aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.cz.toml5
-rw-r--r--.dockerignore12
-rw-r--r--.gitignore15
-rw-r--r--.gitmodules3
-rw-r--r--.pre-commit-config.yaml7
-rw-r--r--AUTHORS2
-rw-r--r--CMakeLists.txt70
-rw-r--r--Dockerfile.dev53
-rw-r--r--Makefile240
-rw-r--r--README.md58
-rw-r--r--apps/.clang-format2
-rw-r--r--apps/CMakeLists.txt87
-rw-r--r--apps/cmake/packaging.cmake (renamed from apps/cmake/Modules/Packaging.cmake)25
-rw-r--r--apps/higet/CMakeLists.txt45
-rw-r--r--apps/higet/higet.cc17
-rw-r--r--apps/hiperf/CMakeLists.txt41
-rw-r--r--apps/hiperf/src/client.cc524
-rw-r--r--apps/hiperf/src/client.h6
-rw-r--r--apps/hiperf/src/common.h80
-rw-r--r--apps/hiperf/src/forwarder_config.h2
-rw-r--r--apps/hiperf/src/forwarder_interface.cc122
-rw-r--r--apps/hiperf/src/forwarder_interface.h18
-rw-r--r--apps/hiperf/src/main.cc145
-rw-r--r--apps/hiperf/src/server.cc209
-rw-r--r--apps/hiperf/src/server.h3
-rw-r--r--apps/http-proxy/CMakeLists.txt66
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt5
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h14
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h2
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h2
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_proxy.h8
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_session.h9
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h5
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/utils.h9
-rw-r--r--apps/http-proxy/main.cc3
-rw-r--r--apps/http-proxy/src/forwarder_interface.cc4
-rw-r--r--apps/http-proxy/src/http_1x_message_fast_parser.cc2
-rw-r--r--apps/http-proxy/src/http_proxy.cc12
-rw-r--r--apps/http-proxy/src/http_session.cc14
-rw-r--r--apps/http-proxy/src/icn_receiver.cc12
-rw-r--r--apps/ping/.clang-format2
-rw-r--r--apps/ping/CMakeLists.txt31
-rw-r--r--apps/ping/src/ping_client.cc102
-rw-r--r--apps/ping/src/ping_server.cc101
m---------cmake0
-rw-r--r--cmake/Modules/BuildMacros.cmake300
-rw-r--r--cmake/Modules/FindAsio.cmake41
-rw-r--r--cmake/Modules/FindCURL.cmake69
-rw-r--r--cmake/Modules/FindCollectd.cmake41
-rw-r--r--cmake/Modules/FindGFlags.cmake36
-rw-r--r--cmake/Modules/FindGlog.cmake36
-rw-r--r--cmake/Modules/FindHicnLight.cmake40
-rw-r--r--cmake/Modules/FindHicnPlugin.cmake35
-rw-r--r--cmake/Modules/FindJsoncpp.cmake47
-rw-r--r--cmake/Modules/FindLibEvent.cmake55
-rw-r--r--cmake/Modules/FindLibconfig++.cmake43
-rw-r--r--cmake/Modules/FindLibconfig.cmake43
-rw-r--r--cmake/Modules/FindLibhicn.cmake52
-rwxr-xr-xcmake/Modules/FindLibhicnctrl.cmake45
-rw-r--r--cmake/Modules/FindLibmemif.cmake47
-rw-r--r--cmake/Modules/FindLibparc.cmake50
-rw-r--r--cmake/Modules/FindLibtransport.cmake49
-rw-r--r--cmake/Modules/FindLongBow.cmake55
-rw-r--r--cmake/Modules/FindPThread.cmake58
-rw-r--r--cmake/Modules/FindSafeVapi.cmake40
-rw-r--r--cmake/Modules/FindSysrepo.cmake46
-rw-r--r--cmake/Modules/FindVapiSafe.cmake40
-rw-r--r--cmake/Modules/FindVpp.cmake95
-rw-r--r--cmake/Modules/GTestImport.cmake45
-rw-r--r--cmake/Modules/License.txt12
-rw-r--r--cmake/Modules/Packager.cmake344
-rw-r--r--cmake/Modules/PostInstall.cmake83
-rw-r--r--cmake/Modules/ServiceScript.cmake42
-rw-r--r--cmake/Modules/WindowsMacros.cmake33
-rw-r--r--cmake/Modules/detectCacheSize.cmake21
-rw-r--r--ctrl/.clang-format (renamed from libtransport/cmake/Modules/TestMacros.cmake)6
-rw-r--r--ctrl/CMakeLists.txt16
-rw-r--r--ctrl/facemgr/CMakeLists.txt110
-rw-r--r--ctrl/facemgr/cmake/packaging.cmake (renamed from ctrl/facemgr/cmake/Modules/Packaging.cmake)22
-rw-r--r--ctrl/facemgr/config/facemgr.service2
-rwxr-xr-xctrl/facemgr/config/postinst4
-rwxr-xr-xctrl/facemgr/config/prerm4
-rwxr-xr-xctrl/facemgr/config/preun4
-rw-r--r--ctrl/facemgr/examples/mobility/mobility.c103
-rw-r--r--ctrl/facemgr/examples/updowncli/updowncli.c82
-rw-r--r--ctrl/facemgr/examples/updownsrv/updownsrv.c348
-rw-r--r--ctrl/facemgr/includes/CMakeLists.txt20
-rw-r--r--ctrl/facemgr/includes/facemgr.h3
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr.h3
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/api.h68
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/cfg.h204
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/facelet.h323
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/loop.h35
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt197
-rw-r--r--ctrl/facemgr/src/api.c3658
-rw-r--r--ctrl/facemgr/src/cache.c116
-rw-r--r--ctrl/facemgr/src/cache.h22
-rw-r--r--ctrl/facemgr/src/cfg.c1950
-rw-r--r--ctrl/facemgr/src/cfg_file.c1121
-rw-r--r--ctrl/facemgr/src/cfg_file.h6
-rw-r--r--ctrl/facemgr/src/common.h103
-rw-r--r--ctrl/facemgr/src/error.c7
-rw-r--r--ctrl/facemgr/src/error.h12
-rw-r--r--ctrl/facemgr/src/facelet.c2114
-rw-r--r--ctrl/facemgr/src/facelet_array.c3
-rw-r--r--ctrl/facemgr/src/facelet_array.h2
-rw-r--r--ctrl/facemgr/src/interface.c254
-rw-r--r--ctrl/facemgr/src/interface.h79
-rw-r--r--ctrl/facemgr/src/interfaces/CMakeLists.txt27
-rw-r--r--ctrl/facemgr/src/interfaces/android/CMakeLists.txt (renamed from ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt)11
-rw-r--r--ctrl/facemgr/src/interfaces/android/android.c294
-rw-r--r--ctrl/facemgr/src/interfaces/android/android.h (renamed from hicn-light/src/hicn/config/controlUpdateConnection.h)32
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c138
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.h48
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.c572
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.h12
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c302
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h950
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/dummy.c96
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/dummy.h4
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt13
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c1144
-rw-r--r--ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/src/interfaces/netlink/netlink.c782
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.c687
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.h3
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c366
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h8
-rw-r--r--ctrl/facemgr/src/interfaces/updown/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/src/interfaces/updown/updown.c173
-rw-r--r--ctrl/facemgr/src/loop_dispatcher.c58
-rw-r--r--ctrl/facemgr/src/loop_libevent.c563
-rw-r--r--ctrl/facemgr/src/main.c255
-rw-r--r--ctrl/libhicnctrl/CMakeLists.txt88
-rw-r--r--ctrl/libhicnctrl/cmake/packaging.cmake (renamed from ctrl/libhicnctrl/cmake/Modules/Packaging.cmake)10
-rw-r--r--ctrl/libhicnctrl/examples/create_face.c191
-rw-r--r--ctrl/libhicnctrl/examples/update_priority.c61
-rw-r--r--ctrl/libhicnctrl/includes/CMakeLists.txt17
-rw-r--r--ctrl/libhicnctrl/includes/ctrl.h2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl.h2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h495
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/commands.h434
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/face.h206
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h427
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h (renamed from hicn-light/src/hicn/utils/commands.h)14
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/route.h27
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt147
-rw-r--r--ctrl/libhicnctrl/src/api.c1735
-rw-r--r--ctrl/libhicnctrl/src/api_private.h223
-rw-r--r--ctrl/libhicnctrl/src/cli.c883
-rw-r--r--ctrl/libhicnctrl/src/face.c430
-rw-r--r--ctrl/libhicnctrl/src/hicnctrl.c805
-rw-r--r--ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in8
-rw-r--r--ctrl/libhicnctrl/src/modules/CMakeLists.txt69
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_api.c2278
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_common.c33
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_common.h95
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c3111
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_plugin_api.c895
-rw-r--r--ctrl/libhicnctrl/src/route.c102
-rw-r--r--ctrl/libhicnctrl/src/util/hash.h379
-rw-r--r--ctrl/sysrepo-plugins/CMakeLists.txt8
-rw-r--r--ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake11
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt2
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt2
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c5
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h2
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c19
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h22
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c192
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h6
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c27
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h18
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt2
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c10
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h3
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c10
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h37
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c838
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h3
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c2
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h142
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c27
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h18
-rw-r--r--[-rwxr-xr-x]ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c316
-rw-r--r--ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang2
-rw-r--r--docs/etc/requirements.txt32
-rw-r--r--docs/source/1-architecture.md42
-rw-r--r--docs/source/apps.md1
-rw-r--r--docs/source/conf.py10
-rw-r--r--docs/source/control.md22
-rw-r--r--docs/source/hicn-light.md127
-rw-r--r--docs/source/index.rst71
-rw-r--r--docs/source/interface.md33
-rw-r--r--docs/source/packethicn.md36
-rw-r--r--docs/source/started.md143
-rw-r--r--docs/source/telemetry.md23
-rw-r--r--docs/source/transport.md315
-rw-r--r--docs/source/utils.md77
-rw-r--r--docs/source/vpp-plugin.md26
-rw-r--r--extras/CMakeLists.txt3
-rw-r--r--extras/libmemif/CMakeLists.txt43
-rw-r--r--extras/libmemif/CMakeLists1.patch75
-rw-r--r--extras/libmemif/CMakeLists2.patch44
-rw-r--r--extras/libmemif/cmake/Modules/Packaging.cmake44
-rw-r--r--extras/libyang/CMakeLists.txt2
-rw-r--r--extras/libyang/cmake/Modules/Packaging.cmake2
-rw-r--r--extras/packethicn/CMakeLists.txt86
-rw-r--r--extras/packethicn/cmake/packaging.cmake (renamed from extras/packethicn/cmake/Modules/Packaging.cmake)6
-rw-r--r--extras/packethicn/packet-hicn.c256
-rw-r--r--extras/router-plugin/.clang-format20
-rw-r--r--extras/router-plugin/CMakeLists.txt6
-rw-r--r--extras/router-plugin/cmake/Modules/Packaging.cmake11
-rw-r--r--extras/router-plugin/devices/rtnetlink/mapper.c279
-rw-r--r--extras/router-plugin/devices/rtnetlink/mapper.h9
-rw-r--r--extras/router-plugin/devices/rtnetlink/netns.c935
-rw-r--r--extras/router-plugin/devices/rtnetlink/netns.h63
-rw-r--r--extras/router-plugin/devices/rtnetlink/rtnl.c685
-rw-r--r--extras/router-plugin/devices/rtnetlink/rtnl.h24
-rw-r--r--extras/router-plugin/devices/rtnetlink/test.c197
-rw-r--r--extras/router-plugin/rtinject/tap_inject.c161
-rw-r--r--extras/router-plugin/rtinject/tap_inject.h40
-rw-r--r--extras/router-plugin/rtinject/tap_inject_netlink.c227
-rw-r--r--extras/router-plugin/rtinject/tap_inject_node.c172
-rw-r--r--extras/router-plugin/rtinject/tap_inject_tap.c30
-rw-r--r--extras/sysrepo/CMakeLists.txt2
-rw-r--r--extras/sysrepo/cmake/Modules/Packaging.cmake4
-rw-r--r--hicn-light/.clang-format (renamed from cmake/Modules/FindUncrustify.cmake)12
-rw-r--r--hicn-light/CMakeLists.txt138
-rw-r--r--hicn-light/cmake/packaging.cmake (renamed from hicn-light/cmake/Modules/Packaging.cmake)6
-rw-r--r--hicn-light/config/hicn-light.service2
-rwxr-xr-xhicn-light/config/post2
-rwxr-xr-xhicn-light/config/postinst4
-rwxr-xr-xhicn-light/config/prerm4
-rwxr-xr-xhicn-light/config/preun4
-rw-r--r--hicn-light/src/hicn/CMakeLists.txt118
-rw-r--r--hicn-light/src/hicn/base/CMakeLists.txt (renamed from hicn-light/src/hicn/messenger/CMakeLists.txt)31
-rw-r--r--hicn-light/src/hicn/base/bitmap.h188
-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/loop.c201
-rw-r--r--hicn-light/src/hicn/base/loop.h138
-rw-r--r--hicn-light/src/hicn/base/pool.c158
-rw-r--r--hicn-light/src/hicn/base/pool.h254
-rw-r--r--hicn-light/src/hicn/base/ring.c45
-rw-r--r--hicn-light/src/hicn/base/ring.h201
-rw-r--r--hicn-light/src/hicn/base/vector.c85
-rw-r--r--hicn-light/src/hicn/base/vector.h327
-rw-r--r--hicn-light/src/hicn/cli/CMakeLists.txt93
-rw-r--r--hicn-light/src/hicn/cli/color.c71
-rw-r--r--hicn-light/src/hicn/cli/color.h (renamed from hicn-light/src/hicn/core/connectionState.h)39
-rw-r--r--hicn-light/src/hicn/cli/hicnc.c390
-rw-r--r--hicn-light/src/hicn/cli/hicnd.c311
-rw-r--r--hicn-light/src/hicn/cli/hicns.c206
-rw-r--r--hicn-light/src/hicn/cli/logo.h37
-rw-r--r--hicn-light/src/hicn/command_line/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/command_line/controller/CMakeLists.txt35
-rw-r--r--hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c382
-rw-r--r--hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c414
-rw-r--r--hicn-light/src/hicn/config.h.in3
-rw-r--r--hicn-light/src/hicn/config/CMakeLists.txt107
-rw-r--r--hicn-light/src/hicn/config/command.c119
-rw-r--r--hicn-light/src/hicn/config/command.h179
-rw-r--r--hicn-light/src/hicn/config/commandOps.c72
-rw-r--r--hicn-light/src/hicn/config/commandOps.h132
-rw-r--r--hicn-light/src/hicn/config/commandParser.c221
-rw-r--r--hicn-light/src/hicn/config/commandParser.h200
-rw-r--r--hicn-light/src/hicn/config/commandReturn.h43
-rw-r--r--hicn-light/src/hicn/config/command_cache.c54
-rw-r--r--hicn-light/src/hicn/config/command_connection.c128
-rw-r--r--hicn-light/src/hicn/config/command_face.c16
-rw-r--r--hicn-light/src/hicn/config/command_listener.c111
-rw-r--r--hicn-light/src/hicn/config/command_mapme.c59
-rw-r--r--hicn-light/src/hicn/config/command_policy.c52
-rw-r--r--hicn-light/src/hicn/config/command_punting.c40
-rw-r--r--hicn-light/src/hicn/config/command_route.c53
-rw-r--r--hicn-light/src/hicn/config/command_strategy.c47
-rw-r--r--hicn-light/src/hicn/config/command_subscription.c23
-rw-r--r--hicn-light/src/hicn/config/commands.c1530
-rw-r--r--hicn-light/src/hicn/config/commands.h152
-rw-r--r--hicn-light/src/hicn/config/configuration.c1547
-rw-r--r--hicn-light/src/hicn/config/configuration.h109
-rw-r--r--hicn-light/src/hicn/config/configurationFile.c314
-rw-r--r--hicn-light/src/hicn/config/configurationFile.h93
-rw-r--r--hicn-light/src/hicn/config/configurationListeners.c629
-rw-r--r--hicn-light/src/hicn/config/configurationListeners.h74
-rw-r--r--hicn-light/src/hicn/config/configuration_file.c137
-rw-r--r--hicn-light/src/hicn/config/configuration_file.h56
-rw-r--r--hicn-light/src/hicn/config/controlAdd.c128
-rw-r--r--hicn-light/src/hicn/config/controlAddConnection.c450
-rw-r--r--hicn-light/src/hicn/config/controlAddConnection.h31
-rw-r--r--hicn-light/src/hicn/config/controlAddListener.c201
-rw-r--r--hicn-light/src/hicn/config/controlAddListener.h30
-rw-r--r--hicn-light/src/hicn/config/controlAddPolicy.c183
-rw-r--r--hicn-light/src/hicn/config/controlAddPunting.c159
-rw-r--r--hicn-light/src/hicn/config/controlAddRoute.c162
-rw-r--r--hicn-light/src/hicn/config/controlAddRoute.h30
-rw-r--r--hicn-light/src/hicn/config/controlCache.c99
-rw-r--r--hicn-light/src/hicn/config/controlCacheClear.c90
-rw-r--r--hicn-light/src/hicn/config/controlCacheClear.h30
-rw-r--r--hicn-light/src/hicn/config/controlCacheServe.c108
-rw-r--r--hicn-light/src/hicn/config/controlCacheServe.h22
-rw-r--r--hicn-light/src/hicn/config/controlCacheStore.c109
-rw-r--r--hicn-light/src/hicn/config/controlCacheStore.h22
-rw-r--r--hicn-light/src/hicn/config/controlList.c130
-rw-r--r--hicn-light/src/hicn/config/controlList.h30
-rw-r--r--hicn-light/src/hicn/config/controlListConnections.c195
-rw-r--r--hicn-light/src/hicn/config/controlListConnections.h30
-rw-r--r--hicn-light/src/hicn/config/controlListInterfaces.c81
-rw-r--r--hicn-light/src/hicn/config/controlListInterfaces.h31
-rw-r--r--hicn-light/src/hicn/config/controlListListeners.c160
-rw-r--r--hicn-light/src/hicn/config/controlListListeners.h31
-rw-r--r--hicn-light/src/hicn/config/controlListPolicies.c250
-rw-r--r--hicn-light/src/hicn/config/controlListPolicies.h34
-rw-r--r--hicn-light/src/hicn/config/controlListRoutes.c158
-rw-r--r--hicn-light/src/hicn/config/controlListRoutes.h29
-rw-r--r--hicn-light/src/hicn/config/controlMapMe.c104
-rw-r--r--hicn-light/src/hicn/config/controlMapMe.h22
-rw-r--r--hicn-light/src/hicn/config/controlMapMeDiscovery.c109
-rw-r--r--hicn-light/src/hicn/config/controlMapMeDiscovery.h22
-rw-r--r--hicn-light/src/hicn/config/controlMapMeEnable.c107
-rw-r--r--hicn-light/src/hicn/config/controlMapMeEnable.h22
-rw-r--r--hicn-light/src/hicn/config/controlMapMeRetx.c101
-rw-r--r--hicn-light/src/hicn/config/controlMapMeRetx.h22
-rw-r--r--hicn-light/src/hicn/config/controlMapMeTimescale.c102
-rw-r--r--hicn-light/src/hicn/config/controlMapMeTimescale.h22
-rw-r--r--hicn-light/src/hicn/config/controlQuit.c74
-rw-r--r--hicn-light/src/hicn/config/controlQuit.h29
-rw-r--r--hicn-light/src/hicn/config/controlRemove.c132
-rw-r--r--hicn-light/src/hicn/config/controlRemove.h29
-rw-r--r--hicn-light/src/hicn/config/controlRemoveConnection.c122
-rw-r--r--hicn-light/src/hicn/config/controlRemoveConnection.h31
-rw-r--r--hicn-light/src/hicn/config/controlRemoveListener.c123
-rw-r--r--hicn-light/src/hicn/config/controlRemoveListener.h31
-rw-r--r--hicn-light/src/hicn/config/controlRemovePolicy.c147
-rw-r--r--hicn-light/src/hicn/config/controlRemovePunting.c83
-rw-r--r--hicn-light/src/hicn/config/controlRemoveRoute.c154
-rw-r--r--hicn-light/src/hicn/config/controlRemoveRoute.h31
-rw-r--r--hicn-light/src/hicn/config/controlRoot.c173
-rw-r--r--hicn-light/src/hicn/config/controlRoot.h31
-rw-r--r--hicn-light/src/hicn/config/controlSet.c98
-rw-r--r--hicn-light/src/hicn/config/controlSet.h29
-rw-r--r--hicn-light/src/hicn/config/controlSetDebug.c81
-rw-r--r--hicn-light/src/hicn/config/controlSetDebug.h30
-rw-r--r--hicn-light/src/hicn/config/controlSetStrategy.c264
-rw-r--r--hicn-light/src/hicn/config/controlSetStrategy.h22
-rw-r--r--hicn-light/src/hicn/config/controlSetWldr.c131
-rw-r--r--hicn-light/src/hicn/config/controlSetWldr.h22
-rw-r--r--hicn-light/src/hicn/config/controlState.c243
-rw-r--r--hicn-light/src/hicn/config/controlState.h242
-rw-r--r--hicn-light/src/hicn/config/controlUnset.c85
-rw-r--r--hicn-light/src/hicn/config/controlUnset.h29
-rw-r--r--hicn-light/src/hicn/config/controlUnsetDebug.c83
-rw-r--r--hicn-light/src/hicn/config/controlUnsetDebug.h30
-rw-r--r--hicn-light/src/hicn/config/controlUpdate.c105
-rw-r--r--hicn-light/src/hicn/config/controlUpdateConnection.c154
-rw-r--r--hicn-light/src/hicn/config/parse.c402
-rw-r--r--hicn-light/src/hicn/config/parse.h15
-rw-r--r--hicn-light/src/hicn/config/symbolicNameTable.c191
-rw-r--r--hicn-light/src/hicn/config/symbolicNameTable.h131
-rw-r--r--hicn-light/src/hicn/content_store/CMakeLists.txt16
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreEntry.c136
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreEntry.h146
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreInterface.c57
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreInterface.h211
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreLRU.c462
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreLRU.h39
-rw-r--r--hicn-light/src/hicn/content_store/listLRU.c135
-rw-r--r--hicn-light/src/hicn/content_store/listLRU.h94
-rw-r--r--hicn-light/src/hicn/content_store/listTimeOrdered.c94
-rw-r--r--hicn-light/src/hicn/content_store/listTimeOrdered.h103
-rw-r--r--hicn-light/src/hicn/content_store/lru.c167
-rw-r--r--hicn-light/src/hicn/content_store/lru.h56
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt70
-rw-r--r--hicn-light/src/hicn/core/address.c66
-rw-r--r--hicn-light/src/hicn/core/address.h141
-rw-r--r--hicn-light/src/hicn/core/address_pair.c41
-rw-r--r--hicn-light/src/hicn/core/address_pair.h58
-rw-r--r--hicn-light/src/hicn/core/connection.c517
-rw-r--r--hicn-light/src/hicn/core/connection.h304
-rw-r--r--hicn-light/src/hicn/core/connectionList.c68
-rw-r--r--hicn-light/src/hicn/core/connectionList.h70
-rw-r--r--hicn-light/src/hicn/core/connectionManager.c196
-rw-r--r--hicn-light/src/hicn/core/connectionManager.h37
-rw-r--r--hicn-light/src/hicn/core/connectionTable.c226
-rw-r--r--hicn-light/src/hicn/core/connectionTable.h99
-rw-r--r--hicn-light/src/hicn/core/connection_table.c162
-rw-r--r--hicn-light/src/hicn/core/connection_table.h297
-rw-r--r--hicn-light/src/hicn/core/connection_vft.c37
-rw-r--r--hicn-light/src/hicn/core/connection_vft.h54
-rw-r--r--hicn-light/src/hicn/core/content_store.c86
-rw-r--r--hicn-light/src/hicn/core/content_store.h106
-rw-r--r--hicn-light/src/hicn/core/dispatcher.c474
-rw-r--r--hicn-light/src/hicn/core/dispatcher.h288
-rw-r--r--hicn-light/src/hicn/core/fib.c478
-rw-r--r--hicn-light/src/hicn/core/fib.h62
-rw-r--r--hicn-light/src/hicn/core/fib_entry.c588
-rw-r--r--hicn-light/src/hicn/core/fib_entry.h175
-rw-r--r--hicn-light/src/hicn/core/forwarder.c1334
-rw-r--r--hicn-light/src/hicn/core/forwarder.h316
-rw-r--r--hicn-light/src/hicn/core/listener.c444
-rw-r--r--hicn-light/src/hicn/core/listener.h131
-rw-r--r--hicn-light/src/hicn/core/listener_table.c153
-rw-r--r--hicn-light/src/hicn/core/listener_table.h310
-rw-r--r--hicn-light/src/hicn/core/listener_vft.c36
-rw-r--r--hicn-light/src/hicn/core/listener_vft.h58
-rw-r--r--hicn-light/src/hicn/core/logger.c177
-rw-r--r--hicn-light/src/hicn/core/logger.h170
-rw-r--r--hicn-light/src/hicn/core/mapme.c1586
-rw-r--r--hicn-light/src/hicn/core/mapme.h80
-rw-r--r--hicn-light/src/hicn/core/message.c299
-rw-r--r--hicn-light/src/hicn/core/message.h180
-rw-r--r--hicn-light/src/hicn/core/messageHandler.h302
-rw-r--r--hicn-light/src/hicn/core/messagePacketType.h32
-rw-r--r--hicn-light/src/hicn/core/msgbuf.c (renamed from hicn-light/src/hicn/strategies/rnd.h)14
-rw-r--r--hicn-light/src/hicn/core/msgbuf.h127
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.c117
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.h157
-rw-r--r--hicn-light/src/hicn/core/name.c236
-rw-r--r--hicn-light/src/hicn/core/name.h52
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.c190
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.h26
-rw-r--r--hicn-light/src/hicn/core/nexthops.c142
-rw-r--r--hicn-light/src/hicn/core/nexthops.h176
-rw-r--r--hicn-light/src/hicn/core/numberSet.c203
-rw-r--r--hicn-light/src/hicn/core/numberSet.h157
-rw-r--r--hicn-light/src/hicn/core/packet_cache.c547
-rw-r--r--hicn-light/src/hicn/core/packet_cache.h445
-rw-r--r--hicn-light/src/hicn/core/pit.c74
-rw-r--r--hicn-light/src/hicn/core/pit.h73
-rw-r--r--hicn-light/src/hicn/core/policy_stats.c189
-rw-r--r--hicn-light/src/hicn/core/policy_stats.h93
-rw-r--r--hicn-light/src/hicn/core/strategy.c56
-rw-r--r--hicn-light/src/hicn/core/strategy.h79
-rw-r--r--hicn-light/src/hicn/core/strategy_vft.c37
-rw-r--r--hicn-light/src/hicn/core/strategy_vft.h128
-rw-r--r--hicn-light/src/hicn/core/streamBuffer.c2
-rw-r--r--hicn-light/src/hicn/core/streamBuffer.h2
-rw-r--r--hicn-light/src/hicn/core/subscription.c124
-rw-r--r--hicn-light/src/hicn/core/subscription.h81
-rw-r--r--hicn-light/src/hicn/core/system.h9
-rw-r--r--hicn-light/src/hicn/core/ticks.h37
-rw-r--r--hicn-light/src/hicn/core/wldr.c109
-rw-r--r--hicn-light/src/hicn/core/wldr.h22
-rw-r--r--hicn-light/src/hicn/io/CMakeLists.txt50
-rw-r--r--hicn-light/src/hicn/io/addressPair.c129
-rw-r--r--hicn-light/src/hicn/io/addressPair.h128
-rw-r--r--hicn-light/src/hicn/io/base.c139
-rw-r--r--hicn-light/src/hicn/io/base.h37
-rw-r--r--hicn-light/src/hicn/io/hicn.c450
-rw-r--r--hicn-light/src/hicn/io/hicnConnection.c541
-rw-r--r--hicn-light/src/hicn/io/hicnConnection.h53
-rw-r--r--hicn-light/src/hicn/io/hicnListener.c673
-rw-r--r--hicn-light/src/hicn/io/hicnListener.h42
-rw-r--r--hicn-light/src/hicn/io/hicnTunnel.c106
-rw-r--r--hicn-light/src/hicn/io/hicnTunnel.h65
-rw-r--r--hicn-light/src/hicn/io/ioOperations.c100
-rw-r--r--hicn-light/src/hicn/io/ioOperations.h449
-rw-r--r--hicn-light/src/hicn/io/listener.h128
-rw-r--r--hicn-light/src/hicn/io/listenerSet.c182
-rw-r--r--hicn-light/src/hicn/io/listenerSet.h188
-rw-r--r--hicn-light/src/hicn/io/streamConnection.c773
-rw-r--r--hicn-light/src/hicn/io/streamConnection.h76
-rw-r--r--hicn-light/src/hicn/io/tcp.c535
-rw-r--r--hicn-light/src/hicn/io/tcpListener.c262
-rw-r--r--hicn-light/src/hicn/io/tcpListener.h40
-rw-r--r--hicn-light/src/hicn/io/tcpTunnel.c43
-rw-r--r--hicn-light/src/hicn/io/tcpTunnel.h42
-rw-r--r--hicn-light/src/hicn/io/udp.c566
-rw-r--r--hicn-light/src/hicn/io/udpConnection.c495
-rw-r--r--hicn-light/src/hicn/io/udpConnection.h53
-rw-r--r--hicn-light/src/hicn/io/udpListener.c653
-rw-r--r--hicn-light/src/hicn/io/udpListener.h35
-rw-r--r--hicn-light/src/hicn/io/udpTunnel.c105
-rw-r--r--hicn-light/src/hicn/io/udpTunnel.h42
-rw-r--r--hicn-light/src/hicn/messenger/messenger.c171
-rw-r--r--hicn-light/src/hicn/messenger/messenger.h69
-rw-r--r--hicn-light/src/hicn/messenger/messengerRecipient.c62
-rw-r--r--hicn-light/src/hicn/messenger/messengerRecipient.h104
-rw-r--r--hicn-light/src/hicn/messenger/missive.c54
-rw-r--r--hicn-light/src/hicn/messenger/missive.h89
-rw-r--r--hicn-light/src/hicn/messenger/missiveDeque.c77
-rw-r--r--hicn-light/src/hicn/messenger/missiveDeque.h55
-rw-r--r--hicn-light/src/hicn/messenger/missiveType.h55
-rw-r--r--hicn-light/src/hicn/platforms/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/platforms/README.txt3
-rw-r--r--hicn-light/src/hicn/platforms/android/system.c4
-rw-r--r--hicn-light/src/hicn/platforms/darwin/system.c6
-rw-r--r--hicn-light/src/hicn/platforms/linux/system.c67
-rw-r--r--hicn-light/src/hicn/platforms/windows/system.c446
-rw-r--r--hicn-light/src/hicn/platforms/windows/win_portability.c102
-rw-r--r--hicn-light/src/hicn/platforms/windows/win_portability.h88
-rw-r--r--hicn-light/src/hicn/processor/CMakeLists.txt38
-rw-r--r--hicn-light/src/hicn/processor/fib.c553
-rw-r--r--hicn-light/src/hicn/processor/fib.h45
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.c894
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.h166
-rw-r--r--hicn-light/src/hicn/processor/fibEntryList.c72
-rw-r--r--hicn-light/src/hicn/processor/fibEntryList.h96
-rw-r--r--hicn-light/src/hicn/processor/hashTableFunction.c47
-rw-r--r--hicn-light/src/hicn/processor/hashTableFunction.h73
-rw-r--r--hicn-light/src/hicn/processor/matchingRulesTable.c132
-rw-r--r--hicn-light/src/hicn/processor/matchingRulesTable.h113
-rw-r--r--hicn-light/src/hicn/processor/messageProcessor.c909
-rw-r--r--hicn-light/src/hicn/processor/messageProcessor.h206
-rw-r--r--hicn-light/src/hicn/processor/pit.c45
-rw-r--r--hicn-light/src/hicn/processor/pit.h114
-rw-r--r--hicn-light/src/hicn/processor/pitEntry.c142
-rw-r--r--hicn-light/src/hicn/processor/pitEntry.h164
-rw-r--r--hicn-light/src/hicn/processor/pitStandard.c305
-rw-r--r--hicn-light/src/hicn/processor/pitStandard.h41
-rw-r--r--hicn-light/src/hicn/processor/pitVerdict.h40
-rw-r--r--hicn-light/src/hicn/socket/CMakeLists.txt8
-rw-r--r--hicn-light/src/hicn/socket/api.c54
-rw-r--r--hicn-light/src/hicn/socket/api.h3
-rw-r--r--hicn-light/src/hicn/socket/ops_linux.c81
-rw-r--r--hicn-light/src/hicn/strategies/CMakeLists.txt27
-rw-r--r--hicn-light/src/hicn/strategies/best_path.c344
-rw-r--r--hicn-light/src/hicn/strategies/best_path.h57
-rw-r--r--hicn-light/src/hicn/strategies/loadBalancer.c369
-rw-r--r--hicn-light/src/hicn/strategies/load_balancer.c153
-rw-r--r--hicn-light/src/hicn/strategies/load_balancer.h (renamed from hicn-light/src/hicn/config/controlUpdate.h)30
-rw-r--r--hicn-light/src/hicn/strategies/local_prefixes.c81
-rw-r--r--hicn-light/src/hicn/strategies/local_prefixes.h43
-rw-r--r--hicn-light/src/hicn/strategies/lowLatency.c851
-rw-r--r--hicn-light/src/hicn/strategies/lowLatency.h33
-rw-r--r--hicn-light/src/hicn/strategies/low_latency.c776
-rw-r--r--hicn-light/src/hicn/strategies/low_latency.h101
-rw-r--r--hicn-light/src/hicn/strategies/nexthopState.c212
-rw-r--r--hicn-light/src/hicn/strategies/nexthopState.h94
-rw-r--r--hicn-light/src/hicn/strategies/nexthopStateLowLatency.c386
-rw-r--r--hicn-light/src/hicn/strategies/nexthopStateLowLatency.h16
-rw-r--r--hicn-light/src/hicn/strategies/probe_generator.c114
-rw-r--r--hicn-light/src/hicn/strategies/probe_generator.h46
-rw-r--r--hicn-light/src/hicn/strategies/random.c76
-rw-r--r--hicn-light/src/hicn/strategies/random.h (renamed from hicn-light/src/hicn/config/controlRemovePunting.h)26
-rw-r--r--hicn-light/src/hicn/strategies/replication.c98
-rw-r--r--hicn-light/src/hicn/strategies/replication.h (renamed from hicn-light/src/hicn/config/controlAddPolicy.h)30
-rw-r--r--hicn-light/src/hicn/strategies/rnd.c211
-rw-r--r--hicn-light/src/hicn/strategies/strategyImpl.h73
-rw-r--r--hicn-light/src/hicn/test/CMakeLists.txt43
-rw-r--r--hicn-light/src/hicn/test/main.cc (renamed from hicn-light/src/hicn/strategies/loadBalancer.h)18
-rw-r--r--hicn-light/src/hicn/test/test-bitmap.cc133
-rw-r--r--hicn-light/src/hicn/test/test-configuration.cc82
-rw-r--r--hicn-light/src/hicn/test/test-connection_table.cc250
-rw-r--r--hicn-light/src/hicn/test/test-ctrl.cc164
-rw-r--r--hicn-light/src/hicn/test/test-hash.cc123
-rw-r--r--hicn-light/src/hicn/test/test-khash.cc154
-rw-r--r--hicn-light/src/hicn/test/test-listener_table.cc240
-rw-r--r--hicn-light/src/hicn/test/test-local_prefixes.cc229
-rw-r--r--hicn-light/src/hicn/test/test-loop.cc288
-rw-r--r--hicn-light/src/hicn/test/test-msgbuf_pool.cc191
-rw-r--r--hicn-light/src/hicn/test/test-nexthops.cc274
-rw-r--r--hicn-light/src/hicn/test/test-packet_cache.cc524
-rw-r--r--hicn-light/src/hicn/test/test-parser.cc71
-rw-r--r--hicn-light/src/hicn/test/test-pool.cc196
-rw-r--r--hicn-light/src/hicn/test/test-probe_generator.cc154
-rw-r--r--hicn-light/src/hicn/test/test-ring.cc99
-rw-r--r--hicn-light/src/hicn/test/test-strategy-best-path.cc107
-rw-r--r--hicn-light/src/hicn/test/test-strategy-load-balancing.cc152
-rw-r--r--hicn-light/src/hicn/test/test-strategy-random.cc150
-rw-r--r--hicn-light/src/hicn/test/test-strategy-replication.cc163
-rw-r--r--hicn-light/src/hicn/test/test-subscription.cc204
-rw-r--r--hicn-light/src/hicn/test/test-vector.cc148
-rw-r--r--hicn-light/src/hicn/utils/CMakeLists.txt25
-rw-r--r--hicn-light/src/hicn/utils/address.c450
-rw-r--r--hicn-light/src/hicn/utils/address.h524
-rw-r--r--hicn-light/src/hicn/utils/addressList.c133
-rw-r--r--hicn-light/src/hicn/utils/addressList.h196
-rw-r--r--hicn-light/src/hicn/utils/interface.c8
-rw-r--r--hicn-light/src/hicn/utils/interface.h9
-rw-r--r--hicn-light/src/hicn/utils/interfaceSet.c2
-rw-r--r--hicn-light/src/hicn/utils/interfaceSet.h2
-rw-r--r--hicn-light/src/hicn/utils/punting.c10
-rw-r--r--hicn-light/src/hicn/utils/punting.h21
-rw-r--r--hicn-light/src/hicn/utils/token.h4
-rw-r--r--hicn-light/src/hicn/utils/utils.c235
-rw-r--r--hicn-light/src/hicn/utils/utils.h70
-rw-r--r--hicn-plugin/CMakeLists.txt51
-rw-r--r--hicn-plugin/cmake/Modules/Packaging.cmake56
-rw-r--r--hicn-plugin/cmake/packaging.cmake69
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt (renamed from cmake/Modules/IosMacros.cmake)27
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/error.h (renamed from hicn-plugin/src/error.h)8
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h (renamed from hicn-plugin/src/hicn_all_api_h.h)4
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h (renamed from hicn-plugin/src/hicn_api.h)4
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h (renamed from hicn-plugin/src/hicn_msg_enum.h)4
-rw-r--r--hicn-plugin/scripts/post20
-rw-r--r--hicn-plugin/scripts/postinst19
-rw-r--r--hicn-plugin/scripts/postun5
-rw-r--r--hicn-plugin/src/CMakeLists.txt446
-rw-r--r--hicn-plugin/src/cache_policies/cs_lru.c2
-rw-r--r--hicn-plugin/src/cache_policies/cs_lru.h2
-rw-r--r--hicn-plugin/src/cache_policies/cs_policy.h2
-rw-r--r--hicn-plugin/src/cli.c53
-rw-r--r--hicn-plugin/src/data_fwd.h2
-rw-r--r--hicn-plugin/src/data_fwd_node.c13
-rw-r--r--hicn-plugin/src/data_input_node.c164
-rw-r--r--hicn-plugin/src/data_pcslookup.h2
-rw-r--r--hicn-plugin/src/data_pcslookup_node.c4
-rw-r--r--hicn-plugin/src/error.c4
-rw-r--r--hicn-plugin/src/face_db.h10
-rw-r--r--hicn-plugin/src/faces/app/address_mgr.c7
-rw-r--r--hicn-plugin/src/faces/app/address_mgr.h2
-rw-r--r--hicn-plugin/src/faces/app/face_app_cli.c10
-rw-r--r--hicn-plugin/src/faces/app/face_cons.c10
-rw-r--r--hicn-plugin/src/faces/app/face_cons.h2
-rw-r--r--hicn-plugin/src/faces/app/face_prod.c64
-rw-r--r--hicn-plugin/src/faces/app/face_prod.h3
-rw-r--r--hicn-plugin/src/faces/app/face_prod_node.c30
-rw-r--r--hicn-plugin/src/faces/face.c98
-rw-r--r--hicn-plugin/src/faces/face.h275
-rw-r--r--hicn-plugin/src/faces/face_cli.c2
-rw-r--r--hicn-plugin/src/faces/face_node.c145
-rw-r--r--hicn-plugin/src/faces/face_node.h2
-rw-r--r--hicn-plugin/src/faces/iface_node.c111
-rw-r--r--hicn-plugin/src/faces/iface_node.h2
-rw-r--r--hicn-plugin/src/faces/inlines.h23
-rw-r--r--hicn-plugin/src/hashtb.c6
-rw-r--r--hicn-plugin/src/hashtb.h2
-rw-r--r--hicn-plugin/src/hicn.api10
-rw-r--r--hicn-plugin/src/hicn.c6
-rw-r--r--hicn-plugin/src/hicn.h9
-rw-r--r--hicn-plugin/src/hicn_api.c37
-rw-r--r--hicn-plugin/src/hicn_api_test.c18
-rw-r--r--hicn-plugin/src/hicn_logging.h32
-rw-r--r--hicn-plugin/src/infra.c (renamed from libtransport/src/protocols/fec_base.cc)15
-rw-r--r--hicn-plugin/src/infra.h6
-rw-r--r--hicn-plugin/src/interest_hitcs.h2
-rw-r--r--hicn-plugin/src/interest_hitcs_node.c4
-rw-r--r--hicn-plugin/src/interest_hitpit.h2
-rw-r--r--hicn-plugin/src/interest_hitpit_node.c83
-rw-r--r--hicn-plugin/src/interest_pcslookup.h2
-rw-r--r--hicn-plugin/src/interest_pcslookup_node.c2
-rw-r--r--hicn-plugin/src/mapme.h68
-rw-r--r--hicn-plugin/src/mapme_ack.h4
-rw-r--r--hicn-plugin/src/mapme_ack_node.c10
-rw-r--r--hicn-plugin/src/mapme_ctrl.h4
-rw-r--r--hicn-plugin/src/mapme_ctrl_node.c172
-rw-r--r--hicn-plugin/src/mapme_eventmgr.c39
-rw-r--r--hicn-plugin/src/mapme_eventmgr.h5
-rw-r--r--hicn-plugin/src/mgmt.c7
-rw-r--r--hicn-plugin/src/mgmt.h4
-rw-r--r--hicn-plugin/src/params.h10
-rw-r--r--hicn-plugin/src/parser.h24
-rw-r--r--hicn-plugin/src/pcs.c2
-rw-r--r--hicn-plugin/src/pcs.h64
-rw-r--r--hicn-plugin/src/pg.c44
-rw-r--r--hicn-plugin/src/pg.h2
-rw-r--r--hicn-plugin/src/route.c205
-rw-r--r--hicn-plugin/src/route.h31
-rw-r--r--hicn-plugin/src/state.h2
-rw-r--r--hicn-plugin/src/strategies/dpo_mw.c19
-rw-r--r--hicn-plugin/src/strategies/dpo_mw.h9
-rw-r--r--hicn-plugin/src/strategies/dpo_rp.c155
-rw-r--r--hicn-plugin/src/strategies/dpo_rp.h152
-rw-r--r--hicn-plugin/src/strategies/dpo_rr.c16
-rw-r--r--hicn-plugin/src/strategies/dpo_rr.h9
-rw-r--r--hicn-plugin/src/strategies/strategy_mw.c16
-rw-r--r--hicn-plugin/src/strategies/strategy_mw.h2
-rw-r--r--hicn-plugin/src/strategies/strategy_mw_cli.c4
-rw-r--r--hicn-plugin/src/strategies/strategy_rp.c118
-rw-r--r--hicn-plugin/src/strategies/strategy_rp.h (renamed from hicn-light/src/hicn/config/controlRemovePolicy.h)37
-rw-r--r--hicn-plugin/src/strategies/strategy_rr.c16
-rw-r--r--hicn-plugin/src/strategies/strategy_rr.h2
-rw-r--r--hicn-plugin/src/strategy.h6
-rw-r--r--hicn-plugin/src/strategy_dpo_ctx.c28
-rw-r--r--hicn-plugin/src/strategy_dpo_ctx.h4
-rw-r--r--hicn-plugin/src/strategy_dpo_manager.c11
-rw-r--r--hicn-plugin/src/strategy_dpo_manager.h6
-rw-r--r--hicn-plugin/src/strategy_node.c141
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_decap.h2
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_decap_node.c107
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_tunnel.c27
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_tunnel.h15
-rw-r--r--hicn-plugin/src/utils.h2
-rw-r--r--hicn-plugin/vapi/CMakeLists.txt113
-rw-r--r--hicn-plugin/vapi/include/vapi/vapi_safe.h19
-rw-r--r--hicn-plugin/vapi/includes/vapi/vapi_safe.h (renamed from hicn-light/src/hicn/config/controlAddPunting.h)23
-rw-r--r--hicn-plugin/vapi/libsafevapi-config.cmake.in8
-rw-r--r--hicn-plugin/vapi/src/vapi_safe.c98
-rw-r--r--hicn-plugin/vapi/vapi_safe.c73
-rw-r--r--lib/CMakeLists.txt49
-rw-r--r--lib/cmake/packaging.cmake (renamed from lib/cmake/Modules/Packaging.cmake)16
-rw-r--r--lib/includes/CMakeLists.txt21
-rw-r--r--lib/includes/hicn/base.h109
-rw-r--r--lib/includes/hicn/common.h125
-rw-r--r--lib/includes/hicn/compat.h84
-rw-r--r--lib/includes/hicn/error.h29
-rw-r--r--lib/includes/hicn/face.h233
-rw-r--r--lib/includes/hicn/header.h65
-rw-r--r--lib/includes/hicn/hicn.h14
-rw-r--r--lib/includes/hicn/mapme.h70
-rw-r--r--lib/includes/hicn/name.h151
-rw-r--r--lib/includes/hicn/ops.h157
-rw-r--r--lib/includes/hicn/policy.h263
-rw-r--r--lib/includes/hicn/protocol.h4
-rw-r--r--lib/includes/hicn/protocol/ah.h16
-rw-r--r--lib/includes/hicn/protocol/icmp.h12
-rw-r--r--lib/includes/hicn/protocol/icmprd.h6
-rw-r--r--lib/includes/hicn/protocol/ipv4.h41
-rw-r--r--lib/includes/hicn/protocol/ipv6.h32
-rw-r--r--lib/includes/hicn/protocol/new.h88
-rw-r--r--lib/includes/hicn/protocol/tcp.h102
-rw-r--r--lib/includes/hicn/protocol/udp.h4
-rw-r--r--lib/includes/hicn/strategy.h63
-rw-r--r--lib/includes/hicn/util/array.h323
-rw-r--r--lib/includes/hicn/util/ip_address.h167
-rw-r--r--lib/includes/hicn/util/log.h62
-rw-r--r--lib/includes/hicn/util/map.h444
-rw-r--r--lib/includes/hicn/util/set.h370
-rw-r--r--lib/includes/hicn/util/sstrncpy.h68
-rw-r--r--lib/includes/hicn/util/token.h8
-rw-r--r--lib/includes/hicn/util/types.h16
-rw-r--r--lib/includes/hicn/util/win_portability.h88
-rw-r--r--lib/includes/hicn/util/windows/dlfcn.h15
-rw-r--r--[-rwxr-xr-x]lib/includes/hicn/util/windows/windows_utils.h326
-rw-r--r--lib/includes/hicn/validation.h55
-rw-r--r--lib/src/CMakeLists.txt138
-rw-r--r--lib/src/common.c22
-rw-r--r--lib/src/compat.c269
-rw-r--r--lib/src/error.c4
-rw-r--r--lib/src/face.c451
-rw-r--r--lib/src/libhicn-config.cmake.in12
-rw-r--r--lib/src/mapme.c64
-rw-r--r--lib/src/name.c493
-rw-r--r--lib/src/ops.c15
-rw-r--r--lib/src/policy.c73
-rw-r--r--lib/src/protocol/ah.c24
-rw-r--r--lib/src/protocol/icmp.c23
-rw-r--r--lib/src/protocol/ipv4.c98
-rw-r--r--lib/src/protocol/ipv6.c102
-rw-r--r--lib/src/protocol/new.c441
-rw-r--r--lib/src/protocol/tcp.c114
-rw-r--r--lib/src/protocol/udp.c312
-rw-r--r--lib/src/strategy.c (renamed from hicn-light/src/hicn/config/controlCache.h)14
-rw-r--r--lib/src/test/CMakeLists.txt47
-rw-r--r--lib/src/test/main.cc23
-rw-r--r--lib/src/test/test_name.cc339
-rw-r--r--lib/src/test/test_new_header.cc340
-rw-r--r--lib/src/test/test_udp_header.cc355
-rw-r--r--lib/src/test/test_validation.cc55
-rw-r--r--lib/src/util/ip_address.c284
-rw-r--r--lib/src/util/log.c242
-rw-r--r--lib/src/util/windows/dlfcn.c84
-rw-r--r--libtransport/.clang-format2
-rw-r--r--libtransport/CMakeLists.txt96
-rw-r--r--libtransport/cmake/Modules/Android.cmake19
-rw-r--r--libtransport/cmake/Modules/DefaultConfiguration.cmake30
-rw-r--r--libtransport/cmake/Modules/Ios.cmake20
-rw-r--r--libtransport/cmake/packaging.cmake (renamed from libtransport/cmake/Modules/Packaging.cmake)34
-rw-r--r--libtransport/includes/hicn/transport/CMakeLists.txt19
-rw-r--r--libtransport/includes/hicn/transport/auth/CMakeLists.txt3
-rw-r--r--libtransport/includes/hicn/transport/auth/common.h2
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hash.h4
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_suite.h5
-rw-r--r--libtransport/includes/hicn/transport/auth/identity.h77
-rw-r--r--libtransport/includes/hicn/transport/auth/key_id.h2
-rw-r--r--libtransport/includes/hicn/transport/auth/policies.h4
-rw-r--r--libtransport/includes/hicn/transport/auth/signer.h22
-rw-r--r--libtransport/includes/hicn/transport/auth/verifier.h14
-rw-r--r--libtransport/includes/hicn/transport/core/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/core/connector.h24
-rw-r--r--libtransport/includes/hicn/transport/core/content_object.h21
-rw-r--r--libtransport/includes/hicn/transport/core/endpoint.h14
-rw-r--r--libtransport/includes/hicn/transport/core/global_object_pool.h14
-rw-r--r--libtransport/includes/hicn/transport/core/interest.h19
-rw-r--r--libtransport/includes/hicn/transport/core/io_module.h11
-rw-r--r--libtransport/includes/hicn/transport/core/name.h11
-rw-r--r--libtransport/includes/hicn/transport/core/packet.h218
-rw-r--r--libtransport/includes/hicn/transport/core/payload_type.h2
-rw-r--r--libtransport/includes/hicn/transport/core/prefix.h6
-rw-r--r--libtransport/includes/hicn/transport/errors/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/errors/errors.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/indexing_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/invalid_ip_address_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/malformed_ahpacket_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/malformed_name_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/malformed_packet_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/not_implemented_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/null_pointer_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/runtime_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/tokenizer_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/errors/unexpected_manifest_exception.h2
-rw-r--r--libtransport/includes/hicn/transport/http/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/http/client_connection.h6
-rw-r--r--libtransport/includes/hicn/transport/http/default_values.h2
-rw-r--r--libtransport/includes/hicn/transport/http/facade.h2
-rw-r--r--libtransport/includes/hicn/transport/http/message.h2
-rw-r--r--libtransport/includes/hicn/transport/http/request.h2
-rw-r--r--libtransport/includes/hicn/transport/http/response.h2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/CMakeLists.txt3
-rw-r--r--libtransport/includes/hicn/transport/interfaces/callbacks.h9
-rw-r--r--libtransport/includes/hicn/transport/interfaces/notification.h (renamed from hicn-light/src/hicn/config/controlAdd.h)29
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h7
-rw-r--r--libtransport/includes/hicn/transport/interfaces/portal.h106
-rw-r--r--libtransport/includes/hicn/transport/interfaces/publication_options.h2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_consumer.h33
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h17
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_options_keys.h44
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_producer.h43
-rw-r--r--libtransport/includes/hicn/transport/interfaces/statistics.h62
-rw-r--r--libtransport/includes/hicn/transport/portability/CMakeLists.txt3
-rw-r--r--libtransport/includes/hicn/transport/portability/c_portability.h2
-rw-r--r--libtransport/includes/hicn/transport/portability/cpu.h40
-rw-r--r--libtransport/includes/hicn/transport/portability/portability.h5
-rw-r--r--libtransport/includes/hicn/transport/portability/win_portability.h86
-rw-r--r--libtransport/includes/hicn/transport/utils/CMakeLists.txt3
-rw-r--r--libtransport/includes/hicn/transport/utils/array.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/branch_prediction.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/chrono_typedefs.h101
-rw-r--r--libtransport/includes/hicn/transport/utils/conversions.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/daemonizator.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/event_thread.h15
-rw-r--r--libtransport/includes/hicn/transport/utils/fixed_block_allocator.h57
-rw-r--r--libtransport/includes/hicn/transport/utils/hash.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/linux.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/literals.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/log.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/move_wrapper.h1
-rw-r--r--libtransport/includes/hicn/transport/utils/noncopyable.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/object_pool.h21
-rw-r--r--libtransport/includes/hicn/transport/utils/ring_buffer.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/rtc_quality_score.h69
-rw-r--r--libtransport/includes/hicn/transport/utils/singleton.h15
-rw-r--r--libtransport/includes/hicn/transport/utils/spinlock.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/string_tokenizer.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/string_utils.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/thread_pool.h39
-rw-r--r--libtransport/includes/hicn/transport/utils/uri.h2
-rw-r--r--libtransport/src/CMakeLists.txt166
-rw-r--r--libtransport/src/auth/CMakeLists.txt3
-rw-r--r--libtransport/src/auth/crypto_hash.cc46
-rw-r--r--libtransport/src/auth/crypto_suite.cc50
-rw-r--r--libtransport/src/auth/identity.cc288
-rw-r--r--libtransport/src/auth/signer.cc113
-rw-r--r--libtransport/src/auth/verifier.cc101
-rw-r--r--libtransport/src/config.h.in5
-rw-r--r--libtransport/src/core/CMakeLists.txt19
-rw-r--r--libtransport/src/core/content_object.cc39
-rw-r--r--libtransport/src/core/errors.cc11
-rw-r--r--libtransport/src/core/errors.h7
-rw-r--r--libtransport/src/core/facade.h2
-rw-r--r--libtransport/src/core/global_workers.h43
-rw-r--r--libtransport/src/core/interest.cc19
-rw-r--r--libtransport/src/core/io_module.cc9
-rw-r--r--libtransport/src/core/local_connector.cc12
-rw-r--r--libtransport/src/core/local_connector.h4
-rw-r--r--libtransport/src/core/manifest.cc2
-rw-r--r--libtransport/src/core/manifest.h74
-rw-r--r--libtransport/src/core/manifest_format.h108
-rw-r--r--libtransport/src/core/manifest_format_fixed.cc318
-rw-r--r--libtransport/src/core/manifest_format_fixed.h228
-rw-r--r--libtransport/src/core/manifest_inline.h42
-rw-r--r--libtransport/src/core/memif_connector.cc497
-rw-r--r--libtransport/src/core/memif_connector.h (renamed from libtransport/src/io_modules/memif/memif_connector.h)72
-rw-r--r--libtransport/src/core/name.cc60
-rw-r--r--libtransport/src/core/packet.cc618
-rw-r--r--libtransport/src/core/pending_interest.cc74
-rw-r--r--libtransport/src/core/pending_interest.h26
-rw-r--r--libtransport/src/core/portal.cc10
-rw-r--r--libtransport/src/core/portal.h550
-rw-r--r--libtransport/src/core/prefix.cc14
-rw-r--r--libtransport/src/core/tcp_socket_connector.cc16
-rw-r--r--libtransport/src/core/tcp_socket_connector.h2
-rw-r--r--libtransport/src/core/udp_connector.cc371
-rw-r--r--libtransport/src/core/udp_connector.h (renamed from libtransport/src/io_modules/forwarder/udp_tunnel.h)39
-rw-r--r--libtransport/src/core/udp_listener.cc (renamed from libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc)20
-rw-r--r--libtransport/src/core/udp_listener.h (renamed from libtransport/src/io_modules/forwarder/udp_tunnel_listener.h)8
-rw-r--r--libtransport/src/http/CMakeLists.txt2
-rw-r--r--libtransport/src/http/client_connection.cc26
-rw-r--r--libtransport/src/http/request.cc2
-rw-r--r--libtransport/src/http/response.cc2
-rw-r--r--libtransport/src/implementation/CMakeLists.txt2
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.cc36
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.h6
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.cc71
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.h13
-rw-r--r--libtransport/src/implementation/socket.cc31
-rw-r--r--libtransport/src/implementation/socket.h24
-rw-r--r--libtransport/src/implementation/socket_consumer.h178
-rw-r--r--libtransport/src/implementation/socket_producer.h207
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.cc6
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.h2
-rw-r--r--libtransport/src/implementation/tls_socket_consumer.cc31
-rw-r--r--libtransport/src/implementation/tls_socket_consumer.h7
-rw-r--r--libtransport/src/implementation/tls_socket_producer.cc11
-rw-r--r--libtransport/src/implementation/tls_socket_producer.h2
-rw-r--r--libtransport/src/interfaces/CMakeLists.txt2
-rw-r--r--libtransport/src/interfaces/callbacks.cc2
-rw-r--r--libtransport/src/interfaces/p2psecure_socket_consumer.cc2
-rw-r--r--libtransport/src/interfaces/p2psecure_socket_producer.cc11
-rw-r--r--libtransport/src/interfaces/portal.cc115
-rw-r--r--libtransport/src/interfaces/socket_consumer.cc43
-rw-r--r--libtransport/src/interfaces/socket_producer.cc44
-rw-r--r--libtransport/src/interfaces/tls_rtc_socket_producer.cc2
-rw-r--r--libtransport/src/interfaces/tls_rtc_socket_producer.h2
-rw-r--r--libtransport/src/interfaces/tls_socket_consumer.cc2
-rw-r--r--libtransport/src/interfaces/tls_socket_consumer.h2
-rw-r--r--libtransport/src/interfaces/tls_socket_producer.cc2
-rw-r--r--libtransport/src/interfaces/tls_socket_producer.h2
-rw-r--r--libtransport/src/io_modules/CMakeLists.txt58
-rw-r--r--libtransport/src/io_modules/forwarder/CMakeLists.txt11
-rw-r--r--libtransport/src/io_modules/forwarder/errors.cc2
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.cc64
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.h29
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.cc19
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.h9
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel.cc290
-rw-r--r--libtransport/src/io_modules/hicn-light-ng/CMakeLists.txt62
-rw-r--r--libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc264
-rw-r--r--libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h (renamed from libtransport/src/io_modules/udp/hicn_forwarder_module.h)34
-rw-r--r--libtransport/src/io_modules/loopback/CMakeLists.txt8
-rw-r--r--libtransport/src/io_modules/loopback/local_face.cc2
-rw-r--r--libtransport/src/io_modules/loopback/local_face.h2
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.cc14
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.h7
-rw-r--r--libtransport/src/io_modules/memif/CMakeLists.txt38
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.c15
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.h2
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.cc492
-rw-r--r--libtransport/src/io_modules/memif/memif_vapi.c7
-rw-r--r--libtransport/src/io_modules/memif/memif_vapi.h6
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.cc35
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.h12
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_connector.cc200
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_connector.h79
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_interface.cc56
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_interface.h61
-rw-r--r--libtransport/src/io_modules/udp/CMakeLists.txt32
-rw-r--r--libtransport/src/io_modules/udp/hicn_forwarder_module.cc181
-rw-r--r--libtransport/src/io_modules/udp/udp_socket_connector.cc211
-rw-r--r--libtransport/src/io_modules/udp/udp_socket_connector.h88
-rw-r--r--libtransport/src/libhicntransport-config.cmake.in8
-rw-r--r--libtransport/src/protocols/CMakeLists.txt16
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.cc2
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.h2
-rw-r--r--libtransport/src/protocols/cbr.cc10
-rw-r--r--libtransport/src/protocols/cbr.h2
-rw-r--r--libtransport/src/protocols/congestion_window_protocol.h2
-rw-r--r--libtransport/src/protocols/data_processing_events.h2
-rw-r--r--libtransport/src/protocols/datagram_reassembly.cc2
-rw-r--r--libtransport/src/protocols/datagram_reassembly.h2
-rw-r--r--libtransport/src/protocols/errors.cc2
-rw-r--r--libtransport/src/protocols/errors.h2
-rw-r--r--libtransport/src/protocols/fec/CMakeLists.txt2
-rw-r--r--libtransport/src/protocols/fec/fec.cc176
-rw-r--r--libtransport/src/protocols/fec/rely.cc103
-rw-r--r--libtransport/src/protocols/fec/rely.h61
-rw-r--r--libtransport/src/protocols/fec/rs.cc161
-rw-r--r--libtransport/src/protocols/fec/rs.h101
-rw-r--r--libtransport/src/protocols/fec_base.h82
-rw-r--r--libtransport/src/protocols/incremental_indexer_bytestream.cc6
-rw-r--r--libtransport/src/protocols/incremental_indexer_bytestream.h10
-rw-r--r--libtransport/src/protocols/index_manager_bytestream.cc2
-rw-r--r--libtransport/src/protocols/index_manager_bytestream.h18
-rw-r--r--libtransport/src/protocols/indexer.cc35
-rw-r--r--libtransport/src/protocols/indexer.h26
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc59
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer_bytestream.h12
-rw-r--r--libtransport/src/protocols/prod_protocol_bytestream.cc231
-rw-r--r--libtransport/src/protocols/prod_protocol_bytestream.h11
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.cc553
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.h58
-rw-r--r--libtransport/src/protocols/production_protocol.cc141
-rw-r--r--libtransport/src/protocols/production_protocol.h34
-rw-r--r--libtransport/src/protocols/protocol.h73
-rw-r--r--libtransport/src/protocols/raaqm.cc33
-rw-r--r--libtransport/src/protocols/raaqm.h19
-rw-r--r--libtransport/src/protocols/raaqm_data_path.cc31
-rw-r--r--libtransport/src/protocols/raaqm_data_path.h16
-rw-r--r--libtransport/src/protocols/rate_estimation.cc101
-rw-r--r--libtransport/src/protocols/rate_estimation.h21
-rw-r--r--libtransport/src/protocols/reassembly.cc2
-rw-r--r--libtransport/src/protocols/reassembly.h8
-rw-r--r--libtransport/src/protocols/rtc/CMakeLists.txt23
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.cc38
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.h32
-rw-r--r--libtransport/src/protocols/rtc/rtc.cc616
-rw-r--r--libtransport/src/protocols/rtc/rtc.h24
-rw-r--r--libtransport/src/protocols/rtc/rtc_consts.h47
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.cc99
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.h26
-rw-r--r--libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc155
-rw-r--r--libtransport/src/protocols/rtc/rtc_forwarding_strategy.h78
-rw-r--r--libtransport/src/protocols/rtc/rtc_indexer.h45
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.cc539
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.h100
-rw-r--r--libtransport/src/protocols/rtc/rtc_packet.h163
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc.h12
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_congestion_detection.cc74
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_congestion_detection.h47
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_iat.cc287
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_iat.h93
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_queue.cc6
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_queue.h5
-rw-r--r--libtransport/src/protocols/rtc/rtc_reassembly.cc109
-rw-r--r--libtransport/src/protocols/rtc/rtc_reassembly.h21
-rw-r--r--libtransport/src/protocols/rtc/rtc_recovery_strategy.cc418
-rw-r--r--libtransport/src/protocols/rtc/rtc_recovery_strategy.h154
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_delay.cc122
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_delay.h53
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_fec_only.cc118
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_fec_only.h51
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_low_rate.cc167
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_low_rate.h69
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc60
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_recovery_off.h44
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc61
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_rtx_only.h44
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.cc486
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.h150
-rw-r--r--libtransport/src/protocols/rtc/rtc_verifier.cc238
-rw-r--r--libtransport/src/protocols/rtc/rtc_verifier.h79
-rw-r--r--libtransport/src/protocols/transport_protocol.cc144
-rw-r--r--libtransport/src/protocols/transport_protocol.h29
-rw-r--r--libtransport/src/test/CMakeLists.txt54
-rw-r--r--libtransport/src/test/main.cc1
-rw-r--r--libtransport/src/test/test_aggregated_header.cc622
-rw-r--r--libtransport/src/test/test_auth.cc178
-rw-r--r--libtransport/src/test/test_consumer_producer_rtc.cc7
-rw-r--r--libtransport/src/test/test_core_manifest.cc110
-rw-r--r--libtransport/src/test/test_event_thread.cc36
-rw-r--r--libtransport/src/test/test_fec_base_rely.cc453
-rw-r--r--libtransport/src/test/test_fec_base_rs.cc412
-rw-r--r--libtransport/src/test/test_fec_reedsolomon.cc122
-rw-r--r--libtransport/src/test/test_fec_rely_wrapper.cc131
-rw-r--r--libtransport/src/test/test_fixed_block_allocator.cc211
-rw-r--r--libtransport/src/test/test_interest.cc20
-rw-r--r--libtransport/src/test/test_memif_connector.cc152
-rw-r--r--libtransport/src/test/test_packet.cc11
-rw-r--r--libtransport/src/test/test_packet_allocator.cc106
-rw-r--r--libtransport/src/test/test_quality_score.cc135
-rw-r--r--libtransport/src/test/test_sessions.cc77
-rw-r--r--libtransport/src/test/test_thread_pool.cc70
-rw-r--r--libtransport/src/transport.config2
-rw-r--r--libtransport/src/utils/CMakeLists.txt7
-rw-r--r--libtransport/src/utils/content_store.cc9
-rw-r--r--libtransport/src/utils/content_store.h5
-rw-r--r--libtransport/src/utils/daemonizator.cc2
-rw-r--r--libtransport/src/utils/deadline_timer.h57
-rw-r--r--libtransport/src/utils/epoll_event_reactor.cc190
-rw-r--r--libtransport/src/utils/epoll_event_reactor.h165
-rw-r--r--libtransport/src/utils/event_reactor.h2
-rw-r--r--libtransport/src/utils/fd_deadline_timer.h8
-rw-r--r--libtransport/src/utils/log.cc4
-rw-r--r--libtransport/src/utils/max_filter.h58
-rw-r--r--libtransport/src/utils/membuf.cc23
-rw-r--r--libtransport/src/utils/memory_pool_allocator.h2
-rw-r--r--libtransport/src/utils/min_filter.h2
-rw-r--r--libtransport/src/utils/stream_buffer.h2
-rw-r--r--libtransport/src/utils/string_tokenizer.cc2
-rw-r--r--libtransport/src/utils/suffix_strategy.h166
-rw-r--r--libtransport/src/utils/test.h2
-rw-r--r--libtransport/src/utils/uri.cc2
-rw-r--r--libtransport/third-party/CMakeLists.txt77
-rw-r--r--libtransport/third-party/CMakeLists.txt.orig85
-rw-r--r--libtransport/third-party/CMakeLists.txt.rej21
-rw-r--r--libtransport/third-party/glog.patch2
-rw-r--r--libtransport/third-party/memif.patch43
-rw-r--r--scripts/build-packages.sh40
-rw-r--r--scripts/checkstyle.sh4
-rw-r--r--scripts/functions.sh121
-rw-r--r--scripts/install-vpp.sh38
-rw-r--r--telemetry/CMakeLists.txt14
-rw-r--r--telemetry/vpp-collectd/CMakeLists.txt46
-rw-r--r--telemetry/vpp-collectd/cmake/packaging.cmake (renamed from telemetry/vpp-collectd/cmake/Modules/Packaging.cmake)6
-rw-r--r--telemetry/vpp-collectd/common/plugin.h12
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt67
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c4
-rw-r--r--telemetry/vpp-collectd/vpp/CMakeLists.txt52
-rw-r--r--telemetry/vpp-collectd/vpp/vpp.c4
-rw-r--r--tests/.env13
-rw-r--r--tests/2-nodes-hicn-light.yml65
-rw-r--r--tests/2-nodes-vpp-bridge.yml107
-rw-r--r--tests/2-nodes-vpp-memif-replication.yml143
-rw-r--r--tests/2-nodes-vpp-memif.yml116
-rw-r--r--tests/2-nodes.yml43
-rw-r--r--tests/Dockerfile.ci5
-rwxr-xr-xtests/channel.sh22
-rwxr-xr-xtests/config.sh290
-rw-r--r--tests/forwarder.robot45
-rw-r--r--tests/functional-tests/2-nodes-hicn-light.robot24
-rw-r--r--tests/functional-tests/2-nodes-vpp-bridge.robot24
-rw-r--r--tests/functional-tests/2-nodes-vpp-memif-replication.robot23
-rw-r--r--tests/functional-tests/2-nodes-vpp-memif.robot23
-rw-r--r--tests/resources/libraries/robot/common.robot23
-rw-r--r--tests/resources/libraries/robot/runtest.robot92
-rw-r--r--tests/run-functional.sh (renamed from hicn-light/src/hicn/command_line/daemon/CMakeLists.txt)42
-rw-r--r--tests/test_forwarder.sh437
-rw-r--r--versions.cmake8
1096 files changed, 68012 insertions, 64497 deletions
diff --git a/.cz.toml b/.cz.toml
new file mode 100644
index 000000000..2cbf9452e
--- /dev/null
+++ b/.cz.toml
@@ -0,0 +1,5 @@
+[tool]
+[tool.commitizen]
+name = "cz_conventional_commits"
+version = "3.9.1"
+tag_format = "v$version"
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..486e001fb
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,12 @@
+**/report.xml
+**/build*
+**/.devcontainer
+**/.vscode
+**/docker/Dockerfile
+**/docker/Dockerfile.clang
+ci/Dockerfile*
+#**/deb
+**/*.tar
+**/.gitignore
+**/info.txt
+./install*
diff --git a/.gitignore b/.gitignore
index 52ecb4eba..685e356c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,18 @@
build*
.ccls-cache/
compile_commands.json
+sonar*
+.scannerwork*
+deb
+info.txt
+.vscode
+.DS_Store
+
+# Local install
+install*
+
+# Robot
+tests/**/*.xml
+tests/**/*.html
+tests/**/*.log
+*.tar
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..55a6478e7
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "cmake"]
+ path = cmake
+ url = https://github.com/icn-team/cmake-modules.git
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 000000000..af94bbc3d
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,7 @@
+repos:
+- hooks:
+ - id: commitizen
+ stages:
+ - commit-msg
+ repo: https://github.com/commitizen-tools/commitizen
+ rev: v2.19.0
diff --git a/AUTHORS b/AUTHORS
index 8f67db1f5..535ea8297 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,8 +1,10 @@
Jordan Augé <jordan.auge@cisco.com>
Giovanna Carofiglio <gcarofig@cisco.com>
Alberto Compagno <acompagn@cisco.com>
+Enrico Loparco <eloparco@cisco.com>
Angelo Mantellini <manangel@cisco.com>
Luca Muscariello <lumuscar@cisco.com>
Michele Papalini <mpapal@cisco.com>
+Olivier Roques <oroques@cisco.com>
Jacques Samain <jsamain@cisco.com>
Mauro Sardara <msardara@cisco.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ad59c81d..1ba276c41 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,15 +11,55 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-
+##############################################################
+# Project and cmake version
+##############################################################
+cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
project(hicn-fdio)
+##############################################################
+# Fetch submodules if needed
+##############################################################
+find_package(Git QUIET)
+if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
+ # Update submodules as needed
+ option(GIT_SUBMODULE "Check submodules during build" ON)
+ if(GIT_SUBMODULE)
+ message(STATUS "Submodule update")
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ RESULT_VARIABLE GIT_SUBMOD_RESULT
+ )
+
+ if(NOT GIT_SUBMOD_RESULT EQUAL "0")
+ message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
+ endif()
+ endif()
+endif()
+
+if(NOT EXISTS "${PROJECT_SOURCE_DIR}/cmake/Modules")
+ message(
+ FATAL_ERROR
+ "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again."
+ )
+endif()
+
+##############################################################
+# CMake Modules
+##############################################################
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
+if(EXISTS "${PROJECT_SOURCE_DIR}/internal/cmake/Modules")
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/internal/cmake/Modules")
+ set(INTERNAL_ENVIRONMENT True)
+endif()
+include("${CMAKE_CURRENT_SOURCE_DIR}/versions.cmake")
-set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+include(CommonSetup)
-## Enabled components
+##############################################################
+# Enabled components
+##############################################################
option(BUILD_LIBHICN "Build the hicn core library" ON)
option(BUILD_HICNLIGHT "Build the hicn light forwarder" ON)
option(BUILD_LIBTRANSPORT "Build the hicn transport library" ON)
@@ -38,6 +78,10 @@ option(BUILD_TELEMETRY "Build telemetry projects" OFF)
option(BUILD_TESTS "Build unit tests" OFF)
option(DISABLE_EXECUTABLES "Disable executables" OFF)
+
+##############################################################
+# Basic sanity checks
+##############################################################
if (BUILD_APPS AND NOT BUILD_LIBTRANSPORT)
message(STATUS "Libhicntransport required. Enabled by default.")
set (BUILD_LIBTRANSPORT ON)
@@ -61,9 +105,9 @@ endif()
list(APPEND dir_options
BUILD_LIBHICN
- BUILD_HICNLIGHT
BUILD_HICNPLUGIN
BUILD_CTRL
+ BUILD_HICNLIGHT
BUILD_LIBTRANSPORT
BUILD_APPS
BUILD_SYSREPOPLUGIN
@@ -81,7 +125,10 @@ set(BUILD_SYSREPOPLUGIN_DIR ctrl/sysrepo-plugins)
set(BUILD_EXTRAS_DIR extras/)
set(BUILD_TELEMETRY_DIR telemetry)
-## Add enabled components
+
+##############################################################
+# Add enabled components to the build
+##############################################################
foreach (opt ${dir_options})
if (${opt})
list(APPEND subdirs
@@ -90,7 +137,10 @@ foreach (opt ${dir_options})
endif()
endforeach()
-# Add unit tests
+
+##############################################################
+# Build gtest if tests are enabled
+##############################################################
if (BUILD_TESTS)
message(STATUS "Tests enabled.")
include (GTestImport)
@@ -105,10 +155,10 @@ endif()
message(STATUS "Building the following subprojects: ${subdirs}")
foreach(dir ${subdirs})
+ pr_title("Subproject" "${dir}")
add_subdirectory(${dir})
endforeach()
add_subdirectory(docs/doxygen)
-include(Packager)
-make_packages() \ No newline at end of file
+make_packages()
diff --git a/Dockerfile.dev b/Dockerfile.dev
new file mode 100644
index 000000000..bcd75746f
--- /dev/null
+++ b/Dockerfile.dev
@@ -0,0 +1,53 @@
+FROM ubuntu:focal
+
+WORKDIR /hicn-build
+
+RUN apt-get update
+
+# Do not prompt
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Prevent vpp to set sysctl
+ENV VPP_INSTALL_SKIP_SYSCTL=1
+
+# Add packagecloud repo
+RUN apt-get install -y git curl
+
+# Get versions from versions.cmake
+ARG VERSIONS_PATH=/tmp/versions.cmake
+COPY versions.cmake ${VERSIONS_PATH}
+
+RUN export VPP_VERSION=$(cat ${VERSIONS_PATH} | grep VPP_DEFAULT_VERSION | cut -d ' ' -f 2 | tr -d '"' | grep -Po '\d\d.\d\d') && echo ${VPP_VERSION}
+
+# Install devel packages
+RUN apt update
+SHELL ["/bin/bash", "-c"]
+RUN export VPP_VERSION=$(cat ${VERSIONS_PATH} | grep VPP_DEFAULT_VERSION | cut -d ' ' -f 2 | tr -d '"' | grep -Po '\d\d.\d\d') && \
+ curl -s https://packagecloud.io/install/repositories/fdio/${VPP_VERSION//./}/script.deb.sh | bash && \
+ apt-get install -y \
+ cmake \
+ ninja-build \
+ unzip \
+ libconfig-dev \
+ python3-ply \
+ libconfig++-dev \
+ build-essential \
+ vpp-dev \
+ libvppinfra-dev \
+ vpp-plugin-core \
+ vpp \
+ libvppinfra \
+ libevent-dev \
+ libssl-dev \
+ make \
+ sudo \
+ libcurl4-openssl-dev \
+ iproute2 \
+ iperf3 \
+ iputils-ping \
+ tcpdump \
+ gdb \
+ libasio-dev --no-install-recommends
+
+# Switch back to dialog for any ad-hoc use of apt-get
+ENV DEBIAN_FRONTEND=
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..3d74f9b72
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,240 @@
+# Copyright (c) 2021-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.
+
+
+export WS_ROOT=$(CURDIR)
+SHELL := /bin/bash
+FUNCTIONAL := tests/run-functional.sh
+MKDIR := mkdir -p
+RM := rm
+VERSIONFILE := $(CURDIR)/versions.cmake
+
+# Docker stuff
+DOCKER := docker
+DEV_IMAGE := hicn-dev-img
+DOCKERFILE := Dockerfile.dev
+DEV_CONTAINER := hicn-dev
+
+#
+# OS Detection
+#
+ifeq ($(shell uname),Darwin)
+OS_ID = macos
+OPENSSL_ROOT=/usr/local/opt/openssl@1.1
+else
+OS_ID = $(shell grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
+OS_VERSION_ID = $(shell grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
+endif
+
+ifeq ($(shell uname),Darwin)
+BUILD_HICNPLUGIN := OFF
+PUNTING := OFF
+else
+BUILD_HICNPLUGIN := ON
+PUNTING := ON
+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 += doxygen
+
+MACOS_DEPENDS = asio libconfig ninja
+
+.PHONY = help
+help:
+ @echo "Targets"
+ @echo " dep - install software dependencies"
+ @echo " build - build debug binaries. Optional argument: INSTALL_DIR"
+ @echo " build-release - build release binaries"
+ @echo " build-coverage - build with coverage metainformation"
+ @echo " wipe - wipe debug binaries"
+ @echo " wipe-release - wipe release binaries"
+ @echo " docs - build documentation"
+ @echo ""
+ @echo "Make Arguments:"
+ @echo " INSTALL_PREFIX=<path> - Install software at specified location."
+ @echo " BUILD_PATH=<path> - Path of build folder."
+ @echo " VPP_HOME=<path> - Path of VPP"
+ @echo " OPENSSL_ROOT=<path> - Path of Openssl installation"
+ @echo " ENABLE_RELY=<ON/OFF> - Enable/disable rely compilation"
+ @echo " SONAR_BUILD_WRAPPER=<path>" - Path of sonarqube build wrapper
+ @echo " SONAR_OUT_DIR=<path>" - Path of directory of sonarqube report
+ @echo "Current Arguments:"
+ @echo " INSTALL_PREFIX=$(INSTALL_PREFIX)"
+ @echo " VPP_HOME=$(VPP_HOME)"
+ @echo " OPENSSL_ROOT=$(OPENSSL_ROOT)"
+ @echo " ENABLE_RELY=$(ENABLE_RELY)"
+ @echo " SONAR_BUILD_WRAPPER=$(SONAR_BUILD_WRAPPER)"
+ @echo " SONAR_OUT_DIR=$(SONAR_OUT_DIR)"
+
+.PHONY = vpp-dep
+vpp-dep:
+ VERSION_PATH=$(VERSIONFILE) sudo -E $(SHELL) scripts/install-vpp.sh
+
+.PHONY = dep
+dep: vpp-dep
+ifeq ($(shell uname),Darwin)
+ brew install $(MACOS_DEPENDS)
+else ifeq ($(filter ubuntu debian,$(OS_ID)),$(OS_ID))
+ @sudo -E apt-get update
+ @sudo -E apt-get $(APT_ARGS) -y install $(DEB_DEPENDS) --no-install-recommends
+else
+ @echo "Operating system not supported (yet)"
+endif
+
+.PHONY = deps
+deps: dep
+
+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)))
+ $(1) := $$(BUILD_FOLDER)
+endef
+
+define configure
+ $(eval $(call build_folder,BUILD_FOLDER,$(1)))
+ $(eval PREFIX=$(or $(INSTALL_PREFIX), $(WS_ROOT)/install-$(LOWER_BUILDTYPE)))
+ $(eval COVERAGE=$(or $(COVERAGE), OFF))
+ $(eval VPP_HOME=$(or $(VPP_HOME), /usr))
+ $(eval ENABLE_RELY=$(or $(ENABLE_RELY), OFF))
+ $(MKDIR) $(BUILD_FOLDER)
+ cmake \
+ -B $(BUILD_FOLDER) \
+ -S $(WS_ROOT) \
+ -G Ninja \
+ -DCMAKE_INSTALL_PREFIX=$(PREFIX) \
+ -DCMAKE_BUILD_TYPE=$(1) \
+ -DBUILD_HICNLIGHT=ON \
+ -DBUILD_APPS=ON \
+ -DBUILD_SYSREPOPLUGIN=OFF \
+ -DBUILD_EXTRAS=OFF \
+ -DBUILD_TELEMETRY=OFF \
+ -DBUILD_CTRL=ON \
+ -DBUILD_HICNPLUGIN=$(BUILD_HICNPLUGIN) \
+ -DVPP_HOME=$(VPP_HOME) \
+ -DCOVERAGE=$(COVERAGE) \
+ -DENABLE_RELY=$(ENABLE_RELY) \
+ -DOPENSSL_ROOT_DIR=$(OPENSSL_ROOT) \
+ -DBUILD_TESTS=ON
+endef
+
+define build
+ $(eval $(call build_folder,BUILD_FOLDER,$(1)))
+ cmake --build $(BUILD_FOLDER) -- -j 4 install
+endef
+
+define build_coverage
+ $(eval $(call build_folder,BUILD_FOLDER,$(1)))
+ $(eval SONAR_OUT_DIR=$(or $(SONAR_OUT_DIR), $(WS_ROOT)/sonarqube-output))
+ $(SONAR_BUILD_WRAPPER) --out-dir $(SONAR_OUT_DIR) cmake --build $(BUILD_FOLDER) -- install
+endef
+
+define package
+ $(eval $(call build_folder,BUILD_FOLDER,$(1)))
+ cmake --build $(BUILD_FOLDER) -- package
+endef
+
+.PHONY: configure-debug
+configure-debug:
+ $(call configure,Debug,)
+
+.PHONY: configure-release
+configure-release:
+ $(call configure,Release,)
+
+.PHONY = build
+build: configure-debug
+ $(call build,Debug,)
+
+.PHONY = build-coverage
+build-coverage:
+ifndef SONAR_BUILD_WRAPPER
+ $(error SONAR_BUILD_WRAPPER is not set)
+endif
+ $(eval COVERAGE := ON)
+ $(call configure,Debug,)
+ $(call build_coverage,Debug,)
+
+.PHONY = build-release
+build-release: configure-release
+ $(call build,Release,)
+
+.PHONY = package
+package: build
+ $(call package,Debug,)
+
+.PHONY = package-release
+package-release: build-release
+ $(call package,Release,)
+
+define wipe
+ $(eval LOWER_BUILDTYPE=$(shell echo $(1) | tr A-Z a-z))
+ $(RM) -rf build-$(LOWER_BUILDTYPE)-$(OS_ID)
+ $(RM) -rf install-$(LOWER_BUILDTYPE)
+endef
+
+.PHONY = wipe
+wipe:
+ $(call wipe,Debug,)
+
+.PHONY = wipe-release
+wipe-release:
+ $(call wipe,Release,)
+
+define test
+ $(eval $(call build_folder,BUILD_FOLDER,$(1)))
+ cmake --build $(BUILD_FOLDER) -- test
+endef
+
+.PHONY = test-debug
+test-debug: build
+ $(call test, Debug,)
+
+.PHONY = test
+test: build-release
+ $(call test, Release,)
+
+.PHONY = functional
+functional:
+ $(SHELL) $(FUNCTIONAL)
+
+define documentation
+ python3 -m pip install --user virtualenv
+ python3 -m virtualenv env
+ (source $(WS_ROOT)/env/bin/activate; \
+ pip install -r $(WS_ROOT)/docs/etc/requirements.txt; \
+ cd docs; \
+ make html )
+endef
+
+.PHONY = doc
+doc:
+ $(call documentation,)
+
+
+.PHONY = docker
+docker:
+ $(DOCKER) build -t $(DEV_IMAGE) -f $(DOCKERFILE) ${PWD}
+ifeq ($(strip $(shell $(DOCKER) ps -q -f name=$(DEV_CONTAINER))),)
+ifneq ($(shell $(DOCKER) ps -aq -f status=exited -f name=$(DEV_CONTAINER)),)
+ docker rm $(DEV_CONTAINER)
+endif
+ $(DOCKER) run -dv ${PWD}:/workspace -w /workspace --name $(DEV_CONTAINER) --entrypoint=tail $(DEV_IMAGE) -f /dev/null
+endif
+ $(DOCKER) exec -it $(DEV_CONTAINER) bash
+
+.PHONY = wipe-docker
+wipe-docker:
+ $(DOCKER) rm --force $(DEV_CONTAINER) \ No newline at end of file
diff --git a/README.md b/README.md
index 4ddd78fcf..98f57d61c 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,13 @@
## Introduction
-hicn is an open source implementation of Cisco's hICN. It includes a network stack, that implements
-ICN forwarding path in IPv6, and a transport stack that implements two main transport protocols and
-a socket API. The transport protocols provide one reliable transport service implementation and a
-real-time transport service for audio/video media.
+This is an open source implementation of Cisco's hICN. It includes a network
+stack, that implements ICN forwarding path in IPv6, and a transport stack that
+implements reliable and unrelieable transport with congestion control and loss
+management by ARQ or FEC. It supports applications such as reliable multicast
+for ABR video, real-time video conferencing and on-line multiplayer games.
+The client stack has been tested on iOS and Android over Wi-Fi, LTE and Ethernet
+including multi-homing use cases.
## Directory layout
@@ -15,29 +18,27 @@ real-time transport service for audio/video media.
| hicn-plugin | VPP plugin |
| hicn-light | Lightweight packet forwarder |
| libtransport | Support library with transport layer and API |
-| utils | Tools for testing |
-| apps | Application examples using hicn stack |
+| apps | Application examples using hicn stack and tools |
| ctrl | Tools and libraries for network configuration and control |
-hicn plugin is a VPP plugin that implement hicn packet processing as specified in
-https://datatracker.ietf.org/doc/draft-muscariello-intarea-hicn/. The transport library is used to
-implement the hicn host stack and makes use of libmemif as high performance connector between
-transport and the network stack. The transport library makes use of VPP binary API to configure the
-local namespace (local face management).
+hicn plugin is a VPP plugin that implement hicn packet processing as specified
+in https://datatracker.ietf.org/doc/draft-muscariello-intarea-hicn/. The
+transport library is used to implement the hicn host stack and makes use of
+libmemif as high performance connector between transport and the network stack.
+The transport library makes use of VPP binary API to configure the local
+namespace (local face management).
## Supported platforms
-- Ubuntu 16.04 LTS (amd64)
-- Ubuntu 18.04 LTS (amd64, arm64)
-- CentOS 7 (x86_64)
-- Android 10
-- iOS 13
-- macOS 10.15
-- Windows 10
+- Ubuntu 20.04 LTS (amd64, arm64)
+- Android 10+
+- iOS 13+
+- macOS 10.15+
+- Windows 10+
## Binaries
-### Ubuntu 16/18 (amd64) and CentOS 7 (x86_64)
+### Ubuntu (amd64, arm64)
<https://packagecloud.io/fdio/release>
@@ -45,17 +46,12 @@ local namespace (local face management).
<https://hub.docker.com/u/icnteam>
-### Vagrant
-
-<https://app.vagrantup.com/icnteam/>
-
### Release note
-The current master branch provides the latest release which is compatible with the latest VPP stable.
-No other VPP releases are supported nor maintained. At every new VPP release distribution hicn
-master branch is updated to work with the latest stable release. All previous stable releases
-are discontinued and not maintained. The user who is interested in a specific release can always
-checkout the right code tree by searching the latest commit under a given git tag carrying the
-release version.
-
-
+The current master branch provides the latest release which is compatible with
+the latest VPP stable. No other VPP releases are supported nor maintained. At
+every new VPP release distribution hicn master branch is updated to work with
+the latest stable release. All previous stable releases are discontinued and not
+maintained. The user who is interested in a specific release can always checkout
+the right code tree by searching the latest commit under a given git tag
+carrying the release version.
diff --git a/apps/.clang-format b/apps/.clang-format
index cd21e2017..adc73c6fd 100644
--- a/apps/.clang-format
+++ b/apps/.clang-format
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2021 Cisco and/or its affiliates.
+# 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:
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index df1b9fc7c..b06d7bcb4 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,37 +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)
-set(CMAKE_CXX_STANDARD 14)
-
project(apps)
+
+##############################################################
+# C Standard
+##############################################################
+set(CMAKE_CXX_STANDARD 17)
+
+
+##############################################################
+# Cmake modules
+##############################################################
+include("${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake")
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
- "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+ ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules
)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif ()
-
-include(BuildMacros)
-include(WindowsMacros)
+##############################################################
+# Libs and Bins names
+##############################################################
set(HICN_APPS hicn-apps CACHE INTERNAL "" FORCE)
+set(HIGET higet)
+set(HTTP_PROXY hicn-http-proxy)
+set(LIBHTTP_PROXY hicnhttpproxy)
+set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static)
+
+##############################################################
+# Dependencies and third party libs
+##############################################################
find_package(Threads REQUIRED)
-find_package(Libconfig++ REQUIRED)
+find_package(Libconfig++ ${LIBCONFIG_DEFAULT_VERSION} REQUIRED)
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(Libtransport REQUIRED)
- find_package(Libhicn REQUIRED)
- find_package(hicnctrl REQUIRED)
+ include(CommonSetup)
+
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
+ find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE)
+ find_package(Libhicntransport ${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 LIBTRANSPORT_LIBRARIES hicn::hicntransport.${LIBTYPE})
+ list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
else()
if (DISABLE_SHARED_LIBRARIES)
- find_package(OpenSSL REQUIRED)
+ find_package(OpenSSL ${OPENSSL_DEFAULT_VERSION} REQUIRED)
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC})
set(LIBHICN_LIBRARIES ${LIBHICN_STATIC})
set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
@@ -56,20 +87,18 @@ else()
)
endif()
-if (WIN32)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 /wd4996")
-endif ()
-include(Packaging)
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
+
+##############################################################
+# Subdirectories
+##############################################################
add_subdirectory(ping)
add_subdirectory(hiperf)
-
-set(HIGET higet)
-set(HTTP_PROXY hicn-http-proxy)
-
-if (NOT WIN32)
- add_subdirectory(http-proxy)
-endif ()
-
+add_subdirectory(http-proxy)
add_subdirectory(higet)
diff --git a/apps/cmake/Modules/Packaging.cmake b/apps/cmake/packaging.cmake
index 981eb728e..9142598ad 100644
--- a/apps/cmake/Modules/Packaging.cmake
+++ b/apps/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -18,21 +18,34 @@ useful for testing and debugging within a hicn network."
)
set(${HICN_APPS}_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT} (>= stable_version), lib${LIBHICNCTRL} (>= stable_version)"
+ "lib${LIBTRANSPORT} (= stable_version), lib${LIBHICNCTRL} (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_APPS}-dev_DEB_DEPENDENCIES
- "${HICN_APPS} (>= stable_version), lib${LIBTRANSPORT}-dev (>= stable_version), lib${LIBHICNCTRL}-dev (>= stable_version)"
+ "${HICN_APPS} (= stable_version), lib${LIBTRANSPORT}-dev (= stable_version), lib${LIBHICNCTRL}-dev (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_APPS}_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT} >= stable_version, lib${LIBHICNCTRL} >= stable_version"
+ "lib${LIBTRANSPORT} = stable_version, lib${LIBHICNCTRL} = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_APPS}-dev_RPM_DEPENDENCIES
- "${HICN_APPS} >= stable_version, lib${LIBTRANSPORT}-dev >= stable_version, lib${LIBHICNCTRL}-dev >= stable_version"
+ "${HICN_APPS} = stable_version, lib${LIBTRANSPORT}-dev = stable_version, lib${LIBHICNCTRL}-dev = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
-) \ No newline at end of file
+)
+
+if (INTERNAL_ENVIRONMENT)
+ include(CheckSsl)
+ CheckSsl()
+ set(${HICN_APPS}_DEB_DEPENDENCIES
+ "${${HICN_APPS}_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY}"
+ CACHE STRING "Dependencies for deb/rpm package."
+ )
+ set(${HICN_APPS}-dev_DEB_DEPENDENCIES
+ "${${HICN_APPS}-dev_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY_DEV}"
+ CACHE STRING "Dependencies for deb/rpm package."
+ )
+endif () \ No newline at end of file
diff --git a/apps/higet/CMakeLists.txt b/apps/higet/CMakeLists.txt
index 8d112d3a3..f4d2d4ec4 100644
--- a/apps/higet/CMakeLists.txt
+++ b/apps/higet/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -11,36 +11,40 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-set(CMAKE_CXX_STANDARD 14)
-
-project(utils)
-
-find_package(Threads REQUIRED)
-
-set(CMAKE_MODULE_PATH
- ${CMAKE_MODULE_PATH}
- "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
-)
-
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif ()
-
+##############################################################
+# Source files
+##############################################################
list(APPEND APPS_SRC
higet.cc
)
+
+##############################################################
+# Linker flags
+##############################################################
if (WIN32)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" )
+ set(CMAKE_EXE_LINKER_FLAGS
+ "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\""
+ )
endif()
+
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build higet
+##############################################################
if (NOT DISABLE_EXECUTABLES)
build_executable(${HIGET}
SOURCES ${APPS_SRC}
LINK_LIBRARIES
+ ${LIBHICN_LIBRARIES}
${LIBTRANSPORT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${WSOCK32_LIBRARY}
@@ -49,5 +53,6 @@ if (NOT DISABLE_EXECUTABLES)
COMPONENT ${HICN_APPS}
DEFINITIONS ${COMPILER_DEFINITIONS}
LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
endif ()
diff --git a/apps/higet/higet.cc b/apps/higet/higet.cc
index 9ae869731..d72d7d74f 100644
--- a/apps/higet/higet.cc
+++ b/apps/higet/higet.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -14,23 +14,20 @@
*/
#include <hicn/transport/http/client_connection.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <algorithm>
+#include <asio.hpp>
#include <fstream>
#include <functional>
#include <map>
+#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
+#endif
#include <asio.hpp>
-#undef ASIO_STANDALONE
-
#include <thread>
-typedef std::chrono::time_point<std::chrono::system_clock> Time;
-typedef std::chrono::milliseconds TimeDuration;
-
-Time t1;
-
#define DEFAULT_BETA 0.99
#define DEFAULT_GAMMA 0.07
@@ -181,7 +178,7 @@ class ReadBytesCallbackImplementation
});
}
- void onError(const std::error_code ec) {
+ void onError(const std::error_code &ec) {
io_service_.post([this]() {
of_.close();
delete out_;
@@ -345,8 +342,6 @@ int main(int argc, char **argv) {
connection.setVerifier(verifier);
}
- t1 = std::chrono::system_clock::now();
-
http::ReadBytesCallbackImplementation readBytesCallback(conf.file_name,
yetDownloaded);
diff --git a/apps/hiperf/CMakeLists.txt b/apps/hiperf/CMakeLists.txt
index 564525e67..6986c90aa 100644
--- a/apps/hiperf/CMakeLists.txt
+++ b/apps/hiperf/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,6 +12,9 @@
# limitations under the License.
if (NOT DISABLE_EXECUTABLES)
+##############################################################
+# Source files
+##############################################################
list(APPEND HIPERF_SRC
${CMAKE_CURRENT_SOURCE_DIR}/src/client.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc
@@ -19,26 +22,40 @@ if (NOT DISABLE_EXECUTABLES)
${CMAKE_CURRENT_SOURCE_DIR}/src/forwarder_interface.cc
)
+
+##############################################################
+# Libraries
+##############################################################
list (APPEND HIPERF_LIBRARIES
- ${LIBTRANSPORT_LIBRARIES}
- ${LIBHICNCTRL_LIBRARIES}
- ${LIBHICN_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${LIBCONFIG_CPP_LIBRARIES}
- ${WSOCK32_LIBRARY}
- ${WS2_32_LIBRARY}
+ PRIVATE ${LIBTRANSPORT_LIBRARIES}
+ PRIVATE ${LIBHICNCTRL_LIBRARIES}
+ PRIVATE ${LIBHICN_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+ PRIVATE ${LIBCONFIG_CPP_LIBRARIES}
+ PRIVATE ${WSOCK32_LIBRARY}
+ PRIVATE ${WS2_32_LIBRARY}
+ )
+
+##############################################################
+# Compiler options
+##############################################################
+ set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
)
+
+##############################################################
+# Build hiperf
+##############################################################
build_executable(hiperf
SOURCES ${HIPERF_SRC}
LINK_LIBRARIES ${HIPERF_LIBRARIES}
INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR}/src
- ${LIBTRANSPORT_INCLUDE_DIRS}
- ${LIBHICNCTRL_INCLUDE_DIRS}
- ${LIBCONFIG_CPP_INCLUDE_DIRS}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
+ PRIVATE ${LIBCONFIG_CPP_INCLUDE_DIRS}
DEPENDS ${DEPENDENCIES}
COMPONENT ${HICN_APPS}
LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
endif() \ No newline at end of file
diff --git a/apps/hiperf/src/client.cc b/apps/hiperf/src/client.cc
index 820ebf0ce..319fa82ab 100644
--- a/apps/hiperf/src/client.cc
+++ b/apps/hiperf/src/client.cc
@@ -31,17 +31,12 @@ class Callback;
* Hiperf client class: configure and setup an hicn consumer following the
* ClientConfiguration.
*/
-class HIperfClient::Impl
-#ifdef FORWARDER_INTERFACE
- : ForwarderInterface::ICallback
-#endif
-{
- typedef std::chrono::time_point<std::chrono::steady_clock> Time;
- typedef std::chrono::microseconds TimeDuration;
-
+class HIperfClient::Impl : ForwarderInterface::ICallback {
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;
@@ -76,21 +71,29 @@ class HIperfClient::Impl
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_),
- done_(false),
- switch_threshold_(~0)
-#ifdef FORWARDER_INTERFACE
- ,
- forwarder_interface_(io_service_, this)
-#endif
- {
+ // 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_);
}
- ~Impl() {}
+ virtual ~Impl() {}
void checkReceivedRtcContent(ConsumerSocket &c,
const ContentObject &contentObject) {}
@@ -104,174 +107,187 @@ class HIperfClient::Impl
void handleTimerExpiration(ConsumerSocket &c,
const TransportStatistics &stats) {
const char separator = ' ';
- const int width = 15;
+ const int width = 18;
- utils::TimePoint t2 = utils::SteadyClock::now();
- auto exact_duration =
- std::chrono::duration_cast<utils::Milliseconds>(t2 - t_stats_);
+ utils::SteadyTime::TimePoint t2 = utils::SteadyTime::Clock::now();
+ auto exact_duration = utils::SteadyTime::getDurationMs(t_stats_, t2);
- std::stringstream interval;
- interval << total_duration_milliseconds_ / 1000 << "-"
- << total_duration_milliseconds_ / 1000 +
- exact_duration.count() / 1000;
+ 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) << "[MB]";
+ << std::setfill(separator);
std::stringstream bandwidth;
bandwidth << ((stats.getBytesRecv() - old_bytes_value_) * 8) /
(exact_duration.count()) / 1000.0
- << std::setfill(separator) << "[Mbps]";
+ << std::setfill(separator);
std::stringstream window;
- window << stats.getAverageWindowSize() << std::setfill(separator)
- << "[Int]";
+ window << stats.getAverageWindowSize() << std::setfill(separator);
std::stringstream avg_rtt;
- avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[ms]";
+ avg_rtt << stats.getAverageRtt() << std::setfill(separator);
if (configuration_.rtc_) {
- // we get rtc stats more often, thus we need ms in the interval
- std::stringstream interval_ms;
- interval_ms << total_duration_milliseconds_ << "-"
- << total_duration_milliseconds_ + exact_duration.count();
-
std::stringstream lost_data;
lost_data << stats.getLostData() - old_lost_data_value_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream bytes_recovered_data;
bytes_recovered_data << stats.getBytesRecoveredData() -
old_bytes_recovered_value_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream definitely_lost_data;
definitely_lost_data << stats.getDefinitelyLostData() -
old_definitely_lost_data_value_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream data_delay;
- data_delay << avg_data_delay_ << std::setfill(separator) << "[ms]";
+ 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)
- << "[pkt]";
+ received_data_pkt << received_data_pkt_ << std::setfill(separator);
std::stringstream goodput;
- goodput << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0
- << std::setfill(separator) << "[Mbps]";
+ 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)
- << "[%]";
+ << stats.getLossRatio() * 100.0 << std::setfill(separator);
std::stringstream retx_sent;
retx_sent << stats.getRetxCount() - old_retx_value_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream interest_sent;
interest_sent << stats.getInterestTx() - old_sent_int_value_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream nacks;
nacks << stats.getReceivedNacks() - old_received_nacks_value_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream fec_pkt;
fec_pkt << stats.getReceivedFEC() - old_fec_pkt_
- << std::setfill(separator) << "[pkt]";
+ << std::setfill(separator);
std::stringstream queuing_delay;
- queuing_delay << stats.getQueuingDelay() << std::setfill(separator)
- << "[ms]";
+ queuing_delay << std::fixed << std::setprecision(3)
+ << stats.getQueuingDelay() << std::setfill(separator);
-#ifdef FORWARDER_INTERFACE
- if (!done_ && stats.getQueuingDelay() >= switch_threshold_ &&
- total_duration_milliseconds_ > 1000) {
- std::cout << "Switching due to queuing delay" << std::endl;
- forwarder_interface_.createFaceAndRoutes(backup_routes_);
- forwarder_interface_.deleteFaceAndRoutes(main_routes_);
- std::swap(backup_routes_, main_routes_);
- done_ = true;
+ std::stringstream residual_losses;
+ double rl_perc = stats.getResidualLossRate() * 100;
+ residual_losses << std::fixed << std::setprecision(2) << rl_perc
+ << std::setfill(separator);
+
+ std::stringstream quality_score;
+ quality_score << std::fixed << (int)stats.getQualityScore()
+ << std::setfill(separator);
+
+ std::stringstream alerts;
+ alerts << stats.getAlerts() << std::setfill(separator);
+
+ std::stringstream auth_alerts;
+ auth_alerts << auth_alerts_ << std::setfill(separator);
+
+ if (fwd_connected_ && use_bestpath_ &&
+ ((stats.getAverageRtt() > rtt_threshold_) ||
+ ((stats.getResidualLossRate() * 100) > loss_threshold_))) {
+ forwarder_interface_.setStrategy(prefix_name_, prefix_len_, "bestpath");
}
-#endif
- // statistics not yet available in the transport
- // std::stringstream interest_fec_tx;
- // interest_fec_tx << stats.getInterestFecTxCount() -
- // old_fec_interest_tx_value_ << std::setfill(separator) << "[pkt]";
- // std::stringstream bytes_fec_recv;
- // bytes_fec_recv << stats.getBytesFecRecv() - old_fec_data_rx_value_
- // << std::setfill(separator) << "[bytes]";
- std::cout << std::left << std::setw(width) << "Interval";
- std::cout << std::left << std::setw(width) << "RecvData";
- std::cout << std::left << std::setw(width) << "Bandwidth";
- std::cout << std::left << std::setw(width) << "Goodput";
- std::cout << std::left << std::setw(width) << "LossRate";
- std::cout << std::left << std::setw(width) << "Retr";
- std::cout << std::left << std::setw(width) << "InterestSent";
- std::cout << std::left << std::setw(width) << "ReceivedNacks";
- std::cout << std::left << std::setw(width) << "SyncWnd";
- std::cout << std::left << std::setw(width) << "MinRtt";
- std::cout << std::left << std::setw(width) << "QueuingDelay";
- std::cout << std::left << std::setw(width) << "LostData";
- std::cout << std::left << std::setw(width) << "RecoveredData";
- std::cout << std::left << std::setw(width) << "DefinitelyLost";
- std::cout << std::left << std::setw(width) << "State";
- std::cout << std::left << std::setw(width) << "DataDelay";
- std::cout << std::left << std::setw(width) << "FecPkt" << std::endl;
-
- std::cout << std::left << std::setw(width) << interval_ms.str();
- std::cout << std::left << std::setw(width) << received_data_pkt.str();
- std::cout << std::left << std::setw(width) << bandwidth.str();
- std::cout << std::left << std::setw(width) << goodput.str();
- std::cout << std::left << std::setw(width) << loss_rate.str();
- std::cout << std::left << std::setw(width) << retx_sent.str();
- std::cout << std::left << std::setw(width) << interest_sent.str();
- std::cout << std::left << std::setw(width) << nacks.str();
- std::cout << std::left << std::setw(width) << window.str();
- std::cout << std::left << std::setw(width) << avg_rtt.str();
- std::cout << std::left << std::setw(width) << queuing_delay.str();
- std::cout << std::left << std::setw(width) << lost_data.str();
- std::cout << std::left << std::setw(width) << bytes_recovered_data.str();
- std::cout << std::left << std::setw(width) << definitely_lost_data.str();
- std::cout << std::left << std::setw(width) << stats.getCCStatus();
- std::cout << std::left << std::setw(width) << data_delay.str();
- std::cout << std::left << std::setw(width) << fec_pkt.str();
+ 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;
+ }
+
+ 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();
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
- std::cout << now << " DATA-DELAYS:[" << data_delays_ << "]"
- << std::endl;
+ auto now = utils::SteadyTime::nowMs();
+ std::cout << std::fixed << std::setprecision(0) << now.count()
+ << " DATA-DELAYS:[" << data_delays_ << "]" << std::endl;
}
// statistics not yet available in the transport
- // std::cout << std::left << std::setw(width) << interest_fec_tx.str();
- // std::cout << std::left << std::setw(width) << bytes_fec_recv.str();
+ // std::cout << std::right << std::setw(width) << interest_fec_tx.str();
+ // std::cout << std::right << std::setw(width) << bytes_fec_recv.str();
} else {
- std::cout << std::left << std::setw(width) << "Interval";
- std::cout << std::left << std::setw(width) << "Transfer";
- std::cout << std::left << std::setw(width) << "Bandwidth";
- std::cout << std::left << std::setw(width) << "Retr";
- std::cout << std::left << std::setw(width) << "Cwnd";
- std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl;
-
- std::cout << std::left << std::setw(width) << interval.str();
- std::cout << std::left << std::setw(width) << bytes_transferred.str();
- std::cout << std::left << std::setw(width) << bandwidth.str();
- std::cout << std::left << std::setw(width) << stats.getRetxCount();
- std::cout << std::left << std::setw(width) << window.str();
- std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl;
- std::cout << std::endl;
+ 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;
+ }
+
+ 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();
@@ -289,9 +305,95 @@ class HIperfClient::Impl
received_data_pkt_ = 0;
data_delays_ = "";
- t_stats_ = utils::SteadyClock::now();
+ 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;
+ }
+
+ if (config.exists("rtt_threshold")) {
+ unsigned val;
+ config.lookupValue("rtt_threshold", val);
+ rtt_threshold_ = val;
+ }
+
+ if (config.exists("loss_threshold")) {
+ unsigned val;
+ config.lookupValue("loss_threshold", val);
+ loss_threshold_ = val;
+ }
+
+ if (config.exists("name")) {
+ std::string route;
+ config.lookupValue("name", route);
+
+ std::string delimiter = "/";
+ size_t pos = 0;
+
+ 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));
+ }
+ }
+
+ forwarder_interface_.initForwarderInterface(this, forwarder_type);
+
+ return true;
+ }
+
+ void onHicnServiceReady() override {
+ std::cout << "Successfully connected to local forwarder!" << std::endl;
+ fwd_connected_ = true;
+ }
+
+ void onRouteConfigured(
+ std::vector<ForwarderInterface::RouteInfoPtr> &route_info) override {
+ std::cout << "Routes successfully configured!" << std::endl;
+ }
+
+#ifdef FORWARDER_INTERFACE
bool parseConfig(const char *conf_file) {
using namespace libconfig;
Config cfg;
@@ -439,7 +541,6 @@ class HIperfClient::Impl
return true;
}
-#ifdef FORWARDER_INTERFACE
void onHicnServiceReady() override {
std::cout << "Successfully connected to local forwarder!" << std::endl;
@@ -541,6 +642,13 @@ class HIperfClient::Impl
}
#endif
+ transport::auth::VerificationPolicy onAuthFailed(
+ transport::auth::Suffix suffix,
+ transport::auth::VerificationPolicy policy) {
+ auth_alerts_++;
+ return transport::auth::VerificationPolicy::ACCEPT;
+ }
+
int setup() {
int ret;
@@ -557,6 +665,7 @@ class HIperfClient::Impl
producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
producer_socket_->registerPrefix(configuration_.relay_name_);
producer_socket_->connect();
+ producer_socket_->start();
}
if (configuration_.output_stream_mode_ && configuration_.rtc_) {
@@ -586,6 +695,17 @@ class HIperfClient::Impl
GeneralTransportOptions::INTEREST_LIFETIME,
configuration_.interest_lifetime_);
+ consumer_socket_->setSocketOption(
+ GeneralTransportOptions::MAX_UNVERIFIED_TIME,
+ configuration_.unverified_delay_);
+
+ 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);
@@ -623,20 +743,24 @@ class HIperfClient::Impl
}
}
+ std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>();
+
if (!configuration_.producer_certificate.empty()) {
- std::shared_ptr<Verifier> verifier = std::make_shared<AsymmetricVerifier>(
+ verifier = std::make_shared<AsymmetricVerifier>(
configuration_.producer_certificate);
- if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier) == SOCKET_OPTION_NOT_SET)
- return ERROR_SETUP;
}
if (!configuration_.passphrase.empty()) {
- std::shared_ptr<Verifier> verifier =
- std::make_shared<SymmetricVerifier>(configuration_.passphrase);
- if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier) == SOCKET_OPTION_NOT_SET)
- return ERROR_SETUP;
+ verifier = std::make_shared<SymmetricVerifier>(configuration_.passphrase);
+ }
+
+ verifier->setVerificationFailedCallback(
+ std::bind(&HIperfClient::Impl::onAuthFailed, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier) == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
}
ret = consumer_socket_->setSocketOption(
@@ -662,6 +786,65 @@ class HIperfClient::Impl
}
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);
+ }
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (configuration_.rtc_) {
+ ret = consumer_socket_->setSocketOption(
+ RtcTransportOptions::AGGREGATED_DATA,
+ configuration_.aggregated_data_);
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (configuration_.rtc_) {
ret = consumer_socket_->setSocketOption(
ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
(ConsumerContentObjectCallback)std::bind(
@@ -673,6 +856,15 @@ class HIperfClient::Impl
}
if (configuration_.rtc_) {
+ ret = consumer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE,
+ configuration_.fec_type_);
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (configuration_.rtc_) {
std::shared_ptr<TransportStatistics> transport_stats;
consumer_socket_->getSocketOption(
OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats);
@@ -708,10 +900,10 @@ class HIperfClient::Impl
signals_.async_wait(
[this](const std::error_code &, const int &) { io_service_.stop(); });
- t_download_ = t_stats_ = std::chrono::steady_clock::now();
- consumer_socket_->asyncConsume(configuration_.name);
- io_service_.run();
+ t_download_ = t_stats_ = utils::SteadyTime::now();
+ consumer_socket_->consume(configuration_.name);
+ io_service_.run();
consumer_socket_->stop();
return ERROR_SUCCESS;
@@ -719,11 +911,15 @@ class HIperfClient::Impl
private:
class RTCCallback : public ConsumerSocket::ReadCallback {
- static constexpr std::size_t mtu = 1500;
+ static constexpr std::size_t mtu = HIPERF_MTU;
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);
}
bool isBufferMovable() noexcept override { return false; }
@@ -743,9 +939,7 @@ class HIperfClient::Impl
uint64_t *senderTimeStamp =
(uint64_t *)client_.configuration_.receive_buffer->writableData();
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
+ auto now = utils::SystemTime::nowMs().count();
double new_delay = (double)(now - *senderTimeStamp);
if (*senderTimeStamp > now)
@@ -765,7 +959,7 @@ class HIperfClient::Impl
client_.producer_socket_->produceDatagram(
client_.configuration_.relay_name_.getName(),
client_.configuration_.receive_buffer->writableData(),
- length < 1400 ? length : 1400);
+ length < payload_size_max_ ? length : payload_size_max_);
}
if (client_.configuration_.output_stream_mode_) {
uint8_t *start =
@@ -778,7 +972,7 @@ class HIperfClient::Impl
size_t maxBufferSize() const override { return mtu; }
- void readError(const std::error_code ec) noexcept override {
+ void readError(const std::error_code &ec) noexcept override {
std::cerr << "Error while reading from RTC socket" << std::endl;
client_.io_service_.stop();
}
@@ -789,6 +983,7 @@ class HIperfClient::Impl
private:
Impl &client_;
+ std::size_t payload_size_max_;
};
class Callback : public ConsumerSocket::ReadCallback {
@@ -816,16 +1011,15 @@ class HIperfClient::Impl
return client_.configuration_.receive_buffer_size_;
}
- void readError(const std::error_code ec) noexcept override {
+ void readError(const std::error_code &ec) noexcept override {
std::cerr << "Error " << ec.message() << " while reading from socket"
<< std::endl;
client_.io_service_.stop();
}
void readSuccess(std::size_t total_size) noexcept override {
- Time t2 = std::chrono::steady_clock::now();
- TimeDuration dt =
- std::chrono::duration_cast<TimeDuration>(t2 - client_.t_download_);
+ 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]"
@@ -843,8 +1037,8 @@ class HIperfClient::Impl
};
hiperf::ClientConfiguration configuration_;
- Time t_stats_;
- Time t_download_;
+ 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_;
@@ -865,6 +1059,7 @@ class HIperfClient::Impl
uint32_t received_bytes_;
uint32_t received_data_pkt_;
+ uint32_t auth_alerts_;
std::string data_delays_;
@@ -878,19 +1073,44 @@ class HIperfClient::Impl
asio::ip::udp::endpoint remote_;
ForwarderConfiguration config_;
- uint16_t switch_threshold_; /* ms */
- bool done_;
+ // 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_;
-#ifdef FORWARDER_INTERFACE
+ uint16_t header_counter_mask_;
+ uint16_t header_counter_;
+
+ bool print_headers_;
+ bool first_;
+
ForwarderInterface forwarder_interface_;
-#endif
};
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() { delete impl_; }
int HIperfClient::setup() { return impl_->setup(); }
diff --git a/apps/hiperf/src/client.h b/apps/hiperf/src/client.h
index f45b9af43..bc80c874c 100644
--- a/apps/hiperf/src/client.h
+++ b/apps/hiperf/src/client.h
@@ -16,12 +16,16 @@
#pragma once
#include <common.h>
+#include <hicn/transport/utils/noncopyable.h>
namespace hiperf {
-class HIperfClient {
+class HIperfClient : ::utils::NonCopyable {
public:
HIperfClient(const ClientConfiguration &conf);
+ HIperfClient(HIperfClient &&other);
+ HIperfClient &operator=(HIperfClient &&other);
+
~HIperfClient();
int setup();
void run();
diff --git a/apps/hiperf/src/common.h b/apps/hiperf/src/common.h
index e6ba526f9..13c9dcc1d 100644
--- a/apps/hiperf/src/common.h
+++ b/apps/hiperf/src/common.h
@@ -15,7 +15,7 @@
#pragma once
-#include <hicn/transport/auth/identity.h>
+#include <forwarder_interface.h>
#include <hicn/transport/auth/signer.h>
#include <hicn/transport/config.h>
#include <hicn/transport/core/content_object.h>
@@ -45,6 +45,9 @@
#endif
#define ERROR_SETUP -5
#define MIN_PROBE_SEQ 0xefffffff
+#define RTC_HEADER_SIZE 12
+#define FEC_HEADER_MAX_SIZE 36
+#define HIPERF_MTU 1500
using namespace transport::interface;
using namespace transport::auth;
@@ -73,11 +76,51 @@ static inline uint64_t _htonll(const uint64_t *input) {
namespace hiperf {
/**
+ * Class to retrieve the maximum payload size given the MTU and packet headers.
+ */
+class PayloadSize {
+ public:
+ PayloadSize(Packet::Format format, std::size_t mtu = HIPERF_MTU)
+ : mtu_(mtu), format_(format) {}
+
+ std::size_t getPayloadSizeMax(std::size_t transport_size = 0,
+ std::size_t fec_size = 0,
+ std::size_t signature_size = 0) {
+ return mtu_ - Packet::getHeaderSizeFromFormat(format_, signature_size) -
+ transport_size - fec_size;
+ }
+
+ static Packet::Format getFormatFromName(Name name, bool ah = false) {
+ switch (name.getAddressFamily()) {
+ case AF_INET:
+ return ah ? HF_INET_TCP_AH : HF_INET_TCP;
+ case AF_INET6:
+ return ah ? HF_INET6_TCP_AH : HF_INET6_TCP;
+ default:
+ return HF_UNSPEC;
+ }
+ }
+
+ private:
+ std::size_t mtu_;
+ Packet::Format format_;
+};
+
+/**
* Class for handling the production rate for the RTC producer.
*/
class Rate {
public:
Rate() : rate_kbps_(0) {}
+ ~Rate() {}
+
+ Rate &operator=(const Rate &other) {
+ if (this != &other) {
+ rate_kbps_ = other.rate_kbps_;
+ }
+
+ return *this;
+ }
Rate(const std::string &rate) {
std::size_t found = rate.find("kbps");
@@ -137,9 +180,16 @@ struct ClientConfiguration {
secure_(false),
producer_prefix_(),
interest_lifetime_(500),
+ unverified_delay_(2000),
relay_name_("c001::abcd/64"),
output_stream_mode_(false),
- port_(0) {}
+ port_(0),
+ recovery_strategy_(4),
+ aggregated_data_(false),
+ fec_type_(""),
+ packet_format_(default_values::packet_format),
+ print_headers_(true),
+ nb_iterations_(std::numeric_limits<decltype(nb_iterations_)>::max()) {}
Name name;
double beta;
@@ -158,9 +208,17 @@ struct ClientConfiguration {
bool secure_;
Prefix producer_prefix_;
uint32_t interest_lifetime_;
+ uint32_t unverified_delay_;
Prefix relay_name_;
bool output_stream_mode_;
uint16_t port_;
+ uint32_t recovery_strategy_;
+ bool aggregated_data_;
+ std::string fec_type_;
+ Packet::Format packet_format_;
+ bool print_headers_;
+ std::uint32_t nb_iterations_;
+ forwarder_type_t forwarder_type_;
};
/**
@@ -170,11 +228,11 @@ struct ServerConfiguration {
ServerConfiguration()
: name("b001::abcd/64"),
virtual_producer(true),
- manifest(false),
+ manifest(0),
live_production(false),
content_lifetime(600000000_U32),
download_size(20 * 1024 * 1024),
- hash_algorithm(CryptoHashType::SHA256),
+ hash_algorithm_(CryptoHashType::SHA256),
keystore_name(""),
passphrase(""),
keystore_password("cisco"),
@@ -185,18 +243,21 @@ struct ServerConfiguration {
trace_index_(0),
trace_file_(nullptr),
production_rate_(std::string("2048kbps")),
- payload_size_(1400),
+ payload_size_(1384),
secure_(false),
input_stream_mode_(false),
- port_(0) {}
+ port_(0),
+ aggregated_data_(false),
+ fec_type_(""),
+ packet_format_(default_values::packet_format) {}
Prefix name;
bool virtual_producer;
- bool manifest;
+ std::uint32_t manifest;
bool live_production;
std::uint32_t content_lifetime;
std::uint32_t download_size;
- CryptoHashType hash_algorithm;
+ CryptoHashType hash_algorithm_;
std::string keystore_name;
std::string passphrase;
std::string keystore_password;
@@ -212,6 +273,9 @@ struct ServerConfiguration {
bool input_stream_mode_;
uint16_t port_;
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
index 655ac3b66..aaac14839 100644
--- a/apps/hiperf/src/forwarder_config.h
+++ b/apps/hiperf/src/forwarder_config.h
@@ -94,4 +94,4 @@ class ForwarderConfiguration {
std::size_t n_threads_;
};
-} \ No newline at end of file
+} // namespace hiperf \ No newline at end of file
diff --git a/apps/hiperf/src/forwarder_interface.cc b/apps/hiperf/src/forwarder_interface.cc
index 864208239..e87a5953d 100644
--- a/apps/hiperf/src/forwarder_interface.cc
+++ b/apps/hiperf/src/forwarder_interface.cc
@@ -25,6 +25,7 @@
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
@@ -36,27 +37,14 @@ extern "C" {
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)
- : external_ioservice_(io_service),
- 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;
- })),
- // set_route_callback_(std::forward<Callback &&>(setRouteCallback)),
- 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),
- timer_(io_service),
- num_reattempts(0) {
- std::cout << "Forwarder interface created... connecting to forwarder...\n";
- internal_ioservice_.post([this]() { onHicnServiceAvailable(true); });
+ ICallback *callback,
+ forwarder_type_t fwd_type)
+ : external_ioservice_(io_service), timer_(io_service) {
+ initForwarderInterface(callback, fwd_type);
}
ForwarderInterface::~ForwarderInterface() {
@@ -72,8 +60,27 @@ ForwarderInterface::~ForwarderInterface() {
thread_->join();
}
+}
- std::cout << "ForwarderInterface::~ForwarderInterface" << std::endl;
+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) {
@@ -93,26 +100,15 @@ void ForwarderInterface::onHicnServiceAvailable(bool flag) {
std::cout << "Connected to forwarder... cancelling reconnection timer"
<< std::endl;
+
timer_.cancel();
num_reattempts = 0;
- // case State::Connected:
- // checkListener();
-
- // if (state_ != State::Ready) {
- // std::cout << "Listener not found" << std::endl;
- // goto REATTEMPT;
- // }
- // state_ = State::Ready;
-
- // 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;
}
@@ -136,14 +132,14 @@ REATTEMPT:
std::chrono::milliseconds(ForwarderInterface::REATTEMPT_DELAY_MS));
// timer_.async_wait(std::bind(&ForwarderInterface::onHicnServiceAvailable,
// this, flag, std::placeholders::_1));
- timer_.async_wait([this, flag](std::error_code ec) {
+ timer_.async_wait([this, flag](const std::error_code &ec) {
if (ec) return;
onHicnServiceAvailable(flag);
});
}
int ForwarderInterface::connectToForwarder() {
- sock_ = hc_sock_create();
+ sock_ = hc_sock_create_forwarder(fwd_type_);
if (!sock_) {
std::cout << "Could not create socket" << std::endl;
goto ERR_SOCK;
@@ -256,6 +252,27 @@ void ForwarderInterface::deleteFaceAndRoutes(
});
}
+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;
@@ -346,10 +363,11 @@ void ForwarderInterface::internalCreateFaceAndRoutes(
}
max_try--;
timer->expires_from_now(std::chrono::milliseconds(500));
- timer->async_wait([this, failed, max_try, timer](std::error_code ec) {
- if (ec) return;
- internalCreateFaceAndRoutes(failed, max_try, timer);
- });
+ timer->async_wait(
+ [this, failed, max_try, timer](const std::error_code &ec) {
+ if (ec) return;
+ internalCreateFaceAndRoutes(failed, max_try, timer);
+ });
return;
}
@@ -422,16 +440,18 @@ int ForwarderInterface::tryToCreateFace(RouteInfo *route_info,
std::string name = "l_" + route_info->name;
listener.local_addr = local_address;
- listener.type = CONNECTION_TYPE_UDP;
+ listener.type = FACE_TYPE_UDP;
listener.family = AF_INET;
listener.local_port = route_info->local_port;
- strncpy(listener.name, name.c_str(), sizeof(listener.name));
- strncpy(listener.interface_name, route_info->interface.c_str(),
- sizeof(listener.interface_name));
+ 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;
- int ret = hc_listener_create(sock_, &listener);
+ ret = hc_listener_create(sock_, &listener);
if (ret < 0) {
std::cerr << "Error creating listener." << std::endl;
@@ -520,7 +540,7 @@ int ForwarderInterface::tryToCreateRoute(RouteInfo *route_info,
#if 0 // not used
void ForwarderInterface::checkRoutesLoop() {
check_routes_timer_->expires_from_now(std::chrono::milliseconds(1000));
- check_routes_timer_->async_wait([this](std::error_code ec) {
+ check_routes_timer_->async_wait([this](const std::error_code &ec) {
if (ec) return;
if (pending_add_route_counter_ == 0) checkRoutes();
});
@@ -580,7 +600,7 @@ void ForwarderInterface::checkRoutes() {
} else {
// XXX This should be moved somewhere else
getMainListener(
- [this](std::error_code ec, uint32_t hicn_listen_port) {
+ [this](const std::error_code &ec, uint32_t hicn_listen_port) {
if (!ec)
{
hicn_listen_port_ = hicn_listen_port;
@@ -597,7 +617,7 @@ void ForwarderInterface::checkRoutes() {
tryToConnectToForwarder();
}
private:
- void doGetMainListener(std::error_code ec)
+ void doGetMainListener(const std::error_code &ec)
{
if (!ec)
{
@@ -607,7 +627,7 @@ void ForwarderInterface::checkRoutes() {
{
// 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 <<
+ std::cout <<
"Could not retrieve main listener port from the forwarder. "
"Retrying.";
@@ -635,7 +655,7 @@ void ForwarderInterface::checkRoutes() {
doTryToConnectToForwarder(std::make_error_code(std::errc(0)));
}
- void doTryToConnectToForwarder(std::error_code ec)
+ void doTryToConnectToForwarder(const std::error_code &ec)
{
if (!ec)
{
@@ -673,4 +693,4 @@ void ForwarderInterface::checkRoutes() {
constexpr uint32_t ForwarderInterface::REATTEMPT_DELAY_MS;
constexpr uint32_t ForwarderInterface::MAX_REATTEMPT;
-} // namespace hiperf \ No newline at end of file
+} // namespace hiperf
diff --git a/apps/hiperf/src/forwarder_interface.h b/apps/hiperf/src/forwarder_interface.h
index 7591ea257..e58989295 100644
--- a/apps/hiperf/src/forwarder_interface.h
+++ b/apps/hiperf/src/forwarder_interface.h
@@ -15,6 +15,8 @@
#pragma once
+#include <hicn/transport/utils/noncopyable.h>
+
extern "C" {
#ifndef WITH_POLICY
#define WITH_POLICY
@@ -27,14 +29,13 @@ extern "C" {
#define ASIO_STANDALONE
#endif
#include <asio.hpp>
-
#include <functional>
#include <thread>
#include <unordered_map>
namespace hiperf {
-class ForwarderInterface {
+class ForwarderInterface : ::utils::NonCopyable {
static const uint32_t REATTEMPT_DELAY_MS = 500;
static const uint32_t MAX_REATTEMPT = 10;
@@ -68,10 +69,14 @@ class ForwarderInterface {
};
public:
- ForwarderInterface(asio::io_service &io_service, ICallback *callback);
+ 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);
@@ -88,11 +93,16 @@ class ForwarderInterface {
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();
@@ -123,6 +133,8 @@ class ForwarderInterface {
State state_;
+ forwarder_type_t fwd_type_;
+
/* Reattempt timer */
asio::steady_timer timer_;
unsigned num_reattempts;
diff --git a/apps/hiperf/src/main.cc b/apps/hiperf/src/main.cc
index b2d99c4a4..b69392de8 100644
--- a/apps/hiperf/src/main.cc
+++ b/apps/hiperf/src/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,13 +14,13 @@
*/
#include <client.h>
-#include <server.h>
#include <forwarder_interface.h>
+#include <server.h>
namespace hiperf {
void usage() {
- std::cerr << "HIPERF - A tool for performing network throughput "
+ std::cerr << "HIPERF - Instrumentation tool for performing active network"
"measurements with hICN"
<< std::endl;
std::cerr << "usage: hiperf [-S|-C] [options] [prefix|name]" << std::endl;
@@ -34,19 +34,27 @@ void usage() {
std::cerr << "-f\t<filename>\t\t\t"
<< "Log file" << std::endl;
std::cerr << "-z\t<io_module>\t\t\t"
- << "IO module to use. Default: hicnlight_module" << std::endl;
+ << "IO module to use. Default: hicnlightng_module" << std::endl;
+ std::cerr << "-F\t<conf_file>\t\t\t"
+ << "Path to optional configuration file for libtransport"
+ << std::endl;
+ std::cerr << "-a\t\t\t\t\t"
+ << "Enables data packet aggregation. "
+ << "Works only in RTC mode" << std::endl;
+ std::cerr << "-X\t<param>\t\t\t\t"
+ << "Set FEC params. Options are Rely_K#_N# or RS_K#_N#"
+ << std::endl;
#endif
std::cerr << std::endl;
std::cerr << "SERVER SPECIFIC:" << std::endl;
std::cerr << "-A\t<content_size>\t\t\t"
- "Size of the content to publish. This "
- "is not the size of the packet (see -s for it)."
- << std::endl;
- std::cerr << "-s\t<packet_size>\t\t\tSize of the payload of each data packet."
+ "Sends an application data unit in bytes that is published once "
+ "before exit"
<< 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\t\t\t\t"
+ std::cerr << "-m\t<manifest_capacity>\t\t"
<< "Produce transport manifest" << std::endl;
std::cerr << "-l\t\t\t\t\t"
<< "Start producing content upon the reception of the "
@@ -60,20 +68,17 @@ void usage() {
<< "String from which a 128-bit symmetric key will be "
"derived for signing packets"
<< std::endl;
+ std::cerr << "-p\t<password>\t\t\t"
+ << "Password for p12 keystore" << std::endl;
std::cerr << "-y\t<hash_algorithm>\t\t"
<< "Use the selected hash algorithm for "
- "calculating manifest digests"
+ "computing manifest digests (default: SHA256)"
<< std::endl;
- std::cerr << "-p\t<password>\t\t\t"
- << "Password for p12 keystore" << std::endl;
std::cerr << "-x\t\t\t\t\t"
- << "Produce a content of <content_size>, then after downloading "
- "it produce a new content of"
- << "\n\t\t\t\t\t<content_size> without resetting "
- "the suffix to 0."
- << std::endl;
+ << "Produces application data units of size <content_size> "
+ << "without resetting the name suffix to 0." << std::endl;
std::cerr << "-B\t<bitrate>\t\t\t"
- << "Bitrate for RTC producer, to be used with the -R option."
+ << "RTC producer data bitrate, to be used with the -R option."
<< std::endl;
#ifndef _WIN32
std::cerr << "-I\t\t\t\t\t"
@@ -92,8 +97,8 @@ void usage() {
"file containing the "
"crypto material used for the TLS handshake"
<< std::endl;
- std::cerr << "-G\t<port>\t\t\t"
- << "input stream from localhost at the specified port" << std::endl;
+ std::cerr << "-G\t<port>\t\t\t\t"
+ << "Input stream from localhost at the specified port" << std::endl;
#endif
std::cerr << std::endl;
std::cerr << "CLIENT SPECIFIC:" << std::endl;
@@ -105,6 +110,8 @@ 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 << "-M\t<input_buffer_size>\t\t"
<< "Size of consumer input buffer. If 0, reassembly of packets "
"will be disabled."
@@ -127,17 +134,31 @@ void usage() {
std::cerr << "-t\t\t\t\t\t"
"Test mode, check if the client is receiving the "
"correct data. This is an RTC specific option, to be "
- "used with the -R (default false)"
+ "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;
std::cerr << "-j\t<relay_name>\t\t\t"
- << "Publish the received content under the name relay_name."
+ << "Publish received content under the name relay_name."
"This is an RTC specific option, to be "
- "used with the -R (default false)"
+ "used with the -R (default: false)"
+ << std::endl;
+ std::cerr << "-g\t<port>\t\t\t\t"
+ << "Output stream to localhost at the specified port" << std::endl;
+ std::cerr << "-e\t<strategy>\t\t\t"
+ << "Enance the network with a realiability 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;
+ 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"
+ << "Print the stats report <nb_iterations> times and exit.\n"
+ << "\t\t\t\t\tThis option limits the duration of the run to "
+ "<nb_iterations> * <stats_interval> milliseconds."
<< std::endl;
- std::cerr << "-g\t<port>\t\t\t"
- << "output stream to localhost at the specified port" << std::endl;
}
int main(int argc, char *argv[]) {
@@ -156,7 +177,7 @@ int main(int argc, char *argv[]) {
char *log_file = nullptr;
transport::interface::global_config::IoModuleConfiguration config;
std::string conf_file;
- config.name = "hicnlight_module";
+ config.name = "hicnlightng_module";
// Consumer
ClientConfiguration client_configuration;
@@ -166,10 +187,9 @@ int main(int argc, char *argv[]) {
int opt;
#ifndef _WIN32
- while ((opt = getopt(
- argc, argv,
- "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:g:G:")) !=
- -1) {
+ while ((opt = getopt(argc, argv,
+ "DSCf:b:d:W:RM:c:vA:s:rm:lK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:"
+ "g:G:e:awHn:X:u:")) != -1) {
switch (opt) {
// Common
case 'D': {
@@ -202,9 +222,11 @@ int main(int argc, char *argv[]) {
break;
}
#else
- while ((opt = getopt(argc, argv,
- "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:z:F:j:")) !=
- -1) {
+ while (
+ (opt = getopt(
+ argc, argv,
+ "SCf:b:d:W:RM:c:vA:s:rm:lK:k:y:p:hi:xB:E:P:tL:z:F:j:e:awHn:X:u:")) !=
+ -1) {
switch (opt) {
#endif
case 'f': {
@@ -216,6 +238,21 @@ int main(int argc, char *argv[]) {
server_configuration.rtc_ = true;
break;
}
+ case 'a': {
+ client_configuration.aggregated_data_ = true;
+ server_configuration.aggregated_data_ = true;
+ break;
+ }
+ case 'X': {
+ client_configuration.fec_type_ = std::string(optarg);
+ server_configuration.fec_type_ = std::string(optarg);
+ break;
+ }
+ case 'w': {
+ client_configuration.packet_format_ = Packet::Format::HF_INET6_UDP;
+ server_configuration.packet_format_ = Packet::Format::HF_INET6_UDP;
+ break;
+ }
case 'z': {
config.name = optarg;
break;
@@ -286,12 +323,27 @@ int main(int argc, char *argv[]) {
options = 1;
break;
}
+ case 'u': {
+ client_configuration.unverified_delay_ = std::stoul(optarg);
+ options = 1;
+ break;
+ }
case 'j': {
client_configuration.relay_ = true;
client_configuration.relay_name_ = Prefix(optarg);
options = 1;
break;
}
+ case 'H': {
+ client_configuration.print_headers_ = false;
+ options = 1;
+ break;
+ }
+ case 'n': {
+ client_configuration.nb_iterations_ = std::stoul(optarg);
+ options = 1;
+ break;
+ }
// Server specific
case 'A': {
server_configuration.download_size = std::stoul(optarg);
@@ -309,7 +361,7 @@ int main(int argc, char *argv[]) {
break;
}
case 'm': {
- server_configuration.manifest = true;
+ server_configuration.manifest = std::stoul(optarg);
options = -1;
break;
}
@@ -324,18 +376,19 @@ int main(int argc, char *argv[]) {
break;
}
case 'y': {
+ CryptoHashType hash_algorithm = CryptoHashType::SHA256;
if (strncasecmp(optarg, "sha256", 6) == 0) {
- server_configuration.hash_algorithm = CryptoHashType::SHA256;
+ hash_algorithm = CryptoHashType::SHA256;
} else if (strncasecmp(optarg, "sha512", 6) == 0) {
- server_configuration.hash_algorithm = CryptoHashType::SHA512;
+ hash_algorithm = CryptoHashType::SHA512;
} else if (strncasecmp(optarg, "blake2b512", 10) == 0) {
- server_configuration.hash_algorithm = CryptoHashType::BLAKE2B512;
+ hash_algorithm = CryptoHashType::BLAKE2B512;
} else if (strncasecmp(optarg, "blake2s256", 10) == 0) {
- server_configuration.hash_algorithm = CryptoHashType::BLAKE2S256;
+ hash_algorithm = CryptoHashType::BLAKE2S256;
} else {
- std::cerr << "Ignored unknown hash algorithm. Using SHA 256."
- << std::endl;
+ std::cerr << "Unknown hash algorithm. Using SHA 256." << std::endl;
}
+ server_configuration.hash_algorithm_ = hash_algorithm;
options = -1;
break;
}
@@ -361,6 +414,11 @@ int main(int argc, char *argv[]) {
server_configuration.secure_ = true;
break;
}
+ case 'e': {
+ client_configuration.recovery_strategy_ = std::stoul(optarg);
+ options = 1;
+ break;
+ }
case 'h':
default:
usage();
@@ -430,6 +488,13 @@ int main(int argc, char *argv[]) {
transport::interface::global_config::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 968d42e2c..7101e7a4a 100644
--- a/apps/hiperf/src/server.cc
+++ b/apps/hiperf/src/server.cc
@@ -21,7 +21,7 @@ namespace hiperf {
* Hiperf server class: configure and setup an hicn producer following the
* ServerConfiguration.
*/
-class HIperfServer::Impl {
+class HIperfServer::Impl : public ProducerSocket::Callback {
const std::size_t log2_content_object_buffer_size = 8;
public:
@@ -35,11 +35,8 @@ class HIperfServer::Impl {
mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1),
last_segment_(0),
#ifndef _WIN32
- ptr_last_segment_(&last_segment_),
input_(io_service_),
rtc_running_(false),
-#else
- ptr_last_segment_(&last_segment_),
#endif
flow_name_(configuration_.name.getName()),
socket_(io_service_),
@@ -54,14 +51,16 @@ class HIperfServer::Impl {
#endif
for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) {
- content_objects_[i] = ContentObject::Ptr(
- new ContentObject(conf.name.getName(), HF_INET6_TCP, 0,
- (const uint8_t *)buffer.data(), buffer.size()));
+ 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);
}
}
+ virtual ~Impl() {}
+
void virtualProcessInterest(ProducerSocket &p, const Interest &interest) {
content_objects_[content_objects_index_ & mask_]->setName(
interest.getName());
@@ -91,16 +90,14 @@ class HIperfServer::Impl {
if (suffix == 0) {
last_segment_ = 0;
- ptr_last_segment_ = &last_segment_;
unsatisfied_interests_.clear();
}
- // The suffix will either be the one from the received interest or the
- // smallest suffix of a previous interest not satisfed
+ // 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(), *ptr_last_segment_);
+ auto it = std::lower_bound(unsatisfied_interests_.begin(),
+ unsatisfied_interests_.end(), last_segment_);
if (it != unsatisfied_interests_.end()) {
suffix = *it;
}
@@ -121,27 +118,28 @@ class HIperfServer::Impl {
b->append(configuration_.download_size);
uint32_t total;
- utils::TimePoint t0 = utils::SteadyClock::now();
+ utils::SteadyTime::TimePoint t0 = utils::SteadyTime::Clock::now();
total = p.produceStream(content_name, std::move(b),
!configuration_.multiphase_produce_, suffix);
- utils::TimePoint t1 = utils::SteadyClock::now();
+ utils::SteadyTime::TimePoint t1 = utils::SteadyTime::Clock::now();
- std::cout
- << "Written " << total
- << " data packets in output buffer (Segmentation time: "
- << std::chrono::duration_cast<utils::Microseconds>(t1 - t0).count()
- << " us)" << std::endl;
+ std::cout << "Written " << total
+ << " data packets in output buffer (Segmentation time: "
+ << utils::SteadyTime::getDurationUs(t0, t1).count() << " us)"
+ << std::endl;
}
void produceContentAsync(ProducerSocket &p, 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);
-
- p.asyncProduce(content_name, std::move(b),
- !configuration_.multiphase_produce_, suffix,
- &ptr_last_segment_);
+ 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);
+ });
}
void cacheMiss(ProducerSocket &p, const Interest &interest) {
@@ -156,27 +154,22 @@ class HIperfServer::Impl {
std::placeholders::_1, std::placeholders::_2));
}
- std::shared_ptr<Identity> getProducerIdentity(std::string &keystore_path,
- std::string &keystore_pwd,
- CryptoHashType &hash_type) {
- if (access(keystore_path.c_str(), F_OK) != -1) {
- return std::make_shared<Identity>(keystore_path, keystore_pwd, hash_type);
- }
- return std::make_shared<Identity>(keystore_path, keystore_pwd,
- CryptoSuite::RSA_SHA256, 1024, 365,
- "producer-test");
+ 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();
}
int setup() {
int ret;
int production_protocol;
+ std::shared_ptr<Signer> signer = std::make_shared<VoidSigner>();
if (configuration_.secure_) {
- auto identity = getProducerIdentity(configuration_.keystore_name,
- configuration_.keystore_password,
- configuration_.hash_algorithm);
producer_socket_ = std::make_unique<P2PSecureProducerSocket>(
- configuration_.rtc_, identity);
+ configuration_.rtc_, configuration_.keystore_name,
+ configuration_.keystore_password);
} else {
if (!configuration_.rtc_) {
production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM;
@@ -188,36 +181,79 @@ class HIperfServer::Impl {
}
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 (!configuration_.passphrase.empty()) {
- std::shared_ptr<Signer> signer = std::make_shared<SymmetricSigner>(
- CryptoSuite::HMAC_SHA256, configuration_.passphrase);
- producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
- signer);
+ signer = std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256,
+ configuration_.passphrase);
}
if (!configuration_.keystore_name.empty()) {
- auto identity = getProducerIdentity(configuration_.keystore_name,
- configuration_.keystore_password,
- configuration_.hash_algorithm);
- std::shared_ptr<Signer> signer = identity->getSigner();
- producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
- signer);
+ signer = std::make_shared<AsymmetricSigner>(
+ configuration_.keystore_name, configuration_.keystore_password);
+ }
+
+ producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, signer);
+
+ // 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_.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_.rtc_) {
+ ret = producer_socket_->setSocketOption(
+ RtcTransportOptions::AGGREGATED_DATA,
+ configuration_.aggregated_data_);
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (configuration_.rtc_) {
+ ret = producer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE,
+ configuration_.fec_type_);
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
}
- uint32_t rtc_header_size = 0;
- if (configuration_.rtc_) rtc_header_size = 12;
- producer_socket_->setSocketOption(
- GeneralTransportOptions::DATA_PACKET_SIZE,
- (uint32_t)(
- configuration_.payload_size_ + rtc_header_size +
- (configuration_.name.getAddressFamily() == AF_INET ? 40 : 60)));
producer_socket_->registerPrefix(configuration_.name);
producer_socket_->connect();
+ producer_socket_->start();
if (configuration_.rtc_) {
std::cout << "Running RTC producer: the prefix length will be ignored."
@@ -239,6 +275,13 @@ class HIperfServer::Impl {
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.getName(), 0);
} else {
@@ -283,7 +326,7 @@ class HIperfServer::Impl {
void receiveStream() {
socket_.async_receive_from(
asio::buffer(recv_buffer_.first, recv_buffer_.second), remote_,
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
if (ec) return;
sendRTCContentFromStream(recv_buffer_.first, length);
receiveStream();
@@ -296,9 +339,8 @@ class HIperfServer::Impl {
// this is used to compute the data packet delay
// Used only for performance evaluation
// It requires clock synchronization between producer and consumer
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SystemTime::nowMs().count();
+
uint8_t *start = (uint8_t *)payload->writableData();
std::memcpy(start, &now, sizeof(uint64_t));
std::memcpy(start + sizeof(uint64_t), buff, len);
@@ -306,7 +348,7 @@ class HIperfServer::Impl {
len + sizeof(uint64_t));
}
- void sendRTCContentObjectCallback(std::error_code ec) {
+ void sendRTCContentObjectCallback(const std::error_code &ec) {
if (ec) return;
rtc_timer_.expires_from_now(
configuration_.production_rate_.getMicrosecondsForPacket(
@@ -319,18 +361,17 @@ class HIperfServer::Impl {
// this is used to compute the data packet delay
// Used only for performance evaluation
// It requires clock synchronization between producer and consumer
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SystemTime::nowMs().count();
std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
- producer_socket_->produceDatagram(
- flow_name_, payload->data(),
- payload->length() < 1400 ? payload->length() : 1400);
+ producer_socket_->produceDatagram(flow_name_, payload->data(),
+ payload->length() < payload_size_max_
+ ? payload->length()
+ : payload_size_max_);
}
- void sendRTCContentObjectCallbackWithTrace(std::error_code ec) {
+ void sendRTCContentObjectCallbackWithTrace(const std::error_code &ec) {
if (ec) return;
auto payload =
@@ -342,14 +383,11 @@ class HIperfServer::Impl {
// this is used to compute the data packet delay
// used only for performance evaluation
// it requires clock synchronization between producer and consumer
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
-
+ uint64_t now = utils::SystemTime::nowMs().count();
std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
if (packet_len > payload->length()) packet_len = payload->length();
- if (packet_len > 1400) packet_len = 1400;
+ if (packet_len > payload_size_max_) packet_len = payload_size_max_;
producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len);
@@ -450,13 +488,13 @@ class HIperfServer::Impl {
std::placeholders::_1));
} else if (configuration_.input_stream_mode_) {
rtc_running_ = true;
- // crate socket
+ // create socket
remote_ = asio::ip::udp::endpoint(
asio::ip::address::from_string("127.0.0.1"), configuration_.port_);
socket_.open(asio::ip::udp::v4());
socket_.bind(remote_);
- recv_buffer_.first = (uint8_t *)malloc(1500);
- recv_buffer_.second = 1500;
+ recv_buffer_.first = (uint8_t *)malloc(HIPERF_MTU);
+ recv_buffer_.second = HIPERF_MTU;
receiveStream();
} else {
rtc_running_ = true;
@@ -490,8 +528,9 @@ class HIperfServer::Impl {
std::uint16_t content_objects_index_;
std::uint16_t mask_;
std::uint32_t last_segment_;
- std::uint32_t *ptr_last_segment_;
std::unique_ptr<ProducerSocket> producer_socket_;
+ ::utils::EventThread produce_thread_;
+ std::size_t payload_size_max_;
#ifndef _WIN32
asio::posix::stream_descriptor input_;
asio::streambuf input_buffer_;
@@ -507,6 +546,20 @@ 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() { delete impl_; }
int HIperfServer::setup() { return impl_->setup(); }
diff --git a/apps/hiperf/src/server.h b/apps/hiperf/src/server.h
index 05407a807..73ac72123 100644
--- a/apps/hiperf/src/server.h
+++ b/apps/hiperf/src/server.h
@@ -22,6 +22,9 @@ namespace hiperf {
class HIperfServer {
public:
HIperfServer(const ServerConfiguration &conf);
+ HIperfServer(HIperfServer &&other);
+ HIperfServer &operator=(HIperfServer &&other);
+
~HIperfServer();
int setup();
void run();
diff --git a/apps/http-proxy/CMakeLists.txt b/apps/http-proxy/CMakeLists.txt
index 66b9c1bab..dbe9bc51c 100644
--- a/apps/http-proxy/CMakeLists.txt
+++ b/apps/http-proxy/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,8 +11,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-set(CMAKE_CXX_STANDARD 14)
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
# -Wno-c99-designator issue
#
@@ -22,20 +26,22 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string )
string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 11)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c99-designator")
+ list(APPEND COMPILER_OPTIONS
+ "-Wno-c99-designator"
+ )
endif()
endif()
-set(CMAKE_MODULE_PATH
- ${CMAKE_MODULE_PATH}
- "${CMAKE_SOURCE_DIR}/cmake/Modules/"
-)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif ()
+##############################################################
+# Includes subdirectory
+##############################################################
+add_subdirectory(includes/hicn/http-proxy)
+
+##############################################################
+# Source files
+##############################################################
set(LIB_SOURCE_FILES
src/http_session.cc
src/http_proxy.cc
@@ -48,41 +54,45 @@ set(APP_SOURCE_FILES
main.cc
)
-add_subdirectory(includes/hicn/http-proxy)
-set(LIBHTTP_PROXY hicnhttpproxy)
-set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static)
-
-list(APPEND COMPILER_DEFINITIONS
- -DWITH_POLICY
-)
-
+##############################################################
+# Libraries to link
+##############################################################
list(APPEND HTTP_PROXY_LIBRARIES
- ${LIBTRANSPORT_LIBRARIES}
- ${LIBHICNCTRL_LIBRARIES}
- ${LIBHICN_LIBRARIES}
- ${OPENSSL_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
+ PUBLIC ${LIBTRANSPORT_LIBRARIES}
+ PUBLIC ${LIBHICNCTRL_LIBRARIES}
+ PUBLIC ${LIBHICN_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
)
+
+##############################################################
+# Build http proxy library
+##############################################################
build_library(${LIBHTTP_PROXY}
STATIC
SOURCES ${LIB_SOURCE_FILES}
LINK_LIBRARIES ${HTTP_PROXY_LIBRARIES}
DEPENDS ${DEPENDENCIES}
INSTALL_HEADERS ${LIBPROXY_TO_INSTALL_HEADER_FILES}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBHICNCTRL_INCLUDE_DIRS} ${LIBPROXY_INCLUDE_DIRS}
+ INCLUDE_DIRS
+ PUBLIC
+ $<BUILD_INTERFACE:${LIBPROXY_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
COMPONENT ${HICN_APPS}
LINK_FLAGS ${LINK_FLAGS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
+
+##############################################################
+# Build http proxy executable
+##############################################################
if (NOT DISABLE_EXECUTABLES)
build_executable(${HTTP_PROXY}
SOURCES ${APP_SOURCE_FILES}
LINK_LIBRARIES ${LIBHTTP_PROXY_STATIC}
DEPENDS ${LIBHTTP_PROXY_STATIC}
COMPONENT ${HICN_APPS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
LINK_FLAGS ${LINK_FLAGS}
)
endif ()
diff --git a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
index 5cc80a168..18f5704d1 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
+++ b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -24,7 +24,7 @@ list(APPEND HEADER_FILES
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
set(LIBPROXY_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR}/../.. ""
+ ${CMAKE_CURRENT_SOURCE_DIR}/../..
CACHE INTERNAL
"" FORCE
)
@@ -34,4 +34,3 @@ set(LIBPROXY_TO_INSTALL_HEADER_FILES
CACHE INTERNAL
"" FORCE
)
-
diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
index e02b9d9a7..935b85e78 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -60,7 +60,7 @@ class ForwarderConfig {
doTryToConnectToForwarder(std::make_error_code(std::errc(0)));
}
- void doTryToConnectToForwarder(std::error_code ec) {
+ void doTryToConnectToForwarder(const std::error_code& ec) {
if (!ec) {
// ec == 0 --> timer expired
int ret = forwarder_interface_.connectToForwarder();
@@ -84,7 +84,7 @@ class ForwarderConfig {
}
}
- void doGetMainListener(std::error_code ec) {
+ void doGetMainListener(const std::error_code& ec) {
if (!ec) {
// ec == 0 --> timer expired
int ret = forwarder_interface_.getMainListenerPort();
@@ -114,7 +114,7 @@ class ForwarderConfig {
TRANSPORT_ALWAYS_INLINE bool parseHicnHeader(std::string& header,
Callback&& callback) {
std::stringstream ss(header);
- route_info_t* ret = new route_info_t();
+ RouteInfoPtr ret = std::make_shared<route_info_t>();
std::string port_string;
while (ss.good()) {
@@ -174,9 +174,9 @@ class ForwarderConfig {
ret->family = AF_INET;
std::string _prefix = ret->route_addr;
forwarder_interface_.createFaceAndRoute(
- RouteInfoPtr(ret), [callback = std::forward<Callback>(callback),
- configured_prefix = std::move(_prefix)](
- uint32_t route_id, bool result) {
+ std::move(ret), [callback = std::forward<Callback>(callback),
+ configured_prefix = std::move(_prefix)](
+ uint32_t route_id, bool result) {
callback(result, configured_prefix);
});
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 54941a4ba..1741aedc6 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h
index 7c035c83b..87a5c7d4e 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h
index a4139a620..efb9f850e 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -22,7 +22,9 @@
#include "http_session.h"
#include "icn_receiver.h"
+#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
+#endif
#include <asio.hpp>
#include <asio/version.hpp>
#include <unordered_set>
@@ -50,9 +52,9 @@ class TcpListener {
void doAccept() {
#if ((ASIO_VERSION / 100 % 1000) >= 12)
acceptor_.async_accept(
- [this](std::error_code ec, asio::ip::tcp::socket socket) {
+ [this](const std::error_code& ec, asio::ip::tcp::socket socket) {
#else
- acceptor_.async_accept(socket_, [this](std::error_code ec) {
+ acceptor_.async_accept(socket_, [this](const std::error_code& ec) {
auto socket = std::move(socket_);
#endif
if (!ec) {
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 f4a3dbdee..ee9380a8c 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/http_session.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,13 +17,12 @@
#include <hicn/transport/core/packet.h>
-#include "http_1x_message_fast_parser.h"
-
-#define ASIO_STANDALONE
#include <asio.hpp>
#include <deque>
#include <functional>
+#include "http_1x_message_fast_parser.h"
+
namespace transport {
using asio::ip::tcp;
@@ -98,7 +97,7 @@ class HTTPSession {
bool checkConnected();
private:
- void handleRead(std::error_code ec, std::size_t length);
+ void handleRead(const std::error_code &ec, std::size_t length);
void tryReconnection();
void startConnectionTimer();
void handleDeadline(const std::error_code &ec);
diff --git a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h
index 780037665..ab90fab07 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <hicn/http-proxy/http_session.h>
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/interfaces/publication_options.h>
#include <hicn/transport/interfaces/socket_producer.h>
@@ -23,8 +24,6 @@
#include <cstring>
#include <queue>
#include <utility>
-
-#include <hicn/http-proxy/http_session.h>
//#include "http_session.h"
namespace transport {
diff --git a/apps/http-proxy/includes/hicn/http-proxy/utils.h b/apps/http-proxy/includes/hicn/http-proxy/utils.h
index d87c796d0..0df24dfd9 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/utils.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -35,14 +35,13 @@ TRANSPORT_ALWAYS_INLINE std::string generatePrefix(
str += pos;
uint32_t locator_hash = utils::hash::fnv32_buf(str, strlen(str));
+ uint16_t* word = (uint16_t*)&locator_hash;
std::stringstream stream;
stream << first_ipv6_word << ":0";
- for (uint16_t* word = (uint16_t*)&locator_hash;
- std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash));
- word++) {
- stream << ":" << std::hex << *word;
+ for (std::size_t i = 0; i < sizeof(locator_hash) / 2; i++) {
+ stream << ":" << std::hex << word[i];
}
stream << "::";
diff --git a/apps/http-proxy/main.cc b/apps/http-proxy/main.cc
index d9c29ecde..9bd97e02e 100644
--- a/apps/http-proxy/main.cc
+++ b/apps/http-proxy/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -139,7 +139,6 @@ int main(int argc, char** argv) {
case 'h':
default:
return usage(argv[0]);
- break;
}
}
diff --git a/apps/http-proxy/src/forwarder_interface.cc b/apps/http-proxy/src/forwarder_interface.cc
index c2448de9a..1c034f60f 100644
--- a/apps/http-proxy/src/forwarder_interface.cc
+++ b/apps/http-proxy/src/forwarder_interface.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -163,7 +163,7 @@ void ForwarderInterface::internalCreateFaceAndRoute(RouteInfoPtr route_info,
max_try--;
timer->expires_from_now(std::chrono::milliseconds(500));
timer->async_wait([this, _route_info = std::move(route_info), max_try,
- timer, callback](std::error_code ec) {
+ timer, callback](const std::error_code &ec) {
if (ec) return;
internalCreateFaceAndRoute(std::move(_route_info), max_try, timer,
std::move(callback));
diff --git a/apps/http-proxy/src/http_1x_message_fast_parser.cc b/apps/http-proxy/src/http_1x_message_fast_parser.cc
index 4b6b78d55..e97c33161 100644
--- a/apps/http-proxy/src/http_1x_message_fast_parser.cc
+++ b/apps/http-proxy/src/http_1x_message_fast_parser.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/apps/http-proxy/src/http_proxy.cc b/apps/http-proxy/src/http_proxy.cc
index 2040f7cfa..5abe8780f 100644
--- a/apps/http-proxy/src/http_proxy.cc
+++ b/apps/http-proxy/src/http_proxy.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -36,7 +36,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
: tcp_receiver_(tcp_receiver),
thread_(thread),
prefix_hash_(tcp_receiver_.prefix_hash_),
- consumer_(TransportProtocolAlgorithms::RAAQM, thread_.getIoService()),
+ consumer_(TransportProtocolAlgorithms::RAAQM, thread_),
session_(nullptr),
current_size_(0) {
consumer_.setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, this);
@@ -69,8 +69,8 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
std::uint16_t remote_port = socket.remote_endpoint().port();
TRANSPORT_LOG_INFO << "Client " << remote_address << ":"
<< remote_port << "disconnected.";
- } catch (std::system_error& e) {
- // Do nothing
+ } catch (asio::system_error& e) {
+ TRANSPORT_LOG_INFO << "Client disconnected.";
}
consumer_.stop();
@@ -191,7 +191,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
session_->send(_buffer, []() {});
}
- void readError(const std::error_code ec) noexcept {
+ void readError(const std::error_code& ec) noexcept {
TRANSPORT_LOG_ERROR
<< "Error reading from hicn consumer socket. Closing session.";
session_->close();
@@ -265,7 +265,7 @@ TcpReceiver::TcpReceiver(std::uint16_t port, const std::string& prefix,
prefix_hash_(generatePrefix(prefix_, ipv6_first_word_)),
forwarder_config_(
thread_.getIoService(),
- [this](std::error_code ec) {
+ [this](const std::error_code& ec) {
if (!ec) {
listener_.doAccept();
for (int i = 0; i < 10; i++) {
diff --git a/apps/http-proxy/src/http_session.cc b/apps/http-proxy/src/http_session.cc
index 84c814cbd..870f188cd 100644
--- a/apps/http-proxy/src/http_session.cc
+++ b/apps/http-proxy/src/http_session.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -92,7 +92,7 @@ void HTTPSession::send(const uint8_t *packet, std::size_t len,
io_service_.dispatch([this, packet, len, content_sent]() {
asio::async_write(socket_, asio::buffer(packet, len),
[content_sent = std::move(content_sent)](
- std::error_code ec, std::size_t /*length*/) {
+ const std::error_code &ec, std::size_t /*length*/) {
if (!ec) {
content_sent();
}
@@ -131,7 +131,7 @@ void HTTPSession::doWrite() {
auto &buffer = write_msgs_.front().first;
asio::async_write(socket_, asio::buffer(buffer->data(), buffer->length()),
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
if (TRANSPORT_EXPECT_FALSE(!ec)) {
write_msgs_.front().second();
write_msgs_.pop_front();
@@ -142,7 +142,7 @@ void HTTPSession::doWrite() {
});
} // namespace transport
-void HTTPSession::handleRead(std::error_code ec, std::size_t length) {
+void HTTPSession::handleRead(const std::error_code &ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
content_length_ -= length;
const uint8_t *buffer =
@@ -207,7 +207,7 @@ void HTTPSession::doReadBody(std::size_t body_size,
void HTTPSession::doReadChunkedHeader() {
asio::async_read_until(
socket_, input_buffer_, "\r\n",
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
const uint8_t *buffer =
asio::buffer_cast<const uint8_t *>(input_buffer_.data());
@@ -226,7 +226,7 @@ void HTTPSession::doReadChunkedHeader() {
void HTTPSession::doReadHeader() {
asio::async_read_until(
socket_, input_buffer_, "\r\n\r\n",
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
const uint8_t *buffer =
asio::buffer_cast<const uint8_t *>(input_buffer_.data());
@@ -287,7 +287,7 @@ void HTTPSession::tryReconnection() {
void HTTPSession::doConnect() {
asio::async_connect(
socket_, endpoint_iterator_,
- [this](std::error_code ec, tcp::resolver::iterator) {
+ [this](const std::error_code &ec, tcp::resolver::iterator) {
if (!ec) {
timer_.cancel();
state_ = ConnectorState::CONNECTED;
diff --git a/apps/http-proxy/src/icn_receiver.cc b/apps/http-proxy/src/icn_receiver.cc
index ea8ac7191..954861e3a 100644
--- a/apps/http-proxy/src/icn_receiver.cc
+++ b/apps/http-proxy/src/icn_receiver.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -112,6 +112,7 @@ void AsyncConsumerProducer::doReceive() {
});
producer_socket_.connect();
+ producer_socket_.start();
}
void AsyncConsumerProducer::manageIncomingInterest(
@@ -128,9 +129,9 @@ void AsyncConsumerProducer::manageIncomingInterest(
if (seg >= _it->second.first) {
// TRANSPORT_LOGD(
- // "Ignoring interest with name %s for a content object which does not "
- // "exist. (Request: %u, max: %u)",
- // name.toString().c_str(), (uint32_t)seg, (uint32_t)_it->second.first);
+ // "Ignoring interest with name %s for a content object which does not
+ // " "exist. (Request: %u, max: %u)", name.toString().c_str(),
+ // (uint32_t)seg, (uint32_t)_it->second.first);
return;
}
}
@@ -168,7 +169,8 @@ void AsyncConsumerProducer::publishContent(const uint8_t* data,
options.getLifetime());
if (TRANSPORT_EXPECT_FALSE(ret != SOCKET_OPTION_SET)) {
- TRANSPORT_LOG_WARNING << "Warning: content object lifetime has not been set.";
+ TRANSPORT_LOG_WARNING
+ << "Warning: content object lifetime has not been set.";
}
const interface::Name& name = options.getName();
diff --git a/apps/ping/.clang-format b/apps/ping/.clang-format
index cd21e2017..adc73c6fd 100644
--- a/apps/ping/.clang-format
+++ b/apps/ping/.clang-format
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2021 Cisco and/or its affiliates.
+# 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:
diff --git a/apps/ping/CMakeLists.txt b/apps/ping/CMakeLists.txt
index 42f7f98c1..a094cebe3 100644
--- a/apps/ping/CMakeLists.txt
+++ b/apps/ping/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,28 +12,45 @@
# limitations under the License.
if (NOT DISABLE_EXECUTABLES)
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+##############################################################
+# Libraries to link
+##############################################################
list (APPEND PING_LIBRARIES
- ${LIBTRANSPORT_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${WSOCK32_LIBRARY}
- ${WS2_32_LIBRARY}
+ PRIVATE ${LIBHICN_LIBRARIES}
+ PRIVATE ${LIBTRANSPORT_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+ PRIVATE ${WSOCK32_LIBRARY}
+ PRIVATE ${WS2_32_LIBRARY}
)
+##############################################################
+# Build ping server
+##############################################################
build_executable(hicn-ping-server
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_server.cc
LINK_LIBRARIES ${PING_LIBRARIES}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
DEPENDS ${DEPENDENCIES}
COMPONENT ${HICN_APPS}
LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
+##############################################################
+# Build ping client
+##############################################################
build_executable(hicn-ping-client
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_client.cc
LINK_LIBRARIES ${PING_LIBRARIES}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
DEPENDS ${DEPENDENCIES}
COMPONENT ${HICN_APPS}
LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
endif () \ No newline at end of file
diff --git a/apps/ping/src/ping_client.cc b/apps/ping/src/ping_client.cc
index 24e0bf3ed..0217f2f8c 100644
--- a/apps/ping/src/ping_client.cc
+++ b/apps/ping/src/ping_client.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,7 +16,9 @@
#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/core/interest.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
#include <hicn/transport/interfaces/portal.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <asio/signal_set.hpp>
#include <asio/steady_timer.hpp>
@@ -32,7 +34,7 @@ namespace core {
namespace ping {
-typedef std::map<uint64_t, uint64_t> SendTimeMap;
+typedef std::map<uint64_t, utils::SteadyTime::TimePoint> SendTimeMap;
typedef auth::AsymmetricVerifier Verifier;
class Configuration {
@@ -77,17 +79,12 @@ class Configuration {
}
};
-class Client : interface::Portal::ConsumerCallback {
+class Client : interface::Portal::TransportCallback {
public:
- Client(Configuration *c)
- : portal_(), signals_(portal_.getIoService(), SIGINT) {
+ Client(Configuration *c) : portal_(), signals_(io_service_, SIGINT) {
// Let the main thread to catch SIGINT
- portal_.connect();
- portal_.setConsumerCallback(this);
-
signals_.async_wait(std::bind(&Client::afterSignal, this));
-
- timer_.reset(new asio::steady_timer(portal_.getIoService()));
+ timer_.reset(new asio::steady_timer(portal_.getThread().getIoService()));
config_ = c;
sequence_number_ = config_->first_suffix_;
last_jump_ = 0;
@@ -105,19 +102,28 @@ class Client : interface::Portal::ConsumerCallback {
void ping() {
std::cout << "start ping" << std::endl;
- doPing();
- portal_.runEventsLoop();
+
+ portal_.getThread().add([this]() {
+ portal_.connect();
+ portal_.registerTransportCallback(this);
+ doPing();
+ });
+
+ io_service_.run();
+ }
+
+ void onInterest(Interest &interest) override {
+ throw errors::RuntimeException("Unexpected interest received.");
}
void onContentObject(Interest &interest, ContentObject &object) override {
- uint64_t rtt = 0;
+ double rtt = 0;
if (!config_->certificate_.empty()) {
- auto t0 = std::chrono::steady_clock::now();
+ auto t0 = utils::SteadyTime::now();
if (verifier_.verifyPacket(&object)) {
- auto t1 = std::chrono::steady_clock::now();
- auto dt =
- std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0);
+ 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 {
@@ -127,10 +133,9 @@ class Client : interface::Portal::ConsumerCallback {
auto it = send_timestamps_.find(interest.getName().getSuffix());
if (it != send_timestamps_.end()) {
- rtt = std::chrono::duration_cast<std::chrono::microseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count() -
- it->second;
+ rtt =
+ utils::SteadyTime::getDurationUs(it->second, utils::SteadyTime::now())
+ .count();
send_timestamps_.erase(it);
}
@@ -206,7 +211,11 @@ class Client : interface::Portal::ConsumerCallback {
}
}
- void onError(std::error_code ec) override {}
+ void onError(const std::error_code &ec) override {
+ std::cout << "Aborting ping due to internal error: " << ec.message()
+ << std::endl;
+ afterSignal();
+ }
void doPing() {
const Name interest_name(config_->name_, (uint32_t)sequence_number_);
@@ -254,10 +263,7 @@ class Client : interface::Portal::ConsumerCallback {
if (!config_->quiet_) std::cout << std::endl;
- send_timestamps_[sequence_number_] =
- std::chrono::duration_cast<std::chrono::microseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ send_timestamps_[sequence_number_] = utils::SteadyTime::now();
portal_.sendInterest(std::move(interest));
@@ -267,7 +273,11 @@ class Client : interface::Portal::ConsumerCallback {
if (sent_ < config_->maxPing_) {
this->timer_->expires_from_now(
std::chrono::microseconds(config_->pingInterval_));
- this->timer_->async_wait([this](const std::error_code e) { doPing(); });
+ this->timer_->async_wait([this](const std::error_code e) {
+ if (!e) {
+ doPing();
+ }
+ });
}
}
@@ -275,11 +285,11 @@ class Client : interface::Portal::ConsumerCallback {
std::cout << "Stop ping" << std::endl;
std::cout << "Sent: " << sent_ << " Received: " << received_
<< " Timeouts: " << timedout_ << std::endl;
- portal_.stopEventsLoop();
+ io_service_.stop();
}
void reset() {
- timer_.reset(new asio::steady_timer(portal_.getIoService()));
+ timer_.reset(new asio::steady_timer(portal_.getThread().getIoService()));
sequence_number_ = config_->first_suffix_;
last_jump_ = 0;
processed_ = 0;
@@ -291,6 +301,7 @@ class Client : interface::Portal::ConsumerCallback {
private:
SendTimeMap send_timestamps_;
+ asio::io_service io_service_;
interface::Portal portal_;
asio::signal_set signals_;
uint64_t sequence_number_;
@@ -337,6 +348,11 @@ void help() {
<< std::endl;
std::cout << "-q quiet, not prints (default false)"
<< std::endl;
+ std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module"
+ << std::endl;
+ std::cerr << "-F <conf_file> Path to optional configuration file for "
+ "libtransport"
+ << std::endl;
std::cout << "-H prints this message" << std::endl;
}
@@ -350,7 +366,11 @@ int main(int argc, char *argv[]) {
int opt;
std::string producer_certificate = "";
- while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:f:c:SAOqVDH")) != -1) {
+ std::string conf_file;
+ 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) {
switch (opt) {
case 't':
c->ttl_ = (uint8_t)std::stoi(optarg);
@@ -406,6 +426,12 @@ int main(int argc, char *argv[]) {
case 'c':
c->certificate_ = std::string(optarg);
break;
+ case 'z':
+ io_config.name = optarg;
+ break;
+ case 'F':
+ conf_file = optarg;
+ break;
case 'H':
default:
help();
@@ -413,16 +439,24 @@ int main(int argc, char *argv[]) {
}
}
+ /**
+ * IO module configuration
+ */
+ io_config.set();
+
+ /**
+ * Parse config file
+ */
+ transport::interface::global_config::parseConfigurationFile(conf_file);
+
auto ping = std::make_unique<Client>(c);
auto t0 = std::chrono::steady_clock::now();
ping->ping();
auto t1 = std::chrono::steady_clock::now();
- std::cout
- << "Elapsed time: "
- << std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count()
- << std::endl;
+ std::cout << "Elapsed time: "
+ << utils::SteadyTime::getDurationUs(t0, t1).count() << std::endl;
#ifdef _WIN32
WSACleanup();
diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc
index baf9c6698..3ffbc7325 100644
--- a/apps/ping/src/ping_server.cc
+++ b/apps/ping/src/ping_server.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,10 +21,10 @@
#include <openssl/applink.c>
#endif
-#include <hicn/transport/auth/identity.h>
#include <hicn/transport/auth/signer.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/utils/string_tokenizer.h>
#include <asio.hpp>
@@ -36,24 +36,13 @@ namespace interface {
using HashAlgorithm = core::HashAlgorithm;
using CryptoSuite = auth::CryptoSuite;
-auth::Identity setProducerIdentity(std::string keystore_name,
- std::string keystore_password,
- auth::CryptoHashType hash_algorithm) {
- if (access(keystore_name.c_str(), F_OK) != -1) {
- return auth::Identity(keystore_name, keystore_password, hash_algorithm);
- } else {
- return auth::Identity(keystore_name, keystore_password,
- CryptoSuite::RSA_SHA256, 1024, 365, "producer-test");
- }
-}
-
class CallbackContainer {
const std::size_t log2_content_object_buffer_size = 12;
public:
CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose,
bool dump, bool quite, bool flags, bool reset, uint8_t ttl,
- auth::Identity *identity, bool sign, uint32_t lifetime)
+ auth::Signer *signer, bool sign, uint32_t lifetime)
: buffer_(object_size, 'X'),
content_objects_((std::uint32_t)(1 << log2_content_object_buffer_size)),
mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1),
@@ -64,7 +53,7 @@ class CallbackContainer {
flags_(flags),
reset_(reset),
ttl_(ttl),
- identity_(identity),
+ signer_(signer),
sign_(sign) {
core::Packet::Format format;
@@ -151,8 +140,8 @@ class CallbackContainer {
if (!quite_) std::cout << std::endl;
- if (sign_) {
- identity_->getSigner()->signPacket(content_object.get());
+ if (sign_ && signer_) {
+ signer_->signPacket(content_object.get());
}
p.produce(*content_object);
@@ -170,33 +159,43 @@ class CallbackContainer {
bool flags_;
bool reset_;
uint8_t ttl_;
- auth::Identity *identity_;
+ auth::Signer *signer_;
bool sign_;
};
void help() {
std::cout << "usage: hicn-preoducer-ping [options]" << std::endl;
std::cout << "PING options" << std::endl;
- std::cout << "-s <val> object content size (default 1350B)" << std::endl;
- std::cout << "-n <val> hicn name (default b001::/64)" << std::endl;
- std::cout << "-f set tcp flags according to the flag received "
- "(default false)"
+ std::cout << "-s <val> object content size (default 1350B)"
<< std::endl;
- std::cout << "-l data lifetime" << std::endl;
- std::cout << "-r always reply with a reset flag (default false)"
+ std::cout << "-n <val> hicn name (default b001::/64)" << std::endl;
+ std::cout << "-f set tcp flags according to the flag received "
+ " (default false)"
<< std::endl;
- std::cout << "-t set ttl (default 64)" << std::endl;
+ std::cout << "-l data lifetime" << std::endl;
+ std::cout
+ << "-r always reply with a reset flag (default false)"
+ << std::endl;
+ std::cout << "-t set ttl (default 64)" << std::endl;
std::cout << "OUTPUT options" << std::endl;
- std::cout << "-V verbose, prints statistics about the messagges sent "
- "and received (default false)"
+ std::cout << "-V verbose, prints statistics about the "
+ "messagges sent "
+ " and received (default false)"
+ << std::endl;
+ std::cout << "-D dump, dumps sent and received packets "
+ "(default false)"
<< std::endl;
- std::cout << "-D dump, dumps sent and received packets (default false)"
+ std::cout << "-q quite, not prints (default false)"
+ << std::endl;
+ std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module"
+ << std::endl;
+ std::cerr << "-F <conf_file> Path to optional configuration file for "
+ "libtransport"
<< std::endl;
- std::cout << "-q quite, not prints (default false)" << std::endl;
#ifndef _WIN32
- std::cout << "-d daemon mode" << std::endl;
+ std::cout << "-d daemon mode" << std::endl;
#endif
- std::cout << "-H prints this message" << std::endl;
+ std::cout << "-H prints this message" << std::endl;
}
int main(int argc, char **argv) {
@@ -220,11 +219,15 @@ int main(int argc, char **argv) {
bool sign = false;
uint32_t data_lifetime = default_values::content_object_expiry_time;
+ std::string conf_file;
+ transport::interface::global_config::IoModuleConfiguration io_config;
+ io_config.name = "hicnlightng_module";
+
int opt;
#ifndef _WIN32
- while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:")) != -1) {
+ while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:z:F:")) != -1) {
#else
- while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:")) != -1) {
+ while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:z:F:")) != -1) {
#endif
switch (opt) {
case 's':
@@ -268,6 +271,12 @@ int main(int argc, char **argv) {
case 'p':
keystore_password = optarg;
break;
+ case 'z':
+ io_config.name = optarg;
+ break;
+ case 'F':
+ conf_file = optarg;
+ break;
case 'H':
default:
help();
@@ -281,6 +290,16 @@ int main(int argc, char **argv) {
}
#endif
+ /**
+ * IO module configuration
+ */
+ io_config.set();
+
+ /**
+ * Parse config file
+ */
+ transport::interface::global_config::parseConfigurationFile(conf_file);
+
core::Prefix producer_namespace(name_prefix);
utils::StringTokenizer tokenizer(name_prefix, delimiter);
@@ -290,21 +309,24 @@ int main(int argc, char **argv) {
if (object_size > 1350) object_size = 1350;
CallbackContainer *stubs;
- auth::Identity identity = setProducerIdentity(
- keystore_path, keystore_password, auth::CryptoHashType::SHA256);
+ std::unique_ptr<auth::AsymmetricSigner> signer;
if (sign) {
- stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
- reset, ttl, &identity, sign, data_lifetime);
+ 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);
} else {
- auth::Identity *identity = nullptr;
+ auth::Signer *signer = nullptr;
stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
- reset, ttl, identity, sign, data_lifetime);
+ reset, ttl, signer, sign, data_lifetime);
}
ProducerSocket p;
p.registerPrefix(producer_namespace);
+ p.setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, false);
p.setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U);
p.setSocketOption(
ProducerCallbacksOptions::CACHE_MISS,
@@ -313,6 +335,7 @@ int main(int argc, char **argv) {
std::placeholders::_2, data_lifetime));
p.connect();
+ p.start();
asio::io_service io_service;
asio::signal_set signal_set(io_service, SIGINT);
diff --git a/cmake b/cmake
new file mode 160000
+Subproject 5fc3324dd897a75aa1fca4290a8ec02a8f19386
diff --git a/cmake/Modules/BuildMacros.cmake b/cmake/Modules/BuildMacros.cmake
deleted file mode 100644
index 15e2ff1a8..000000000
--- a/cmake/Modules/BuildMacros.cmake
+++ /dev/null
@@ -1,300 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-##############################
-# Utils for building libraries and executables
-#
-
-include(GNUInstallDirs)
-
-macro(remove_flag_from_target target flag)
- get_target_property(target_cxx_flags ${target} COMPILE_OPTIONS)
- if(target_cxx_flags)
- list(REMOVE_ITEM target_cxx_flags ${flag})
- set_target_properties(${target} PROPERTIES COMPILE_OPTIONS "${target_cxx_flags}")
- endif()
-endmacro()
-
-macro(build_executable exec)
- cmake_parse_arguments(ARG
- "NO_INSTALL"
- "COMPONENT"
- "SOURCES;LINK_LIBRARIES;DEPENDS;INCLUDE_DIRS;DEFINITIONS;COMPILE_OPTIONS;LINK_FLAGS"
- ${ARGN}
- )
-
- add_executable(${exec}-bin ${ARG_SOURCES})
-
- set(BUILD_ROOT ${CMAKE_BINARY_DIR}/build-root)
-
- set_target_properties(${exec}-bin
- PROPERTIES
- OUTPUT_NAME ${exec}
- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
- BUILD_RPATH "${BUILD_ROOT}/lib"
- INSTALL_RPATH_USE_LINK_PATH TRUE
- ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
- LIBRARY_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
- RUNTIME_OUTPUT_DIRECTORY "${BUILD_ROOT}/bin"
- LINK_FLAGS "${ARG_LINK_FLAGS}"
- )
-
- if(ARG_LINK_LIBRARIES)
- target_link_libraries(${exec}-bin ${ARG_LINK_LIBRARIES})
- endif()
-
- if(ARG_DEPENDS)
- add_dependencies(${exec}-bin ${ARG_DEPENDS})
- endif()
-
- if (ARG_COMPILE_OPTIONS)
- target_compile_options(${exec}-bin PRIVATE -Wall -Werror ${ARG_COMPILE_OPTIONS})
- endif()
-
- if(ARG_DEFINITIONS)
- target_compile_definitions(${exec}-bin PRIVATE ${ARG_DEFINITIONS})
- endif()
-
- if(ARG_INCLUDE_DIRS)
- target_include_directories(${exec}-bin BEFORE PUBLIC
- ${ARG_INCLUDE_DIRS}
- ${PROJECT_BINARY_DIR}
- )
- endif()
-
- if(NOT ARG_NO_INSTALL)
- install(
- TARGETS ${exec}-bin
- RUNTIME
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- COMPONENT ${ARG_COMPONENT}
- )
- endif()
-endmacro()
-
-macro(build_library lib)
- cmake_parse_arguments(ARG
- "SHARED;STATIC;NO_DEV"
- "COMPONENT;"
- "SOURCES;LINK_LIBRARIES;OBJECT_LIBRARIES;LINK_FLAGS;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;HEADER_ROOT_DIR;LIBRARY_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;COMPILE_OPTIONS;VERSION"
- ${ARGN}
- )
-
- message(STATUS "Building library ${lib}")
-
- # Clear target_libs
- unset(TARGET_LIBS)
-
- if (ARG_SHARED)
- list(APPEND TARGET_LIBS
- ${lib}.shared
- )
- add_library(${lib}.shared SHARED ${ARG_SOURCES} ${ARG_OBJECT_LIBRARIES})
- endif()
-
- if(ARG_STATIC)
- list(APPEND TARGET_LIBS
- ${lib}.static
- )
- add_library(${lib}.static STATIC ${ARG_SOURCES} ${ARG_OBJECT_LIBRARIES})
- endif()
-
- if(NOT ARG_COMPONENT)
- set(ARG_COMPONENT hicn)
- endif()
-
- set(BUILD_ROOT ${CMAKE_BINARY_DIR}/build-root)
-
- foreach(library ${TARGET_LIBS})
-
- if(HICN_VERSION)
- set_target_properties(${library}
- PROPERTIES
- SOVERSION ${HICN_VERSION}
- )
- endif()
-
- if (${ARG_EMPTY_PREFIX})
- set_target_properties(${library}
- PROPERTIES
- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
- BUILD_RPATH "${BUILD_ROOT}/lib"
- INSTALL_RPATH_USE_LINK_PATH TRUE
- PREFIX ""
- ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
- LIBRARY_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
- RUNTIME_OUTPUT_DIRECTORY "${BUILD_ROOT}/bin"
- LINK_FLAGS "${ARG_LINK_FLAGS}"
- )
- else ()
- set_target_properties(${library}
- PROPERTIES
- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
- BUILD_RPATH "${BUILD_ROOT}/lib"
- INSTALL_RPATH_USE_LINK_PATH TRUE
- ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
- LIBRARY_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
- RUNTIME_OUTPUT_DIRECTORY "${BUILD_ROOT}/bin"
- LINK_FLAGS "${ARG_LINK_FLAGS}"
- )
- endif()
-
- if (WIN32)
- target_compile_options(${library} PRIVATE ${ARG_COMPILE_OPTIONS})
- set_target_properties(${library}
- PROPERTIES
- WINDOWS_EXPORT_ALL_SYMBOLS TRUE
- )
- else ()
- target_compile_options(${library}
- PRIVATE -Wall -Werror ${ARG_COMPILE_OPTIONS}
- )
- set_target_properties(${library}
- PROPERTIES
- OUTPUT_NAME ${lib}
- )
- endif ()
-
- # library deps
- if(ARG_LINK_LIBRARIES)
- target_link_libraries(${library} PUBLIC ${ARG_LINK_LIBRARIES})
- endif()
-
- if(ARG_DEFINITIONS)
- target_compile_definitions(${library} PRIVATE ${ARG_DEFINITIONS})
- endif()
-
- if(ARG_INCLUDE_DIRS)
- target_include_directories(${library} BEFORE PUBLIC
- ${ARG_INCLUDE_DIRS}
- ${PROJECT_BINARY_DIR}
- )
- endif()
-
- if(ARG_VERSION)
- set_target_properties(${library}
- PROPERTIES
- VERSION ${ARG_VERSION}
- )
- endif()
-
- set(INSTALL_LIB_PATH "${CMAKE_INSTALL_LIBDIR}/${ARG_LIBRARY_ROOT_DIR}")
-
- if (ARG_INSTALL_FULL_PATH_DIR)
- set(INSTALL_LIB_PATH ${ARG_INSTALL_FULL_PATH_DIR})
- endif()
-
- install(
- TARGETS ${library}
- COMPONENT ${ARG_COMPONENT}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${INSTALL_LIB_PATH}
- )
-
- if(ARG_DEPENDS)
- add_dependencies(${library} ${ARG_DEPENDS})
- endif()
- endforeach()
-
- # install headers
- if(ARG_INSTALL_HEADERS)
- if (NOT ARG_HEADER_ROOT_DIR)
- set(ARG_HEADER_ROOT_DIR "hicn")
- endif()
-
- list(APPEND local_comps
- ${ARG_COMPONENT}-dev
- )
-
- foreach(file ${ARG_INSTALL_HEADERS})
- get_filename_component(_dir ${file} DIRECTORY)
-
- if (_dir)
- get_filename_component(dir ${_dir} NAME)
- if ("${dir}" STREQUAL src)
- set(dir "")
- endif()
- if ("${dir}" STREQUAL includes)
- set(dir "")
- endif()
- if ("${dir}" STREQUAL ${ARG_HEADER_ROOT_DIR})
- set(dir "")
- endif()
- else()
- set(dir "")
- endif()
-
- set(COMPONENT ${ARG_COMPONENT})
- if (NOT ARG_NO_DEV)
- set(COMPONENT ${COMPONENT}-dev)
- endif()
- install(
- FILES ${file}
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${ARG_HEADER_ROOT_DIR}/${dir}
- COMPONENT ${COMPONENT}
- )
- endforeach()
- endif()
-endmacro()
-
-macro (build_module module)
- cmake_parse_arguments(ARG
- "SHARED;STATIC;NO_DEV"
- "COMPONENT;"
- "SOURCES;LINK_LIBRARIES;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;HEADER_ROOT_DIR;LIBRARY_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;COMPILE_OPTIONS;VERSION"
- ${ARGN}
- )
-
- message(STATUS "Building module ${module}")
-
- build_library(${module}
- SHARED
- SOURCES ${ARG_SOURCES}
- LINK_LIBRARIES ${ARG_LINK_LIBRARIES}
- INSTALL_HEADERS ${ARG_INSTALL_HEADERS}
- DEPENDS ${ARG_DEPENDS}
- COMPONENT ${ARG_COMPONENT}
- INCLUDE_DIRS ${ARG_INCLUDE_DIRS}
- HEADER_ROOT_DIR ${ARG_HEADER_ROOT_DIR}
- LIBRARY_ROOT_DIR ${ARG_LIBRARY_ROOT_DIR}
- INSTALL_FULL_PATH_DIR ${ARG_INSTALL_FULL_PATH_DIR}
- DEFINITIONS ${ARG_DEFINITIONS}
- EMPTY_PREFIX ${ARG_EMPTY_PREFIX}
- COMPILE_OPTIONS ${ARG_COMPILE_OPTIONS}
- VERSION ${ARG_VERSION}
- )
-
- if (${CMAKE_SYSTEM_NAME} MATCHES Darwin)
- set(LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
- elseif(${CMAKE_SYSTEM_NAME} MATCHES iOS)
- set(LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
- elseif(${CMAKE_SYSTEM_NAME} MATCHES Linux)
- set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-all")
- elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
- set(LINK_FLAGS "/wd4275")
- else()
- message(FATAL_ERROR "Trying to build module on a not supportd platform. Aborting.")
- endif()
-
- set_target_properties(${module}.shared
- PROPERTIES
- LINKER_LANGUAGE C
- PREFIX ""
- LINK_FLAGS ${LINK_FLAGS}
- )
-
-endmacro(build_module)
-
-include(IosMacros)
-include(WindowsMacros)
diff --git a/cmake/Modules/FindAsio.cmake b/cmake/Modules/FindAsio.cmake
deleted file mode 100644
index 73888e519..000000000
--- a/cmake/Modules/FindAsio.cmake
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the hcin libraries and includes
-# This module sets:
-# ASIO_FOUND: True if asio was found
-# ASIO_INCLUDE_DIR: The asio include dir
-#
-
-set(ASIO_SEARCH_PATH_LIST
- ${ASIO_HOME}
- $ENV{ASIO_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(ASIO_INCLUDE_DIR asio.hpp
- HINTS ${ASIO_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the asio includes"
-)
-
-set(ASIO_INCLUDE_DIRS ${ASIO_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Asio
- REQUIRED_VARS ASIO_INCLUDE_DIRS
-) \ No newline at end of file
diff --git a/cmake/Modules/FindCURL.cmake b/cmake/Modules/FindCURL.cmake
deleted file mode 100644
index 239b0e505..000000000
--- a/cmake/Modules/FindCURL.cmake
+++ /dev/null
@@ -1,69 +0,0 @@
-#.rst:
-# FindCURL
-# --------
-#
-# Find curl
-#
-# Find the native CURL headers and libraries.
-#
-# ::
-#
-# CURL_INCLUDE_DIRS - where to find curl_/curl_.h, etc.
-# CURL_LIBRARIES - List of libraries when using curl.
-# CURL_FOUND - True if curl found.
-# CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8)
-
-#=============================================================================
-# Copyright 2006-2009 Kitware, Inc.
-# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de>
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-# Look for the header file.
-find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
-mark_as_advanced(CURL_INCLUDE_DIR)
-
-# Look for the library (sorted from most current/relevant entry to least).
-find_library(CURL_LIBRARY NAMES
- curl
- # Windows MSVC prebuilts:
- curllib
- libcurl_imp
- curllib_static
- # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
- libcurl
- )
-mark_as_advanced(CURL_LIBRARY)
-
-if(CURL_INCLUDE_DIR)
- foreach(_curl_version_header curlver.h curl.h)
- if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}")
- file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"")
-
- string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}")
- unset(curl_version_str)
- break()
- endif()
- endforeach()
-endif()
-
-# handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE if
-# all listed variables are TRUE
-include(FindPackageHandleStandardArgs)
-
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL
- REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
- VERSION_VAR CURL_VERSION_STRING)
-
-if(CURL_FOUND)
- set(CURL_LIBRARIES ${CURL_LIBRARY})
- set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
-endif()
diff --git a/cmake/Modules/FindCollectd.cmake b/cmake/Modules/FindCollectd.cmake
deleted file mode 100644
index 244fd14e5..000000000
--- a/cmake/Modules/FindCollectd.cmake
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(COLLECTD_SEARCH_PATH_LIST
- ${COLLECTD_HOME}
- $ENV{COLLECTD_HOME}
- /usr/local
- /opt
- /usr
- )
-
-find_path(COLLECTD_INCLUDE_DIR collectd.h
- HINTS ${COLLECTD_SEARCH_PATH_LIST}
- PATH_SUFFIXES include/collectd/core/daemon/ daemon/
- DOC "Find the collectd includes"
-)
-
-find_path(COLLECTD_CONFIG_INCLUDE_DIR config.h
- HINTS ${COLLECTD_SEARCH_PATH_LIST}
- PATH_SUFFIXES include/collectd/core/
- DOC "Find the collectd includes"
-)
-
-message(STATUS ${COLLECTD_INCLUDE_DIR} ${COLLECTD_CONFIG_INCLUDE_DIR})
-
-set(COLLECTD_INCLUDE_DIRS ${COLLECTD_INCLUDE_DIR} ${COLLECTD_CONFIG_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Collectd DEFAULT_MSG COLLECTD_INCLUDE_DIRS)
-
-mark_as_advanced(COLLECTD_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindGFlags.cmake b/cmake/Modules/FindGFlags.cmake
deleted file mode 100644
index 804bfebdc..000000000
--- a/cmake/Modules/FindGFlags.cmake
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#
-# Find libgflags
-#
-# LIBGFLAGS_INCLUDE_DIR - where to find gflags/gflags.h, etc.
-# LIBGFLAGS_LIBRARY - List of libraries when using libgflags.
-# LIBGFLAGS_FOUND - True if libgflags found.
-
-
-IF (LIBGFLAGS_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LIBGFLAGS_FIND_QUIETLY TRUE)
-ENDIF ()
-
-FIND_PATH(LIBGFLAGS_INCLUDE_DIR gflags/gflags.h)
-
-FIND_LIBRARY(LIBGFLAGS_LIBRARY NAMES gflags gflags_static)
-
-# handle the QUIETLY and REQUIRED arguments and set LIBGFLAGS_FOUND to TRUE if
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGFLAGS DEFAULT_MSG LIBGFLAGS_LIBRARY LIBGFLAGS_INCLUDE_DIR)
-
-MARK_AS_ADVANCED(LIBGFLAGS_LIBRARY LIBGFLAGS_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindGlog.cmake b/cmake/Modules/FindGlog.cmake
deleted file mode 100644
index 10023a187..000000000
--- a/cmake/Modules/FindGlog.cmake
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#
-# Find libglog
-#
-# LIBGLOG_INCLUDE_DIR - where to find glog/logging.h, etc.
-# LIBGLOG_LIBRARY - List of libraries when using libglog.
-# LIBGLOG_FOUND - True if libglog found.
-
-
-IF (LIBGLOG_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LIBGLOG_FIND_QUIETLY TRUE)
-ENDIF ()
-
-FIND_PATH(LIBGLOG_INCLUDE_DIR glog/logging.h)
-
-FIND_LIBRARY(LIBGLOG_LIBRARY glog)
-
-# handle the QUIETLY and REQUIRED arguments and set LIBGLOG_FOUND to TRUE if
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGLOG DEFAULT_MSG LIBGLOG_LIBRARY LIBGLOG_INCLUDE_DIR)
-
-MARK_AS_ADVANCED(LIBGLOG_LIBRARY LIBGLOG_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindHicnLight.cmake b/cmake/Modules/FindHicnLight.cmake
deleted file mode 100644
index 6894415e7..000000000
--- a/cmake/Modules/FindHicnLight.cmake
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(HICNLIGHT_SEARCH_PATH_LIST
- ${HICNLIGHT_HOME}
- $ENV{HICNLIGHT_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(HICNLIGHT_INCLUDE_DIR hicn/ctrl/api.h
- HINTS ${HICNLIGHT_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the hicn plugin includes"
-)
-
-find_library(HICNLIGHT_LIBRARY NAMES libhicnctrl.so
- HINTS ${HICNLIGHT_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x86_64-linux-gnu/
- DOC "Find the hicn light lib"
-)
-
-set(HICNLIGHT_LIBRARIES ${HICNLIGHT_LIBRARY})
-set(HICNLIGHT_INCLUDE_DIRS ${HICNLIGHT_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Hicnlight HICNLIGHT_LIBRARIES HICNLIGHT_INCLUDE_DIRS)
-
-mark_as_advanced(HICNLIGHT_LIBRARY HICNLIGHT_INCLUDE_DIR)
diff --git a/cmake/Modules/FindHicnPlugin.cmake b/cmake/Modules/FindHicnPlugin.cmake
deleted file mode 100644
index 07e5f9a8c..000000000
--- a/cmake/Modules/FindHicnPlugin.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(HICNPLUGIN_SEARCH_PATH_LIST
- ${VPP_SEARCH_PATH_LIST}
- ${HICNPLUGIN_HOME}
- $ENV{HICNPLUGIN_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(HICNPLUGIN_INCLUDE_DIR vapi/hicn.api.vapi.h
- HINTS ${HICNPLUGIN_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the hicn plugin includes"
-)
-
-
-set(HICNPLUGIN_INCLUDE_DIRS ${HICNPLUGIN_INCLUDE_DIR} ${HICNPLUGIN_INCLUDE_DIR}/vpp_plugins)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(HicnPlugin DEFAULT_MSG HICNPLUGIN_INCLUDE_DIR)
-
-mark_as_advanced(HICNPLUGIN_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindJsoncpp.cmake b/cmake/Modules/FindJsoncpp.cmake
deleted file mode 100644
index acde7b95b..000000000
--- a/cmake/Modules/FindJsoncpp.cmake
+++ /dev/null
@@ -1,47 +0,0 @@
-# Find jsoncpp
-#
-# Find the jsoncpp includes and library
-#
-# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH
-#
-# This module defines
-# JSONCPP_INCLUDE_DIRS, where to find header, etc.
-# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp.
-# JSONCPP_FOUND, If false, do not try to use jsoncpp.
-# JSONCPP_INCLUDE_PREFIX, include prefix for jsoncpp
-
-# only look in default directories
-find_path(
- JSONCPP_INCLUDE_DIR
- NAMES jsoncpp/json/json.h json/json.h
- DOC "jsoncpp include dir"
-)
-
-find_library(
- JSONCPP_LIBRARY
- NAMES jsoncpp
- DOC "jsoncpp library"
-)
-
-set(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR})
-set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})
-
-# find JSONCPP_INCLUDE_PREFIX
-find_path(
- JSONCPP_INCLUDE_PREFIX
- NAMES json.h
- PATH_SUFFIXES jsoncpp/json json
-)
-
-if (${JSONCPP_INCLUDE_PREFIX} MATCHES "jsoncpp")
- set(JSONCPP_INCLUDE_PREFIX "jsoncpp/json")
-else()
- set(JSONCPP_INCLUDE_PREFIX "json")
-endif()
-
-# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE
-# if all listed variables are TRUE, hide their existence from configuration view
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(jsoncpp DEFAULT_MSG
- JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY)
-mark_as_advanced (JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) \ No newline at end of file
diff --git a/cmake/Modules/FindLibEvent.cmake b/cmake/Modules/FindLibEvent.cmake
deleted file mode 100644
index 5e4113716..000000000
--- a/cmake/Modules/FindLibEvent.cmake
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the LibEvent libraries and includes
-# This module sets:
-# LIBEVENT_FOUND: True if LibEvent was found
-# LIBEVENT_LIBRARY: The LibEvent library
-# LIBEVENT_LIBRARIES: The LibEvent library and dependencies
-# LIBEVENT_INCLUDE_DIR: The LibEvent include dir
-#
-# This module will look for the libraries in various locations
-# See the LIBEVENT_SEARCH_PATH_LIST for a full list.
-#
-# The caller can hint at locations using the following variables:
-#
-# LIBEVENT_HOME (passed as -D to cmake)
-# LIBEVENT_HOME (in environment)
-#
-
-set(LIBEVENT_SEARCH_PATH_LIST
- ${LIBEVENT_HOME}
- $ENV{DEPENDENCIES}
- $ENV{LIBEVENT_HOME}
- /usr/local
- /opt
- /usr
- )
-
-find_path(LIBEVENT_INCLUDE_DIR event2/event.h
- HINTS ${LIBEVENT_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the LibEvent includes" )
-
-find_library(LIBEVENT_LIBRARY NAMES event
- HINTS ${LIBEVENT_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the LibEvent libraries" )
-
-set(LIBEVENT_LIBRARIES ${LIBEVENT_LIBRARY})
-set(LIBEVENT_INCLUDE_DIRS ${LIBEVENT_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LibEvent DEFAULT_MSG LIBEVENT_LIBRARY LIBEVENT_INCLUDE_DIR)
diff --git a/cmake/Modules/FindLibconfig++.cmake b/cmake/Modules/FindLibconfig++.cmake
deleted file mode 100644
index 1636ae96a..000000000
--- a/cmake/Modules/FindLibconfig++.cmake
+++ /dev/null
@@ -1,43 +0,0 @@
-set(LIBCONFIG_SEARCH_PATH_LIST
- ${LIBCONFIG_HOME}
- $ENV{LIBCONFIG_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(LIBCONFIG_INCLUDE_DIR libconfig.h++
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the libconfig include"
-)
-
-if (WIN32)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- find_library(LIBCONFIG_CPP_LIBRARIES NAMES libconfig++.lib
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x64
- DOC "Find the libconfig libraries"
- )
- elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
- find_library(LIBCONFIG_CPP_LIBRARIES NAMES libconfig++.lib
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x32
- DOC "Find the libconfig libraries"
- )
- endif()
-else()
- find_library(LIBCONFIG_CPP_LIBRARY NAMES config++
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the libconfig++ libraries"
- )
-endif()
-
-set(LIBCONFIG_CPP_LIBRARIES ${LIBCONFIG_CPP_LIBRARY})
-set(LIBCONFIG_INCLUDE_DIRS ${LIBCONFIG_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Libconfig++ LIBCONFIG_CPP_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
-
-mark_as_advanced(LIBCONFIG_CPP_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibconfig.cmake b/cmake/Modules/FindLibconfig.cmake
deleted file mode 100644
index 55d2a0fad..000000000
--- a/cmake/Modules/FindLibconfig.cmake
+++ /dev/null
@@ -1,43 +0,0 @@
-set(LIBCONFIG_SEARCH_PATH_LIST
- ${LIBCONFIG_HOME}
- $ENV{LIBCONFIG_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(LIBCONFIG_INCLUDE_DIR libconfig.h
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the libconfig include"
-)
-
-if (WIN32)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- find_library(LIBCONFIG_LIBRARY NAMES libconfig.lib
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x64
- DOC "Find the libconfig libraries"
- )
- elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
- find_library(LIBCONFIG_LIBRARY NAMES libconfig.lib
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x32
- DOC "Find the libconfig libraries"
- )
- endif()
-else()
- find_library(LIBCONFIG_LIBRARY NAMES config
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the libconfig libraries"
- )
-endif()
-
-set(LIBCONFIG_LIBRARIES ${LIBCONFIG_LIBRARY})
-set(LIBCONFIG_INCLUDE_DIRS ${LIBCONFIG_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Libconfig LIBCONFIG_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
-
-mark_as_advanced(LIBCONFIG_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibhicn.cmake b/cmake/Modules/FindLibhicn.cmake
deleted file mode 100644
index 5f241a6cd..000000000
--- a/cmake/Modules/FindLibhicn.cmake
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the hcin libraries and includes
-# This module sets:
-# HICN_FOUND: True if hicn was found
-# HICN_LIBRARY: The hicn library
-# HICN_LIBRARIES: The hicn library and dependencies
-# HCIN_INCLUDE_DIR: The hicn include dir
-#
-
-set(HICN_SEARCH_PATH_LIST
- ${HICN_HOME}
- $ENV{HICN_HOME}
- $ENV{FOUNDATION_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(HICN_INCLUDE_DIR hicn/hicn.h
- HINTS ${HICN_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the hicn includes"
-)
-
-find_library(HICN_LIBRARY NAMES hicn
- HINTS ${HICN_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the hicn libraries"
-)
-
-set(HICN_LIBRARIES ${HICN_LIBRARY})
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
- set(HICN_LIBRARIES ${HICN_LIBRARIES} log)
-endif()
-set(HICN_INCLUDE_DIRS ${HICN_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(hicn DEFAULT_MSG HICN_LIBRARY HICN_INCLUDE_DIR)
diff --git a/cmake/Modules/FindLibhicnctrl.cmake b/cmake/Modules/FindLibhicnctrl.cmake
deleted file mode 100755
index 7c20420b4..000000000
--- a/cmake/Modules/FindLibhicnctrl.cmake
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the hICN control library and include files
-#
-
-set(HICN_SEARCH_PATH_LIST
- ${HICN_HOME}
- $ENV{HICN_HOME}
- $ENV{FOUNDATION_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(LIBHICNCTRL_INCLUDE_DIR hicn/ctrl.h
- HINTS ${HICN_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the hICN control include"
-)
-
-find_library(LIBHICNCTRL_LIBRARY NAMES hicnctrl
- HINTS ${HICN_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the hicn control library"
-)
-
-set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_LIBRARY})
-set(LIBHICNCTRL_INCLUDE_DIRS ${LIBHICNCTRL_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(hicnctrl DEFAULT_MSG
- LIBHICNCTRL_LIBRARY LIBHICNCTRL_INCLUDE_DIR)
diff --git a/cmake/Modules/FindLibmemif.cmake b/cmake/Modules/FindLibmemif.cmake
deleted file mode 100644
index 48460eecd..000000000
--- a/cmake/Modules/FindLibmemif.cmake
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the hcin libraries and includes
-# This module sets:
-# LIBMEMIF_FOUND: True if core was found
-# LIBMEMIF_LIBRARY: The core library
-# LIBMEMIF_INCLUDE_DIR: The core include dir
-#
-
-set(LIBMEMIF_SEARCH_PATH_LIST
- ${LIBMEMIF_HOME}
- $ENV{LIBMEMIF_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(LIBMEMIF_INCLUDE_DIR memif/libmemif.h
- HINTS ${LIBMEMIF_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the libmemif includes"
-)
-
-find_library(LIBMEMIF_LIBRARY NAMES memif
- HINTS ${LIBMEMIF_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the libmemif libraries"
-)
-
-set(LIBMEMIF_LIBRARIES ${LIBMEMIF_LIBRARY})
-set(LIBMEMIF_INCLUDE_DIRS ${LIBMEMIF_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Libmemif DEFAULT_MSG LIBMEMIF_LIBRARY LIBMEMIF_INCLUDE_DIR)
diff --git a/cmake/Modules/FindLibparc.cmake b/cmake/Modules/FindLibparc.cmake
deleted file mode 100644
index c5c99af15..000000000
--- a/cmake/Modules/FindLibparc.cmake
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the Libparc libraries and includes
-# This module sets:
-# LIBPARC_FOUND: True if Libparc was found
-# LIBPARC_LIBRARY: The Libparc library
-# LIBPARC_LIBRARIES: The Libparc library and dependencies
-# LIBPARC_INCLUDE_DIR: The Libparc include dir
-#
-
-set(LIBPARC_SEARCH_PATH_LIST
- ${LIBPARC_HOME}
- $ENV{LIBPARC_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(LIBPARC_INCLUDE_DIR parc/libparc_About.h
- HINTS ${LIBPARC_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the Libparc includes"
-)
-
-find_library(LIBPARC_LIBRARY NAMES parc
- HINTS ${LIBPARC_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the Libparc libraries"
-)
-
-set(LIBPARC_LIBRARIES ${LIBPARC_LIBRARY})
-set(LIBPARC_INCLUDE_DIRS ${LIBPARC_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Libparc DEFAULT_MSG LIBPARC_LIBRARY LIBPARC_INCLUDE_DIR)
-
-mark_as_advanced(LIBPARC_LIBRARY LIBPARC_INCLUDE_DIR)
diff --git a/cmake/Modules/FindLibtransport.cmake b/cmake/Modules/FindLibtransport.cmake
deleted file mode 100644
index 8a650b98c..000000000
--- a/cmake/Modules/FindLibtransport.cmake
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the LibTRANSPORT libraries and includes
-# This module sets:
-# LIBTRANSPORT_FOUND: True if Libconsumer-producer was found
-# LIBTRANSPORTR_LIBRARY: The Libconsumer-producer library
-# LIBTRANSPORT_LIBRARIES: The Libconsumer-producer library and dependencies
-# LIBTRANSPORT_INCLUDE_DIR: The Libconsumer-producer include dir
-#
-
-set(LIBTRANSPORT_SEARCH_PATH_LIST
- ${LIBTRANSPORT_HOME}
- $ENV{LIBTRANSPORTHOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(LIBTRANSPORT_INCLUDE_DIR hicn/transport/config.h
- HINTS ${LIBTRANSPORT_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the libtransport includes"
-)
-
-find_library(LIBTRANSPORT_LIBRARY
- NAMES hicntransport hicntransport-memif
- HINTS ${LIBTRANSPORT_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the libtransport libraries"
-)
-
-set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_LIBRARY})
-set(LIBTRANSPORT_INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Libtransport DEFAULT_MSG LIBTRANSPORT_LIBRARIES LIBTRANSPORT_INCLUDE_DIRS) \ No newline at end of file
diff --git a/cmake/Modules/FindLongBow.cmake b/cmake/Modules/FindLongBow.cmake
deleted file mode 100644
index 4a05d7fdf..000000000
--- a/cmake/Modules/FindLongBow.cmake
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the LongBow libraries and includes
-# This module sets:
-# LONGBOW_FOUND: True if LongBow was found
-# LONGBOW_LIBRARY: The LongBow library
-# LONGBOW_LIBRARIES: The LongBow library and dependencies
-# LONGBOW_INCLUDE_DIR: The LongBow include dir
-#
-
-set(LONGBOW_SEARCH_PATH_LIST
- ${LONGBOW_HOME}
- $ENV{LONGBOW_HOME}
- $ENV{PARC_HOME}
- $ENV{FOUNDATION_HOME}
- /usr/local/parc
- /usr/local/ccn
- /usr/local
- /opt
- /usr
- )
-
-find_path(LONGBOW_INCLUDE_DIR LongBow/longBow_About.h
- HINTS ${LONGBOW_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the LongBow includes" )
-
-find_library(LONGBOW_LIBRARY NAMES longbow
- HINTS ${LONGBOW_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the LongBow libraries" )
-
-find_library(LONGBOW_REPORT_LIBRARY NAMES longbow-textplain longbow-ansiterm
- HINTS ${LONGBOW_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the LongBow report libraries" )
-
-set(LONGBOW_LIBRARIES ${LONGBOW_LIBRARY} ${LONGBOW_REPORT_LIBRARY})
-set(LONGBOW_INCLUDE_DIRS ${LONGBOW_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LongBow DEFAULT_MSG LONGBOW_LIBRARY LONGBOW_INCLUDE_DIR)
diff --git a/cmake/Modules/FindPThread.cmake b/cmake/Modules/FindPThread.cmake
deleted file mode 100644
index 6f0eeb7c0..000000000
--- a/cmake/Modules/FindPThread.cmake
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the PThread libraries and includes
-# This module sets:
-# PTHREAD_FOUND: True if pthread was found
-# PTHREADR_LIBRARY: The pthread library
-# PTHREAD_LIBRARIES: The pthread library and dependencies
-# PTHREAD_INCLUDE_DIR: The pthread include dir
-#
-
-
-set(PTHREAD_SEARCH_PATH_LIST
- ${PTHREAD_HOME}
- $ENV{PTHREAD_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(PTHREAD_INCLUDE_DIR pthread.h
- HINTS ${PTHREAD_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the pthreadincludes"
-)
-
-if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- find_library(PTHREAD_LIBRARY NAMES pthreadVC2.lib
- HINTS ${PTHREAD_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x64
- DOC "Find the pthread libraries"
- )
-elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
- find_library(PTHREAD_LIBRARY NAMES pthreadVC2.lib
- HINTS ${PTHREAD_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x32
- DOC "Find the pthread libraries"
- )
-endif()
-
-
-set(PTHREAD_LIBRARIES ${PTHREAD_LIBRARY})
-set(PTHREAD_INCLUDE_DIRS ${PTHREAD_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Pthread DEFAULT_MSG PTHREAD_LIBRARIES PTHREAD_INCLUDE_DIRS) \ No newline at end of file
diff --git a/cmake/Modules/FindSafeVapi.cmake b/cmake/Modules/FindSafeVapi.cmake
deleted file mode 100644
index a9077ae14..000000000
--- a/cmake/Modules/FindSafeVapi.cmake
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(SAFE_VAPI_SEARCH_PATH_LIST
- ${SAFE_VAPI_HOME}
- $ENV{SAFE_VAPI_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(SAFE_VAPI_INCLUDE_DIR vapi/vapi_safe.h
- HINTS ${SAFE_VAPI_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the vapi_safe includes"
-)
-
-find_library(SAFE_VAPI_LIBRARY NAMES libsafe_vapi.so
- HINTS ${SAFE_VAPI_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x86_64-linux-gnu/
- DOC "Find the vapi safe lib"
-)
-
-set(SAFE_VAPI_LIBRARIES ${SAFE_VAPI_LIBRARY})
-set(SAFE_VAPI_INCLUDE_DIRS ${SAFE_VAPI_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Hicnlight SAFE_VAPI_LIBRARIES SAFE_VAPI_INCLUDE_DIRS)
-
-mark_as_advanced(SAFE_VAPI_LIBRARY SAFE_VAPI_INCLUDE_DIR)
diff --git a/cmake/Modules/FindSysrepo.cmake b/cmake/Modules/FindSysrepo.cmake
deleted file mode 100644
index 1c389e480..000000000
--- a/cmake/Modules/FindSysrepo.cmake
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(SYSREPO_SEARCH_PATH_LIST
- ${SYSREPO_HOME}
- $ENV{SYSREPO_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(SYSREPO_INCLUDE_DIR sysrepo/values.h
- HINTS ${SYSREPO_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the sysrepo includes"
-)
-
-find_path(SYSREPO_INCLUDE_MAIN_DIR sysrepo.h
- HINTS ${SYSREPO_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the sysrepo includes"
-)
-
-find_library(SYSREPO_LIBRARY NAMES libsysrepo.so
- HINTS ${SYSREPO_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the sysrepo library"
-)
-
-set(SYSREPO_LIBRARIES ${SYSREPO_LIBRARY})
-set(SYSREPO_INCLUDE_DIRS ${SYSREPO_INCLUDE_DIR} ${SYSREPO_INCLUDE_MAIN_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Sysrepo DEFAULT_MSG SYSREPO_LIBRARIES SYSREPO_INCLUDE_DIRS)
-
-mark_as_advanced(SYSREPO_LIBRARY SYSREPO_INCLUDE_DIR SYSREPO_INCLUDE_MAIN_DIR)
diff --git a/cmake/Modules/FindVapiSafe.cmake b/cmake/Modules/FindVapiSafe.cmake
deleted file mode 100644
index c2c9fd762..000000000
--- a/cmake/Modules/FindVapiSafe.cmake
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(SAFE_VAPI_SEARCH_PATH_LIST
- ${SAFE_VAPI_HOME}
- $ENV{SAFE_VAPI_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(SAFE_VAPI_INCLUDE_DIR vapi/vapi_safe.h
- HINTS ${SAFE_VAPI_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the vapi_safe includes"
-)
-
-find_library(SAFE_VAPI_LIBRARY NAMES libsafe_vapi.so
- HINTS ${SAFE_VAPI_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x86_64-linux-gnu/
- DOC "Find the vapi safe lib"
-)
-
-set(SAFE_VAPI_LIBRARIES ${SAFE_VAPI_LIBRARY})
-set(SAFE_VAPI_INCLUDE_DIRS ${SAFE_VAPI_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(VapiSafe DEFAULT_MSG SAFE_VAPI_LIBRARIES SAFE_VAPI_INCLUDE_DIRS)
-
-mark_as_advanced(SAFE_VAPI_LIBRARY SAFE_VAPI_INCLUDE_DIR)
diff --git a/cmake/Modules/FindVpp.cmake b/cmake/Modules/FindVpp.cmake
deleted file mode 100644
index 4f8dba17a..000000000
--- a/cmake/Modules/FindVpp.cmake
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(VPP_SEARCH_PATH_LIST
- ${VPP_HOME}
- $ENV{VPP_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(VPP_INCLUDE_DIR vnet/vnet.h
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the VPP includes"
-)
-
-find_library(VPP_LIBRARY_MEMORYCLIENT
- NAMES vlibmemoryclient
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp Memoryclient library"
-)
-
-find_library(VPP_LIBRARY_SVM
- NAMES svm
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp svm library"
-)
-
-find_library(VPP_LIBRARY_INFRA
- NAMES vppinfra
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp infra library"
-)
-
-find_library(VPP_LIBRARY_VNET
- NAMES vnet
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp vnet library"
-)
-
-find_library(VPP_LIBRARY_VATPLUGIN
- NAMES vatplugin
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp vatplugin library"
-)
-
-find_library(VPP_LIBRARY_VLIB
- NAMES vlib
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp vlib library"
-)
-
-find_library(VPP_LIBRARY_VPPAPICLIENT
- NAMES vppapiclient
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp api library"
-)
-
-find_library(VPP_LIBRARY_VAPICLIENT
- NAMES vapiclient
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp vapi library"
-)
-
-find_library(VPP_LIBRARY_VLIBMEMORY
- NAMES vlibmemory
- HINTS ${VPP_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib lib64
- DOC "Find the Vpp vlibmemory library"
-)
-
-set(VPP_LIBRARIES ${VPP_LIBRARY_MEMORYCLIENT} ${VPP_LIBRARY_SVM} ${VPP_LIBRARY_INFRA} ${VPP_LIBRARY_VATPLUGIN} ${VPP_LIBRARY_VLIB} ${VPP_LIBRARY_VNET} ${VPP_LIBRARY_VAPICLIENT} ${VPP_LIBRARY_VLIBMEMORY})
-set(VPP_INCLUDE_DIRS ${VPP_INCLUDE_DIR} ${VPP_INCLUDE_DIR}/vpp_plugins)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Vpp DEFAULT_MSG VPP_LIBRARIES VPP_INCLUDE_DIRS)
diff --git a/cmake/Modules/GTestImport.cmake b/cmake/Modules/GTestImport.cmake
deleted file mode 100644
index d9d182578..000000000
--- a/cmake/Modules/GTestImport.cmake
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-##################################
-# Download and install GoogleTest
-
-include(ExternalProject)
-ExternalProject_Add(gtest
- URL https://github.com/google/googletest/archive/v1.10.x.zip
- PREFIX ${CMAKE_BINARY_DIR}/gtest
- BUILD_BYPRODUCTS
- ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgmock_main.a
- ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgmock.a
- ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgtest_main.a
- ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgtest.a
- INSTALL_COMMAND ""
-)
-
-ExternalProject_Get_Property(gtest source_dir binary_dir)
-
-message (STATUS "GTest include dir: ${source_dir}/googlemock/include ${source_dir}/googletest/include)")
-message (STATUS "GTest libs: ${binary_dir}/lib/libgmock_main.a ${binary_dir}/lib/libgmock.a ${binary_dir}/lib/libgtest_main.a ${binary_dir}/lib/libgtest.a")
-
-set(GTEST_INCLUDE_DIRS ${source_dir}/googlemock/include ${source_dir}/googletest/include)
-set(GTEST_LIBRARIES ${binary_dir}/lib/libgmock_main.a ${binary_dir}/lib/libgmock.a ${binary_dir}/lib/libgtest_main.a ${binary_dir}/lib/libgtest.a)
-
-macro(add_test_internal test)
- if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
- gtest_discover_tests(${test}-bin TEST_PREFIX new:)
- else()
- add_test(NAME ${test}-bin COMMAND ${test})
- endif()
-endmacro(add_test_internal)
-
-enable_testing()
diff --git a/cmake/Modules/License.txt b/cmake/Modules/License.txt
deleted file mode 100644
index 4d84c0dc7..000000000
--- a/cmake/Modules/License.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Copyright (c) 2017-2021 Cisco and/or its affiliates.
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. \ No newline at end of file
diff --git a/cmake/Modules/Packager.cmake b/cmake/Modules/Packager.cmake
deleted file mode 100644
index 105952662..000000000
--- a/cmake/Modules/Packager.cmake
+++ /dev/null
@@ -1,344 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#############
-# RPM/DEB/TGZ Packaging utils
-#
-
-set(CONTACT "hicn-dev@lists.fd.io" CACHE STRING "Contact")
-set(PACKAGE_MAINTAINER "ICN Team" CACHE STRING "Maintainer")
-set(PACKAGE_VENDOR "fd.io" CACHE STRING "Vendor")
-
-function(get_next_version VERSION NEXT_VERSION)
- string(REGEX REPLACE "([0-9]+).([0-9]+)" "\\1;\\2" VER_NUMBERS ${VERSION})
-
- # Increment version for getting next version value
- list(GET VER_NUMBERS 0 major)
- list(GET VER_NUMBERS 1 minor)
-
- math(EXPR minor "${minor} + 4")
-
- if (minor GREATER 12)
- math(EXPR minor "${minor} % 12")
- math(EXPR major "${major} + 1")
- endif()
-
- if (minor LESS 10)
- set(minor "0${minor}")
- endif()
-
- set(${NEXT_VERSION} "${major}.${minor}" PARENT_SCOPE)
-endfunction()
-
-macro(extract_version)
- # Extract version from git
- execute_process(
- COMMAND git describe --long --match v*
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- OUTPUT_VARIABLE VER
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
- if (NOT VER)
- set(VER "v1.2-0-gcafe")
- endif()
- message(STATUS "Git describe output: ${VER}")
-
- string(REGEX REPLACE "v([0-9]+).([0-9]+)-?(.*)?-([0-9]+)-(g[0-9a-f]+)" "\\1;\\2;\\3;\\4;\\5;" VER ${VER})
- list(GET VER 0 VERSION_MAJOR)
- list(GET VER 1 VERSION_MINOR)
- list(GET VER 2 RELEASE_CANDIDATE)
- list(GET VER 3 VERSION_REVISION)
- list(GET VER 4 COMMIT_NAME)
-endmacro(extract_version)
-
-function(make_packages)
- if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- # parse /etc/os-release
- file(READ "/etc/os-release" os_version)
- string(REPLACE "\n" ";" os_version ${os_version})
- foreach(_ver ${os_version})
- string(REPLACE "=" ";" _ver ${_ver})
- list(GET _ver 0 _name)
- list(GET _ver 1 _value)
- set(OS_${_name} ${_value})
- endforeach()
-
- extract_version()
-
- message(STATUS "Version major: ${VERSION_MAJOR}")
- message(STATUS "Version minor: ${VERSION_MINOR}")
- message(STATUS "Release: ${RELEASE_CANDIDATE}")
- message(STATUS "Revision: ${VERSION_REVISION}")
- message(STATUS "Commit hash: ${COMMIT_NAME}")
-
- set(tag "${VERSION_MAJOR}.${VERSION_MINOR}")
- string(REPLACE "-" "~" tag ${tag})
- set(commit_num ${VERSION_REVISION})
- set(commit_name ${COMMIT_NAME})
-
- if (NOT DEFINED ENV{BUILD_NUMBER})
- set(bld "b1")
- else()
- set(bld "b$ENV{BUILD_NUMBER}")
- endif()
- message(STATUS "Build number is: ${bld}")
-
- #define DEB and RPM version numbers
- if(NOT RELEASE_CANDIDATE)
- if (commit_num)
- set(deb_ver "${tag}.${commit_num}-release")
- set(rpm_ver "${tag}.${commit_num}")
- else()
- set(deb_ver "${tag}-release")
- set(rpm_ver "${tag}")
- endif()
- set(rpm_release "release")
- else()
- # TODO To be changed for next release with
- # set(deb_ver "${tag}${RELEASE_CANDIDATE}~${commit_num}")
- # set(rpm_ver "${tag}")
- # set(rpm_release "${RELEASE_CANDIDATE}~${commit_num}")
- set(deb_ver "${tag}-${commit_num}")
- set(rpm_ver "${tag}-${commit_num}")
- set(rpm_release "1")
- endif()
-
- message(STATUS "Version: ${deb_ver}")
-
- get_next_version(${tag} next_version)
- message(STATUS "Next version: ${next_version}")
-
- get_cmake_property(components COMPONENTS)
- list(REMOVE_ITEM components "Unspecified")
- set(CPACK_COMPONENTS_ALL ${components})
-
- list(LENGTH components N_COMPONENTS)
-
- if (NOT N_COMPONENTS)
- return()
- endif()
-
- if(OS_ID MATCHES "debian" OR OS_ID_LIKE MATCHES "debian")
- set(CPACK_GENERATOR "DEB")
- set(type "DEBIAN")
-
- execute_process(
- COMMAND dpkg --print-architecture
- OUTPUT_VARIABLE arch
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
- set(CPACK_${type}_PACKAGE_VERSION "${deb_ver}")
- foreach(lc ${components})
- if (${lc} MATCHES ".*Unspecified.*")
- continue()
- endif()
-
- string(TOUPPER ${lc} uc)
- set(CPACK_${type}_${uc}_FILE_NAME "${lc}_${deb_ver}_${arch}.deb")
-
- set(DEB_DEPS)
- if (NOT ${${lc}_DEB_DEPENDENCIES} STREQUAL "")
- string(REPLACE "stable_version" ${tag} DEB_DEPS ${${lc}_DEB_DEPENDENCIES})
- string(REPLACE "next_version" ${next_version} DEB_DEPS ${DEB_DEPS})
- endif()
-
- set(CPACK_${type}_${uc}_PACKAGE_DEPENDS "${DEB_DEPS}")
- set(CPACK_${type}_${uc}_PACKAGE_NAME "${lc}")
- set(CPACK_COMPONENT_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}")
-
- if (${lc}_DEB_PACKAGE_CONTROL_EXTRA)
- set(CPACK_DEBIAN_${uc}_PACKAGE_CONTROL_EXTRA "${${lc}_DEB_PACKAGE_CONTROL_EXTRA}")
- endif()
- endforeach()
- elseif(OS_ID_LIKE MATCHES "rhel")
- set(CPACK_GENERATOR "RPM")
- set(type "RPM")
-
- execute_process(
- COMMAND uname -m
- OUTPUT_VARIABLE arch
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
- set(CPACK_${type}_PACKAGE_VERSION "${rpm_ver}")
- set(CPACK_${type}_PACKAGE_RELEASE "${rpm_release}")
- foreach(lc ${components})
- if (${lc} MATCHES ".*Unspecified.*")
- continue()
- endif()
-
- string(TOUPPER ${lc} uc)
- set(CPACK_${type}_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}")
-
- set(RPM_DEPS)
- if (NOT ${${lc}_RPM_DEPENDENCIES} STREQUAL "")
- string(REPLACE "stable_version" ${tag} RPM_DEPS ${${lc}_RPM_DEPENDENCIES})
- string(REPLACE "next_version" ${next_version} RPM_DEPS ${RPM_DEPS})
- endif()
-
- set(CPACK_${type}_${uc}_PACKAGE_REQUIRES "${RPM_DEPS}")
-
- if(${lc} MATCHES ".*-dev")
- set(package_name ${lc}el)
- else()
- set(package_name ${lc})
- endif()
-
- set(CPACK_RPM_${uc}_PACKAGE_NAME "${package_name}")
- set(CPACK_${type}_${uc}_FILE_NAME "${package_name}-${rpm_ver}-${rpm_release}.${arch}.rpm")
-
- if (NOT ${${lc}_RPM_POST_INSTALL_SCRIPT_FILE} STREQUAL "")
- set(CPACK_RPM_${uc}_POST_INSTALL_SCRIPT_FILE "${${lc}_RPM_POST_INSTALL_SCRIPT_FILE}")
- endif()
-
- if (NOT ${${lc}_RPM_POST_UNINSTALL_SCRIPT_FILE} STREQUAL "")
- set(CPACK_RPM_${uc}_POST_UNINSTALL_SCRIPT_FILE "${${lc}_RPM_POST_UNINSTALL_SCRIPT_FILE}")
- endif()
-
- if (NOT ${${lc}_RPM_PRE_UNINSTALL_SCRIPT_FILE} STREQUAL "")
- set(CPACK_RPM_${uc}_PRE_UNINSTALL_SCRIPT_FILE "${${lc}_RPM_PRE_UNINSTALL_SCRIPT_FILE}")
- endif()
- endforeach()
- endif()
-
- if(CPACK_GENERATOR)
- set(CPACK_PACKAGE_NAME ${ARG_NAME})
- set(CPACK_STRIP_FILES OFF)
- set(CPACK_PACKAGE_VENDOR "${PACKAGE_VENDOR}")
- set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
- set(CPACK_${CPACK_GENERATOR}_COMPONENT_INSTALL ON)
- set(CPACK_${type}_PACKAGE_MAINTAINER "HICN Team")
- set(CPACK_PACKAGE_CONTACT ${CONTACT})
- include(CPack)
- endif()
- elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
- set(CMAKE_SKIP_BUILD_RPATH FALSE)
- set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
- set(CMAKE_INSTALL_RPATH /opt/hicn)
-
- set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
-
- set(CPACK_SET_DESTDIR true)
-
- set(CMAKE_INSTALL_RPATH "\${CPACK_INSTALL_PREFIX}")
- set(CMAKE_SKIP_INSTALL_RPATH FALSE)
- set(HICN_DEPENDECIES_INSTALLER "${LIBTRANSPORT_LIBRARIES_LIST};${FACEMGR_LIBRARY_LIST};${APPS_LIBRARY_LIST}")
- separate_arguments(HICN_DEPENDECIES_INSTALLER)
- foreach (HICN_DEPENDECY ${HICN_DEPENDECIES_INSTALLER})
- get_filename_component(DEPENDENCY_NAME "${HICN_DEPENDECY}" NAME)
- get_filename_component(DEPENDENCY "${HICN_DEPENDECY}" REALPATH)
- get_filename_component(DEPENDENCY_PATH "${DEPENDENCY}" DIRECTORY)
- install(FILES ${DEPENDENCY} DESTINATION lib COMPONENT dependencies)
- endforeach()
- set(CPACK_PACKAGE_NAME "hicn")
- extract_version()
- set(CPACK_PACKAGE_VENDOR "${PACKAGE_VENDOR}")
- set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "hICN")
- set(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
- set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
- set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
- set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_REVISION}")
- set(CPACK_PACKAGE_INSTALL_DIRECTORY "hICN Components")
-
- set(CPACK_COMPONENTS_ALL dependencies ${HICN_UTILS} ${HICN_LIGHT} ${HICN_APPS} ${FACEMGR} lib${LIBTRANSPORT} ${LIBTRANSPORT}-dev lib${LIBHICN} ${LIBHICN}-dev ${HICN_UTILS}-dev ${HICN_LIGHT}-dev ${HICN_APPS}-dev ${FACEMGR}-dev)
- set(CPACK_COMPONENT_DEPENDENCIES_DISPLAY_NAME "Dependencies")
- if (NOT "${HICN_UTILS}" STREQUAL "")
- string(TOUPPER ${HICN_UTILS} HICN_UTILS_UPPERCASE)
- string(TOUPPER ${HICN_UTILS}-dev HICN_UTILS_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_DISPLAY_NAME "hICN utils")
- set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_DISPLAY_NAME "hicn utils headers")
- set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_GROUP "Executables")
- set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif ()
-
- if (NOT "${HICN_LIGHT}" STREQUAL "")
- string(TOUPPER ${HICN_LIGHT} HICN_LIGHT_UPPERCASE)
- string(TOUPPER ${HICN_LIGHT}-dev HICN_LIGHT_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_DISPLAY_NAME "hICN light apps")
- set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_DISPLAY_NAME "hicn-light headers")
- set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_GROUP "Executables")
- set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif ()
-
- if (NOT "${HICN_APPS}" STREQUAL "")
- string(TOUPPER ${HICN_APPS} HICN_APPS_UPPERCASE)
- string(TOUPPER ${HICN_APPS}-dev HICN_APPS_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_DISPLAY_NAME "hICN apps")
- set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_DISPLAY_NAME "hicn-apps headers")
- set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_GROUP "Executables")
- set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif ()
-
- if (NOT "${FACEMGR}" STREQUAL "")
- string(TOUPPER ${FACEMGR} FACEMGR_UPPERCASE)
- string(TOUPPER ${FACEMGR}-dev FACEMGR_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_DISPLAY_NAME "facemgr")
- set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_DISPLAY_NAME "facemgr headers")
- set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_GROUP "Executables")
- set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif ()
-
- if (NOT "${LIBTRANSPORT}" STREQUAL "")
- string(TOUPPER lib${LIBTRANSPORT} LIBTRANSPORT_UPPERCASE)
- string(TOUPPER ${LIBTRANSPORT}-dev LIBTRANSPORT_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_DISPLAY_NAME "libtransport libs")
- set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_DISPLAY_NAME "libtransport headers")
- set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_GROUP "Libraries")
- set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif ()
-
- if (NOT "${LIBHICN}" STREQUAL "")
- string(TOUPPER lib${LIBHICN} LIBHICN_UPPERCASE)
- string(TOUPPER ${LIBHICN}-dev LIBHICN_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_DISPLAY_NAME "hicn libs")
- set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_DISPLAY_NAME "hicn headers")
- set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_GROUP "Libraries")
- set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif ()
-
- set (CPACK_RESOURCE_FILE_LICENSE
- "${PROJECT_SOURCE_DIR}/cmake/Modules/License.txt")
- set(CPACK_COMPONENT_DEPENDENCIES_DESCRIPTION
- "All dependency libreries")
- set(CPACK_COMPONENT_DEPENDENCIES_GROUP "Dependencies")
- set(CPACK_COMPONENT_GROUP_DEVELOPMENT_EXPANDED ON)
- set(CPACK_COMPONENT_GROUP_DEPENDENCIES_DESCRIPTION
- "All dependency libreries")
- set(CPACK_ALL_INSTALL_TYPES Full Developer)
- set(CPACK_INSTALL_TYPE_FULL_DISPLAY_NAME "Everything")
- if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set(CMAKE_INSTALL_RPATH /opt/hicn)
-
- set(CPACK_INSTALL_PREFIX "/opt/hicn")
- set(CPACK_GENERATOR productbuild)
- set( CPACK_PRE_BUILD_SCRIPTS "${PROJECT_SOURCE_DIR}/cmake/Modules/PostInstall.cmake")
- else()
- set(CPACK_INSTALL_PREFIX "c:/Program Files/hicn")
- endif()
- include(CPack)
- endif()
-endfunction()
diff --git a/cmake/Modules/PostInstall.cmake b/cmake/Modules/PostInstall.cmake
deleted file mode 100644
index 89c7b9f68..000000000
--- a/cmake/Modules/PostInstall.cmake
+++ /dev/null
@@ -1,83 +0,0 @@
-function(change_rpath LIB_PATH TYPE)
- execute_process (
- COMMAND bash -c "ls ${LIB_PATH}"
- OUTPUT_VARIABLE ITEMS
- )
- string(REPLACE "\n" ";" ITEMS ${ITEMS})
-
- separate_arguments(ITEMS)
- foreach (ITEM ${ITEMS})
- if (NOT ITEM MATCHES ".a$")
- if (TYPE STREQUAL "LIB")
- execute_process (
- COMMAND bash -c "otool -L ${LIB_PATH}/${ITEM} | head -2 | tail -1| sed -e 's/^[[:space:]]*//'|awk '{print $1;}'"
- OUTPUT_VARIABLE OTOOL_OUTPUT
- )
- string(REPLACE "\n" "" OTOOL_OUTPUT ${OTOOL_OUTPUT})
-
- execute_process (
- COMMAND bash -c "basename ${OTOOL_OUTPUT}| sed -e 's/^[[:space:]]*//'"
- OUTPUT_VARIABLE BASENAME
- )
- string(REPLACE "\n" "" BASENAME ${BASENAME})
- execute_process (
- COMMAND bash -c "install_name_tool -id ${CPACK_INSTALL_PREFIX}/${BASENAME} ${LIB_PATH}/${ITEM}"
- OUTPUT_VARIABLE OUTPUT_INSTALL_NAME_TOOL
- )
- #change rpath
- execute_process (
- COMMAND bash -c "otool -L ${LIB_PATH}/${ITEM} | tail -n +3| sed -e 's/^[[:space:]]*//'|awk '{print $1;}'"
- OUTPUT_VARIABLE OTOOL_OUTPUTS
- )
- else ()
- #change rpath
- execute_process (
- COMMAND bash -c "otool -L ${LIB_PATH}/${ITEM} | tail -n +2| sed -e 's/^[[:space:]]*//'|awk '{print $1;}'"
- OUTPUT_VARIABLE OTOOL_OUTPUTS
- )
- endif ()
- string(REPLACE "\n" ";" OTOOL_OUTPUTS ${OTOOL_OUTPUTS})
- separate_arguments(OTOOL_OUTPUTS)
- foreach (OTOOL_OUTPUT ${OTOOL_OUTPUTS})
- execute_process (
- COMMAND bash -c "basename ${OTOOL_OUTPUT}| sed -e 's/^[[:space:]]*//'"
- OUTPUT_VARIABLE BASENAME
- )
- string(REPLACE "\n" "" BASENAME ${BASENAME})
- execute_process (
- COMMAND bash -c "dirname ${OTOOL_OUTPUT}| sed -e 's/^[[:space:]]*//'"
- OUTPUT_VARIABLE DIRNAME
- )
- string(REPLACE "\n" "" DIRNAME ${DIRNAME})
- if(NOT DIRNAME MATCHES "/usr/lib")
- execute_process (
- COMMAND bash -c "install_name_tool -change ${OTOOL_OUTPUT} ${CPACK_INSTALL_PREFIX}/${BASENAME} ${LIB_PATH}/${ITEM}"
- OUTPUT_VARIABLE OUTPUT_INSTALL_NAME_TOOL
- )
- endif()
-
- endforeach()
- endif()
- endforeach()
-endfunction()
-string(TOLOWER ${CPACK_COMPONENT_DEPENDENCIES_GROUP} CPACK_COMPONENT_DEPENDENCIES_GROUP )
-set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/${CPACK_COMPONENT_DEPENDENCIES_GROUP}${CPACK_INSTALL_PREFIX}/lib")
-change_rpath(${LIB_PATH} LIB)
-
-set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/facemgr${CPACK_INSTALL_PREFIX}/lib")
-change_rpath(${LIB_PATH} LIB)
-set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/libhicntransport${CPACK_INSTALL_PREFIX}/lib")
-change_rpath(${LIB_PATH} LIB)
-set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/libhicn${CPACK_INSTALL_PREFIX}/lib")
-change_rpath(${LIB_PATH} LIB)
-
-set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicn-utils${CPACK_INSTALL_PREFIX}/bin")
-change_rpath(${EXE_PATH} EXE)
-set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicn-light${CPACK_INSTALL_PREFIX}/bin")
-change_rpath(${EXE_PATH} EXE)
-set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicn-apps${CPACK_INSTALL_PREFIX}/bin")
-change_rpath(${EXE_PATH} EXE)
-set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/facemgr${CPACK_INSTALL_PREFIX}/bin")
-change_rpath(${EXE_PATH} EXE)
-#set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicnctrl${CPACK_INSTALL_PREFIX}/bin")
-#change_rpath(${EXE_PATH} EXE)
diff --git a/cmake/Modules/ServiceScript.cmake b/cmake/Modules/ServiceScript.cmake
deleted file mode 100644
index 8e7056a5a..000000000
--- a/cmake/Modules/ServiceScript.cmake
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-########################################
-#
-# Find the LongBow libraries and includes
-# This module sets:
-# SYSTEMD_FOUND: True if Systemd was found
-# SYSTEMD_SERVICES_INSTALL_DIR: The Systemd install directory
-
-set(SYSTEMD_SERVICE_FOLDER "/lib/systemd/system")
-
-macro(install_service_script script)
-cmake_parse_arguments(ARG
- ""
- "COMPONENT"
- ""
- ${ARGN}
-)
-
- # Install service file only if
- # 1) We are on a linux system
- # 2) The installation prefix is /usr
-
- if (NOT ARG_COMPONENT)
- set(ARG_COMPONENT hicn)
- endif()
-
- if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ${CMAKE_INSTALL_PREFIX} STREQUAL "/usr")
- install (FILES ${script} DESTINATION ${SYSTEMD_SERVICE_FOLDER} COMPONENT ${ARG_COMPONENT})
- endif()
-endmacro(install_service_script)
diff --git a/cmake/Modules/WindowsMacros.cmake b/cmake/Modules/WindowsMacros.cmake
deleted file mode 100644
index 0b34cde19..000000000
--- a/cmake/Modules/WindowsMacros.cmake
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if(WIN32)
- find_package(LibEvent REQUIRED)
- find_package(OpenSSL REQUIRED)
- find_package(PThread REQUIRED)
- find_library(WSOCK32_LIBRARY wsock32 required)
- find_library(WS2_32_LIBRARY ws2_32 required)
- list(APPEND WINDOWS_LIBRARIES
- ${LIBEVENT_LIBRARIES}
- ${OPENSSL_LIBRARIES}
- ${PTHREAD_LIBRARIES}
- ${WSOCK32_LIBRARY}
- ${WS2_32_LIBRARY}
- )
-
- list(APPEND WINDOWS_INCLUDE_DIRS
- ${LIBEVENT_INCLUDE_DIRS}
- ${OPENSSL_INCLUDE_DIR}
- ${PTHREAD_INCLUDE_DIRS}
- )
-endif() \ No newline at end of file
diff --git a/cmake/Modules/detectCacheSize.cmake b/cmake/Modules/detectCacheSize.cmake
deleted file mode 100644
index a8209bb27..000000000
--- a/cmake/Modules/detectCacheSize.cmake
+++ /dev/null
@@ -1,21 +0,0 @@
-# Detect the cache size
-#
-# XXX: TODO: This is a bug when cross compiling. We are detecting the local
-# Cache Line size and not the target cache line size. We should provide some
-# way to define this
-
-set(LEVEL1_DCACHE_LINESIZE 32)
-
-if( APPLE )
- execute_process(COMMAND sysctl -n hw.cachelinesize
- OUTPUT_VARIABLE LEVEL1_DCACHE_LINESIZE
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-endif( APPLE )
-
-if( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" )
- execute_process(COMMAND getconf LEVEL1_DCACHE_LINESIZE
- OUTPUT_VARIABLE LEVEL1_DCACHE_LINESIZE
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-endif()
-
-message(STATUS "Cache line size: ${LEVEL1_DCACHE_LINESIZE}")
diff --git a/libtransport/cmake/Modules/TestMacros.cmake b/ctrl/.clang-format
index 680b5585f..2f629734d 100644
--- a/libtransport/cmake/Modules/TestMacros.cmake
+++ b/ctrl/.clang-format
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -11,5 +11,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-include(CTest)
-
+BasedOnStyle: Google
+SortIncludes: false
diff --git a/ctrl/CMakeLists.txt b/ctrl/CMakeLists.txt
index 331ae9078..d6fe72d3e 100644
--- a/ctrl/CMakeLists.txt
+++ b/ctrl/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -10,13 +10,17 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 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(ctrl)
-add_subdirectory(libhicnctrl)
-if (NOT (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
- add_subdirectory(facemgr)
+##############################################################
+# Subdirectories
+##############################################################
+add_subdirectory(libhicnctrl)
+if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
+ add_subdirectory(facemgr)
endif () \ No newline at end of file
diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt
index 2fad5d839..9d549bddf 100644
--- a/ctrl/facemgr/CMakeLists.txt
+++ b/ctrl/facemgr/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,62 +11,98 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+##############################################################
+# Project and cmake version
+##############################################################
+project(facemgr)
+
if (APPLE)
- # >= 3.13 - CMP0079 (only needed on Apple platform for conditionally linking Network.framwork to libfacemgr)
- cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
+ # >= 3.13 - CMP0079 (only needed on Apple platform for conditionally linking Network.framwork to libfacemgr)
+ cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
else()
- cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
endif()
-project(facemgr)
+##############################################################
+# C Standard
+##############################################################
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+
+##############################################################
+# CMAKE Options
+##############################################################
option(WITH_THREAD "Run library as thread" OFF)
option(WITH_EXAMPLE_DUMMY "Compile dummy example interface" OFF)
option(WITH_EXAMPLE_UPDOWN "Compile updown example interface" OFF)
if(WITH_THREAD)
- message("Building with thread support")
+ message(STATUS "Building with thread support")
endif()
if(WITH_EXAMPLE_DUMMY)
- message("Building with 'dummy' example interface")
+ message(STATUS "Building with 'dummy' example interface")
endif()
if(WITH_EXAMPLE_UPDOWN)
- message("Building with 'updown' example interface")
-endif()
-
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
+ message(STATUS "Building with 'updown' example interface")
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
endif()
+
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
-include(BuildMacros)
-set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_STANDARD_REQUIRED ON)
+##############################################################
+# Libs and Bins names
+##############################################################
+set(FACEMGR facemgr CACHE INTERNAL "" FORCE)
+set(LIBFACEMGR facemgr CACHE INTERNAL "" FORCE)
+
+
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
-find_package_wrapper(Libconfig REQUIRED)
-find_package_wrapper(LibEvent REQUIRED)
-set(FACEMGR facemgr CACHE INTERNAL "" FORCE)
-set(LIBFACEMGR facemgr CACHE INTERNAL "" FORCE)
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(Libconfig ${LIBCONFIG_DEFAULT_VERSION} REQUIRED)
+find_package(LibEvent ${LIBEVENT_DEFAULT_VERSION} REQUIRED)
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package_wrapper(Libhicn REQUIRED)
- find_package_wrapper(Libhicnctrl REQUIRED)
+ include(CommonSetup)
+
+ 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 HICN_LIBRARIES hicn::hicn.${LIBTYPE})
+ list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
@@ -89,11 +125,18 @@ else()
endif ()
endif()
+
+##############################################################
+# Subdirectories
+##############################################################
add_subdirectory(includes)
add_subdirectory(src)
-include(Packaging)
+
+##############################################################
+# Service file
+##############################################################
# Install service file in linux systems
include(ServiceScript)
install_service_script(
@@ -101,14 +144,23 @@ install_service_script(
COMPONENT ${FACEMGR}
)
+
+##############################################################
# Configuration file
+##############################################################
set(FACEMGR_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/config/facemgr.conf)
-set(FACEMGR_CONF_FOLDER "/etc/facemgr")
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
- install (FILES ${FACEMGR_CONF_FILE} DESTINATION ${FACEMGR_CONF_FOLDER} COMPONENT ${FACEMGR})
+if (${CMAKE_SYSTEM_NAME} MATCHES Darwin OR ${CMAKE_SYSTEM_NAME} MATCHES Linux)
+ set(FACEMGR_CONF_FOLDER "${CMAKE_INSTALL_FULL_SYSCONFDIR}/facemgr")
+else ()
+ set(FACEMGR_CONF_FOLDER "${CMAKE_INSTALL_PREFIX}/etc/hicn")
endif()
+install (FILES
+ ${FACEMGR_CONF_FILE}
+ DESTINATION ${FACEMGR_CONF_FOLDER}
+ COMPONENT ${FACEMGR}
+)
+
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
- make_packages()
+ make_packages()
endif()
diff --git a/ctrl/facemgr/cmake/Modules/Packaging.cmake b/ctrl/facemgr/cmake/packaging.cmake
index bb4fa42fa..62b14b202 100644
--- a/ctrl/facemgr/cmake/Modules/Packaging.cmake
+++ b/ctrl/facemgr/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -20,27 +20,37 @@ set(${FACEMGR}_DESCRIPTION
CACHE STRING "Description for deb/rpm package."
)
+set(${FACEMGR}-dev_DEB_DEPENDENCIES
+ "libconfig9, libevent-dev, lib${LIBHICNCTRL}-dev (= stable_version)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
set(${FACEMGR}_DEB_DEPENDENCIES
- "libconfig9, libevent-dev, lib${LIBHICNCTRL} (>= stable_version)"
+ "libconfig9, libevent-2.1-7, lib${LIBHICNCTRL} (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
-set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA
+set(${FACEMGR}_DEB_PACKAGE_CONTROL_EXTRA
"${CMAKE_CURRENT_SOURCE_DIR}/config/postinst;${CMAKE_CURRENT_SOURCE_DIR}/config/prerm"
CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
)
set(${FACEMGR}_RPM_DEPENDENCIES
- "libconfig, libevent-devel, lib${LIBHICNCTRL} >= stable_version"
+ "libconfig, libevent, lib${LIBHICNCTRL} = stable_version"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
+set(${FACEMGR}-dev_RPM_DEPENDENCIES
+ "libconfig, libevent-devel, lib${LIBHICNCTRL}-dev = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
-set(${HICN_LIGHT}_RPM_POST_INSTALL_SCRIPT_FILE
+set(${FACEMGR}_RPM_POST_INSTALL_SCRIPT_FILE
"${CMAKE_CURRENT_SOURCE_DIR}/config/post"
CACHE STRING "Install script that will be copied in the %post section"
)
-set(${HICN_LIGHT}_RPM_PRE_UNINSTALL_SCRIPT_FILE
+set(${FACEMGR}_RPM_PRE_UNINSTALL_SCRIPT_FILE
"${CMAKE_CURRENT_SOURCE_DIR}/config/preun"
CACHE STRING "Install script that will be copied in the %post section"
)
diff --git a/ctrl/facemgr/config/facemgr.service b/ctrl/facemgr/config/facemgr.service
index 0f9e818ea..89d4f9283 100644
--- a/ctrl/facemgr/config/facemgr.service
+++ b/ctrl/facemgr/config/facemgr.service
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/config/postinst b/ctrl/facemgr/config/postinst
index 4113b0eca..7b2fd57fe 100755
--- a/ctrl/facemgr/config/postinst
+++ b/ctrl/facemgr/config/postinst
@@ -1,3 +1,5 @@
#!/bin/bash
-systemctl enable facemgr
+if pidof systemd; then
+ systemctl enable facemgr
+fi
diff --git a/ctrl/facemgr/config/prerm b/ctrl/facemgr/config/prerm
index b5c486ea5..8c0eadf0d 100755
--- a/ctrl/facemgr/config/prerm
+++ b/ctrl/facemgr/config/prerm
@@ -1,3 +1,5 @@
#!/bin/bash
-systemctl disable facemgr
+if pidof systemd; then
+ systemctl disable facemgr
+fi
diff --git a/ctrl/facemgr/config/preun b/ctrl/facemgr/config/preun
index b5c486ea5..8c0eadf0d 100755
--- a/ctrl/facemgr/config/preun
+++ b/ctrl/facemgr/config/preun
@@ -1,3 +1,5 @@
#!/bin/bash
-systemctl disable facemgr
+if pidof systemd; then
+ systemctl disable facemgr
+fi
diff --git a/ctrl/facemgr/examples/mobility/mobility.c b/ctrl/facemgr/examples/mobility/mobility.c
index 528951446..ae1d6dee3 100644
--- a/ctrl/facemgr/examples/mobility/mobility.c
+++ b/ctrl/facemgr/examples/mobility/mobility.c
@@ -7,82 +7,81 @@
* Test server using nc: nc -4kvul localhost 9533
*/
-#include <arpa/inet.h> // inet_ntop
-#include <errno.h> // EINTR,. ..
-#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
+#include <arpa/inet.h> // inet_ntop
+#include <errno.h> // EINTR,. ..
+#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/timerfd.h>
-#include <sys/un.h> // sockaddr_un
-#include <unistd.h> // fcntl
-#include <fcntl.h> // fcntl
+#include <sys/un.h> // sockaddr_un
+#include <unistd.h> // fcntl
+#include <fcntl.h> // fcntl
#define MS2US(x) (x * 1000)
/**
* \brief Main function
*/
-int main(int argc, char **argv)
-{
- int rc;
+int main(int argc, char **argv) {
+ int rc;
- if (argc != 4) {
- fprintf(stderr, "Usage: %s IP PORT INTERVAL\n", argv[0]);
- fprintf(stderr, "\n");
- fprintf(stderr, " IP Target hostname\n");
- fprintf(stderr, " PORT Target port\n");
- fprintf(stderr, " INTERVAL Interval between mobility events (in ms)\n");
- fprintf(stderr, "\n");
- exit(EXIT_FAILURE);
- }
+ if (argc != 4) {
+ fprintf(stderr, "Usage: %s IP PORT INTERVAL\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " IP Target hostname\n");
+ fprintf(stderr, " PORT Target port\n");
+ fprintf(stderr, " INTERVAL Interval between mobility events (in ms)\n");
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+ }
- int interval = atoi(argv[3]);
+ int interval = atoi(argv[3]);
- int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (fd < 0) {
- perror("socket");
- goto ERR_SOCKET;
- }
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ perror("socket");
+ goto ERR_SOCKET;
+ }
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(argv[1]);
- addr.sin_port = htons(atoi(argv[2]));
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(argv[1]);
+ addr.sin_port = htons(atoi(argv[2]));
- if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- perror("connect");
- goto ERR_CONNECT;
- }
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ perror("connect");
+ goto ERR_CONNECT;
+ }
- unsigned state = 0;
- char buf[1];
- for(;;) {
- usleep(MS2US(interval));
+ unsigned state = 0;
+ char buf[1];
+ for (;;) {
+ usleep(MS2US(interval));
- buf[0] = state;
- rc = send(fd, buf, 1, 0);
- if (rc < 0) {
- if (errno == ECONNREFUSED) {
- continue;
- }
- perror("send");
- goto ERR_SEND;
- }
-
- state = 1 - state;
+ buf[0] = state;
+ rc = send(fd, buf, 1, 0);
+ if (rc < 0) {
+ if (errno == ECONNREFUSED) {
+ continue;
+ }
+ perror("send");
+ goto ERR_SEND;
}
- close(fd);
+ state = 1 - state;
+ }
+
+ close(fd);
- exit(EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
ERR_SEND:
ERR_CONNECT:
- close(fd);
+ close(fd);
ERR_SOCKET:
- exit(EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
diff --git a/ctrl/facemgr/examples/updowncli/updowncli.c b/ctrl/facemgr/examples/updowncli/updowncli.c
index 4f5a14165..34ec3fb97 100644
--- a/ctrl/facemgr/examples/updowncli/updowncli.c
+++ b/ctrl/facemgr/examples/updowncli/updowncli.c
@@ -5,6 +5,8 @@
#include <stdlib.h>
#include <unistd.h>
+#include <hicn/util/sstrncpy.h>
+
/**
* \brief Default unix socket path (the leading \0 means using the abstract
* namespace instead of the filesystem).
@@ -12,46 +14,46 @@
#define UNIX_PATH "\0updownsrv"
int main() {
- struct sockaddr_un addr;
- char buf[100];
- int fd,rc;
-
- char * socket_path = UNIX_PATH;
-
- if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- perror("socket error");
- exit(-1);
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- if (*socket_path == '\0') {
- *addr.sun_path = '\0';
- strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
- } else {
- strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
- }
-
- if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
- perror("connect error");
- exit(-1);
- }
-
- printf("Waiting for server data...\n");
- while( (rc=read(fd, buf, sizeof(buf))) > 0) {
- assert(rc == 1);
- switch(buf[0]) {
- case '\0':
- printf("WiFi\n");
- break;
- case '\1':
- printf("LTE\n");
- break;
- default:
- printf("Unknown\n");
- break;
- }
+ struct sockaddr_un addr;
+ char buf[100];
+ int fd, rc;
+
+ char* socket_path = UNIX_PATH;
+
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ perror("socket error");
+ exit(-1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*socket_path == '\0') {
+ *addr.sun_path = '\0';
+ strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, socket_path + 1);
+ } else {
+ strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, socket_path);
+ }
+
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("connect error");
+ exit(-1);
+ }
+
+ printf("Waiting for server data...\n");
+ while ((rc = read(fd, buf, sizeof(buf))) > 0) {
+ assert(rc == 1);
+ switch (buf[0]) {
+ case '\0':
+ printf("WiFi\n");
+ break;
+ case '\1':
+ printf("LTE\n");
+ break;
+ default:
+ printf("Unknown\n");
+ break;
}
+ }
- return 0;
+ return 0;
}
diff --git a/ctrl/facemgr/examples/updownsrv/updownsrv.c b/ctrl/facemgr/examples/updownsrv/updownsrv.c
index 3aba3cfd0..57661d427 100644
--- a/ctrl/facemgr/examples/updownsrv/updownsrv.c
+++ b/ctrl/facemgr/examples/updownsrv/updownsrv.c
@@ -5,19 +5,20 @@
* using unix domains that sets a face up and down.
*/
-#include <arpa/inet.h> // inet_ntop
-#include <errno.h> // EINTR,. ..
-#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
+#include <arpa/inet.h> // inet_ntop
+#include <errno.h> // EINTR,. ..
+#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/timerfd.h>
-#include <sys/un.h> // sockaddr_un
-#include <unistd.h> // fcntl
-#include <fcntl.h> // fcntl
+#include <sys/un.h> // sockaddr_un
+#include <unistd.h> // fcntl
+#include <fcntl.h> // fcntl
+#include <hicn/util/sstrncpy.h>
/**
* \brief Default unix socket path (the leading \0 means using the abstract
@@ -40,199 +41,190 @@
*/
#define LISTEN_BACKLOG MAX_CLIENTS
-
/**
* \brief Creates a unix server socket
* \param [in] path - string representing the path on which to listen for
* connections
* \return int - fd associated to the socket
*/
-int
-create_unix_server(char * path)
-{
- struct sockaddr_un addr;
- int fd;
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1) {
- perror("socket error");
- return -1;
- }
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- perror("fcntl");
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- if (*path == '\0') {
- *addr.sun_path = '\0';
- strncpy(addr.sun_path+1, path+1, sizeof(addr.sun_path)-2);
- } else {
- strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
- unlink(path);
- }
-
- if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
- perror("bind error");
- return -1;
- }
-
- if (listen(fd, LISTEN_BACKLOG) == -1) {
- perror("listen error");
- return -1;
- }
-
- return fd;
+int create_unix_server(char* path) {
+ struct sockaddr_un addr;
+ int fd;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1) {
+ perror("socket error");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*path == '\0') {
+ *addr.sun_path = '\0';
+ strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, path + 1);
+ } else {
+ strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, path);
+ unlink(path);
+ }
+
+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("bind error");
+ return -1;
+ }
+
+ if (listen(fd, LISTEN_BACKLOG) == -1) {
+ perror("listen error");
+ return -1;
+ }
+
+ return fd;
}
-
/**
* \brief Main function
*/
int main() {
- int fd, tfd;
- int rc;
-
- /* Alternating state of the server : 0 / 1 */
- unsigned state = 0;
-
- /*
- * This server has to send a signal to all connected clients at periodic
- * intervals. Since we don't expect a large number of connected clients for
- * such a simple program, we simply use a statically allocated array.
- */
- int clients[MAX_CLIENTS];
- size_t num_clients = 0;
-
- fd_set active_fd_set, read_fd_set;
- FD_ZERO (&active_fd_set);
-
- /* Create listening unix socket */
- fd = create_unix_server(UNIX_PATH);
- if (fd < 0)
- exit(EXIT_FAILURE);
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- perror("fcntl");
- exit(EXIT_FAILURE);
- }
-
- FD_SET (fd, &active_fd_set);
-
- /* Create timer */
- tfd = timerfd_create(CLOCK_MONOTONIC, 0);
- if (tfd == -1) {
- perror("timer error");
- exit(EXIT_FAILURE);
+ int fd, tfd;
+ int rc;
+
+ /* Alternating state of the server : 0 / 1 */
+ unsigned state = 0;
+
+ /*
+ * This server has to send a signal to all connected clients at periodic
+ * intervals. Since we don't expect a large number of connected clients for
+ * such a simple program, we simply use a statically allocated array.
+ */
+ int clients[MAX_CLIENTS];
+ size_t num_clients = 0;
+
+ fd_set active_fd_set, read_fd_set;
+ FD_ZERO(&active_fd_set);
+
+ /* Create listening unix socket */
+ fd = create_unix_server(UNIX_PATH);
+ if (fd < 0) exit(EXIT_FAILURE);
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ exit(EXIT_FAILURE);
+ }
+
+ FD_SET(fd, &active_fd_set);
+
+ /* Create timer */
+ tfd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (tfd == -1) {
+ perror("timer error");
+ exit(EXIT_FAILURE);
+ }
+
+ if (fcntl(tfd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ exit(EXIT_FAILURE);
+ }
+
+ FD_SET(tfd, &active_fd_set);
+
+ struct itimerspec ts = {.it_interval =
+ {
+ .tv_sec = DEFAULT_INTERVAL_SEC,
+ .tv_nsec = DEFAULT_INTERVAL_NSEC,
+ },
+ .it_value = {
+ .tv_sec = DEFAULT_INTERVAL_SEC,
+ .tv_nsec = DEFAULT_INTERVAL_NSEC,
+ }};
+ rc = timerfd_settime(tfd, 0, &ts, NULL);
+ if (rc == -1) {
+ perror("timerfd_settime");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Waiting for clients...\n");
+
+ for (;;) {
+ /* Block until input arrives on one or more active sockets. */
+ read_fd_set = active_fd_set;
+ rc = select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);
+ if (rc < 0) {
+ if (rc == EINTR) break;
+ perror("select");
+ exit(EXIT_FAILURE);
}
- if (fcntl(tfd, F_SETFL, O_NONBLOCK) < 0) {
- perror("fcntl");
- exit(EXIT_FAILURE);
- }
-
- FD_SET (tfd, &active_fd_set);
-
- struct itimerspec ts = {
- .it_interval = {
- .tv_sec = DEFAULT_INTERVAL_SEC,
- .tv_nsec = DEFAULT_INTERVAL_NSEC,
- },
- .it_value = {
- .tv_sec = DEFAULT_INTERVAL_SEC,
- .tv_nsec = DEFAULT_INTERVAL_NSEC,
- }
- };
- rc = timerfd_settime(tfd, 0, &ts, NULL);
- if (rc == -1) {
- perror("timerfd_settime");
- exit(EXIT_FAILURE);
- }
-
- printf("Waiting for clients...\n");
-
- for(;;) {
- /* Block until input arrives on one or more active sockets. */
- read_fd_set = active_fd_set;
- rc = select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);
- if (rc < 0) {
- if (rc == EINTR)
- break;
- perror("select");
- exit (EXIT_FAILURE);
+ /* Service all the sockets with input pending. */
+ for (int i = 0; i < FD_SETSIZE; ++i) {
+ if (!FD_ISSET(i, &read_fd_set)) continue;
+ if (i == fd) {
+ /* Connection request on original socket. */
+ int client_fd = accept(fd, NULL, NULL);
+ if (client_fd < 0) {
+ perror("accept");
+ continue;
}
- /* Service all the sockets with input pending. */
- for (int i = 0; i < FD_SETSIZE; ++i) {
- if (!FD_ISSET (i, &read_fd_set))
- continue;
- if (i == fd) {
- /* Connection request on original socket. */
- int client_fd = accept(fd, NULL, NULL);
- if (client_fd < 0) {
- perror("accept");
- continue;
- }
-
- fprintf(stderr, "Server: connect from new client\n");
- clients[num_clients++] = client_fd;
- FD_SET(client_fd, &active_fd_set);
- } else if (i == tfd) {
- /* Timer event */
- uint64_t res;
-
- read(tfd, &res, sizeof(res));
-// while (read(fd, &missed, sizeof(missed)) > 0)
-// ;
- for (unsigned j = 0; j < num_clients; j++) {
- write(clients[j], state ? "\1" : "\0", 1);
- }
- printf("STATE=%d\n", state);
- state = 1 - state;
- } else {
- char buf[1024];
- rc = read(i, buf, sizeof(buf));
- /* Client event : we close the connection on any event... */
- for (unsigned j = 0; j < num_clients; j++) {
- if (i == clients[j]) {
- clients[j] = clients[num_clients--];
- break;
- }
- }
- close(i);
- FD_CLR(i, &active_fd_set);
- }
+ fprintf(stderr, "Server: connect from new client\n");
+ clients[num_clients++] = client_fd;
+ FD_SET(client_fd, &active_fd_set);
+ } else if (i == tfd) {
+ /* Timer event */
+ uint64_t res;
+
+ read(tfd, &res, sizeof(res));
+ // while (read(fd, &missed, sizeof(missed)) > 0)
+ // ;
+ for (unsigned j = 0; j < num_clients; j++) {
+ write(clients[j], state ? "\1" : "\0", 1);
}
-
- }
-
- int ret = EXIT_SUCCESS;
-
- /* Close all active client connections */
- for (unsigned i = 0; i < num_clients; i++) {
- rc = close(clients[i]);
- if (rc == -1) {
- perror("close");
- ret = EXIT_FAILURE;
+ printf("STATE=%d\n", state);
+ state = 1 - state;
+ } else {
+ char buf[1024];
+ rc = read(i, buf, sizeof(buf));
+ /* Client event : we close the connection on any event... */
+ for (unsigned j = 0; j < num_clients; j++) {
+ if (i == clients[j]) {
+ clients[j] = clients[num_clients--];
+ break;
+ }
}
+ close(i);
+ FD_CLR(i, &active_fd_set);
+ }
}
+ }
- /* Close server */
- rc = close(fd);
- if (rc == -1) {
- perror("close");
- ret = EXIT_FAILURE;
- }
+ int ret = EXIT_SUCCESS;
- /* Terminate timer */
- ts.it_value.tv_sec = 0;
- rc = timerfd_settime(tfd, 0, &ts, NULL);
+ /* Close all active client connections */
+ for (unsigned i = 0; i < num_clients; i++) {
+ rc = close(clients[i]);
if (rc == -1) {
- perror("timerfd_settime");
- exit(EXIT_FAILURE);
+ perror("close");
+ ret = EXIT_FAILURE;
}
-
- exit(ret);
+ }
+
+ /* Close server */
+ rc = close(fd);
+ if (rc == -1) {
+ perror("close");
+ ret = EXIT_FAILURE;
+ }
+
+ /* Terminate timer */
+ ts.it_value.tv_sec = 0;
+ rc = timerfd_settime(tfd, 0, &ts, NULL);
+ if (rc == -1) {
+ perror("timerfd_settime");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(ret);
}
diff --git a/ctrl/facemgr/includes/CMakeLists.txt b/ctrl/facemgr/includes/CMakeLists.txt
index 065a9022f..bfbf65717 100644
--- a/ctrl/facemgr/includes/CMakeLists.txt
+++ b/ctrl/facemgr/includes/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,15 +11,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# XXX
-
+##############################################################
+# Public headers directory
+##############################################################
set(LIBFACEMGR_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR} ""
+ ${CMAKE_CURRENT_SOURCE_DIR}
CACHE INTERNAL
"" FORCE
)
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+
+##############################################################
+# To install header files
+##############################################################
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h
@@ -28,9 +33,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/loop.h
PARENT_SCOPE
)
-
else ()
-
set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h
@@ -39,7 +42,4 @@ else ()
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/loop.h
PARENT_SCOPE
)
-
endif ()
-
-
diff --git a/ctrl/facemgr/includes/facemgr.h b/ctrl/facemgr/includes/facemgr.h
index b3b482ccc..b62bb88ce 100644
--- a/ctrl/facemgr/includes/facemgr.h
+++ b/ctrl/facemgr/includes/facemgr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,4 +26,3 @@
#include <hicn/facemgr/loop.h>
#endif /* HICN_FACEMGR_H */
-
diff --git a/ctrl/facemgr/includes/hicn/facemgr.h b/ctrl/facemgr/includes/hicn/facemgr.h
index 4165a8fc4..83a76cc08 100644
--- a/ctrl/facemgr/includes/hicn/facemgr.h
+++ b/ctrl/facemgr/includes/hicn/facemgr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,4 +24,3 @@
#include <hicn/facemgr/api.h>
#endif /* HICN_FACEMGR_H */
-
diff --git a/ctrl/facemgr/includes/hicn/facemgr/api.h b/ctrl/facemgr/includes/hicn/facemgr/api.h
index e9d25f132..3fe049c06 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/api.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -30,40 +30,38 @@
/* facemgr callbacks */
typedef enum {
- FACEMGR_CB_TYPE_REGISTER_FD,
- FACEMGR_CB_TYPE_UNREGISTER_FD,
- FACEMGR_CB_TYPE_REGISTER_TIMER,
- FACEMGR_CB_TYPE_UNREGISTER_TIMER,
+ FACEMGR_CB_TYPE_REGISTER_FD,
+ FACEMGR_CB_TYPE_UNREGISTER_FD,
+ FACEMGR_CB_TYPE_REGISTER_TIMER,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER,
} facemgr_cb_type_t;
-typedef int (*facemgr_cb_t)(void * loop, facemgr_cb_type_t type, void * data);
-
+typedef int (*facemgr_cb_t)(void *loop, facemgr_cb_type_t type, void *data);
/*
* \brief Manual overlay settings (alternative to service discovery)
*/
typedef struct {
- uint16_t local_port;
- ip_address_t remote_addr;
- uint16_t remote_port;
+ uint16_t local_port;
+ ip_address_t remote_addr;
+ uint16_t remote_port;
} facemgr_overlay_setting_t;
-#define FACEMGR_OVERLAY_SETTING_EMPTY (facemgr_overlay_setting_t) { \
- .local_port = 0, \
- .remote_addr = IP_ADDRESS_EMPTY, \
- .remote_port = 0, \
-}
+#define FACEMGR_OVERLAY_SETTING_EMPTY \
+ (facemgr_overlay_setting_t) { \
+ .local_port = 0, .remote_addr = IP_ADDRESS_EMPTY, .remote_port = 0, \
+ }
typedef struct {
- facemgr_overlay_setting_t v4;
- facemgr_overlay_setting_t v6;
+ facemgr_overlay_setting_t v4;
+ facemgr_overlay_setting_t v6;
} facemgr_overlay_t;
-#define FACEMGR_OVERLAY_EMPTY (facemgr_overlay_t) { \
- .v4 = FACEMGR_OVERLAY_SETTING_EMPTY, \
- .v6 = FACEMGR_OVERLAY_SETTING_EMPTY, \
-}
+#define FACEMGR_OVERLAY_EMPTY \
+ (facemgr_overlay_t) { \
+ .v4 = FACEMGR_OVERLAY_SETTING_EMPTY, .v6 = FACEMGR_OVERLAY_SETTING_EMPTY, \
+ }
/*
* \brief Face manager context
@@ -72,24 +70,30 @@ typedef struct facemgr_s facemgr_t;
int facemgr_initialize(facemgr_t *);
int facemgr_finalize(facemgr_t *);
-facemgr_t * facemgr_create();
-facemgr_t * facemgr_create_with_config(facemgr_cfg_t * cfg);
+facemgr_t *facemgr_create();
+facemgr_t *facemgr_create_with_config(facemgr_cfg_t *cfg);
void facemgr_stop(facemgr_t *);
void facemgr_free(facemgr_t *);
+void facemgr_set_callback(facemgr_t *facemgr, void *callback_owner,
+ facemgr_cb_t callback);
-void facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t callback);
-
-int facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg);
-int facemgr_reset_config(facemgr_t * facemgr);
-int facemgr_bootstrap(facemgr_t * facemgr);
+int facemgr_set_config(facemgr_t *facemgr, facemgr_cfg_t *cfg);
+int facemgr_reset_config(facemgr_t *facemgr);
+int facemgr_bootstrap(facemgr_t *facemgr);
#ifdef __ANDROID__
-void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm);
+void facemgr_set_jvm(facemgr_t *facemgr, JavaVM *jvm);
+void facemgr_on_android_callback(facemgr_t *facemgr, const char *interface_name,
+ netdevice_type_t netdevice_type, bool up,
+ int family, const char *ip_address);
#endif /* __ANDROID__ */
-typedef int (*facemgr_list_facelets_cb_t)(const facemgr_t * facemgr, const facelet_t * facelet, void * user_data);
+typedef int (*facemgr_list_facelets_cb_t)(const facemgr_t *facemgr,
+ const facelet_t *facelet,
+ void *user_data);
-void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t cb, void * user_data);
-int facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer);
+void facemgr_list_facelets(const facemgr_t *facemgr,
+ facemgr_list_facelets_cb_t cb, void *user_data);
+int facemgr_list_facelets_json(const facemgr_t *facemgr, char **buffer);
#endif /* FACEMGR_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
index 84d63fe73..fee38daf1 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,7 +20,7 @@
#ifndef FACEMGR_CFG_H
#define FACEMGR_CFG_H
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/facemgr/facelet.h>
#include <hicn/util/log.h>
@@ -38,68 +38,70 @@
#define FACEMGR_CFG_DEFAULT_IPV4 true
#define FACEMGR_CFG_DEFAULT_IPV6 false
-
-
typedef struct facemgr_cfg_s facemgr_cfg_t;
-facemgr_cfg_t * facemgr_cfg_create();
-void facemgr_cfg_free(facemgr_cfg_t * cfg);
-int facemgr_cfg_initialize(facemgr_cfg_t * cfg);
-int facemgr_cfg_finalize(facemgr_cfg_t * cfg);
-void facemgr_cfg_dump(facemgr_cfg_t * cfg);
+facemgr_cfg_t* facemgr_cfg_create();
+void facemgr_cfg_free(facemgr_cfg_t* cfg);
+int facemgr_cfg_initialize(facemgr_cfg_t* cfg);
+int facemgr_cfg_finalize(facemgr_cfg_t* cfg);
+void facemgr_cfg_dump(facemgr_cfg_t* cfg);
/* Rules */
typedef struct facemgr_cfg_rule_s facemgr_cfg_rule_t;
-facemgr_cfg_rule_t * facemgr_cfg_rule_create();
-void facemgr_cfg_rule_free(facemgr_cfg_rule_t * rule);
-int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t * rule);
-int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t * rule);
+facemgr_cfg_rule_t* facemgr_cfg_rule_create();
+void facemgr_cfg_rule_free(facemgr_cfg_rule_t* rule);
+int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t* rule);
+int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t* rule);
-int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t * rule,
- const char * interface_name, netdevice_type_t interface_type);
+int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t* rule,
+ const char* interface_name,
+ netdevice_type_t interface_type);
-int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t * cfg_rule, facemgr_face_type_t * face_type);
-int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t * cfg_rule);
+int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t* cfg_rule,
+ facemgr_face_type_t* face_type);
+int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t* cfg_rule);
-int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t * cfg_rule, bool status);
-int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t * cfg_rule);
+int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t* cfg_rule, bool status);
+int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t* cfg_rule);
-int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t * cfg_rule, bool status);
-int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t * cfg_rule);
+int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t* cfg_rule, bool status);
+int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t* cfg_rule);
-int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t * cfg_rule, bool status);
-int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t * cfg_rule);
+int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t* cfg_rule, bool status);
+int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t* cfg_rule);
-int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t * cfg_rule, bool status);
-int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t * cfg_rule);
+int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t* cfg_rule, bool status);
+int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t* cfg_rule);
-int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t * rule, int family,
- ip_address_t * local_addr, uint16_t local_port,
- ip_address_t * remote_addr, uint16_t remote_port);
-int facemgr_rule_unset_overlay(facemgr_cfg_rule_t * rule, int family);
+int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t* rule, int family,
+ ip_address_t* local_addr, uint16_t local_port,
+ ip_address_t* remote_addr,
+ uint16_t remote_port);
+int facemgr_rule_unset_overlay(facemgr_cfg_rule_t* rule, int family);
/* General */
-int facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_type);
-int facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg);
-int facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status);
-int facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg);
-int facemgr_cfg_set_ipv4(facemgr_cfg_t * cfg, bool status);
-int facemgr_cfg_unset_ipv4(facemgr_cfg_t * cfg);
-int facemgr_cfg_set_ipv6(facemgr_cfg_t * cfg, bool status);
-int facemgr_cfg_unset_ipv6(facemgr_cfg_t * cfg);
-
-int facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family,
- ip_address_t * local_addr, uint16_t local_port,
- ip_address_t * remote_addr, uint16_t remote_port);
-int facemgr_cfg_unset_overlay(facemgr_cfg_t * cfg, int family);
-
-
-int facemgr_cfg_add_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule);
-int facemgr_cfg_del_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule);
-int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name,
- netdevice_type_t interface_type, facemgr_cfg_rule_t ** rule);
+int facemgr_cfg_set_face_type(facemgr_cfg_t* cfg,
+ facemgr_face_type_t* face_type);
+int facemgr_cfg_unset_face_type(facemgr_cfg_t* cfg);
+int facemgr_cfg_set_discovery(facemgr_cfg_t* cfg, bool status);
+int facemgr_cfg_unset_discovery(facemgr_cfg_t* cfg);
+int facemgr_cfg_set_ipv4(facemgr_cfg_t* cfg, bool status);
+int facemgr_cfg_unset_ipv4(facemgr_cfg_t* cfg);
+int facemgr_cfg_set_ipv6(facemgr_cfg_t* cfg, bool status);
+int facemgr_cfg_unset_ipv6(facemgr_cfg_t* cfg);
+
+int facemgr_cfg_set_overlay(facemgr_cfg_t* cfg, int family,
+ ip_address_t* local_addr, uint16_t local_port,
+ ip_address_t* remote_addr, uint16_t remote_port);
+int facemgr_cfg_unset_overlay(facemgr_cfg_t* cfg, int family);
+
+int facemgr_cfg_add_rule(facemgr_cfg_t* cfg, facemgr_cfg_rule_t* rule);
+int facemgr_cfg_del_rule(facemgr_cfg_t* cfg, facemgr_cfg_rule_t* rule);
+int facemgr_cfg_get_rule(const facemgr_cfg_t* cfg, const char* interface_name,
+ netdevice_type_t interface_type,
+ facemgr_cfg_rule_t** rule);
/* Log */
@@ -107,57 +109,63 @@ int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name,
* Query API
*
* Takes the overrides into account
- *
- * TODO : interface_types are currently not taken into account by this API
*/
-int facemgr_cfg_get_face_type(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- facemgr_face_type_t * face_type);
-int facemgr_cfg_get_discovery(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * discovery);
-int facemgr_cfg_get_ignore(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * ignore);
-int facemgr_cfg_get_ipv4(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * ipv4);
-int facemgr_cfg_get_ipv6(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * ipv6);
-int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, ip_address_t * addr);
-int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, u16 * port);
-int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, ip_address_t * addr);
-int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, u16 * port);
-
-int facemgr_cfg_rule_get(const facemgr_cfg_t * cfg, const netdevice_t netdevice,
- netdevice_type_t netdevice_type, facemgr_cfg_rule_t ** rule);
-int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t * cfg_rule, facemgr_face_type_t * face_type);
-int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t * cfg_rule, bool * status);
-int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t * cfg_rule, bool * status);
-int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t * cfg_rule, bool * status);
-int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t * cfg_rule, bool * status);
-int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t * rule, int family,
- ip_address_t * addr);
-int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t * rule, int family,
- uint16_t * port);
-int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t * rule, int family,
- ip_address_t * addr);
-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);
+int facemgr_cfg_get_face_type(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type,
+ facemgr_face_type_t* face_type);
+int facemgr_cfg_get_discovery(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type, bool* discovery);
+int facemgr_cfg_get_ignore(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type, bool* ignore);
+int facemgr_cfg_get_ipv4(const facemgr_cfg_t* cfg, const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type, bool* ipv4);
+int facemgr_cfg_get_ipv6(const facemgr_cfg_t* cfg, const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type, bool* ipv6);
+int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type,
+ int family, ip_address_t* addr);
+int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type,
+ int family, u16* port);
+int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type,
+ int family, ip_address_t* addr);
+int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t* cfg,
+ const netdevice_t* netdevice,
+ netdevice_type_t netdevice_type,
+ int family, u16* port);
+
+int facemgr_cfg_rule_get(const facemgr_cfg_t* cfg, const netdevice_t netdevice,
+ netdevice_type_t netdevice_type,
+ facemgr_cfg_rule_t** rule);
+int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t* cfg_rule,
+ facemgr_face_type_t* face_type);
+int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t* cfg_rule,
+ bool* status);
+int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t* cfg_rule,
+ bool* status);
+int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t* cfg_rule, bool* status);
+int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t* cfg_rule, bool* status);
+int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t* rule,
+ int family, ip_address_t* addr);
+int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t* rule,
+ int family, uint16_t* port);
+int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t* rule,
+ int family, ip_address_t* addr);
+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);
#endif /* FACEMGR_CFG_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
index cfdc5540e..d9c986731 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -28,7 +28,7 @@
#include <stdbool.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/ctrl/route.h>
#define MAXSZ_FACELET 1024
@@ -36,111 +36,111 @@
#define FACELET_MAX_ERRORS 10
/* NOTE: Any test should be sufficient */
-#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0'))
+#define IS_VALID_NETDEVICE(netdevice) \
+ ((netdevice.index != 0) && (netdevice.name[0] != '\0'))
typedef struct facelet_s facelet_t;
/* Face type */
#define foreach_face_type_layer \
- _(UNDEFINED) \
- _(3) \
- _(4) \
- _(N)
+ _(UNDEFINED) \
+ _(3) \
+ _(4) \
+ _(N)
typedef enum {
-#define _(x) FACE_TYPE_LAYER_ ## x,
- foreach_face_type_layer
+#define _(x) FACE_TYPE_LAYER_##x,
+ foreach_face_type_layer
#undef _
} face_type_layer_t;
#define foreach_face_type_encap \
- _(UNDEFINED) \
- _(TCP) \
- _(UDP) \
- _(N)
+ _(UNDEFINED) \
+ _(TCP) \
+ _(UDP) \
+ _(N)
typedef enum {
-#define _(x) FACE_TYPE_ENCAP_ ## x,
- foreach_face_type_encap
+#define _(x) FACE_TYPE_ENCAP_##x,
+ foreach_face_type_encap
#undef _
} face_type_encap_t;
typedef struct {
- face_type_layer_t layer;
- face_type_encap_t encap;
+ face_type_layer_t layer;
+ face_type_encap_t encap;
} facemgr_face_type_t;
+extern const char* face_type_layer_str[];
+extern const char* face_type_encap_str[];
-extern const char * face_type_layer_str[];
-extern const char * face_type_encap_str[];
+#define FACEMGR_FACE_TYPE_STR(x) \
+ face_type_layer_str[x.layer], face_type_encap_str[x.encap]
-#define FACEMGR_FACE_TYPE_STR(x) \
- face_type_layer_str[x.layer], face_type_encap_str[x.encap]
+#define FACEMGR_FACE_TYPE_UNDEFINED \
+ (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_UNDEFINED, .encap = FACE_TYPE_ENCAP_UNDEFINED, \
+ }
-#define FACEMGR_FACE_TYPE_UNDEFINED (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_UNDEFINED, \
- .encap = FACE_TYPE_ENCAP_UNDEFINED, \
-}
+#define FACEMGR_FACE_TYPE_NATIVE_UDP \
+ (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_3, .encap = FACE_TYPE_ENCAP_UDP, \
+ }
-#define FACEMGR_FACE_TYPE_NATIVE_UDP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_3, \
- .encap = FACE_TYPE_ENCAP_UDP, \
-}
+#define FACEMGR_FACE_TYPE_NATIVE_TCP \
+ (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_3, .encap = FACE_TYPE_ENCAP_TCP, \
+ }
-#define FACEMGR_FACE_TYPE_NATIVE_TCP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_3, \
- .encap = FACE_TYPE_ENCAP_TCP, \
-}
+#define FACEMGR_FACE_TYPE_OVERLAY_UDP \
+ (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_4, .encap = FACE_TYPE_ENCAP_UDP, \
+ }
-#define FACEMGR_FACE_TYPE_OVERLAY_UDP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_4, \
- .encap = FACE_TYPE_ENCAP_UDP, \
-}
-
-#define FACEMGR_FACE_TYPE_OVERLAY_TCP (facemgr_face_type_t) { \
- .layer = FACE_TYPE_LAYER_4, \
- .encap = FACE_TYPE_ENCAP_TCP, \
-}
+#define FACEMGR_FACE_TYPE_OVERLAY_TCP \
+ (facemgr_face_type_t) { \
+ .layer = FACE_TYPE_LAYER_4, .encap = FACE_TYPE_ENCAP_TCP, \
+ }
/* Facelet status */
-#define foreach_facelet_status \
- _(UNDEFINED) \
- _(DOWN) \
- _(UNCERTAIN) \
- _(INCOMPLETE) \
- _(CREATE) \
- _(CLEAN) \
- _(IGNORED) \
- _(UPDATE) \
- _(DELETE) \
- _(DELETED) \
- _(N)
+#define foreach_facelet_status \
+ _(UNDEFINED) \
+ _(DOWN) \
+ _(UNCERTAIN) \
+ _(INCOMPLETE) \
+ _(CREATE) \
+ _(CLEAN) \
+ _(IGNORED) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(DELETED) \
+ _(N)
typedef enum {
-#define _(x) FACELET_STATUS_ ## x,
- foreach_facelet_status
+#define _(x) FACELET_STATUS_##x,
+ foreach_facelet_status
#undef _
} facelet_status_t;
-extern const char * facelet_status_str[];
+extern const char* facelet_status_str[];
/* Facelet error reason */
-#define foreach_facelet_error_reason \
- _(UNDEFINED) \
- _(UNSPECIFIED_ERROR) \
- _(FORWARDER_OFFLINE) \
- _(PERMISSION_DENIED) \
- _(INTERNAL_ERROR) \
- _(N)
+#define foreach_facelet_error_reason \
+ _(UNDEFINED) \
+ _(UNSPECIFIED_ERROR) \
+ _(FORWARDER_OFFLINE) \
+ _(PERMISSION_DENIED) \
+ _(INTERNAL_ERROR) \
+ _(N)
typedef enum {
-#define _(x) FACELET_ERROR_REASON_ ## x,
- foreach_facelet_error_reason
+#define _(x) FACELET_ERROR_REASON_##x,
+ foreach_facelet_error_reason
#undef _
} facelet_error_reason_t;
-extern const char * facelet_error_reason_str[];
+extern const char* facelet_error_reason_str[];
/* Facelet attribute status */
@@ -148,62 +148,62 @@ extern const char * facelet_error_reason_str[];
* We expect an attribute in the cache to be able to take any value but
* UNDEFINED and N, which facelet events should either be UNSET or CLEAN
*/
-#define foreach_facelet_attr_status \
- _(UNDEFINED, '?') \
- _(UNSET, 'X') \
- _(CLEAN, ' ') \
- _(DIRTY, '*') \
- _(PENDING, 'P') \
- _(CONFLICT, '!') \
- _(N, '-')
+#define foreach_facelet_attr_status \
+ _(UNDEFINED, '?') \
+ _(UNSET, 'X') \
+ _(CLEAN, ' ') \
+ _(DIRTY, '*') \
+ _(PENDING, 'P') \
+ _(CONFLICT, '!') \
+ _(N, '-')
typedef enum {
-#define _(x, y) FACELET_ATTR_STATUS_ ## x,
- foreach_facelet_attr_status
+#define _(x, y) FACELET_ATTR_STATUS_##x,
+ foreach_facelet_attr_status
#undef _
} facelet_attr_status_t;
-extern const char * facelet_attr_status_str[];
-extern const char * facelet_attr_status_str_short[];
+extern const char* facelet_attr_status_str[];
+extern const char* facelet_attr_status_str_short[];
/* Facelet attribute */
#ifdef WITH_POLICY
-#define foreach_facelet_attr \
- _(netdevice_type_t, netdevice_type) \
- _(netdevice_t, netdevice) \
- _(int, family) \
- _(ip_address_t, local_addr) \
- _(u16, local_port) \
- _(ip_address_t, remote_addr) \
- _(u16, remote_port) \
- _(face_state_t, admin_state) \
- _(face_state_t, state) \
- _(u32, priority) \
- _(facemgr_face_type_t, face_type)
+#define foreach_facelet_attr \
+ _(netdevice_type_t, netdevice_type) \
+ _(netdevice_t, netdevice) \
+ _(int, family) \
+ _(ip_address_t, local_addr) \
+ _(u16, local_port) \
+ _(ip_address_t, remote_addr) \
+ _(u16, remote_port) \
+ _(face_state_t, admin_state) \
+ _(face_state_t, state) \
+ _(u32, priority) \
+ _(facemgr_face_type_t, face_type)
#else
-#define foreach_facelet_attr \
- _(netdevice_type_t, netdevice_type) \
- _(netdevice_t, netdevice) \
- _(int, family) \
- _(ip_address_t, local_addr) \
- _(u16, local_port) \
- _(ip_address_t, remote_addr) \
- _(u16, remote_port) \
- _(face_state_t, admin_state) \
- _(face_state_t, state) \
- _(facemgr_face_type_t, face_type)
+#define foreach_facelet_attr \
+ _(netdevice_type_t, netdevice_type) \
+ _(netdevice_t, netdevice) \
+ _(int, family) \
+ _(ip_address_t, local_addr) \
+ _(u16, local_port) \
+ _(ip_address_t, remote_addr) \
+ _(u16, remote_port) \
+ _(face_state_t, admin_state) \
+ _(face_state_t, state) \
+ _(facemgr_face_type_t, face_type)
#endif /* WITH_POLICY */
-#define foreach_facelet_event \
- _(UNDEFINED) \
- _(GET) \
- _(CREATE) \
- _(UPDATE) \
- _(DELETE) \
- _(SET_UP) \
- _(SET_DOWN) \
- _(N)
+#define foreach_facelet_event \
+ _(UNDEFINED) \
+ _(GET) \
+ _(CREATE) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(SET_UP) \
+ _(SET_DOWN) \
+ _(N)
#define MAXSZ_EVENT__ 10
#define MAXSZ_EVENT_ MAXSZ_EVENT_ + 1
@@ -212,37 +212,37 @@ extern const char * facelet_attr_status_str_short[];
* \brief Enumeration of the possible types of event
*/
typedef enum {
-#define _(x) FACELET_EVENT_ ## x,
-foreach_facelet_event
+#define _(x) FACELET_EVENT_##x,
+ foreach_facelet_event
#undef _
} facelet_event_t;
-extern const char * facelet_event_str[];
+extern const char* facelet_event_str[];
/**
* \brief Create a facelet.
*/
-facelet_t * facelet_create();
+facelet_t* facelet_create();
-facelet_t * facelet_create_from_netdevice(netdevice_t * netdevice);
+facelet_t* facelet_create_from_netdevice(netdevice_t* netdevice);
-unsigned facelet_get_id(facelet_t * facelet);
-void facelet_set_id(facelet_t * facelet, unsigned id);
+unsigned facelet_get_id(facelet_t* facelet);
+void facelet_set_id(facelet_t* facelet, unsigned id);
-int facelet_validate_face(const facelet_t * facelet);
+int facelet_validate_face(const facelet_t* facelet);
-facelet_t * facelet_create_from_face(face_t * face);
+facelet_t* facelet_create_from_face(face_t* face);
-void facelet_free(facelet_t * facelet);
+void facelet_free(facelet_t* facelet);
-facelet_t * facelet_dup(const facelet_t * current_facelet);
+facelet_t* facelet_dup(const facelet_t* current_facelet);
-int facelet_cmp(const facelet_t * f1, const facelet_t * f2);
+int facelet_cmp(const facelet_t* f1, const facelet_t* f2);
-bool facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2);
+bool facelet_equals(const facelet_t* facelet1, const facelet_t* facelet2);
/* NOTE: only clean attributes are matched */
-bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match);
+bool facelet_match(const facelet_t* facelet, const facelet_t* facelet_match);
/**
* \brief Returns whether the specified facelet has all key attributes defined.
@@ -251,55 +251,58 @@ bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match);
* uniquely identify a facelet, otherwise it is a 'wildcard' facelet
* specification and might match several facelets.
*/
-bool facelet_has_key(const facelet_t * facelet);
+bool facelet_has_key(const facelet_t* facelet);
-#define FACELET_ACCESSORS_H(TYPE, NAME) \
-bool facelet_has_ ## NAME(const facelet_t * facelet); \
-facelet_attr_status_t facelet_get_ ## NAME ## _status(const facelet_t * facelet);\
-void facelet_set_ ## NAME ## _status(facelet_t * facelet, \
- facelet_attr_status_t status); \
-int facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME); \
-int facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME); \
-int facelet_unset_ ## NAME(facelet_t * facelet);
+#define FACELET_ACCESSORS_H(TYPE, NAME) \
+ bool facelet_has_##NAME(const facelet_t* facelet); \
+ facelet_attr_status_t facelet_get_##NAME##_status(const facelet_t* facelet); \
+ void facelet_set_##NAME##_status(facelet_t* facelet, \
+ facelet_attr_status_t status); \
+ int facelet_get_##NAME(const facelet_t* facelet, TYPE* NAME); \
+ int facelet_set_##NAME(facelet_t* facelet, TYPE NAME); \
+ int facelet_unset_##NAME(facelet_t* facelet);
#define _(TYPE, NAME) FACELET_ACCESSORS_H(TYPE, NAME)
foreach_facelet_attr
#undef _
-int facelet_get_face(const facelet_t * facelet, face_t ** pface);
+ int
+ facelet_get_face(const facelet_t* facelet, face_t** pface);
-int facelet_merge(facelet_t * facelet, facelet_t * facelet_to_merge);
+int facelet_merge(facelet_t* facelet, facelet_t* facelet_to_merge);
-facelet_status_t facelet_get_status(const facelet_t * facelet);
-void facelet_set_status(facelet_t * facelet, facelet_status_t status);
-void facelet_set_attr_clean(facelet_t * facelet);
+facelet_status_t facelet_get_status(const facelet_t* facelet);
+void facelet_set_status(facelet_t* facelet, facelet_status_t status);
+void facelet_set_attr_clean(facelet_t* facelet);
-void facelet_set_error(facelet_t * facelet, facelet_error_reason_t reason);
-void facelet_unset_error(facelet_t * facelet);
-bool facelet_get_error(const facelet_t * facelet);
+void facelet_set_error(facelet_t* facelet, facelet_error_reason_t reason);
+void facelet_unset_error(facelet_t* facelet);
+bool facelet_get_error(const facelet_t* facelet);
-void facelet_set_bj_done(facelet_t * facelet);
-void facelet_unset_bj_done(facelet_t * facelet);
-bool facelet_is_bj_done(const facelet_t * facelet);
-void facelet_set_au_done(facelet_t * facelet);
-bool facelet_is_au_done(const facelet_t * facelet);
+void facelet_set_bj_done(facelet_t* facelet);
+void facelet_unset_bj_done(facelet_t* facelet);
+bool facelet_is_bj_done(const facelet_t* facelet);
-facelet_event_t facelet_get_event(const facelet_t * facelet);
-void facelet_set_event(facelet_t * facelet, facelet_event_t event);
+facelet_event_t facelet_get_event(const facelet_t* facelet);
+void facelet_set_event(facelet_t* facelet, facelet_event_t event);
-int facelet_add_route(facelet_t * facelet, hicn_route_t * route);
-int facelet_remove_route(facelet_t * facelet, hicn_route_t * route, hicn_route_t ** route_removed);
-int facelet_clear_routes(facelet_t * facelet);
-int facelet_get_route_array(const facelet_t * facelet, hicn_route_t *** route_array);
+int facelet_add_route(facelet_t* facelet, hicn_route_t* route);
+int facelet_remove_route(facelet_t* facelet, hicn_route_t* route,
+ hicn_route_t** route_removed);
+int facelet_clear_routes(facelet_t* facelet);
+int facelet_get_route_array(const facelet_t* facelet,
+ hicn_route_t*** route_array);
-int facelet_snprintf(char * buf, size_t size, const facelet_t * facelet);
+int facelet_snprintf(char* buf, size_t size, const facelet_t* facelet);
-#define DUMP_FACELET(msg, facelet) do { \
- char buf[MAXSZ_FACELET]; \
- facelet_snprintf(buf, MAXSZ_FACELET, facelet); \
- DEBUG("%s : %s", msg, buf); \
-} while(0)
+#define DUMP_FACELET(msg, facelet) \
+ do { \
+ char buf[MAXSZ_FACELET]; \
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet); \
+ DEBUG("%s : %s", msg, buf); \
+ } while (0)
-int facelet_snprintf_json(char * buf, size_t size, const facelet_t * facelet, int indent);
+int facelet_snprintf_json(char* buf, size_t size, const facelet_t* facelet,
+ int indent);
#endif /* FACEMGR_FACELET_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/loop.h b/ctrl/facemgr/includes/hicn/facemgr/loop.h
index 752a3b365..3965a1f27 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/loop.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/loop.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,23 +25,21 @@
/* fd & timer callbacks */
-typedef int (*fd_callback_t)(void * owner, int fd, void * data);
+typedef int (*fd_callback_t)(void *owner, int fd, void *data);
typedef struct {
- int fd;
- void *owner;
- fd_callback_t callback;
- //int (*callback)(void * owner, int fd, void * data);
- void *data;
+ int fd;
+ void *owner;
+ fd_callback_t callback;
+ void *data;
} fd_callback_data_t;
/* timer callbacks */
typedef struct {
- unsigned delay_ms;
- void *owner;
- fd_callback_t callback;
- //int (*callback)(void * owner, int fd, void * data);
- void *data;
+ unsigned delay_ms;
+ void *owner;
+ fd_callback_t callback;
+ void *data;
} timer_callback_data_t;
/* loop */
@@ -52,33 +50,32 @@ typedef struct loop_s loop_t;
* \brief Creates a main loop
* \return Pointer to the newly created loop, or NULL in case of error
*/
-loop_t * loop_create();
+loop_t *loop_create();
/**
* \brief Releases a loop instance and frees all associated memory
* \param [in] loop - Pointer to the loop instance to free
*/
-void loop_free(loop_t * loop);
+void loop_free(loop_t *loop);
/**
* \brief Runs the loop instance to process events
* \param [in] loop - Pointer to the loop instance
* \return 0 if successful, -1 otherwise
*/
-int loop_dispatch(loop_t * loop);
+int loop_dispatch(loop_t *loop);
/**
* \brief Terminates the dispatching of events
* \param [in] loop - Pointer to the loop instance
*/
-int loop_undispatch(loop_t * loop);
+int loop_undispatch(loop_t *loop);
/**
* \brief Breaks out of the loop
* \param [in] loop - Pointer to the loop instance
*/
-void loop_break(loop_t * loop);
-
+void loop_break(loop_t *loop);
/**
* \brief Callback for loop helpers
@@ -86,6 +83,6 @@ void loop_break(loop_t * loop);
* \param [in] type - Type of service to be requested
* \param [in] data - Service specific data
*/
-int loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data);
+int loop_callback(loop_t *loop, facemgr_cb_type_t type, void *data);
#endif /* FACEMGR_LOOP_H */
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index cf5606e04..87938fb57 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,130 +12,157 @@
# limitations under the License.
if(UNIX AND NOT APPLE)
- set(LINUX TRUE)
+ set(LINUX TRUE)
endif()
-set(COMPILER_DEFINITIONS
- "-DWITH_POLICY"
-)
+##############################################################
+# Sources
+##############################################################
set(HEADER_FILES
- common.h
- error.h
- facelet_array.h
- interface.h
- loop.h
+ common.h
+ error.h
+ facelet_array.h
+ interface.h
+ loop.h
)
set(SOURCE_FILES
- api.c
- cfg.c
- cfg_file.c
- error.c
- facelet.c
- facelet_array.c
- interface.c
+ api.c
+ cfg.c
+ cfg_file.c
+ error.c
+ facelet.c
+ facelet_array.c
+ interface.c
)
if(APPLE)
-set(SOURCE_FILES
+ set(SOURCE_FILES
${SOURCE_FILES}
loop_dispatcher.c
-)
+ )
endif()
if (LINUX)
-set(SOURCE_FILES
+ set(SOURCE_FILES
${SOURCE_FILES}
loop_libevent.c
-)
+ )
endif()
+add_subdirectory(interfaces)
+
+
+##############################################################
+# Include directories
+##############################################################
set(INCLUDE_DIRS
- ./
- ../includes/
- ${HICN_INCLUDE_DIRS}
- ${LIBHICNCTRL_INCLUDE_DIRS}
- ${CONFIG_INCLUDE_DIR}
- ${LIBEVENT_INCLUDE_DIR}
+ PRIVATE ./
+ PRIVATE ${CONFIG_INCLUDE_DIR}
+ PRIVATE ${LIBEVENT_INCLUDE_DIR}
+ PUBLIC
+ $<BUILD_INTERFACE:${LIBFACEMGR_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
+
+##############################################################
+# Libraries to link
+##############################################################
set(LIBRARIES
- m
- ${HICN_LIBRARIES}
- ${LIBHICNCTRL_LIBRARIES}
- ${LIBCONFIG_LIBRARIES}
- ${LIBEVENT_LIBRARY}
+ PUBLIC ${HICN_LIBRARIES}
+ PUBLIC ${LIBHICNCTRL_LIBRARIES}
+ PRIVATE m
+ PRIVATE ${LIBCONFIG_LIBRARIES}
+ PRIVATE ${LIBEVENT_LIBRARY}
)
-set(FACEMGR_LIBRARY_LIST "${LIBCONFIG_LIBRARIES};${LIBEVENT_LIBRARY}" CACHE INTERNAL "FACEMGR_LIBRARY_LIST")
+if(WITH_THREAD)
+ set(LIBRARIES
+ ${LIBRARIES}
+ "pthread"
+ "event_pthreads"
+ )
+ set(COMPILER_DEFINITIONS
+ ${COMPILER_DEFINITIONS}
+ "-DWITH_THREAD"
+ )
+endif()
-add_subdirectory(interfaces)
+##############################################################
+# Compiler definitions
+##############################################################
if(WITH_THREAD)
- set(LIBRARIES
- ${LIBRARIES}
- "pthread"
- "event_pthreads"
- )
- set(COMPILER_DEFINITIONS
- ${COMPILER_DEFINITIONS}
- "-DWITH_THREAD"
- )
+ list(APPEND COMPILER_DEFINITIONS
+ "-DWITH_THREAD"
+ )
endif()
if(WITH_EXAMPLE_DUMMY)
- set(COMPILER_DEFINITIONS
- ${COMPILER_DEFINITIONS}
- "-DWITH_EXAMPLE_DUMMY"
- )
+ list(APPEND COMPILER_DEFINITIONS
+ "-DWITH_EXAMPLE_DUMMY"
+ )
endif()
if(WITH_EXAMPLE_UPDOWN)
- set(COMPILER_DEFINITIONS
- ${COMPILER_DEFINITIONS}
- "-DWITH_EXAMPLE_UPDOWN"
- )
+ list(APPEND COMPILER_DEFINITIONS
+ "-DWITH_EXAMPLE_UPDOWN"
+ )
endif()
+
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build type
+##############################################################
if (DISABLE_SHARED_LIBRARIES)
- build_library(${LIBFACEMGR}
- STATIC
- SOURCES ${SOURCE_FILES}
- INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
- DEPENDS ${DEPENDENCIES}
- LINK_LIBRARIES ${LIBRARIES}
- COMPONENT ${FACEMGR}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
+ set(LINK_TYPE STATIC)
else ()
- build_library(${LIBFACEMGR}
- SHARED STATIC NO_DEV
- SOURCES ${SOURCE_FILES}
- INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
- DEPENDS ${DEPENDENCIES}
- LINK_LIBRARIES ${LIBRARIES}
- COMPONENT ${FACEMGR}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
+ set(LINK_TYPE SHARED STATIC)
endif ()
+
+##############################################################
+# Build libfacemgr
+##############################################################
+build_library(${LIBFACEMGR}
+ ${LINK_TYPE}
+ SOURCES ${SOURCE_FILES}
+ INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
+ DEPENDS ${DEPENDENCIES}
+ LINK_LIBRARIES ${LIBRARIES}
+ COMPONENT ${FACEMGR}
+ INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS}
+ DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build executable
+##############################################################
if(NOT DISABLE_EXECUTABLES)
- list(APPEND DAEMON_SRC
- main.c
- )
-
- build_executable(${FACEMGR}
- SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${LIBFACEMGR}.static ${LIBRARIES}
- DEPENDS ${LIBFACEMGR}.static
- COMPONENT ${FACEMGR}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
+ list(APPEND DAEMON_SRC
+ main.c
+ )
+
+ build_executable(${FACEMGR}
+ SOURCES ${DAEMON_SRC}
+ LINK_LIBRARIES PRIVATE ${LIBFACEMGR}.static
+ DEPENDS ${LIBFACEMGR}.static
+ COMPONENT ${FACEMGR}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ )
endif ()
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index dfbd24bcb..d030abd1f 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,17 +21,9 @@
#ifdef __ANDROID__
/*
- * Use FacemgrUtility to determine interface types
- *
- * NOTE: this is currently disabled as SDK APIs do not allow to determine the
- * type of interfaces that are DOWN
- */
-//#define WITH_FACEMGR_UTILITY
-
-/*
* Use priority controller interface
*/
-#define WITH_PRIORITY_CONTROLLER
+//#define WITH_PRIORITY_CONTROLLER
/*
* Dump facelets (debug)
@@ -62,15 +54,14 @@
#ifdef __linux__
#include "interfaces/bonjour/bonjour.h"
+#ifdef __ANDROID__
+#include "interfaces/android/android.h"
+#endif /* __ANDROID__ */
#endif /* __linux__ */
-#ifdef WITH_FACEMGR_UTILITY
-#include "interfaces/android_utility/android_utility.h"
-#endif /* WITH_FACEMGR_UTILITY */
-
#include "interfaces/priority_controller/priority_controller.h"
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/facemgr/facelet.h>
#include "common.h"
#include "facelet_array.h"
@@ -84,19 +75,21 @@
#define MAX_FDS 10
typedef struct {
- interface_t * interface;
- int fds[MAX_FDS];
- size_t num_fds;
+ interface_t *interface;
+ int fds[MAX_FDS];
+ size_t num_fds;
} interface_map_data_t;
TYPEDEF_SET_H(facelet_set, facelet_t *);
TYPEDEF_SET(facelet_set, facelet_t *, facelet_cmp, facelet_snprintf);
TYPEDEF_MAP_H(interface_map, const char *, interface_map_data_t *);
-TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp, string_snprintf, generic_snprintf);
+TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp,
+ string_snprintf, generic_snprintf);
TYPEDEF_MAP_H(bonjour_map, netdevice_t *, interface_t *);
-TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, generic_snprintf, generic_snprintf);
+TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp,
+ generic_snprintf, generic_snprintf);
/* TODO automatically register interfaces */
@@ -104,12 +97,13 @@ TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, generic_sn
extern interface_ops_t network_framework_ops;
#endif
#ifdef __linux__
+#ifdef __ANDROID__
+extern interface_ops_t android_ops;
+#else
extern interface_ops_t netlink_ops;
+#endif /* __ANDROID__ */
extern interface_ops_t bonjour_ops;
#endif
-#ifdef WITH_FACEMGR_UTILITY
-extern interface_ops_t android_utility_ops;
-#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
extern interface_ops_t priority_controller_ops;
#endif
@@ -121,458 +115,421 @@ extern interface_ops_t updown_ops;
#endif
extern interface_ops_t hicn_light_ops;
-int facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet);
+int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet);
-int
-facemgr_overlay_snprintf(char * s, size_t size, const facemgr_overlay_t * overlay)
-{
- return -1;
+int facemgr_overlay_snprintf(char *s, size_t size,
+ const facemgr_overlay_t *overlay) {
+ return -1;
}
struct facemgr_s {
- /**************************************************/
- /* Configuration parameters (exposed through API) */
+ /**************************************************/
+ /* Configuration parameters (exposed through API) */
- facemgr_cfg_t * cfg;
+ facemgr_cfg_t *cfg;
#ifdef __ANDROID__
- /*
- * Those two pointers are needed to call java functions from the face
- * manager.
- */
- JavaVM *jvm;
+ /*
+ * Those two pointers are needed to call java functions from the face
+ * manager.
+ */
+ JavaVM *jvm;
#endif /* __ANDROID__ */
- /* Callback */
- facemgr_cb_t callback;
- void * callback_owner;
+ /* Callback */
+ facemgr_cb_t callback;
+ void *callback_owner;
- /****************************/
- /* Internal data structures */
+ /****************************/
+ /* Internal data structures */
- /* Map of interfaces index by name */
- interface_map_t * interface_map;
+ /* Map of interfaces index by name */
+ interface_map_t *interface_map;
- /* Faces under construction */
- facelet_set_t * facelet_cache;
+ /* Faces under construction */
+ facelet_set_t *facelet_cache;
- /* Static facelets */
- facelet_array_t * static_facelets;
+ /* Static facelets */
+ facelet_array_t *static_facelets;
#ifdef WITH_DEFAULT_PRIORITIES
- /* Default priorities */
- u32 default_priority[NETDEVICE_TYPE_N+1];
+ /* Default priorities */
+ u32 default_priority[NETDEVICE_TYPE_N + 1];
#endif /* WITH_DEFAULT_PRIORITIES */
- /********************************************************/
- /* Interfaces - Those should be fully replaced by a map */
-
- interface_t * hl;
+ /********************************************************/
+ /* Interfaces - Those should be fully replaced by a map */
-#ifdef WITH_FACEMGR_UTILITY
- interface_t * au; /* android_utility */
-#endif /* WITH_FACEMGR_UTILITY */
+ interface_t *hl;
#ifdef WITH_PRIORITY_CONTROLLER
- interface_t * pc;
+ interface_t *pc;
#endif
#ifdef __APPLE__
- interface_t * nf; /* network_framework */
-#endif /* __APPLE__ */
+ interface_t *nf; /* network_framework */
+#endif /* __APPLE__ */
#ifdef __linux__
- interface_t * nl; /* netlink */
- /*
- * We maintain a map of dynamically created bonjour interfaces, one for each
- * found netdevice
- */
- bonjour_map_t * bonjour_map;
+#ifdef __ANDROID__
+ interface_t *android;
+#else
+ interface_t *nl; /* netlink */
+#endif /* __ANDROID__ */
+ /*
+ * We maintain a map of dynamically created bonjour interfaces, one for each
+ * found netdevice
+ */
+ bonjour_map_t *bonjour_map;
#endif /* __linux__ */
#ifdef WITH_EXAMPLE_DUMMY
- interface_t * dummy;
+ interface_t *dummy;
#endif
#ifdef WITH_EXAMPLE_UPDOWN
- interface_t * updown;
+ interface_t *updown;
#endif
- int timer_fd; /* Timer used for reattempts */
+ int timer_fd; /* Timer used for reattempts */
- int cur_static_id; /* Used to distinguish static faces (pre-incremented) */
+ int cur_static_id; /* Used to distinguish static faces (pre-incremented) */
};
-int
-facemgr_initialize(facemgr_t * facemgr)
-{
- facemgr->interface_map = interface_map_create();
- if (!facemgr->interface_map) {
- ERROR("[facemgr_initialize] Error creating interface map");
- goto ERR_INTERFACE_MAP;
- }
-
- facemgr->facelet_cache = facelet_set_create();
- if (!facemgr->facelet_cache) {
- ERROR("[facemgr_initialize] Error creating interface map");
- goto ERR_FACE_CACHE_PENDING;
- }
-
- facemgr->static_facelets = facelet_array_create();
- if (!facemgr->static_facelets) {
- ERROR("[facemgr_initialize] Error creating interface map");
- goto ERR_STATIC;
- }
+int facemgr_initialize(facemgr_t *facemgr) {
+ facemgr->interface_map = interface_map_create();
+ if (!facemgr->interface_map) {
+ ERROR("[facemgr_initialize] Error creating interface map");
+ goto ERR_INTERFACE_MAP;
+ }
+
+ facemgr->facelet_cache = facelet_set_create();
+ if (!facemgr->facelet_cache) {
+ ERROR("[facemgr_initialize] Error creating interface map");
+ goto ERR_FACE_CACHE_PENDING;
+ }
+
+ facemgr->static_facelets = facelet_array_create();
+ if (!facemgr->static_facelets) {
+ ERROR("[facemgr_initialize] Error creating interface map");
+ goto ERR_STATIC;
+ }
#ifdef __linux__
- facemgr->bonjour_map = bonjour_map_create();
- if (!facemgr->bonjour_map) {
- ERROR("[facemgr_initialize] Error creating bonjour map");
- goto ERR_BJ;
- }
+ facemgr->bonjour_map = bonjour_map_create();
+ if (!facemgr->bonjour_map) {
+ ERROR("[facemgr_initialize] Error creating bonjour map");
+ goto ERR_BJ;
+ }
#endif /* __linux */
- facemgr->cfg = facemgr_cfg_create();
- if (!facemgr->cfg) {
- ERROR("[facemgr_initialize] Error creating face manager configuration");
- goto ERR_CFG;
- }
+ facemgr->cfg = facemgr_cfg_create();
+ if (!facemgr->cfg) {
+ ERROR("[facemgr_initialize] Error creating face manager configuration");
+ goto ERR_CFG;
+ }
- facemgr->timer_fd = 0;
- facemgr->cur_static_id = 0;
+ facemgr->timer_fd = 0;
+ facemgr->cur_static_id = 0;
#ifdef WITH_DEFAULT_PRIORITIES
-#define _(x) facemgr->default_priority[NETDEVICE_TYPE_ ## x] = 0;
-foreach_netdevice_type
+#define _(x) facemgr->default_priority[NETDEVICE_TYPE_##x] = 0;
+ foreach_netdevice_type
#undef _
#endif /* WITH_DEFAULT_PRIORITIES */
- return 0;
+ return 0;
ERR_CFG:
#ifdef __linux__
- bonjour_map_free(facemgr->bonjour_map);
+ bonjour_map_free(facemgr->bonjour_map);
ERR_BJ:
#endif /* __linux__ */
- facelet_array_free(facemgr->static_facelets);
+ facelet_array_free(facemgr->static_facelets);
ERR_STATIC:
- facelet_set_free(facemgr->facelet_cache);
+ facelet_set_free(facemgr->facelet_cache);
ERR_FACE_CACHE_PENDING:
- interface_map_free(facemgr->interface_map);
+ interface_map_free(facemgr->interface_map);
ERR_INTERFACE_MAP:
- return -1;
+ return -1;
}
-int
-facemgr_finalize(facemgr_t * facemgr)
-{
- int ret = 0;
- int rc;
+int facemgr_finalize(facemgr_t *facemgr) {
+ int ret = 0;
+ int rc;
- if (facemgr->timer_fd) {
- rc = facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd);
- if (rc < 0) {
- ERROR("[facemgr_finalize] Error unregistering timer");
- ret = -1;
- }
- facemgr->timer_fd = 0;
+ if (facemgr->timer_fd) {
+ rc =
+ facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd);
+ if (rc < 0) {
+ ERROR("[facemgr_finalize] Error unregistering timer");
+ ret = -1;
}
+ facemgr->timer_fd = 0;
+ }
- interface_map_free(facemgr->interface_map);
+ interface_map_free(facemgr->interface_map);
- /* Free all facelets from cache */
- facelet_t ** facelet_array;
- int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
- if (n < 0) {
- ERROR("[facemgr_finalize] Could not retrieve facelets in cache");
- } else {
- for (unsigned i = 0; i < n; i++) {
- facelet_t * facelet = facelet_array[i];
- if (facelet_set_remove(facemgr->facelet_cache, facelet, NULL)) {
- ERROR("[facemgr_finalize] Could not purge facelet from cache");
- }
- facelet_free(facelet);
- }
- free(facelet_array);
+ /* Free all facelets from cache */
+ facelet_t **facelet_array;
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_finalize] Could not retrieve facelets in cache");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t *facelet = facelet_array[i];
+ if (!facelet) continue; /* Should not occur */
+ if (facelet_set_remove(facemgr->facelet_cache, facelet, NULL)) {
+ ERROR("[facemgr_finalize] Could not purge facelet from cache");
+ }
+ facelet_free(facelet);
}
+ free(facelet_array);
+ }
- facelet_set_free(facemgr->facelet_cache);
+ facelet_set_free(facemgr->facelet_cache);
- /* Free all facelets from static array */
- for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) {
- facelet_t * facelet;
- if (facelet_array_get_index(facemgr->static_facelets, i, &facelet) < 0) {
- ERROR("[facemgr_cfg_finalize] Error getting facelet in array");
- continue;
- }
- if (facelet_array_remove_index(facemgr->static_facelets, i, NULL) < 0) {
- ERROR("[facemgr_finalize] Could not purge facelet from static array");
- }
- facelet_free(facelet);
+ /* Free all facelets from static array */
+ for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) {
+ facelet_t *facelet;
+ if (facelet_array_get_index(facemgr->static_facelets, i, &facelet) < 0) {
+ ERROR("[facemgr_cfg_finalize] Error getting facelet in array");
+ continue;
+ }
+ if (facelet_array_remove_index(facemgr->static_facelets, i, NULL) < 0) {
+ ERROR("[facemgr_finalize] Could not purge facelet from static array");
}
+ facelet_free(facelet);
+ }
- facelet_array_free(facemgr->static_facelets);
+ facelet_array_free(facemgr->static_facelets);
#ifdef __linux__
- bonjour_map_free(facemgr->bonjour_map);
+ bonjour_map_free(facemgr->bonjour_map);
#endif /* __linux__ */
- interface_unregister_all();
+ interface_unregister_all();
- return ret;
+ return ret;
}
AUTOGENERATE_CREATE_FREE(facemgr);
-int
-facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg)
-{
- if (facemgr->cfg) {
- facemgr_cfg_free(facemgr->cfg);
- }
- facemgr->cfg = cfg;
-
- /* Populate the initial list of static facelets */
- facelet_t ** facelet_array;
- int n = facemgr_cfg_get_static_facelet_array(cfg, &facelet_array);
- if (n < 0) {
- ERROR("[facemgr_finalize] Could not retrieve static facelets from cfg");
- } else {
- for (unsigned i = 0; i < n; i++) {
- facelet_t * facelet = facelet_dup(facelet_array[i]);
- facelet_set_status(facelet, FACELET_STATUS_UNDEFINED);
- facelet_set_attr_clean(facelet);
- if (facelet_array_add(facemgr->static_facelets, facelet)) {
- ERROR("[facemgr_finalize] Could not add static facelet to face manager");
- }
- }
+int facemgr_set_config(facemgr_t *facemgr, facemgr_cfg_t *cfg) {
+ if (facemgr->cfg) {
+ facemgr_cfg_free(facemgr->cfg);
+ }
+ facemgr->cfg = cfg;
+
+ /* Populate the initial list of static facelets */
+ facelet_t **facelet_array;
+ int n = facemgr_cfg_get_static_facelet_array(cfg, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_finalize] Could not retrieve static facelets from cfg");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t *facelet = facelet_dup(facelet_array[i]);
+ facelet_set_status(facelet, FACELET_STATUS_UNDEFINED);
+ facelet_set_attr_clean(facelet);
+ if (facelet_array_add(facemgr->static_facelets, facelet)) {
+ ERROR(
+ "[facemgr_finalize] Could not add static facelet to face manager");
+ }
}
+ }
- return 0;
+ return 0;
}
-int facemgr_reset_config(facemgr_t * facemgr)
-{
- assert(facemgr->cfg);
- facemgr_cfg_free(facemgr->cfg);
- facemgr->cfg = facemgr_cfg_create();
- if (!facemgr->cfg)
- return -1;
- return 0;
+int facemgr_reset_config(facemgr_t *facemgr) {
+ assert(facemgr->cfg);
+ facemgr_cfg_free(facemgr->cfg);
+ facemgr->cfg = facemgr_cfg_create();
+ if (!facemgr->cfg) return -1;
+ return 0;
}
-facemgr_t *
-facemgr_create_with_config(facemgr_cfg_t * cfg)
-{
- facemgr_t * facemgr = facemgr_create();
- if (!facemgr)
- return NULL;
- int rc = facemgr_set_config(facemgr, cfg);
- if (rc < 0) {
- free(facemgr);
- return NULL;
- }
- return facemgr;
+facemgr_t *facemgr_create_with_config(facemgr_cfg_t *cfg) {
+ facemgr_t *facemgr = facemgr_create();
+ if (!facemgr) return NULL;
+ int rc = facemgr_set_config(facemgr, cfg);
+ if (rc < 0) {
+ free(facemgr);
+ return NULL;
+ }
+ return facemgr;
}
/*
* \brief Heuristics to determine face type based on name, until a better
* solution is found
*/
-netdevice_type_t
-facemgr_get_netdevice_type(const facemgr_t * facemgr, const char * interface_name)
-{
- if (strncmp(interface_name, "lo", 2) == 0) {
- return NETDEVICE_TYPE_LOOPBACK;
- }
- if ((strncmp(interface_name, "eth", 3) == 0) ||
- (strncmp(interface_name, "en", 2) == 0)) {
- /* eth* en* enx* */
- return NETDEVICE_TYPE_WIRED;
- }
- if (strncmp(interface_name, "wl", 2) == 0) {
- /* wlan* wlp* wlx* */
- return NETDEVICE_TYPE_WIFI;
- }
- if (strncmp(interface_name, "rmnet_ipa", 9) == 0) {
- /* Qualcomm IPA driver */
- return NETDEVICE_TYPE_UNDEFINED;
- }
- if ((strncmp(interface_name, "rmnet", 5) == 0) ||
- (strncmp(interface_name, "rev_rmnet", 9) == 0) ||
- (strncmp(interface_name, "ccmni", 5) == 0)) {
- /*
- * rmnet* (Qualcomm) ccmni* (MediaTek)
- */
- return NETDEVICE_TYPE_CELLULAR;
- }
- /* usb0 might be cellular (eg Zenfone2) */
- /* what about tethering */
- /* tun* dummy* ... */
- /* bnet* pan* hci* for bluetooth */
+netdevice_type_t facemgr_get_netdevice_type(const facemgr_t *facemgr,
+ const char *interface_name) {
+ if (strncmp(interface_name, "lo", 2) == 0) {
+ return NETDEVICE_TYPE_LOOPBACK;
+ }
+ if ((strncmp(interface_name, "eth", 3) == 0) ||
+ (strncmp(interface_name, "en", 2) == 0)) {
+ /* eth* en* enx* */
+ return NETDEVICE_TYPE_WIRED;
+ }
+ if (strncmp(interface_name, "wl", 2) == 0) {
+ /* wlan* wlp* wlx* */
+ return NETDEVICE_TYPE_WIFI;
+ }
+ if (strncmp(interface_name, "rmnet_ipa", 9) == 0) {
+ /* Qualcomm IPA driver */
return NETDEVICE_TYPE_UNDEFINED;
+ }
+ if ((strncmp(interface_name, "rmnet", 5) == 0) ||
+ (strncmp(interface_name, "rev_rmnet", 9) == 0) ||
+ (strncmp(interface_name, "ccmni", 5) == 0)) {
+ /*
+ * rmnet* (Qualcomm) ccmni* (MediaTek)
+ */
+ return NETDEVICE_TYPE_CELLULAR;
+ }
+ /* usb0 might be cellular (eg Zenfone2) */
+ /* what about tethering */
+ /* tun* dummy* ... */
+ /* bnet* pan* hci* for bluetooth */
+ return NETDEVICE_TYPE_UNDEFINED;
}
-int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data);
-
-int
-facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * type, void * cfg, interface_t ** pinterface)
-{
- char rand_name[RAND_NAME_LEN+1];
- interface_t * interface;
-
- if (!name) {
- /*
- * We can manipulate the name on the stack as it will be strdup'ed by
- * interface_create
- */
- rand_str(rand_name, RAND_NAME_LEN);
- name = rand_name;
- }
-
- INFO("Creating interface %s [%s]...", name, type);
- interface = interface_create(name, type);
- if (!interface) {
- ERROR("Error creating interface %s [%s]", name, type);
- goto ERR_CREATE;
- }
- interface_set_callback(interface, facemgr, facemgr_callback);
+int facemgr_callback(facemgr_t *facemgr, interface_cb_type_t type, void *data);
- interface_map_data_t * interface_map_data = malloc(sizeof(interface_map_data_t));
- if (!interface_map_data)
- goto ERR_MAP_DATA;
-
- *interface_map_data = (interface_map_data_t) {
- .interface = interface,
- .fds = {0},
- .num_fds = 0,
- };
-
- if (interface_map_add(facemgr->interface_map, interface->name, interface_map_data) < 0)
- goto ERR_MAP_ADD;
+int facemgr_create_interface(facemgr_t *facemgr, const char *name,
+ const char *type, void *cfg,
+ interface_t **pinterface) {
+ char rand_name[RAND_NAME_LEN + 1];
+ interface_t *interface;
+ if (!name) {
/*
- * This should be called _after_ the interface_map is initialized otherwise
- * it will be impossible to register fds from *_initialize
+ * We can manipulate the name on the stack as it will be strdup'ed by
+ * interface_create
*/
- if (interface_initialize(interface, cfg) < 0) {
- ERROR("[facemgr_create_interface] Error initializing interface");
- goto ERR_INIT;
- }
-
- DEBUG("Interface %s created successfully.", name);
- if (pinterface)
- *pinterface = interface;
- return 0;
-
-
- //interface_finalize(interface);
+ rand_str(rand_name, RAND_NAME_LEN);
+ name = rand_name;
+ }
+
+ INFO("Creating interface %s [%s]...", name, type);
+ interface = interface_create(name, type);
+ if (!interface) {
+ ERROR("Error creating interface %s [%s]", name, type);
+ goto ERR_CREATE;
+ }
+ interface_set_callback(interface, facemgr, facemgr_callback);
+
+ interface_map_data_t *interface_map_data =
+ malloc(sizeof(interface_map_data_t));
+ if (!interface_map_data) goto ERR_MAP_DATA;
+
+ *interface_map_data = (interface_map_data_t){
+ .interface = interface,
+ .fds = {0},
+ .num_fds = 0,
+ };
+
+ if (interface_map_add(facemgr->interface_map, interface->name,
+ interface_map_data) < 0)
+ goto ERR_MAP_ADD;
+
+ /*
+ * This should be called _after_ the interface_map is initialized otherwise
+ * it will be impossible to register fds from *_initialize
+ */
+ if (interface_initialize(interface, cfg) < 0) {
+ ERROR("[facemgr_create_interface] Error initializing interface");
+ goto ERR_INIT;
+ }
+
+ DEBUG("Interface %s created successfully.", name);
+ if (pinterface) *pinterface = interface;
+ return 0;
+
+ // interface_finalize(interface);
ERR_INIT:
- interface_map_remove(facemgr->interface_map, interface->name, NULL);
+ interface_map_remove(facemgr->interface_map, interface->name, NULL);
ERR_MAP_ADD:
- free(interface_map_data);
+ free(interface_map_data);
ERR_MAP_DATA:
- interface_free(interface);
+ interface_free(interface);
ERR_CREATE:
- if (pinterface)
- *pinterface = NULL;
- return -1;
+ if (pinterface) *pinterface = NULL;
+ return -1;
}
-int
-facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface)
-{
- int rc;
-
- interface_map_data_t * interface_map_data = NULL;
+int facemgr_delete_interface(facemgr_t *facemgr, interface_t *interface) {
+ int rc;
- DEBUG("Removing interface %s", interface->name);
- rc = interface_map_remove(facemgr->interface_map, interface->name, &interface_map_data);
- if (rc < 0)
- return -1;
+ /*
+ * It is possible that one interface was never initialized, and thus the
+ * facemgr never started, and we still call stop(). This is for instance the
+ * case on Android (sdk 30) when netlink is blocked.
+ */
+ if (!interface) return 0;
- if (!interface_map_data)
- return -1;
-
- for (unsigned i = 0; i < interface_map_data->num_fds; i++) {
- int fd = interface_map_data->fds[i];
- fd_callback_data_t fd_callback_data = {
- .fd = fd,
- .owner = facemgr,
- .callback = NULL,
- .data = NULL,
- };
- facemgr->callback(facemgr->callback_owner, FACEMGR_CB_TYPE_UNREGISTER_FD, &fd_callback_data);
- if (rc < 0)
- WARN("[facemgr_delete_interface] Error unregistering fd %d for interface", fd);
- }
+ interface_map_data_t *interface_map_data = NULL;
- free(interface_map_data);
+ DEBUG("Removing interface %s", interface->name);
+ rc = interface_map_remove(facemgr->interface_map, interface->name,
+ &interface_map_data);
+ if (rc < 0) return -1;
- interface_finalize(interface);
- interface_free(interface);
+ if (!interface_map_data) return -1;
- return 0;
-}
-
-#ifdef __linux__
-int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice)
-{
- interface_t * bj = NULL;
-
- int rc = bonjour_map_get(facemgr->bonjour_map, netdevice, &bj);
+ for (unsigned i = 0; i < interface_map_data->num_fds; i++) {
+ int fd = interface_map_data->fds[i];
+ fd_callback_data_t fd_callback_data = {
+ .fd = fd,
+ .owner = facemgr,
+ .callback = NULL,
+ .data = NULL,
+ };
+ facemgr->callback(facemgr->callback_owner, FACEMGR_CB_TYPE_UNREGISTER_FD,
+ &fd_callback_data);
if (rc < 0)
- return rc;
-
- if (!bj) {
- /* Create a new bonjour interface */
- bonjour_cfg_t bj_cfg = {
- .netdevice = *netdevice,
- };
- rc = facemgr_create_interface(facemgr, NULL, "bonjour", &bj_cfg, &bj);
- if (rc < 0) {
- ERROR("Error creating 'Bonjour' interface for '%s'\n", netdevice->name);
- return -1;
- }
- }
+ WARN("[facemgr_delete_interface] Error unregistering fd %d for interface",
+ fd);
+ }
- DEBUG("sending event to bonjour interface");
+ free(interface_map_data);
- /* Send an event to the interface (GET ?) */
- // XXX error handling
- return interface_on_event(bj, NULL);
+ interface_finalize(interface);
+ interface_free(interface);
+
+ return 0;
}
-#endif /* __linux__ */
-#ifdef WITH_FACEMGR_UTILITY
-int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice)
-{
- /* Send an event to the interface */
- facelet_t * facelet = facelet_create();
- if (!facelet)
- goto ERR_MALLOC;
+#ifdef __linux__
+int facemgr_query_bonjour(facemgr_t *facemgr, netdevice_t *netdevice) {
+ interface_t *bj = NULL;
- int rc = facelet_set_netdevice(facelet, netdevice);
- if (rc < 0)
- goto ERR_ND;
+ int rc = bonjour_map_get(facemgr->bonjour_map, netdevice, &bj);
+ if (rc < 0) return rc;
- rc = interface_on_event(facemgr->au, facelet);
+ if (!bj) {
+ /* Create a new bonjour interface */
+ bonjour_cfg_t bj_cfg = {
+ .netdevice = *netdevice,
+ };
+ rc = facemgr_create_interface(facemgr, NULL, "bonjour", &bj_cfg, &bj);
if (rc < 0) {
- // XXX error handling
- goto ERR_EVENT;
+ ERROR("Error creating 'Bonjour' interface for '%s'\n", netdevice->name);
+ return -1;
}
+ }
- return 0;
+ DEBUG("sending event to bonjour interface");
-ERR_EVENT:
-ERR_ND:
- facelet_free(facelet);
-ERR_MALLOC:
- return -1;
+ /* Send an event to the interface (GET ?) */
+ // XXX error handling
+ return interface_on_event(bj, NULL);
}
-#endif /* WITH_FACEMGR_UTILITY */
-
+#endif /* __linux__ */
/**
* \brief Performs a cache lookup to find matching facelets
@@ -583,43 +540,38 @@ ERR_MALLOC:
* \return The number of entries in the array in case of success (positive
* value), or -1 in case of error.
*/
-int
-facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet,
- facelet_t ***cached_facelets)
-{
- assert(facelet);
-
- /* ...otherwise, we iterate over the facelet
- * cache to find matching elements.
- */
- facelet_t ** facelet_array;
- int n = facelet_set_get_array(facelet_cache, &facelet_array);
- if (n < 0) {
- ERROR("[facelet_cache_lookup] Error during cache match");
- return -1;
- }
- if (cached_facelets)
- *cached_facelets = malloc(n * sizeof(facelet_t*));
+int facelet_cache_lookup(const facelet_set_t *facelet_cache, facelet_t *facelet,
+ facelet_t ***cached_facelets) {
+ assert(facelet);
+
+ /* ...otherwise, we iterate over the facelet
+ * cache to find matching elements.
+ */
+ facelet_t **facelet_array;
+ int n = facelet_set_get_array(facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facelet_cache_lookup] Error during cache match");
+ return -1;
+ }
+ if (cached_facelets) *cached_facelets = malloc(n * sizeof(facelet_t *));
- int num_match = 0;
- for (unsigned i = 0; i < n; i++) {
+ int num_match = 0;
+ for (unsigned i = 0; i < n; i++) {
#if 0
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_array[i]);
- DEBUG("cache entry #%d/%di = %s", i+1, n, facelet_s);
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_array[i]);
+ DEBUG("cache entry #%d/%di = %s", i + 1, n, facelet_s);
#endif
- if (!facelet_match(facelet_array[i], facelet)) {
- continue;
- }
- if (cached_facelets)
- (*cached_facelets)[num_match] = facelet_array[i];
- num_match++;
- }
- free(facelet_array);
- return num_match;
+ facelet_t *f = facelet_array[i];
+ if (!f) continue; /* Should not occur */
+ if (!facelet_match(f, facelet)) continue;
+ if (cached_facelets) (*cached_facelets)[num_match] = f;
+ num_match++;
+ }
+ free(facelet_array);
+ return num_match;
}
-
/**
* \brief Checks whether the facelet satisfies face creation rules
* \param [in] facemgr - Pointer to the face manager instance
@@ -627,129 +579,92 @@ facelet_cache_lookup(const facelet_set_t * facelet_cache, facelet_t * facelet,
* \return 0 in case of success, -2 if we don't have enough information to
* decide, -3 if the face does not satisfy rules, and -1 in case of error
*/
-int
-facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
-{
- /* As key, netdevice and family should always be present */
- netdevice_t netdevice = NETDEVICE_EMPTY;
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet");
+int facemgr_facelet_satisfy_rules(facemgr_t *facemgr, facelet_t *facelet) {
+ /* As key, netdevice and family should always be present */
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_facelet_satisfy_rules] Error retrieving netdevice from "
+ "facelet");
+ return -1;
+ }
+
+ int family = AF_UNSPEC;
+ if (facelet_has_family(facelet)) {
+ if (facelet_get_family(facelet, &family) < 0) {
+ ERROR(
+ "[facemgr_facelet_satisfy_rules] Error retrieving family from "
+ "facelet");
+ return -1;
+ }
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from "
+ "facelet");
+ return -2;
+ }
+
+ /* Default ignore list */
+ if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) ||
+ (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) {
+ DEBUG("Ignored interface '%s/%s'...", netdevice.name,
+ netdevice_type_str(netdevice_type));
+ return -3;
+ }
+
+ /* Ignore */
+ bool ignore;
+ if (facemgr_cfg_get_ignore(facemgr->cfg, &netdevice, netdevice_type,
+ &ignore) < 0)
+ return -1;
+ if (ignore) {
+ DEBUG("Ignored interface '%s/%s'...", netdevice.name,
+ netdevice_type_str(netdevice_type));
+ return -3;
+ }
+
+ switch (family) {
+ case AF_INET: {
+ bool ipv4;
+ if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type,
+ &ipv4) < 0)
return -1;
- }
-
- int family = AF_UNSPEC;
- if (facelet_has_family(facelet)) {
- if (facelet_get_family(facelet, &family) < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving family from facelet");
- return -1;
- }
- }
-
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_FACEMGR_UTILITY
- /*
- * In addition to netdevice, netdevice_type should be present to correctly
- * apply rules
- */
- rc = facelet_get_netdevice_type(facelet, &netdevice_type);
- if (rc < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
- return -2;
- }
-#endif /* WITH_FACEMGR_UTILITY */
-
- /* Default ignore list */
- if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) {
- DEBUG("Ignored interface '%s/%s'...", netdevice.name,
- netdevice_type_str[netdevice_type]);
+ if (!ipv4) {
+ DEBUG("Ignored IPv4 facelet...");
return -3;
+ }
+ break;
}
- /* Ignore */
- bool ignore;
- if (facemgr_cfg_get_ignore(facemgr->cfg, &netdevice, netdevice_type,
- &ignore) < 0)
+ case AF_INET6: {
+ bool ipv6;
+ if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type,
+ &ipv6) < 0)
return -1;
- if (ignore) {
- DEBUG("Ignored interface '%s/%s'...", netdevice.name,
- netdevice_type_str[netdevice_type]);
+ if (!ipv6) {
+ DEBUG("Ignored IPv6 facelet...");
return -3;
+ }
+ break;
}
- switch(family) {
- case AF_INET:
- {
- bool ipv4;
- if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type,
- &ipv4) < 0)
- return -1;
- if (!ipv4) {
- DEBUG("Ignored IPv4 facelet...");
- return -3;
- }
- break;
- }
-
- case AF_INET6:
- {
- bool ipv6;
- if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type,
- &ipv6) < 0)
- return -1;
- if (!ipv6) {
- DEBUG("Ignored IPv6 facelet...");
- return -3;
- }
- break;
- }
-
- default:
- DEBUG("Ignored facelet with unknown family");
- return -2;
- }
+ default:
+ DEBUG("Ignored facelet with unknown family");
+ return -2;
+ }
- return 0;
+ return 0;
}
-#ifdef WITH_FACEMGR_UTILITY
-/**
- * \brief Complements facelet information through Android Utility interface
- * \return 0 if request was successful, -1 in case of error, and -2 if the
- * interface is not applicable
- *
- * This function returnds _after_ completion.
- */
-int
-facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
-{
-
- if (facelet_has_netdevice_type(facelet))
- return -2;
-
- if (facelet_is_au_done(facelet))
- return -2;
-
- netdevice_t netdevice = NETDEVICE_EMPTY;
-
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet");
- return -1;
- }
-
- DEBUG("Querying android utility...");
-
- /* /!\ Synchronous code here /!\ */
- if (facemgr_query_android_utility(facemgr, netdevice) < 0) {
- return -1;
- }
-
- facelet_set_au_done(facelet);
- return 0;
-}
-#endif /* WITH_FACEMGR_UTILITY */
-
#ifdef __linux__
/**
* \brief Complements facelet information through Bonjour interface.
@@ -759,66 +674,68 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
* This function returnds _before_ completion as bonjour querying is
* asynchronous.
*/
-int
-facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
-{
- netdevice_t netdevice = NETDEVICE_EMPTY;
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice from facelet");
- return -1;
- }
-
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_FACEMGR_UTILITY
- /*
- * In addition to netdevice, netdevice_type should be present to correctly
- * apply rules
- */
- rc = facelet_get_netdevice_type(facelet, &netdevice_type);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice_type from facelet");
- return -2;
- }
-#endif /* WITH_FACEMGR_UTILITY */
-
- bool discovery;
- if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
- &discovery) < 0)
- return -2;
-
- DEBUG("Discovery: %s", discovery ? "ON" : "OFF");
-
- if (!discovery)
- return -2;
-
- facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
- if (facelet_get_face_type(facelet, &face_type) < 0) {
- ERROR("[facemgr_complement_facelet_bj] Error retrieving face type from facelet");
- return -1;
- }
+int facemgr_complement_facelet_bj(facemgr_t *facemgr, facelet_t *facelet) {
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_bj] Error retrieving netdevice from "
+ "facelet");
+ return -1;
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_bj] Error retrieving netdevice_type from "
+ "facelet");
+ return -2;
+ }
+
+ bool discovery;
+ if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
+ &discovery) < 0)
+ return -2;
+
+ DEBUG("Discovery: %s", discovery ? "ON" : "OFF");
+
+ if (!discovery) return -2;
+
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facelet_get_face_type(facelet, &face_type) < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_bj] Error retrieving face type from "
+ "facelet");
+ return -1;
+ }
- bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) &&
- ((!facelet_has_remote_addr(facelet)) || (!facelet_has_remote_port(facelet)));
+ bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) &&
+ ((!facelet_has_remote_addr(facelet)) ||
+ (!facelet_has_remote_port(facelet)));
- DEBUG("Discovery needed: %s", discovery ? "ON" : "OFF");
+ DEBUG("Discovery needed: %s", discovery ? "ON" : "OFF");
- if (!discovery_needed) {
- return -2;
- }
+ if (!discovery_needed) {
+ return -2;
+ }
- if (!facelet_has_local_addr(facelet)) {
- DEBUG("No discovery possible without local address");
- return -2;
- }
+ if (!facelet_has_local_addr(facelet)) {
+ DEBUG("No discovery possible without local address");
+ return -2;
+ }
- if (facelet_is_bj_done(facelet)) {
- DEBUG("Bonjour already queried");
- return -2;
- }
+ if (facelet_is_bj_done(facelet)) {
+ DEBUG("Bonjour already queried");
+ return -2;
+ }
- facelet_set_bj_done(facelet);
- return facemgr_query_bonjour(facemgr, &netdevice);
+ facelet_set_bj_done(facelet);
+ return facemgr_query_bonjour(facemgr, &netdevice);
}
#endif /* __linux__ */
@@ -830,49 +747,52 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
* This function returnds _before_ completion as bonjour querying is
* asynchronous.
*/
-int
-facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
-{
-
- netdevice_t netdevice = NETDEVICE_EMPTY;
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice from facelet");
- return -1;
- }
-
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_FACEMGR_UTILITY
- /*
- * In addition to netdevice, netdevice_type should be present to correctly
- * apply rules
- */
- rc = facelet_get_netdevice_type(facelet, &netdevice_type);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice_type from facelet");
- return -2;
- }
-#endif /* WITH_FACEMGR_UTILITY */
-
- int family = AF_UNSPEC;
- if (facelet_has_family(facelet)) {
- if (facelet_get_family(facelet, &family) < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error retrieving family from facelet");
- return -1;
- }
- }
-
- /* Do not query manual is there is a change to go through bonjour */
- bool discovery;
- if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
- &discovery) < 0)
- return -2;
-
- facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
- if (facelet_get_face_type(facelet, &face_type) < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error retrieving face type from facelet");
- return -1;
- }
+int facemgr_complement_facelet_manual(facemgr_t *facemgr, facelet_t *facelet) {
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error retrieving netdevice from "
+ "facelet");
+ return -1;
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error retrieving netdevice_type "
+ "from facelet");
+ return -2;
+ }
+
+ int family = AF_UNSPEC;
+ if (facelet_has_family(facelet)) {
+ if (facelet_get_family(facelet, &family) < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error retrieving family from "
+ "facelet");
+ return -1;
+ }
+ }
+
+ /* Do not query manual is there is a change to go through bonjour */
+ bool discovery;
+ if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
+ &discovery) < 0)
+ return -2;
+
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facelet_get_face_type(facelet, &face_type) < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error retrieving face type from "
+ "facelet");
+ return -1;
+ }
#if 0 /* Wrong if we need to complement local addr / port */
bool discovery_needed = (face_type.layer == FACE_TYPE_LAYER_4) &&
@@ -884,91 +804,97 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
}
#endif
- if (discovery && !facelet_is_bj_done(facelet)) {
- DEBUG("manual settings not considered as discovery is enabled and Bonjour has not yet been done");
- return -2;
- }
-
- DEBUG("Applying manual settings...");
- /*
- * Manual overlay specification (remote addr/port)
- * We never override a result we have obtained through bonjour
- */
- if (!facelet_has_remote_addr(facelet)) {
- ip_address_t remote_addr;
- if (facemgr_cfg_get_overlay_remote_addr(facemgr->cfg,
- &netdevice, netdevice_type, family, &remote_addr) < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error getting remote addr information from cfg");
- return -1;
- }
- if (ip_address_empty(&remote_addr)) {
- ERROR("[facemgr_complement_facelet_manual] Got empty remote addr information from cfg");
- } else {
- DEBUG(" - remote address");
- facelet_set_remote_addr(facelet, remote_addr);
- }
- }
-
- if (!facelet_has_remote_port(facelet)) {
- uint16_t remote_port;
- int rc = facemgr_cfg_get_overlay_remote_port(facemgr->cfg,
- &netdevice, netdevice_type, family, &remote_port);
- if (rc < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error getting remote port information from cfg");
- return -1;
- }
- DEBUG(" - remote port");
- facelet_set_remote_port(facelet, remote_port);
- }
-
- /*
- * Complementing local addr/port XXX this should be done somewhere
- * else : manual settings have the lowest priority
- *
- * Local IP address is specific as it allows to override the source
- * address just before creating the face... we would need to check
- * whether this is an address that belong to us... it might be used
- * to arbitrate amongst several IP addresses instead...
- */
- ip_address_t local_addr;
- if (facemgr_cfg_get_overlay_local_addr(facemgr->cfg, &netdevice,
- netdevice_type, family, &local_addr) < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error getting local addr information from cfg");
- return -1;
- }
- if (ip_address_empty(&local_addr)) {
- ERROR("[facemgr_complement_facelet_manual] Got empty local addr information from cfg");
+ if (discovery && !facelet_is_bj_done(facelet)) {
+ DEBUG(
+ "manual settings not considered as discovery is enabled and Bonjour "
+ "has not yet been done");
+ return -2;
+ }
+
+ DEBUG("Applying manual settings...");
+ /*
+ * Manual overlay specification (remote addr/port)
+ * We never override a result we have obtained through bonjour
+ */
+ if (!facelet_has_remote_addr(facelet)) {
+ ip_address_t remote_addr;
+ if (facemgr_cfg_get_overlay_remote_addr(facemgr->cfg, &netdevice,
+ netdevice_type, family,
+ &remote_addr) < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error getting remote addr "
+ "information from cfg");
+ return -1;
+ }
+ if (ip_address_empty(&remote_addr)) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Got empty remote addr "
+ "information from cfg");
} else {
- DEBUG(" - local addres");
- facelet_set_local_addr(facelet, local_addr);
+ DEBUG(" - remote address");
+ facelet_set_remote_addr(facelet, remote_addr);
}
+ }
- /* Sets a default local port, so far nobody sets it */
- uint16_t local_port;
- if (facemgr_cfg_get_overlay_local_port(facemgr->cfg,
- &netdevice, netdevice_type, family, &local_port) < 0) {
- ERROR("[facemgr_complement_facelet_manual] Error getting local port information from cfg");
- return -1;
- }
- DEBUG(" - local port");
- facelet_set_local_port(facelet, local_port);
- return 0;
+ if (!facelet_has_remote_port(facelet)) {
+ uint16_t remote_port;
+ int rc = facemgr_cfg_get_overlay_remote_port(
+ facemgr->cfg, &netdevice, netdevice_type, family, &remote_port);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error getting remote port "
+ "information from cfg");
+ return -1;
+ }
+ DEBUG(" - remote port");
+ facelet_set_remote_port(facelet, remote_port);
+ }
+
+ /*
+ * Complementing local addr/port XXX this should be done somewhere
+ * else : manual settings have the lowest priority
+ *
+ * Local IP address is specific as it allows to override the source
+ * address just before creating the face... we would need to check
+ * whether this is an address that belong to us... it might be used
+ * to arbitrate amongst several IP addresses instead...
+ */
+ ip_address_t local_addr;
+ if (facemgr_cfg_get_overlay_local_addr(
+ facemgr->cfg, &netdevice, netdevice_type, family, &local_addr) < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error getting local addr "
+ "information from cfg");
+ return -1;
+ }
+ if (ip_address_empty(&local_addr)) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Got empty local addr information "
+ "from cfg");
+ } else {
+ DEBUG(" - local addres");
+ facelet_set_local_addr(facelet, local_addr);
+ }
+
+ /* Sets a default local port, so far nobody sets it */
+ uint16_t local_port;
+ if (facemgr_cfg_get_overlay_local_port(
+ facemgr->cfg, &netdevice, netdevice_type, family, &local_port) < 0) {
+ ERROR(
+ "[facemgr_complement_facelet_manual] Error getting local port "
+ "information from cfg");
+ return -1;
+ }
+ DEBUG(" - local port");
+ facelet_set_local_port(facelet, local_port);
+ return 0;
}
-int
-facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
-{
- int rc;
+int facemgr_complement_facelet(facemgr_t *facemgr, facelet_t *facelet) {
+ int rc;
- DEBUG("[facemgr_complement_facelet]");
- if (!facelet_has_key(facelet))
- return -2;
-
-#ifdef WITH_FACEMGR_UTILITY
- rc = facemgr_complement_facelet_au(facemgr, facelet);
- if (rc != -2)
- return rc;
-#endif /* WITH_FACEMGR_UTILITY */
+ DEBUG("[facemgr_complement_facelet]");
+ if (!facelet_has_key(facelet)) return -2;
#if 0
if (!facelet_has_netdevice_type(facelet)) {
@@ -988,51 +914,51 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
*/
#ifdef __linux__
- rc = facemgr_complement_facelet_bj(facemgr, facelet);
- if (rc != -2)
- return rc;
+ rc = facemgr_complement_facelet_bj(facemgr, facelet);
+ if (rc != -2) return rc;
#endif /* __linux__ */
- DEBUG("[facemgr_complement_facelet] Complement manual");
+ DEBUG("[facemgr_complement_facelet] Complement manual");
- rc = facemgr_complement_facelet_manual(facemgr, facelet);
- if (rc != -2)
- return rc;
+ rc = facemgr_complement_facelet_manual(facemgr, facelet);
+ if (rc != -2) return rc;
- INFO("[facemgr_complement_facelet] No more interfaces to query... incomplete face");
- return 0;
+ INFO(
+ "[facemgr_complement_facelet] No more interfaces to query... incomplete "
+ "face");
+ return 0;
}
-int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
-{
- DEBUG("[facemgr_assign_face_type]");
- /* As key, netdevice and family should always be present */
- netdevice_t netdevice = NETDEVICE_EMPTY;
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_assign_face_type] Error retrieving netdevice from facelet");
- return -1;
- }
-
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_FACEMGR_UTILITY
- /*
- * In addition to netdevice, netdevice_type should be present to correctly
- * apply rules
- */
- rc = facelet_get_netdevice_type(facelet, &netdevice_type);
- if (rc < 0) {
- ERROR("[facemgr_assign_face_type] Error retrieving netdevice_type from facelet");
- return -2;
- }
-#endif /* WITH_FACEMGR_UTILITY */
-
- facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
- if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0)
- return rc;
- facelet_set_face_type(facelet, face_type);
- DEBUG("[facemgr_assign_face_type] %s", FACEMGR_FACE_TYPE_STR(face_type));
- return 0;
+int facemgr_assign_face_type(facemgr_t *facemgr, facelet_t *facelet) {
+ DEBUG("[facemgr_assign_face_type]");
+ /* As key, netdevice and family should always be present */
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_assign_face_type] Error retrieving netdevice from facelet");
+ return -1;
+ }
+
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ /*
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
+ */
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_assign_face_type] Error retrieving netdevice_type from "
+ "facelet");
+ return -2;
+ }
+
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type,
+ &face_type) < 0)
+ return rc;
+ facelet_set_face_type(facelet, face_type);
+ DEBUG("[facemgr_assign_face_type] %s", FACEMGR_FACE_TYPE_STR(face_type));
+ return 0;
}
/*
@@ -1041,102 +967,102 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
*
* We assume the facelet is already present in the cache
*/
-int
-facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
-{
- int rc;
- facelet_error_reason_t reason = FACELET_ERROR_REASON_INTERNAL_ERROR;
-
- switch(facelet_get_status(facelet)) {
- case FACELET_STATUS_UNCERTAIN:
- /*
- * All new faces are marked UNCERTAIN. We need to check whether we
- * have sufficient information to check rules, if not proceed,
- * otherwise possibly mark the face as IGNORED. Otherwise, we verify
- * the completeness of the information we have, and continue towards
- * being able to mark the face as CREATE.
- */
- rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
- switch(rc) {
- case -3:
- /* Does not satisfy rules */
- DEBUG("[facemgr_process_facelet] Does not satisfy rules");
- facelet_set_status(facelet, FACELET_STATUS_IGNORED);
- return 0;
-
- case -2:
- DEBUG("[facemgr_process_facelet] Complementing facelet is required");
- if (facemgr_complement_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet] Error while attempting to complement face for fields required by face creation");
- goto ERR;
- }
- return 0;
-
- case 0:
- /* Ok pass rules */
- break;
-
- default:
- /* -1 - Error */
- goto ERR;
- }
-
- if (facemgr_assign_face_type(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet] Could not assign face type");
- goto ERR;
- }
- facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE);
- /* Continue in case facelet satisfies rules */
-
- case FACELET_STATUS_INCOMPLETE:
- if (!facelet_validate_face(facelet)) {
- /* We need additional information */
- if (facemgr_complement_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet] Error while attempting to complement face for fields required by face creation");
- goto ERR;
- }
- }
- if (!facelet_validate_face(facelet))
- return 0;
-
- facelet_set_status(facelet, FACELET_STATUS_CREATE);
- /* Continue in case we need to proceed to creation */
-
- case FACELET_STATUS_CREATE:
- facelet_set_event(facelet, FACELET_EVENT_CREATE);
- rc = interface_on_event(facemgr->hl, facelet);
- if (rc < 0) {
- ERROR("[facemgr_process_facelet] Failed to create face");
- reason = -rc;
- goto ERR;
- }
-
- /* This works assuming the call to hicn-light is blocking */
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
- break;
+int facemgr_process_facelet(facemgr_t *facemgr, facelet_t *facelet) {
+ int rc;
+ facelet_error_reason_t reason = FACELET_ERROR_REASON_INTERNAL_ERROR;
+
+ switch (facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ /*
+ * All new faces are marked UNCERTAIN. We need to check whether we
+ * have sufficient information to check rules, if not proceed,
+ * otherwise possibly mark the face as IGNORED. Otherwise, we verify
+ * the completeness of the information we have, and continue towards
+ * being able to mark the face as CREATE.
+ */
+ rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
+ switch (rc) {
+ case -3:
+ /* Does not satisfy rules */
+ DEBUG("[facemgr_process_facelet] Does not satisfy rules");
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
+ return 0;
+
+ case -2:
+ DEBUG("[facemgr_process_facelet] Complementing facelet is required");
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR(
+ "[facemgr_process_facelet] Error while attempting to "
+ "complement face for fields required by face creation");
+ goto ERR;
+ }
+ return 0;
+ case 0:
+ /* Ok pass rules */
+ break;
- case FACELET_STATUS_UPDATE:
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- rc = interface_on_event(facemgr->hl, facelet);
- if (rc < 0) {
- ERROR("[facemgr_process_facelet] Failed to update face");
- reason = -rc;
- goto ERR;
- }
+ default:
+ /* -1 - Error */
+ goto ERR;
+ }
- /* This works assuming the call to hicn-light is blocking */
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
- break;
-
- case FACELET_STATUS_DELETE:
- facelet_set_event(facelet, FACELET_EVENT_DELETE);
- rc = interface_on_event(facemgr->hl, facelet);
- if (rc < 0) {
- ERROR("[facemgr_process_facelet] Failed to delete face");
- reason = -rc;
- goto ERR;
- }
+ if (facemgr_assign_face_type(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Could not assign face type");
+ goto ERR;
+ }
+ facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE);
+ /* Continue in case facelet satisfies rules */
+
+ case FACELET_STATUS_INCOMPLETE:
+ if (!facelet_validate_face(facelet)) {
+ /* We need additional information */
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR(
+ "[facemgr_process_facelet] Error while attempting to complement "
+ "face for fields required by face creation");
+ goto ERR;
+ }
+ }
+ if (!facelet_validate_face(facelet)) return 0;
+
+ facelet_set_status(facelet, FACELET_STATUS_CREATE);
+ /* Continue in case we need to proceed to creation */
+
+ case FACELET_STATUS_CREATE:
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ rc = interface_on_event(facemgr->hl, facelet);
+ if (rc < 0) {
+ ERROR("[facemgr_process_facelet] Failed to create face");
+ reason = -rc;
+ goto ERR;
+ }
+
+ /* This works assuming the call to hicn-light is blocking */
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ break;
+
+ case FACELET_STATUS_UPDATE:
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ rc = interface_on_event(facemgr->hl, facelet);
+ if (rc < 0) {
+ ERROR("[facemgr_process_facelet] Failed to update face");
+ reason = -rc;
+ goto ERR;
+ }
+
+ /* This works assuming the call to hicn-light is blocking */
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ break;
+
+ case FACELET_STATUS_DELETE:
+ facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ rc = interface_on_event(facemgr->hl, facelet);
+ if (rc < 0) {
+ ERROR("[facemgr_process_facelet] Failed to delete face");
+ reason = -rc;
+ goto ERR;
+ }
#if 0
if (facelet_get_id(facelet) > 0) {
@@ -1147,111 +1073,102 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
facelet_free(facelet);
} else {
#endif
- /* This works assuming the call to hicn-light is blocking */
- DEBUG("[facemgr_process_facelet] Cleaning cached data");
- facelet_unset_local_addr(facelet);
- facelet_unset_local_port(facelet);
- if (facelet_get_id(facelet) == 0) {
- facelet_unset_remote_addr(facelet);
- facelet_unset_remote_port(facelet);
- facelet_clear_routes(facelet);
- }
-
- facelet_unset_admin_state(facelet);
- facelet_unset_state(facelet);
- facelet_unset_bj_done(facelet);
-#ifdef WITH_FACEMGR_UTILITY
- facelet_unset_au_done(facelet);
-#endif /* WITH_FACEMGR_UTILITY */
-
- facelet_set_status(facelet, FACELET_STATUS_DELETED);
+ /* This works assuming the call to hicn-light is blocking */
+ DEBUG("[facemgr_process_facelet] Cleaning cached data");
+ facelet_unset_local_addr(facelet);
+ facelet_unset_local_port(facelet);
+ if (facelet_get_id(facelet) == 0) {
+ facelet_unset_remote_addr(facelet);
+ facelet_unset_remote_port(facelet);
+ facelet_clear_routes(facelet);
+ }
+
+ facelet_unset_admin_state(facelet);
+ facelet_unset_state(facelet);
+ facelet_unset_bj_done(facelet);
+
+ facelet_set_status(facelet, FACELET_STATUS_DELETED);
#if 0
}
#endif
- break;
-
- case FACELET_STATUS_CLEAN:
- case FACELET_STATUS_IGNORED:
- case FACELET_STATUS_DOWN:
- case FACELET_STATUS_DELETED:
- /* Nothing to do */
- break;
-
- case FACELET_STATUS_UNDEFINED:
- case FACELET_STATUS_N:
- ERROR("[facemgr_process_facelet] Unexpected facelet status");
- goto ERR;
- }
+ break;
- facelet_unset_error(facelet);
- return 0;
+ case FACELET_STATUS_CLEAN:
+ case FACELET_STATUS_IGNORED:
+ case FACELET_STATUS_DOWN:
+ case FACELET_STATUS_DELETED:
+ /* Nothing to do */
+ break;
+
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet] Unexpected facelet status");
+ goto ERR;
+ }
+
+ facelet_unset_error(facelet);
+ return 0;
ERR:
- facelet_set_error(facelet, reason);
- return -1;
+ facelet_set_error(facelet, reason);
+ return -1;
}
-int
-facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data)
-{
- bool has_error = false;
+int facemgr_reattempt_timeout(facemgr_t *facemgr, int fd, void *data) {
+ bool has_error = false;
- assert(data == NULL);
+ assert(data == NULL);
- /* Free all facelets from cache */
- facelet_t ** facelet_array;
- int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
- if (n < 0) {
- ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache");
+ /* Free all facelets from cache */
+ facelet_t **facelet_array;
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_reattempt_timeout] Could not retrieve facelets in cache");
+ has_error = true;
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t *facelet = facelet_array[i];
+ if (!facelet) continue; /* Should not occur */
+ if (!facelet_get_error(facelet)) continue;
+
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ DEBUG("Reattempt to process failed facelet %s", buf);
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_reattempt_timeout] Error processing facelet");
has_error = true;
- } else {
- for (unsigned i = 0; i < n; i++) {
- facelet_t * facelet = facelet_array[i];
-
- if (!facelet_get_error(facelet))
- continue;
-
- char buf[MAXSZ_FACELET];
- facelet_snprintf(buf, MAXSZ_FACELET, facelet);
- DEBUG("Reattempt to process failed facelet %s", buf);
- if (facemgr_process_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_reattempt_timeout] Error processing facelet");
- has_error = true;
- continue;
- }
- facelet_unset_error(facelet);
- }
- free(facelet_array);
+ continue;
+ }
+ facelet_unset_error(facelet);
}
+ free(facelet_array);
+ }
- if (has_error)
- return 0;
+ if (has_error) return 0;
- DEBUG("Cancelling timer");
- if (facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd) < 0) {
- ERROR("[facemgr_reattempt_timeout] Error unregistering reattempt timer");
- return -1;
- }
- facemgr->timer_fd = 0;
- return 0;
+ DEBUG("Cancelling timer");
+ if (facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER,
+ &facemgr->timer_fd) < 0) {
+ ERROR("[facemgr_reattempt_timeout] Error unregistering reattempt timer");
+ return -1;
+ }
+ facemgr->timer_fd = 0;
+ return 0;
}
-int
-facemgr_start_reattempts(facemgr_t * facemgr)
-{
- if (facemgr->timer_fd > 0)
- return 0;
-
- timer_callback_data_t timer_callback = {
- .delay_ms = DEFAULT_REATTEMPT_DELAY_MS,
- .owner = facemgr,
- .callback = (fd_callback_t)facemgr_reattempt_timeout,
- .data = NULL,
- };
- facemgr->timer_fd = facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_REGISTER_TIMER, &timer_callback);
- return (facemgr->timer_fd > 0);
+int facemgr_start_reattempts(facemgr_t *facemgr) {
+ if (facemgr->timer_fd > 0) return 0;
+
+ timer_callback_data_t timer_callback = {
+ .delay_ms = DEFAULT_REATTEMPT_DELAY_MS,
+ .owner = facemgr,
+ .callback = (fd_callback_t)facemgr_reattempt_timeout,
+ .data = NULL,
+ };
+ facemgr->timer_fd = facemgr->callback(
+ facemgr->callback_owner, FACEMGR_CB_TYPE_REGISTER_TIMER, &timer_callback);
+ return (facemgr->timer_fd > 0);
}
/**
@@ -1261,218 +1178,226 @@ facemgr_start_reattempts(facemgr_t * facemgr)
* \return 0 if everything went correctly, or -1 in case of error.
* -2 means we ignored the face purposedly
*/
-int
-facemgr_process_facelet_create(facemgr_t * facemgr, facelet_t * facelet)
-{
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- DEBUG("[facemgr_process_facelet_create] %s", facelet_s);
- switch(facelet_get_status(facelet)) {
- case FACELET_STATUS_UNCERTAIN:
- case FACELET_STATUS_INCOMPLETE:
- case FACELET_STATUS_CREATE:
- /* No change */
- DEBUG("[facemgr_process_facelet_create] UNCHANGED STATUS");
- break;
- case FACELET_STATUS_UPDATE:
- case FACELET_STATUS_DELETE:
- /*
- * Unlikely. The face had been created and is planned to
- * be deleted. Schedule for creation (we should have all
- * needed information), but make sure to handle errors
- * correctly if the face is still present.
- * TODO What if some fields have been updated ?
- */
- DEBUG("[facemgr_process_facelet_create] SET STATUS TO CREATE");
- facelet_set_status(facelet, FACELET_STATUS_CREATE);
- break;
- case FACELET_STATUS_CLEAN:
- case FACELET_STATUS_IGNORED:
- /*
- * We should have nothing to do unless some fields have
- * been updated.
- */
- DEBUG("[facemgr_process_facelet_create] NOTHING TO DO");
- break;
-
- case FACELET_STATUS_DOWN:
- case FACELET_STATUS_DELETED:
- /*
- * Unless rules have changed, we only need to recover
- * missing information, and proceed to face creation.
- * Rule changes should be handled separately.
- */
- DEBUG("[facemgr_process_facelet_create] SET STATUS TO INCOMPLETE");
- facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE);
- break;
- case FACELET_STATUS_UNDEFINED:
- case FACELET_STATUS_N:
- ERROR("[facemgr_process_facelet_create] Unexpected facelet status");
- return -1;
- }
-
-
- DEBUG("[facemgr_process_facelet_create] Processing facelet");
- if (facemgr_process_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet_create] Error processing facelet");
- return -1;
- }
+int facemgr_process_facelet_create(facemgr_t *facemgr, facelet_t *facelet) {
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ DEBUG("[facemgr_process_facelet_create] %s", facelet_s);
+ switch (facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ case FACELET_STATUS_INCOMPLETE:
+ case FACELET_STATUS_CREATE:
+ /* No change */
+ DEBUG("[facemgr_process_facelet_create] UNCHANGED STATUS");
+ break;
+ case FACELET_STATUS_UPDATE:
+ case FACELET_STATUS_DELETE:
+ /*
+ * Unlikely. The face had been created and is planned to
+ * be deleted. Schedule for creation (we should have all
+ * needed information), but make sure to handle errors
+ * correctly if the face is still present.
+ * TODO What if some fields have been updated ?
+ */
+ DEBUG("[facemgr_process_facelet_create] SET STATUS TO CREATE");
+ facelet_set_status(facelet, FACELET_STATUS_CREATE);
+ break;
+ case FACELET_STATUS_CLEAN:
+ case FACELET_STATUS_IGNORED:
+ /*
+ * We should have nothing to do unless some fields have
+ * been updated.
+ */
+ DEBUG("[facemgr_process_facelet_create] NOTHING TO DO");
+ break;
+
+ case FACELET_STATUS_DOWN:
+ case FACELET_STATUS_DELETED:
+ /*
+ * Unless rules have changed, we only need to recover
+ * missing information, and proceed to face creation.
+ * Rule changes should be handled separately.
+ */
+ DEBUG("[facemgr_process_facelet_create] SET STATUS TO INCOMPLETE");
+ facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE);
+ break;
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet_create] Unexpected facelet status");
+ return -1;
+ }
+
+ DEBUG("[facemgr_process_facelet_create] Processing facelet");
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_create] Error processing facelet");
+ return -1;
+ }
- return 0;
+ return 0;
}
/*
* \return 0 in case of success and no static facelet was added, 1 if a static
* facelet was added, and -1 in case of error.
*/
-int
-facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet)
-{
- /*
- * We need to analyze the facelet and eventually:
- * - add it in our static list
- * - replicate it on multipath interfaces
- */
- netdevice_type_t netdevice_type;
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0)
- return -1;
-
- if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) ||
- (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
- return 0;
-
- if ((facelet_get_route_array(facelet, NULL) == 0))
- return 0;
-
- /*
- * How to differenciate facelet created by face manager from user
- * created ones ? This cannot be a flag in the facelet as it needs
- * to work across restarts of the face manager...
- * Also we might have two default routes.
- *
- * TODO:
- * - The static one should not be a duplicate of the one we would
- * create by default....
- * - This should anyways be detected...
- *
- * One solution would be to install the default ones as static but
- * this requires to implement a priority scheme between some of the
- * static routes so that the override mechanism continues to work as
- * usual.
- *
- * Current, we recognize the routes created by default by the face
- * maanger thanks to the routing prefixes (a single default route).
- */
-
- facelet_t * static_facelet = facelet_dup(facelet);
- facelet_set_event(static_facelet, FACELET_EVENT_CREATE);
- facelet_unset_netdevice(static_facelet);
- facelet_unset_netdevice_type(static_facelet);
- facelet_unset_local_addr(static_facelet);
- facelet_unset_local_port(static_facelet);
-
- facelet_t * facelet_found = NULL;
- if (facelet_array_get(facemgr->static_facelets, static_facelet, &facelet_found) < 0) {
- ERROR("[facemgr_consider_static_facelet] Error checking whether static facelet already exists or not");
- return -1;
- }
+int facemgr_consider_static_facelet(facemgr_t *facemgr, facelet_t *facelet) {
+ /*
+ * We need to analyze the facelet and eventually:
+ * - add it in our static list
+ * - replicate it on multipath interfaces
+ */
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) return -1;
+
+ if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) ||
+ (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
+ return 0;
- /* Skip addition if facelet exists */
- if (facelet_found)
- return 0;
+ if ((facelet_get_route_array(facelet, NULL) == 0)) return 0;
+
+ /*
+ * How to differenciate facelet created by face manager from user
+ * created ones ? This cannot be a flag in the facelet as it needs
+ * to work across restarts of the face manager...
+ * Also we might have two default routes.
+ *
+ * TODO:
+ * - The static one should not be a duplicate of the one we would
+ * create by default....
+ * - This should anyways be detected...
+ *
+ * One solution would be to install the default ones as static but
+ * this requires to implement a priority scheme between some of the
+ * static routes so that the override mechanism continues to work as
+ * usual.
+ *
+ * Current, we recognize the routes created by default by the face
+ * maanger thanks to the routing prefixes (a single default route).
+ */
+
+ facelet_t *static_facelet = facelet_dup(facelet);
+ facelet_set_event(static_facelet, FACELET_EVENT_CREATE);
+ facelet_unset_netdevice(static_facelet);
+ facelet_unset_netdevice_type(static_facelet);
+ facelet_unset_local_addr(static_facelet);
+ facelet_unset_local_port(static_facelet);
+
+ facelet_t *facelet_found = NULL;
+ if (facelet_array_get(facemgr->static_facelets, static_facelet,
+ &facelet_found) < 0) {
+ ERROR(
+ "[facemgr_consider_static_facelet] Error checking whether static "
+ "facelet already exists or not");
+ return -1;
+ }
- facemgr->cur_static_id++;
+ /* Skip addition if facelet exists */
+ if (facelet_found) return 0;
- facelet_set_id(static_facelet, facemgr->cur_static_id);
- facelet_set_id(facelet, facemgr->cur_static_id);
+ facemgr->cur_static_id++;
- if (facelet_array_add(facemgr->static_facelets, static_facelet) < 0) {
- ERROR("[facemgr_consider_static_facelet] Could not add facelet to static array");
- facelet_free(static_facelet);
- return -1;
- }
+ facelet_set_id(static_facelet, facemgr->cur_static_id);
+ facelet_set_id(facelet, facemgr->cur_static_id);
- char facelet_s[MAXSZ_FACELET];
- int rc = facelet_snprintf(facelet_s, MAXSZ_FACELET, static_facelet);
- if (rc >= MAXSZ_FACELET)
- ERROR("[facemgr_consider_static_facelet] Unexpected truncation of facelet string");
- if (rc < 0)
- ERROR("[facemgr_consider_static_facelet] Error during facelet string output");
- DEBUG("[facemgr_consider_static_facelet] Successfully added facelet to static array %s", facelet_s);
+ if (facelet_array_add(facemgr->static_facelets, static_facelet) < 0) {
+ ERROR(
+ "[facemgr_consider_static_facelet] Could not add facelet to static "
+ "array");
+ facelet_free(static_facelet);
+ return -1;
+ }
+
+ char facelet_s[MAXSZ_FACELET];
+ int rc = facelet_snprintf(facelet_s, MAXSZ_FACELET, static_facelet);
+ if (rc >= MAXSZ_FACELET)
+ ERROR(
+ "[facemgr_consider_static_facelet] Unexpected truncation of facelet "
+ "string");
+ if (rc < 0)
+ ERROR(
+ "[facemgr_consider_static_facelet] Error during facelet string output");
+ DEBUG(
+ "[facemgr_consider_static_facelet] Successfully added facelet to static "
+ "array %s",
+ facelet_s);
#if 1
- /* Force application of the static face on all existing interfaces */
- facelet_t ** facelet_array;
- int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
- if (n >= 0) {
- for (unsigned i = 0; i < n; i++) {
- facelet_t * cached_facelet = facelet_array[i];
-
- netdevice_type_t netdevice_type;
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- ERROR("[facemgr_consider_static_facelet] Error retrieving netdevice type from cached facelet");
- continue;
- }
- if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED))
- continue;
-
- facelet_t * new_facelet = facelet_dup(cached_facelet);
- facelet_unset_remote_addr(new_facelet);
- facelet_unset_remote_port(new_facelet);
- facelet_unset_admin_state(new_facelet);
- facelet_unset_state(new_facelet);
- facelet_unset_bj_done(new_facelet);
- facelet_clear_routes(new_facelet);
-#ifdef WITH_FACEMGR_UTILITY
- facelet_unset_au_done(new_facelet);
-#endif /* WITH_FACEMGR_UTILITY */
-
- /* We try to apply static_facelet over facelet */
- if (!facelet_match(new_facelet, static_facelet)) {
- facelet_free(new_facelet);
- continue;
- }
-
- if (facelet_merge(new_facelet, static_facelet) < 0) {
- ERROR("[facemgr_consider_static_facelet] Error merging facelets");
- facelet_free(new_facelet);
- continue;
- }
-
- /*
- * We need to set the id before checking for existence as tuple used
- * is (id, netdevice, family)
- */
- facelet_set_id(new_facelet, facemgr->cur_static_id);
-
- facelet_found = NULL;
- if (facelet_set_get(facemgr->facelet_cache, new_facelet, &facelet_found) < 0) {
- ERROR("[facemgr_consider_static_facelet] Error checking whether new static facelet already exists or not");
- continue;
- }
-
-
- /* Skip addition if facelet exists */
- if (facelet_found) {
- facelet_free(new_facelet);
- continue;
- }
-
- facelet_set_attr_clean(new_facelet);
- facelet_set_status(facelet, FACELET_STATUS_UNDEFINED);
-
- if (facemgr_on_event(facemgr, new_facelet) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error creating static facelet for existing face");
- continue;
- }
-
- INFO("Successfully created static facelet for existing face");
- }
- free(facelet_array);
+ /* Force application of the static face on all existing interfaces */
+ facelet_t **facelet_array;
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
+ if (n >= 0) {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t *cached_facelet = facelet_array[i];
+ if (!cached_facelet) continue; /* Should not occur */
+
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ ERROR(
+ "[facemgr_consider_static_facelet] Error retrieving netdevice type "
+ "from cached facelet");
+ continue;
+ }
+ if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) ||
+ (netdevice_type == NETDEVICE_TYPE_UNDEFINED))
+ continue;
+
+ facelet_t *new_facelet = facelet_dup(cached_facelet);
+ facelet_unset_remote_addr(new_facelet);
+ facelet_unset_remote_port(new_facelet);
+ facelet_unset_admin_state(new_facelet);
+ facelet_unset_state(new_facelet);
+ facelet_unset_bj_done(new_facelet);
+ facelet_clear_routes(new_facelet);
+
+ /* We try to apply static_facelet over facelet */
+ if (!facelet_match(new_facelet, static_facelet)) {
+ facelet_free(new_facelet);
+ continue;
+ }
+
+ if (facelet_merge(new_facelet, static_facelet) < 0) {
+ ERROR("[facemgr_consider_static_facelet] Error merging facelets");
+ facelet_free(new_facelet);
+ continue;
+ }
+
+ /*
+ * We need to set the id before checking for existence as tuple used
+ * is (id, netdevice, family)
+ */
+ facelet_set_id(new_facelet, facemgr->cur_static_id);
+
+ facelet_found = NULL;
+ if (facelet_set_get(facemgr->facelet_cache, new_facelet, &facelet_found) <
+ 0) {
+ ERROR(
+ "[facemgr_consider_static_facelet] Error checking whether new "
+ "static facelet already exists or not");
+ continue;
+ }
+
+ /* Skip addition if facelet exists */
+ if (facelet_found) {
+ facelet_free(new_facelet);
+ continue;
+ }
+
+ facelet_set_attr_clean(new_facelet);
+ facelet_set_status(facelet, FACELET_STATUS_UNDEFINED);
+
+ if (facemgr_on_event(facemgr, new_facelet) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error creating static "
+ "facelet for existing face");
+ continue;
+ }
+
+ INFO("Successfully created static facelet for existing face");
}
+ free(facelet_array);
+ }
#endif
- return 1;
+ return 1;
}
/**
@@ -1482,93 +1407,96 @@ facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet)
* \return 0 if everything went correctly, or -1 in case of error.
* -2 means we ignored the face purposedly
*/
-int
-facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet)
-{
- assert(facelet);
+int facemgr_process_facelet_get(facemgr_t *facemgr, facelet_t *facelet) {
+ assert(facelet);
- if (!facelet_has_netdevice(facelet))
- return -2;
+ if (!facelet_has_netdevice(facelet)) return -2;
- netdevice_t netdevice;
- if (facelet_get_netdevice(facelet, &netdevice) < 0)
- return -1;
- if (!IS_VALID_NETDEVICE(netdevice))
- return -2;
+ netdevice_t netdevice;
+ if (facelet_get_netdevice(facelet, &netdevice) < 0) return -1;
+ if (!IS_VALID_NETDEVICE(netdevice)) return -2;
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
- /* Skip if face exists */
- int n = facelet_cache_lookup(facemgr->facelet_cache, facelet, NULL);
- if (n < 0) {
- ERROR("[facemgr_process_facelet_get] Error during cache lookup");
- return -1;
- }
- assert (n <= 1);
- if (n > 0)
- return 0;
-
- /* Process untagged faces */
- netdevice_type_t netdevice_type;
+ /* Skip if face exists */
+ int n = facelet_cache_lookup(facemgr->facelet_cache, facelet, NULL);
+ if (n < 0) {
+ ERROR("[facemgr_process_facelet_get] Error during cache lookup");
+ return -1;
+ }
+ assert(n <= 1);
+ if (n > 0) return 0;
+
+ /* Process untagged faces */
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ facelet_set_netdevice_type(
+ facelet, facemgr_get_netdevice_type(facemgr, netdevice.name));
if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- facelet_set_netdevice_type(facelet, facemgr_get_netdevice_type(facemgr, netdevice.name));
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- /* Inspect local address */
- int family;
- ip_address_t local;
- if (facelet_get_family(facelet, &family) < 0) {
- ERROR("[facemgr_process_facelet_get] Error getting facelet family");
- return -1;
- }
- if (facelet_get_local_addr(facelet, &local) < 0) {
- ERROR("[facemgr_process_facelet_get] Error getting facelet local address");
- return -1;
- }
- switch(family) {
- case AF_INET:
- if (ip_address_cmp(&local, &IPV4_LOOPBACK, family) == 0) {
- facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK);
- } else {
- return -2;
- }
- break;
- case AF_INET6:
- if (ip_address_cmp(&local, &IPV6_LOOPBACK, family) == 0) {
- facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK);
- } else {
- return -2;
- }
- break;
- default:
- return -2;
- }
- }
-
- if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
- return 0;
-
- if (facemgr_process_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet_get] Error processing facelet");
- return -1;
- }
- }
-
- if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) || (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
- return 0;
-
- if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) {
- ERROR("[facemgr_process_facelet_get] Error adding received facelet to cache");
+ /* Inspect local address */
+ int family;
+ ip_address_t local;
+ if (facelet_get_family(facelet, &family) < 0) {
+ ERROR("[facemgr_process_facelet_get] Error getting facelet family");
return -1;
+ }
+ if (facelet_get_local_addr(facelet, &local) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_get] Error getting facelet local "
+ "address");
+ return -1;
+ }
+ switch (family) {
+ case AF_INET:
+ if (ip_address_cmp(&local, &IPV4_LOOPBACK, family) == 0) {
+ facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK);
+ } else {
+ return -2;
+ }
+ break;
+ case AF_INET6:
+ if (ip_address_cmp(&local, &IPV6_LOOPBACK, family) == 0) {
+ facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK);
+ } else {
+ return -2;
+ }
+ break;
+ default:
+ return -2;
+ }
}
- n = facemgr_consider_static_facelet(facemgr, facelet);
- if (n < 0) {
- ERROR("[facemgr_process_facelet_get] Could not add facelet to static array");
- return -1;
+ if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) ||
+ (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
+ return -2;
+
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_get] Error processing facelet");
+ return -1;
}
+ }
+ if ((netdevice_type == NETDEVICE_TYPE_UNDEFINED) ||
+ (netdevice_type == NETDEVICE_TYPE_LOOPBACK))
+ return -2;
- return 0;
+ if (facelet_set_add(facemgr->facelet_cache, facelet) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_get] Error adding received facelet to cache");
+ return -1;
+ }
+
+ /*
+ * From there, don't raise errors otherwise the facelet just added to cache
+ * will be freed
+ */
+ n = facemgr_consider_static_facelet(facemgr, facelet);
+ if (n < 0) {
+ ERROR(
+ "[facemgr_process_facelet_get] Could not add facelet to static array");
+ }
+
+ return 0;
}
/**
@@ -1578,45 +1506,43 @@ facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet)
* \return 0 if everything went correctly, or -1 in case of error.
* -2 means we ignored the face purposedly
*/
-int
-facemgr_process_facelet_update(facemgr_t * facemgr, facelet_t * facelet)
-{
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- DEBUG("[facemgr_process_facelet_update] %s", facelet_s);
- switch(facelet_get_status(facelet)) {
- case FACELET_STATUS_UNCERTAIN:
- case FACELET_STATUS_INCOMPLETE:
- case FACELET_STATUS_CREATE:
- case FACELET_STATUS_UPDATE:
- /* No change */
- DEBUG("[facemgr_process_facelet_update] UNCHANGED STATUS");
- break;
- case FACELET_STATUS_CLEAN:
- DEBUG("[facemgr_process_facelet_update] SET STATUS TO UPDATE");
- facelet_set_status(facelet, FACELET_STATUS_UPDATE);
- break;
- case FACELET_STATUS_DOWN:
- case FACELET_STATUS_DELETE:
- case FACELET_STATUS_DELETED:
- case FACELET_STATUS_IGNORED:
- /* Reconsider face creation in light of new information */
- DEBUG("[facemgr_process_facelet_update] SET STATUS TO UNCERTAIN");
- facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN);
- break;
- case FACELET_STATUS_UNDEFINED:
- case FACELET_STATUS_N:
- ERROR("[facemgr_process_facelet_update] Unexpected facelet status");
- return -1;
- }
-
- DEBUG("[facemgr_process_facelet_update] Processing facelet");
- if (facemgr_process_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet_update] Error processing facelet");
- return -1;
- }
+int facemgr_process_facelet_update(facemgr_t *facemgr, facelet_t *facelet) {
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ DEBUG("[facemgr_process_facelet_update] %s", facelet_s);
+ switch (facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ case FACELET_STATUS_INCOMPLETE:
+ case FACELET_STATUS_CREATE:
+ case FACELET_STATUS_UPDATE:
+ /* No change */
+ DEBUG("[facemgr_process_facelet_update] UNCHANGED STATUS");
+ break;
+ case FACELET_STATUS_CLEAN:
+ DEBUG("[facemgr_process_facelet_update] SET STATUS TO UPDATE");
+ facelet_set_status(facelet, FACELET_STATUS_UPDATE);
+ break;
+ case FACELET_STATUS_DOWN:
+ case FACELET_STATUS_DELETE:
+ case FACELET_STATUS_DELETED:
+ case FACELET_STATUS_IGNORED:
+ /* Reconsider face creation in light of new information */
+ DEBUG("[facemgr_process_facelet_update] SET STATUS TO UNCERTAIN");
+ facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN);
+ break;
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet_update] Unexpected facelet status");
+ return -1;
+ }
+
+ DEBUG("[facemgr_process_facelet_update] Processing facelet");
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_update] Error processing facelet");
+ return -1;
+ }
- return 0;
+ return 0;
}
/**
@@ -1626,15 +1552,13 @@ facemgr_process_facelet_update(facemgr_t * facemgr, facelet_t * facelet)
* \return 0 if everything went correctly, or -1 in case of error.
* -2 means we ignored the face purposedly
*/
-int
-facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet)
-{
- switch(facelet_get_status(facelet)) {
- case FACELET_STATUS_UNCERTAIN:
- case FACELET_STATUS_INCOMPLETE:
- case FACELET_STATUS_IGNORED:
- case FACELET_STATUS_DOWN:
- case FACELET_STATUS_CREATE:
+int facemgr_process_facelet_delete(facemgr_t *facemgr, facelet_t *facelet) {
+ switch (facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ case FACELET_STATUS_INCOMPLETE:
+ case FACELET_STATUS_IGNORED:
+ case FACELET_STATUS_DOWN:
+ case FACELET_STATUS_CREATE:
#if 0
/* Facelets created from static get deleted */
if (facelet_get_id(facelet) > 0) {
@@ -1645,142 +1569,159 @@ facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet)
facelet_free(facelet);
} else {
#endif
- /* Face has not been created */
- DEBUG("[facemgr_process_facelet] Cleaning cached data");
- facelet_unset_local_addr(facelet);
- facelet_unset_local_port(facelet);
- if (facelet_get_id(facelet) == 0) {
- facelet_unset_remote_addr(facelet);
- facelet_unset_remote_port(facelet);
- facelet_clear_routes(facelet);
- }
- facelet_unset_admin_state(facelet);
- facelet_unset_state(facelet);
- facelet_unset_bj_done(facelet);
-#ifdef WITH_FACEMGR_UTILITY
- facelet_unset_au_done(facelet);
-#endif /* WITH_FACEMGR_UTILITY */
- facelet_unset_error(facelet);
- facelet_set_status(facelet, FACELET_STATUS_DELETED);
+ /* Face has not been created */
+ DEBUG("[facemgr_process_facelet] Cleaning cached data");
+ facelet_unset_local_addr(facelet);
+ facelet_unset_local_port(facelet);
+ if (facelet_get_id(facelet) == 0) {
+ facelet_unset_remote_addr(facelet);
+ facelet_unset_remote_port(facelet);
+ facelet_clear_routes(facelet);
+ }
+ facelet_unset_admin_state(facelet);
+ facelet_unset_state(facelet);
+ facelet_unset_bj_done(facelet);
+ facelet_unset_error(facelet);
+ facelet_set_status(facelet, FACELET_STATUS_DELETED);
#if 0
}
#endif
- break;
-
- case FACELET_STATUS_UPDATE:
- case FACELET_STATUS_CLEAN:
- facelet_set_status(facelet, FACELET_STATUS_DELETE);
- if (facemgr_process_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_facelet_delete] Error processing facelet");
- return -1;
- }
- break;
+ break;
- case FACELET_STATUS_DELETE:
- case FACELET_STATUS_DELETED:
- /* Nothing to do */
- break;
+ case FACELET_STATUS_UPDATE:
+ case FACELET_STATUS_CLEAN:
+ facelet_set_status(facelet, FACELET_STATUS_DELETE);
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_delete] Error processing facelet");
+ return -1;
+ }
+ break;
- case FACELET_STATUS_UNDEFINED:
- case FACELET_STATUS_N:
- ERROR("[facemgr_process_facelet_delete] Unexpected facelet status");
- return -1;
- }
+ case FACELET_STATUS_DELETE:
+ case FACELET_STATUS_DELETED:
+ /* Nothing to do */
+ break;
- return 0;
-}
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet_delete] Unexpected facelet status");
+ return -1;
+ }
-int
-facemgr_process_facelet_create_no_family(facemgr_t * facemgr, facelet_t * facelet)
-{
+ return 0;
+}
+int facemgr_process_facelet_create_no_family(facemgr_t *facemgr,
+ facelet_t *facelet) {
#ifdef WITH_DEFAULT_PRIORITIES
- /* Assign default priority based on face type */
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error getting netdevice_type: no default priority set.");
- goto ERR_PRIORITY;
- }
- if (facelet_set_priority(facelet, facemgr->default_priority[netdevice_type]) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error setting default priority");
- }
+ /* Assign default priority based on face type */
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error getting "
+ "netdevice_type: no default priority set.");
+ goto ERR_PRIORITY;
+ }
+ if (facelet_set_priority(facelet, facemgr->default_priority[netdevice_type]) <
+ 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error setting default "
+ "priority");
+ }
ERR_PRIORITY:
#endif /* WITH_DEFAULT_PRIORITIES */
- DEBUG("[facemgr_process_facelet_create_no_family] Default v4");
- /* Create default v4 and v6 facelets */
- facelet_t * facelet_v4 = facelet_dup(facelet);
- if (!facelet_v4) {
- ERROR("[facemgr_process_facelet_create_no_family] Error allocating default IPv4 face");
- } else {
- facelet_set_family(facelet_v4, AF_INET);
- facelet_set_attr_clean(facelet_v4);
- if (facemgr_on_event(facemgr, facelet_v4) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error creating default IPv4 face");
- //facelet_free(facelet_v4);
- }
- }
-
- DEBUG("[facemgr_process_facelet_create_no_family] Default v6");
- facelet_t * facelet_v6 = facelet_dup(facelet);
- if (!facelet_v6) {
- ERROR("[facemgr_process_facelet_create_no_family] Error allocating default IPv6 face");
- } else {
- facelet_set_family(facelet_v6, AF_INET6);
- facelet_set_attr_clean(facelet_v6);
- if (facemgr_on_event(facemgr, facelet_v6) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error creating default IPv6 face");
- //facelet_free(facelet_v6);
- }
+ DEBUG("[facemgr_process_facelet_create_no_family] Default v4");
+ /* Create default v4 and v6 facelets */
+ facelet_t *facelet_v4 = facelet_dup(facelet);
+ if (!facelet_v4) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error allocating default "
+ "IPv4 face");
+ } else {
+ facelet_set_family(facelet_v4, AF_INET);
+ facelet_set_attr_clean(facelet_v4);
+ if (facemgr_on_event(facemgr, facelet_v4) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error creating default "
+ "IPv4 face");
+ // facelet_free(facelet_v4);
+ }
+ }
+
+ DEBUG("[facemgr_process_facelet_create_no_family] Default v6");
+ facelet_t *facelet_v6 = facelet_dup(facelet);
+ if (!facelet_v6) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error allocating default "
+ "IPv6 face");
+ } else {
+ facelet_set_family(facelet_v6, AF_INET6);
+ facelet_set_attr_clean(facelet_v6);
+ if (facemgr_on_event(facemgr, facelet_v6) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error creating default "
+ "IPv6 face");
+ // facelet_free(facelet_v6);
+ }
+ }
+
+ /* Create additional connections
+ *
+ * This is where we spawn multiple facelets based on the
+ * configured "static routes" in addition to the default
+ * routes managed by the face manager.
+ */
+ DEBUG("[facemgr_process_facelet_create_no_family] Loop static");
+ for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) {
+ facelet_t *static_facelet;
+ if (facelet_array_get_index(facemgr->static_facelets, i, &static_facelet) <
+ 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error getting static "
+ "facelet");
+ continue;
}
- /* Create additional connections
- *
- * This is where we spawn multiple facelets based on the
- * configured "static routes" in addition to the default
- * routes managed by the face manager.
+ /*
+ * We don't enforce any present or absent fields. A match
+ * operation will be performed deciding whether to create
+ * the facelet (if it bring additional information to the
+ * ingress one) or not.
*/
- DEBUG("[facemgr_process_facelet_create_no_family] Loop static");
- for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) {
- facelet_t * static_facelet;
- if (facelet_array_get_index(facemgr->static_facelets, i, &static_facelet) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error getting static facelet");
- continue;
- }
-
- /*
- * We don't enforce any present or absent fields. A match
- * operation will be performed deciding whether to create
- * the facelet (if it bring additional information to the
- * ingress one) or not.
- */
- /* We try to apply static_facelet over facelet */
- if (!facelet_match(facelet, static_facelet)) {
- continue;
- }
-
- facelet_t * facelet_new = facelet_dup(facelet);
- if (!facelet_new) {
- ERROR("[facemgr_process_facelet_create_no_family] Error allocating static facelet");
- continue;
- } else {
- if (facelet_merge(facelet_new, static_facelet) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error merging facelets");
- facelet_free(facelet_new);
- continue;
- }
- facelet_set_id(facelet_new, facelet_get_id(static_facelet));
- facelet_set_attr_clean(facelet_new);
- facelet_set_status(facelet, FACELET_STATUS_UNDEFINED);
-
- if (facemgr_on_event(facemgr, facelet_new) < 0) {
- ERROR("[facemgr_process_facelet_create_no_family] Error creating default IPv6 face");
- //facelet_free(facelet_new);
- }
- }
+ /* We try to apply static_facelet over facelet */
+ if (!facelet_match(facelet, static_facelet)) {
+ continue;
}
- return 0;
+ facelet_t *facelet_new = facelet_dup(facelet);
+ if (!facelet_new) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error allocating static "
+ "facelet");
+ continue;
+ } else {
+ if (facelet_merge(facelet_new, static_facelet) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error merging "
+ "facelets");
+ facelet_free(facelet_new);
+ continue;
+ }
+ facelet_set_id(facelet_new, facelet_get_id(static_facelet));
+ facelet_set_attr_clean(facelet_new);
+ facelet_set_status(facelet, FACELET_STATUS_UNDEFINED);
+
+ if (facemgr_on_event(facemgr, facelet_new) < 0) {
+ ERROR(
+ "[facemgr_process_facelet_create_no_family] Error creating default "
+ "IPv6 face");
+ // facelet_free(facelet_new);
+ }
+ }
+ }
+
+ return 0;
}
/**
@@ -1790,30 +1731,29 @@ ERR_PRIORITY:
* - Any event or timeout due to an interface triggers either a local cache
* update, as well a face operations needed to resync the state.
*/
-int
-facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
-{
- bool remove_facelet = true;
+int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet_in) {
+ bool remove_facelet = true;
#if WITH_DUMP
- bool dump = true;
+ bool dump = true;
#endif /* WITH_DUMP */
- int ret = 0;
- int rc;
- assert(facelet_in);
-
- /* Update Netdevice type */
- if ((facelet_get_event(facelet_in) != FACELET_EVENT_GET) &&
- facelet_has_netdevice(facelet_in) &&
- (!facelet_has_netdevice_type(facelet_in))) {
- netdevice_t netdevice = NETDEVICE_EMPTY;
+ int ret = 0;
+ int rc;
+ assert(facelet_in);
+
+ /* Update Netdevice type */
+ if ((facelet_get_event(facelet_in) != FACELET_EVENT_GET) &&
+ facelet_has_netdevice(facelet_in) &&
+ (!facelet_has_netdevice_type(facelet_in))) {
+ netdevice_t netdevice = NETDEVICE_EMPTY;
- rc = facelet_get_netdevice(facelet_in, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_on_event] Error retrieving netdevice from facelet");
- return -1;
- }
- facelet_set_netdevice_type(facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name));
+ rc = facelet_get_netdevice(facelet_in, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_on_event] Error retrieving netdevice from facelet");
+ return -1;
}
+ facelet_set_netdevice_type(
+ facelet_in, facemgr_get_netdevice_type(facemgr, netdevice.name));
+ }
#if 0
netdevice_type_t netdevice_type;
@@ -1826,656 +1766,660 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
return 0;
#endif
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in);
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in);
- facelet_t ** cached_facelets = NULL;
- assert(facelet_in);
+ facelet_t **cached_facelets = NULL;
+ assert(facelet_in);
- if (facelet_get_status(facelet_in) == FACELET_STATUS_UNDEFINED) {
- facelet_set_status(facelet_in, FACELET_STATUS_UNCERTAIN);
- }
+ if (facelet_get_status(facelet_in) == FACELET_STATUS_UNDEFINED) {
+ facelet_set_status(facelet_in, FACELET_STATUS_UNCERTAIN);
+ }
- int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in, &cached_facelets);
- if (n < 0) {
- ERROR("[facemgr_on_event] Error during cache lookup");
- free(facelet_in);
- return -1;
- }
- if (n == 0) {
- /* This is a new facelet... we expect a CREATE event. */
- switch(facelet_get_event(facelet_in)) {
- case FACELET_EVENT_CREATE:
- {
- /*
- * This is the first time we hear about a facelet, it will
- * likely not have an address family
- *
- * Assumption: we should always see the link before the address
- * assignment
- */
- DEBUG("[facemgr_on_event] CREATE NEW %s", facelet_s);
-
- if (!facelet_has_family(facelet_in)) {
- facemgr_assign_face_type(facemgr, facelet_in);
- if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error processing new interface event");
- goto ERR;
- }
- goto DUMP_CACHE;
- }
+ int n = facelet_cache_lookup(facemgr->facelet_cache, facelet_in,
+ &cached_facelets);
+ if (n < 0) {
+ ERROR("[facemgr_on_event] Error during cache lookup");
+ free(facelet_in);
+ return -1;
+ }
+ if (n == 0) {
+ /* This is a new facelet... we expect a CREATE event. */
+ switch (facelet_get_event(facelet_in)) {
+ case FACELET_EVENT_CREATE: {
+ /*
+ * This is the first time we hear about a facelet, it will
+ * likely not have an address family
+ *
+ * Assumption: we should always see the link before the address
+ * assignment
+ */
+ DEBUG("[facemgr_on_event] CREATE NEW %s", facelet_s);
- if (facelet_set_add(facemgr->facelet_cache, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error adding facelet to cache");
- goto ERR;
- }
+ if (!facelet_has_family(facelet_in)) {
+ facemgr_assign_face_type(facemgr, facelet_in);
+ if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) <
+ 0) {
+ ERROR("[facemgr_on_event] Error processing new interface event");
+ goto ERR;
+ }
+ goto DUMP_CACHE;
+ }
- if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error processing facelet CREATE event");
- ret = -1;
- }
+ if (facelet_set_add(facemgr->facelet_cache, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error adding facelet to cache");
+ goto ERR;
+ }
- remove_facelet = false;
+ if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet CREATE event");
+ ret = -1;
+ }
- break;
- }
+ remove_facelet = false;
- case FACELET_EVENT_GET:
- /* Insert new facelet in cached */
- //DEBUG("[facemgr_on_event] GET NEW %s", facelet_s);
- rc = facemgr_process_facelet_get(facemgr, facelet_in);
- if (rc == 0)
- remove_facelet = false;
+ break;
+ }
+
+ case FACELET_EVENT_GET:
+ /* Insert new facelet in cached */
+ // DEBUG("[facemgr_on_event] GET NEW %s", facelet_s);
+ rc = facemgr_process_facelet_get(facemgr, facelet_in);
+ if (rc == 0) remove_facelet = false;
#if WITH_DUMP
- dump = false;
+ dump = false;
#endif
- if (rc == -1) {
- ERROR("[facemgr_on_event] Error processing GET event");
- goto ERR;
- }
- break;
+ if (rc == -1) {
+ ERROR("[facemgr_on_event] Error processing GET event");
+ goto ERR;
+ }
+ break;
- case FACELET_EVENT_UPDATE:
- /* Might be because we previously ignored the facelet... */
- //ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist");
- //goto ERR;
+ case FACELET_EVENT_UPDATE:
+ /* Might be because we previously ignored the facelet... */
+ // ERROR("[facemgr_on_event] Unexpected UPDATE... face does not exist");
+ // goto ERR;
#ifdef WITH_DEFAULT_PRIORITIES
- if (facelet_has_netdevice_type(facelet_in) && !facelet_has_netdevice(facelet_in) && facelet_has_priority(facelet_in)) {
- /* Remember last priority choice for newly created facelets */
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
- u32 priority = 0;
- if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) {
- ERROR("[facelet_on_event] Error getting netdevice_type");
- goto ERR;
- }
- if (facelet_get_priority(facelet_in, &priority) < 0) {
- ERROR("[facelet_on_event] Error getting priority");
- goto ERR;
- }
- facemgr->default_priority[netdevice_type] = priority;
- }
+ if (facelet_has_netdevice_type(facelet_in) &&
+ !facelet_has_netdevice(facelet_in) &&
+ facelet_has_priority(facelet_in)) {
+ /* Remember last priority choice for newly created facelets */
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ u32 priority = 0;
+ if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) {
+ ERROR("[facelet_on_event] Error getting netdevice_type");
+ goto ERR;
+ }
+ if (facelet_get_priority(facelet_in, &priority) < 0) {
+ ERROR("[facelet_on_event] Error getting priority");
+ goto ERR;
+ }
+ facemgr->default_priority[netdevice_type] = priority;
+ }
#endif /* WITH_DEFAULT_PRIORITIES */
- DEBUG("[facemgr_on_event] UPDATE NEW %s", facelet_s);
- INFO("Ignored UPDATE for non-existing face");
- break;
+ DEBUG("[facemgr_on_event] UPDATE NEW %s", facelet_s);
+ INFO("Ignored UPDATE for non-existing face");
+ break;
- case FACELET_EVENT_DELETE:
- DEBUG("[facemgr_on_event] DELETE NEW %s", facelet_s);
- ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist");
- goto ERR;
-
- case FACELET_EVENT_SET_UP:
- case FACELET_EVENT_SET_DOWN:
- ERROR("[facemgr_on_event] Unexpected event on a face that does not exist");
- goto ERR;
+ case FACELET_EVENT_DELETE:
+ DEBUG("[facemgr_on_event] DELETE NEW %s", facelet_s);
+ ERROR("[facemgr_on_event] Unexpected DELETE... face does not exist");
+ goto ERR;
- case FACELET_EVENT_UNDEFINED:
- case FACELET_EVENT_N:
- ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
- ret = -1;
- goto ERR;
+ case FACELET_EVENT_SET_UP:
+ case FACELET_EVENT_SET_DOWN:
+ ERROR(
+ "[facemgr_on_event] Unexpected event on a face that does not "
+ "exist");
+ goto ERR;
- }
- goto DUMP_CACHE;
+ case FACELET_EVENT_UNDEFINED:
+ case FACELET_EVENT_N:
+ ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
+ ret = -1;
+ goto ERR;
}
+ goto DUMP_CACHE;
+ }
+ /*
+ * From now on, it should not make any difference whether we have one or
+ * more facelet.
+ */
+ for (unsigned i = 0; i < n; i++) {
/*
- * From now on, it should not make any difference whether we have one or
- * more facelet.
+ * We merge each cached facelet with incoming one, and perform state
+ * reconciliation by sending appropriate updates to the forwarder
*/
- for (unsigned i = 0; i < n; i ++) {
+ facelet_t *facelet = cached_facelets[i];
+
+ char facelet_old_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_old_s, MAXSZ_FACELET, facelet);
+ // DEBUG("Facelet from cache #%d %s", i, facelet_s);
+
+ switch (facelet_get_event(facelet_in)) {
+ case FACELET_EVENT_CREATE:
/*
- * We merge each cached facelet with incoming one, and perform state
- * reconciliation by sending appropriate updates to the forwarder
+ * This can occur for a facelet already in cache but that has
+ * been previously deleted... we need to be able to consider
+ * static facelets in this situation too...
*/
- facelet_t * facelet = cached_facelets[i];
-
- char facelet_old_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_old_s, MAXSZ_FACELET, facelet);
- //DEBUG("Facelet from cache #%d %s", i, facelet_s);
-
- switch(facelet_get_event(facelet_in)) {
- case FACELET_EVENT_CREATE:
- /*
- * This can occur for a facelet already in cache but that has
- * been previously deleted... we need to be able to consider
- * static facelets in this situation too...
- */
- DEBUG("[facemgr_on_event] CREATE EXISTING %s", facelet_s);
-
- if (!facelet_has_family(facelet_in)) {
- if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error processing new interface event");
- goto ERR;
- }
- goto DUMP_CACHE;
- }
+ DEBUG("[facemgr_on_event] CREATE EXISTING %s", facelet_s);
- // This case will occur when we try to re-create existing faces,
- // eg. in the situation of a forwarder restarting.
- // likely this occurs when the interface receives a (potentially new) address
- if (facelet_merge(facelet, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error merging facelets");
- continue;
- }
+ if (!facelet_has_family(facelet_in)) {
+ if (facemgr_process_facelet_create_no_family(facemgr, facelet_in) <
+ 0) {
+ ERROR("[facemgr_on_event] Error processing new interface event");
+ goto ERR;
+ }
+ goto DUMP_CACHE;
+ }
- if (facemgr_process_facelet_create(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing facelet CREATE event");
- ret = -1;
- }
+ // This case will occur when we try to re-create existing faces,
+ // eg. in the situation of a forwarder restarting.
+ // likely this occurs when the interface receives a (potentially new)
+ // address
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
- continue;
+ if (facemgr_process_facelet_create(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet CREATE event");
+ ret = -1;
+ }
- case FACELET_EVENT_GET: /* should be an INFORM message */
- /*
- * This happens due to polling of the forwarder (or when it
- * restarts)
- */
- //DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_old_s);
- //DEBUG(" WITH %s", facelet_s);
- //ERROR("[facemgr_on_event] GET event for a face that already exists...");
+ continue;
+
+ case FACELET_EVENT_GET: /* should be an INFORM message */
+ /*
+ * This happens due to polling of the forwarder (or when it
+ * restarts)
+ */
+ // DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_old_s);
+ // DEBUG(" WITH %s", facelet_s);
+ // ERROR("[facemgr_on_event] GET event for a face that already
+ // exists...");
#ifdef WITH_DUMP
- dump = false;
+ dump = false;
#endif /* WITH_DUMP */
- continue;
+ continue;
- case FACELET_EVENT_UPDATE:
- DEBUG("[facemgr_on_event] UPDATE EXISTING %s", facelet_old_s);
- DEBUG(" WITH %s", facelet_s);
+ case FACELET_EVENT_UPDATE:
+ DEBUG("[facemgr_on_event] UPDATE EXISTING %s", facelet_old_s);
+ DEBUG(" WITH %s", facelet_s);
#ifdef WITH_DEFAULT_PRIORITIES
- if (facelet_has_netdevice_type(facelet_in) && !facelet_has_netdevice(facelet_in) && facelet_has_priority(facelet_in)) {
- /* Remember last priority choice for newly created facelets */
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
- u32 priority = 0;
- if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) {
- ERROR("[facelet_on_event] Error getting netdevice_type");
- goto ERR;
- }
- if (facelet_get_priority(facelet_in, &priority) < 0) {
- ERROR("[facelet_on_event] Error getting priority");
- goto ERR;
- }
- facemgr->default_priority[netdevice_type] = priority;
- }
+ if (facelet_has_netdevice_type(facelet_in) &&
+ !facelet_has_netdevice(facelet_in) &&
+ facelet_has_priority(facelet_in)) {
+ /* Remember last priority choice for newly created facelets */
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ u32 priority = 0;
+ if (facelet_get_netdevice_type(facelet_in, &netdevice_type) < 0) {
+ ERROR("[facelet_on_event] Error getting netdevice_type");
+ goto ERR;
+ }
+ if (facelet_get_priority(facelet_in, &priority) < 0) {
+ ERROR("[facelet_on_event] Error getting priority");
+ goto ERR;
+ }
+ facemgr->default_priority[netdevice_type] = priority;
+ }
#endif /* WITH_DEFAULT_PRIORITIES */
- if (facelet_merge(facelet, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error merging facelets");
- continue;
- }
- if (facemgr_process_facelet_update(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing facelet UPDATE event");
- ret = -1;
- }
- continue;
-
- case FACELET_EVENT_DELETE:
- DEBUG("[facemgr_on_event] DELETE EXISTING %s", facelet_old_s);
- DEBUG(" WITH %s", facelet_s);
- if (facelet_merge(facelet, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error merging facelets");
- continue;
- }
- if (facemgr_process_facelet_delete(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing facelet DELETE event");
- ret = -1;
- }
- continue;
-
- case FACELET_EVENT_SET_UP:
- ERROR("[facemgr_on_event] Not implemented\n");
- ret = -1;
- continue;
-
- case FACELET_EVENT_SET_DOWN:
- DEBUG("[facemgr_on_event] SET DOWN EXISTING %s", facelet_old_s);
- DEBUG(" WITH %s", facelet_s);
- /* We don't even need to merge */
- if (facelet_merge(facelet, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error merging facelets");
- continue;
- }
- if (facemgr_process_facelet_delete(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing facelet DELETE event");
- continue;
- }
- continue;
-
- case FACELET_EVENT_UNDEFINED:
- case FACELET_EVENT_N:
- ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
- ret = -1;
- goto ERR;
-
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
}
+ if (facemgr_process_facelet_update(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet UPDATE event");
+ ret = -1;
+ }
+ continue;
+
+ case FACELET_EVENT_DELETE:
+ DEBUG("[facemgr_on_event] DELETE EXISTING %s", facelet_old_s);
+ DEBUG(" WITH %s", facelet_s);
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
+ if (facemgr_process_facelet_delete(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet DELETE event");
+ ret = -1;
+ }
+ continue;
+
+ case FACELET_EVENT_SET_UP:
+ ERROR("[facemgr_on_event] Not implemented\n");
+ ret = -1;
+ continue;
+
+ case FACELET_EVENT_SET_DOWN:
+ DEBUG("[facemgr_on_event] SET DOWN EXISTING %s", facelet_old_s);
+ DEBUG(" WITH %s", facelet_s);
+ /* We don't even need to merge */
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
+ if (facemgr_process_facelet_delete(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet DELETE event");
+ continue;
+ }
+ continue;
+ case FACELET_EVENT_UNDEFINED:
+ case FACELET_EVENT_N:
+ ERROR("[facemgr_on_event] Unexpected UNDEFINED event.");
+ ret = -1;
+ goto ERR;
}
- goto DUMP_CACHE;
+ }
+ goto DUMP_CACHE;
ERR:
- ret = -1;
+ ret = -1;
DUMP_CACHE:
#if WITH_DUMP
- if (dump) {
- DEBUG(" <CACHE>");
- facelet_set_dump(facemgr->facelet_cache);
- DEBUG(" </CACHE>");
- DEBUG("</EVENT ret=%d>", ret);
- DEBUG("----------------------------------");
- }
+ if (dump) {
+ DEBUG(" <CACHE>");
+ facelet_set_dump(facemgr->facelet_cache);
+ DEBUG(" </CACHE>");
+ DEBUG("</EVENT ret=%d>", ret);
+ DEBUG("----------------------------------");
+ }
#endif /* WITH_DUMP */
- free(cached_facelets);
+ free(cached_facelets);
- if (remove_facelet)
- facelet_free(facelet_in);
+ if (remove_facelet) facelet_free(facelet_in);
- if (ret == -1) {
- INFO("Error... starting reattempts");
- facemgr_start_reattempts(facemgr);
- }
+ if (ret == -1) {
+ INFO("Error... starting reattempts");
+ facemgr_start_reattempts(facemgr);
+ }
- return ret;
+ return ret;
}
-int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data)
-{
- switch(type) {
- case INTERFACE_CB_TYPE_RAISE_EVENT:
- return facemgr_on_event(facemgr, data);
-
- case INTERFACE_CB_TYPE_REGISTER_FD:
- {
- /* Remember fd for further release */
- fd_callback_data_t * fd_callback_data = data;
- interface_t * interface = (interface_t*)(fd_callback_data->owner);
-
- interface_map_data_t * interface_map_data = NULL;
- if (interface_map_get(facemgr->interface_map, interface->name, &interface_map_data) < 0) {
- ERROR("[facemgr_callback] Error getting interface map data");
- return -1;
- }
- if (!interface_map_data) {
- ERROR("[facemgr_callback] No entry in interface map data");
- return -1;
- }
- interface_map_data->fds[interface_map_data->num_fds++] = fd_callback_data->fd;
+int facemgr_callback(facemgr_t *facemgr, interface_cb_type_t type, void *data) {
+ switch (type) {
+ case INTERFACE_CB_TYPE_RAISE_EVENT:
+ return facemgr_on_event(facemgr, data);
- return facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_REGISTER_FD, data);
- }
+ case INTERFACE_CB_TYPE_REGISTER_FD: {
+ /* Remember fd for further release */
+ fd_callback_data_t *fd_callback_data = data;
+ interface_t *interface = (interface_t *)(fd_callback_data->owner);
- case INTERFACE_CB_TYPE_UNREGISTER_FD:
- {
- fd_callback_data_t * fd_callback_data = data;
- interface_t * interface = (interface_t*)(fd_callback_data->owner);
+ interface_map_data_t *interface_map_data = NULL;
+ if (interface_map_get(facemgr->interface_map, interface->name,
+ &interface_map_data) < 0) {
+ ERROR("[facemgr_callback] Error getting interface map data");
+ return -1;
+ }
+ if (!interface_map_data) {
+ ERROR("[facemgr_callback] No entry in interface map data");
+ return -1;
+ }
+ interface_map_data->fds[interface_map_data->num_fds++] =
+ fd_callback_data->fd;
- interface_map_data_t * interface_map_data = NULL;
- if (interface_map_get(facemgr->interface_map, interface->name, &interface_map_data) < 0) {
- ERROR("[facemgr_callback] Error getting interface map data");
- return -1;
- }
- if (!interface_map_data) {
- ERROR("[facemgr_callback] No entry in interface map data");
- return -1;
- }
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_REGISTER_FD, data);
+ }
- for (unsigned i = 0; i < interface_map_data->num_fds; i++) {
- if (interface_map_data->fds[i] == fd_callback_data->fd) {
- interface_map_data->fds[i] = interface_map_data->fds[--interface_map_data->num_fds];
- break;
- }
- }
+ case INTERFACE_CB_TYPE_UNREGISTER_FD: {
+ fd_callback_data_t *fd_callback_data = data;
+ interface_t *interface = (interface_t *)(fd_callback_data->owner);
- return facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_UNREGISTER_FD, data);
+ interface_map_data_t *interface_map_data = NULL;
+ if (interface_map_get(facemgr->interface_map, interface->name,
+ &interface_map_data) < 0) {
+ ERROR("[facemgr_callback] Error getting interface map data");
+ return -1;
+ }
+ if (!interface_map_data) {
+ ERROR("[facemgr_callback] No entry in interface map data");
+ return -1;
+ }
+
+ for (unsigned i = 0; i < interface_map_data->num_fds; i++) {
+ if (interface_map_data->fds[i] == fd_callback_data->fd) {
+ interface_map_data->fds[i] =
+ interface_map_data->fds[--interface_map_data->num_fds];
+ break;
}
+ }
- case INTERFACE_CB_TYPE_REGISTER_TIMER:
- return facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_REGISTER_TIMER, data);
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_FD, data);
+ }
- case INTERFACE_CB_TYPE_UNREGISTER_TIMER:
- return facemgr->callback(facemgr->callback_owner,
- FACEMGR_CB_TYPE_UNREGISTER_TIMER, data);
+ case INTERFACE_CB_TYPE_REGISTER_TIMER:
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_REGISTER_TIMER, data);
- }
- return -1;
+ case INTERFACE_CB_TYPE_UNREGISTER_TIMER:
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER, data);
+ }
+ return -1;
}
-int
-facemgr_bootstrap(facemgr_t * facemgr)
-{
- int rc;
+int facemgr_bootstrap(facemgr_t *facemgr) {
+ int rc;
- DEBUG("Registering interfaces...");
- rc = interface_register(&hicn_light_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering hicn_light interface");
- goto ERR_REGISTER;
- }
+ DEBUG("Registering interfaces...");
+ rc = interface_register(&hicn_light_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering hicn_light interface");
+ goto ERR_REGISTER;
+ }
#ifdef __APPLE__
- rc = interface_register(&network_framework_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering network_framework interface");
- goto ERR_REGISTER;
- }
+ rc = interface_register(&network_framework_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering network_framework interface");
+ goto ERR_REGISTER;
+ }
#endif /* __APPLE__ */
#ifdef __linux__
- rc = interface_register(&netlink_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering netlink interface");
- goto ERR_REGISTER;
- }
+#ifdef __ANDROID__
+ rc = interface_register(&android_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering android interface");
+ goto ERR_REGISTER;
+ }
+#else
+ rc = interface_register(&netlink_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering netlink interface");
+ goto ERR_REGISTER;
+ }
+#endif /* __ANDROID__ */
- rc = interface_register(&bonjour_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering bonjour interface");
- goto ERR_REGISTER;
- }
+ rc = interface_register(&bonjour_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering bonjour interface");
+ goto ERR_REGISTER;
+ }
#endif /* __linux__ */
-#ifdef WITH_FACEMGR_UTILITY
- rc = interface_register(&android_utility_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering android_utility interface");
- goto ERR_REGISTER;
- }
-#endif /* WITH_FACEMGR_UTILITY */
-
#ifdef WITH_PRIORITY_CONTROLLER
- INFO("[facemgr_bootstrap] registering priority_controller interface");
- rc = interface_register(&priority_controller_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering priority_controller interface");
- goto ERR_REGISTER;
- }
+ INFO("[facemgr_bootstrap] registering priority_controller interface");
+ rc = interface_register(&priority_controller_ops);
+ if (rc < 0) {
+ ERROR(
+ "[facemgr_bootstrap] Error registering priority_controller interface");
+ goto ERR_REGISTER;
+ }
#endif
#ifdef WITH_EXAMPLE_DUMMY
- rc = interface_register(&dummy_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering dummy interface");
- goto ERR_REGISTER;
- }
+ rc = interface_register(&dummy_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering dummy interface");
+ goto ERR_REGISTER;
+ }
#endif
#ifdef WITH_EXAMPLE_UPDOWN
- rc = interface_register(&updown_ops);
- if (rc < 0) {
- ERROR("[facemgr_bootstrap] Error registering updown interface");
- goto ERR_REGISTER;
- }
+ rc = interface_register(&updown_ops);
+ if (rc < 0) {
+ ERROR("[facemgr_bootstrap] Error registering updown interface");
+ goto ERR_REGISTER;
+ }
#endif
- rc = facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl);
- if (rc < 0) {
- ERROR("Error creating 'hICN forwarder (hicn-light)' interface\n");
- goto ERR_HL_CREATE;
- }
-
#ifdef __APPLE__
- network_framework_cfg_t nf_cfg = {
- };
- rc = facemgr_create_interface(facemgr, "nf", "network_framework", &nf_cfg, &facemgr->nf);
- if (rc < 0) {
- ERROR("Error creating 'Apple Network Framework' interface\n");
- goto ERR_NF_CREATE;
- }
+ network_framework_cfg_t nf_cfg = {};
+ rc = facemgr_create_interface(facemgr, "nf", "network_framework", &nf_cfg,
+ &facemgr->nf);
+ if (rc < 0) {
+ ERROR("Error creating 'Apple Network Framework' interface\n");
+ goto ERR_NF_CREATE;
+ }
#endif /* __APPLE__ */
#ifdef __linux__
- rc = facemgr_create_interface(facemgr, "nl", "netlink", NULL, &facemgr->nl);
- if (rc < 0) {
- ERROR("Error creating 'Netlink' interface\n");
- goto ERR_NL_CREATE;
- }
+#ifdef __ANDROID__
+ android_cfg_t android_cfg = {
+ .jvm = facemgr->jvm,
+ };
+ rc = facemgr_create_interface(facemgr, "android", "android", &android_cfg,
+ &facemgr->android);
+ if (rc < 0) {
+ ERROR("Error creating 'Android' interface\n");
+ goto ERR_ANDROID_CREATE;
+ }
+#else
+ rc = facemgr_create_interface(facemgr, "nl", "netlink", NULL, &facemgr->nl);
+ if (rc < 0) {
+ ERROR("Error creating 'Netlink' interface\n");
+ goto ERR_NL_CREATE;
+ }
+#endif /* __ANDROID__ */
#endif /* __linux__ */
-#ifdef WITH_FACEMGR_UTILITY
- android_utility_cfg_t au_cfg = {
- .jvm = facemgr->jvm,
- };
- rc = facemgr_create_interface(facemgr, "au", "android_utility", &au_cfg, &facemgr->au);
- if (rc < 0) {
- ERROR("Error creating 'Android Utility' interface\n");
- goto ERR_AU_CREATE;
- }
-#endif /* WITH_FACEMGR_UTILITY */
-
#ifdef WITH_PRIORITY_CONTROLLER
- INFO("[facemgr_bootstrap] creating priority_controller interface");
- priority_controller_cfg_t pc_cfg = {
+ INFO("[facemgr_bootstrap] creating priority_controller interface");
+ priority_controller_cfg_t pc_cfg = {
#ifdef PRIORITY_CONTROLLER_INTERNAL
- .jvm = facemgr->jvm,
+ .jvm = facemgr->jvm,
#endif /* PRIORITY_CONTROLLER_INTERNAL */
- };
- rc = facemgr_create_interface(facemgr, "pc", "priority_controller", &pc_cfg, &facemgr->pc);
- if (rc < 0) {
- ERROR("Error creating 'Priority Controller' interface\n");
- goto ERR_PC_CREATE;
- }
+ };
+ rc = facemgr_create_interface(facemgr, "pc", "priority_controller", &pc_cfg,
+ &facemgr->pc);
+ if (rc < 0) {
+ ERROR("Error creating 'Priority Controller' interface\n");
+ goto ERR_PC_CREATE;
+ }
#endif
#ifdef WITH_EXAMPLE_DUMMY
- rc = facemgr_create_interface(facemgr, "dummy0", "dummy", NULL, &facemgr->dummy);
- if (rc < 0) {
- ERROR("Error creating 'dummy' interface\n");
- goto ERR_DUMMY_CREATE;
- }
+ rc = facemgr_create_interface(facemgr, "dummy0", "dummy", NULL,
+ &facemgr->dummy);
+ if (rc < 0) {
+ ERROR("Error creating 'dummy' interface\n");
+ goto ERR_DUMMY_CREATE;
+ }
#endif
#ifdef WITH_EXAMPLE_UPDOWN
- rc = facemgr_create_interface(facemgr, "updown0", "updown", NULL, &facemgr->updown);
- if (rc < 0) {
- ERROR("Error creating 'updown' interface\n");
- goto ERR_UPDOWN_CREATE;
- }
+ rc = facemgr_create_interface(facemgr, "updown0", "updown", NULL,
+ &facemgr->updown);
+ if (rc < 0) {
+ ERROR("Error creating 'updown' interface\n");
+ goto ERR_UPDOWN_CREATE;
+ }
#endif
- DEBUG("Facemgr successfully initialized...");
+ rc =
+ facemgr_create_interface(facemgr, "hl", "hicn_light", NULL, &facemgr->hl);
+ if (rc < 0) {
+ ERROR("Error creating 'hICN forwarder (hicn-light)' interface\n");
+ goto ERR_HL_CREATE;
+ }
- return 0;
+ DEBUG("Facemgr successfully initialized...");
+
+ return 0;
+ERR_HL_CREATE:
#ifdef WITH_EXAMPLE_UPDOWN
- facemgr_delete_interface(facemgr, facemgr->updown);
+ facemgr_delete_interface(facemgr, facemgr->updown);
ERR_UPDOWN_CREATE:
#endif
+
#ifdef WITH_EXAMPLE_DUMMY
- facemgr_delete_interface(facemgr, facemgr->dummy);
+ facemgr_delete_interface(facemgr, facemgr->dummy);
ERR_DUMMY_CREATE:
#endif
-#ifdef WITH_FACEMGR_UTILITY
- facemgr_delete_interface(facemgr, facemgr->au);
-ERR_AU_CREATE:
-#endif /* WITH_FACEMGR_UTILITY */
+
#ifdef WITH_PRIORITY_CONTROLLER
- facemgr_delete_interface(facemgr, facemgr->pc);
+ facemgr_delete_interface(facemgr, facemgr->pc);
ERR_PC_CREATE:
#endif
+
#ifdef __linux__
- facemgr_delete_interface(facemgr, facemgr->nl);
+#ifdef __ANDROID__
+ facemgr_delete_interface(facemgr, facemgr->android);
+ERR_ANDROID_CREATE:
+#else
+ facemgr_delete_interface(facemgr, facemgr->nl);
ERR_NL_CREATE:
+#endif /* __ANDROID__ */
#endif /* __linux__ */
+
#ifdef __APPLE__
- facemgr_delete_interface(facemgr, facemgr->nf);
+ facemgr_delete_interface(facemgr, facemgr->nf);
ERR_NF_CREATE:
#endif /* __APPLE__ */
- facemgr_delete_interface(facemgr, facemgr->hl);
-ERR_HL_CREATE:
ERR_REGISTER:
- return -1;
+ return -1;
}
-void facemgr_stop(facemgr_t * facemgr)
-{
- // FIXME we should iterate on interface map
+void facemgr_stop(facemgr_t *facemgr) {
+ // FIXME we should iterate on interface map
#ifdef __APPLE__
- facemgr_delete_interface(facemgr, facemgr->nf);
+ facemgr_delete_interface(facemgr, facemgr->nf);
#endif /* __APPLE__ */
-
#ifdef __linux__
- facemgr_delete_interface(facemgr, facemgr->nl);
-
- /* Delete all bonjour interfaces */
- interface_t ** bonjour_array = NULL;
- int n = bonjour_map_get_value_array(facemgr->bonjour_map, &bonjour_array);
- if (n >= 0) {
- netdevice_t ** netdevice_array = NULL;
- int m = bonjour_map_get_key_array(facemgr->bonjour_map, &netdevice_array);
- if (m >= 0) {
- assert(m == n);
- for (int i = 0; i < n; i++) { /* Fail silently */
- DEBUG("Deleting bonjour interface associated to %s (%p)",
- netdevice_array[i]->name, bonjour_array[i]);
- facemgr_delete_interface(facemgr, bonjour_array[i]);
- }
- free(netdevice_array);
- }
- free(bonjour_array);
- }
-#endif /* __linux__ */
+#ifdef __ANDROID__
+ facemgr_delete_interface(facemgr, facemgr->android);
+#else
+ facemgr_delete_interface(facemgr, facemgr->nl);
+#endif /* __ANDROID__ */
-#ifdef WITH_FACEMGR_UTILITY
- facemgr_delete_interface(facemgr, facemgr->au);
-#endif /* WITH_FACEMGR_UTILITY */
+ /* Delete all bonjour interfaces */
+ interface_t **bonjour_array = NULL;
+ int n = bonjour_map_get_value_array(facemgr->bonjour_map, &bonjour_array);
+ if (n >= 0) {
+ netdevice_t **netdevice_array = NULL;
+ int m = bonjour_map_get_key_array(facemgr->bonjour_map, &netdevice_array);
+ if (m >= 0) {
+ assert(m == n);
+ for (int i = 0; i < n; i++) { /* Fail silently */
+ DEBUG("Deleting bonjour interface associated to %s (%p)",
+ netdevice_array[i]->name, bonjour_array[i]);
+ facemgr_delete_interface(facemgr, bonjour_array[i]);
+ }
+ free(netdevice_array);
+ }
+ free(bonjour_array);
+ }
+#endif /* __linux__ */
#ifdef WITH_PRIORITY_CONTROLLER
- facemgr_delete_interface(facemgr, facemgr->pc);
+ facemgr_delete_interface(facemgr, facemgr->pc);
#endif
- facemgr_delete_interface(facemgr, facemgr->hl);
+ facemgr_delete_interface(facemgr, facemgr->hl);
#ifdef WITH_EXAMPLE_DUMMY
- facemgr_delete_interface(facemgr, facemgr->dummy);
+ facemgr_delete_interface(facemgr, facemgr->dummy);
#endif
#ifdef WITH_EXAMPLE_UPDOWN
- facemgr_delete_interface(facemgr, facemgr->updown);
+ facemgr_delete_interface(facemgr, facemgr->updown);
#endif
}
#ifdef __ANDROID__
-void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm)
-{
- facemgr->jvm = jvm;
+void facemgr_set_jvm(facemgr_t *facemgr, JavaVM *jvm) { facemgr->jvm = jvm; }
+
+void facemgr_on_android_callback(facemgr_t *facemgr, const char *interface_name,
+ netdevice_type_t netdevice_type, bool up,
+ int family, const char *ip_address) {
+ android_on_network_event(facemgr->android, interface_name, netdevice_type, up,
+ family, ip_address);
}
#endif /* __ANDROID__ */
-void
-facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t callback)
-{
- facemgr->callback = callback;
- facemgr->callback_owner = callback_owner;
+void facemgr_set_callback(facemgr_t *facemgr, void *callback_owner,
+ facemgr_cb_t callback) {
+ facemgr->callback = callback;
+ facemgr->callback_owner = callback_owner;
}
-void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t cb, void * user_data)
-{
- facelet_t ** facelet_array;
- if (!cb)
- return;
- int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
- if (n < 0) {
- ERROR("[facemgr_list_facelets] Could not retrieve facelets in cache");
- return;
- }
- for (unsigned i = 0; i < n; i++) {
- facelet_t * facelet = facelet_array[i];
- cb(facemgr, facelet, user_data);
- }
- free(facelet_array);
+void facemgr_list_facelets(const facemgr_t *facemgr,
+ facemgr_list_facelets_cb_t cb, void *user_data) {
+ facelet_t **facelet_array;
+ if (!cb) return;
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_list_facelets] Could not retrieve facelets in cache");
+ return;
+ }
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t *facelet = facelet_array[i];
+ if (!facelet) continue; /* Should not occur */
+ cb(facemgr, facelet, user_data);
+ }
+ free(facelet_array);
}
-int
-facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer)
-{
- char * cur;
- char * s;
- int rc;
-
- facelet_t ** facelet_array;
- int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
- if (n < 0) {
- ERROR("[facemgr_list_facelets_json] Could not retrieve facelets in cache");
- return -1;
- }
- /* This should be enough for JSON overhead, refine later */
- size_t size = 2 * n * MAXSZ_FACELET;
- *buffer = malloc(size);
- if (!buffer) {
- ERROR("[facemgr_list_facelets_json] Could not allocate JSON s");
- free(facelet_array);
- return -1;
- }
- s = *buffer;
- cur = s;
+int facemgr_list_facelets_json(const facemgr_t *facemgr, char **buffer) {
+ char *cur;
+ char *s;
+ int rc;
- rc = snprintf(cur, s + size - cur, "{\"facelets\": [\n");
- if (rc < 0)
- goto ERR;
- cur += rc;
- if (size != 0 && cur >= s + size)
- goto END;
+ facelet_t **facelet_array;
+ int n = facelet_set_get_array(facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_list_facelets_json] Could not retrieve facelets in cache");
+ return -1;
+ }
+ /* This should be enough for JSON overhead, refine later */
+ size_t size = 2 * n * MAXSZ_FACELET;
+ *buffer = malloc(size);
+ if (!buffer) {
+ ERROR("[facemgr_list_facelets_json] Could not allocate JSON s");
+ free(facelet_array);
+ return -1;
+ }
+ s = *buffer;
+ cur = s;
- for (unsigned i = 0; i < n; i++) {
- facelet_t * facelet = facelet_array[i];
+ rc = snprintf(cur, s + size - cur, "{\"facelets\": [\n");
+ if (rc < 0) goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size) goto END;
- rc = facelet_snprintf_json(cur, s + size - cur, facelet, /* indent */ 1);
- if (rc < 0)
- goto ERR;
- cur += rc;
- if (size != 0 && cur >= s + size)
- goto END;
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t *facelet = facelet_array[i];
+ if (!facelet) continue; /* Should not occur */
- rc = snprintf(cur, s + size - cur, (i == n-1) ? "\n" : ",\n");
- if (rc < 0)
- goto ERR;
- cur += rc;
- if (size != 0 && cur >= s + size)
- goto END;
- }
+ rc = facelet_snprintf_json(cur, s + size - cur, facelet, /* indent */ 1);
+ if (rc < 0) goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size) goto END;
- rc = snprintf(cur, s + size - cur, "]}\n");
- if (rc < 0)
- goto ERR;
+ rc = snprintf(cur, s + size - cur, (i == n - 1) ? "\n" : ",\n");
+ if (rc < 0) goto ERR;
cur += rc;
- if (size != 0 && cur >= s + size)
- goto END;
+ if (size != 0 && cur >= s + size) goto END;
+ }
+
+ rc = snprintf(cur, s + size - cur, "]}\n");
+ if (rc < 0) goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size) goto END;
END:
- free(facelet_array);
- return (int)(cur - s);
+ free(facelet_array);
+ return (int)(cur - s);
ERR:
- free(facelet_array);
- return rc;
+ free(facelet_array);
+ return rc;
}
-
diff --git a/ctrl/facemgr/src/cache.c b/ctrl/facemgr/src/cache.c
index f994d7d37..98c68e9b0 100644
--- a/ctrl/facemgr/src/cache.c
+++ b/ctrl/facemgr/src/cache.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,106 +22,86 @@
* search.h).
*/
-#include <math.h> // log2
-#include <string.h> // memmove
+#include <math.h> // log2
+#include <string.h> // memmove
#include "cache.h"
#define FACE_CACHE_MAX_SIZE_LOG_INIT 0
-face_cache_t *
-face_cache_create()
-{
- face_cache_t * face_cache = malloc(sizeof(face_cache_t));
- if (!face_cache)
- goto ERR_MALLOC;
+face_cache_t* face_cache_create() {
+ face_cache_t* face_cache = malloc(sizeof(face_cache_t));
+ if (!face_cache) goto ERR_MALLOC;
- face_cache->max_size_log = FACE_CACHE_MAX_SIZE_LOG_INIT;
-#if(FACE_CACHE_MAX_SIZE_LOG_INIT == 0)
- face_cache->faces = NULL;
+ face_cache->max_size_log = FACE_CACHE_MAX_SIZE_LOG_INIT;
+#if (FACE_CACHE_MAX_SIZE_LOG_INIT == 0)
+ face_cache->faces = NULL;
#else
- face_cache->faces = malloc((1 << face_cache->max_size_log) * sizeof(face_t*));
- if (!face_cache->faces)
- goto ERR_ARRAY:
+ face_cache->faces = malloc((1 << face_cache->max_size_log) * sizeof(face_t*));
+ if (!face_cache->faces)
+ goto ERR_ARRAY :
#endif
- face_cache->size = 0;
+ face_cache->size = 0;
- return face_cache;
+ return face_cache;
-#if(FACE_CACHE_MAX_SIZE_LOG_INIT != 0)
+#if (FACE_CACHE_MAX_SIZE_LOG_INIT != 0)
ERR_ARRAY:
- free(face_cache);
+ free(face_cache);
#endif
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-void
-face_cache_free(face_cache_t * face_cache)
-{
- free(face_cache->faces);
+void face_cache_free(face_cache_t* face_cache) {
+ free(face_cache->faces);
- free(face_cache);
+ free(face_cache);
}
-face_t *
-face_cache_add(face_cache_t * face_cache, face_t * face)
-{
- /* Ensure sufficient space for next addition */
- size_t new_size_log = (face_cache->size > 0) ? log2(face_cache->size) + 1 : 0;
- if (new_size_log > face_cache->max_size_log) {
- face_cache->max_size_log = new_size_log;
- face_cache->faces = realloc(face_cache->faces, (1 << new_size_log) * sizeof(face_t*));
- }
+face_t* face_cache_add(face_cache_t* face_cache, face_t* face) {
+ /* Ensure sufficient space for next addition */
+ size_t new_size_log = (face_cache->size > 0) ? log2(face_cache->size) + 1 : 0;
+ if (new_size_log > face_cache->max_size_log) {
+ face_cache->max_size_log = new_size_log;
+ face_cache->faces =
+ realloc(face_cache->faces, (1 << new_size_log) * sizeof(face_t*));
+ }
- if (!face_cache->faces)
- goto ERR_REALLOC;
+ if (!face_cache->faces) goto ERR_REALLOC;
- face_cache->faces[face_cache->size++] = face;
+ face_cache->faces[face_cache->size++] = face;
- return face;
+ return face;
ERR_REALLOC:
- return NULL;
+ return NULL;
}
-int face_cache_search(face_cache_t * face_cache, face_t * face, face_cmp_t face_cmp)
-{
- for (int i = 0; i < face_cache->size; i++)
- if (face_cmp(face, face_cache->faces[i]))
- return i;
- return -1;
+int face_cache_search(face_cache_t* face_cache, face_t* face,
+ face_cmp_t face_cmp) {
+ for (int i = 0; i < face_cache->size; i++)
+ if (face_cmp(face, face_cache->faces[i])) return i;
+ return -1;
}
/* Remove a single occurrence */
-face_t *
-face_cache_remove(face_cache_t * face_cache, face_t * face)
-{
- int pos = face_cache_search(face_cache, face, face_cmp);
- if (pos < 0)
- return NULL;
+face_t* face_cache_remove(face_cache_t* face_cache, face_t* face) {
+ int pos = face_cache_search(face_cache, face, face_cmp);
+ if (pos < 0) return NULL;
- /* No need to move memory if last item is removed */
- if (pos < face_cache->size)
- memmove(face_cache->faces+pos, face_cache->faces+pos+1, face_cache->size - pos);
+ /* No need to move memory if last item is removed */
+ if (pos < face_cache->size)
+ memmove(face_cache->faces + pos, face_cache->faces + pos + 1,
+ face_cache->size - pos);
- face_cache->size--;
+ face_cache->size--;
- return face;
+ return face;
}
/* TODO : remove by ... */
-face_t *
-face_cache_get_by_id(face_cache_t * face_cache, int id)
-{
- return NULL;
-}
-
-
+face_t* face_cache_get_by_id(face_cache_t* face_cache, int id) { return NULL; }
-void
-face_cache_dump(face_cache_t * face_cache)
-{
-
-}
+void face_cache_dump(face_cache_t* face_cache) {}
diff --git a/ctrl/facemgr/src/cache.h b/ctrl/facemgr/src/cache.h
index 1389ed6ec..ac14fabb8 100644
--- a/ctrl/facemgr/src/cache.h
+++ b/ctrl/facemgr/src/cache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,22 +32,22 @@
* \brief Face cache
*/
typedef struct {
- face_t ** faces; /**< array of _pointers_ to faces */
- size_t max_size_log; /**< log2 of allocated size */
- size_t size; /**< effective array size */
+ face_t** faces; /**< array of _pointers_ to faces */
+ size_t max_size_log; /**< log2 of allocated size */
+ size_t size; /**< effective array size */
} face_cache_t;
-face_cache_t * face_cache_create();
-void face_cache_free(face_cache_t * face_cache);
+face_cache_t* face_cache_create();
+void face_cache_free(face_cache_t* face_cache);
/* a la VPP vector, we never create a face outside of the vector */
/* problem is that face ptr can get invalid if we manipulate the vector */
-face_t * face_cache_get(face_cache_t * cache_cache);
+face_t* face_cache_get(face_cache_t* cache_cache);
-face_t * face_cache_add(face_cache_t * face_cache, face_t * face);
-face_t * face_cache_remove(face_cache_t * face_cache, face_t * face);
-face_t * face_cache_get_by_id(face_cache_t * face_cache, int id);
+face_t* face_cache_add(face_cache_t* face_cache, face_t* face);
+face_t* face_cache_remove(face_cache_t* face_cache, face_t* face);
+face_t* face_cache_get_by_id(face_cache_t* face_cache, int id);
-void face_cache_dump(face_cache_t * face_cache);
+void face_cache_dump(face_cache_t* face_cache);
#endif /* FACEMGR_CACHE_H */
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
index df73acd1b..9c374388a 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -4,7 +4,7 @@
*/
#include <assert.h>
-#include <hicn/ctrl.h> // HICN_DEFAULT_PORT
+#include <hicn/ctrl.h> // HICN_DEFAULT_PORT
#include <hicn/facemgr/cfg.h>
#include <hicn/policy.h>
#include <hicn/util/ip_address.h>
@@ -14,691 +14,643 @@
/* Overlay */
typedef struct {
- bool is_local_port;
- uint16_t local_port;
- bool is_local_addr;
- ip_address_t local_addr;
- bool is_remote_port;
- uint16_t remote_port;
- bool is_remote_addr;
- ip_address_t remote_addr;
+ bool is_local_port;
+ uint16_t local_port;
+ bool is_local_addr;
+ ip_address_t local_addr;
+ bool is_remote_port;
+ uint16_t remote_port;
+ bool is_remote_addr;
+ ip_address_t remote_addr;
} facemgr_cfg_overlay_t;
-int facemgr_cfg_overlay_initialize(facemgr_cfg_overlay_t * overlay)
-{
- overlay->is_local_port = false;
- overlay->local_port = 0;
- overlay->is_local_addr = false;
- overlay->local_addr = IP_ADDRESS_EMPTY;
+int facemgr_cfg_overlay_initialize(facemgr_cfg_overlay_t *overlay) {
+ overlay->is_local_port = false;
+ overlay->local_port = 0;
+ overlay->is_local_addr = false;
+ overlay->local_addr = IP_ADDRESS_EMPTY;
- overlay->is_remote_port = false;
- overlay->remote_port = 0;
- overlay->is_remote_addr = false;
- overlay->remote_addr = IP_ADDRESS_EMPTY;
+ overlay->is_remote_port = false;
+ overlay->remote_port = 0;
+ overlay->is_remote_addr = false;
+ overlay->remote_addr = IP_ADDRESS_EMPTY;
- return 0;
+ return 0;
}
-int facemgr_cfg_overlay_finalize(facemgr_cfg_overlay_t * overlay)
-{
- return 0;
-}
+int facemgr_cfg_overlay_finalize(facemgr_cfg_overlay_t *overlay) { return 0; }
-facemgr_cfg_overlay_t * facemgr_cfg_overlay_create()
-{
- facemgr_cfg_overlay_t * overlay = malloc(sizeof(facemgr_cfg_overlay_t));
- if (!overlay)
- return NULL;
+facemgr_cfg_overlay_t *facemgr_cfg_overlay_create() {
+ facemgr_cfg_overlay_t *overlay = malloc(sizeof(facemgr_cfg_overlay_t));
+ if (!overlay) return NULL;
- int rc = facemgr_cfg_overlay_initialize(overlay);
- if (rc < 0) {
- free(overlay);
- return NULL;
- }
+ int rc = facemgr_cfg_overlay_initialize(overlay);
+ if (rc < 0) {
+ free(overlay);
+ return NULL;
+ }
- return overlay;
+ return overlay;
}
-void facemgr_cfg_overlay_free(facemgr_cfg_overlay_t * overlay)
-{
- facemgr_cfg_overlay_finalize(overlay);
- free(overlay);
+void facemgr_cfg_overlay_free(facemgr_cfg_overlay_t *overlay) {
+ facemgr_cfg_overlay_finalize(overlay);
+ free(overlay);
}
typedef struct {
- facemgr_cfg_overlay_t * v4;
- facemgr_cfg_overlay_t * v6;
+ facemgr_cfg_overlay_t *v4;
+ facemgr_cfg_overlay_t *v6;
} facemgr_cfg_overlays_t;
typedef struct {
- const char * interface_name;
- netdevice_type_t interface_type;
+ const char *interface_name;
+ netdevice_type_t interface_type;
} facemgr_cfg_match_t;
-
typedef struct {
- /* Interface specific */
- bool is_face_type; // default is auto
- facemgr_face_type_t face_type;
-
- /* This should be defaut for the global settings */
- bool is_ignore;
- bool ignore;
- bool is_discovery;
- bool discovery;
- bool is_ipv4;
- bool ipv4;
- bool is_ipv6;
- bool ipv6;
-
- facemgr_cfg_overlays_t overlays; // fallback unless discovery is disabled
+ /* Interface specific */
+ bool is_face_type; // default is auto
+ facemgr_face_type_t face_type;
+
+ /* This should be defaut for the global settings */
+ bool is_ignore;
+ bool ignore;
+ bool is_discovery;
+ bool discovery;
+ bool is_ipv4;
+ bool ipv4;
+ bool is_ipv6;
+ bool ipv6;
+
+ facemgr_cfg_overlays_t overlays; // fallback unless discovery is disabled
} facemgr_cfg_override_t;
struct facemgr_cfg_rule_s {
- facemgr_cfg_match_t match;
- facemgr_cfg_override_t override;
+ facemgr_cfg_match_t match;
+ facemgr_cfg_override_t override;
};
-int facemgr_cfg_override_initialize(facemgr_cfg_override_t * override)
-{
- override->is_face_type = false;
- override->face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+int facemgr_cfg_override_initialize(facemgr_cfg_override_t *override) {
+ override->is_face_type = false;
+ override->face_type = FACEMGR_FACE_TYPE_UNDEFINED;
- override->is_ignore = false;
- override->ignore = false;
+ override->is_ignore = false;
+ override->ignore = false;
- override->is_discovery = false;
- override->discovery = false;
+ override->is_discovery = false;
+ override->discovery = false;
- override->is_ipv4 = false;
- override->ipv6 = false;
- override->is_ipv6 = false;
- override->ipv6 = false;
+ override->is_ipv4 = false;
+ override->ipv6 = false;
+ override->is_ipv6 = false;
+ override->ipv6 = false;
- override->overlays.v4 = NULL;
- override->overlays.v6 = NULL;
+ override->overlays.v4 = NULL;
+ override->overlays.v6 = NULL;
- return 0;
+ return 0;
}
-int facemgr_cfg_override_finalize(facemgr_cfg_override_t * override)
-{
- if (override->overlays.v4) {
- facemgr_cfg_overlay_free(override->overlays.v4);
- override->overlays.v4 = NULL;
- }
- if (override->overlays.v6) {
- facemgr_cfg_overlay_free(override->overlays.v6);
- override->overlays.v6 = NULL;
- }
+int facemgr_cfg_override_finalize(facemgr_cfg_override_t *override) {
+ if (override->overlays.v4) {
+ facemgr_cfg_overlay_free(override->overlays.v4);
+ override->overlays.v4 = NULL;
+ }
+ if (override->overlays.v6) {
+ facemgr_cfg_overlay_free(override->overlays.v6);
+ override->overlays.v6 = NULL;
+ }
- return 0;
+ return 0;
}
-
/* Rule */
-facemgr_cfg_rule_t * facemgr_cfg_rule_create()
-{
- facemgr_cfg_rule_t * rule = malloc(sizeof(facemgr_cfg_rule_t));
- if (!rule)
- return NULL;
+facemgr_cfg_rule_t *facemgr_cfg_rule_create() {
+ facemgr_cfg_rule_t *rule = malloc(sizeof(facemgr_cfg_rule_t));
+ if (!rule) return NULL;
- int rc = facemgr_cfg_rule_initialize(rule);
- if (rc < 0)
- return NULL;
+ int rc = facemgr_cfg_rule_initialize(rule);
+ if (rc < 0) return NULL;
- return rule;
+ return rule;
}
-void facemgr_cfg_rule_free(facemgr_cfg_rule_t * rule)
-{
- facemgr_cfg_rule_finalize(rule);
- free(rule);
+void facemgr_cfg_rule_free(facemgr_cfg_rule_t *rule) {
+ facemgr_cfg_rule_finalize(rule);
+ free(rule);
}
-int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t * rule)
-{
- rule->match.interface_name = NULL;
- rule->match.interface_type = NETDEVICE_TYPE_UNDEFINED;
+int facemgr_cfg_rule_initialize(facemgr_cfg_rule_t *rule) {
+ rule->match.interface_name = NULL;
+ rule->match.interface_type = NETDEVICE_TYPE_UNDEFINED;
- int rc = facemgr_cfg_override_initialize(&rule->override);
- if (rc < 0)
- return -1;
+ int rc = facemgr_cfg_override_initialize(&rule->override);
+ if (rc < 0) return -1;
- return 0;
+ return 0;
}
-int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t * rule)
-{
- if (rule->match.interface_name) {
- free((void*)rule->match.interface_name);
- rule->match.interface_name = NULL;
+int facemgr_cfg_rule_finalize(facemgr_cfg_rule_t *rule) {
+ if (rule->match.interface_name) {
+ free((void *)rule->match.interface_name);
+ rule->match.interface_name = NULL;
+ }
+ return facemgr_cfg_override_finalize(&rule->override);
+}
+
+void facemgr_cfg_rule_dump(facemgr_cfg_rule_t *rule) {
+ DEBUG(" <rule>");
+ DEBUG(" <match interface_name=%s interface_type=%s>",
+ rule->match.interface_name,
+ netdevice_type_str(rule->match.interface_type));
+ DEBUG(" <override>");
+ if (rule->override.is_face_type) {
+ DEBUG(" <face_type>%d</face_type>", rule->override.face_type);
+ }
+ if (rule->override.is_ignore) {
+ DEBUG(" <ignore>%d</ignore>", rule->override.ignore);
+ }
+ if (rule->override.is_discovery) {
+ DEBUG(" <discovery>%d</discovery>", rule->override.discovery);
+ }
+ if (rule->override.is_ipv4) {
+ DEBUG(" <ipv4>%d</ipv4>", rule->override.ipv4);
+ }
+ if (rule->override.is_ipv6) {
+ DEBUG(" <ipv6>%d</ipv6>", rule->override.ipv6);
+ }
+ DEBUG(" <overlays>");
+ if (rule->override.overlays.v4) {
+ DEBUG(" <ipv4>");
+ if (rule->override.overlays.v4->is_local_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v4->local_addr, AF_INET);
+ DEBUG(" <local_addr>%s</local_addr>", buf);
}
- return facemgr_cfg_override_finalize(&rule->override);
-}
-
-void facemgr_cfg_rule_dump(facemgr_cfg_rule_t * rule)
-{
- DEBUG(" <rule>");
- DEBUG(" <match interface_name=%s interface_type=%s>",
- rule->match.interface_name,
- netdevice_type_str[rule->match.interface_type]);
- DEBUG(" <override>");
- if (rule->override.is_face_type) {
- DEBUG(" <face_type>%d</face_type>", rule->override.face_type);
+ if (rule->override.overlays.v4->is_local_port) {
+ DEBUG(" <local_port>%d</local_port>",
+ rule->override.overlays.v4->local_port);
}
- if (rule->override.is_ignore) {
- DEBUG(" <ignore>%d</ignore>", rule->override.ignore);
+ if (rule->override.overlays.v4->is_remote_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v4->remote_addr, AF_INET);
+ DEBUG(" <remote_addr>%s</remote_addr>", buf);
}
- if (rule->override.is_discovery) {
- DEBUG(" <discovery>%d</discovery>", rule->override.discovery);
+ if (rule->override.overlays.v4->is_remote_port) {
+ DEBUG(" <remote_port>%d</remote_port>",
+ rule->override.overlays.v4->remote_port);
}
- if (rule->override.is_ipv4) {
- DEBUG(" <ipv4>%d</ipv4>", rule->override.ipv4);
+ DEBUG(" </ipv4>");
+ }
+ if (rule->override.overlays.v6) {
+ DEBUG(" <ipv6>");
+ if (rule->override.overlays.v6->is_local_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v6->local_addr, AF_INET6);
+ DEBUG(" <local_addr>%s</local_addr>", buf);
}
- if (rule->override.is_ipv6) {
- DEBUG(" <ipv6>%d</ipv6>", rule->override.ipv6);
+ if (rule->override.overlays.v6->is_local_port) {
+ DEBUG(" <local_port>%d</local_port>",
+ rule->override.overlays.v6->local_port);
}
- DEBUG(" <overlays>");
- if (rule->override.overlays.v4) {
- DEBUG(" <ipv4>");
- if (rule->override.overlays.v4->is_local_addr) {
- char buf[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
- &rule->override.overlays.v4->local_addr, AF_INET);
- DEBUG(" <local_addr>%s</local_addr>", buf);
- }
- if (rule->override.overlays.v4->is_local_port) {
- DEBUG(" <local_port>%d</local_port>",
- rule->override.overlays.v4->local_port);
- }
- if (rule->override.overlays.v4->is_remote_addr) {
- char buf[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
- &rule->override.overlays.v4->remote_addr, AF_INET);
- DEBUG(" <remote_addr>%s</remote_addr>", buf);
- }
- if (rule->override.overlays.v4->is_remote_port) {
- DEBUG(" <remote_port>%d</remote_port>",
- rule->override.overlays.v4->remote_port);
- }
- DEBUG(" </ipv4>");
+ if (rule->override.overlays.v6->is_remote_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
+ &rule->override.overlays.v6->remote_addr, AF_INET6);
+ DEBUG(" <remote_addr>%s</remote_addr>", buf);
}
- if (rule->override.overlays.v6) {
- DEBUG(" <ipv6>");
- if (rule->override.overlays.v6->is_local_addr) {
- char buf[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
- &rule->override.overlays.v6->local_addr, AF_INET6);
- DEBUG(" <local_addr>%s</local_addr>", buf);
- }
- if (rule->override.overlays.v6->is_local_port) {
- DEBUG(" <local_port>%d</local_port>",
- rule->override.overlays.v6->local_port);
- }
- if (rule->override.overlays.v6->is_remote_addr) {
- char buf[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
- &rule->override.overlays.v6->remote_addr, AF_INET6);
- DEBUG(" <remote_addr>%s</remote_addr>", buf);
- }
- if (rule->override.overlays.v6->is_remote_port) {
- DEBUG(" <remote_port>%d</remote_port>",
- rule->override.overlays.v6->remote_port);
- }
- DEBUG(" </ipv6>");
+ if (rule->override.overlays.v6->is_remote_port) {
+ DEBUG(" <remote_port>%d</remote_port>",
+ rule->override.overlays.v6->remote_port);
}
- DEBUG(" </overlays>");
- DEBUG(" </override>");
- DEBUG(" </rule>");
+ DEBUG(" </ipv6>");
+ }
+ DEBUG(" </overlays>");
+ DEBUG(" </override>");
+ DEBUG(" </rule>");
}
-int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t * rule, const char * interface_name,
- netdevice_type_t interface_type)
-{
- rule->match.interface_name = interface_name ? strdup(interface_name) : NULL;
- rule->match.interface_type = interface_type;
- return 0;
+int facemgr_cfg_rule_set_match(facemgr_cfg_rule_t *rule,
+ const char *interface_name,
+ netdevice_type_t interface_type) {
+ rule->match.interface_name = interface_name ? strdup(interface_name) : NULL;
+ rule->match.interface_type = interface_type;
+ return 0;
}
-int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t * rule, facemgr_face_type_t * face_type)
-{
- rule->override.is_face_type = true;
- rule->override.face_type = *face_type;
- return 0;
+int facemgr_cfg_rule_set_face_type(facemgr_cfg_rule_t *rule,
+ facemgr_face_type_t *face_type) {
+ rule->override.is_face_type = true;
+ rule->override.face_type = *face_type;
+ return 0;
}
-int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t * rule)
-{
- rule->override.is_face_type = false;
- rule->override.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */
- return 0;
+int facemgr_cfg_rule_unset_face_type(facemgr_cfg_rule_t *rule) {
+ rule->override.is_face_type = false;
+ rule->override.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */
+ return 0;
}
-int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t * rule, bool status)
-{
- rule->override.is_discovery = true;
- rule->override.discovery = status;
- return 0;
+int facemgr_cfg_rule_set_discovery(facemgr_cfg_rule_t *rule, bool status) {
+ rule->override.is_discovery = true;
+ rule->override.discovery = status;
+ return 0;
}
-int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t * rule)
-{
- rule->override.is_discovery = false;
- return 0;
+int facemgr_cfg_rule_unset_discovery(facemgr_cfg_rule_t *rule) {
+ rule->override.is_discovery = false;
+ return 0;
}
-int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t * rule, bool status)
-{
- rule->override.is_ignore = true;
- rule->override.ignore = status;
- return 0;
+int facemgr_cfg_rule_set_ignore(facemgr_cfg_rule_t *rule, bool status) {
+ rule->override.is_ignore = true;
+ rule->override.ignore = status;
+ return 0;
}
-int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t * rule)
-{
- rule->override.is_ignore = false;
- return 0;
+int facemgr_cfg_rule_unset_ignore(facemgr_cfg_rule_t *rule) {
+ rule->override.is_ignore = false;
+ return 0;
}
-int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t * rule, bool status)
-{
- rule->override.is_ipv4 = true;
- rule->override.ipv4 = status;
- return 0;
+int facemgr_cfg_rule_set_ipv4(facemgr_cfg_rule_t *rule, bool status) {
+ rule->override.is_ipv4 = true;
+ rule->override.ipv4 = status;
+ return 0;
}
-int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t * rule)
-{
- rule->override.is_ipv4 = false;
- return 0;
+int facemgr_cfg_rule_unset_ipv4(facemgr_cfg_rule_t *rule) {
+ rule->override.is_ipv4 = false;
+ return 0;
}
-int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t * rule, bool status)
-{
- rule->override.is_ipv6 = true;
- rule->override.ipv6 = status;
- return 0;
+int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t *rule, bool status) {
+ rule->override.is_ipv6 = true;
+ rule->override.ipv6 = status;
+ return 0;
}
-int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t * rule)
-{
- rule->override.is_ipv6 = false;
- return 0;
+int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t *rule) {
+ rule->override.is_ipv6 = false;
+ return 0;
}
-int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t * rule, int family,
- ip_address_t * local_addr, uint16_t local_port,
- ip_address_t * remote_addr, uint16_t remote_port) {
- if ((family != AF_INET) && (family != AF_INET6))
- return -1;
+int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t *rule, int family,
+ ip_address_t *local_addr, uint16_t local_port,
+ ip_address_t *remote_addr,
+ uint16_t remote_port) {
+ if ((family != AF_INET) && (family != AF_INET6)) return -1;
- facemgr_cfg_overlay_t * overlay = facemgr_cfg_overlay_create();
- if (local_addr) {
- overlay->is_local_addr = true;
- overlay->local_addr = *local_addr;
- }
- if (IS_VALID_PORT(local_port)) {
- overlay->is_local_port = true;
- overlay->local_port = local_port;
- }
- if (remote_addr) {
- overlay->is_remote_addr = true;
- overlay->remote_addr = *remote_addr;
- }
- if (IS_VALID_PORT(remote_port)) {
- overlay->is_remote_port = true;
- overlay->remote_port = remote_port;
- }
+ facemgr_cfg_overlay_t *overlay = facemgr_cfg_overlay_create();
+ if (local_addr) {
+ overlay->is_local_addr = true;
+ overlay->local_addr = *local_addr;
+ }
+ if (IS_VALID_PORT(local_port)) {
+ overlay->is_local_port = true;
+ overlay->local_port = local_port;
+ }
+ if (remote_addr) {
+ overlay->is_remote_addr = true;
+ overlay->remote_addr = *remote_addr;
+ }
+ if (IS_VALID_PORT(remote_port)) {
+ overlay->is_remote_port = true;
+ overlay->remote_port = remote_port;
+ }
- switch(family) {
- case AF_INET:
- rule->override.overlays.v4 = overlay;
- break;
+ switch (family) {
+ case AF_INET:
+ rule->override.overlays.v4 = overlay;
+ break;
- case AF_INET6:
- rule->override.overlays.v6 = overlay;
- break;
+ case AF_INET6:
+ rule->override.overlays.v6 = overlay;
+ break;
- default:
- return -1;
- }
+ default:
+ return -1;
+ }
- return 0;
+ return 0;
}
-int facemgr_rule_unset_overlay(facemgr_cfg_rule_t * rule, int family)
-{
- if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC))
- return -1;
+int facemgr_rule_unset_overlay(facemgr_cfg_rule_t *rule, int family) {
+ if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC))
+ return -1;
- if ((family == AF_UNSPEC) || (family == AF_INET)) {
- if (rule->override.overlays.v4) {
- facemgr_cfg_overlay_free(rule->override.overlays.v4);
- rule->override.overlays.v4 = NULL;
- }
- }
- if ((family == AF_UNSPEC) || (family == AF_INET6)) {
- if (rule->override.overlays.v6) {
- facemgr_cfg_overlay_free(rule->override.overlays.v6);
- rule->override.overlays.v6 = NULL;
- }
+ if ((family == AF_UNSPEC) || (family == AF_INET)) {
+ if (rule->override.overlays.v4) {
+ facemgr_cfg_overlay_free(rule->override.overlays.v4);
+ rule->override.overlays.v4 = NULL;
}
- return 0;
-}
-
-int facemgr_cfg_rule_cmp(const facemgr_cfg_rule_t * r1, const facemgr_cfg_rule_t * r2)
-{
- /*
- * We implement a lexicographic order on the tuple (interface_name,
- * interface_type)
- */
-
- /* We need to handle NULL cases out of strcmp */
- if (!r1->match.interface_name) {
- if (r2->match.interface_name)
- return 1;
- else
- goto BOTH_NULL;
- } else {
- if (!r2->match.interface_name)
- return -1;
+ }
+ if ((family == AF_UNSPEC) || (family == AF_INET6)) {
+ if (rule->override.overlays.v6) {
+ facemgr_cfg_overlay_free(rule->override.overlays.v6);
+ rule->override.overlays.v6 = NULL;
}
-
-
- /* Only if both are non-NULL, we proceed to strcmp */
- int rc = strcmp(r1->match.interface_name, r2->match.interface_name);
- if (rc != 0)
- return rc;
+ }
+ return 0;
+}
+
+int facemgr_cfg_rule_cmp(const facemgr_cfg_rule_t *r1,
+ const facemgr_cfg_rule_t *r2) {
+ /*
+ * We implement a lexicographic order on the tuple (interface_name,
+ * interface_type)
+ */
+
+ /* We need to handle NULL cases out of strcmp */
+ if (!r1->match.interface_name) {
+ if (r2->match.interface_name)
+ return 1;
+ else
+ goto BOTH_NULL;
+ } else {
+ if (!r2->match.interface_name) return -1;
+ }
+
+ /* Only if both are non-NULL, we proceed to strcmp */
+ int rc = strcmp(r1->match.interface_name, r2->match.interface_name);
+ if (rc != 0) return rc;
BOTH_NULL:
- return r1->match.interface_type - r2->match.interface_type;
+ return r1->match.interface_type - r2->match.interface_type;
}
/* General */
TYPEDEF_SET_H(facemgr_cfg_rule_set, facemgr_cfg_rule_t *);
-TYPEDEF_SET(facemgr_cfg_rule_set, facemgr_cfg_rule_t *, facemgr_cfg_rule_cmp, generic_snprintf);
+TYPEDEF_SET(facemgr_cfg_rule_set, facemgr_cfg_rule_t *, facemgr_cfg_rule_cmp,
+ generic_snprintf);
struct facemgr_cfg_s {
- facemgr_cfg_override_t global;
- facemgr_cfg_rule_set_t * rule_set;
- facelet_array_t * static_facelets;
- //log_cfg_t log;
+ facemgr_cfg_override_t global;
+ facemgr_cfg_rule_set_t *rule_set;
+ facelet_array_t *static_facelets;
+ // log_cfg_t log;
};
-facemgr_cfg_t * facemgr_cfg_create()
-{
- facemgr_cfg_t * cfg = malloc(sizeof(facemgr_cfg_t));
- if (!cfg) {
- ERROR("[facemgr_cfg_create] Error allocating face manager configuration");
- goto ERR_MALLOC;
- }
+facemgr_cfg_t *facemgr_cfg_create() {
+ facemgr_cfg_t *cfg = malloc(sizeof(facemgr_cfg_t));
+ if (!cfg) {
+ ERROR("[facemgr_cfg_create] Error allocating face manager configuration");
+ goto ERR_MALLOC;
+ }
- int rc = facemgr_cfg_initialize(cfg);
- if (rc < 0) {
- ERROR("[facemgr_cfg_create] Error initializing face manager configuration");
- goto ERR_INIT;
- }
+ int rc = facemgr_cfg_initialize(cfg);
+ if (rc < 0) {
+ ERROR("[facemgr_cfg_create] Error initializing face manager configuration");
+ goto ERR_INIT;
+ }
- return cfg;
+ return cfg;
ERR_INIT:
- free(cfg);
+ free(cfg);
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-void facemgr_cfg_free(facemgr_cfg_t * cfg)
-{
- facemgr_cfg_finalize(cfg);
- free(cfg);
+void facemgr_cfg_free(facemgr_cfg_t *cfg) {
+ facemgr_cfg_finalize(cfg);
+ free(cfg);
}
-int facemgr_cfg_initialize(facemgr_cfg_t * cfg)
-{
- int rc = facemgr_cfg_override_initialize(&cfg->global);
- if (rc < 0) {
- ERROR("[facemgr_cfg_initialize] Error initializing global values");
- goto ERR_OVERRIDE;
- }
+int facemgr_cfg_initialize(facemgr_cfg_t *cfg) {
+ int rc = facemgr_cfg_override_initialize(&cfg->global);
+ if (rc < 0) {
+ ERROR("[facemgr_cfg_initialize] Error initializing global values");
+ goto ERR_OVERRIDE;
+ }
- cfg->rule_set = facemgr_cfg_rule_set_create();
- if (!cfg->rule_set) {
- ERROR("[facemgr_cfg_initialize] Error creating rule set");
- goto ERR_RULE_SET;
- }
+ cfg->rule_set = facemgr_cfg_rule_set_create();
+ if (!cfg->rule_set) {
+ ERROR("[facemgr_cfg_initialize] Error creating rule set");
+ goto ERR_RULE_SET;
+ }
- cfg->static_facelets = facelet_array_create(cfg->static_facelets);
- if (!cfg->static_facelets) {
- ERROR("[facemgr_cfg_initialize] Error creating static facelet set");
- goto ERR_STATIC;
- }
+ cfg->static_facelets = facelet_array_create();
+ if (!cfg->static_facelets) {
+ ERROR("[facemgr_cfg_initialize] Error creating static facelet set");
+ goto ERR_STATIC;
+ }
- return 0;
+ return 0;
ERR_STATIC:
- facemgr_cfg_rule_set_free(cfg->rule_set);
+ facemgr_cfg_rule_set_free(cfg->rule_set);
ERR_RULE_SET:
- facemgr_cfg_override_finalize(&cfg->global);
+ facemgr_cfg_override_finalize(&cfg->global);
ERR_OVERRIDE:
- return -1;
-}
-
-int facemgr_cfg_finalize(facemgr_cfg_t * cfg)
-{
- /* TODO Free all rules */
- facemgr_cfg_rule_t ** rule_array;
- int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
- if (n < 0) {
- ERROR("[facemgr_cfg_finalize] Could not retrieve rule set array from configuration");
- } else {
- for (unsigned i = 0; i < n; i++) {
- facemgr_cfg_rule_t * rule = rule_array[i];
- if (facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL) < 0) {
- ERROR("[facemgr_cfg_finalize] Could not remove rule from set");
- }
- facemgr_cfg_rule_free(rule);
- }
- free(rule_array);
+ return -1;
+}
+
+int facemgr_cfg_finalize(facemgr_cfg_t *cfg) {
+ /* TODO Free all rules */
+ facemgr_cfg_rule_t **rule_array;
+ int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
+ if (n < 0) {
+ ERROR(
+ "[facemgr_cfg_finalize] Could not retrieve rule set array from "
+ "configuration");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facemgr_cfg_rule_t *rule = rule_array[i];
+ if (!rule) continue; /* Should not occur */
+ if (facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL) < 0) {
+ ERROR("[facemgr_cfg_finalize] Could not remove rule from set");
+ }
+ facemgr_cfg_rule_free(rule);
}
- facemgr_cfg_rule_set_free(cfg->rule_set);
-
- /* Free all facelets from static array */
- for (unsigned i = 0; i < facelet_array_len(cfg->static_facelets); i++) {
- facelet_t * facelet;
- if (facelet_array_get_index(cfg->static_facelets, i, &facelet) < 0) {
- ERROR("[facemgr_cfg_finalize] Error getting facelet in array");
- continue;
- }
- if (facelet_array_remove_index(cfg->static_facelets, i, NULL)) {
- ERROR("[facemgr_cfg_finalize] Could not purge facelet from static set");
- }
- facelet_free(facelet);
+ free(rule_array);
+ }
+ facemgr_cfg_rule_set_free(cfg->rule_set);
+
+ /* Free all facelets from static array */
+ for (unsigned i = 0; i < facelet_array_len(cfg->static_facelets); i++) {
+ facelet_t *facelet;
+ if (facelet_array_get_index(cfg->static_facelets, i, &facelet) < 0) {
+ ERROR("[facemgr_cfg_finalize] Error getting facelet in array");
+ continue;
}
+ if (facelet_array_remove_index(cfg->static_facelets, i, NULL)) {
+ ERROR("[facemgr_cfg_finalize] Could not purge facelet from static set");
+ }
+ facelet_free(facelet);
+ }
- facelet_array_free(cfg->static_facelets);
+ facelet_array_free(cfg->static_facelets);
- return facemgr_cfg_override_finalize(&cfg->global);
+ return facemgr_cfg_override_finalize(&cfg->global);
}
-void facemgr_cfg_dump(facemgr_cfg_t * cfg)
-{
- return; /* NOT IMPLEMENTED */
-}
+void facemgr_cfg_dump(facemgr_cfg_t *cfg) { return; /* NOT IMPLEMENTED */ }
/* General */
-int facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_type)
-{
- cfg->global.is_face_type = true;
- cfg->global.face_type = *face_type;
- return 0;
-}
-
-int facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg)
-{
- cfg->global.is_face_type = false;
- cfg->global.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */
- return 0;
-}
-
-int facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status)
-{
- cfg->global.is_discovery = true;
- cfg->global.discovery = status;
- return 0;
-}
-
-int facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg)
-{
- cfg->global.is_discovery = false;
- return 0;
-}
-
-int facemgr_cfg_set_ipv4(facemgr_cfg_t * cfg, bool status)
-{
- cfg->global.is_ipv4 = true;
- cfg->global.ipv4 = status;
- DEBUG("<global>");
- DEBUG(" <ipv4>%d</ipv4>", cfg->global.ipv4);
- DEBUG("</global>");
- return 0;
-}
-
-int facemgr_cfg_unset_ipv4(facemgr_cfg_t * cfg)
-{
- cfg->global.is_ipv4 = false;
- return 0;
-}
-
-int facemgr_cfg_set_ipv6(facemgr_cfg_t * cfg, bool status)
-{
- cfg->global.is_ipv6 = true;
- cfg->global.ipv6 = status;
- DEBUG("<global>");
- DEBUG(" <ipv6>%d</ipv6>", cfg->global.ipv6);
- DEBUG("</global>");
- return 0;
-}
-
-int facemgr_cfg_unset_ipv6(facemgr_cfg_t * cfg)
-{
- cfg->global.is_ipv6 = false;
- return 0;
-}
-
-int facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family,
- ip_address_t * local_addr, uint16_t local_port,
- ip_address_t * remote_addr, uint16_t remote_port)
-{
- if ((family != AF_INET) && (family != AF_INET6))
- return -1;
-
- facemgr_cfg_overlay_t * overlay = facemgr_cfg_overlay_create();
- if (local_addr) {
- overlay->is_local_addr = true;
- overlay->local_addr = *local_addr;
+int facemgr_cfg_set_face_type(facemgr_cfg_t *cfg,
+ facemgr_face_type_t *face_type) {
+ cfg->global.is_face_type = true;
+ cfg->global.face_type = *face_type;
+ return 0;
+}
+
+int facemgr_cfg_unset_face_type(facemgr_cfg_t *cfg) {
+ cfg->global.is_face_type = false;
+ cfg->global.face_type = FACEMGR_FACE_TYPE_UNDEFINED; /* optional */
+ return 0;
+}
+
+int facemgr_cfg_set_discovery(facemgr_cfg_t *cfg, bool status) {
+ cfg->global.is_discovery = true;
+ cfg->global.discovery = status;
+ return 0;
+}
+
+int facemgr_cfg_unset_discovery(facemgr_cfg_t *cfg) {
+ cfg->global.is_discovery = false;
+ return 0;
+}
+
+int facemgr_cfg_set_ipv4(facemgr_cfg_t *cfg, bool status) {
+ cfg->global.is_ipv4 = true;
+ cfg->global.ipv4 = status;
+ DEBUG("<global>");
+ DEBUG(" <ipv4>%d</ipv4>", cfg->global.ipv4);
+ DEBUG("</global>");
+ return 0;
+}
+
+int facemgr_cfg_unset_ipv4(facemgr_cfg_t *cfg) {
+ cfg->global.is_ipv4 = false;
+ return 0;
+}
+
+int facemgr_cfg_set_ipv6(facemgr_cfg_t *cfg, bool status) {
+ cfg->global.is_ipv6 = true;
+ cfg->global.ipv6 = status;
+ DEBUG("<global>");
+ DEBUG(" <ipv6>%d</ipv6>", cfg->global.ipv6);
+ DEBUG("</global>");
+ return 0;
+}
+
+int facemgr_cfg_unset_ipv6(facemgr_cfg_t *cfg) {
+ cfg->global.is_ipv6 = false;
+ return 0;
+}
+
+int facemgr_cfg_set_overlay(facemgr_cfg_t *cfg, int family,
+ ip_address_t *local_addr, uint16_t local_port,
+ ip_address_t *remote_addr, uint16_t remote_port) {
+ if ((family != AF_INET) && (family != AF_INET6)) return -1;
+
+ facemgr_cfg_overlay_t *overlay = facemgr_cfg_overlay_create();
+ if (local_addr) {
+ overlay->is_local_addr = true;
+ overlay->local_addr = *local_addr;
+ }
+ if (IS_VALID_PORT(local_port)) {
+ overlay->is_local_port = true;
+ overlay->local_port = local_port;
+ }
+ if (remote_addr) {
+ overlay->is_remote_addr = true;
+ overlay->remote_addr = *remote_addr;
+ }
+ if (IS_VALID_PORT(remote_port)) {
+ overlay->is_remote_port = true;
+ overlay->remote_port = remote_port;
+ }
+
+ DEBUG("facemgr_cfg_set_overlay");
+
+ switch (family) {
+ case AF_INET:
+ cfg->global.overlays.v4 = overlay;
+ break;
+
+ case AF_INET6:
+ cfg->global.overlays.v6 = overlay;
+ break;
+
+ default:
+ return -1;
+ }
+
+ DEBUG("<global>");
+ DEBUG(" <overlay>");
+ if (overlay) {
+ DEBUG(" <ipv4>");
+ if (overlay->is_local_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->local_addr, AF_INET);
+ DEBUG(" <local_addr>%s</local_addr>", buf);
}
- if (IS_VALID_PORT(local_port)) {
- overlay->is_local_port = true;
- overlay->local_port = local_port;
+ if (overlay->is_local_port) {
+ DEBUG(" <local_port>%d</local_port>", overlay->local_port);
}
- if (remote_addr) {
- overlay->is_remote_addr = true;
- overlay->remote_addr = *remote_addr;
- }
- if (IS_VALID_PORT(remote_port)) {
- overlay->is_remote_port = true;
- overlay->remote_port = remote_port;
- }
-
- DEBUG("facemgr_cfg_set_overlay");
-
- switch(family) {
- case AF_INET:
- cfg->global.overlays.v4 = overlay;
- break;
-
- case AF_INET6:
- cfg->global.overlays.v6 = overlay;
- break;
-
- default:
- return -1;
+ if (overlay->is_remote_addr) {
+ char buf[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->remote_addr,
+ AF_INET);
+ DEBUG(" <remote_addr>%s</remote_addr>", buf);
}
-
- DEBUG("<global>");
- DEBUG(" <overlay>");
- if (overlay) {
- DEBUG(" <ipv4>");
- if (overlay->is_local_addr) {
- char buf[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
- &overlay->local_addr, AF_INET);
- DEBUG(" <local_addr>%s</local_addr>", buf);
- }
- if (overlay->is_local_port) {
- DEBUG(" <local_port>%d</local_port>",
- overlay->local_port);
- }
- if (overlay->is_remote_addr) {
- char buf[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(buf, MAXSZ_IP_ADDRESS,
- &overlay->remote_addr, AF_INET);
- DEBUG(" <remote_addr>%s</remote_addr>", buf);
- }
- if (overlay->is_remote_port) {
- DEBUG(" <remote_port>%d</remote_port>",
- overlay->remote_port);
- }
- DEBUG(" </ipv4>");
+ if (overlay->is_remote_port) {
+ DEBUG(" <remote_port>%d</remote_port>", overlay->remote_port);
}
- DEBUG(" </overlay>");
- DEBUG("</global>");
+ DEBUG(" </ipv4>");
+ }
+ DEBUG(" </overlay>");
+ DEBUG("</global>");
- return 0;
+ return 0;
}
-int facemgr_cfg_unset_overlay(facemgr_cfg_t * cfg, int family)
-{
- if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC))
- return -1;
+int facemgr_cfg_unset_overlay(facemgr_cfg_t *cfg, int family) {
+ if ((family != AF_INET) && (family != AF_INET6) && (family != AF_UNSPEC))
+ return -1;
- if ((family == AF_UNSPEC) || (family == AF_INET)) {
- if (cfg->global.overlays.v4) {
- facemgr_cfg_overlay_free(cfg->global.overlays.v4);
- cfg->global.overlays.v4 = NULL;
- }
+ if ((family == AF_UNSPEC) || (family == AF_INET)) {
+ if (cfg->global.overlays.v4) {
+ facemgr_cfg_overlay_free(cfg->global.overlays.v4);
+ cfg->global.overlays.v4 = NULL;
}
- if ((family == AF_UNSPEC) || (family == AF_INET6)) {
- if (cfg->global.overlays.v6) {
- facemgr_cfg_overlay_free(cfg->global.overlays.v6);
- cfg->global.overlays.v6 = NULL;
- }
+ }
+ if ((family == AF_UNSPEC) || (family == AF_INET6)) {
+ if (cfg->global.overlays.v6) {
+ facemgr_cfg_overlay_free(cfg->global.overlays.v6);
+ cfg->global.overlays.v6 = NULL;
}
- return 0;
+ }
+ return 0;
}
-int facemgr_cfg_add_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule)
-{
- facemgr_cfg_rule_dump(rule);
- return facemgr_cfg_rule_set_add(cfg->rule_set, rule);
+int facemgr_cfg_add_rule(facemgr_cfg_t *cfg, facemgr_cfg_rule_t *rule) {
+ facemgr_cfg_rule_dump(rule);
+ return facemgr_cfg_rule_set_add(cfg->rule_set, rule);
}
-int facemgr_cfg_del_rule(facemgr_cfg_t * cfg, facemgr_cfg_rule_t * rule)
-{
- return facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL);
+int facemgr_cfg_del_rule(facemgr_cfg_t *cfg, facemgr_cfg_rule_t *rule) {
+ return facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL);
}
-int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name,
- netdevice_type_t interface_type, facemgr_cfg_rule_t ** rule) {
- facemgr_cfg_rule_t rule_search = {
- .match = {
- .interface_name = interface_name,
- .interface_type = interface_type,
- },
- };
- return facemgr_cfg_rule_set_get(cfg->rule_set, &rule_search, rule);
+int facemgr_cfg_get_rule(const facemgr_cfg_t *cfg, const char *interface_name,
+ netdevice_type_t interface_type,
+ facemgr_cfg_rule_t **rule) {
+ facemgr_cfg_rule_t rule_search = {
+ .match =
+ {
+ .interface_name = interface_name,
+ .interface_type = interface_type,
+ },
+ };
+ return facemgr_cfg_rule_set_get(cfg->rule_set, &rule_search, rule);
}
/* Query API */
@@ -709,506 +661,476 @@ int facemgr_cfg_get_rule(const facemgr_cfg_t * cfg, const char * interface_name,
* TODO:
* - until we have proper indexes we loop through the whole structure
*/
-int facemgr_cfg_get_override(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- facemgr_cfg_override_t ** override)
-{
- if (!netdevice) {
- *override = NULL;
- return 0;
- }
-
- facemgr_cfg_rule_t **rule_array;
- int rc = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
- if (rc < 0) {
- ERROR("facemgr_cfg_rule_set_get_array failed");
- return rc;
- }
- for (unsigned i = 0; i < rc; i++) {
- const char * interface_name = rule_array[i]->match.interface_name;
- /* Check match for interface name */
- if (interface_name && (strcmp(interface_name, netdevice->name) != 0))
- continue;
- /* Check match for interface type */
- if (rule_array[i]->match.interface_type != NETDEVICE_TYPE_UNDEFINED) {
-//#ifdef __ANDROID__
- if (netdevice_type != rule_array[i]->match.interface_type)
- continue;
-//#else
-// ERROR("Match on interface type is currently not implemented");
-// goto ERR_ARRAY;
-//#endif /* __ANDROID__ */
- }
- /* Found match... do we have an override for face_type */
- *override = &rule_array[i]->override;
- goto FOUND;
- }
-
+int facemgr_cfg_get_override(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ facemgr_cfg_override_t **override) {
+ if (!netdevice) {
*override = NULL;
-
-FOUND:
- free(rule_array);
return 0;
-
-//#ifndef __ANDROID__
-//ERR_ARRAY:
-// free(rule_array);
-// return -1;
-//#endif /* __ANDROID__ */
-}
-
-int facemgr_cfg_get_face_type(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- facemgr_face_type_t * face_type)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0) {
- ERROR("get override failed");
- return rc;
+ }
+
+ facemgr_cfg_rule_t **rule_array;
+ int rc = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
+ if (rc < 0) {
+ ERROR("facemgr_cfg_rule_set_get_array failed");
+ return rc;
+ }
+ for (unsigned i = 0; i < rc; i++) {
+ facemgr_cfg_rule_t *rule = rule_array[i];
+ if (!rule) continue; /* Should not occur */
+ const char *interface_name = rule->match.interface_name;
+ /* Check match for interface name */
+ if (interface_name && (strcmp(interface_name, netdevice->name) != 0))
+ continue;
+ /* Check match for interface type */
+ if (rule->match.interface_type != NETDEVICE_TYPE_UNDEFINED) {
+ //#ifdef __ANDROID__
+ if (netdevice_type != rule->match.interface_type) continue;
+ //#else
+ // ERROR("Match on interface type is currently not
+ // implemented"); goto ERR_ARRAY;
+ //#endif /* __ANDROID__ */
}
+ /* Found match... do we have an override for face_type */
+ *override = &rule->override;
+ goto FOUND;
+ }
- if ((override) && (override->is_face_type)) {
- *face_type = override->face_type;
- return 0;
- }
-
- *face_type = cfg->global.is_face_type
- ? cfg->global.face_type
- : FACEMGR_FACE_TYPE_DEFAULT;
-
- return 0;
-}
-
-int facemgr_cfg_get_discovery(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * discovery)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
-
- if ((override) && (override->is_discovery)) {
- *discovery = override->discovery;
- return 0;
- }
-
- *discovery = cfg->global.is_discovery
- ? cfg->global.discovery
- : FACEMGR_CFG_DEFAULT_DISCOVERY;
- return 0;
-}
-
-int facemgr_cfg_get_ipv4(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * ipv4)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
+ *override = NULL;
- if ((override) && (override->is_ipv4)) {
- *ipv4 = override->ipv4;
- return 0;
- }
-
- *ipv4 = cfg->global.is_ipv4
- ? cfg->global.ipv4
- : FACEMGR_CFG_DEFAULT_IPV4;
- return 0;
-}
-
-int facemgr_cfg_get_ipv6(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * ipv6)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
-
- if ((override) && (override->is_ipv6)) {
- *ipv6 = override->ipv6;
- return 0;
- }
-
- *ipv6 = cfg->global.is_ipv6
- ? cfg->global.ipv6
- : FACEMGR_CFG_DEFAULT_IPV6;
+FOUND:
+ free(rule_array);
+ return 0;
+
+ //#ifndef __ANDROID__
+ // ERR_ARRAY:
+ // free(rule_array);
+ // return -1;
+ //#endif /* __ANDROID__ */
+}
+
+int facemgr_cfg_get_face_type(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ facemgr_face_type_t *face_type) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) {
+ ERROR("get override failed");
+ return rc;
+ }
+
+ if ((override) && (override->is_face_type)) {
+ *face_type = override->face_type;
return 0;
-}
+ }
-int facemgr_cfg_get_ignore(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- bool * ignore)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
+ *face_type = cfg->global.is_face_type ? cfg->global.face_type
+ : FACEMGR_FACE_TYPE_DEFAULT;
- if ((override) && (override->is_ignore)) {
- *ignore = override->ignore;
- return 0;
- }
-
- assert (!cfg->global.is_ignore);
-
- *ignore = (netdevice && (netdevice->name[0] != '\0') && strcmp(netdevice->name, "lo") == 0);
-
- return 0;
+ return 0;
}
-int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, ip_address_t * addr)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
-
- switch (family) {
- case AF_INET:
- if ((override) && (override->overlays.v4) && (override->overlays.v4->is_local_addr)) {
- *addr = override->overlays.v4->local_addr;
- return 0;
- }
- if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_local_addr)) {
- *addr = cfg->global.overlays.v4->local_addr;
- return 0;
- }
- break;
- case AF_INET6:
- if ((override) && (override->overlays.v6) && (override->overlays.v6->is_local_addr)) {
- *addr = override->overlays.v6->local_addr;
- return 0;
- }
- if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_local_addr)) {
- *addr = cfg->global.overlays.v6->local_addr;
- return 0;
- }
- break;
- case AF_UNSPEC:
- break;
- default:
- return -1;
- }
+int facemgr_cfg_get_discovery(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ bool *discovery) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
- *addr = IP_ADDRESS_EMPTY;
+ if ((override) && (override->is_discovery)) {
+ *discovery = override->discovery;
return 0;
-}
-
-int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, u16 * port)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
-
- switch (family) {
- case AF_INET:
- if ((override) && (override->overlays.v4) && (override->overlays.v4->is_local_port)) {
- *port = override->overlays.v4->local_port;
- return 0;
- }
- if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_local_port)) {
- *port = cfg->global.overlays.v4->local_port;
- return 0;
- }
- break;
- case AF_INET6:
- if ((override) && (override->overlays.v6) && (override->overlays.v6->is_local_port)) {
- *port = override->overlays.v6->local_port;
- return 0;
- }
- if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_local_port)) {
- *port = cfg->global.overlays.v6->local_port;
- return 0;
- }
- break;
- case AF_UNSPEC:
- break;
- default:
- return -1;
- }
+ }
- *port = HICN_DEFAULT_PORT;
- return 0;
+ *discovery = cfg->global.is_discovery ? cfg->global.discovery
+ : FACEMGR_CFG_DEFAULT_DISCOVERY;
+ return 0;
}
-int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, ip_address_t * addr)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
-
- switch (family) {
- case AF_INET:
- if ((override) && (override->overlays.v4) && (override->overlays.v4->is_remote_addr)) {
- DEBUG("remote addr v4 from override");
- *addr = override->overlays.v4->remote_addr;
- return 0;
- }
- if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_remote_addr)) {
- DEBUG("remote addr v4 from global");
- *addr = cfg->global.overlays.v4->remote_addr;
- return 0;
- }
- break;
- case AF_INET6:
- if ((override) && (override->overlays.v6) && (override->overlays.v6->is_remote_addr)) {
- DEBUG("remote addr v6 from override");
- *addr = override->overlays.v6->remote_addr;
- return 0;
- }
- if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_remote_addr)) {
- DEBUG("remote addr v6 from global");
- *addr = cfg->global.overlays.v6->remote_addr;
- return 0;
- }
- break;
- case AF_UNSPEC:
- break;
- default:
- return -1;
- }
+int facemgr_cfg_get_ipv4(const facemgr_cfg_t *cfg, const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type, bool *ipv4) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
- DEBUG("remote addr empty");
- *addr = IP_ADDRESS_EMPTY;
+ if ((override) && (override->is_ipv4)) {
+ *ipv4 = override->ipv4;
return 0;
-}
-
-int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t * cfg,
- const netdevice_t * netdevice, netdevice_type_t netdevice_type,
- int family, u16 * port)
-{
- facemgr_cfg_override_t * override;
- int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type,
- &override);
- if (rc < 0)
- return rc;
-
- switch (family) {
- case AF_INET:
- if ((override) && (override->overlays.v4) && (override->overlays.v4->is_remote_port)) {
- *port = override->overlays.v4->remote_port;
- return 0;
- }
- if ((cfg->global.overlays.v4) && (cfg->global.overlays.v4->is_remote_port)) {
- *port = cfg->global.overlays.v4->remote_port;
- return 0;
- }
- break;
- case AF_INET6:
- if ((override) && (override->overlays.v6) && (override->overlays.v6->is_remote_port)) {
- *port = override->overlays.v6->remote_port;
- return 0;
- }
- if ((cfg->global.overlays.v6) && (cfg->global.overlays.v6->is_remote_port)) {
- *port = cfg->global.overlays.v6->remote_port;
- return 0;
- }
- break;
- case AF_UNSPEC:
- break;
- default:
- return -1;
- }
+ }
- *port = HICN_DEFAULT_PORT;
- return 0;
+ *ipv4 = cfg->global.is_ipv4 ? cfg->global.ipv4 : FACEMGR_CFG_DEFAULT_IPV4;
+ return 0;
}
-int facemgr_cfg_rule_get(const facemgr_cfg_t * cfg, const netdevice_t netdevice, netdevice_type_t
- netdevice_type, facemgr_cfg_rule_t ** rule)
-{
- facemgr_cfg_rule_t **rule_array;
- *rule = NULL;
- int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
- if (n < 0) {
- ERROR("facemgr_cfg_rule_set_get_array failed");
- return n;
- }
- for (unsigned i = 0; i < n; i++) {
- const char * interface_name = rule_array[i]->match.interface_name;
- /* Check match for interface name */
- if (netdevice.name[0] != '\0') {
- if (!interface_name)
- continue;
- if (strcmp(netdevice.name, interface_name) != 0)
- continue;
- } else {
- if (interface_name && interface_name[0] != '\0')
- continue;
- }
-
- /* Check match for netdevice_type */
- if (netdevice_type != rule_array[i]->match.interface_type)
- continue;
-
- /* Found */
- *rule = rule_array[i];
- break;
- }
- return 0;
-}
+int facemgr_cfg_get_ipv6(const facemgr_cfg_t *cfg, const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type, bool *ipv6) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
-int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t * rule,
- facemgr_face_type_t * face_type)
-{
- if (!rule->override.is_face_type)
- return -1;
- *face_type = rule->override.face_type;
+ if ((override) && (override->is_ipv6)) {
+ *ipv6 = override->ipv6;
return 0;
-}
+ }
-int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t * rule, bool * discovery)
-{
- if (!rule->override.is_discovery)
- return -1;
- *discovery = rule->override.discovery;
- return 0;
+ *ipv6 = cfg->global.is_ipv6 ? cfg->global.ipv6 : FACEMGR_CFG_DEFAULT_IPV6;
+ return 0;
}
-int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t * rule, bool * ignore)
-{
- if (!rule->override.is_ignore)
- return -1;
- *ignore = rule->override.ignore;
- return 0;
-}
+int facemgr_cfg_get_ignore(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type, bool *ignore) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
-int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t * rule, bool * ipv4)
-{
- if (!rule->override.is_ipv4)
- return -1;
- *ipv4 = rule->override.ipv4;
+ if ((override) && (override->is_ignore)) {
+ *ignore = override->ignore;
return 0;
-}
+ }
-int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t * rule, bool * ipv6)
-{
- if (!rule->override.is_ipv6)
- return -1;
- *ipv6 = rule->override.ipv6;
- return 0;
-}
+ assert(!cfg->global.is_ignore);
-int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t * rule, int family,
- ip_address_t * addr)
-{
- facemgr_cfg_overlay_t * overlay = NULL;
- switch(family) {
- case AF_INET:
- overlay = rule->override.overlays.v4;
- break;
- case AF_INET6:
- overlay = rule->override.overlays.v6;
- break;
- default:
- return -1;
- }
- if (!overlay->is_local_addr)
- return -1;
- *addr = overlay->local_addr;
- return 0;
-}
+ *ignore = (netdevice && (netdevice->name[0] != '\0') &&
+ strcmp(netdevice->name, "lo") == 0);
-int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t * rule, int family,
- uint16_t * port)
-{
- facemgr_cfg_overlay_t * overlay = NULL;
- switch(family) {
- case AF_INET:
- overlay = rule->override.overlays.v4;
- break;
- case AF_INET6:
- overlay = rule->override.overlays.v6;
- break;
- default:
- return -1;
- }
- if (!overlay->is_local_port)
- return -1;
- *port = overlay->local_port;
- return 0;
+ return 0;
}
-int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t * rule, int family,
- ip_address_t * addr)
-{
- facemgr_cfg_overlay_t * overlay = NULL;
- switch(family) {
- case AF_INET:
- overlay = rule->override.overlays.v4;
- break;
- case AF_INET6:
- overlay = rule->override.overlays.v6;
- break;
- default:
- return -1;
- }
- if (!overlay->is_remote_addr)
- return -1;
- *addr = overlay->remote_addr;
- return 0;
-}
+int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ int family, ip_address_t *addr) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
-int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t * rule, int family,
- uint16_t * port)
-{
- facemgr_cfg_overlay_t * overlay = NULL;
- switch(family) {
- case AF_INET:
- overlay = rule->override.overlays.v4;
- break;
- case AF_INET6:
- overlay = rule->override.overlays.v6;
- break;
- default:
- return -1;
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) &&
+ (override->overlays.v4->is_local_addr)) {
+ *addr = override->overlays.v4->local_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) &&
+ (cfg->global.overlays.v4->is_local_addr)) {
+ *addr = cfg->global.overlays.v4->local_addr;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) &&
+ (override->overlays.v6->is_local_addr)) {
+ *addr = override->overlays.v6->local_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) &&
+ (cfg->global.overlays.v6->is_local_addr)) {
+ *addr = cfg->global.overlays.v6->local_addr;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ *addr = IP_ADDRESS_EMPTY;
+ return 0;
+}
+
+int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ int family, u16 *port) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) &&
+ (override->overlays.v4->is_local_port)) {
+ *port = override->overlays.v4->local_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) &&
+ (cfg->global.overlays.v4->is_local_port)) {
+ *port = cfg->global.overlays.v4->local_port;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) &&
+ (override->overlays.v6->is_local_port)) {
+ *port = override->overlays.v6->local_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) &&
+ (cfg->global.overlays.v6->is_local_port)) {
+ *port = cfg->global.overlays.v6->local_port;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ *port = HICN_DEFAULT_PORT;
+ return 0;
+}
+
+int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ int family, ip_address_t *addr) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) &&
+ (override->overlays.v4->is_remote_addr)) {
+ DEBUG("remote addr v4 from override");
+ *addr = override->overlays.v4->remote_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) &&
+ (cfg->global.overlays.v4->is_remote_addr)) {
+ DEBUG("remote addr v4 from global");
+ *addr = cfg->global.overlays.v4->remote_addr;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) &&
+ (override->overlays.v6->is_remote_addr)) {
+ DEBUG("remote addr v6 from override");
+ *addr = override->overlays.v6->remote_addr;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) &&
+ (cfg->global.overlays.v6->is_remote_addr)) {
+ DEBUG("remote addr v6 from global");
+ *addr = cfg->global.overlays.v6->remote_addr;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ DEBUG("remote addr empty");
+ *addr = IP_ADDRESS_EMPTY;
+ return 0;
+}
+
+int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t *cfg,
+ const netdevice_t *netdevice,
+ netdevice_type_t netdevice_type,
+ int family, u16 *port) {
+ facemgr_cfg_override_t *override;
+ int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override);
+ if (rc < 0) return rc;
+
+ switch (family) {
+ case AF_INET:
+ if ((override) && (override->overlays.v4) &&
+ (override->overlays.v4->is_remote_port)) {
+ *port = override->overlays.v4->remote_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v4) &&
+ (cfg->global.overlays.v4->is_remote_port)) {
+ *port = cfg->global.overlays.v4->remote_port;
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if ((override) && (override->overlays.v6) &&
+ (override->overlays.v6->is_remote_port)) {
+ *port = override->overlays.v6->remote_port;
+ return 0;
+ }
+ if ((cfg->global.overlays.v6) &&
+ (cfg->global.overlays.v6->is_remote_port)) {
+ *port = cfg->global.overlays.v6->remote_port;
+ return 0;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ default:
+ return -1;
+ }
+
+ *port = HICN_DEFAULT_PORT;
+ return 0;
+}
+
+int facemgr_cfg_rule_get(const facemgr_cfg_t *cfg, const netdevice_t netdevice,
+ netdevice_type_t netdevice_type,
+ facemgr_cfg_rule_t **rule_p) {
+ facemgr_cfg_rule_t **rule_array;
+ *rule_p = NULL;
+ int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
+ if (n < 0) {
+ ERROR("facemgr_cfg_rule_set_get_array failed");
+ return n;
+ }
+ for (unsigned i = 0; i < n; i++) {
+ facemgr_cfg_rule_t *rule = rule_array[i];
+ if (!rule) continue; /* Should not occur */
+ const char *interface_name = rule->match.interface_name;
+ /* Check match for interface name */
+ if (netdevice.name[0] != '\0') {
+ if (!interface_name) continue;
+ if (strcmp(netdevice.name, interface_name) != 0) continue;
+ } else {
+ if (interface_name && interface_name[0] != '\0') continue;
}
- if (!overlay->is_remote_port)
- return -1;
- *port = overlay->remote_port;
- return 0;
-}
-int facemgr_cfg_add_static_facelet(facemgr_cfg_t * cfg, facelet_t * facelet)
-{
- char buf[MAXSZ_FACELET];
- facelet_snprintf(buf, MAXSZ_FACELET, facelet);
- DEBUG("STATIC FACELET: %s", buf);
- 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) {
- ERROR("[facemgr_cfg_get_static_facelet_array] Error getting array elements");
- return -1;
- }
- return (int)facelet_array_len(cfg->static_facelets);
+ /* Check match for netdevice_type */
+ if (netdevice_type != rule->match.interface_type) continue;
+
+ /* Found */
+ *rule_p = rule;
+ break;
+ }
+ return 0;
+}
+
+int facemgr_cfg_rule_get_face_type(const facemgr_cfg_rule_t *rule,
+ facemgr_face_type_t *face_type) {
+ if (!rule->override.is_face_type) return -1;
+ *face_type = rule->override.face_type;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_discovery(const facemgr_cfg_rule_t *rule,
+ bool *discovery) {
+ if (!rule->override.is_discovery) return -1;
+ *discovery = rule->override.discovery;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t *rule, bool *ignore) {
+ if (!rule->override.is_ignore) return -1;
+ *ignore = rule->override.ignore;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t *rule, bool *ipv4) {
+ if (!rule->override.is_ipv4) return -1;
+ *ipv4 = rule->override.ipv4;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t *rule, bool *ipv6) {
+ if (!rule->override.is_ipv6) return -1;
+ *ipv6 = rule->override.ipv6;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t *rule,
+ int family, ip_address_t *addr) {
+ facemgr_cfg_overlay_t *overlay = NULL;
+ switch (family) {
+ case AF_INET:
+ overlay = rule->override.overlays.v4;
+ break;
+ case AF_INET6:
+ overlay = rule->override.overlays.v6;
+ break;
+ default:
+ return -1;
+ }
+ if (!overlay->is_local_addr) return -1;
+ *addr = overlay->local_addr;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t *rule,
+ int family, uint16_t *port) {
+ facemgr_cfg_overlay_t *overlay = NULL;
+ switch (family) {
+ case AF_INET:
+ overlay = rule->override.overlays.v4;
+ break;
+ case AF_INET6:
+ overlay = rule->override.overlays.v6;
+ break;
+ default:
+ return -1;
+ }
+ if (!overlay->is_local_port) return -1;
+ *port = overlay->local_port;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t *rule,
+ int family, ip_address_t *addr) {
+ facemgr_cfg_overlay_t *overlay = NULL;
+ switch (family) {
+ case AF_INET:
+ overlay = rule->override.overlays.v4;
+ break;
+ case AF_INET6:
+ overlay = rule->override.overlays.v6;
+ break;
+ default:
+ return -1;
+ }
+ if (!overlay->is_remote_addr) return -1;
+ *addr = overlay->remote_addr;
+ return 0;
+}
+
+int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t *rule,
+ int family, uint16_t *port) {
+ facemgr_cfg_overlay_t *overlay = NULL;
+ switch (family) {
+ case AF_INET:
+ overlay = rule->override.overlays.v4;
+ break;
+ case AF_INET6:
+ overlay = rule->override.overlays.v6;
+ break;
+ default:
+ return -1;
+ }
+ if (!overlay->is_remote_port) return -1;
+ *port = overlay->remote_port;
+ return 0;
+}
+
+int facemgr_cfg_add_static_facelet(facemgr_cfg_t *cfg, facelet_t *facelet) {
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ DEBUG("STATIC FACELET: %s", buf);
+ 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) {
+ ERROR(
+ "[facemgr_cfg_get_static_facelet_array] Error getting array elements");
+ return -1;
+ }
+ return (int)facelet_array_len(cfg->static_facelets);
}
diff --git a/ctrl/facemgr/src/cfg_file.c b/ctrl/facemgr/src/cfg_file.c
index cb1ded1c9..966e35816 100644
--- a/ctrl/facemgr/src/cfg_file.c
+++ b/ctrl/facemgr/src/cfg_file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,338 +18,311 @@
* \brief Implementation of configuration file parsing
*/
-#include <unistd.h> // access
+#include <unistd.h> // access
#include <libconfig.h>
#include <hicn/ctrl/route.h>
#include "cfg_file.h"
-#define ARRAYSIZE(x) (sizeof(x)/sizeof(*x))
+#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x))
-static const char * DEFAULT_CFGFILES[] = {
+static const char *DEFAULT_CFGFILES[] = {
"/etc/facemgr.conf",
"~/facemgr.conf",
};
-int
-probe_cfgfile(char * f)
-{
- for (unsigned i = 0; i < ARRAYSIZE(DEFAULT_CFGFILES); i++) {
- if (access(DEFAULT_CFGFILES[i], F_OK ) != -1) {
- if (!realpath(DEFAULT_CFGFILES[i], f))
- continue;
- return 0;
- }
+int probe_cfgfile(char *f) {
+ for (unsigned i = 0; i < ARRAYSIZE(DEFAULT_CFGFILES); i++) {
+ if (access(DEFAULT_CFGFILES[i], F_OK) != -1) {
+ if (!realpath(DEFAULT_CFGFILES[i], f)) continue;
+ return 0;
}
- return -1;
+ }
+ return -1;
}
-int
-parse_config_global(facemgr_cfg_t * cfg, config_setting_t * setting)
-{
- /* - face_type */
-
- const char *face_type_str;
- facemgr_face_type_t face_type;
- if (config_setting_lookup_string(setting, "face_type", &face_type_str)) {
- if (strcasecmp(face_type_str, "auto") == 0) {
- face_type = FACEMGR_FACE_TYPE_DEFAULT;
- } else
- if (strcasecmp(face_type_str, "native-udp") == 0) {
- face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
- } else
- if (strcasecmp(face_type_str, "native-tcp") == 0) {
- face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
- } else
- if (strcasecmp(face_type_str, "overlay-udp") == 0) {
- face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
- } else
- if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
- face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
- } else {
- ERROR("Invalid face type in section 'global'");
- return -1;
- }
-
- int rc = facemgr_cfg_set_face_type(cfg, &face_type);
- if (rc < 0)
- goto ERR;
+int parse_config_global(facemgr_cfg_t *cfg, config_setting_t *setting) {
+ /* - face_type */
+
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ if (config_setting_lookup_string(setting, "face_type", &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto") == 0) {
+ face_type = FACEMGR_FACE_TYPE_DEFAULT;
+ } else if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ return -1;
}
- /* - disable_discovery */
-
- int disable_discovery;
- if (config_setting_lookup_bool(setting, "disable_discovery",
- &disable_discovery)) {
- int rc = facemgr_cfg_set_discovery(cfg, !disable_discovery);
- if (rc < 0)
- goto ERR;
- }
-
- /* - disable_ipv4 */
-
- int disable_ipv4;
- if (config_setting_lookup_bool(setting, "disable_ipv4",
- &disable_ipv4)) {
- int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4);
- if (rc < 0)
- goto ERR;
- }
-
- /* - disable ipv6 */
-
- int disable_ipv6;
- if (config_setting_lookup_bool(setting, "disable_ipv6",
- &disable_ipv6)) {
- int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6);
- if (rc < 0)
- goto ERR;
+ int rc = facemgr_cfg_set_face_type(cfg, &face_type);
+ if (rc < 0) goto ERR;
+ }
+
+ /* - disable_discovery */
+
+ int disable_discovery;
+ if (config_setting_lookup_bool(setting, "disable_discovery",
+ &disable_discovery)) {
+ int rc = facemgr_cfg_set_discovery(cfg, !disable_discovery);
+ if (rc < 0) goto ERR;
+ }
+
+ /* - disable_ipv4 */
+
+ int disable_ipv4;
+ if (config_setting_lookup_bool(setting, "disable_ipv4", &disable_ipv4)) {
+ int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4);
+ if (rc < 0) goto ERR;
+ }
+
+ /* - disable ipv6 */
+
+ int disable_ipv6;
+ if (config_setting_lookup_bool(setting, "disable_ipv6", &disable_ipv6)) {
+ int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6);
+ if (rc < 0) goto ERR;
+ }
+
+ /* - overlay */
+ config_setting_t *overlay = config_setting_get_member(setting, "overlay");
+ if (overlay) {
+ /* ipv4 */
+ config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
+ if (overlay_v4) {
+ const char *local_addr_str, *remote_addr_str;
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ ip_address_t *local_addr_p = NULL;
+ ip_address_t *remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v4, "local_addr",
+ &local_addr_str)) {
+ if (ip_address_pton(local_addr_str, &local_addr) < 0) {
+ ERROR("Error parsing v4 local addr");
+ goto ERR;
+ }
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port)) goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v4, "remote_addr",
+ &remote_addr_str)) {
+ if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
+ ERROR("Error parsing v4 remote addr");
+ goto ERR;
+ }
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port)) goto ERR;
+ }
+ int rc = facemgr_cfg_set_overlay(cfg, AF_INET, local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0) goto ERR;
}
- /* - overlay */
- config_setting_t *overlay = config_setting_get_member(setting, "overlay");
- if (overlay) {
-
- /* ipv4 */
- config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
- if (overlay_v4) {
- const char * local_addr_str, * remote_addr_str;
- ip_address_t local_addr = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
- if (ip_address_pton(local_addr_str, &local_addr) < 0) {
- ERROR("Error parsing v4 local addr");
- goto ERR;
- }
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v4 remote addr");
- goto ERR;
- }
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_set_overlay(cfg, AF_INET,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
+ /* ipv6 */
+ config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
+ if (overlay_v6) {
+ const char *local_addr_str, *remote_addr_str;
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ ip_address_t *local_addr_p = NULL;
+ ip_address_t *remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v6, "local_addr",
+ &local_addr_str)) {
+ if (ip_address_pton(local_addr_str, &local_addr) < 0) {
+ ERROR("Error parsing v6 local addr");
+ goto ERR;
}
-
- /* ipv6 */
- config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
- if (overlay_v6) {
- const char * local_addr_str, * remote_addr_str;
- ip_address_t local_addr = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
- if (ip_address_pton(local_addr_str, &local_addr) < 0) {
- ERROR("Error parsing v6 local addr");
- goto ERR;
- }
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v6 remote addr");
- goto ERR;
- }
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_set_overlay(cfg, AF_INET6,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port)) goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v6, "remote_addr",
+ &remote_addr_str)) {
+ if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
+ ERROR("Error parsing v6 remote addr");
+ goto ERR;
}
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port)) goto ERR;
+ }
+ int rc = facemgr_cfg_set_overlay(cfg, AF_INET6, local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0) goto ERR;
+ }
- } /* overlay */
+ } /* overlay */
- return 0;
+ return 0;
ERR:
- return -1;
+ return -1;
}
-int
-parse_config_rules(facemgr_cfg_t * cfg, config_setting_t * setting)
-{
- /* List of match-override tuples */
- facemgr_cfg_rule_t * rule;
+int parse_config_rules(facemgr_cfg_t *cfg, config_setting_t *setting) {
+ /* List of match-override tuples */
+ facemgr_cfg_rule_t *rule;
- int count = config_setting_length(setting);
- for (unsigned i = 0; i < count; ++i) {
- config_setting_t * rule_setting = config_setting_get_elem(setting, i);
+ int count = config_setting_length(setting);
+ for (unsigned i = 0; i < count; ++i) {
+ config_setting_t *rule_setting = config_setting_get_elem(setting, i);
- /* Sanity check */
+ /* Sanity check */
- config_setting_t * match_setting = config_setting_get_member(rule_setting, "match");
- if (!match_setting) {
- ERROR("Missing match section in rule #%d", i);
- goto ERR_CHECK;
- }
+ config_setting_t *match_setting =
+ config_setting_get_member(rule_setting, "match");
+ if (!match_setting) {
+ ERROR("Missing match section in rule #%d", i);
+ goto ERR_CHECK;
+ }
- config_setting_t * override_setting = config_setting_get_member(rule_setting, "override");
- if (!override_setting) {
- ERROR("Missing override section in rule #%d", i);
- goto ERR_CHECK;
- }
+ config_setting_t *override_setting =
+ config_setting_get_member(rule_setting, "override");
+ if (!override_setting) {
+ ERROR("Missing override section in rule #%d", i);
+ goto ERR_CHECK;
+ }
- rule = facemgr_cfg_rule_create();
- if (!rule)
- goto ERR_RULE;
-
- /* Parse match */
-
- const char * interface_name = NULL;
- config_setting_lookup_string(match_setting, "interface_name", &interface_name);
-
- const char * interface_type_str;
- netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
- if (config_setting_lookup_string(match_setting, "interface_type", &interface_type_str)) {
- if (strcasecmp(interface_type_str, "wired") == 0) {
- interface_type = NETDEVICE_TYPE_WIRED;
- } else
- if (strcasecmp(interface_type_str, "wifi") == 0) {
- interface_type = NETDEVICE_TYPE_WIFI;
- } else
- if (strcasecmp(interface_type_str, "cellular") == 0) {
- interface_type = NETDEVICE_TYPE_CELLULAR;
- } else {
- ERROR("Unknown interface type in rule #%d", i);
- goto ERR;
- }
- }
+ rule = facemgr_cfg_rule_create();
+ if (!rule) goto ERR_RULE;
+
+ /* Parse match */
+
+ const char *interface_name = NULL;
+ config_setting_lookup_string(match_setting, "interface_name",
+ &interface_name);
+
+ const char *interface_type_str;
+ netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
+ if (config_setting_lookup_string(match_setting, "interface_type",
+ &interface_type_str)) {
+ if (strcasecmp(interface_type_str, "wired") == 0) {
+ interface_type = NETDEVICE_TYPE_WIRED;
+ } else if (strcasecmp(interface_type_str, "wifi") == 0) {
+ interface_type = NETDEVICE_TYPE_WIFI;
+ } else if (strcasecmp(interface_type_str, "cellular") == 0) {
+ interface_type = NETDEVICE_TYPE_CELLULAR;
+ } else {
+ ERROR("Unknown interface type in rule #%d", i);
+ goto ERR;
+ }
+ }
- if ((!interface_name) && (interface_type == NETDEVICE_TYPE_UNDEFINED)) {
- ERROR("Empty match section in rule #%d", i);
- goto ERR;
- }
+ if ((!interface_name) && (interface_type == NETDEVICE_TYPE_UNDEFINED)) {
+ ERROR("Empty match section in rule #%d", i);
+ goto ERR;
+ }
- /* Associate match to rule */
+ /* Associate match to rule */
- int rc = facemgr_cfg_rule_set_match(rule, interface_name, interface_type);
- if (rc < 0)
- goto ERR;
+ int rc = facemgr_cfg_rule_set_match(rule, interface_name, interface_type);
+ if (rc < 0) goto ERR;
- /* Parse override */
+ /* Parse override */
- /* - face_type */
+ /* - face_type */
- const char *face_type_str;
- facemgr_face_type_t face_type;
- if (config_setting_lookup_string(override_setting, "face_type", &face_type_str)) {
- if (strcasecmp(face_type_str, "auto")) {
- /* We currently hardcode different behaviours based on the OS */
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ if (config_setting_lookup_string(override_setting, "face_type",
+ &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto")) {
+ /* We currently hardcode different behaviours based on the OS */
#ifdef __ANDROID__
- face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
#else
- face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
#endif
- } else
- if (strcasecmp(face_type_str, "native-udp") == 0) {
- face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
- } else
- if (strcasecmp(face_type_str, "native-tcp") == 0) {
- face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
- } else
- if (strcasecmp(face_type_str, "overlay-udp") == 0) {
- face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
- } else
- if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
- face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
- } else {
- ERROR("Invalid face type in section 'global'");
- return -1;
- }
+ } else if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ return -1;
+ }
- int rc = facemgr_cfg_rule_set_face_type(rule, &face_type);
- if (rc < 0)
- goto ERR;
- }
+ int rc = facemgr_cfg_rule_set_face_type(rule, &face_type);
+ if (rc < 0) goto ERR;
+ }
- /* - disable_discovery */
+ /* - disable_discovery */
- int disable_discovery;
- if (config_setting_lookup_bool(override_setting, "disable_discovery",
- &disable_discovery)) {
- int rc = facemgr_cfg_rule_set_discovery(rule, !disable_discovery);
- if (rc < 0)
- goto ERR;
- }
+ int disable_discovery;
+ if (config_setting_lookup_bool(override_setting, "disable_discovery",
+ &disable_discovery)) {
+ int rc = facemgr_cfg_rule_set_discovery(rule, !disable_discovery);
+ if (rc < 0) goto ERR;
+ }
- /* - disable_ipv4 */
+ /* - disable_ipv4 */
- int disable_ipv4;
- if (config_setting_lookup_bool(override_setting, "disable_ipv4",
- &disable_ipv4)) {
- INFO("Ignored setting 'disable_ipv4' in rule #%d (not implemented).", i);
+ int disable_ipv4;
+ if (config_setting_lookup_bool(override_setting, "disable_ipv4",
+ &disable_ipv4)) {
+ INFO("Ignored setting 'disable_ipv4' in rule #%d (not implemented).", i);
#if 0
int rc = facemgr_cfg_rule_set_ipv4(rule, !disable_ipv4);
if (rc < 0)
goto ERR;
#endif
- }
+ }
- /* - disable ipv6 */
+ /* - disable ipv6 */
- int disable_ipv6;
- if (config_setting_lookup_bool(override_setting, "disable_ipv6",
- &disable_ipv6)) {
- INFO("Ignored setting 'disable_ipv6' in rule #%d (not implemented).", i);
+ int disable_ipv6;
+ if (config_setting_lookup_bool(override_setting, "disable_ipv6",
+ &disable_ipv6)) {
+ INFO("Ignored setting 'disable_ipv6' in rule #%d (not implemented).", i);
#if 0
int rc = facemgr_cfg_rule_set_ipv6(rule, !disable_ipv6);
if (rc < 0)
goto ERR;
#endif
- }
+ }
- /* - ignore */
- int ignore;
- if (config_setting_lookup_bool(override_setting, "ignore", &ignore)) {
- int rc = facemgr_cfg_rule_set_ignore(rule, !!ignore);
- if (rc < 0)
- goto ERR;
- }
+ /* - ignore */
+ int ignore;
+ if (config_setting_lookup_bool(override_setting, "ignore", &ignore)) {
+ int rc = facemgr_cfg_rule_set_ignore(rule, !!ignore);
+ if (rc < 0) goto ERR;
+ }
- /* - tags */
- config_setting_t *tag_settings = config_setting_get_member(override_setting, "tags");
- if (tag_settings) {
- INFO("Ignored setting 'tags' in rule #%d (not implemented).", i);
+ /* - tags */
+ config_setting_t *tag_settings =
+ config_setting_get_member(override_setting, "tags");
+ if (tag_settings) {
+ INFO("Ignored setting 'tags' in rule #%d (not implemented).", i);
#if 0
policy_tags_t tags = POLICY_TAGS_EMPTY;
for (unsigned j = 0; j < config_setting_length(tag_settings); j++) {
@@ -370,361 +343,337 @@ parse_config_rules(facemgr_cfg_t * cfg, config_setting_t * setting)
DEBUG("Added tags tags=%s", tags_str);
#endif
#endif
+ }
+
+ /* - overlay */
+ config_setting_t *overlay =
+ config_setting_get_member(override_setting, "overlay");
+ if (overlay) {
+ /* ipv4 */
+ config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
+ if (overlay_v4) {
+ const char *local_addr_str, *remote_addr_str;
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ ip_address_t *local_addr_p = NULL;
+ ip_address_t *remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v4, "local_addr",
+ &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
}
- /* - overlay */
- config_setting_t *overlay = config_setting_get_member(override_setting, "overlay");
- if (overlay) {
-
- /* ipv4 */
- config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
- if (overlay_v4) {
- const char * local_addr_str, * remote_addr_str;
- ip_address_t local_addr = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
- ip_address_pton(local_addr_str, &local_addr);
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
- ip_address_pton(remote_addr_str, &remote_addr);
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
- }
+ if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port)) goto ERR;
+ }
- /* ipv6 */
- config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
- if (overlay_v6) {
- const char * local_addr_str, * remote_addr_str;
- ip_address_t local_addr = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
- ip_address_pton(local_addr_str, &local_addr);
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
- ip_address_pton(remote_addr_str, &remote_addr);
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
- }
+ if (config_setting_lookup_string(overlay_v4, "remote_addr",
+ &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
- } /* overlay */
+ if (config_setting_lookup_int(overlay_v4, "remote_port",
+ &remote_port)) {
+ if (!IS_VALID_PORT(remote_port)) goto ERR;
+ }
+ int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET, local_addr_p,
+ local_port, remote_addr_p,
+ remote_port);
+ if (rc < 0) goto ERR;
+ }
+
+ /* ipv6 */
+ config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
+ if (overlay_v6) {
+ const char *local_addr_str, *remote_addr_str;
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ ip_address_t *local_addr_p = NULL;
+ ip_address_t *remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
- /* Add newly created rule */
+ if (config_setting_lookup_string(overlay_v6, "local_addr",
+ &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
- rc = facemgr_cfg_add_rule(cfg, rule);
- if (rc < 0)
- goto ERR;
- }
- return 0;
+ if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port)) goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v6, "remote_addr",
+ &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "remote_port",
+ &remote_port)) {
+ if (!IS_VALID_PORT(remote_port)) goto ERR;
+ }
+ int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6, local_addr_p,
+ local_port, remote_addr_p,
+ remote_port);
+ if (rc < 0) goto ERR;
+ }
+
+ } /* overlay */
+
+ /* Add newly created rule */
+
+ rc = facemgr_cfg_add_rule(cfg, rule);
+ if (rc < 0) goto ERR;
+ }
+ return 0;
ERR:
- facemgr_cfg_rule_free(rule);
+ facemgr_cfg_rule_free(rule);
ERR_RULE:
ERR_CHECK:
- return -1;
+ return -1;
}
-int parse_config_static_facelets(facemgr_cfg_t * cfg, config_setting_t * setting)
-{
- int count = config_setting_length(setting);
- for (unsigned i = 0; i < count; ++i) {
- config_setting_t * static_setting = config_setting_get_elem(setting, i);
-
- const char *face_type_str;
- facemgr_face_type_t face_type;
- const char * family_str;
- int family;
- const char * remote_addr_str;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- int remote_port = 0;
- const char * interface_name;
- const char * interface_type_str;
-
- facelet_t * facelet = facelet_create();
-
- /* Face type */
- if (config_setting_lookup_string(static_setting, "face_type", &face_type_str)) {
- if (strcasecmp(face_type_str, "auto") == 0) {
- face_type = FACEMGR_FACE_TYPE_DEFAULT;
- } else
- if (strcasecmp(face_type_str, "native-udp") == 0) {
- face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
- } else
- if (strcasecmp(face_type_str, "native-tcp") == 0) {
- face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
- } else
- if (strcasecmp(face_type_str, "overlay-udp") == 0) {
- face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
- } else
- if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
- face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
- } else {
- ERROR("Invalid face type in section 'global'");
- goto ERR_FACELET;
- }
+int parse_config_static_facelets(facemgr_cfg_t *cfg,
+ config_setting_t *setting) {
+ int count = config_setting_length(setting);
+ for (unsigned i = 0; i < count; ++i) {
+ config_setting_t *static_setting = config_setting_get_elem(setting, i);
- int rc = facelet_set_face_type(facelet, face_type);
- if (rc < 0)
- goto ERR_FACELET;
- }
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ const char *family_str;
+ int family;
+ const char *remote_addr_str;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ int remote_port = 0;
+ const char *interface_name;
+ const char *interface_type_str;
+
+ facelet_t *facelet = facelet_create();
+
+ /* Face type */
+ if (config_setting_lookup_string(static_setting, "face_type",
+ &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto") == 0) {
+ face_type = FACEMGR_FACE_TYPE_DEFAULT;
+ } else if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ goto ERR_FACELET;
+ }
+
+ int rc = facelet_set_face_type(facelet, face_type);
+ if (rc < 0) goto ERR_FACELET;
+ }
- /* Family */
- if (config_setting_lookup_string(static_setting, "family", &family_str)) {
- if (strcasecmp(family_str, "AF_INET") == 0) {
- family = AF_INET;
- } else
- if (strcasecmp(family_str, "AF_INET6") == 0) {
- family = AF_INET6;
- } else {
- ERROR("Invalid family in section 'static', items #%d", i+1);
- goto ERR_FACELET;
- }
- int rc = facelet_set_family(facelet, family);
- if (rc < 0)
- goto ERR_FACELET;
- }
+ /* Family */
+ if (config_setting_lookup_string(static_setting, "family", &family_str)) {
+ if (strcasecmp(family_str, "AF_INET") == 0) {
+ family = AF_INET;
+ } else if (strcasecmp(family_str, "AF_INET6") == 0) {
+ family = AF_INET6;
+ } else {
+ ERROR("Invalid family in section 'static', items #%d", i + 1);
+ goto ERR_FACELET;
+ }
+ int rc = facelet_set_family(facelet, family);
+ if (rc < 0) goto ERR_FACELET;
+ }
- /* Remote address */
- if (config_setting_lookup_string(static_setting, "remote_addr", &remote_addr_str)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v4 remote addr");
- goto ERR_FACELET;
- }
+ /* Remote address */
+ if (config_setting_lookup_string(static_setting, "remote_addr",
+ &remote_addr_str)) {
+ if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
+ ERROR("Error parsing v4 remote addr");
+ goto ERR_FACELET;
+ }
- int rc = facelet_set_remote_addr(facelet, remote_addr);
- if (rc < 0)
- goto ERR_FACELET;
- }
+ int rc = facelet_set_remote_addr(facelet, remote_addr);
+ if (rc < 0) goto ERR_FACELET;
+ }
- /* Remote port */
- if (config_setting_lookup_int(static_setting, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR_FACELET;
- int rc = facelet_set_remote_port(facelet, remote_port);
- if (rc < 0)
- goto ERR_FACELET;
- }
+ /* Remote port */
+ if (config_setting_lookup_int(static_setting, "remote_port",
+ &remote_port)) {
+ if (!IS_VALID_PORT(remote_port)) goto ERR_FACELET;
+ int rc = facelet_set_remote_port(facelet, remote_port);
+ if (rc < 0) goto ERR_FACELET;
+ }
- /* Interface name */
- if (config_setting_lookup_string(static_setting, "interface_name", &interface_name)) {
- netdevice_t netdevice;
- /* Warning: interface might not exist when we create the facelet */
- snprintf(netdevice.name, IFNAMSIZ, "%s", interface_name);
- netdevice.index = 0;
- int rc = facelet_set_netdevice(facelet, netdevice);
- if (rc < 0)
- goto ERR_FACELET;
- }
+ /* Interface name */
+ if (config_setting_lookup_string(static_setting, "interface_name",
+ &interface_name)) {
+ netdevice_t netdevice;
+ /* Warning: interface might not exist when we create the facelet */
+ snprintf(netdevice.name, IFNAMSIZ, "%s", interface_name);
+ netdevice.index = 0;
+ int rc = facelet_set_netdevice(facelet, netdevice);
+ if (rc < 0) goto ERR_FACELET;
+ }
- /* Interface type */
- netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
- if (config_setting_lookup_string(static_setting, "interface_type", &interface_type_str)) {
- if (strcasecmp(interface_type_str, "wired") == 0) {
- interface_type = NETDEVICE_TYPE_WIRED;
- } else
- if (strcasecmp(interface_type_str, "wifi") == 0) {
- interface_type = NETDEVICE_TYPE_WIFI;
- } else
- if (strcasecmp(interface_type_str, "cellular") == 0) {
- interface_type = NETDEVICE_TYPE_CELLULAR;
- } else {
- ERROR("Unknown interface type in rule #%d", i);
- goto ERR_FACELET;
- }
+ /* Interface type */
+ netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
+ if (config_setting_lookup_string(static_setting, "interface_type",
+ &interface_type_str)) {
+ if (strcasecmp(interface_type_str, "wired") == 0) {
+ interface_type = NETDEVICE_TYPE_WIRED;
+ } else if (strcasecmp(interface_type_str, "wifi") == 0) {
+ interface_type = NETDEVICE_TYPE_WIFI;
+ } else if (strcasecmp(interface_type_str, "cellular") == 0) {
+ interface_type = NETDEVICE_TYPE_CELLULAR;
+ } else {
+ ERROR("Unknown interface type in rule #%d", i);
+ goto ERR_FACELET;
+ }
+
+ int rc = facelet_set_netdevice_type(facelet, interface_type);
+ if (rc < 0) goto ERR_FACELET;
+ }
- int rc = facelet_set_netdevice_type(facelet, interface_type);
- if (rc < 0)
- goto ERR_FACELET;
+ /* Routes */
+ config_setting_t *routes_static_setting =
+ config_setting_get_member(static_setting, "routes");
+ if (routes_static_setting) {
+ /* ... */
+ int count_routes = config_setting_length(routes_static_setting);
+ for (unsigned j = 0; j < count_routes; ++j) {
+ config_setting_t *route_static_setting =
+ config_setting_get_elem(routes_static_setting, j);
+
+ const char *prefix_str;
+ ip_prefix_t prefix;
+ int cost = 0; /* default */
+
+ if (config_setting_lookup_string(route_static_setting, "prefix",
+ &prefix_str)) {
+ if (ip_prefix_pton(prefix_str, &prefix) < 0) {
+ ERROR("Error parsing prefix in route #%d, rule #%d", j, i);
+ goto ERR_FACELET;
+ }
+ } else {
+ ERROR("Cannot add route without prefix");
+ goto ERR_FACELET;
}
- /* Routes */
- config_setting_t * routes_static_setting = config_setting_get_member(static_setting, "routes");
- if (routes_static_setting) {
- /* ... */
- int count_routes = config_setting_length(routes_static_setting);
- for (unsigned j = 0; j < count_routes; ++j) {
- config_setting_t * route_static_setting = config_setting_get_elem(routes_static_setting, j);
-
- const char * prefix_str;
- ip_prefix_t prefix;
- int cost = 0; /* default */
-
- if (config_setting_lookup_string(route_static_setting, "prefix", &prefix_str)) {
- if (ip_prefix_pton(prefix_str, &prefix) < 0) {
- ERROR("Error parsing prefix in route #%d, rule #%d", j, i);
- goto ERR_FACELET;
- }
- } else {
- ERROR("Cannot add route without prefix");
- goto ERR_FACELET;
- }
-
- config_setting_lookup_int(static_setting, "cost", &cost);
-
- hicn_route_t * route = hicn_route_create(&prefix, 0, cost);
- if (!route) {
- ERROR("Could not create hICN route");
- goto ERR_FACELET;
- }
-
- int rc = facelet_add_route(facelet, route);
- if (rc < 0) {
- ERROR("Could not add route to facelet");
- goto ERR_ROUTE;
- }
-
- continue;
-
-ERR_ROUTE:
- hicn_route_free(route);
- goto ERR_FACELET;
- }
+ config_setting_lookup_int(static_setting, "cost", &cost);
+
+ hicn_route_t *route = hicn_route_create(&prefix, 0, cost);
+ if (!route) {
+ ERROR("Could not create hICN route");
+ goto ERR_FACELET;
}
- if (facemgr_cfg_add_static_facelet(cfg, facelet) < 0) {
- ERROR("Could not add static facelet to configuration");
- goto ERR_FACELET;
+ int rc = facelet_add_route(facelet, route);
+ if (rc < 0) {
+ ERROR("Could not add route to facelet");
+ goto ERR_ROUTE;
}
continue;
-ERR_FACELET:
- facelet_free(facelet);
- return -1;
+ ERR_ROUTE:
+ hicn_route_free(route);
+ goto ERR_FACELET;
+ }
+ }
- }
- return 0;
+ if (facemgr_cfg_add_static_facelet(cfg, facelet) < 0) {
+ ERROR("Could not add static facelet to configuration");
+ goto ERR_FACELET;
+ }
+
+ continue;
+
+ ERR_FACELET:
+ facelet_free(facelet);
+ return -1;
+ }
+ return 0;
}
/* Currently not using facemgr_cfg_t */
-int
-parse_config_log(facemgr_cfg_t * cfg, config_setting_t * setting)
-{
- const char *log_level_str;
- if (config_setting_lookup_string(setting, "log_level", &log_level_str)) {
- if (strcasecmp(log_level_str, "FATAL") == 0) {
- log_conf.log_level = LOG_FATAL;
- } else
- if (strcasecmp(log_level_str, "ERROR") == 0) {
- log_conf.log_level = LOG_ERROR;
- } else
- if (strcasecmp(log_level_str, "WARN") == 0) {
- log_conf.log_level = LOG_WARN;
- } else
- if (strcasecmp(log_level_str, "INFO") == 0) {
- log_conf.log_level = LOG_INFO;
- } else
- if (strcasecmp(log_level_str, "DEBUG") == 0) {
- log_conf.log_level = LOG_DEBUG;
- } else
- if (strcasecmp(log_level_str, "TRACE") == 0) {
- log_conf.log_level = LOG_TRACE;
- } else {
- ERROR("Invalid log level in section 'log'");
- return -1;
- }
+int parse_config_log(facemgr_cfg_t *cfg, config_setting_t *setting) {
+ const char *log_level_str;
+ if (config_setting_lookup_string(setting, "log_level", &log_level_str)) {
+ if (strcasecmp(log_level_str, "FATAL") == 0) {
+ log_conf.log_level = LOG_FATAL;
+ } else if (strcasecmp(log_level_str, "ERROR") == 0) {
+ log_conf.log_level = LOG_ERROR;
+ } else if (strcasecmp(log_level_str, "WARN") == 0) {
+ log_conf.log_level = LOG_WARN;
+ } else if (strcasecmp(log_level_str, "INFO") == 0) {
+ log_conf.log_level = LOG_INFO;
+ } else if (strcasecmp(log_level_str, "DEBUG") == 0) {
+ log_conf.log_level = LOG_DEBUG;
+ } else if (strcasecmp(log_level_str, "TRACE") == 0) {
+ log_conf.log_level = LOG_TRACE;
+ } else {
+ ERROR("Invalid log level in section 'log'");
+ return -1;
}
- return 0;
+ }
+ return 0;
}
-int
-parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg)
-{
- /* Reading configuration file */
- config_t cfgfile;
- config_setting_t *setting;
+int parse_config_file(const char *cfgpath, facemgr_cfg_t *cfg) {
+ /* Reading configuration file */
+ config_t cfgfile;
+ config_setting_t *setting;
- config_init(&cfgfile);
+ config_init(&cfgfile);
- /* Read the file. If there is an error, report it and exit. */
- if(!config_read_file(&cfgfile, cfgpath))
- goto ERR_FILE;
+ /* Read the file. If there is an error, report it and exit. */
+ if (!config_read_file(&cfgfile, cfgpath)) goto ERR_FILE;
- setting = config_lookup(&cfgfile, "global");
- if (setting) {
- int rc = parse_config_global(cfg, setting);
- if (rc < 0)
- goto ERR_PARSE;
- }
+ setting = config_lookup(&cfgfile, "global");
+ if (setting) {
+ int rc = parse_config_global(cfg, setting);
+ if (rc < 0) goto ERR_PARSE;
+ }
- setting = config_lookup(&cfgfile, "rules");
- if (setting) {
- int rc = parse_config_rules(cfg, setting);
- if (rc < 0)
- goto ERR_PARSE;
- }
+ setting = config_lookup(&cfgfile, "rules");
+ if (setting) {
+ int rc = parse_config_rules(cfg, setting);
+ if (rc < 0) goto ERR_PARSE;
+ }
- setting = config_lookup(&cfgfile, "static");
- if (setting) {
- int rc = parse_config_static_facelets(cfg, setting);
- if (rc < 0)
- goto ERR_PARSE;
- }
+ setting = config_lookup(&cfgfile, "static");
+ if (setting) {
+ int rc = parse_config_static_facelets(cfg, setting);
+ if (rc < 0) goto ERR_PARSE;
+ }
- setting = config_lookup(&cfgfile, "log");
- if (setting) {
- int rc = parse_config_log(cfg, setting);
- if (rc < 0)
- goto ERR_PARSE;
- }
+ setting = config_lookup(&cfgfile, "log");
+ if (setting) {
+ int rc = parse_config_log(cfg, setting);
+ if (rc < 0) goto ERR_PARSE;
+ }
- config_destroy(&cfgfile);
- return 0;
+ config_destroy(&cfgfile);
+ return 0;
ERR_FILE:
- ERROR("Could not read configuration file %s", cfgpath);
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
- config_error_line(&cfgfile), config_error_text(&cfgfile));
- config_destroy(&cfgfile);
- exit(EXIT_FAILURE);
- return -1;
+ ERROR("Could not read configuration file %s", cfgpath);
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
+ return -1;
ERR_PARSE:
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
- config_error_line(&cfgfile), config_error_text(&cfgfile));
- config_destroy(&cfgfile);
- return -1;
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
+ return -1;
}
-
diff --git a/ctrl/facemgr/src/cfg_file.h b/ctrl/facemgr/src/cfg_file.h
index dfce041d8..fea6a84a6 100644
--- a/ctrl/facemgr/src/cfg_file.h
+++ b/ctrl/facemgr/src/cfg_file.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -28,7 +28,7 @@
* \param [in] f - File name
* \return 0 in case of success, -1 otherwise.
*/
-int probe_cfgfile(char * f);
+int probe_cfgfile(char* f);
/**
* \brief Parses the provided configuration file into the facemgr configuration
@@ -37,6 +37,6 @@ int probe_cfgfile(char * f);
* \param [out] cfg - Pre-allocated configuration data structure
* \return 0 in case of success, -1 otherwise.
*/
-int parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg);
+int parse_config_file(const char* cfgpath, facemgr_cfg_t* cfg);
#endif /* FACEMGR_CFG_FILE_H */
diff --git a/ctrl/facemgr/src/common.h b/ctrl/facemgr/src/common.h
index 56bd706f1..2fda668c8 100644
--- a/ctrl/facemgr/src/common.h
+++ b/ctrl/facemgr/src/common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,71 +32,58 @@
/* Dump with indent */
#define INDENT(n, fmt) "%*s" fmt, n, ""
-#define printfi(n, fmt, ...) printf(INDENT(n*4, fmt), ##__VA_ARGS__)
+#define printfi(n, fmt, ...) printf(INDENT(n * 4, fmt), ##__VA_ARGS__)
#define _unused(x) ((void)(x))
/* Random strings */
-static inline
-void rand_str(char *dest, size_t length) {
- char charset[] = "0123456789"
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- while (length-- > 0) {
- size_t index = (double) rand() / RAND_MAX * (sizeof charset - 1);
- *dest++ = charset[index];
- }
- *dest = '\0';
+static inline void rand_str(char *dest, size_t length) {
+ char charset[] =
+ "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ while (length-- > 0) {
+ size_t index = (double)rand() / RAND_MAX * (sizeof charset - 1);
+ *dest++ = charset[index];
+ }
+ *dest = '\0';
}
/* Boilerplate code */
-#define NO_INITIALIZE(NAME) \
-int \
-NAME ## _initialize(NAME ## _t * obj) { \
- return 0; \
-}
-
-#define NO_FINALIZE(NAME) \
-int \
-NAME ## _finalize(NAME ## _t * obj) { \
- return 0; \
-}
-
-#define AUTOGENERATE_CREATE_FREE(NAME) \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * obj = malloc(sizeof(NAME ## _t)); \
- if (!obj) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(obj) < 0) \
- goto ERR_INIT; \
- \
- return obj; \
- \
-ERR_INIT: \
- free(obj); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * obj) \
-{ \
- if (NAME ## _finalize(obj) < 0) \
- (void)0; /* XXX */ \
- free(obj); \
-} \
-
-#define AUTOGENERATE_DEFS(NAME) \
-int NAME ## _initialize(NAME ## _t *); \
-int NAME ## _finalize(NAME ## _t *); \
-NAME ## _t * NAME ## _create(); \
-void NAME ## _free(NAME ## _t *); \
+#define NO_INITIALIZE(NAME) \
+ int NAME##_initialize(NAME##_t *obj) { return 0; }
+
+#define NO_FINALIZE(NAME) \
+ int NAME##_finalize(NAME##_t *obj) { return 0; }
+
+#define AUTOGENERATE_CREATE_FREE(NAME) \
+ \
+ NAME##_t *NAME##_create() { \
+ NAME##_t *obj = malloc(sizeof(NAME##_t)); \
+ if (!obj) goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize(obj) < 0) goto ERR_INIT; \
+ \
+ return obj; \
+ \
+ ERR_INIT: \
+ free(obj); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free(NAME##_t *obj) { \
+ if (NAME##_finalize(obj) < 0) (void)0; /* XXX */ \
+ free(obj); \
+ }
+
+#define AUTOGENERATE_DEFS(NAME) \
+ int NAME##_initialize(NAME##_t *); \
+ int NAME##_finalize(NAME##_t *); \
+ NAME##_t *NAME##_create(); \
+ void NAME##_free(NAME##_t *);
#endif /* FACEMGR_COMMON_H */
diff --git a/ctrl/facemgr/src/error.c b/ctrl/facemgr/src/error.c
index 4dcea6e1f..36ce5f561 100644
--- a/ctrl/facemgr/src/error.c
+++ b/ctrl/facemgr/src/error.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,8 +21,7 @@
#include "error.h"
const char *FACEMGR_ERROR_STRING[] = {
-#define _(a,b,c) [b] = c,
- foreach_facemgr_error
+#define _(a, b, c) [b] = c,
+ foreach_facemgr_error
#undef _
};
-
diff --git a/ctrl/facemgr/src/error.h b/ctrl/facemgr/src/error.h
index a0d76b3e5..7fadea49f 100644
--- a/ctrl/facemgr/src/error.h
+++ b/ctrl/facemgr/src/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,15 +16,13 @@
#ifndef FACEMGR_ERROR_H
#define FACEMGR_ERROR_H
-#define foreach_facemgr_error \
-_(NONE, 0, "OK") \
-
+#define foreach_facemgr_error _(NONE, 0, "OK")
typedef enum {
-#define _(a,b,c) FACEMGR_ERROR_##a = (-b),
- foreach_facemgr_error
+#define _(a, b, c) FACEMGR_ERROR_##a = (-b),
+ foreach_facemgr_error
#undef _
- FACEMGR_ERROR_N,
+ FACEMGR_ERROR_N,
} facemgr_error_t;
extern const char *HICN_LIB_ERROR_STRING[];
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 9e9f3f67f..609950f75 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,7 +20,7 @@
#include <assert.h>
#include <stdbool.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/ctrl/route.h>
#include <hicn/facemgr/cfg.h>
#include <hicn/facemgr/facelet.h>
@@ -32,152 +32,132 @@
TYPEDEF_SET_H(route_set, hicn_route_t *);
TYPEDEF_SET(route_set, hicn_route_t *, hicn_route_cmp, generic_snprintf);
-const char * face_type_layer_str[] = {
-#define _(x) [FACE_TYPE_LAYER_ ## x] = STRINGIZE(x),
+const char *face_type_layer_str[] = {
+#define _(x) [FACE_TYPE_LAYER_##x] = STRINGIZE(x),
foreach_face_type_layer
#undef _
};
-const char * face_type_encap_str[] = {
-#define _(x) [FACE_TYPE_ENCAP_ ## x] = STRINGIZE(x),
+const char *face_type_encap_str[] = {
+#define _(x) [FACE_TYPE_ENCAP_##x] = STRINGIZE(x),
foreach_face_type_encap
#undef _
};
-const char * facelet_status_str[] = {
-#define _(x) [FACELET_STATUS_ ## x] = STRINGIZE(x),
+const char *facelet_status_str[] = {
+#define _(x) [FACELET_STATUS_##x] = STRINGIZE(x),
foreach_facelet_status
#undef _
};
-const char * facelet_error_reason_str[] = {
-#define _(x) [FACELET_ERROR_REASON_ ## x] = STRINGIZE(x),
+const char *facelet_error_reason_str[] = {
+#define _(x) [FACELET_ERROR_REASON_##x] = STRINGIZE(x),
foreach_facelet_error_reason
#undef _
};
/* Facelet attribute status */
-const char * facelet_attr_status_str[] = {
-#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(x),
+const char *facelet_attr_status_str[] = {
+#define _(x, str) [FACELET_ATTR_STATUS_##x] = STRINGIZE(x),
foreach_facelet_attr_status
#undef _
};
-const char * facelet_attr_status_str_short[] = {
-#define _(x, str) [FACELET_ATTR_STATUS_ ## x] = STRINGIZE(str),
+const char *facelet_attr_status_str_short[] = {
+#define _(x, str) [FACELET_ATTR_STATUS_##x] = STRINGIZE(str),
foreach_facelet_attr_status
#undef _
};
-
/* Facelet */
struct facelet_s {
- unsigned id;
+ unsigned id;
#define _(TYPE, NAME) TYPE NAME;
- foreach_facelet_attr
+ foreach_facelet_attr
#undef _
-#define _(TYPE, NAME) facelet_attr_status_t NAME ## _status;
- foreach_facelet_attr
+#define _(TYPE, NAME) facelet_attr_status_t NAME##_status;
+ foreach_facelet_attr
#undef _
+ facelet_status_t status;
+ int error;
+ facelet_event_t event;
- facelet_status_t status;
- int error;
-
- facelet_event_t event;
-
- route_set_t * routes;
- bool routes_done;
+ route_set_t *routes;
+ bool routes_done;
- bool bj_done;
- bool au_done;
+ bool bj_done;
};
-const char * facelet_event_str[] = {
-#define _(x) [FACELET_EVENT_ ## x] = STRINGIZE(x),
-foreach_facelet_event
+const char *facelet_event_str[] = {
+#define _(x) [FACELET_EVENT_##x] = STRINGIZE(x),
+ foreach_facelet_event
#undef _
};
-facelet_t *
-facelet_create()
-{
- facelet_t * facelet = calloc(1, sizeof(facelet_t));
- if (!facelet)
- goto ERR_MALLOC;
-
- facelet->id = 0;
-
- facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
- facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
- facelet->family_status = FACELET_ATTR_STATUS_UNSET;
- facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
- facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
- facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
- facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
- facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
- facelet->state_status = FACELET_ATTR_STATUS_UNSET;
+facelet_t *facelet_create() {
+ facelet_t *facelet = calloc(1, sizeof(facelet_t));
+ if (!facelet) goto ERR_MALLOC;
+
+ facelet->id = 0;
+
+ facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->family_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->state_status = FACELET_ATTR_STATUS_UNSET;
#ifdef WITH_POLICY
- facelet->priority_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->priority_status = FACELET_ATTR_STATUS_UNSET;
#endif /* WITH_POLICY */
- facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
- facelet->status = FACELET_STATUS_UNDEFINED;
- facelet->error = 0;
+ facelet->status = FACELET_STATUS_UNDEFINED;
+ facelet->error = 0;
- facelet->bj_done = false;
- facelet->au_done = false;
+ facelet->bj_done = false;
- facelet->event = FACELET_EVENT_UNDEFINED;
+ facelet->event = FACELET_EVENT_UNDEFINED;
- facelet->routes = route_set_create();
- if (!facelet->routes) {
- ERROR("[facelet_create] Cannot create route set");
- goto ERR_ROUTE_SET;
- }
- facelet->routes_done = false;
+ facelet->routes = route_set_create();
+ if (!facelet->routes) {
+ ERROR("[facelet_create] Cannot create route set");
+ goto ERR_ROUTE_SET;
+ }
+ facelet->routes_done = false;
- return facelet;
+ return facelet;
ERR_ROUTE_SET:
- free(facelet);
+ free(facelet);
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-unsigned
-facelet_get_id(facelet_t * facelet)
-{
- return facelet->id;
-}
+unsigned facelet_get_id(facelet_t *facelet) { return facelet->id; }
-void
-facelet_set_id(facelet_t * facelet, unsigned id)
-{
- facelet->id = id;
-}
+void facelet_set_id(facelet_t *facelet, unsigned id) { facelet->id = id; }
-facelet_t *
-facelet_create_from_netdevice(netdevice_t * netdevice)
-{
- facelet_t * facelet = facelet_create();
- if (!facelet)
- goto ERR_FACELET;
+facelet_t *facelet_create_from_netdevice(netdevice_t *netdevice) {
+ facelet_t *facelet = facelet_create();
+ if (!facelet) goto ERR_FACELET;
- int rc = facelet_set_netdevice(facelet, *netdevice);
- if (rc < 0)
- goto ERR_NETDEV;
+ int rc = facelet_set_netdevice(facelet, *netdevice);
+ if (rc < 0) goto ERR_NETDEV;
- return facelet;
+ return facelet;
ERR_NETDEV:
- facelet_free(facelet);
+ facelet_free(facelet);
ERR_FACELET:
- return NULL;
+ return NULL;
}
/**
@@ -186,368 +166,339 @@ ERR_FACELET:
* \param [in] facelet - Pointer to the facelet to verify
* \return 0 in case of success, -1 otherwise
*/
-int
-facelet_validate_face(const facelet_t * facelet)
-{
- if (!facelet_has_face_type(facelet))
- return false;
- switch(facelet->face_type.layer) {
- case FACE_TYPE_LAYER_4:
- if (!facelet_has_remote_port(facelet))
- return false;
- if (!facelet_has_remote_addr(facelet))
- return false;
- case FACE_TYPE_LAYER_3:
- if (!facelet_has_local_port(facelet))
- return false;
- if (!facelet_has_local_addr(facelet))
- return false;
- if (!facelet_has_netdevice(facelet))
- return false;
- return true;
-
- default:
- return false; /* Error */
- }
- // FIXME Not implemented
- return 0;
+int facelet_validate_face(const facelet_t *facelet) {
+ if (!facelet_has_face_type(facelet)) return false;
+
+ switch (facelet->face_type.layer) {
+ case FACE_TYPE_LAYER_4:
+ if (!facelet_has_remote_port(facelet)) return false;
+ if (!facelet_has_remote_addr(facelet)) return false;
+ case FACE_TYPE_LAYER_3:
+ if (!facelet_has_local_port(facelet)) return false;
+ if (!facelet_has_local_addr(facelet)) return false;
+ if (!facelet_has_netdevice(facelet)) return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
}
-
-netdevice_type_t
-netdevice_type_from_face_tags(const face_t * face)
-{
- policy_tags_t tags = face->tags;
- if (policy_tags_has(tags, POLICY_TAG_WIRED))
- return NETDEVICE_TYPE_WIRED;
- else if (policy_tags_has(tags, POLICY_TAG_WIFI))
- return NETDEVICE_TYPE_WIFI;
- else if (policy_tags_has(tags, POLICY_TAG_CELLULAR))
- return NETDEVICE_TYPE_CELLULAR;
- return NETDEVICE_TYPE_UNDEFINED;
+netdevice_type_t netdevice_type_from_face_tags(const face_t *face) {
+#ifdef WITH_POLICY
+ policy_tags_t tags = face->tags;
+ if (policy_tags_has(tags, POLICY_TAG_WIRED))
+ return NETDEVICE_TYPE_WIRED;
+ else if (policy_tags_has(tags, POLICY_TAG_WIFI))
+ return NETDEVICE_TYPE_WIFI;
+ else if (policy_tags_has(tags, POLICY_TAG_CELLULAR))
+ return NETDEVICE_TYPE_CELLULAR;
+#endif /* WITH_POLICY */
+ return NETDEVICE_TYPE_UNDEFINED;
}
-facelet_t *
-facelet_create_from_face(face_t * face)
-{
- facelet_t * facelet = malloc(sizeof(facelet_t));
- if (!facelet)
- goto ERR_MALLOC;
+facelet_t *facelet_create_from_face(face_t *face) {
+ facelet_t *facelet = malloc(sizeof(facelet_t));
+ if (!facelet) goto ERR_MALLOC;
- facelet->id = 0;
+ facelet->id = 0;
- /* Go through the face attributes to update the local representation */
+ /* Go through the face attributes to update the local representation */
- /* Attribute : netdevice */
- /* NOTE index is not set */
- if (IS_VALID_NETDEVICE(face->netdevice)) {
- /* /!\ A face has only the netdevice name */
- netdevice_set_name(&facelet->netdevice, face->netdevice.name);
- facelet->netdevice_status = FACELET_ATTR_STATUS_CLEAN;
+ /* Attribute : netdevice */
+ /* NOTE index is not set */
+ if (IS_VALID_NETDEVICE(face->netdevice)) {
+ /* /!\ A face has only the netdevice name */
+ netdevice_set_name(&facelet->netdevice, face->netdevice.name);
+ facelet->netdevice_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : netdevice_type */
+ facelet->netdevice_type = netdevice_type_from_face_tags(face);
+ if (facelet->netdevice_type != NETDEVICE_TYPE_UNDEFINED) {
+ facelet->netdevice_type_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : family */
+ if (IS_VALID_FAMILY(face->family)) {
+ facelet->family = face->family;
+ facelet->family_status = FACELET_ATTR_STATUS_CLEAN;
+
+ /* Attribute : local_addr */
+ if (ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY, face->family) !=
+ 0) {
+ facelet->local_addr = face->local_addr;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_CLEAN;
} else {
- facelet->netdevice_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
}
- /* Attribute : netdevice_type */
- facelet->netdevice_type = netdevice_type_from_face_tags(face);
- if (facelet->netdevice_type != NETDEVICE_TYPE_UNDEFINED) {
- facelet->netdevice_type_status = FACELET_ATTR_STATUS_CLEAN;
+ /* Attribute : local_port */
+ if (IS_VALID_PORT(face->local_port)) {
+ facelet->local_port = face->local_port;
+ facelet->local_port_status = FACELET_ATTR_STATUS_CLEAN;
} else {
- facelet->netdevice_type = NETDEVICE_TYPE_UNDEFINED;
- facelet->netdevice_type_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
}
- /* Attribute : family */
- if (IS_VALID_FAMILY(face->family)) {
- facelet->family = face->family;
- facelet->family_status = FACELET_ATTR_STATUS_CLEAN;
-
- /* Attribute : local_addr */
- if (ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY, face->family) != 0) {
- facelet->local_addr = face->local_addr;
- facelet->local_addr_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
- }
-
- /* Attribute : local_port */
- if (IS_VALID_PORT(face->local_port)) {
- facelet->local_port = face->local_port;
- facelet->local_port_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
- }
-
- /* Attribute : remote_addr */
- if (ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY, face->family) != 0) {
- facelet->remote_addr = face->remote_addr;
- facelet->remote_addr_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
- }
-
- /* Attribute : remote_port */
- if (IS_VALID_PORT(face->remote_port)) {
- facelet->remote_port = face->remote_port;
- facelet->remote_port_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
- }
-
+ /* Attribute : remote_addr */
+ if (ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY, face->family) !=
+ 0) {
+ facelet->remote_addr = face->remote_addr;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_CLEAN;
} else {
- facelet->family_status = FACELET_ATTR_STATUS_UNSET;
- facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
- facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
- facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
- facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
}
- /* Attribute : admin_state */
- if ((face->admin_state == FACE_STATE_UP) ||
- (face->admin_state == FACE_STATE_DOWN)) {
- facelet->admin_state = face->admin_state;
- facelet->admin_state_status = FACELET_ATTR_STATUS_CLEAN;
+ /* Attribute : remote_port */
+ if (IS_VALID_PORT(face->remote_port)) {
+ facelet->remote_port = face->remote_port;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_CLEAN;
} else {
- facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
}
- /* Attribute : state */
- if ((face->state == FACE_STATE_UP) ||
- (face->state == FACE_STATE_DOWN)) {
- facelet->state = face->state;
- facelet->state_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->state_status = FACELET_ATTR_STATUS_UNSET;
- }
+ } else {
+ facelet->family_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->local_port_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_addr_status = FACELET_ATTR_STATUS_UNSET;
+ facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : admin_state */
+ if ((face->admin_state == FACE_STATE_UP) ||
+ (face->admin_state == FACE_STATE_DOWN)) {
+ facelet->admin_state = face->admin_state;
+ facelet->admin_state_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET;
+ }
+
+ /* Attribute : state */
+ if ((face->state == FACE_STATE_UP) || (face->state == FACE_STATE_DOWN)) {
+ facelet->state = face->state;
+ facelet->state_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->state_status = FACELET_ATTR_STATUS_UNSET;
+ }
#ifdef WITH_POLICY
- /* Attribute : priority */
- if (face->priority > 0) {
- facelet->priority = face->priority;
- facelet->priority_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->priority_status = FACELET_ATTR_STATUS_UNSET;
- }
+ /* Attribute : priority */
+ if (face->priority > 0) {
+ facelet->priority = face->priority;
+ facelet->priority_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->priority_status = FACELET_ATTR_STATUS_UNSET;
+ }
#endif /* WITH_POLICY */
- /* Attribute : face_type */
- if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) {
- switch(face->type) {
- case FACE_TYPE_UDP:
- facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
- break;
- case FACE_TYPE_TCP:
- facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
- break;
- case FACE_TYPE_HICN:
- facelet->face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
- break;
- default:
- ERROR("[facelet_create_from_face] Face type not (yet) implemented");
- goto ERR_FACE;
- }
- facelet->face_type_status = FACELET_ATTR_STATUS_CLEAN;
- } else {
- facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
+ /* Attribute : face_type */
+ if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) {
+ switch (face->type) {
+ case FACE_TYPE_UDP:
+ facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ break;
+ case FACE_TYPE_TCP:
+ facelet->face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ break;
+ case FACE_TYPE_HICN:
+ facelet->face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ break;
+ default:
+ ERROR("[facelet_create_from_face] Face type not (yet) implemented");
+ goto ERR_FACE;
}
+ facelet->face_type_status = FACELET_ATTR_STATUS_CLEAN;
+ } else {
+ facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
+ }
- /* Status */
- facelet->status = FACELET_STATUS_CLEAN;
- facelet->error = 0;
+ /* Status */
+ facelet->status = FACELET_STATUS_CLEAN;
+ facelet->error = 0;
- /* TODO Consistency check between face type and found attributes */
- if (facelet_validate_face(facelet) < 0) {
- ERROR("[facelet_create_from_face] Cannot validate face");
- goto ERR_FACE;
- }
+ /* TODO Consistency check between face type and found attributes */
+ if (facelet_validate_face(facelet) < 0) {
+ ERROR("[facelet_create_from_face] Cannot validate face");
+ goto ERR_FACE;
+ }
- facelet->bj_done = false;
- facelet->au_done = false;
+ facelet->bj_done = false;
- facelet->event = FACELET_EVENT_UNDEFINED;
+ facelet->event = FACELET_EVENT_UNDEFINED;
- /* We need to get route set */
- facelet->routes = route_set_create();
- if (!facelet->routes) {
- ERROR("[facelet_create_from_face] Cannot create route set");
- goto ERR_ROUTE_SET;
- }
- facelet->routes_done = false;
+ /* We need to get route set */
+ facelet->routes = route_set_create();
+ if (!facelet->routes) {
+ ERROR("[facelet_create_from_face] Cannot create route set");
+ goto ERR_ROUTE_SET;
+ }
+ facelet->routes_done = false;
- return facelet;
+ return facelet;
ERR_ROUTE_SET:
ERR_FACE:
- free(facelet);
+ free(facelet);
ERR_MALLOC:
- return NULL;
+ return NULL;
}
+void facelet_free(facelet_t *facelet) {
+ /* Workaround: investigate how routes could be NULL */
+ if (!facelet->routes) return;
-void
-facelet_free(facelet_t * facelet)
-{
- /* Free up routes */
- route_set_clear(facelet->routes);
- route_set_free(facelet->routes);
- free(facelet);
+ /* Free up routes */
+ route_set_clear(facelet->routes);
+ route_set_free(facelet->routes);
+ free(facelet);
}
-facelet_t *
-facelet_dup(const facelet_t * current_facelet)
-{
- facelet_t * facelet = facelet_create();
- if (!facelet)
- goto ERR_CREATE;
+facelet_t *facelet_dup(const facelet_t *current_facelet) {
+ facelet_t *facelet = facelet_create();
+ if (!facelet) goto ERR_CREATE;
-#define _(TYPE, NAME) facelet-> NAME = current_facelet-> NAME;
- foreach_facelet_attr
+#define _(TYPE, NAME) facelet->NAME = current_facelet->NAME;
+ foreach_facelet_attr
#undef _
-#define _(TYPE, NAME) facelet-> NAME ## _status = current_facelet-> NAME ## _status;
- foreach_facelet_attr
+#define _(TYPE, NAME) facelet->NAME##_status = current_facelet->NAME##_status;
+ foreach_facelet_attr
#undef _
- facelet->status = current_facelet->status;
- facelet->event = current_facelet->event;
-
- facelet->bj_done = current_facelet->bj_done;
- facelet->au_done = current_facelet->au_done;
-
- /* Routes */
- hicn_route_t ** route_array;
- int n = route_set_get_array(current_facelet->routes, &route_array);
- if (n < 0) {
- ERROR("[facelet_free] Error getting route set associated to facelet");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hicn_route_t * route = route_array[i];
- hicn_route_t * new_route = hicn_route_dup(route);
- if (!new_route)
- goto ERR_ROUTE;
- route_set_add(facelet->routes, new_route);
- }
+ facelet->status = current_facelet->status;
+ facelet->event = current_facelet->event;
+
+ facelet->bj_done = current_facelet->bj_done;
+
+ /* Routes */
+ hicn_route_t **route_array;
+ int n = route_set_get_array(current_facelet->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t *route = route_array[i];
+ if (!route) continue; /* Should not occur */
+ hicn_route_t *new_route = hicn_route_dup(route);
+ if (!new_route) goto ERR_ROUTE;
+ route_set_add(facelet->routes, new_route);
}
- free(route_array);
+ }
+ free(route_array);
- return facelet;
+ return facelet;
ERR_ROUTE:
- /* This will free all routes */
- facelet_free(facelet);
+ /* This will free all routes */
+ facelet_free(facelet);
ERR_CREATE:
- return NULL;
+ return NULL;
}
-int
-facelet_cmp(const facelet_t * f1, const facelet_t * f2)
-{
- /*
- * Under the assumption we only create a face per physical interface, a
- * facelet is uniquely identified by its netdevice attribute, and address
- * family if any.
- *
- * Because of additional static faces, we introduce a unique facelet id
- *
- * This function is mostly used for lookups into the cache, and the face
- * thus needs to have a netdevice associated, and optionally, an address
- * family.
- *
- * For other situations, the `facelet_match` function is more appropriate.
+int facelet_cmp(const facelet_t *f1, const facelet_t *f2) {
+ /*
+ * Under the assumption we only create a face per physical interface, a
+ * facelet is uniquely identified by its netdevice attribute, and address
+ * family if any.
+ *
+ * Because of additional static faces, we introduce a unique facelet id
+ *
+ * This function is mostly used for lookups into the cache, and the face
+ * thus needs to have a netdevice associated, and optionally, an address
+ * family.
+ *
+ * For other situations, the `facelet_match` function is more appropriate.
+ */
+
+ if (f1->id != f2->id) return f1->id > f2->id ? 1 : -1;
+
+ if ((f1->netdevice_status != FACELET_ATTR_STATUS_UNSET) &&
+ (f2->netdevice_status != FACELET_ATTR_STATUS_UNSET)) {
+ int rc = netdevice_cmp(&f1->netdevice, &f2->netdevice);
+ if (rc != 0) return rc;
+
+ } else {
+ /* Both unset : we might have the face without netdevice due to hicn
+ * light not returning it currently, but we cannot skip it in the match
+ * otherwise we cannot distinguish with other faces except matching on
+ * other fields which might unfortunately not be determined yet...
*/
+ return (f1->netdevice_status == FACELET_ATTR_STATUS_UNSET) ? -1 : 1;
+ }
- if (f1->id != f2->id)
- return f1->id > f2->id ? 1 : -1;
-
- if ((f1->netdevice_status != FACELET_ATTR_STATUS_UNSET) &&
- (f2->netdevice_status != FACELET_ATTR_STATUS_UNSET)) {
- int rc = netdevice_cmp(&f1->netdevice, &f2->netdevice);
- if (rc != 0)
- return rc;
-
- } else {
- /* Both unset : we might have the face without netdevice due to hicn
- * light not returning it currently, but we cannot skip it in the match
- * otherwise we cannot distinguish with other faces except matching on
- * other fields which might unfortunately not be determined yet...
- */
- return (f1->netdevice_status == FACELET_ATTR_STATUS_UNSET) ? -1 : 1;
- }
-
- assert(f1->family_status != FACELET_ATTR_STATUS_UNSET);
- assert(f2->family_status != FACELET_ATTR_STATUS_UNSET);
+ assert(f1->family_status != FACELET_ATTR_STATUS_UNSET);
+ assert(f2->family_status != FACELET_ATTR_STATUS_UNSET);
- if ((f1->family == AF_UNSPEC) || (f2->family == AF_UNSPEC))
- return 0;
- int diff = f1->family - f2->family;
- return (diff > 0) ? 1 :
- (diff < 0) ? -1 : 0;
+ if ((f1->family == AF_UNSPEC) || (f2->family == AF_UNSPEC)) return 0;
+ int diff = f1->family - f2->family;
+ return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
}
/*
* If the match has a field set, then the facelet only matches iif it has the
* same field set, and both values are equal
*/
-#define EQUALS_ATTRIBUTE(TYPE, NAME) \
-do { \
- if (facelet_has_ ## NAME(facelet1)) { \
- if (facelet_has_ ## NAME(facelet2)) { \
- TYPE NAME ## 1; \
- TYPE NAME ## 2; \
- if (facelet_get_ ## NAME (facelet1, & NAME ## 1) < 0) \
- return false; \
- if (facelet_get_ ## NAME (facelet2, & NAME ## 2) < 0) \
- return false; \
- if (memcmp(& NAME ## 1, & NAME ## 2, sizeof(TYPE)) != 0) \
- return false; \
- } else { \
- return false; \
- } \
- } else { \
- if (facelet_has_ ## NAME(facelet2)) { \
- return false; \
- } \
- } \
-} while(0)
-
-bool
-facelet_equals(const facelet_t * facelet1, const facelet_t * facelet2)
-{
+#define EQUALS_ATTRIBUTE(TYPE, NAME) \
+ do { \
+ if (facelet_has_##NAME(facelet1)) { \
+ if (facelet_has_##NAME(facelet2)) { \
+ TYPE NAME##1; \
+ TYPE NAME##2; \
+ if (facelet_get_##NAME(facelet1, &NAME##1) < 0) return false; \
+ if (facelet_get_##NAME(facelet2, &NAME##2) < 0) return false; \
+ if (memcmp(&NAME##1, &NAME##2, sizeof(TYPE)) != 0) return false; \
+ } else { \
+ return false; \
+ } \
+ } else { \
+ if (facelet_has_##NAME(facelet2)) { \
+ return false; \
+ } \
+ } \
+ } while (0)
+
+bool facelet_equals(const facelet_t *facelet1, const facelet_t *facelet2) {
#define _(TYPE, NAME) EQUALS_ATTRIBUTE(TYPE, NAME);
- foreach_facelet_attr
+ foreach_facelet_attr
#undef _
- return true;
+ return true;
}
/*
* If the match has a field set, then the facelet only matches iif it has the
* same field set, and both values are equal
*/
-#define MATCH_ATTRIBUTE(TYPE, NAME) \
-do { \
- if (facelet_match->NAME ## _status == FACELET_ATTR_STATUS_CLEAN) { \
- if (facelet_has_ ## NAME(facelet_match)) { \
- TYPE NAME; \
- TYPE NAME ## _match; \
- if (!facelet_has_ ## NAME(facelet)) { \
- continue; /* return false; */ \
- } \
- if (facelet_get_ ## NAME (facelet, & NAME) < 0) \
- return false; \
- if (facelet_get_ ## NAME (facelet_match, & NAME ## _match) < 0) \
- return false; \
- if (memcmp(& NAME, & NAME ## _match, sizeof(NAME)) != 0) { \
- return false; \
- } \
- } \
- } \
-} while(0)
+#define MATCH_ATTRIBUTE(TYPE, NAME) \
+ do { \
+ if (facelet_match->NAME##_status == FACELET_ATTR_STATUS_CLEAN) { \
+ if (facelet_has_##NAME(facelet_match)) { \
+ TYPE NAME; \
+ TYPE NAME##_match; \
+ if (!facelet_has_##NAME(facelet)) { \
+ continue; /* return false; */ \
+ } \
+ if (facelet_get_##NAME(facelet, &NAME) < 0) return false; \
+ if (facelet_get_##NAME(facelet_match, &NAME##_match) < 0) \
+ return false; \
+ if (memcmp(&NAME, &NAME##_match, sizeof(NAME)) != 0) { \
+ return false; \
+ } \
+ } \
+ } \
+ } while (0)
/* facelet_match is the incoming one */
-bool
-facelet_match(const facelet_t * facelet, const facelet_t * facelet_match)
-{
+bool facelet_match(const facelet_t *facelet, const facelet_t *facelet_match) {
#define _(TYPE, NAME) MATCH_ATTRIBUTE(TYPE, NAME);
- foreach_facelet_attr
+ foreach_facelet_attr
#undef _
#if 0
@@ -557,117 +508,101 @@ facelet_match(const facelet_t * facelet, const facelet_t * facelet_match)
facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
DEBUG(" WITH %s", facelet_s);
#endif
- return true;
+ return true;
}
-bool facelet_has_key(const facelet_t * facelet) {
- return (facelet_has_netdevice(facelet) && facelet_has_family(facelet));
+bool facelet_has_key(const facelet_t *facelet) {
+ return (facelet_has_netdevice(facelet) && facelet_has_family(facelet));
}
/*
* Implementation note:
* - facelet_set_* is equivalent to merge with a CLEAN remote attribute
*/
-#define FACELET_ACCESSORS(TYPE, NAME) \
-bool \
-facelet_has_ ## NAME(const facelet_t * facelet) \
-{ \
- assert(facelet); \
- assert(facelet->NAME ## _status != FACELET_ATTR_STATUS_UNDEFINED); \
- assert(facelet->NAME ## _status != FACELET_ATTR_STATUS_N); \
- return ((facelet-> NAME ## _status != FACELET_ATTR_STATUS_UNSET)); \
-} \
- \
-facelet_attr_status_t \
-facelet_get_ ## NAME ## _status(const facelet_t * facelet) \
-{ \
- return (facelet->NAME ## _status); \
-} \
- \
-void \
-facelet_set_ ## NAME ## _status(facelet_t * facelet, \
- facelet_attr_status_t status) \
-{ \
- facelet->NAME ## _status = status; \
-} \
- \
-int \
-facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME) \
-{ \
- assert(facelet); \
- if (!facelet_has_ ## NAME(facelet)) \
- return -1; \
- *NAME = facelet-> NAME; \
- return 0; \
-} \
- \
-int \
-facelet_set_local_ ## NAME(facelet_t * facelet, TYPE NAME) \
-{ \
- assert(facelet); \
- switch(facelet->NAME ## _status) { \
- case FACELET_ATTR_STATUS_UNSET: \
- case FACELET_ATTR_STATUS_CLEAN: \
- case FACELET_ATTR_STATUS_DIRTY: \
- case FACELET_ATTR_STATUS_PENDING: \
- facelet-> NAME = NAME; \
- facelet->NAME ## _status = FACELET_ATTR_STATUS_DIRTY; \
- if (facelet->status == FACELET_STATUS_CLEAN) \
- facelet->status = FACELET_STATUS_UPDATE; \
- break; \
- case FACELET_ATTR_STATUS_CONFLICT: \
- break; \
- case FACELET_ATTR_STATUS_UNDEFINED: \
- case FACELET_ATTR_STATUS_N: \
- ERROR("Unexpected attribute status value"); \
- return -1; \
- } \
- return 0; \
-} \
- \
-int \
-facelet_set_remote_ ## NAME(facelet_t * facelet, TYPE NAME) \
-{ \
- assert(facelet); \
- switch(facelet->NAME ## _status) { \
- case FACELET_ATTR_STATUS_UNSET: \
- facelet-> NAME = NAME; \
- facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \
- break; \
- case FACELET_ATTR_STATUS_CLEAN: \
- facelet->NAME = NAME; \
- break; \
- case FACELET_ATTR_STATUS_DIRTY: \
- ERROR("Discarded remote value for status reasons"); \
- break; \
- case FACELET_ATTR_STATUS_PENDING: \
- ERROR("Received remote value on pending attribute"); \
- facelet->NAME ## _status = FACELET_ATTR_STATUS_CONFLICT; \
- /* We need to proceed to an update of the face */ \
- if (facelet->status != FACELET_STATUS_UPDATE) \
- facelet->status = FACELET_STATUS_UPDATE; \
- break; \
- case FACELET_ATTR_STATUS_CONFLICT: \
- return -1; \
- case FACELET_ATTR_STATUS_UNDEFINED: \
- case FACELET_ATTR_STATUS_N: \
- ERROR("Unexpected attribute status value"); \
- return -1; \
- } \
- return 0; \
-} \
- \
-int \
-facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME) \
-{ \
- return facelet_set_local_ ## NAME(facelet, NAME); \
-} \
- \
-int \
-facelet_unset_ ## NAME(facelet_t * facelet) \
-{ \
- return facelet->NAME ## _status = FACELET_ATTR_STATUS_UNSET; \
-}
+#define FACELET_ACCESSORS(TYPE, NAME) \
+ bool facelet_has_##NAME(const facelet_t *facelet) { \
+ assert(facelet); \
+ assert(facelet->NAME##_status != FACELET_ATTR_STATUS_UNDEFINED); \
+ assert(facelet->NAME##_status != FACELET_ATTR_STATUS_N); \
+ return ((facelet->NAME##_status != FACELET_ATTR_STATUS_UNSET)); \
+ } \
+ \
+ facelet_attr_status_t facelet_get_##NAME##_status( \
+ const facelet_t *facelet) { \
+ return (facelet->NAME##_status); \
+ } \
+ \
+ void facelet_set_##NAME##_status(facelet_t *facelet, \
+ facelet_attr_status_t status) { \
+ facelet->NAME##_status = status; \
+ } \
+ \
+ int facelet_get_##NAME(const facelet_t *facelet, TYPE *NAME) { \
+ assert(facelet); \
+ if (!facelet_has_##NAME(facelet)) return -1; \
+ *NAME = facelet->NAME; \
+ return 0; \
+ } \
+ \
+ int facelet_set_local_##NAME(facelet_t *facelet, TYPE NAME) { \
+ assert(facelet); \
+ switch (facelet->NAME##_status) { \
+ case FACELET_ATTR_STATUS_UNSET: \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ case FACELET_ATTR_STATUS_PENDING: \
+ facelet->NAME = NAME; \
+ facelet->NAME##_status = FACELET_ATTR_STATUS_DIRTY; \
+ if (facelet->status == FACELET_STATUS_CLEAN) \
+ facelet->status = FACELET_STATUS_UPDATE; \
+ break; \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ break; \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ ERROR("Unexpected attribute status value"); \
+ return -1; \
+ } \
+ return 0; \
+ } \
+ \
+ int facelet_set_remote_##NAME(facelet_t *facelet, TYPE NAME) { \
+ assert(facelet); \
+ switch (facelet->NAME##_status) { \
+ case FACELET_ATTR_STATUS_UNSET: \
+ facelet->NAME = NAME; \
+ facelet->NAME##_status = FACELET_ATTR_STATUS_CLEAN; \
+ break; \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ facelet->NAME = NAME; \
+ break; \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ ERROR("Discarded remote value for status reasons"); \
+ break; \
+ case FACELET_ATTR_STATUS_PENDING: \
+ ERROR("Received remote value on pending attribute"); \
+ facelet->NAME##_status = FACELET_ATTR_STATUS_CONFLICT; \
+ /* We need to proceed to an update of the face */ \
+ if (facelet->status != FACELET_STATUS_UPDATE) \
+ facelet->status = FACELET_STATUS_UPDATE; \
+ break; \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ return -1; \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ ERROR("Unexpected attribute status value"); \
+ return -1; \
+ } \
+ return 0; \
+ } \
+ \
+ int facelet_set_##NAME(facelet_t *facelet, TYPE NAME) { \
+ return facelet_set_local_##NAME(facelet, NAME); \
+ } \
+ \
+ int facelet_unset_##NAME(facelet_t *facelet) { \
+ return facelet->NAME##_status = FACELET_ATTR_STATUS_UNSET; \
+ }
#define _(TYPE, NAME) FACELET_ACCESSORS(TYPE, NAME)
foreach_facelet_attr
@@ -681,773 +616,630 @@ foreach_facelet_attr
// FIXME CLEAN for key fields, dirty for fields to update.
-#define MERGE_ATTRIBUTE(TYPE, NAME) \
-do { \
- switch(facelet_to_merge->NAME ## _status) { \
- case FACELET_ATTR_STATUS_UNDEFINED: \
- case FACELET_ATTR_STATUS_N: \
- case FACELET_ATTR_STATUS_PENDING: \
- case FACELET_ATTR_STATUS_CONFLICT: \
- ERROR("Unexpected facelet attribute status"); \
- return -1; \
- case FACELET_ATTR_STATUS_UNSET: \
- break; \
- case FACELET_ATTR_STATUS_CLEAN: \
- case FACELET_ATTR_STATUS_DIRTY: \
- facelet_set_ ## NAME(facelet, facelet_to_merge-> NAME); \
- break; \
- } \
-} while (0)
-
-int facelet_merge(facelet_t * facelet, facelet_t * facelet_to_merge)
-{
- assert(facelet && facelet_to_merge);
+#define MERGE_ATTRIBUTE(TYPE, NAME) \
+ do { \
+ switch (facelet_to_merge->NAME##_status) { \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ case FACELET_ATTR_STATUS_PENDING: \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ ERROR("Unexpected facelet attribute status"); \
+ return -1; \
+ case FACELET_ATTR_STATUS_UNSET: \
+ break; \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ facelet_set_##NAME(facelet, facelet_to_merge->NAME); \
+ break; \
+ } \
+ } while (0)
+
+ int
+ facelet_merge(facelet_t *facelet, facelet_t *facelet_to_merge) {
+ assert(facelet && facelet_to_merge);
#define _(TYPE, NAME) MERGE_ATTRIBUTE(TYPE, NAME);
- foreach_facelet_attr
+ foreach_facelet_attr
#undef _
- facelet->event = facelet_to_merge->event;
-
- /* Routes */
- hicn_route_t ** route_array;
- int n = route_set_get_array(facelet_to_merge->routes, &route_array);
- if (n < 0) {
- ERROR("[facelet_free] Error getting route set associated to facelet");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hicn_route_t * route = route_array[i];
- hicn_route_t * route_found = NULL;
- if (route_set_get(facelet->routes, route, &route_found) < 0) {
- ERROR("Error searching for route");
- continue;
- }
- if (route_found)
- continue;
- route_set_add(facelet->routes, hicn_route_dup(route));
- }
+ facelet->event = facelet_to_merge->event;
+
+ /* Routes */
+ hicn_route_t **route_array;
+ int n = route_set_get_array(facelet_to_merge->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t *route = route_array[i];
+ if (!route) continue; /* Should not occur */
+ hicn_route_t *route_found = NULL;
+ if (route_set_get(facelet->routes, route, &route_found) < 0) {
+ ERROR("Error searching for route");
+ continue;
+ }
+ if (route_found) continue;
+ route_set_add(facelet->routes, hicn_route_dup(route));
}
- free(route_array);
+ }
+ free(route_array);
- return 0;
+ return 0;
}
-#define MERGE_ATTRIBUTE_REMOTE(TYPE, NAME) \
-do { \
- switch(facelet_to_merge->NAME ## _status) { \
- case FACELET_ATTR_STATUS_UNDEFINED: \
- case FACELET_ATTR_STATUS_N: \
- case FACELET_ATTR_STATUS_DIRTY: \
- case FACELET_ATTR_STATUS_PENDING: \
- case FACELET_ATTR_STATUS_CONFLICT: \
- ERROR("Unexpected facelet attribute status"); \
- return -1; \
- case FACELET_ATTR_STATUS_UNSET: \
- break; \
- case FACELET_ATTR_STATUS_CLEAN: \
- facelet_set_ ## NAME(facelet, facelet_to_merge-> NAME); \
- break; \
- \
- } \
-} while (0)
-
-int facelet_merge_remote(facelet_t * facelet, const facelet_t * facelet_to_merge)
-{
- assert(facelet && facelet_to_merge);
+#define MERGE_ATTRIBUTE_REMOTE(TYPE, NAME) \
+ do { \
+ switch (facelet_to_merge->NAME##_status) { \
+ case FACELET_ATTR_STATUS_UNDEFINED: \
+ case FACELET_ATTR_STATUS_N: \
+ case FACELET_ATTR_STATUS_DIRTY: \
+ case FACELET_ATTR_STATUS_PENDING: \
+ case FACELET_ATTR_STATUS_CONFLICT: \
+ ERROR("Unexpected facelet attribute status"); \
+ return -1; \
+ case FACELET_ATTR_STATUS_UNSET: \
+ break; \
+ case FACELET_ATTR_STATUS_CLEAN: \
+ facelet_set_##NAME(facelet, facelet_to_merge->NAME); \
+ break; \
+ } \
+ } while (0)
+
+int facelet_merge_remote(facelet_t *facelet,
+ const facelet_t *facelet_to_merge) {
+ assert(facelet && facelet_to_merge);
#define _(TYPE, NAME) MERGE_ATTRIBUTE_REMOTE(TYPE, NAME);
- foreach_facelet_attr
+ foreach_facelet_attr
#undef _
- facelet->event = facelet_to_merge->event;
- return 0;
+ facelet->event = facelet_to_merge->event;
+ return 0;
}
-int
-facelet_get_face(const facelet_t * facelet, face_t ** pface)
-{
- assert(pface);
-
- /* Facelet has all the required information to create a face */
- if (facelet_validate_face(facelet) < 0) {
- ERROR("[facelet_get_face] Face does not validate");
- return 0;
- }
+int facelet_get_face(const facelet_t *facelet, face_t **pface) {
+ assert(pface);
- face_t * face = face_create();
- if (!face)
- goto ERR_CREATE;
-
- assert(facelet_has_netdevice(facelet));
- face->netdevice = facelet->netdevice;
-
- /* Face type */
- switch(facelet->face_type.layer) {
- case FACE_TYPE_LAYER_4:
- switch(facelet->face_type.encap) {
- case FACE_TYPE_ENCAP_UDP:
- face->type = FACE_TYPE_UDP;
- break;
- case FACE_TYPE_ENCAP_TCP:
- face->type = FACE_TYPE_TCP;
- break;
- case FACE_TYPE_ENCAP_UNDEFINED:
- case FACE_TYPE_ENCAP_N:
- ERROR("[facelet_get_face] Unsupported face encapsulation");
- goto ERR;
- }
-
- if (facelet_get_family(facelet, &face->family) < 0) {
- ERROR("[facelet_get_face] Error retrieving face family");
- goto ERR;
- }
- if (facelet_get_local_addr(facelet, &face->local_addr) < 0) {
- ERROR("[facelet_get_face] Error retrieving face local address");
- goto ERR;
- }
- if (facelet_get_local_port(facelet, &face->local_port) < 0) {
- ERROR("[facelet_get_face] Error retrieving face local port");
- goto ERR;
- }
- if (facelet_get_remote_addr(facelet, &face->remote_addr) < 0) {
- ERROR("[facelet_get_face] Error retrieving face remote address");
- goto ERR;
- }
- if (facelet_get_remote_port(facelet, &face->remote_port) < 0) {
- ERROR("[facelet_get_face] Error retrieving face remote port");
- goto ERR;
- }
- break;
-
- case FACE_TYPE_LAYER_3:
- ERROR("{facelet_get_face] hICN face not (yet) implemented");
- goto ERR;
-
- case FACE_TYPE_LAYER_UNDEFINED:
- case FACE_TYPE_LAYER_N:
- ERROR("[facelet_get_face] Unsupported face type");
- goto ERR;
- }
-
- if (facelet_has_admin_state(facelet)) {
- if (facelet_get_admin_state(facelet, &face->admin_state) < 0) {
- ERROR("[facelet_get_face] Error getting face admin state");
- goto ERR;
- }
- } else {
- face->admin_state = FACE_STATE_UP;
+ /* Facelet has all the required information to create a face */
+ if (facelet_validate_face(facelet) < 0) {
+ ERROR("[facelet_get_face] Face does not validate");
+ return 0;
+ }
+
+ face_t *face = face_create();
+ if (!face) goto ERR_CREATE;
+
+ assert(facelet_has_netdevice(facelet));
+ face->netdevice = facelet->netdevice;
+
+ /* Face type */
+ switch (facelet->face_type.layer) {
+ case FACE_TYPE_LAYER_4:
+ switch (facelet->face_type.encap) {
+ case FACE_TYPE_ENCAP_UDP:
+ face->type = FACE_TYPE_UDP;
+ break;
+ case FACE_TYPE_ENCAP_TCP:
+ face->type = FACE_TYPE_TCP;
+ break;
+ case FACE_TYPE_ENCAP_UNDEFINED:
+ case FACE_TYPE_ENCAP_N:
+ ERROR("[facelet_get_face] Unsupported face encapsulation");
+ goto ERR;
+ }
+
+ if (facelet_get_family(facelet, &face->family) < 0) {
+ ERROR("[facelet_get_face] Error retrieving face family");
+ goto ERR;
+ }
+ if (facelet_get_local_addr(facelet, &face->local_addr) < 0) {
+ ERROR("[facelet_get_face] Error retrieving face local address");
+ goto ERR;
+ }
+ if (facelet_get_local_port(facelet, &face->local_port) < 0) {
+ ERROR("[facelet_get_face] Error retrieving face local port");
+ goto ERR;
+ }
+ if (facelet_get_remote_addr(facelet, &face->remote_addr) < 0) {
+ ERROR("[facelet_get_face] Error retrieving face remote address");
+ goto ERR;
+ }
+ if (facelet_get_remote_port(facelet, &face->remote_port) < 0) {
+ ERROR("[facelet_get_face] Error retrieving face remote port");
+ goto ERR;
+ }
+ break;
+
+ case FACE_TYPE_LAYER_3:
+ ERROR("{facelet_get_face] hICN face not (yet) implemented");
+ goto ERR;
+
+ case FACE_TYPE_LAYER_UNDEFINED:
+ case FACE_TYPE_LAYER_N:
+ ERROR("[facelet_get_face] Unsupported face type");
+ goto ERR;
+ }
+
+ if (facelet_has_admin_state(facelet)) {
+ if (facelet_get_admin_state(facelet, &face->admin_state) < 0) {
+ ERROR("[facelet_get_face] Error getting face admin state");
+ goto ERR;
}
-
- if (facelet_has_state(facelet)) {
- if (facelet_get_state(facelet, &face->state) < 0) {
- ERROR("[facelet_get_face] Error getting face state");
- goto ERR;
- }
- } else {
- face->state = FACE_STATE_UP;
+ } else {
+ face->admin_state = FACE_STATE_UP;
+ }
+
+ if (facelet_has_state(facelet)) {
+ if (facelet_get_state(facelet, &face->state) < 0) {
+ ERROR("[facelet_get_face] Error getting face state");
+ goto ERR;
}
+ } else {
+ face->state = FACE_STATE_UP;
+ }
#ifdef WITH_POLICY
- /* Priority */
- if (facelet_has_priority(facelet)) {
- if (facelet_get_priority(facelet, &face->priority) < 0) {
- ERROR("[facelet_get_face] Error getting face priority");
- goto ERR;
- }
- } else {
- face->priority = 0;
+ /* Priority */
+ if (facelet_has_priority(facelet)) {
+ if (facelet_get_priority(facelet, &face->priority) < 0) {
+ ERROR("[facelet_get_face] Error getting face priority");
+ goto ERR;
+ }
+ } else {
+ face->priority = 0;
+ }
+
+ /* Tags */
+
+ /* - based on netdevice type */
+ policy_tags_t tags = POLICY_TAGS_EMPTY;
+ if (facelet_has_netdevice_type(facelet)) {
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ ERROR("error getting netdevice_type");
+ goto ERR;
}
- /* Tags */
-
- /* - based on netdevice type */
- policy_tags_t tags = POLICY_TAGS_EMPTY;
- if (facelet_has_netdevice_type(facelet)) {
- netdevice_type_t netdevice_type;
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- ERROR("error getting netdevice_type");
- goto ERR;
- }
-
-
- switch(netdevice_type) {
- case NETDEVICE_TYPE_UNDEFINED:
- case NETDEVICE_TYPE_LOOPBACK:
- break;
- case NETDEVICE_TYPE_WIRED:
- policy_tags_add(&tags, POLICY_TAG_WIRED);
- break;
- case NETDEVICE_TYPE_WIFI:
- policy_tags_add(&tags, POLICY_TAG_WIFI);
- break;
- case NETDEVICE_TYPE_CELLULAR:
- policy_tags_add(&tags, POLICY_TAG_CELLULAR);
- break;
- default:
- goto ERR;
- }
+ switch (netdevice_type) {
+ case NETDEVICE_TYPE_UNDEFINED:
+ case NETDEVICE_TYPE_LOOPBACK:
+ break;
+ case NETDEVICE_TYPE_WIRED:
+ policy_tags_add(&tags, POLICY_TAG_WIRED);
+ break;
+ case NETDEVICE_TYPE_WIFI:
+ policy_tags_add(&tags, POLICY_TAG_WIFI);
+ break;
+ case NETDEVICE_TYPE_CELLULAR:
+ policy_tags_add(&tags, POLICY_TAG_CELLULAR);
+ break;
+ default:
+ goto ERR;
}
- face->tags = tags;
+ }
+ face->tags = tags;
#endif /* WITH_POLICY */
- *pface = face;
+ *pface = face;
- return 0;
+ return 0;
ERR:
- free(face);
+ free(face);
ERR_CREATE:
- *pface = NULL;
- return -1;
+ *pface = NULL;
+ return -1;
}
-facelet_status_t
-facelet_get_status(const facelet_t * facelet)
-{
- return facelet->status;
+facelet_status_t facelet_get_status(const facelet_t *facelet) {
+ return facelet->status;
}
-void
-facelet_set_status(facelet_t * facelet, facelet_status_t status)
-{
- facelet->status = status;
+void facelet_set_status(facelet_t *facelet, facelet_status_t status) {
+ facelet->status = status;
}
-#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \
-do { \
- if (facelet->NAME ## _status == FACELET_ATTR_STATUS_DIRTY) \
- facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \
-} while (0)
+#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \
+ do { \
+ if (facelet->NAME##_status == FACELET_ATTR_STATUS_DIRTY) \
+ facelet->NAME##_status = FACELET_ATTR_STATUS_CLEAN; \
+ } while (0)
-void
-facelet_set_attr_clean(facelet_t * facelet)
-{
+void facelet_set_attr_clean(facelet_t *facelet) {
#define _(TYPE, NAME) SET_ATTR_STATUS_CLEAN(TYPE, NAME);
- foreach_facelet_attr
+ foreach_facelet_attr
#undef _
}
-void
-facelet_set_error(facelet_t * facelet, facelet_error_reason_t reason)
-{
- facelet->error++;
- switch(reason) {
- case FACELET_ERROR_REASON_UNSPECIFIED_ERROR:
- case FACELET_ERROR_REASON_INTERNAL_ERROR:
- case FACELET_ERROR_REASON_PERMISSION_DENIED:
- if (facelet->error >= FACELET_MAX_ERRORS)
- facelet_set_status(facelet, FACELET_STATUS_IGNORED);
- break;
- case FACELET_ERROR_REASON_FORWARDER_OFFLINE:
- break;
- case FACELET_ERROR_REASON_UNDEFINED:
- case FACELET_ERROR_REASON_N:
- ERROR("facelet_set_error] Unexpected error reason");
- break;
- }
+void facelet_set_error(facelet_t *facelet, facelet_error_reason_t reason) {
+ facelet->error++;
+ switch (reason) {
+ case FACELET_ERROR_REASON_UNSPECIFIED_ERROR:
+ case FACELET_ERROR_REASON_INTERNAL_ERROR:
+ case FACELET_ERROR_REASON_PERMISSION_DENIED:
+ if (facelet->error >= FACELET_MAX_ERRORS)
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
+ break;
+ case FACELET_ERROR_REASON_FORWARDER_OFFLINE:
+ break;
+ case FACELET_ERROR_REASON_UNDEFINED:
+ case FACELET_ERROR_REASON_N:
+ ERROR("facelet_set_error] Unexpected error reason");
+ break;
+ }
}
-void
-facelet_unset_error(facelet_t * facelet)
-{
- facelet->error = 0;
-}
+void facelet_unset_error(facelet_t *facelet) { facelet->error = 0; }
-bool
-facelet_get_error(const facelet_t * facelet)
-{
- return facelet->error;
-}
+bool facelet_get_error(const facelet_t *facelet) { return facelet->error; }
-void
-facelet_set_bj_done(facelet_t * facelet)
-{
- facelet->bj_done = true;
-}
-
-void
-facelet_unset_bj_done(facelet_t * facelet)
-{
- facelet->bj_done = false;
-}
-
-bool
-facelet_is_bj_done(const facelet_t * facelet)
-{
- return facelet->bj_done;
-}
+void facelet_set_bj_done(facelet_t *facelet) { facelet->bj_done = true; }
-void
-facelet_set_au_done(facelet_t * facelet)
-{
- facelet->au_done = true;
-}
+void facelet_unset_bj_done(facelet_t *facelet) { facelet->bj_done = false; }
-bool
-facelet_is_au_done(const facelet_t * facelet)
-{
- return facelet->au_done;
-}
+bool facelet_is_bj_done(const facelet_t *facelet) { return facelet->bj_done; }
-facelet_event_t
-facelet_get_event(const facelet_t * facelet)
-{
- return facelet->event;
+facelet_event_t facelet_get_event(const facelet_t *facelet) {
+ return facelet->event;
}
-void
-facelet_set_event(facelet_t * facelet, facelet_event_t event)
-{
- facelet->event = event;
+void facelet_set_event(facelet_t *facelet, facelet_event_t event) {
+ facelet->event = event;
}
-int
-facelet_add_route(facelet_t * facelet, hicn_route_t * route)
-{
- return route_set_add(facelet->routes, route);
+int facelet_add_route(facelet_t *facelet, hicn_route_t *route) {
+ return route_set_add(facelet->routes, route);
}
-int
-facelet_remove_route(facelet_t * facelet, hicn_route_t * route, hicn_route_t ** route_removed)
-{
- return route_set_remove(facelet->routes, route, route_removed);
+int facelet_remove_route(facelet_t *facelet, hicn_route_t *route,
+ hicn_route_t **route_removed) {
+ return route_set_remove(facelet->routes, route, route_removed);
}
-int
-facelet_clear_routes(facelet_t * facelet)
-{
- return route_set_clear(facelet->routes);
+int facelet_clear_routes(facelet_t *facelet) {
+ return route_set_clear(facelet->routes);
}
-int
-facelet_get_route_array(const facelet_t * facelet, hicn_route_t *** route_array)
-{
- return route_set_get_array(facelet->routes, route_array);
+int facelet_get_route_array(const facelet_t *facelet,
+ hicn_route_t ***route_array) {
+ return route_set_get_array(facelet->routes, route_array);
}
-int
-facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
-{
- char * cur = s;
- int rc;
-
- assert(facelet);
-
- /* Header + key attributes (netdevice + family) */
- rc = snprintf(cur, s + size - cur, "<Facelet [%d] %s %s (%s)",
- facelet->id,
- facelet_status_str[facelet->status],
- facelet_get_error(facelet) ? "/!\\" : "",
- (facelet->family == AF_INET) ? "AF_INET" :
- (facelet->family == AF_INET6) ? "AF_INET6" :
- (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
- "unknown");
- if (rc < 0)
- return rc;
+int facelet_snprintf(char *s, size_t size, const facelet_t *facelet) {
+ char *cur = s;
+ int rc;
+
+ assert(facelet);
+
+ /* Header + key attributes (netdevice + family) */
+ rc = snprintf(cur, s + size - cur, "<Facelet [%d] %s %s (%s)", facelet->id,
+ facelet_status_str[facelet->status],
+ facelet_get_error(facelet) ? "/!\\" : "",
+ (facelet->family == AF_INET) ? "AF_INET"
+ : (facelet->family == AF_INET6) ? "AF_INET6"
+ : (facelet->family == AF_UNSPEC) ? "AF_UNSPEC"
+ : "unknown");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ /* Netdevice */
+ if (facelet_has_netdevice(facelet)) {
+ rc = snprintf(cur, s + size - cur, " netdevice=%s",
+ facelet->netdevice.name[0] ? facelet->netdevice.name : "*");
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- /* Netdevice */
- if (facelet_has_netdevice(facelet)) {
- rc = snprintf(cur, s + size - cur, " netdevice=%s",
- facelet->netdevice.name[0] ? facelet->netdevice.name : "*");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = snprintf(cur, s + size - cur, "/%d", facelet->netdevice.index);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
+ if (cur >= s + size) return (int)(cur - s);
- } else {
- rc = snprintf(cur, s + size - cur, " netdevice=*/*");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = snprintf(cur, s + size - cur, "/%d", facelet->netdevice.index);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- /* Netdevice type */
- if (facelet_has_netdevice_type(facelet)) {
- rc = snprintf(cur, s + size - cur, " type=%s",
- netdevice_type_str[facelet->netdevice_type]);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ } else {
+ rc = snprintf(cur, s + size - cur, " netdevice=*/*");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Netdevice type */
+ if (facelet_has_netdevice_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, " type=%s",
+ netdevice_type_str(facelet->netdevice_type));
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
- /* Local ip address */
- if (facelet_has_local_addr(facelet)) {
- rc = snprintf(cur, s + size - cur, " local_addr=");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
- facelet->family);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ /* Local ip address */
+ if (facelet_has_local_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, " local_addr=");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- /* Local port */
- if (facelet_has_local_port(facelet)) {
- rc = snprintf(cur, s + size - cur, " local_port=%d",
- facelet->local_port);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
+ facelet->family);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
- /* Remote ip address */
- if (facelet_has_remote_addr(facelet)) {
- rc = snprintf(cur, s + size - cur, " remote_addr=");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
- facelet->family);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ /* Local port */
+ if (facelet_has_local_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, " local_port=%d", facelet->local_port);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
- /* Remote port */
- if (facelet_has_remote_port(facelet)) {
- rc = snprintf(cur, s + size - cur, " remote_port=%d",
- facelet->remote_port);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ /* Remote ip address */
+ if (facelet_has_remote_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, " remote_addr=");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- /* Admin state */
- if (facelet_has_admin_state(facelet)) {
- rc = snprintf(cur, s + size - cur, " admin_state=%s",
- face_state_str[facelet->admin_state]);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
+ facelet->family);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
- /* State */
- if (facelet_has_state(facelet)) {
- rc = snprintf(cur, s + size - cur, " state=%s",
- face_state_str[facelet->state]);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ /* Remote port */
+ if (facelet_has_remote_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, " remote_port=%d", facelet->remote_port);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Admin state */
+ if (facelet_has_admin_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, " admin_state=%s",
+ face_state_str(facelet->admin_state));
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* State */
+ if (facelet_has_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, " state=%s",
+ face_state_str(facelet->state));
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
#ifdef WITH_POLICY
- /* Priority */
- if (facelet_has_priority(facelet)) {
- rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ /* Priority */
+ if (facelet_has_priority(facelet)) {
+ rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
#endif /* WITH_POLICY */
- /* Face type */
- if (facelet_has_face_type(facelet)) {
- rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s",
- FACEMGR_FACE_TYPE_STR(facelet->face_type));
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
-
- /* Routes */
- rc = snprintf(cur, s + size - cur, " routes={ ");
- if (rc < 0)
- return rc;
+ /* Face type */
+ if (facelet_has_face_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s",
+ FACEMGR_FACE_TYPE_STR(facelet->face_type));
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- hicn_route_t ** route_array;
- int n = route_set_get_array(facelet->routes, &route_array);
- if (n < 0) {
- ERROR("[facelet_free] Error getting route set associated to facelet");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hicn_route_t * route = route_array[i];
- rc = (int)hicn_route_snprintf(cur, s + size - cur, route);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = snprintf(cur, s + size - cur, ", ");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Routes */
+ rc = snprintf(cur, s + size - cur, " routes={ ");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ hicn_route_t **route_array;
+ int n = route_set_get_array(facelet->routes, &route_array);
+ if (n < 0) {
+ ERROR("[facelet_free] Error getting route set associated to facelet");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t *route = route_array[i];
+ if (!route) continue; /* Should not occur */
+ rc = (int)hicn_route_snprintf(cur, s + size - cur, route);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ rc = snprintf(cur, s + size - cur, ", ");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
}
- free(route_array);
+ }
+ free(route_array);
- rc = snprintf(cur, s + size - cur, "}>");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
+ rc = snprintf(cur, s + size - cur, "}>");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- return (int)(cur - s);
+ return (int)(cur - s);
}
-int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int indent)
-{
- char * cur = s;
- int rc;
-
- assert(facelet);
-
- /* Header + key attributes (netdevice + family) */
- rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "{\n");
- if (rc < 0)
- return rc;
+int facelet_snprintf_json(char *s, size_t size, const facelet_t *facelet,
+ int indent) {
+ char *cur = s;
+ int rc;
+
+ assert(facelet);
+
+ /* Header + key attributes (netdevice + family) */
+ rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "{\n");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ /* id */
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "",
+ "\"id\"", facelet->id);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ /* Status */
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"status\"", facelet_status_str[facelet->status]);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ /* Family */
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"family\"",
+ (facelet->family == AF_INET) ? "AF_INET"
+ : (facelet->family == AF_INET6) ? "AF_INET6"
+ : (facelet->family == AF_UNSPEC) ? "AF_UNSPEC"
+ : "unknown");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ /* Netdevice */
+ if (facelet_has_netdevice(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"netdevice\"",
+ facelet->netdevice.name[0] ? facelet->netdevice.name : "*");
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- /* id */
- rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "", "\"id\"",
- facelet->id);
- if (rc < 0)
- return rc;
+ if (cur >= s + size) return (int)(cur - s);
+
+ } else {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"netdevice\"", "*");
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- /* Status */
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", "\"status\"",
- facelet_status_str[facelet->status]);
- if (rc < 0)
- return rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Netdevice type */
+ if (facelet_has_netdevice_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"netdevice_type\"",
+ netdevice_type_str(facelet->netdevice_type));
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- /* Family */
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", "\"family\"",
- (facelet->family == AF_INET) ? "AF_INET" :
- (facelet->family == AF_INET6) ? "AF_INET6" :
- (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
- "unknown");
- if (rc < 0)
- return rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Local ip address */
+ if (facelet_has_local_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent + 1), "",
+ "\"local_addr\"");
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- /* Netdevice */
- if (facelet_has_netdevice(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
- "\"netdevice\"",
- facelet->netdevice.name[0] ? facelet->netdevice.name : "*");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- } else {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
- "\"netdevice\"", "*");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ if (cur >= s + size) return (int)(cur - s);
- /* Netdevice type */
- if (facelet_has_netdevice_type(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
- "\"netdevice_type\"",
- netdevice_type_str[facelet->netdevice_type]);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
-
- /* Local ip address */
- if (facelet_has_local_addr(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent+1), "",
- "\"local_addr\"");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
- facelet->family);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = snprintf(cur, s + size - cur, "\",\n");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
-
- /* Local port */
- if (facelet_has_local_port(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "",
- "\"local_port\"",
- facelet->local_port);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
-
- /* Remote ip address */
- if (facelet_has_remote_addr(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent+1), "",
- "\"remote_addr\"");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
- facelet->family);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
-
- rc = snprintf(cur, s + size - cur, "\",\n");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
+ facelet->family);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- /* Remote port */
- if (facelet_has_remote_port(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "",
- "\"remote_port\"",
- facelet->remote_port);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = snprintf(cur, s + size - cur, "\",\n");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Local port */
+ if (facelet_has_local_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "",
+ "\"local_port\"", facelet->local_port);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Remote ip address */
+ if (facelet_has_remote_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent + 1), "",
+ "\"remote_addr\"");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- /* Admin state */
- if (facelet_has_admin_state(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
- "\"admin_state\"",
- face_state_str[facelet->admin_state]);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
+ facelet->family);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- /* State */
- if (facelet_has_state(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
- "\"state\"",
- face_state_str[facelet->state]);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ rc = snprintf(cur, s + size - cur, "\",\n");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Remote port */
+ if (facelet_has_remote_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "",
+ "\"remote_port\"", facelet->remote_port);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* Admin state */
+ if (facelet_has_admin_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"admin_state\"", face_state_str(facelet->admin_state));
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
+
+ /* State */
+ if (facelet_has_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent + 1), "",
+ "\"state\"", face_state_str(facelet->state));
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
#ifdef WITH_POLICY
- /* Priority */
- if (facelet_has_priority(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "",
- "\"priority\"", facelet->priority);
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
+ /* Priority */
+ if (facelet_has_priority(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "",
+ "\"priority\"", facelet->priority);
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
+ }
#endif /* WITH_POLICY */
- if (facelet_has_face_type(facelet)) {
- rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", 4 * (indent+1), "",
- "\"face_type\"",
- FACEMGR_FACE_TYPE_STR(facelet->face_type));
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
- }
-
- /* Status error */
- rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\"\n", 4 * (indent+1), "",
- "\"error\"",
- facelet_get_error(facelet) ? "true" : "false");
- if (rc < 0)
- return rc;
+ if (facelet_has_face_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n",
+ 4 * (indent + 1), "", "\"face_type\"",
+ FACEMGR_FACE_TYPE_STR(facelet->face_type));
+ if (rc < 0) return rc;
cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
+ if (cur >= s + size) return (int)(cur - s);
+ }
- /* Routes */
- // TODO
+ /* Status error */
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\"\n", 4 * (indent + 1), "",
+ "\"error\"", facelet_get_error(facelet) ? "true" : "false");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "}");
- if (rc < 0)
- return rc;
- cur += rc;
- if (cur >= s + size)
- return (int)(cur - s);
+ /* Routes */
+ // TODO
+
+ rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "}");
+ if (rc < 0) return rc;
+ cur += rc;
+ if (cur >= s + size) return (int)(cur - s);
- return (int)(cur - s);
+ return (int)(cur - s);
}
diff --git a/ctrl/facemgr/src/facelet_array.c b/ctrl/facemgr/src/facelet_array.c
index 3ee110b8e..d48625979 100644
--- a/ctrl/facemgr/src/facelet_array.c
+++ b/ctrl/facemgr/src/facelet_array.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,4 +23,3 @@
#include "facelet_array.h"
TYPEDEF_ARRAY(facelet_array, facelet_t *, facelet_equals, facelet_snprintf);
-
diff --git a/ctrl/facemgr/src/facelet_array.h b/ctrl/facemgr/src/facelet_array.h
index 099774691..b3b17e88b 100644
--- a/ctrl/facemgr/src/facelet_array.h
+++ b/ctrl/facemgr/src/facelet_array.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/ctrl/facemgr/src/interface.c b/ctrl/facemgr/src/interface.c
index 7f95be4ce..a9aeeaf33 100644
--- a/ctrl/facemgr/src/interface.c
+++ b/ctrl/facemgr/src/interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -29,170 +29,144 @@
#include "interface.h"
TYPEDEF_MAP_H(interface_ops_map, const char *, const interface_ops_t *);
-TYPEDEF_MAP(interface_ops_map, const char *, const interface_ops_t *, strcmp, string_snprintf, generic_snprintf);
-
-static interface_ops_map_t * interface_ops_map = NULL;
-
-int
-interface_register(const interface_ops_t * ops)
-{
- if (!interface_ops_map) {
- interface_ops_map = interface_ops_map_create();
- if (!interface_ops_map)
- return -1;
- }
- interface_ops_map_add(interface_ops_map, ops->type, ops);
- return 0;
+TYPEDEF_MAP(interface_ops_map, const char *, const interface_ops_t *, strcmp,
+ string_snprintf, generic_snprintf);
+
+static interface_ops_map_t *interface_ops_map = NULL;
+
+int interface_register(const interface_ops_t *ops) {
+ if (!interface_ops_map) {
+ interface_ops_map = interface_ops_map_create();
+ if (!interface_ops_map) return -1;
+ }
+ interface_ops_map_add(interface_ops_map, ops->type, ops);
+ return 0;
}
-int
-interface_unregister_all()
-{
- int ret = 0;
- const char ** ops_name_array = NULL;
- int n = interface_ops_map_get_key_array(interface_ops_map, &ops_name_array);
- if (n < 0) {
- ERROR("[interface_unregister_all] Could not get interface ops array");
- return -1;
- }
-
- for (unsigned i = 0; i < n; i++) {
- const char * ops_name = ops_name_array[i];
- if (interface_ops_map_remove(interface_ops_map, ops_name, NULL) < 0) {
- ERROR("[interface_unregister_all] Could not remove %s from interface ops map", ops_name);
- ret = -1;
- }
+int interface_unregister_all() {
+ int ret = 0;
+ const char **ops_name_array = NULL;
+ int n = interface_ops_map_get_key_array(interface_ops_map, &ops_name_array);
+ if (n < 0) {
+ ERROR("[interface_unregister_all] Could not get interface ops array");
+ return -1;
+ }
+
+ for (unsigned i = 0; i < n; i++) {
+ const char *ops_name = ops_name_array[i];
+ if (interface_ops_map_remove(interface_ops_map, ops_name, NULL) < 0) {
+ ERROR(
+ "[interface_unregister_all] Could not remove %s from interface ops "
+ "map",
+ ops_name);
+ ret = -1;
}
- free(ops_name_array);
+ }
+ free(ops_name_array);
- interface_ops_map_free(interface_ops_map);
- interface_ops_map = NULL;
+ interface_ops_map_free(interface_ops_map);
+ interface_ops_map = NULL;
- return ret;
+ return ret;
}
-interface_t *
-interface_create(const char * name, const char * type)
-{
-
- const interface_ops_t * ops = NULL;
- int rc = interface_ops_map_get(interface_ops_map, type, &ops);
- if (rc < 0) {
- printf("Interface type not found %s\n", type);
- return NULL;
- }
-
- interface_t * interface = malloc(sizeof(interface_t));
- if (!interface)
- return NULL;
-
- interface->name = strdup(name);
- /* this should use type */
- interface->ops = ops;
- interface->callback = NULL;
- interface->callback_owner = NULL;
- interface->data = NULL;
-
- return interface;
+interface_t *interface_create(const char *name, const char *type) {
+ const interface_ops_t *ops = NULL;
+ int rc = interface_ops_map_get(interface_ops_map, type, &ops);
+ if (rc < 0) {
+ printf("Interface type not found %s\n", type);
+ return NULL;
+ }
+
+ interface_t *interface = malloc(sizeof(interface_t));
+ if (!interface) return NULL;
+
+ interface->name = strdup(name);
+ /* this should use type */
+ interface->ops = ops;
+ interface->callback = NULL;
+ interface->callback_owner = NULL;
+ interface->data = NULL;
+
+ return interface;
}
-void
-interface_free(interface_t * interface)
-{
- free(interface->name);
- free(interface);
+void interface_free(interface_t *interface) {
+ free(interface->name);
+ free(interface);
}
-void
-interface_set_callback(interface_t * interface, void * callback_owner,
- interface_cb_t callback)
-{
- interface->callback = callback;
- interface->callback_owner = callback_owner;
+void interface_set_callback(interface_t *interface, void *callback_owner,
+ interface_cb_t callback) {
+ interface->callback = callback;
+ interface->callback_owner = callback_owner;
}
-int
-interface_initialize(interface_t * interface, void * cfg)
-{
- if (!interface->ops->initialize)
- return -1;
- return interface->ops->initialize(interface, cfg);
+int interface_initialize(interface_t *interface, void *cfg) {
+ if (!interface->ops->initialize) return -1;
+ return interface->ops->initialize(interface, cfg);
}
-int
-interface_finalize(interface_t * interface)
-{
- if (!interface->ops->finalize)
- return -1;
- return interface->ops->finalize(interface);
+int interface_finalize(interface_t *interface) {
+ if (!interface->ops->finalize) return -1;
+ return interface->ops->finalize(interface);
}
-int
-interface_on_event(interface_t * interface, facelet_t * facelet)
-{
- if (!interface->ops->on_event)
- return -1;
- return interface->ops->on_event(interface, facelet);
+int interface_on_event(interface_t *interface, facelet_t *facelet) {
+ if (!interface->ops->on_event) return -1;
+ return interface->ops->on_event(interface, facelet);
}
-int
-interface_raise_event(interface_t * interface, facelet_t * facelet)
-{
- assert(interface->callback);
- return interface->callback(interface->callback_owner,
- INTERFACE_CB_TYPE_RAISE_EVENT, facelet);
+int interface_raise_event(interface_t *interface, facelet_t *facelet) {
+ assert(interface->callback);
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_RAISE_EVENT, facelet);
}
-int
-interface_register_fd(interface_t * interface, int fd, void * data)
-{
- assert(interface->callback);
- fd_callback_data_t fd_callback = {
- .fd = fd,
- .owner = interface,
- .callback = (fd_callback_t)interface->ops->callback,
- .data = data,
- };
- return interface->callback(interface->callback_owner,
- INTERFACE_CB_TYPE_REGISTER_FD, &fd_callback);
+int interface_register_fd(interface_t *interface, int fd, void *data) {
+ assert(interface->callback);
+ fd_callback_data_t fd_callback = {
+ .fd = fd,
+ .owner = interface,
+ .callback = (fd_callback_t)interface->ops->callback,
+ .data = data,
+ };
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_REGISTER_FD, &fd_callback);
}
-int
-interface_unregister_fd(interface_t * interface, int fd)
-{
- assert(interface->callback);
- fd_callback_data_t fd_callback = {
- .fd = fd,
- .owner = interface,
- .callback = NULL,
- .data = NULL,
- };
- return interface->callback(interface->callback_owner,
- INTERFACE_CB_TYPE_UNREGISTER_FD, &fd_callback);
+int interface_unregister_fd(interface_t *interface, int fd) {
+ assert(interface->callback);
+ fd_callback_data_t fd_callback = {
+ .fd = fd,
+ .owner = interface,
+ .callback = NULL,
+ .data = NULL,
+ };
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_UNREGISTER_FD, &fd_callback);
}
-typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused);
-
-int
-interface_register_timer(interface_t * interface, unsigned delay_ms,
- interface_fd_callback_t callback, void * data)
-{
- assert(interface->callback);
- timer_callback_data_t timer_callback = {
- .delay_ms = delay_ms,
- .owner = interface,
- .callback = (fd_callback_t)callback,
- .data = data,
- };
- int rc = interface->callback(interface->callback_owner,
- INTERFACE_CB_TYPE_REGISTER_TIMER, &timer_callback);
- return rc;
+typedef int (*interface_fd_callback_t)(interface_t *interface, int fd,
+ void *unused);
+
+int interface_register_timer(interface_t *interface, unsigned delay_ms,
+ interface_fd_callback_t callback, void *data) {
+ assert(interface->callback);
+ timer_callback_data_t timer_callback = {
+ .delay_ms = delay_ms,
+ .owner = interface,
+ .callback = (fd_callback_t)callback,
+ .data = data,
+ };
+ int rc =
+ interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_REGISTER_TIMER, &timer_callback);
+ return rc;
}
-int
-interface_unregister_timer(interface_t * interface, int fd)
-{
- assert(interface->callback);
- return interface->callback(interface->callback_owner,
- INTERFACE_CB_TYPE_UNREGISTER_TIMER, &fd);
+int interface_unregister_timer(interface_t *interface, int fd) {
+ assert(interface->callback);
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_UNREGISTER_TIMER, &fd);
}
diff --git a/ctrl/facemgr/src/interface.h b/ctrl/facemgr/src/interface.h
index a4fbda1fb..a999036d5 100644
--- a/ctrl/facemgr/src/interface.h
+++ b/ctrl/facemgr/src/interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,40 +32,41 @@
#include <hicn/facemgr/loop.h>
typedef enum {
- INTERFACE_CB_TYPE_REGISTER_FD,
- INTERFACE_CB_TYPE_UNREGISTER_FD,
- INTERFACE_CB_TYPE_RAISE_EVENT,
- INTERFACE_CB_TYPE_REGISTER_TIMER,
- INTERFACE_CB_TYPE_UNREGISTER_TIMER,
+ INTERFACE_CB_TYPE_REGISTER_FD,
+ INTERFACE_CB_TYPE_UNREGISTER_FD,
+ INTERFACE_CB_TYPE_RAISE_EVENT,
+ INTERFACE_CB_TYPE_REGISTER_TIMER,
+ INTERFACE_CB_TYPE_UNREGISTER_TIMER,
} interface_cb_type_t;
-typedef int (*interface_cb_t)(facemgr_t * facemgr, interface_cb_type_t type, void * data);
+typedef int (*interface_cb_t)(facemgr_t* facemgr, interface_cb_type_t type,
+ void* data);
/**
* \brief Interface operations
*/
struct interface_s;
typedef struct {
- /** The type given to the interfaces */
- char * type;
- /* Constructor */
- int (*initialize)(struct interface_s * interface, void * cfg);
- /* Destructor */
- int (*finalize)(struct interface_s * interface);
- /* Callback upon file descriptor event (iif previously registered) */
- int (*callback)(struct interface_s * interface, int fd, void * data);
- /* Callback upon face events coming from the face manager */
- int (*on_event)(struct interface_s * interface, struct facelet_s * facelet);
+ /** The type given to the interfaces */
+ char* type;
+ /* Constructor */
+ int (*initialize)(struct interface_s* interface, void* cfg);
+ /* Destructor */
+ int (*finalize)(struct interface_s* interface);
+ /* Callback upon file descriptor event (iif previously registered) */
+ int (*callback)(struct interface_s* interface, int fd, void* data);
+ /* Callback upon face events coming from the face manager */
+ int (*on_event)(struct interface_s* interface, struct facelet_s* facelet);
} interface_ops_t;
typedef struct interface_s {
- char * name;
- const interface_ops_t * ops;
+ char* name;
+ const interface_ops_t* ops;
- interface_cb_t callback;
- void * callback_owner;
+ interface_cb_t callback;
+ void* callback_owner;
- void * data;
+ void* data;
} interface_t;
/**
@@ -75,7 +76,7 @@ typedef struct interface_s {
* \return Flag indicating the success (FACEMGR_SUCCESS=0), or failure (any
* other value) of the operation.
*/
-int interface_register(const interface_ops_t * ops);
+int interface_register(const interface_ops_t* ops);
int interface_unregister_all();
@@ -91,22 +92,22 @@ int interface_unregister_all();
* \return A a pointer to the newly created instance of the requested type, or
* NULL in case of failure.
*/
-interface_t * interface_create(const char * name, const char * type);
+interface_t* interface_create(const char* name, const char* type);
/**
* \brief Free an interface instance.
* \param [in] interface - Pointer to the instance to free.
*/
-void interface_free(interface_t * interface);
+void interface_free(interface_t* interface);
+void interface_set_callback(interface_t* interface, void* callback_owner,
+ interface_cb_t callback);
-void interface_set_callback(interface_t * interface, void * callback_owner, interface_cb_t callback);
+int interface_initialize(interface_t* interface, void* cfg);
-int interface_initialize(interface_t * interface, void * cfg);
+int interface_finalize(interface_t* interface);
-int interface_finalize(interface_t * interface);
-
-int interface_on_event(interface_t * interface, struct facelet_s * facelet);
+int interface_on_event(interface_t* interface, struct facelet_s* facelet);
/**
* \brief Raises a facelet event to the face manager
@@ -115,15 +116,17 @@ int interface_on_event(interface_t * interface, struct facelet_s * facelet);
* \param [in] facelet - Facelet to communicate with the event
* \return Error code
*/
-int interface_callback(interface_t * interface, interface_cb_type_t type, void * data);
+int interface_callback(interface_t* interface, interface_cb_type_t type,
+ void* data);
-int interface_raise_event(interface_t * interface, facelet_t * facelet);
+int interface_raise_event(interface_t* interface, facelet_t* facelet);
-int interface_register_fd(interface_t * interface, int fd, void * data);
+int interface_register_fd(interface_t* interface, int fd, void* data);
-int interface_unregister_fd(interface_t * interface, int fd);
+int interface_unregister_fd(interface_t* interface, int fd);
-typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused);
+typedef int (*interface_fd_callback_t)(interface_t* interface, int fd,
+ void* unused);
/**
* \brief Registers a timer event
@@ -135,8 +138,8 @@ typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * u
* \return A positive value uniquely identifying the timer, or -1 in case of
* error
*/
-int interface_register_timer(interface_t * interface, unsigned delay_ms,
- interface_fd_callback_t callback, void * data);
+int interface_register_timer(interface_t* interface, unsigned delay_ms,
+ interface_fd_callback_t callback, void* data);
/**
* \brief Unregisters a timer event
@@ -144,6 +147,6 @@ int interface_register_timer(interface_t * interface, unsigned delay_ms,
* \param [in] fd - Timer identifier
* \return 0 in case of success, -1 otherwise
*/
-int interface_unregister_timer(interface_t * interface, int fd);
+int interface_unregister_timer(interface_t* interface, int fd);
#endif /* FACEMGR_INTERFACE_H */
diff --git a/ctrl/facemgr/src/interfaces/CMakeLists.txt b/ctrl/facemgr/src/interfaces/CMakeLists.txt
index e4d4423e9..02fb0eb48 100644
--- a/ctrl/facemgr/src/interfaces/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -16,28 +16,33 @@ list(APPEND SOURCE_FILES)
list(APPEND INCLUDE_DIRS)
list(APPEND LIBRARIES)
+
+##############################################################
+# Add components
+##############################################################
add_subdirectory(hicn_light)
if(APPLE)
-add_subdirectory(network_framework)
+ add_subdirectory(network_framework)
endif()
if(LINUX)
-add_subdirectory(netlink)
-add_subdirectory(bonjour)
-endif()
-
-if(ANDROID)
-add_subdirectory(android_utility)
-add_subdirectory(priority_controller)
+ if(ANDROID)
+ add_subdirectory(android)
+ add_subdirectory(priority_controller)
+ else()
+ add_subdirectory(netlink)
+ endif()
+
+ add_subdirectory(bonjour)
endif()
if(WITH_EXAMPLE_DUMMY)
-add_subdirectory(dummy)
+ add_subdirectory(dummy)
endif()
if(WITH_EXAMPLE_UPDOWN)
-add_subdirectory(updown)
+ add_subdirectory(updown)
endif()
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt b/ctrl/facemgr/src/interfaces/android/CMakeLists.txt
index 0ebe87745..beabc1280 100644
--- a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/android/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -11,16 +11,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/android_utility.c
+list(APPEND HEADER_FILES
)
-list(APPEND INCLUDE_DIRS
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/android.c
)
list(APPEND LIBRARIES
)
+list(APPEND INCLUDE_DIRS
+)
+
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/android/android.c b/ctrl/facemgr/src/interfaces/android/android.c
new file mode 100644
index 000000000..4e084d76d
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/android/android.c
@@ -0,0 +1,294 @@
+/*
+ * 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 interfaces/android/android.c
+ * \brief Netlink interface
+ */
+
+#include <assert.h>
+#include <pthread.h>
+#include <sys/eventfd.h>
+#include <unistd.h> // close
+
+#include <hicn/facemgr.h>
+#include <hicn/util/ip_address.h>
+#include <hicn/util/log.h>
+
+#include "../../common.h"
+#include "../../interface.h"
+#include "../../facelet_array.h"
+
+#include "android.h"
+
+/*
+ * aar_modules/FaceMgrLibrary/facemgrLibrary/src/main/java/com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility.java
+ */
+#define FACEMGR_ANDROID_CLASS \
+ "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
+
+/* Internal data storage */
+typedef struct {
+ int fd;
+ android_cfg_t cfg;
+ JNIEnv *env;
+ jclass cls;
+ bool attached_to_vm;
+ facelet_array_t *facelets;
+ pthread_mutex_t mutex;
+} android_data_t;
+
+// might replace android utility
+
+jclass find_class_global(JNIEnv *env, const char *name) {
+ jclass c = (*env)->FindClass(env, name);
+ jclass c_global = 0;
+ if (c) {
+ c_global = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return c_global;
+}
+
+int android_on_network_event(interface_t *interface, const char *interface_name,
+ netdevice_type_t netdevice_type, bool up,
+ int family, const char *ip_address) {
+ android_data_t *data = (android_data_t *)interface->data;
+
+ netdevice_t *netdevice = netdevice_create_from_name(interface_name);
+ if (!netdevice) {
+ ERROR("[android_on_network_event] error creating netdevice '%s'",
+ interface_name);
+ goto ERR_ND;
+ }
+
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ if (ip_address) {
+ if (ip_address_pton(ip_address, &local_addr) < 0) {
+ ERROR("[android_on_network_event] error processing IP address");
+ goto ERR_IP_ADDRESS;
+ }
+ }
+
+ facelet_t *facelet = facelet_create();
+ if (!facelet) {
+ ERROR("[android_on_network_event] error creating facelet");
+ goto ERR_FACELET;
+ }
+
+ if (facelet_set_netdevice(facelet, *netdevice) < 0) {
+ ERROR("[android_on_network_event] error setting netdevice");
+ goto ERR;
+ }
+
+ if (netdevice_type != NETDEVICE_TYPE_UNDEFINED) {
+ if (facelet_set_netdevice_type(facelet, netdevice_type) < 0) {
+ ERROR("[android_on_network_event] error setting netdevice type");
+ goto ERR;
+ }
+ }
+
+ if (facelet_set_family(facelet, family) < 0) {
+ ERROR("[android_on_network_event] error setting family");
+ goto ERR;
+ }
+
+ if (ip_address) {
+ if (facelet_set_local_addr(facelet, local_addr) < 0) {
+ ERROR("[android_on_network_event] error setting local address");
+ goto ERR;
+ }
+ }
+ netdevice_free(netdevice);
+
+ facelet_set_event(facelet, up ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE);
+ // FACELET_EVENT_UPDATE, FACELET_EVENT_SET_DOWN
+ facelet_set_attr_clean(facelet);
+
+ pthread_mutex_lock(&data->mutex);
+ if (facelet_array_add(data->facelets, facelet)) {
+ ERROR("[android_on_network_event] Could not add facelet to buffer");
+ goto ERR_ADD;
+ }
+
+ pthread_mutex_unlock(&data->mutex);
+
+ eventfd_write(data->fd, 1);
+ return 0;
+
+ERR_ADD:
+ pthread_mutex_unlock(&data->mutex);
+ERR:
+ facelet_free(facelet);
+ERR_FACELET:
+ERR_IP_ADDRESS:
+ netdevice_free(netdevice);
+ERR_ND:
+ return -1;
+}
+
+bool get_jni_env(JavaVM *jvm, JNIEnv **env) {
+ bool did_attach_thread = false;
+ INFO("initialize: get_jni_env");
+ *env = NULL;
+ // Check if the current thread is attached to the VM
+ int get_env_result = (*jvm)->GetEnv(jvm, (void **)env, JNI_VERSION_1_6);
+ if (get_env_result == JNI_EDETACHED) {
+ INFO("initialize: detached!");
+ if ((*jvm)->AttachCurrentThread(jvm, env, NULL) == JNI_OK) {
+ INFO("initialize: attached...");
+ did_attach_thread = true;
+ } else {
+ INFO("initialize: failed to attach");
+ // Failed to attach thread. Throw an exception if you want to.
+ }
+ } else if (get_env_result == JNI_EVERSION) {
+ // Unsupported JNI version. Throw an exception if you want to.
+ INFO("initialize: unsupported");
+ }
+ return did_attach_thread;
+}
+
+int android_initialize(interface_t *interface, void *cfg) {
+ android_data_t *data = malloc(sizeof(android_data_t));
+ if (!data) goto ERR_MALLOC;
+ interface->data = data;
+
+ if (!cfg) goto ERR_CFG;
+ data->cfg = *(android_cfg_t *)cfg;
+
+ JavaVM *jvm = data->cfg.jvm;
+ if (!jvm) goto ERR_JVM;
+
+ data->facelets = facelet_array_create();
+ if (!data->facelets) goto ERR_FACELETS;
+
+ if ((data->fd = eventfd(0, EFD_SEMAPHORE)) == -1) goto ERR_EVENTFD;
+
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[android_initialize] Error registering fd");
+ goto ERR_REGISTER_FD;
+ }
+
+ pthread_mutex_init(&data->mutex, NULL);
+
+ data->attached_to_vm = get_jni_env(jvm, &data->env);
+
+ if (!data->env) goto ERR_ENV;
+
+ data->cls = find_class_global(data->env, FACEMGR_ANDROID_CLASS);
+ if (data->cls == 0) goto ERR_CLS;
+
+ jmethodID mid_initialize =
+ (*data->env)
+ ->GetStaticMethodID(data->env, data->cls, "initialize", "()I");
+ if (!mid_initialize) goto ERR_MID;
+
+ (*data->env)
+ ->CallStaticIntMethod(data->env, data->cls, mid_initialize,
+ &android_on_network_event, interface);
+
+ return 0;
+
+ERR_MID:
+ (*data->env)->DeleteGlobalRef(data->env, data->cls);
+ERR_CLS:
+ if (data->attached_to_vm) {
+ (*jvm)->DetachCurrentThread(jvm);
+ data->attached_to_vm = false;
+ }
+ data->env = NULL;
+ERR_ENV:
+ interface_unregister_fd(interface, data->fd);
+ERR_REGISTER_FD:
+ close(data->fd);
+ERR_EVENTFD:
+ facelet_array_free(data->facelets);
+ERR_FACELETS:
+ERR_JVM:
+ERR_CFG:
+ free(data);
+ERR_MALLOC:
+ return -1;
+}
+
+int android_finalize(interface_t *interface) {
+ android_data_t *data = (android_data_t *)interface->data;
+
+ jmethodID mid_terminate =
+ (*data->env)->GetStaticMethodID(data->env, data->cls, "terminate", "()I");
+ if (mid_terminate) {
+ (*data->env)
+ ->CallStaticIntMethod(data->env, data->cls, mid_terminate,
+ &android_on_network_event, interface);
+ }
+
+ (*data->env)->DeleteGlobalRef(data->env, data->cls);
+
+ JavaVM *jvm = data->cfg.jvm;
+ if (data->attached_to_vm) {
+ (*jvm)->DetachCurrentThread(jvm);
+ data->attached_to_vm = false;
+ }
+ data->env = NULL;
+
+ pthread_mutex_destroy(&data->mutex);
+
+ // interface_unregister_fd(interface, data->fd); // XXX done in
+ // facemgr_delete_interface...
+ close(data->fd);
+ facelet_array_free(data->facelets);
+
+ free(data);
+
+ return 0;
+}
+
+int android_callback(interface_t *interface, int fd, void *unused) {
+ android_data_t *data = (android_data_t *)interface->data;
+
+ uint64_t ret;
+ if (read(data->fd, &ret, sizeof(ret)) < 0) return -1;
+ if (ret == 0) // EOF
+ return 0;
+
+ pthread_mutex_lock(&data->mutex);
+ for (unsigned i = 0; i < facelet_array_len(data->facelets); i++) {
+ facelet_t *facelet;
+ if (facelet_array_get_index(data->facelets, i, &facelet) < 0) {
+ ERROR("[android_callback] Error getting facelet in array");
+ continue;
+ }
+
+ interface_raise_event(interface, facelet);
+ }
+
+ for (unsigned i = 0; i < facelet_array_len(data->facelets); i++) {
+ if (facelet_array_remove_index(data->facelets, i, NULL) < 0) {
+ ERROR("[android_callback] Could not purge facelet from array");
+ }
+ }
+ pthread_mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
+const interface_ops_t android_ops = {
+ .type = "android",
+ .initialize = android_initialize,
+ .callback = android_callback,
+ .finalize = android_finalize,
+ .on_event = NULL,
+};
diff --git a/hicn-light/src/hicn/config/controlUpdateConnection.h b/ctrl/facemgr/src/interfaces/android/android.h
index eea303202..319bfe10a 100644
--- a/hicn-light/src/hicn/config/controlUpdateConnection.h
+++ b/ctrl/facemgr/src/interfaces/android/android.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,22 +14,26 @@
*/
/**
- * @file control_UpdateConnection.h
- * @brief Update a connection to an interface
- *
- * <#Detailed Description#>
- *
+ * \file android/android.h
+ * \brief Android utility.
*/
-#ifndef Control_UpdateConnection_h
-#define Control_UpdateConnection_h
+#ifndef FACEMGR_INTERFACE_ANDROID_H
+#define FACEMGR_INTERFACE_ANDROID_H
+
+#ifdef __ANDROID__
+
+#include <jni.h>
+#include "../../interface.h"
-#ifdef WITH_POLICY
+typedef struct {
+ JavaVM *jvm;
+} android_cfg_t;
-#include <hicn/config/controlState.h>
-CommandOps *controlUpdateConnection_Create(ControlState *state);
-CommandOps *controlUpdateConnection_HelpCreate(ControlState *state);
+int android_on_network_event(interface_t *interface, const char *interface_name,
+ netdevice_type_t netdevice_type, bool up,
+ int family, const char *ip_address);
-#endif /* WITH_POLICY */
+#endif /* __ANDROID__ */
-#endif // Control_UpdateConnection_h
+#endif /* FACEMGR_INTERFACE_ANDROID_H */
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
deleted file mode 100644
index d8e20659a..000000000
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * \file interfaces/android_utility/android_utility.c
- * \brief Implementation of Android utility.
- */
-
-#include <assert.h>
-
-#include <hicn/facemgr.h>
-#include <hicn/ctrl/face.h>
-#include <hicn/util/log.h>
-#include "../../common.h"
-#include "../../interface.h"
-
-#include "android_utility.h"
-
-#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
-
-
-#define AU_INTERFACE_TYPE_UNDEFINED 0
-#define AU_INTERFACE_TYPE_WIRED 1
-#define AU_INTERFACE_TYPE_WIFI 2
-#define AU_INTERFACE_TYPE_CELLULAR 3
-#define AU_INTERFACE_TYPE_LOOPBACK 4
-#define AU_INTERFACE_TYPE_UNAVAILABLE 5
-
-#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
-
-typedef struct {
- android_utility_cfg_t cfg;
-} au_data_t;
-
-int au_initialize(interface_t * interface, void * cfg)
-{
- au_data_t * data = malloc(sizeof(au_data_t));
- if (!data)
- return -1;
- interface->data = data;
-
- if (!cfg)
- goto ERR_CFG;
-
- data->cfg = * (android_utility_cfg_t *) cfg;
-
- if (!data->cfg.jvm)
- goto ERR_CFG;
-
- return 0;
-
-ERR_CFG:
- fprintf(stderr, ERR_STR_JAVA);
- return -1;
-}
-
-int au_finalize(interface_t * interface)
-{
- /* Nothing to do */
- return 0;
-}
-
-int au_on_event(interface_t * interface, facelet_t * facelet)
-{
- /*
- * This function is responsible to annotate every face we receive with the
- * correct interface type, based on the value returned by the Android
- * utility shipped with the Android forwarder.
- */
- au_data_t * data = (au_data_t*)interface->data;
-
- netdevice_t netdevice = NETDEVICE_EMPTY;
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0)
- return -1;
-
- JNIEnv *env;
- JavaVM *jvm = data->cfg.jvm;
- (*jvm)->AttachCurrentThread(jvm, &env, NULL);
- jclass cls = (*env)->FindClass(env, FACEMGR_UTILITY_CLASS);
- jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls,
- "getNetworkType", "(Ljava/lang/String;)I");
- jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType,
- (*env)->NewStringUTF(env, netdevice.name));
-
- netdevice_type_t netdevice_type = AU_INTERFACE_TYPE_UNDEFINED;
- switch(interface_type) {
- case AU_INTERFACE_TYPE_UNDEFINED:
- break;
- case AU_INTERFACE_TYPE_WIRED:
- netdevice_type = NETDEVICE_TYPE_WIRED;
- break;
- case AU_INTERFACE_TYPE_WIFI:
- netdevice_type = NETDEVICE_TYPE_WIFI;
- break;
- case AU_INTERFACE_TYPE_CELLULAR:
- netdevice_type = NETDEVICE_TYPE_CELLULAR;
- break;
- case AU_INTERFACE_TYPE_LOOPBACK:
- netdevice_type = NETDEVICE_TYPE_LOOPBACK;
- break;
- default:
- DEBUG("AU RETURNED ERROR");
- return -1;
- }
-
- DEBUG("AU RETURNED %s : %s", netdevice.name, netdevice_type_str[netdevice_type]);
-
- facelet_t * facelet_new = facelet_create();
- facelet_set_netdevice(facelet_new, netdevice);
- facelet_set_attr_clean(facelet_new);
- facelet_set_netdevice_type(facelet_new, netdevice_type);
-
- facelet_set_event(facelet_new, FACELET_EVENT_UPDATE);
- interface_raise_event(interface, facelet_new);
-
- return 0;
-}
-
-const interface_ops_t android_utility_ops = {
- .type = "android_utility",
- .initialize = au_initialize,
- .finalize = au_finalize,
- .callback = NULL,
- .on_event = au_on_event,
-};
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.h b/ctrl/facemgr/src/interfaces/android_utility/android_utility.h
deleted file mode 100644
index 53adfedf6..000000000
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * \file android_utility/android_utility.h
- * \brief Android utility.
- *
- * This class relies on a small utility wrapper shipped with the Android
- * application to access to Java SDK APIs for information not available to
- * native code.
- *
- * For instance, we currently don't have on Linux any mean to get the type
- * associated to an interface, especially for cellular interfaces. WiFi and
- * Bluetooth information is for instance available through specific netlink
- * subsystems, or by means of a support library, but cellular detection mostly
- * relies on heuristics based on interface names (eg. in network manager).
- *
- * Android ship a Radio Interface Layer (RIL) daemon that exposes a control
- * socket to the Java API to control the radio layer, but there is no working
- * code exploiting it and no proper documentation.
- */
-
-#ifndef FACEMGR_INTERFACE_ANDROID_UTILITY_H
-#define FACEMGR_INTERFACE_ANDROID_UTILITY_H
-
-#ifdef __ANDROID__
-
-#include <jni.h>
-
-typedef struct {
- JavaVM *jvm;
-} android_utility_cfg_t;
-
-#endif /* __ANDROID__ */
-
-#endif /* FACEMGR_INTERFACE_ANDROID_UTILITY_H */
diff --git a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt
index 8a0ddc888..90ca0e47f 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
index 40b7f5f90..90f18c299 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,6 +25,7 @@
#include <hicn/facemgr.h>
#include <hicn/util/log.h>
#include <hicn/util/map.h>
+#include <hicn/util/sstrncpy.h>
#include "../../common.h"
#include "../../interface.h"
@@ -40,368 +41,357 @@
#define DEFAULT_SERVICE_DOMAIN "local"
typedef struct {
- bonjour_cfg_t cfg;
- int sock;
- size_t buffer_size;
- void* buffer;
+ bonjour_cfg_t cfg;
+ int sock;
+ size_t buffer_size;
+ void* buffer;
- /* The face being resolved, non-NULL values indicate interface is busy... */
- face_t * face;
+ /* The face being resolved, non-NULL values indicate interface is busy... */
+ face_t* face;
} bj_data_t;
-int bj_initialize(interface_t * interface, void * cfg)
-{
- bj_data_t * data = malloc(sizeof(bj_data_t));
- if (!data)
- goto ERR_MALLOC;
- interface->data = data;
+int bj_initialize(interface_t* interface, void* cfg) {
+ bj_data_t* data = malloc(sizeof(bj_data_t));
+ if (!data) goto ERR_MALLOC;
+ interface->data = data;
- if (cfg) {
+ if (cfg) {
#ifndef __linux__
- if (cfg->netdevice)
- WARN("Binding to interface is (currently) only supported on Linux");
+ if (cfg->netdevice)
+ WARN("Binding to interface is (currently) only supported on Linux");
#endif /* ! __linux__ */
- data->cfg = * (bonjour_cfg_t *) cfg;
- } else {
- memset(&data->cfg, 0, sizeof(bonjour_cfg_t));
- }
+ data->cfg = *(bonjour_cfg_t*)cfg;
+ } else {
+ memset(&data->cfg, 0, sizeof(bonjour_cfg_t));
+ }
- if (!data->cfg.service_name)
- data->cfg.service_name = DEFAULT_SERVICE_NAME;
+ if (!data->cfg.service_name) data->cfg.service_name = DEFAULT_SERVICE_NAME;
- if (!data->cfg.service_protocol)
- data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL;
+ if (!data->cfg.service_protocol)
+ data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL;
- if (!data->cfg.service_domain)
- data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN;
+ if (!data->cfg.service_domain)
+ data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN;
- data->sock = mdns_socket_open_ipv4();
- if (data->sock < 0) {
- printf("Failed to open socket: %s\n", strerror(errno));
- goto ERR_SOCK;
- }
+ data->sock = mdns_socket_open_ipv4();
+ if (data->sock < 0) {
+ printf("Failed to open socket: %s\n", strerror(errno));
+ goto ERR_SOCK;
+ }
- /* Netdevice configuration */
+ /* Netdevice configuration */
#ifdef __linux__
#ifndef __ANDROID__
- if (IS_VALID_NETDEVICE(data->cfg.netdevice)) {
- int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE,
- &data->cfg.netdevice.name, strlen(data->cfg.netdevice.name) + 1);
- if (rc == -1) {
- ERROR("setsockopt");
- goto ERR_SOCK_OPT;
- }
+ if (IS_VALID_NETDEVICE(data->cfg.netdevice)) {
+ int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE,
+ &data->cfg.netdevice.name,
+ strnlen_s(data->cfg.netdevice.name, IFNAMSIZ));
+ if (rc == -1) {
+ ERROR("setsockopt");
+ goto ERR_SOCK_OPT;
}
+ }
#endif
#endif /* __linux__ */
- data->buffer_size = DEFAULT_BUFFER_SIZE;
- data->buffer = malloc(data->buffer_size);
- if (!data->buffer)
- goto ERR_BUFFER;
+ data->buffer_size = DEFAULT_BUFFER_SIZE;
+ data->buffer = malloc(data->buffer_size);
+ if (!data->buffer) goto ERR_BUFFER;
#ifdef _WIN32
- WORD versionWanted = MAKEWORD(1, 1);
- WSADATA wsaData;
- WSAStartup(versionWanted, &wsaData);
+ WORD versionWanted = MAKEWORD(1, 1);
+ WSADATA wsaData;
+ WSAStartup(versionWanted, &wsaData);
#endif
- if (interface_register_fd(interface, data->sock, NULL) < 0) {
- ERROR("[bj_initialize] Error registering fd");
- goto ERR_FD;
- }
+ if (interface_register_fd(interface, data->sock, NULL) < 0) {
+ ERROR("[bj_initialize] Error registering fd");
+ goto ERR_FD;
+ }
- return 0;
+ return 0;
ERR_FD:
- free(data->buffer);
+ free(data->buffer);
ERR_BUFFER:
#ifndef __ANDROID__
ERR_SOCK_OPT:
#endif
- mdns_socket_close(data->sock);
+ mdns_socket_close(data->sock);
#ifdef _WIN32
- WSACleanup();
+ WSACleanup();
#endif
ERR_SOCK:
- free(data);
+ free(data);
ERR_MALLOC:
- return -1;
+ return -1;
}
/*
* We reuse the callback to be triggered upon external events
* TODO: move to a cleaner interface architecture later...
*/
-int bj_on_event(interface_t * interface, facelet_t * facelet)
-{
- bj_data_t * data = (bj_data_t*)interface->data;
-
- /*
- printf("Sending DNS-SD discovery\n");
- if (mdns_discovery_send(sock)) {
- printf("Failed to send DNS-DS discovery: %s\n", strerror(errno));
- goto quit;
- }
-
- printf("Reading DNS-SD replies\n");
- for (int i = 0; i < 10; ++i) {
- records = mdns_discovery_recv(sock, buffer, capacity, callback,
- user_data);
- sleep(1);
- }
- */
-
- DEBUG("Sending mDNS query");
- char service_string[SERVICE_STRING_SIZE];
-
- int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.",
- data->cfg.service_name, data->cfg.service_protocol,
- data->cfg.service_domain);
- if (rc < 0)
- ; // error
- else if (rc >= SERVICE_STRING_SIZE)
- ; //truncated
-
- if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR,
- service_string,
- strlen(service_string),
- data->buffer, data->buffer_size)) {
- printf("Failed to send mDNS query: %s\n", strerror(errno));
- return -1;
- }
- return 0;
+int bj_on_event(interface_t* interface, facelet_t* facelet) {
+ bj_data_t* data = (bj_data_t*)interface->data;
+
+ /*
+ printf("Sending DNS-SD discovery\n");
+ if (mdns_discovery_send(sock)) {
+ printf("Failed to send DNS-DS discovery: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ printf("Reading DNS-SD replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_discovery_recv(sock, buffer, capacity, callback,
+ user_data);
+ sleep(1);
+ }
+ */
+
+ DEBUG("Sending mDNS query");
+ char service_string[SERVICE_STRING_SIZE];
+
+ int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.",
+ data->cfg.service_name, data->cfg.service_protocol,
+ data->cfg.service_domain);
+ if (rc < 0)
+ ; // error
+ else if (rc >= SERVICE_STRING_SIZE)
+ ; // truncated
+
+ if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, service_string,
+ strnlen_s(service_string, SERVICE_STRING_SIZE),
+ data->buffer, data->buffer_size)) {
+ printf("Failed to send mDNS query: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
}
static char addrbuffer[64];
static char namebuffer[256];
static mdns_record_txt_t txtbuffer[128];
-static mdns_string_t
-ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) {
- char host[NI_MAXHOST] = {0};
- char service[NI_MAXSERV] = {0};
- int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in),
- host, NI_MAXHOST, service, NI_MAXSERV,
- NI_NUMERICSERV | NI_NUMERICHOST);
- int len = 0;
- if (ret == 0) {
- if (addr->sin_port != 0)
- len = snprintf(buffer, capacity, "%s:%s", host, service);
- else
- len = snprintf(buffer, capacity, "%s", host);
- }
- if (len >= (int)capacity)
- len = (int)capacity - 1;
- mdns_string_t str = {buffer, len};
- return str;
+static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity,
+ const struct sockaddr_in* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr,
+ sizeof(struct sockaddr_in), host, NI_MAXHOST, service,
+ NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin_port != 0)
+ len = snprintf(buffer, capacity, "%s:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity) len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
}
-static mdns_string_t
-ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) {
- char host[NI_MAXHOST] = {0};
- char service[NI_MAXSERV] = {0};
- int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6),
- host, NI_MAXHOST, service, NI_MAXSERV,
- NI_NUMERICSERV | NI_NUMERICHOST);
- int len = 0;
- if (ret == 0) {
- if (addr->sin6_port != 0)
- len = snprintf(buffer, capacity, "[%s]:%s", host, service);
- else
- len = snprintf(buffer, capacity, "%s", host);
- }
- if (len >= (int)capacity)
- len = (int)capacity - 1;
- mdns_string_t str = {buffer, len};
- return str;
+static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity,
+ const struct sockaddr_in6* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr,
+ sizeof(struct sockaddr_in6), host, NI_MAXHOST, service,
+ NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin6_port != 0)
+ len = snprintf(buffer, capacity, "[%s]:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity) len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
}
-static mdns_string_t
-ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) {
- if (addr->sa_family == AF_INET6)
- return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr);
- return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr);
+static mdns_string_t ip_address_to_string(char* buffer, size_t capacity,
+ const struct sockaddr* addr) {
+ if (addr->sa_family == AF_INET6)
+ return ipv6_address_to_string(buffer, capacity,
+ (const struct sockaddr_in6*)addr);
+ return ipv4_address_to_string(buffer, capacity,
+ (const struct sockaddr_in*)addr);
}
-int
-ip_address_set_sockaddr(ip_address_t * ip_address, struct sockaddr * sa)
-{
- switch(sa->sa_family) {
- case AF_INET:
- ip_address->v4.as_inaddr = ((struct sockaddr_in *)sa)->sin_addr;
- break;
- case AF_INET6:
- ip_address->v6.as_in6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
- break;
- default:
- return -1;
- }
-
- return 0;
+int ip_address_set_sockaddr(ip_address_t* ip_address, struct sockaddr* sa) {
+ switch (sa->sa_family) {
+ case AF_INET:
+ ip_address->v4.as_inaddr = ((struct sockaddr_in*)sa)->sin_addr;
+ break;
+ case AF_INET6:
+ ip_address->v6.as_in6addr = ((struct sockaddr_in6*)sa)->sin6_addr;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
}
-static int
-callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
- uint16_t rclass, uint32_t ttl, const void* data, size_t size, size_t
- offset, size_t length, void* user_data)
-{
- interface_t * interface = (interface_t*)user_data;
- bj_data_t * bj_data = (bj_data_t *)interface->data;
-
- struct sockaddr_storage addr;
-
- mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
- const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" :
- ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
-
- switch(type) {
- case MDNS_RECORDTYPE_A:
- {
- ip_address_t ip_address;
- mdns_record_parse_a(data, size, offset, length, (struct sockaddr_in*)&addr);
- ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr);
-
- mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), (struct sockaddr_in *)&addr);
- DEBUG("%.*s : %s A %.*s",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(addrstr));
-
- facelet_t * facelet = facelet_create();
- facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
- facelet_set_family(facelet, AF_INET);
- facelet_set_remote_addr(facelet, ip_address);
- //facelet_set_remote_port(facelet, ((struct sockaddr_in*)&addr)->sin_port);
-
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- interface_raise_event(interface, facelet);
- break;
- }
+static int callback(const struct sockaddr* from, mdns_entry_type_t entry,
+ uint16_t type, uint16_t rclass, uint32_t ttl,
+ const void* data, size_t size, size_t offset, size_t length,
+ void* user_data) {
+ interface_t* interface = (interface_t*)user_data;
+ bj_data_t* bj_data = (bj_data_t*)interface->data;
+
+ struct sockaddr_storage addr;
+
+ mdns_string_t fromaddrstr =
+ ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
+ const char* entrytype =
+ (entry == MDNS_ENTRYTYPE_ANSWER)
+ ? "answer"
+ : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
+
+ switch (type) {
+ case MDNS_RECORDTYPE_A: {
+ ip_address_t ip_address;
+ mdns_record_parse_a(data, size, offset, length,
+ (struct sockaddr_in*)&addr);
+ ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr);
+
+ mdns_string_t addrstr = ipv4_address_to_string(
+ namebuffer, sizeof(namebuffer), (struct sockaddr_in*)&addr);
+ DEBUG("%.*s : %s A %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+
+ facelet_t* facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET);
+ facelet_set_remote_addr(facelet, ip_address);
+ // facelet_set_remote_port(facelet, ((struct
+ // sockaddr_in*)&addr)->sin_port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ interface_raise_event(interface, facelet);
+ break;
+ }
- case MDNS_RECORDTYPE_AAAA:
- {
- ip_address_t ip_address;
- mdns_record_parse_aaaa(data, size, offset, length, (struct sockaddr_in6*)&addr);
- ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr);
-
- mdns_string_t addrstr = ipv6_address_to_string(namebuffer,
- sizeof(namebuffer), (struct sockaddr_in6*)&addr);
- DEBUG("%.*s : %s AAAA %.*s",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(addrstr));
-
- facelet_t * facelet = facelet_create();
- facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
- facelet_set_family(facelet, AF_INET6);
- facelet_set_remote_addr(facelet, ip_address);
- //facelet_set_remote_port(facelet, ((struct sockaddr_in6*)&addr)->sin6_port);
-
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- interface_raise_event(interface, facelet);
- break;
- }
+ case MDNS_RECORDTYPE_AAAA: {
+ ip_address_t ip_address;
+ mdns_record_parse_aaaa(data, size, offset, length,
+ (struct sockaddr_in6*)&addr);
+ ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr);
+
+ mdns_string_t addrstr = ipv6_address_to_string(
+ namebuffer, sizeof(namebuffer), (struct sockaddr_in6*)&addr);
+ DEBUG("%.*s : %s AAAA %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+
+ facelet_t* facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET6);
+ facelet_set_remote_addr(facelet, ip_address);
+ // facelet_set_remote_port(facelet, ((struct
+ // sockaddr_in6*)&addr)->sin6_port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ interface_raise_event(interface, facelet);
+ break;
+ }
- case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */
- {
- mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length,
- namebuffer, sizeof(namebuffer));
-
- DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
-
- /* We raise both v4 and v6
- *
- * Unless we choose whether we query A and/or AAAA, this might leave
- * us with an unused pending facelet, eg. we might not have an IPv6
- * but we raise an IPv6 bonjour event...
- */
-
- facelet_t * facelet = facelet_create();
- facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
- facelet_set_family(facelet, AF_INET);
- facelet_set_remote_port(facelet, srv.port);
-
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- interface_raise_event(interface, facelet);
-
- facelet = facelet_create();
- facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
- facelet_set_family(facelet, AF_INET6);
- facelet_set_remote_port(facelet, srv.port);
-
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- interface_raise_event(interface, facelet);
- break;
- }
+ case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */
+ {
+ mdns_record_srv_t srv = mdns_record_parse_srv(
+ data, size, offset, length, namebuffer, sizeof(namebuffer));
+
+ DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
+
+ /* We raise both v4 and v6
+ *
+ * Unless we choose whether we query A and/or AAAA, this might leave
+ * us with an unused pending facelet, eg. we might not have an IPv6
+ * but we raise an IPv6 bonjour event...
+ */
+
+ facelet_t* facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET);
+ facelet_set_remote_port(facelet, srv.port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ interface_raise_event(interface, facelet);
+
+ facelet = facelet_create();
+ facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
+ facelet_set_family(facelet, AF_INET6);
+ facelet_set_remote_port(facelet, srv.port);
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ interface_raise_event(interface, facelet);
+ break;
+ }
- case MDNS_RECORDTYPE_PTR:
- {
- mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length,
- namebuffer, sizeof(namebuffer));
- DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
- break;
- }
+ case MDNS_RECORDTYPE_PTR: {
+ mdns_string_t namestr = mdns_record_parse_ptr(
+ data, size, offset, length, namebuffer, sizeof(namebuffer));
+ DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
+ break;
+ }
- case MDNS_RECORDTYPE_TXT:
- {
- size_t parsed = mdns_record_parse_txt(data, size, offset, length,
- txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
- for (size_t itxt = 0; itxt < parsed; ++itxt) {
- if (txtbuffer[itxt].value.length) {
- DEBUG("%.*s : %s TXT %.*s = %.*s",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(txtbuffer[itxt].key),
- MDNS_STRING_FORMAT(txtbuffer[itxt].value));
- }
- else {
- DEBUG("%.*s : %s TXT %.*s",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(txtbuffer[itxt].key));
- }
- }
- break;
+ case MDNS_RECORDTYPE_TXT: {
+ size_t parsed =
+ mdns_record_parse_txt(data, size, offset, length, txtbuffer,
+ sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
+ for (size_t itxt = 0; itxt < parsed; ++itxt) {
+ if (txtbuffer[itxt].value.length) {
+ DEBUG("%.*s : %s TXT %.*s = %.*s", MDNS_STRING_FORMAT(fromaddrstr),
+ entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key),
+ MDNS_STRING_FORMAT(txtbuffer[itxt].value));
+ } else {
+ DEBUG("%.*s : %s TXT %.*s", MDNS_STRING_FORMAT(fromaddrstr),
+ entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key));
}
-
- default:
- /* Silently ignore the received record */
- DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- type, rclass, ttl, (int)length);
- return 0;
+ }
+ break;
}
- return 0;
+ default:
+ /* Silently ignore the received record */
+ DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl,
+ (int)length);
+ return 0;
+ }
+ return 0;
}
/*
* The fact we use a single fd does not allow us to get user_data associated to
* the query.
*/
-int bj_callback(interface_t * interface, int fd, void * unused)
-{
- bj_data_t * data = (bj_data_t*)interface->data;
- DEBUG("Got an mDNS reply");
- /* size_t records = */ mdns_query_recv(data->sock, data->buffer, data->buffer_size, callback, interface, 1);
+int bj_callback(interface_t* interface, int fd, void* unused) {
+ bj_data_t* data = (bj_data_t*)interface->data;
+ DEBUG("Got an mDNS reply");
+ /* size_t records = */ mdns_query_recv(
+ data->sock, data->buffer, data->buffer_size, callback, interface, 1);
- return 0;
+ return 0;
}
-int bj_finalize(interface_t * interface)
-{
- bj_data_t * data = (bj_data_t*)interface->data;
+int bj_finalize(interface_t* interface) {
+ bj_data_t* data = (bj_data_t*)interface->data;
- free(data->buffer);
- mdns_socket_close(data->sock);
+ free(data->buffer);
+ mdns_socket_close(data->sock);
#ifdef _WIN32
- WSACleanup();
+ WSACleanup();
#endif
- return 0;
-
+ return 0;
}
const interface_ops_t bonjour_ops = {
@@ -410,5 +400,5 @@ const interface_ops_t bonjour_ops = {
.on_event = bj_on_event,
.callback = bj_callback,
.finalize = bj_finalize,
- // .on_event = NULL,
+ // .on_event = NULL,
};
diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
index fe053079d..6458423ea 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,11 +25,11 @@
* queries...
*/
-#include <hicn/ctrl/face.h> /* netdevice_t */
+#include <hicn/face.h> /* netdevice_t */
typedef struct {
- netdevice_t netdevice;
- char * service_name;
- char * service_protocol;
- char * service_domain;
+ netdevice_t netdevice;
+ char* service_name;
+ char* service_protocol;
+ char* service_domain;
} bonjour_cfg_t;
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
index a8e97e8e0..e2bb4f432 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c
@@ -1,6 +1,6 @@
#ifdef _WIN32
-# define _CRT_SECURE_NO_WARNINGS 1
+#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include "mdns.h"
@@ -9,184 +9,176 @@
#include <errno.h>
#ifdef _WIN32
-# define sleep(x) Sleep(x * 1000)
+#define sleep(x) Sleep(x * 1000)
#else
-# include <netdb.h>
+#include <netdb.h>
#endif
static char addrbuffer[64];
static char namebuffer[256];
static mdns_record_txt_t txtbuffer[128];
-static mdns_string_t
-ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) {
- char host[NI_MAXHOST] = {0};
- char service[NI_MAXSERV] = {0};
- int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in),
- host, NI_MAXHOST, service, NI_MAXSERV,
- NI_NUMERICSERV | NI_NUMERICHOST);
- int len = 0;
- if (ret == 0) {
- if (addr->sin_port != 0)
- len = snprintf(buffer, capacity, "%s:%s", host, service);
- else
- len = snprintf(buffer, capacity, "%s", host);
- }
- if (len >= (int)capacity)
- len = (int)capacity - 1;
- mdns_string_t str = {buffer, len};
- return str;
+static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity,
+ const struct sockaddr_in* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr,
+ sizeof(struct sockaddr_in), host, NI_MAXHOST, service,
+ NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin_port != 0)
+ len = snprintf(buffer, capacity, "%s:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity) len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
}
-static mdns_string_t
-ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) {
- char host[NI_MAXHOST] = {0};
- char service[NI_MAXSERV] = {0};
- int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6),
- host, NI_MAXHOST, service, NI_MAXSERV,
- NI_NUMERICSERV | NI_NUMERICHOST);
- int len = 0;
- if (ret == 0) {
- if (addr->sin6_port != 0)
- len = snprintf(buffer, capacity, "[%s]:%s", host, service);
- else
- len = snprintf(buffer, capacity, "%s", host);
- }
- if (len >= (int)capacity)
- len = (int)capacity - 1;
- mdns_string_t str = {buffer, len};
- return str;
+static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity,
+ const struct sockaddr_in6* addr) {
+ char host[NI_MAXHOST] = {0};
+ char service[NI_MAXSERV] = {0};
+ int ret = getnameinfo((const struct sockaddr*)addr,
+ sizeof(struct sockaddr_in6), host, NI_MAXHOST, service,
+ NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST);
+ int len = 0;
+ if (ret == 0) {
+ if (addr->sin6_port != 0)
+ len = snprintf(buffer, capacity, "[%s]:%s", host, service);
+ else
+ len = snprintf(buffer, capacity, "%s", host);
+ }
+ if (len >= (int)capacity) len = (int)capacity - 1;
+ mdns_string_t str = {buffer, len};
+ return str;
}
-static mdns_string_t
-ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) {
- if (addr->sa_family == AF_INET6)
- return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr);
- return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr);
+static mdns_string_t ip_address_to_string(char* buffer, size_t capacity,
+ const struct sockaddr* addr) {
+ if (addr->sa_family == AF_INET6)
+ return ipv6_address_to_string(buffer, capacity,
+ (const struct sockaddr_in6*)addr);
+ return ipv4_address_to_string(buffer, capacity,
+ (const struct sockaddr_in*)addr);
}
-static int
-callback(const struct sockaddr* from,
- mdns_entry_type_t entry, uint16_t type,
- uint16_t rclass, uint32_t ttl,
- const void* data, size_t size, size_t offset, size_t length,
- void* user_data) {
- mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
- const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" :
- ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
- if (type == MDNS_RECORDTYPE_PTR) {
- mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length,
- namebuffer, sizeof(namebuffer));
- INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
- }
- else if (type == MDNS_RECORDTYPE_SRV) {
- mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length,
- namebuffer, sizeof(namebuffer));
- INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
- }
- else if (type == MDNS_RECORDTYPE_A) {
- struct sockaddr_in addr;
- mdns_record_parse_a(data, size, offset, length, &addr);
- mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr);
- INFO("%.*s : %s A %.*s\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(addrstr));
- }
- else if (type == MDNS_RECORDTYPE_AAAA) {
- struct sockaddr_in6 addr;
- mdns_record_parse_aaaa(data, size, offset, length, &addr);
- mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr);
- INFO("%.*s : %s AAAA %.*s\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(addrstr));
- }
- else if (type == MDNS_RECORDTYPE_TXT) {
- size_t parsed = mdns_record_parse_txt(data, size, offset, length,
- txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
- for (size_t itxt = 0; itxt < parsed; ++itxt) {
- if (txtbuffer[itxt].value.length) {
- INFO("%.*s : %s TXT %.*s = %.*s\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(txtbuffer[itxt].key),
- MDNS_STRING_FORMAT(txtbuffer[itxt].value));
- }
- else {
- INFO("%.*s : %s TXT %.*s\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- MDNS_STRING_FORMAT(txtbuffer[itxt].key));
- }
- }
- }
- else {
- INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n",
- MDNS_STRING_FORMAT(fromaddrstr), entrytype,
- type, rclass, ttl, (int)length);
- }
- return 0;
+static int callback(const struct sockaddr* from, mdns_entry_type_t entry,
+ uint16_t type, uint16_t rclass, uint32_t ttl,
+ const void* data, size_t size, size_t offset, size_t length,
+ void* user_data) {
+ mdns_string_t fromaddrstr =
+ ip_address_to_string(addrbuffer, sizeof(addrbuffer), from);
+ const char* entrytype =
+ (entry == MDNS_ENTRYTYPE_ANSWER)
+ ? "answer"
+ : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional");
+ if (type == MDNS_RECORDTYPE_PTR) {
+ mdns_string_t namestr = mdns_record_parse_ptr(
+ data, size, offset, length, namebuffer, sizeof(namebuffer));
+ INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length);
+ } else if (type == MDNS_RECORDTYPE_SRV) {
+ mdns_record_srv_t srv = mdns_record_parse_srv(
+ data, size, offset, length, namebuffer, sizeof(namebuffer));
+ INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);
+ } else if (type == MDNS_RECORDTYPE_A) {
+ struct sockaddr_in addr;
+ mdns_record_parse_a(data, size, offset, length, &addr);
+ mdns_string_t addrstr =
+ ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr);
+ INFO("%.*s : %s A %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+ } else if (type == MDNS_RECORDTYPE_AAAA) {
+ struct sockaddr_in6 addr;
+ mdns_record_parse_aaaa(data, size, offset, length, &addr);
+ mdns_string_t addrstr =
+ ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr);
+ INFO("%.*s : %s AAAA %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(addrstr));
+ } else if (type == MDNS_RECORDTYPE_TXT) {
+ size_t parsed =
+ mdns_record_parse_txt(data, size, offset, length, txtbuffer,
+ sizeof(txtbuffer) / sizeof(mdns_record_txt_t));
+ for (size_t itxt = 0; itxt < parsed; ++itxt) {
+ if (txtbuffer[itxt].value.length) {
+ INFO("%.*s : %s TXT %.*s = %.*s\n", MDNS_STRING_FORMAT(fromaddrstr),
+ entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key),
+ MDNS_STRING_FORMAT(txtbuffer[itxt].value));
+ } else {
+ INFO("%.*s : %s TXT %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype,
+ MDNS_STRING_FORMAT(txtbuffer[itxt].key));
+ }
+ }
+ } else {
+ INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n",
+ MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl,
+ (int)length);
+ }
+ return 0;
}
-int
-main() {
- size_t capacity = 2048;
- void* buffer = 0;
- void* user_data = 0;
- size_t records;
+int main() {
+ size_t capacity = 2048;
+ void* buffer = 0;
+ void* user_data = 0;
+ size_t records;
#ifdef _WIN32
- WORD versionWanted = MAKEWORD(1, 1);
- WSADATA wsaData;
- WSAStartup(versionWanted, &wsaData);
+ WORD versionWanted = MAKEWORD(1, 1);
+ WSADATA wsaData;
+ WSAStartup(versionWanted, &wsaData);
#endif
- int sock = mdns_socket_open_ipv4();
- if (sock < 0) {
- INFO("Failed to open socket: %s\n", strerror(errno));
- return -1;
- }
- INFO("Opened IPv4 socket for mDNS/DNS-SD\n");
- buffer = malloc(capacity);
-/*
- INFO("Sending DNS-SD discovery\n");
- if (mdns_discovery_send(sock)) {
- INFO("Failed to send DNS-DS discovery: %s\n", strerror(errno));
- goto quit;
- }
-
- INFO("Reading DNS-SD replies\n");
- for (int i = 0; i < 10; ++i) {
- records = mdns_discovery_recv(sock, buffer, capacity, callback,
- user_data);
- sleep(1);
- }
- */
-
- INFO("Sending mDNS query\n");
- if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR,
- MDNS_STRING_CONST("_hicn._udp.local."),
- buffer, capacity)) {
- INFO("Failed to send mDNS query: %s\n", strerror(errno));
- goto quit;
- }
-
- INFO("Reading mDNS replies\n");
- for (int i = 0; i < 10; ++i) {
- records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1);
- sleep(1);
- }
+ int sock = mdns_socket_open_ipv4();
+ if (sock < 0) {
+ INFO("Failed to open socket: %s\n", strerror(errno));
+ return -1;
+ }
+ INFO("Opened IPv4 socket for mDNS/DNS-SD\n");
+ buffer = malloc(capacity);
+ /*
+ INFO("Sending DNS-SD discovery\n");
+ if (mdns_discovery_send(sock)) {
+ INFO("Failed to send DNS-DS discovery: %s\n",
+ strerror(errno)); goto quit;
+ }
+
+ INFO("Reading DNS-SD replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_discovery_recv(sock, buffer, capacity,
+ callback, user_data); sleep(1);
+ }
+ */
+
+ INFO("Sending mDNS query\n");
+ if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR,
+ MDNS_STRING_CONST("_hicn._udp.local."), buffer,
+ capacity)) {
+ INFO("Failed to send mDNS query: %s\n", strerror(errno));
+ goto quit;
+ }
+
+ INFO("Reading mDNS replies\n");
+ for (int i = 0; i < 10; ++i) {
+ records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1);
+ sleep(1);
+ }
quit:
- free(buffer);
+ free(buffer);
- mdns_socket_close(sock);
- INFO("Closed socket\n");
+ mdns_socket_close(sock);
+ INFO("Closed socket\n");
#ifdef _WIN32
- WSACleanup();
+ WSACleanup();
#endif
- return 0;
+ return 0;
}
diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h
index ff04b5d72..4b8e7a7f4 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h
+++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h
@@ -7,7 +7,8 @@
*
* https://github.com/mjansson/mdns
*
- * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
+ * This library is put in the public domain; you can redistribute it and/or
+ * modify it without any restrictions.
*
*/
@@ -31,76 +32,73 @@
#define MDNS_INVALID_POS ((size_t)-1)
-#define MDNS_STRING_CONST(s) (s), (sizeof((s))-1)
+#define MDNS_STRING_CONST(s) (s), (sizeof((s)) - 1)
#define MDNS_STRING_FORMAT(s) (int)((s).length), s.str
enum mdns_record_type {
- MDNS_RECORDTYPE_IGNORE = 0,
- //Address
- MDNS_RECORDTYPE_A = 1,
- //Domain Name pointer
- MDNS_RECORDTYPE_PTR = 12,
- //Arbitrary text string
- MDNS_RECORDTYPE_TXT = 16,
- //IP6 Address [Thomson]
- MDNS_RECORDTYPE_AAAA = 28,
- //Server Selection [RFC2782]
- MDNS_RECORDTYPE_SRV = 33
+ MDNS_RECORDTYPE_IGNORE = 0,
+ // Address
+ MDNS_RECORDTYPE_A = 1,
+ // Domain Name pointer
+ MDNS_RECORDTYPE_PTR = 12,
+ // Arbitrary text string
+ MDNS_RECORDTYPE_TXT = 16,
+ // IP6 Address [Thomson]
+ MDNS_RECORDTYPE_AAAA = 28,
+ // Server Selection [RFC2782]
+ MDNS_RECORDTYPE_SRV = 33
};
enum mdns_entry_type {
- MDNS_ENTRYTYPE_ANSWER = 1,
- MDNS_ENTRYTYPE_AUTHORITY = 2,
- MDNS_ENTRYTYPE_ADDITIONAL = 3
+ MDNS_ENTRYTYPE_ANSWER = 1,
+ MDNS_ENTRYTYPE_AUTHORITY = 2,
+ MDNS_ENTRYTYPE_ADDITIONAL = 3
};
-enum mdns_class {
- MDNS_CLASS_IN = 1
-};
+enum mdns_class { MDNS_CLASS_IN = 1 };
-typedef enum mdns_record_type mdns_record_type_t;
-typedef enum mdns_entry_type mdns_entry_type_t;
-typedef enum mdns_class mdns_class_t;
+typedef enum mdns_record_type mdns_record_type_t;
+typedef enum mdns_entry_type mdns_entry_type_t;
+typedef enum mdns_class mdns_class_t;
-typedef int (* mdns_record_callback_fn)(const struct sockaddr* from,
- mdns_entry_type_t entry, uint16_t type,
- uint16_t rclass, uint32_t ttl,
- const void* data, size_t size, size_t offset, size_t length,
- void* user_data);
+typedef int (*mdns_record_callback_fn)(const struct sockaddr* from,
+ mdns_entry_type_t entry, uint16_t type,
+ uint16_t rclass, uint32_t ttl,
+ const void* data, size_t size,
+ size_t offset, size_t length,
+ void* user_data);
-typedef struct mdns_string_t mdns_string_t;
-typedef struct mdns_string_pair_t mdns_string_pair_t;
-typedef struct mdns_record_srv_t mdns_record_srv_t;
-typedef struct mdns_record_txt_t mdns_record_txt_t;
+typedef struct mdns_string_t mdns_string_t;
+typedef struct mdns_string_pair_t mdns_string_pair_t;
+typedef struct mdns_record_srv_t mdns_record_srv_t;
+typedef struct mdns_record_txt_t mdns_record_txt_t;
struct mdns_string_t {
- const char* str;
- size_t length;
+ const char* str;
+ size_t length;
};
struct mdns_string_pair_t {
- size_t offset;
- size_t length;
- int ref;
+ size_t offset;
+ size_t length;
+ int ref;
};
struct mdns_record_srv_t {
- uint16_t priority;
- uint16_t weight;
- uint16_t port;
- mdns_string_t name;
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ mdns_string_t name;
};
struct mdns_record_txt_t {
- mdns_string_t key;
- mdns_string_t value;
+ mdns_string_t key;
+ mdns_string_t value;
};
-static int
-mdns_socket_open_ipv4(void);
+static int mdns_socket_open_ipv4(void);
-static int
-mdns_socket_setup_ipv4(int sock);
+static int mdns_socket_setup_ipv4(int sock);
#if 0
static int
@@ -112,8 +110,7 @@ static int
mdns_socket_setup_ipv6(int sock);
#endif
-static void
-mdns_socket_close(int sock);
+static void mdns_socket_close(int sock);
#if 0
static int
@@ -125,21 +122,18 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity,
mdns_record_callback_fn callback, void* user_data);
#endif
-static int
-mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length,
- void* buffer, size_t capacity);
+static int mdns_query_send(int sock, mdns_record_type_t type, const char* name,
+ size_t length, void* buffer, size_t capacity);
-static size_t
-mdns_query_recv(int sock, void* buffer, size_t capacity,
- mdns_record_callback_fn callback, void* user_data,
- uint8_t one_shot);
+static size_t mdns_query_recv(int sock, void* buffer, size_t capacity,
+ mdns_record_callback_fn callback, void* user_data,
+ uint8_t one_shot);
-static mdns_string_t
-mdns_string_extract(const void* buffer, size_t size, size_t* offset,
- char* str, size_t capacity);
+static mdns_string_t mdns_string_extract(const void* buffer, size_t size,
+ size_t* offset, char* str,
+ size_t capacity);
-static int
-mdns_string_skip(const void* buffer, size_t size, size_t* offset);
+static int mdns_string_skip(const void* buffer, size_t size, size_t* offset);
#if 0
static int
@@ -147,78 +141,80 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs,
const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs);
#endif
-static void*
-mdns_string_make(void* data, size_t capacity, const char* name, size_t length);
+static void* mdns_string_make(void* data, size_t capacity, const char* name,
+ size_t length);
-static mdns_string_t
-mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length,
- char* strbuffer, size_t capacity);
+static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ char* strbuffer, size_t capacity);
-static mdns_record_srv_t
-mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length,
- char* strbuffer, size_t capacity);
+static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ char* strbuffer,
+ size_t capacity);
-static struct sockaddr_in*
-mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length,
- struct sockaddr_in* addr);
+static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ struct sockaddr_in* addr);
-static struct sockaddr_in6*
-mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length,
- struct sockaddr_in6* addr);
+static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer,
+ size_t size, size_t offset,
+ size_t length,
+ struct sockaddr_in6* addr);
-static size_t
-mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length,
- mdns_record_txt_t* records, size_t capacity);
+static size_t mdns_record_parse_txt(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ mdns_record_txt_t* records,
+ size_t capacity);
// Implementations
-static int
-mdns_socket_open_ipv4(void) {
- int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (sock < 0)
- return -1;
- if (mdns_socket_setup_ipv4(sock)) {
- mdns_socket_close(sock);
- return -1;
- }
- return sock;
+static int mdns_socket_open_ipv4(void) {
+ int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0) return -1;
+ if (mdns_socket_setup_ipv4(sock)) {
+ mdns_socket_close(sock);
+ return -1;
+ }
+ return sock;
}
-static int
-mdns_socket_setup_ipv4(int sock) {
- struct sockaddr_in saddr;
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = INADDR_ANY;
+static int mdns_socket_setup_ipv4(int sock) {
+ struct sockaddr_in saddr;
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = INADDR_ANY;
#ifdef __APPLE__
- saddr.sin_len = sizeof(saddr);
+ saddr.sin_len = sizeof(saddr);
#endif
- if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr)))
- return -1;
+ if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) return -1;
#ifdef _WIN32
- unsigned long param = 1;
- ioctlsocket(sock, FIONBIO, &param);
+ unsigned long param = 1;
+ ioctlsocket(sock, FIONBIO, &param);
#else
- const int flags = fcntl(sock, F_GETFL, 0);
- fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+ const int flags = fcntl(sock, F_GETFL, 0);
+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
#endif
- unsigned char ttl = 1;
- unsigned char loopback = 1;
- struct ip_mreq req;
+ unsigned char ttl = 1;
+ unsigned char loopback = 1;
+ struct ip_mreq req;
- setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl));
- setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback));
+ setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl,
+ sizeof(ttl));
+ setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback,
+ sizeof(loopback));
- memset(&req, 0, sizeof(req));
- req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
- req.imr_interface.s_addr = INADDR_ANY;
- if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req)))
- return -1;
+ memset(&req, 0, sizeof(req));
+ req.imr_multiaddr.s_addr =
+ htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
+ req.imr_interface.s_addr = INADDR_ANY;
+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req)))
+ return -1;
- return 0;
+ return 0;
}
#if 0
@@ -274,67 +270,58 @@ mdns_socket_setup_ipv6(int sock) {
}
#endif
-static void
-mdns_socket_close(int sock) {
+static void mdns_socket_close(int sock) {
#ifdef _WIN32
- closesocket(sock);
+ closesocket(sock);
#else
- close(sock);
+ close(sock);
#endif
}
-static int
-mdns_is_string_ref(uint8_t val) {
- return (0xC0 == (val & 0xC0));
-}
+static int mdns_is_string_ref(uint8_t val) { return (0xC0 == (val & 0xC0)); }
-static mdns_string_pair_t
-mdns_get_next_substring(const void* rawdata, size_t size, size_t offset) {
- const uint8_t* buffer = rawdata;
- mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0};
- if (!buffer[offset]) {
- pair.offset = offset;
- return pair;
- }
- if (mdns_is_string_ref(buffer[offset])) {
- if (size < offset + 2)
- return pair;
+static mdns_string_pair_t mdns_get_next_substring(const void* rawdata,
+ size_t size, size_t offset) {
+ const uint8_t* buffer = rawdata;
+ mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0};
+ if (!buffer[offset]) {
+ pair.offset = offset;
+ return pair;
+ }
+ if (mdns_is_string_ref(buffer[offset])) {
+ if (size < offset + 2) return pair;
- offset = (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]);
- if (offset >= size)
- return pair;
+ offset =
+ (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]);
+ if (offset >= size) return pair;
- pair.ref = 1;
- }
+ pair.ref = 1;
+ }
- size_t length = (size_t)buffer[offset++];
- if (size < offset + length)
- return pair;
+ size_t length = (size_t)buffer[offset++];
+ if (size < offset + length) return pair;
- pair.offset = offset;
- pair.length = length;
+ pair.offset = offset;
+ pair.length = length;
- return pair;
+ return pair;
}
-static int
-mdns_string_skip(const void* buffer, size_t size, size_t* offset) {
- size_t cur = *offset;
- mdns_string_pair_t substr;
- do {
- substr = mdns_get_next_substring(buffer, size, cur);
- if (substr.offset == MDNS_INVALID_POS)
- return 0;
- if (substr.ref) {
- *offset = cur + 2;
- return 1;
- }
- cur = substr.offset + substr.length;
- }
- while (substr.length);
-
- *offset = cur + 1;
- return 1;
+static int mdns_string_skip(const void* buffer, size_t size, size_t* offset) {
+ size_t cur = *offset;
+ mdns_string_pair_t substr;
+ do {
+ substr = mdns_get_next_substring(buffer, size, cur);
+ if (substr.offset == MDNS_INVALID_POS) return 0;
+ if (substr.ref) {
+ *offset = cur + 2;
+ return 1;
+ }
+ cur = substr.offset + substr.length;
+ } while (substr.length);
+
+ *offset = cur + 1;
+ return 1;
}
#if 0
@@ -378,142 +365,133 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs,
}
#endif
-static mdns_string_t
-mdns_string_extract(const void* buffer, size_t size, size_t* offset,
- char* str, size_t capacity) {
- size_t cur = *offset;
- size_t end = MDNS_INVALID_POS;
- mdns_string_pair_t substr;
- mdns_string_t result = {str, 0};
- char* dst = str;
- size_t remain = capacity;
- do {
- substr = mdns_get_next_substring(buffer, size, cur);
- if (substr.offset == MDNS_INVALID_POS)
- return result;
- if (substr.ref && (end == MDNS_INVALID_POS))
- end = cur + 2;
- if (substr.length) {
- size_t to_copy = (substr.length < remain) ? substr.length : remain;
- memcpy(dst, (const char*)buffer + substr.offset, to_copy);
- dst += to_copy;
- remain -= to_copy;
- if (remain) {
- *dst++ = '.';
- --remain;
- }
- }
- cur = substr.offset + substr.length;
- }
- while (substr.length);
-
- if (end == MDNS_INVALID_POS)
- end = cur + 1;
- *offset = end;
-
- result.length = capacity - remain;
- return result;
+static mdns_string_t mdns_string_extract(const void* buffer, size_t size,
+ size_t* offset, char* str,
+ size_t capacity) {
+ size_t cur = *offset;
+ size_t end = MDNS_INVALID_POS;
+ mdns_string_pair_t substr;
+ mdns_string_t result = {str, 0};
+ char* dst = str;
+ size_t remain = capacity;
+ do {
+ substr = mdns_get_next_substring(buffer, size, cur);
+ if (substr.offset == MDNS_INVALID_POS) return result;
+ if (substr.ref && (end == MDNS_INVALID_POS)) end = cur + 2;
+ if (substr.length) {
+ size_t to_copy = (substr.length < remain) ? substr.length : remain;
+ memcpy(dst, (const char*)buffer + substr.offset, to_copy);
+ dst += to_copy;
+ remain -= to_copy;
+ if (remain) {
+ *dst++ = '.';
+ --remain;
+ }
+ }
+ cur = substr.offset + substr.length;
+ } while (substr.length);
+
+ if (end == MDNS_INVALID_POS) end = cur + 1;
+ *offset = end;
+
+ result.length = capacity - remain;
+ return result;
}
-static size_t
-mdns_string_find(const char* str, size_t length, char c, size_t offset) {
- const void* found;
- if (offset >= length)
- return MDNS_INVALID_POS;
- found = memchr(str + offset, c, length - offset);
- if (found)
- return (size_t)((const char*)found - str);
- return MDNS_INVALID_POS;
+static size_t mdns_string_find(const char* str, size_t length, char c,
+ size_t offset) {
+ const void* found;
+ if (offset >= length) return MDNS_INVALID_POS;
+ found = memchr(str + offset, c, length - offset);
+ if (found) return (size_t)((const char*)found - str);
+ return MDNS_INVALID_POS;
}
-static void*
-mdns_string_make(void* data, size_t capacity, const char* name, size_t length) {
- size_t pos = 0;
- size_t last_pos = 0;
- size_t remain = capacity;
- unsigned char* dest = data;
- while ((last_pos < length) && ((pos = mdns_string_find(name, length, '.', last_pos)) != MDNS_INVALID_POS)) {
- size_t sublength = pos - last_pos;
- if (sublength < remain) {
- *dest = (unsigned char)sublength;
- memcpy(dest + 1, name + last_pos, sublength);
- dest += sublength + 1;
- remain -= sublength + 1;
- }
- else {
- return 0;
- }
- last_pos = pos + 1;
- }
- if (last_pos < length) {
- size_t sublength = length - last_pos;
- if (sublength < capacity) {
- *dest = (unsigned char)sublength;
- memcpy(dest + 1, name + last_pos, sublength);
- dest += sublength + 1;
- remain -= sublength + 1;
- }
- else {
- return 0;
- }
- }
- if (!remain)
- return 0;
- *dest++ = 0;
- return dest;
+static void* mdns_string_make(void* data, size_t capacity, const char* name,
+ size_t length) {
+ size_t pos = 0;
+ size_t last_pos = 0;
+ size_t remain = capacity;
+ unsigned char* dest = data;
+ while ((last_pos < length) &&
+ ((pos = mdns_string_find(name, length, '.', last_pos)) !=
+ MDNS_INVALID_POS)) {
+ size_t sublength = pos - last_pos;
+ if (sublength < remain) {
+ *dest = (unsigned char)sublength;
+ memcpy(dest + 1, name + last_pos, sublength);
+ dest += sublength + 1;
+ remain -= sublength + 1;
+ } else {
+ return 0;
+ }
+ last_pos = pos + 1;
+ }
+ if (last_pos < length) {
+ size_t sublength = length - last_pos;
+ if (sublength < capacity) {
+ *dest = (unsigned char)sublength;
+ memcpy(dest + 1, name + last_pos, sublength);
+ dest += sublength + 1;
+ remain -= sublength + 1;
+ } else {
+ return 0;
+ }
+ }
+ if (!remain) return 0;
+ *dest++ = 0;
+ return dest;
}
-static size_t
-mdns_records_parse(const struct sockaddr* from, const void* buffer, size_t size, size_t* offset,
- mdns_entry_type_t type, size_t records, mdns_record_callback_fn callback,
- void* user_data) {
- size_t parsed = 0;
- int do_callback = 1;
- for (size_t i = 0; i < records; ++i) {
- mdns_string_skip(buffer, size, offset);
- const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset));
-
- uint16_t rtype = ntohs(*data++);
- uint16_t rclass = ntohs(*data++);
- uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); data += 2;
- uint16_t length = ntohs(*data++);
-
- *offset += 10;
-
- if (do_callback) {
- ++parsed;
- if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, length,
- user_data))
- do_callback = 0;
- }
-
- *offset += length;
- }
- return parsed;
+static size_t mdns_records_parse(const struct sockaddr* from,
+ const void* buffer, size_t size,
+ size_t* offset, mdns_entry_type_t type,
+ size_t records,
+ mdns_record_callback_fn callback,
+ void* user_data) {
+ size_t parsed = 0;
+ int do_callback = 1;
+ for (size_t i = 0; i < records; ++i) {
+ mdns_string_skip(buffer, size, offset);
+ const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset));
+
+ uint16_t rtype = ntohs(*data++);
+ uint16_t rclass = ntohs(*data++);
+ uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data);
+ data += 2;
+ uint16_t length = ntohs(*data++);
+
+ *offset += 10;
+
+ if (do_callback) {
+ ++parsed;
+ if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset,
+ length, user_data))
+ do_callback = 0;
+ }
+
+ *offset += length;
+ }
+ return parsed;
}
static const uint8_t mdns_services_query[] = {
- // Transaction ID
- 0x00, 0x00,
- // Flags
- 0x00, 0x00,
- // 1 question
- 0x00, 0x01,
- // No answer, authority or additional RRs
- 0x00, 0x00,
- 0x00, 0x00,
- 0x00, 0x00,
- // _services._dns-sd._udp.local.
- 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's',
- 0x07, '_', 'd', 'n', 's', '-', 's', 'd',
- 0x04, '_', 'u', 'd', 'p',
- 0x05, 'l', 'o', 'c', 'a', 'l',
- 0x00,
- // PTR record
- 0x00, MDNS_RECORDTYPE_PTR,
- // QU (unicast response) and class IN
- 0x80, MDNS_CLASS_IN
-};
+ // Transaction ID
+ 0x00, 0x00,
+ // Flags
+ 0x00, 0x00,
+ // 1 question
+ 0x00, 0x01,
+ // No answer, authority or additional RRs
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // _services._dns-sd._udp.local.
+ 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', 0x07, '_', 'd', 'n', 's',
+ '-', 's', 'd', 0x04, '_', 'u', 'd', 'p', 0x05, 'l', 'o', 'c', 'a', 'l',
+ 0x00,
+ // PTR record
+ 0x00, MDNS_RECORDTYPE_PTR,
+ // QU (unicast response) and class IN
+ 0x80, MDNS_CLASS_IN};
#if 0
static int
@@ -645,233 +623,223 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity,
static uint16_t mdns_transaction_id = 0;
-static int
-mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length,
- void* buffer, size_t capacity) {
- if (capacity < (17 + length))
- return -1;
-
- uint16_t* data = buffer;
- //Transaction ID
- *data++ = htons(++mdns_transaction_id);
- //Flags
- *data++ = 0;
- //Questions
- *data++ = htons(1);
- //No answer, authority or additional RRs
- *data++ = 0;
- *data++ = 0;
- *data++ = 0;
- //Name string
- data = mdns_string_make(data, capacity - 17, name, length);
- if (!data)
- return -1;
- //Record type
- *data++ = htons(type);
- //! Unicast response, class IN
- *data++ = htons(0x8000U | MDNS_CLASS_IN);
-
- struct sockaddr_storage addr_storage;
- struct sockaddr_in addr;
- struct sockaddr_in6 addr6;
- struct sockaddr* saddr = (struct sockaddr*)&addr_storage;
- socklen_t saddrlen = sizeof(struct sockaddr_storage);
- if (getsockname(sock, saddr, &saddrlen))
- return -1;
- if (saddr->sa_family == AF_INET6) {
- memset(&addr6, 0, sizeof(struct sockaddr_in6));
- addr6.sin6_family = AF_INET6;
+static int mdns_query_send(int sock, mdns_record_type_t type, const char* name,
+ size_t length, void* buffer, size_t capacity) {
+ if (capacity < (17 + length)) return -1;
+
+ uint16_t* data = buffer;
+ // Transaction ID
+ *data++ = htons(++mdns_transaction_id);
+ // Flags
+ *data++ = 0;
+ // Questions
+ *data++ = htons(1);
+ // No answer, authority or additional RRs
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ // Name string
+ data = mdns_string_make(data, capacity - 17, name, length);
+ if (!data) return -1;
+ // Record type
+ *data++ = htons(type);
+ //! Unicast response, class IN
+ *data++ = htons(0x8000U | MDNS_CLASS_IN);
+
+ struct sockaddr_storage addr_storage;
+ struct sockaddr_in addr;
+ struct sockaddr_in6 addr6;
+ struct sockaddr* saddr = (struct sockaddr*)&addr_storage;
+ socklen_t saddrlen = sizeof(struct sockaddr_storage);
+ if (getsockname(sock, saddr, &saddrlen)) return -1;
+ if (saddr->sa_family == AF_INET6) {
+ memset(&addr6, 0, sizeof(struct sockaddr_in6));
+ addr6.sin6_family = AF_INET6;
#ifdef __APPLE__
- addr6.sin6_len = sizeof(struct sockaddr_in6);
+ addr6.sin6_len = sizeof(struct sockaddr_in6);
#endif
- addr6.sin6_addr.s6_addr[0] = 0xFF;
- addr6.sin6_addr.s6_addr[1] = 0x02;
- addr6.sin6_addr.s6_addr[15] = 0xFB;
- addr6.sin6_port = htons((unsigned short)5353);
- saddr = (struct sockaddr*)&addr6;
- saddrlen = sizeof(struct sockaddr_in6);
- }
- else {
- memset(&addr, 0, sizeof(struct sockaddr_in));
- addr.sin_family = AF_INET;
+ addr6.sin6_addr.s6_addr[0] = 0xFF;
+ addr6.sin6_addr.s6_addr[1] = 0x02;
+ addr6.sin6_addr.s6_addr[15] = 0xFB;
+ addr6.sin6_port = htons((unsigned short)5353);
+ saddr = (struct sockaddr*)&addr6;
+ saddrlen = sizeof(struct sockaddr_in6);
+ } else {
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
#ifdef __APPLE__
- addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_len = sizeof(struct sockaddr_in);
#endif
- addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
- addr.sin_port = htons((unsigned short)5353);
- saddr = (struct sockaddr*)&addr;
- saddrlen = sizeof(struct sockaddr_in);
- }
-
- if (sendto(sock, buffer, (char*)data - (char*)buffer, 0,
- saddr, saddrlen) < 0)
- return -1;
- return 0;
+ addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
+ addr.sin_port = htons((unsigned short)5353);
+ saddr = (struct sockaddr*)&addr;
+ saddrlen = sizeof(struct sockaddr_in);
+ }
+
+ if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, saddr, saddrlen) < 0)
+ return -1;
+ return 0;
}
-static size_t
-mdns_query_recv(int sock, void* buffer, size_t capacity,
- mdns_record_callback_fn callback, void* user_data,
- uint8_t one_shot) {
- struct sockaddr_in6 addr;
- struct sockaddr* saddr = (struct sockaddr*)&addr;
- memset(&addr, 0, sizeof(addr));
- saddr->sa_family = AF_INET;
+static size_t mdns_query_recv(int sock, void* buffer, size_t capacity,
+ mdns_record_callback_fn callback, void* user_data,
+ uint8_t one_shot) {
+ struct sockaddr_in6 addr;
+ struct sockaddr* saddr = (struct sockaddr*)&addr;
+ memset(&addr, 0, sizeof(addr));
+ saddr->sa_family = AF_INET;
#ifdef __APPLE__
- saddr->sa_len = sizeof(addr);
+ saddr->sa_len = sizeof(addr);
#endif
- socklen_t addrlen = sizeof(addr);
- int ret = recvfrom(sock, buffer, capacity, 0,
- saddr, &addrlen);
- if (ret <= 0)
- return 0;
-
- size_t data_size = (size_t)ret;
- uint16_t* data = (uint16_t*)buffer;
-
- uint16_t transaction_id = ntohs(*data++);
- ++data;// uint16_t flags = ntohs(*data++);
- uint16_t questions = ntohs(*data++);
- uint16_t answer_rrs = ntohs(*data++);
- uint16_t authority_rrs = ntohs(*data++);
- uint16_t additional_rrs = ntohs(*data++);
-
- if (one_shot && transaction_id != mdns_transaction_id)// || (flags != 0x8400))
- return 0; //Not a reply to our last question
-
- if (questions > 1)
- return 0;
-
- //Skip questions part
- int i;
- for (i = 0; i < questions; ++i) {
- size_t ofs = (size_t)((char*)data - (char*)buffer);
- if (!mdns_string_skip(buffer, data_size, &ofs))
- return 0;
- data = (void*)((char*)buffer + ofs);
- ++data;
- ++data;
- }
-
- size_t records = 0;
- size_t offset = (size_t)((char*)data - (char*)buffer);
- records += mdns_records_parse(saddr, buffer, data_size, &offset,
- MDNS_ENTRYTYPE_ANSWER, answer_rrs,
- callback, user_data);
- records += mdns_records_parse(saddr, buffer, data_size, &offset,
- MDNS_ENTRYTYPE_AUTHORITY, authority_rrs,
- callback, user_data);
- records += mdns_records_parse(saddr, buffer, data_size, &offset,
- MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs,
- callback, user_data);
- return records;
+ socklen_t addrlen = sizeof(addr);
+ int ret = recvfrom(sock, buffer, capacity, 0, saddr, &addrlen);
+ if (ret <= 0) return 0;
+
+ size_t data_size = (size_t)ret;
+ uint16_t* data = (uint16_t*)buffer;
+
+ uint16_t transaction_id = ntohs(*data++);
+ ++data; // uint16_t flags = ntohs(*data++);
+ uint16_t questions = ntohs(*data++);
+ uint16_t answer_rrs = ntohs(*data++);
+ uint16_t authority_rrs = ntohs(*data++);
+ uint16_t additional_rrs = ntohs(*data++);
+
+ if (one_shot &&
+ transaction_id != mdns_transaction_id) // || (flags != 0x8400))
+ return 0; // Not a reply to our last question
+
+ if (questions > 1) return 0;
+
+ // Skip questions part
+ int i;
+ for (i = 0; i < questions; ++i) {
+ size_t ofs = (size_t)((char*)data - (char*)buffer);
+ if (!mdns_string_skip(buffer, data_size, &ofs)) return 0;
+ data = (void*)((char*)buffer + ofs);
+ ++data;
+ ++data;
+ }
+
+ size_t records = 0;
+ size_t offset = (size_t)((char*)data - (char*)buffer);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_ANSWER, answer_rrs, callback,
+ user_data);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_AUTHORITY, authority_rrs,
+ callback, user_data);
+ records += mdns_records_parse(saddr, buffer, data_size, &offset,
+ MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs,
+ callback, user_data);
+ return records;
}
-static mdns_string_t
-mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length,
- char* strbuffer, size_t capacity) {
- //PTR record is just a string
- if ((size >= offset + length) && (length >= 2))
- return mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
- mdns_string_t empty = {0, 0};
- return empty;
+static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ char* strbuffer, size_t capacity) {
+ // PTR record is just a string
+ if ((size >= offset + length) && (length >= 2))
+ return mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
+ mdns_string_t empty = {0, 0};
+ return empty;
}
-static mdns_record_srv_t
-mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length,
- char* strbuffer, size_t capacity) {
- mdns_record_srv_t srv;
- memset(&srv, 0, sizeof(mdns_record_srv_t));
- // Read the priority, weight, port number and the discovery name
- // SRV record format (http://www.ietf.org/rfc/rfc2782.txt):
- // 2 bytes network-order unsigned priority
- // 2 bytes network-order unsigned weight
- // 2 bytes network-order unsigned port
- // string: discovery (domain) name, minimum 2 bytes when compressed
- if ((size >= offset + length) && (length >= 8)) {
- const uint16_t* recorddata = (const uint16_t*)((const char*)buffer + offset);
- srv.priority = ntohs(*recorddata++);
- srv.weight = ntohs(*recorddata++);
- srv.port = ntohs(*recorddata++);
- offset += 6;
- srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
- }
- return srv;
+static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ char* strbuffer,
+ size_t capacity) {
+ mdns_record_srv_t srv;
+ memset(&srv, 0, sizeof(mdns_record_srv_t));
+ // Read the priority, weight, port number and the discovery name
+ // SRV record format (http://www.ietf.org/rfc/rfc2782.txt):
+ // 2 bytes network-order unsigned priority
+ // 2 bytes network-order unsigned weight
+ // 2 bytes network-order unsigned port
+ // string: discovery (domain) name, minimum 2 bytes when compressed
+ if ((size >= offset + length) && (length >= 8)) {
+ const uint16_t* recorddata =
+ (const uint16_t*)((const char*)buffer + offset);
+ srv.priority = ntohs(*recorddata++);
+ srv.weight = ntohs(*recorddata++);
+ srv.port = ntohs(*recorddata++);
+ offset += 6;
+ srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity);
+ }
+ return srv;
}
-static struct sockaddr_in*
-mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length,
- struct sockaddr_in* addr) {
- memset(addr, 0, sizeof(struct sockaddr_in));
- addr->sin_family = AF_INET;
+static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ struct sockaddr_in* addr) {
+ memset(addr, 0, sizeof(struct sockaddr_in));
+ addr->sin_family = AF_INET;
#ifdef __APPLE__
- addr->sin_len = sizeof(struct sockaddr_in);
+ addr->sin_len = sizeof(struct sockaddr_in);
#endif
- if ((size >= offset + length) && (length == 4))
- addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset);
- return addr;
+ if ((size >= offset + length) && (length == 4))
+ addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset);
+ return addr;
}
-static struct sockaddr_in6*
-mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length,
- struct sockaddr_in6* addr) {
- memset(addr, 0, sizeof(struct sockaddr_in6));
- addr->sin6_family = AF_INET6;
+static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer,
+ size_t size, size_t offset,
+ size_t length,
+ struct sockaddr_in6* addr) {
+ memset(addr, 0, sizeof(struct sockaddr_in6));
+ addr->sin6_family = AF_INET6;
#ifdef __APPLE__
- addr->sin6_len = sizeof(struct sockaddr_in6);
+ addr->sin6_len = sizeof(struct sockaddr_in6);
#endif
- if ((size >= offset + length) && (length == 16))
- addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset);
- return addr;
+ if ((size >= offset + length) && (length == 16))
+ addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset);
+ return addr;
}
-static size_t
-mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length,
- mdns_record_txt_t* records, size_t capacity) {
- size_t parsed = 0;
- const char* strdata;
- size_t separator, sublength;
- size_t end = offset + length;
-
- if (size < end)
- end = size;
-
- while ((offset < end) && (parsed < capacity)) {
- strdata = (const char*)buffer + offset;
- sublength = *(const unsigned char*)strdata;
-
- ++strdata;
- offset += sublength + 1;
-
- separator = 0;
- for (size_t c = 0; c < sublength; ++c) {
- //DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E]
- if ((strdata[c] < 0x20) || (strdata[c] > 0x7E))
- break;
- if (strdata[c] == '=') {
- separator = c;
- break;
- }
- }
-
- if (!separator)
- continue;
-
- if (separator < sublength) {
- records[parsed].key.str = strdata;
- records[parsed].key.length = separator;
- records[parsed].value.str = strdata + separator + 1;
- records[parsed].value.length = sublength - (separator + 1);
- }
- else {
- records[parsed].key.str = strdata;
- records[parsed].key.length = sublength;
- }
-
- ++parsed;
- }
-
- return parsed;
+static size_t mdns_record_parse_txt(const void* buffer, size_t size,
+ size_t offset, size_t length,
+ mdns_record_txt_t* records,
+ size_t capacity) {
+ size_t parsed = 0;
+ const char* strdata;
+ size_t separator, sublength;
+ size_t end = offset + length;
+
+ if (size < end) end = size;
+
+ while ((offset < end) && (parsed < capacity)) {
+ strdata = (const char*)buffer + offset;
+ sublength = *(const unsigned char*)strdata;
+
+ ++strdata;
+ offset += sublength + 1;
+
+ separator = 0;
+ for (size_t c = 0; c < sublength; ++c) {
+ // DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E]
+ if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) break;
+ if (strdata[c] == '=') {
+ separator = c;
+ break;
+ }
+ }
+
+ if (!separator) continue;
+
+ if (separator < sublength) {
+ records[parsed].key.str = strdata;
+ records[parsed].key.length = separator;
+ records[parsed].value.str = strdata + separator + 1;
+ records[parsed].value.length = sublength - (separator + 1);
+ } else {
+ records[parsed].key.str = strdata;
+ records[parsed].key.length = sublength;
+ }
+
+ ++parsed;
+ }
+
+ return parsed;
}
#ifdef _WIN32
diff --git a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt
index 05276bc5a..c68c39273 100644
--- a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.c b/ctrl/facemgr/src/interfaces/dummy/dummy.c
index 69c336e57..df63eef17 100644
--- a/ctrl/facemgr/src/interfaces/dummy/dummy.c
+++ b/ctrl/facemgr/src/interfaces/dummy/dummy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,7 +19,7 @@
*/
#include <stdlib.h>
-#include <unistd.h> // close
+#include <unistd.h> // close
#include <hicn/facemgr.h>
@@ -36,34 +36,32 @@
* Internal data
*/
typedef struct {
- /* The configuration data will likely be allocated on the stack (or should
- * be freed) by the caller, we recommend to make a copy of this data.
- * This copy can further be altered with default values.
- */
- dummy_cfg_t cfg;
+ /* The configuration data will likely be allocated on the stack (or should
+ * be freed) by the caller, we recommend to make a copy of this data.
+ * This copy can further be altered with default values.
+ */
+ dummy_cfg_t cfg;
- /* ... */
+ /* ... */
- int fd; /* Sample internal data: file descriptor */
+ int fd; /* Sample internal data: file descriptor */
} dummy_data_t;
-int dummy_initialize(interface_t * interface, void * cfg)
-{
- dummy_data_t * data = malloc(sizeof(dummy_data_t));
- if (!data)
- goto ERR_MALLOC;
- interface->data = data;
-
- /* Use default values for unspecified configuration parameters */
- if (cfg) {
- data->cfg = *(dummy_cfg_t *)cfg;
- } else {
- memset(&data->cfg, 0, sizeof(data->cfg));
- }
+int dummy_initialize(interface_t *interface, void *cfg) {
+ dummy_data_t *data = malloc(sizeof(dummy_data_t));
+ if (!data) goto ERR_MALLOC;
+ interface->data = data;
+
+ /* Use default values for unspecified configuration parameters */
+ if (cfg) {
+ data->cfg = *(dummy_cfg_t *)cfg;
+ } else {
+ memset(&data->cfg, 0, sizeof(data->cfg));
+ }
- /* ... */
+ /* ... */
- data->fd = 0;
+ data->fd = 0;
#if 0
if (interface_register_fd(interface, data->fd, NULL) < 0) {
ERROR("[dummy_initialize] Error registering fd");
@@ -71,49 +69,45 @@ int dummy_initialize(interface_t * interface, void * cfg)
}
#endif
- /* ... */
+ /* ... */
- /*
- * We should return a negative value in case of error, and a positive value
- * otherwise:
- * - a file descriptor (>0) will be added to the event loop; or
- * - 0 if we don't use any file descriptor
- */
- return 0;
+ /*
+ * We should return a negative value in case of error, and a positive value
+ * otherwise:
+ * - a file descriptor (>0) will be added to the event loop; or
+ * - 0 if we don't use any file descriptor
+ */
+ return 0;
ERR_FD:
ERR_MALLOC:
- return -1;
+ return -1;
}
-int dummy_finalize(interface_t * interface)
-{
- dummy_data_t * data = (dummy_data_t*)interface->data;
+int dummy_finalize(interface_t *interface) {
+ dummy_data_t *data = (dummy_data_t *)interface->data;
- if (data->fd > 0)
- close(data->fd);
+ if (data->fd > 0) close(data->fd);
- return 0;
+ return 0;
}
-int dummy_callback(interface_t * interface)
-{
- dummy_data_t * data = (dummy_data_t*)interface->data;
- UNUSED(data);
+int dummy_callback(interface_t *interface) {
+ dummy_data_t *data = (dummy_data_t *)interface->data;
+ UNUSED(data);
- /* ... */
+ /* ... */
- return 0;
+ return 0;
}
-int dummy_on_event(interface_t * interface, facelet_t * facelet)
-{
- dummy_data_t * data = (dummy_data_t*)interface->data;
- UNUSED(data);
+int dummy_on_event(interface_t *interface, facelet_t *facelet) {
+ dummy_data_t *data = (dummy_data_t *)interface->data;
+ UNUSED(data);
- /* ... */
+ /* ... */
- return 0;
+ return 0;
}
interface_ops_t dummy_ops = {
diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.h b/ctrl/facemgr/src/interfaces/dummy/dummy.h
index 22fe5d1a6..f930ead58 100644
--- a/ctrl/facemgr/src/interfaces/dummy/dummy.h
+++ b/ctrl/facemgr/src/interfaces/dummy/dummy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -28,7 +28,7 @@
* Configuration data
*/
typedef struct {
- /* ... */
+ /* ... */
} dummy_cfg_t;
#endif /* FACEMGR_INTERFACE_DUMMY_H */
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt b/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt
index ef839a69c..a0fb3e351 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,20 +11,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+
+##############################################################
+# Sources
+##############################################################
list(APPEND HEADER_FILES
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c
)
list(APPEND LIBRARIES
- ${HICNCTRL_LIBRARIES}
+ ${LIBHICNCTRL_LIBRARIES}
)
-
list(APPEND INCLUDE_DIRS
- ${HICNCTRL_INCLUDE_DIR}
+ ${LIBHICNCTRL_INCLUDE_DIR}
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index b6e0e605a..b396782f5 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,8 +19,8 @@
*/
#include <assert.h>
#include <stdbool.h>
-#include <stdio.h> // snprintf
-#include <time.h> // time
+#include <stdio.h> // snprintf
+#include <time.h> // time
#include <hicn/ctrl.h>
#include <hicn/facemgr.h>
@@ -38,578 +38,636 @@
#define WITH_POLL
typedef enum {
- HL_STATE_UNDEFINED,
- HL_STATE_IDLE,
- HL_STATE_ROUTES_SENT,
- HL_STATE_ROUTES_RECEIVED,
- HL_STATE_FACES_SENT,
- HL_STATE_FACES_RECEIVED,
- HL_STATE_N
+ HL_STATE_UNDEFINED,
+ HL_STATE_IDLE,
+ HL_STATE_ROUTES_SENT,
+ HL_STATE_ROUTES_RECEIVED,
+ HL_STATE_FACES_SENT,
+ HL_STATE_FACES_RECEIVED,
+ HL_STATE_N
} hl_state_t;
typedef struct {
- hc_sock_t * s; /* NULL means no active socket */
- hl_state_t state;
+ hc_sock_t *s; /* NULL means no active socket */
- /* Timer used for forwarder reconnection */
- int reconnect_timer_fd; /* 0 means no active timer */
+ /* Socket for polling, dependent on s */
+ hc_sock_t *sp; /* NULL means no active socket */
- /* Timer used to periodically poll the forwarder face and routing tables */
- int poll_timer_fd;
- hc_data_t * polled_routes;
-} hl_data_t;
+ hl_state_t state;
+
+ /* Timer used for forwarder reconnection */
+ int reconnect_timer_fd; /* 0 means no active timer */
-/* Forward declarations */
-int hl_timeout(interface_t * interface, int fd, void * unused);
+ /* Timer used to periodically poll the forwarder face and routing tables */
+ int poll_timer_fd;
+ hc_data_t *polled_routes;
+} hl_data_t;
#ifdef WITH_POLL
-int hl_process_state(interface_t * interface, int fd, void * unused)
+int hl_process_state(interface_t *interface, int fd, void *unused);
#else
-int hl_process_state(interface_t * interface)
+int hl_process_state(interface_t *interface);
#endif
-{
- hl_data_t * data = (hl_data_t *)interface->data;
-
- /*
- * Every tick we need to probe the forwarder for the list of faces and
- * associated routes.
- *
- * This is used to guess manually added faces and routes
- *
- * TODO ensure we are idle at tick time
- */
-
- switch(data->state)
- {
- case HL_STATE_IDLE:
- assert(!data->polled_routes);
-
- //DEBUG("[hl_process_state] Querying route list");
- if (hc_route_list_async(data->s) < 0) {
- DEBUG("[hl_process_state] Error querying route list");
- return -1;
- }
- data->state = HL_STATE_ROUTES_SENT;
- break;
+void start_poll_timer(interface_t *interface) {
+ hl_data_t *data = (hl_data_t *)interface->data;
- case HL_STATE_ROUTES_RECEIVED:
- //DEBUG("[hl_process_state] Querying face list");
- if (hc_face_list_async(data->s) < 0) {
- DEBUG("[hl_process_state] Error querying face list");
- return -1;
- }
- data->state = HL_STATE_FACES_SENT;
- break;
-
- case HL_STATE_FACES_RECEIVED:
- data->state = HL_STATE_IDLE;
- break;
-
- case HL_STATE_ROUTES_SENT:
- case HL_STATE_FACES_SENT:
- INFO("[hl_process_state] Out of sync... resetting state");
- if (data->polled_routes) {
- hc_data_free(data->polled_routes);
- data->polled_routes = NULL;
- }
- data->state = HL_STATE_IDLE;
- break;
+ data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS,
+ hl_process_state, interface);
+ if (data->poll_timer_fd < 0) {
+ ERROR("[start_poll_timer) Could not start polling timer");
+ }
+}
- case HL_STATE_UNDEFINED:
- case HL_STATE_N:
- ERROR("[hl_process_state] Unexpected state");
- return -1;
- }
+void stop_poll_timer(interface_t *interface) {
+ hl_data_t *data = (hl_data_t *)interface->data;
- return 0;
+ if (data->poll_timer_fd > 0)
+ if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) {
+ ERROR("[stop_poll_timer] Could not stop polling timer");
+ }
}
-
-int
-hl_after_connect(interface_t * interface)
+#ifdef WITH_POLL
+int hl_process_state(interface_t *interface, int fd, void *unused)
+#else
+int hl_process_state(interface_t *interface)
+#endif
{
- hl_data_t * data = interface->data;
+ hl_data_t *data = (hl_data_t *)interface->data;
+
+ /*
+ * Every tick we need to probe the forwarder for the list of faces and
+ * associated routes.
+ *
+ * This is used to guess manually added faces and routes
+ *
+ * TODO ensure we are idle at tick time
+ */
+
+ switch (data->state) {
+ case HL_STATE_IDLE:
+ assert(!data->polled_routes);
+ stop_poll_timer(interface);
+
+ // DEBUG("[hl_process_state] Querying route list");
+ if (hc_route_list_async(data->sp) < 0) {
+ DEBUG("[hl_process_state] Error querying route list");
+ return -1;
+ }
+ data->state = HL_STATE_ROUTES_SENT;
+ break;
+
+ case HL_STATE_ROUTES_RECEIVED:
+ // DEBUG("[hl_process_state] Querying face list");
+ if (hc_face_list_async(data->sp) < 0) {
+ DEBUG("[hl_process_state] Error querying face list");
+ return -1;
+ }
+ data->state = HL_STATE_FACES_SENT;
+ break;
+
+ case HL_STATE_FACES_RECEIVED:
+ data->state = HL_STATE_IDLE;
+ start_poll_timer(interface);
+ break;
+
+ case HL_STATE_ROUTES_SENT:
+ case HL_STATE_FACES_SENT:
+ WARN("[hl_process_state] Out of sync... resetting state");
+ if (data->polled_routes) {
+ hc_data_free(data->polled_routes);
+ data->polled_routes = NULL;
+ }
+ data->state = HL_STATE_IDLE;
+ start_poll_timer(interface);
+ break;
+
+ case HL_STATE_UNDEFINED:
+ case HL_STATE_N:
+ ERROR("[hl_process_state] Unexpected state");
+ return -1;
+ }
+
+ return 0;
+}
- /* File descriptor for control socket operations */
- if (interface_register_fd(interface, hc_sock_get_fd(data->s), NULL) < 0) {
- ERROR("[hc_connect] Error registering fd");
- goto ERR_FD;
- }
+/*
+ * Called whenever a connection to both sockets succeeds.
+ * Polling will be useful to detect when connection to the forwarder is lost,
+ * and will allow to try reconnect both sockets (the control socket being UDP /
+ * in blocking mode will not detect such loss of connection). Operations on the
+ * control socket that will fail will be reattempted by higher layers.
+ */
+int hl_after_connect(interface_t *interface) {
+ hl_data_t *data = interface->data;
- /* We always restart from the idle phase */
- data->state = HL_STATE_IDLE;
+ /* File descriptor for polling socket operations */
+ if (interface_register_fd(interface, hc_sock_get_fd(data->sp), NULL) < 0) {
+ ERROR("[hc_connect] Error registering fd");
+ goto ERR_FD;
+ }
+ /* We always restart from the idle phase */
+ data->state = HL_STATE_IDLE;
/* poll will replace the original get, ideally we would get notifications */
#ifdef WITH_POLL
- data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS,
- hl_process_state, interface);
- if (data->poll_timer_fd < 0) {
- ERROR("[hc_connect] Could not initialize polling timer");
- return -1;
- }
+ start_poll_timer(interface);
#else
- hl_process_state(interface);
+ hl_process_state(interface);
#endif
- return 0;
+ return 0;
- //interface_unregister_fd(interface, hc_sock_get_fd(data->s));
+ // interface_unregister_fd(interface, hc_sock_get_fd(data->sp));
ERR_FD:
- return -1;
+ return -1;
}
-int _hl_connect(interface_t * interface);
+int _hl_connect(interface_t *interface);
-int
-hl_connect_timeout(interface_t * interface, int fd, void * unused)
-{
- hl_data_t * data = interface->data;
- assert(fd == data->reconnect_timer_fd);
- _unused(data);
+int hl_connect_timeout(interface_t *interface, int fd, void *unused) {
+ hl_data_t *data = interface->data;
+ assert(fd == data->reconnect_timer_fd);
+ _unused(data);
- int rc = _hl_connect(interface);
- if (rc < 0) {
- DEBUG("[hl_initialize] Error during connection reattempt; next attempt in %ds", INTERVAL_MS / 1000);
- return -1;
- }
+ int rc = _hl_connect(interface);
+ if (rc < 0) {
+ DEBUG(
+ "[hl_initialize] Error during connection reattempt; next attempt in "
+ "%ds",
+ INTERVAL_MS / 1000);
+ return -1;
+ }
- if (interface_unregister_timer(interface, fd) < 0) {
- ERROR("[hl_connect_timeout] Could not cancel timer after successful connect");
- }
+ if (interface_unregister_timer(interface, fd) < 0) {
+ ERROR(
+ "[hl_connect_timeout] Could not cancel timer after successful connect");
+ }
- /* Connect success */
- return hl_after_connect(interface);
+ /* Connect success */
+ return hl_after_connect(interface);
}
-
-int
-_hl_connect(interface_t * interface)
-{
- hl_data_t * data = interface->data;
- assert(!data->s);
-
- data->s = hc_sock_create();
- if (data->s <= 0) {
- ERROR("[hc_connect] Could not create control socket");
- goto ERR_SOCK;
- }
-
- if (hc_sock_connect(data->s) < 0) {
- DEBUG("[hc_connect] Could not connect control socket");
- goto ERR_CONNECT;
- }
-
- return 0;
-
+/*
+ * Connection without reattempt. Both control and polling sockets should be
+ * connected to succeed.
+ */
+int _hl_connect(interface_t *interface) {
+ hl_data_t *data = interface->data;
+ assert(!data->s);
+ assert(!data->sp);
+
+ data->s = hc_sock_create();
+ if (data->s <= 0) {
+ ERROR("[hc_connect] Could not create control socket");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(data->s) < 0) {
+ DEBUG("[hc_connect] Could not connect control socket");
+ goto ERR_CONNECT;
+ }
+
+ data->sp = hc_sock_create();
+ if (data->sp <= 0) {
+ ERROR("[hc_connect] Could not create polling socket");
+ goto ERR_SOCK_POLL;
+ }
+
+ if (hc_sock_connect(data->sp) < 0) {
+ DEBUG("[hc_connect] Could not connect polling socket");
+ goto ERR_CONNECT_POLL;
+ }
+
+ return 0;
+
+ERR_CONNECT_POLL:
+ hc_sock_free(data->sp);
+ data->sp = NULL;
+ERR_SOCK_POLL:
ERR_CONNECT:
- hc_sock_free(data->s);
- data->s = NULL;
+ hc_sock_free(data->s);
+ data->s = NULL;
ERR_SOCK:
- return -1;
-
+ return -1;
}
-int hl_disconnect(interface_t * interface)
-{
- hl_data_t * data = (hl_data_t *) interface->data;
- if (data->reconnect_timer_fd > 0)
- interface_unregister_timer(interface, data->reconnect_timer_fd);
+int hl_disconnect(interface_t *interface) {
+ hl_data_t *data = (hl_data_t *)interface->data;
+ if (data->reconnect_timer_fd > 0)
+ interface_unregister_timer(interface, data->reconnect_timer_fd);
- if (data->poll_timer_fd > 0)
- interface_unregister_timer(interface, data->poll_timer_fd);
+ stop_poll_timer(interface);
- if (data->polled_routes)
- hc_data_free(data->polled_routes);
+ if (data->polled_routes) hc_data_free(data->polled_routes);
- if (data->s) {
- interface_unregister_fd(interface, hc_sock_get_fd(data->s));
- hc_sock_free(data->s);
- }
+ if (data->s) {
+ hc_sock_free(data->s);
+ data->s = NULL;
+ }
- return 0;
+ if (data->sp) {
+ interface_unregister_fd(interface, hc_sock_get_fd(data->sp));
+ hc_sock_free(data->sp);
+ data->sp = NULL;
+ }
+
+ return 0;
}
-int
-hl_connect(interface_t * interface)
-{
- hl_data_t * data = interface->data;
+/* Connection with reattempts */
+int hl_connect(interface_t *interface) {
+ hl_data_t *data = interface->data;
- if (_hl_connect(interface) >= 0)
- return hl_after_connect(interface);
+ if (_hl_connect(interface) >= 0) return hl_after_connect(interface);
- /* Timer for managing the connection to the forwarder */
- DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000);
- data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL);
- if (data->reconnect_timer_fd < 0) {
- ERROR("[hc_connect] Could not initialize reattempt timer");
- return -1;
- }
+ /* Timer for managing the connection to the forwarder */
+ DEBUG("Connection to forwarder failed... next retry in %ds",
+ INTERVAL_MS / 1000);
+ data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS,
+ hl_connect_timeout, NULL);
+ if (data->reconnect_timer_fd < 0) {
+ ERROR("[hc_connect] Could not initialize reattempt timer");
+ return -1;
+ }
- return 0;
+ return 0;
}
-int
-hl_initialize(interface_t * interface, void * cfg)
-{
- hl_data_t * data = malloc(sizeof(hl_data_t));
- if (!data) {
- ERROR("[hicn_light] Out of memory!");
- goto ERR_MALLOC;
- }
-
- data->s = NULL;
- data->reconnect_timer_fd = 0;
- data->poll_timer_fd = 0;
+int hl_initialize(interface_t *interface, void *cfg) {
+ hl_data_t *data = malloc(sizeof(hl_data_t));
+ if (!data) {
+ ERROR("[hicn_light] Out of memory!");
+ goto ERR_MALLOC;
+ }
- interface->data = data;
+ data->s = NULL;
+ data->sp = NULL;
+ data->reconnect_timer_fd = 0;
+ data->poll_timer_fd = 0;
+ data->polled_routes = NULL;
+ data->state = HL_STATE_UNDEFINED;
- if (hl_connect(interface) < 0) {
- ERROR("[hl_initialize] Error during connection to forwarder");
- goto ERR_CONNECT;
- }
+ interface->data = data;
- data->polled_routes = NULL;
+ /* Connect both control and polling sockets */
+ if (hl_connect(interface) < 0) {
+ ERROR("[hl_initialize] Error during connection to forwarder");
+ goto ERR_CONNECT;
+ }
- return 0;
+ return 0;
ERR_CONNECT:
- free(data);
+ free(data);
ERR_MALLOC:
- return -1;
+ return -1;
}
-int hl_finalize(interface_t * interface)
-{
- hl_data_t * data = (hl_data_t *) interface->data;
+int hl_finalize(interface_t *interface) {
+ hl_data_t *data = (hl_data_t *)interface->data;
- hl_disconnect(interface);
+ hl_disconnect(interface);
- if (data->polled_routes)
- hc_data_free(data->polled_routes);
+ if (data->polled_routes) hc_data_free(data->polled_routes);
- free(data);
+ free(data);
- return 0;
+ return 0;
}
-int hl_on_event(interface_t * interface, facelet_t * facelet)
-{
- hc_face_t hc_face;
- hc_route_t route;
- int rc;
- int ret = 0;
- hl_data_t * data = (hl_data_t *)interface->data;
- face_t * face = NULL;
-
- hc_face.id = 0;
- memset(hc_face.name, 0, sizeof(hc_face.name));
-
-
- /* NOTE
- * - One example where this fails (and it is normal) is when we delete a
- * face that was not completely created, because for instance bonjour did
- * not give any data
- */
- if (facelet_get_face(facelet, &face) < 0) {
- ERROR("Could not retrieve face from facelet");
- ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
- goto ERR_FACE;
+int hl_on_event(interface_t *interface, facelet_t *facelet) {
+ hc_face_t hc_face;
+ hc_route_t route;
+ int rc;
+ int ret = 0;
+ hl_data_t *data = (hl_data_t *)interface->data;
+ face_t *face = NULL;
+
+ hc_face.id = 0;
+ memset(hc_face.name, 0, sizeof(hc_face.name));
+
+ /* NOTE
+ * - One example where this fails (and it is normal) is when we delete a
+ * face that was not completely created, because for instance bonjour did
+ * not give any data
+ */
+ if (facelet_get_face(facelet, &face) < 0) {
+ ERROR("Could not retrieve face from facelet");
+ ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
+ goto ERR_FACE;
+ }
+
+ if (!data->s) {
+ /* We are not connected to the forwarder */
+ ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE;
+ goto ERR;
+ }
+
+ switch (facelet_get_event(facelet)) {
+ case FACELET_EVENT_CREATE: {
+ /* Create face */
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ DEBUG("Create facelet %s", buf);
+
+ hc_face.face = *face;
+ rc = hc_face_create(data->s, &hc_face);
+ if (rc < 0) {
+ ERROR("Failed to create face\n");
+ ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
+ goto ERR;
+ }
+ INFO("Created face id=%d - %s", hc_face.id, buf);
}
- if (!data->s) {
- /* We are not connected to the forwarder */
- ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE;
+ hicn_route_t **route_array;
+ int n = facelet_get_route_array(facelet, &route_array);
+ if (n < 0) {
+ ERROR("Failed to create default hICN/IPv4 route");
+ ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
goto ERR;
- }
+ }
+ if (n == 0) {
+ /* Adding default routes */
+ route = (hc_route_t){
+ .face_id = hc_face.id,
+ .family = AF_INET,
+ .remote_addr = IPV4_ANY,
+ .len = 0,
+ .cost = DEFAULT_ROUTE_COST,
+
+ };
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create default hICN/IPv4 route");
+ ret = -1;
+ }
- switch(facelet_get_event(facelet)) {
-
- case FACELET_EVENT_CREATE:
- {
- /* Create face */
- char buf[MAXSZ_FACELET];
- facelet_snprintf(buf, MAXSZ_FACELET, facelet);
- DEBUG("Create facelet %s", buf);
-
- hc_face.face = *face;
- rc = hc_face_create(data->s, &hc_face);
- if (rc < 0) {
- ERROR("Failed to create face\n");
- ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
- goto ERR;
- }
- INFO("Created face id=%d - %s", hc_face.id, buf);
- }
+ route = (hc_route_t){
+ .face_id = hc_face.id,
+ .family = AF_INET6,
+ .remote_addr = IPV6_ANY,
+ .len = 0,
+ .cost = DEFAULT_ROUTE_COST,
+ };
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create default hICN/IPv6 route");
+ ret = -1;
+ }
- hicn_route_t ** route_array;
- int n = facelet_get_route_array(facelet, &route_array);
- if (n < 0) {
- ERROR("Failed to create default hICN/IPv4 route");
- ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
- goto ERR;
- }
- if (n == 0) {
- /* Adding default routes */
- route = (hc_route_t) {
- .face_id = hc_face.id,
- .family = AF_INET,
- .remote_addr = IPV4_ANY,
- .len = 0,
- .cost = DEFAULT_ROUTE_COST,
-
- };
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create default hICN/IPv4 route");
- ret = -1;
- }
-
- route = (hc_route_t) {
- .face_id = hc_face.id,
- .family = AF_INET6,
- .remote_addr = IPV6_ANY,
- .len = 0,
- .cost = DEFAULT_ROUTE_COST,
- };
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create default hICN/IPv6 route");
- ret = -1;
- }
-
- INFO("Successfully created default route(s).");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hicn_route_t * hicn_route = route_array[i];
- ip_prefix_t prefix;
- int cost;
- if (hicn_route_get_prefix(hicn_route, &prefix) < 0) {
- ERROR("Failed to get route prefix");
- ret = -1;
- continue;
- }
- if (hicn_route_get_cost(hicn_route, &cost) < 0) {
- ERROR("Failed to get route cost");
- ret = -1;
- continue;
- }
- route = (hc_route_t) {
- .face_id = hc_face.id,
- .family = prefix.family,
- .remote_addr = prefix.address,
- .len = prefix.len,
- .cost = cost,
- };
- if (hc_route_create(data->s, &route) < 0) {
- ERROR("Failed to create static route route");
- ret = -1;
- continue;
- }
- }
- }
- free(route_array);
-
- break;
-
- case FACELET_EVENT_DELETE:
- /* Removing a face should also remove associated routes */
- hc_face.face = *face;
- rc = hc_face_delete(data->s, &hc_face);
- if (rc < 0) {
- ERROR("Failed to delete face\n");
- ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
- goto ERR;
- }
+ INFO("Successfully created default route(s).");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hicn_route_t *hicn_route = route_array[i];
+ ip_prefix_t prefix;
+ int cost;
+ if (hicn_route_get_prefix(hicn_route, &prefix) < 0) {
+ ERROR("Failed to get route prefix");
+ ret = -1;
+ continue;
+ }
+ if (hicn_route_get_cost(hicn_route, &cost) < 0) {
+ ERROR("Failed to get route cost");
+ ret = -1;
+ continue;
+ }
+ route = (hc_route_t){
+ .face_id = hc_face.id,
+ .name = "", /* take face_id into account */
+ .family = prefix.family,
+ .remote_addr = prefix.address,
+ .len = prefix.len,
+ .cost = cost,
+ };
+ if (hc_route_create(data->s, &route) < 0) {
+ ERROR("Failed to create static route route");
+ ret = -1;
+ continue;
+ }
+ }
+ }
+ free(route_array);
+
+ break;
+
+ case FACELET_EVENT_DELETE:
+ /* Removing a face should also remove associated routes */
+ hc_face.face = *face;
+ rc = hc_face_delete(data->s, &hc_face, 1);
+ if (rc < 0) {
+ ERROR("Failed to delete face\n");
+ ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
+ goto ERR;
+ }
+
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ INFO("Deleted face id=%d", hc_face.id);
+
+ break;
+
+ case FACELET_EVENT_UPDATE:
+ /* Currently, only admin_state & priority are supported */
+ if (facelet_get_admin_state_status(facelet) ==
+ FACELET_ATTR_STATUS_DIRTY) {
+ hc_face.face = *face;
+ hc_face_t *face_found;
+
+ rc = hc_face_get(data->s, &hc_face, &face_found);
+ if (rc < 0) {
+ ERROR("Failed to find face\n");
+ ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
+ goto ERR;
+ }
+ if (!face_found) {
+ ERROR("Face to update has not been found");
+ ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
+ goto ERR;
+ }
+ char conn_id_or_name[SYMBOLIC_NAME_LEN];
+ snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
+ free(face_found);
+
+ face_state_t admin_state;
+ if (facelet_get_admin_state(facelet, &admin_state) < 0) {
+ ERROR("Failed to retrieve facelet admin state");
+ ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
+ goto ERR;
+ }
- char buf[MAXSZ_FACELET];
- facelet_snprintf(buf, MAXSZ_FACELET, facelet);
- INFO("Deleted face id=%d", hc_face.id);
-
- break;
-
- case FACELET_EVENT_UPDATE:
- /* Currently, only admin_state & priority are supported */
- if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
- hc_face.face = *face;
- hc_face_t * face_found;
-
- rc = hc_face_get(data->s, &hc_face, &face_found);
- if (rc < 0) {
- ERROR("Failed to find face\n");
- ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
- goto ERR;
- }
- if (!face_found) {
- ERROR("Face to update has not been found");
- ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
- goto ERR;
- }
- char conn_id_or_name[SYMBOLIC_NAME_LEN];
- snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
- free(face_found);
-
- face_state_t admin_state;
- if (facelet_get_admin_state(facelet, &admin_state) < 0) {
- ERROR("Failed to retrieve facelet admin state");
- ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
- goto ERR;
- }
-
- if (hc_connection_set_admin_state(data->s, conn_id_or_name, admin_state) < 0) {
- ERROR("Failed to update admin state");
- ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
- goto ERR;
- }
- facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Updated face id=%d - admin_state=%s", hc_face.id,
- face_state_str[admin_state]);
- }
+ if (hc_connection_set_admin_state(data->s, conn_id_or_name,
+ admin_state) < 0) {
+ ERROR("Failed to update admin state");
+ ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
+ goto ERR;
+ }
+ facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN);
+ INFO("Updated face id=%d - admin_state=%s", hc_face.id,
+ face_state_str(admin_state));
+ }
#ifdef WITH_POLICY
- if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
- hc_face.face = *face;
- hc_face_t * face_found;
-
- rc = hc_face_get(data->s, &hc_face, &face_found);
- if (rc < 0) {
- ERROR("Failed to find face\n");
- goto ERR;
- }
- if (!face_found) {
- ERROR("Face to update has not been found");
- goto ERR;
- }
- char conn_id_or_name[SYMBOLIC_NAME_LEN];
- snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
- free(face_found);
-
- netdevice_type_t netdevice_type;
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- ERROR("Failed to retrieve facelet netdevice_type");
- goto ERR;
- }
-
- /* Encode netdevice type into tags */
- policy_tags_t tags = POLICY_TAGS_EMPTY;
- if (facelet_has_netdevice_type(facelet)) {
- netdevice_type_t netdevice_type;
- if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
- ERROR("error getting netdevice_type");
- goto ERR;
- }
-
-
- switch(netdevice_type) {
- case NETDEVICE_TYPE_UNDEFINED:
- case NETDEVICE_TYPE_LOOPBACK:
- break;
- case NETDEVICE_TYPE_WIRED:
- policy_tags_add(&tags, POLICY_TAG_WIRED);
- break;
- case NETDEVICE_TYPE_WIFI:
- policy_tags_add(&tags, POLICY_TAG_WIFI);
- break;
- case NETDEVICE_TYPE_CELLULAR:
- policy_tags_add(&tags, POLICY_TAG_CELLULAR);
- break;
- default:
- goto ERR;
- }
- }
- //face->tags = tags;
-
- if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) {
- ERROR("Failed to update tags");
- goto ERR;
- }
- facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Updated face id=%d - netdevice_type=%s", hc_face.id,
- netdevice_type_str[netdevice_type]);
- }
- if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
- INFO("Updating priority...");
- hc_face.face = *face;
- hc_face_t * face_found;
-
- rc = hc_face_get(data->s, &hc_face, &face_found);
- if (rc < 0) {
- ERROR("Failed to find face\n");
- goto ERR;
- }
- if (!face_found) {
- ERROR("Face to update has not been found");
- goto ERR;
- }
- char conn_id_or_name[SYMBOLIC_NAME_LEN];
- snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
- free(face_found);
-
- uint32_t priority;
- if (facelet_get_priority(facelet, &priority) < 0) {
- ERROR("Failed to retrieve facelet priority");
- goto ERR;
- }
-
- INFO("Changing connection %s priority to %d", conn_id_or_name, priority);
- if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < 0) {
- ERROR("Failed to update priority");
- goto ERR;
- }
- facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN);
-
- INFO("Updated face id=%d - priority=%d", hc_face.id, priority);
- }
-#endif /* WITH_POLICY */
- break;
+ if (facelet_get_netdevice_type_status(facelet) ==
+ FACELET_ATTR_STATUS_DIRTY) {
+ hc_face.face = *face;
+ hc_face_t *face_found;
+
+ rc = hc_face_get(data->s, &hc_face, &face_found);
+ if (rc < 0) {
+ ERROR("Failed to find face\n");
+ goto ERR;
+ }
+ if (!face_found) {
+ ERROR("Face to update has not been found");
+ goto ERR;
+ }
+ char conn_id_or_name[SYMBOLIC_NAME_LEN];
+ snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
+ free(face_found);
+
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ ERROR("Failed to retrieve facelet netdevice_type");
+ goto ERR;
+ }
- default:
- ERROR("Unknown event %s\n", facelet_event_str[facelet_get_event(facelet)]);
- /* Unsupported events */
- ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
+ /* Encode netdevice type into tags */
+ policy_tags_t tags = POLICY_TAGS_EMPTY;
+ if (facelet_has_netdevice_type(facelet)) {
+ netdevice_type_t netdevice_type;
+ if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
+ ERROR("error getting netdevice_type");
goto ERR;
- }
+ }
+
+ switch (netdevice_type) {
+ case NETDEVICE_TYPE_UNDEFINED:
+ case NETDEVICE_TYPE_LOOPBACK:
+ break;
+ case NETDEVICE_TYPE_WIRED:
+ policy_tags_add(&tags, POLICY_TAG_WIRED);
+ break;
+ case NETDEVICE_TYPE_WIFI:
+ policy_tags_add(&tags, POLICY_TAG_WIFI);
+ break;
+ case NETDEVICE_TYPE_CELLULAR:
+ policy_tags_add(&tags, POLICY_TAG_CELLULAR);
+ break;
+ default:
+ goto ERR;
+ }
+ }
+ // face->tags = tags;
+
+ if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) {
+ ERROR("Failed to update tags");
+ goto ERR;
+ }
+ facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN);
+ INFO("Updated face id=%d - netdevice_type=%s", hc_face.id,
+ netdevice_type_str(netdevice_type));
+ }
+ if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
+ INFO("Updating priority...");
+ hc_face.face = *face;
+ hc_face_t *face_found;
+
+ rc = hc_face_get(data->s, &hc_face, &face_found);
+ if (rc < 0) {
+ ERROR("Failed to find face\n");
+ goto ERR;
+ }
+ if (!face_found) {
+ ERROR("Face to update has not been found");
+ goto ERR;
+ }
+ char conn_id_or_name[SYMBOLIC_NAME_LEN];
+ snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
+ free(face_found);
+
+ uint32_t priority;
+ if (facelet_get_priority(facelet, &priority) < 0) {
+ ERROR("Failed to retrieve facelet priority");
+ goto ERR;
+ }
+
+ INFO("Changing connection %s priority to %d", conn_id_or_name,
+ priority);
+ if (hc_connection_set_priority(data->s, conn_id_or_name, priority) <
+ 0) {
+ ERROR("Failed to update priority");
+ goto ERR;
+ }
+ facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN);
+
+ INFO("Updated face id=%d - priority=%d", hc_face.id, priority);
+ }
+#endif /* WITH_POLICY */
+ break;
+
+ default:
+ ERROR("Unknown event %s\n",
+ facelet_event_str[facelet_get_event(facelet)]);
+ /* Unsupported events */
+ ret = -FACELET_ERROR_REASON_INTERNAL_ERROR;
+ goto ERR;
+ }
ERR:
- face_free(face);
+ face_free(face);
ERR_FACE:
- return ret;
+ return ret;
}
-int hl_callback(interface_t * interface, int fd, void * unused)
-{
- hl_data_t * data = (hl_data_t*)interface->data;
- hc_data_t * results;
- int ret = 0;
-
- /* In case of error, reconnect to forwarder */
- if (hc_sock_callback(data->s, &results) < 0) {
- DEBUG("Closing socket... reconnecting...");
- if (interface_unregister_fd(interface, hc_sock_get_fd(data->s)) < 0) {
- ERROR("[hl_callback] Error unregistering fd");
- }
-
- /* Stopping poll timer */
- if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) {
- ERROR("[hl_callback] Could not cancel polling timer after forwarder disconnect");
- }
- if (data->polled_routes)
- hc_data_free(data->polled_routes);
+/*
+ * This should only receive data from the polling socket which is asynchronous,
+ * while all face creation, etc. operations are done synchronously in this
+ * version.
+ */
+int hl_callback(interface_t *interface, int fd, void *unused) {
+ hl_data_t *data = (hl_data_t *)interface->data;
+ hc_data_t *results;
+ int ret = 0;
+
+ /* Workaround: sometimes this is called with data = NULL */
+ if (!data) {
+ INFO("[hl_callback] no data");
+ return 0;
+ }
- hc_sock_free(data->s);
- data->s = NULL;
- hl_connect(interface);
- return ret;
+ /* In case of error, reconnect to forwarder */
+ if (hc_sock_callback(data->sp, &results) < 0) {
+ INFO("Closing socket... reconnecting...");
+ if (interface_unregister_fd(interface, hc_sock_get_fd(data->sp)) < 0) {
+ ERROR("[hl_callback] Error unregistering fd");
}
- /* Shall we wait for more data ? */
- if (!results->complete)
- return ret;
+ /* Stopping poll timer */
+ stop_poll_timer(interface);
+ if (data->polled_routes) hc_data_free(data->polled_routes);
- /* Process returned data */
- switch(data->state) {
+ hc_sock_free(data->s);
+ data->s = NULL;
+ hc_sock_free(data->sp);
+ data->sp = NULL;
- case HL_STATE_ROUTES_SENT:
- //DEBUG("[hl_callback] Processing routes");
- data->polled_routes = results;
+ hl_connect(interface);
+ return ret;
+ }
+
+ /* Shall we wait for more data ? */
+ if (!results->complete) {
+ INFO("[hl_callback] results incomplete");
+ return ret;
+ }
+
+ /* Process returned data */
+ // DEBUG("Processing data");
+ switch (data->state) {
+ case HL_STATE_ROUTES_SENT:
+ // DEBUG("[hl_callback] Processing routes");
+ data->polled_routes = results;
#if 0
foreach_route(r, results) {
@@ -622,19 +680,17 @@ int hl_callback(interface_t * interface, int fd, void * unused)
DEBUG("Route: %s", buf);
}
#endif
- data->state = HL_STATE_ROUTES_RECEIVED;
- if (hl_process_state(interface, fd, unused) < 0) {
- ERROR("[hl_callback] Error processing state after routes received");
- ret = -1;
- }
- break;
-
-
- case HL_STATE_FACES_SENT:
- //DEBUG("[hl_callback] Processing faces");
- assert(data->polled_routes);
- foreach_face(f, results) {
-
+ data->state = HL_STATE_ROUTES_RECEIVED;
+ if (hl_process_state(interface, fd, unused) < 0) {
+ ERROR("[hl_callback] Error processing state after routes received");
+ ret = -1;
+ }
+ break;
+
+ case HL_STATE_FACES_SENT:
+ // DEBUG("[hl_callback] Processing faces");
+ assert(data->polled_routes);
+ foreach_face(f, results) {
#if 0
char buf[MAXSZ_FACE];
int rc = hc_face_snprintf(buf, MAXSZ_FACE, f);
@@ -646,17 +702,16 @@ int hl_callback(interface_t * interface, int fd, void * unused)
DEBUG("Face: %s", buf);
#endif
- /* We can ignore faces on localhost */
+ /* We can ignore faces on localhost */
- facelet_t * facelet = facelet_create_from_face(&f->face);
- if (!facelet) {
- ERROR("[hl_callback] Could not create facelet... skipping");
- continue;
- }
+ facelet_t *facelet = facelet_create_from_face(&f->face);
+ if (!facelet) {
+ ERROR("[hl_callback] Could not create facelet... skipping");
+ continue;
+ }
- foreach_route(r, data->polled_routes) {
- if (r->face_id != f->id)
- continue;
+ foreach_route(r, data->polled_routes) {
+ if (r->face_id != f->id) continue;
#if 0
char route_s[MAXSZ_HC_ROUTE];
@@ -668,41 +723,40 @@ int hl_callback(interface_t * interface, int fd, void * unused)
DEBUG("Associated route: %s", route_s);
#endif
- if (r->len == 0)
- continue;
-
- ip_prefix_t prefix = {
- .family = r->family,
- .address = r->remote_addr,
- .len = r->len,
- };
- hicn_route_t * route = hicn_route_create(&prefix, r->face_id, r->cost);
- facelet_add_route(facelet, route);
- }
+ if (r->len == 0) continue;
- facelet_set_event(facelet, FACELET_EVENT_GET);
- interface_raise_event(interface, facelet);
- }
- hc_data_free(results);
- hc_data_free(data->polled_routes);
- data->polled_routes = NULL;
- data->state = HL_STATE_FACES_RECEIVED;
- if (hl_process_state(interface, fd, unused) < 0) {
- ERROR("[hl_callback] Error processing state after faces received");
- ret = -1;
- }
- break;
-
- case HL_STATE_IDLE:
- case HL_STATE_FACES_RECEIVED:
- case HL_STATE_ROUTES_RECEIVED:
- case HL_STATE_UNDEFINED:
- case HL_STATE_N:
- ERROR("[hl_callback] Unexpected state");
- ret = -1;
- }
+ ip_prefix_t prefix = {
+ .family = r->family,
+ .address = r->remote_addr,
+ .len = r->len,
+ };
+ hicn_route_t *route = hicn_route_create(&prefix, r->face_id, r->cost);
+ facelet_add_route(facelet, route);
+ }
- return ret;
+ facelet_set_event(facelet, FACELET_EVENT_GET);
+ interface_raise_event(interface, facelet);
+ }
+ hc_data_free(results);
+ hc_data_free(data->polled_routes);
+ data->polled_routes = NULL;
+ data->state = HL_STATE_FACES_RECEIVED;
+ if (hl_process_state(interface, fd, unused) < 0) {
+ ERROR("[hl_callback] Error processing state after faces received");
+ ret = -1;
+ }
+ break;
+
+ case HL_STATE_IDLE:
+ case HL_STATE_FACES_RECEIVED:
+ case HL_STATE_ROUTES_RECEIVED:
+ case HL_STATE_UNDEFINED:
+ case HL_STATE_N:
+ ERROR("[hl_callback] Unexpected state");
+ ret = -1;
+ }
+
+ return ret;
}
const interface_ops_t hicn_light_ops = {
diff --git a/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt b/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt
index 7f44d87fe..5d46cb8b6 100644
--- a/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c
index a1affd719..11738d7ac 100644
--- a/ctrl/facemgr/src/interfaces/netlink/netlink.c
+++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,9 +20,9 @@
#include <assert.h>
#include <linux/rtnetlink.h>
-#include <net/if_arp.h> // ARPHRD_LOOPBACK
-#include <sys/types.h> // getpid
-#include <unistd.h> // getpid
+#include <net/if_arp.h> // ARPHRD_LOOPBACK
+#include <sys/types.h> // getpid
+#include <unistd.h> // getpid
#include <hicn/facemgr.h>
#include <hicn/util/ip_address.h>
@@ -32,202 +32,188 @@
#include "../../interface.h"
typedef enum {
- NL_STATE_UNDEFINED,
- NL_STATE_LINK_SENT,
- NL_STATE_ADDR_SENT,
- NL_STATE_DONE,
+ NL_STATE_UNDEFINED,
+ NL_STATE_LINK_SENT,
+ NL_STATE_ADDR_SENT,
+ NL_STATE_DONE,
} nl_state_t;
/* Internal data storage */
typedef struct {
- int fd;
- nl_state_t state;
+ int fd;
+ nl_state_t state;
} nl_data_t;
-static inline void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len,
- unsigned short flags)
-{
- unsigned short type;
-
- memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
- while (RTA_OK(rta, len)) {
- type = rta->rta_type & ~flags;
- if (type <= max)
- tb[type] = rta;
- rta = RTA_NEXT(rta, len);
- }
+static inline void parse_rtattr(struct rtattr *tb[], int max,
+ struct rtattr *rta, int len,
+ unsigned short flags) {
+ unsigned short type;
+
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ type = rta->rta_type & ~flags;
+ if (type <= max) tb[type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
}
-int nl_process_state(interface_t * interface)
-{
- nl_data_t * data = (nl_data_t*)interface->data;
- int rc;
-
- switch(data->state) {
- case NL_STATE_UNDEFINED:
- {
- DEBUG("[nl_process_state] UNDEFINED->LINK_SENT");
- struct {
- struct nlmsghdr header;
- struct rtgenmsg payload;
- } msg2 = {
- .header = {
- .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
- .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
- .nlmsg_type = RTM_GETLINK,
- .nlmsg_pid = getpid(),
- .nlmsg_seq = 3,
- },
+int nl_process_state(interface_t *interface) {
+ nl_data_t *data = (nl_data_t *)interface->data;
+ int rc;
+
+ switch (data->state) {
+ case NL_STATE_UNDEFINED: {
+ DEBUG("[nl_process_state] UNDEFINED->LINK_SENT");
+ struct {
+ struct nlmsghdr header;
+ struct rtgenmsg payload;
+ } msg2 = {.header =
+ {
+ .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+ .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
+ .nlmsg_type = RTM_GETLINK,
+ .nlmsg_pid = getpid(),
+ .nlmsg_seq = 3,
+ },
.payload = {
.rtgen_family = AF_PACKET,
- }
- };
-
- rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0);
- if (rc < 0)
- printf("E: Error sending netlink query\n");
+ }};
- data->state = NL_STATE_LINK_SENT;
- break;
- }
-
- case NL_STATE_LINK_SENT:
- {
- DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT");
- /* Issue a first query to receive static state */
- struct {
- struct nlmsghdr header;
- struct ifaddrmsg payload;
- } msg = {
- .header = {
- .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
- .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
- .nlmsg_type = RTM_GETADDR,
- .nlmsg_pid = getpid(),
- .nlmsg_seq = 7,
- },
- .payload = {
- .ifa_family = AF_INET,
- }
- };
+ rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0);
+ if (rc < 0) printf("E: Error sending netlink query\n");
- rc = send(data->fd, &msg, msg.header.nlmsg_len, 0);
- if (rc < 0)
- printf("E: Error sending netlink query\n");
-
- data->state = NL_STATE_ADDR_SENT;
- break;
- }
+ data->state = NL_STATE_LINK_SENT;
+ break;
+ }
- case NL_STATE_ADDR_SENT:
- {
- DEBUG("[nl_process_state] ADDR_SENT->DONE");
- data->state = NL_STATE_DONE;
- break;
- }
+ case NL_STATE_LINK_SENT: {
+ DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT");
+ /* Issue a first query to receive static state */
+ struct {
+ struct nlmsghdr header;
+ struct ifaddrmsg payload;
+ } msg = {.header =
+ {
+ .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
+ .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
+ .nlmsg_type = RTM_GETADDR,
+ .nlmsg_pid = getpid(),
+ .nlmsg_seq = 7,
+ },
+ .payload = {
+ .ifa_family = AF_INET,
+ }};
+
+ rc = send(data->fd, &msg, msg.header.nlmsg_len, 0);
+ if (rc < 0) printf("E: Error sending netlink query\n");
+
+ data->state = NL_STATE_ADDR_SENT;
+ break;
+ }
- default: /* NL_STATE_DONE never called */
- break;
+ case NL_STATE_ADDR_SENT: {
+ DEBUG("[nl_process_state] ADDR_SENT->DONE");
+ data->state = NL_STATE_DONE;
+ break;
}
- return 0;
+ default: /* NL_STATE_DONE never called */
+ break;
+ }
+
+ return 0;
}
-int nl_initialize(interface_t * interface, void * cfg)
-{
- nl_data_t * data = malloc(sizeof(nl_data_t));
- if (!data)
- goto ERR_MALLOC;
+int nl_initialize(interface_t *interface, void *cfg) {
+ nl_data_t *data = malloc(sizeof(nl_data_t));
+ if (!data) goto ERR_MALLOC;
- data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (data->fd < 0) {
- ERROR("[nl_initialize] Failed to create netlink socket: %s", (char*)strerror(errno));
- goto ERR_SOCKET;
- }
+ data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (data->fd < 0) {
+ ERROR("[nl_initialize] Failed to create netlink socket: %s",
+ (char *)strerror(errno));
+ goto ERR_SOCKET;
+ }
- data->state = NL_STATE_UNDEFINED;
+ data->state = NL_STATE_UNDEFINED;
- struct sockaddr_nl local; // local addr struct
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK; // set protocol family
- // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc
- local.nl_groups = 0
- | RTMGRP_LINK
- | RTMGRP_IPV4_IFADDR
- | RTMGRP_IPV6_IFADDR
+ struct sockaddr_nl local; // local addr struct
+ memset(&local, 0, sizeof(local));
+ local.nl_family = AF_NETLINK; // set protocol family
+ // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc
+ local.nl_groups = 0 | RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR
#if 0
| RTMGRP_IPV4_ROUTE;
| RTMGRP_IPV6_ROUTE;
#endif
- ;
- local.nl_pid = getpid(); // set out id using current process id
+ ;
+ local.nl_pid = getpid(); // set out id using current process id
- if (bind(data->fd, (struct sockaddr*)&local, sizeof(local)) < 0) { // bind socket
- ERROR("[nl_initialize] Failed to bind netlink socket: %s", (char*)strerror(errno));
- goto ERR_BIND;
- }
+ if (bind(data->fd, (struct sockaddr *)&local, sizeof(local)) <
+ 0) { // bind socket
+ ERROR("[nl_initialize] Failed to bind netlink socket: %s",
+ (char *)strerror(errno));
+ goto ERR_BIND;
+ }
- interface->data = data;
+ interface->data = data;
- if (interface_register_fd(interface, data->fd, NULL) < 0) {
- ERROR("[nl_initialize] Error registering fd");
- goto ERR_FD;
- }
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[nl_initialize] Error registering fd");
+ goto ERR_FD;
+ }
#if 1
- nl_process_state(interface);
+ nl_process_state(interface);
#endif
- return 0;
+ return 0;
ERR_FD:
ERR_BIND:
- close(data->fd);
+ close(data->fd);
ERR_SOCKET:
- free(data);
+ free(data);
ERR_MALLOC:
- return -1;
+ return -1;
}
-int parse_link(struct nlmsghdr * h, facelet_t ** facelet,
- char * interface_name, size_t interface_name_size,
- bool * up, bool * running)
-{
- struct ifinfomsg *ifi; // structure for network interface info
- struct rtattr *tb[IFLA_MAX + 1];
+int parse_link(struct nlmsghdr *h, facelet_t **facelet, char *interface_name,
+ size_t interface_name_size, bool *up, bool *running) {
+ struct ifinfomsg *ifi; // structure for network interface info
+ struct rtattr *tb[IFLA_MAX + 1];
- assert(facelet);
+ assert(facelet);
- ifi = (struct ifinfomsg*) NLMSG_DATA(h); // get information about changed network interface
- parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1<<15);
+ ifi = (struct ifinfomsg *)NLMSG_DATA(
+ h); // get information about changed network interface
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1 << 15);
- if (interface_name) {
- assert(tb[IFLA_IFNAME]);
- snprintf(interface_name, interface_name_size, "%s", (char*)RTA_DATA(tb[IFLA_IFNAME]));
- }
+ if (interface_name) {
+ assert(tb[IFLA_IFNAME]);
+ snprintf(interface_name, interface_name_size, "%s",
+ (char *)RTA_DATA(tb[IFLA_IFNAME]));
+ }
- if (up)
- *up = ifi->ifi_flags & IFF_UP;
- if (running)
- *running = ifi->ifi_flags & IFF_RUNNING;
+ if (up) *up = ifi->ifi_flags & IFF_UP;
+ if (running) *running = ifi->ifi_flags & IFF_RUNNING;
+ netdevice_t *netdevice = netdevice_create_from_name(interface_name);
+ if (!netdevice) {
+ ERROR("[netlink.parse_link] error creating netdevice '%s'", interface_name);
+ goto ERR_ND;
+ }
- netdevice_t * netdevice = netdevice_create_from_name(interface_name);
- if (!netdevice) {
- ERROR("[netlink.parse_link] error creating netdevice '%s'", interface_name);
- goto ERR_ND;
- }
+ *facelet = facelet_create();
+ if (!*facelet) {
+ ERROR("[netlink.parse_link] error creating facelet");
+ goto ERR_FACELET;
+ }
- *facelet = facelet_create();
- if (!*facelet) {
- ERROR("[netlink.parse_link] error creating facelet");
- goto ERR_FACELET;
- }
-
- if (facelet_set_netdevice(*facelet, *netdevice) < 0) {
- ERROR("[netlink.parse_link] error setting netdevice");
- goto ERR;
- }
+ if (facelet_set_netdevice(*facelet, *netdevice) < 0) {
+ ERROR("[netlink.parse_link] error setting netdevice");
+ goto ERR;
+ }
// FIXME Tags
#if 0
@@ -252,160 +238,162 @@ int parse_link(struct nlmsghdr * h, facelet_t ** facelet,
#endif
- // TODO
- // - ifi_change
- // - IFLA_PROTINFO
+ // TODO
+ // - ifi_change
+ // - IFLA_PROTINFO
- netdevice_free(netdevice);
- return 0;
+ netdevice_free(netdevice);
+ return 0;
ERR:
- facelet_free(*facelet);
- *facelet = NULL;
+ facelet_free(*facelet);
+ *facelet = NULL;
ERR_FACELET:
- netdevice_free(netdevice);
+ netdevice_free(netdevice);
ERR_ND:
- return -1;
+ return -1;
}
-int parse_addr(struct nlmsghdr * h, facelet_t ** facelet,
- char * interface_name, size_t interface_name_size,
- char * interface_address, size_t interface_address_size)
-{
- ip_address_t local_addr = IP_ADDRESS_EMPTY;
- struct ifaddrmsg *ifa; // structure for network interface data
- struct rtattr *tba[IFA_MAX+1];
-
- assert(facelet);
-
- ifa = (struct ifaddrmsg*)NLMSG_DATA(h); // get data from the network interface
-
- parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0);
-
- /* FIXME
- *
- * IFA_LOCAL ok for v4, not there for v6
- *
- * IFA_ADDRESS seems to work for both but with the following precaution
- *
- * IFA_ADDRESS is prefix address, rather than local interface address.
- * It makes no difference for normally configured broadcast interfaces,
- * but for point-to-point IFA_ADDRESS is DESTINATION address,
- * local address is supplied in IFA_LOCAL attribute.
- */
- if (!tba[IFA_ADDRESS]) {
- ERROR("[netlink.parse_addr] No local address");
- return -1;
- }
-
- switch(ifa->ifa_family) {
- case AF_INET:
- local_addr.v4.as_inaddr = *(struct in_addr*)RTA_DATA(tba[IFA_ADDRESS]);
- break;
- case AF_INET6:
- local_addr.v6.as_in6addr = *(struct in6_addr*)RTA_DATA(tba[IFA_ADDRESS]);
- break;
- default:
- return 0;
- }
-
- /* See comment in parse_link */
- if (interface_address) {
- assert(tba[IFA_ADDRESS]);
- ip_address_snprintf(interface_address, interface_address_size, &local_addr, ifa->ifa_family);
- }
-
- netdevice_t * netdevice = netdevice_create_from_index(ifa->ifa_index);
- if (!netdevice) {
- ERROR("[netlink.parse_addr] error creating netdevice from index '%d'", ifa->ifa_index);
- goto ERR_ND;
- }
-
- if (interface_name) {
- snprintf(interface_name, interface_name_size, "%s", netdevice->name);
- }
-
- *facelet = facelet_create();
- if (!*facelet) {
- ERROR("[netlink.parse_addr] error creating facelet");
- goto ERR_FACELET;
- }
- if (facelet_set_netdevice(*facelet, *netdevice) < 0) {
- ERROR("[netlink.parse_addr] error setting netdevice");
- goto ERR;
- }
- if (facelet_set_family(*facelet, ifa->ifa_family) < 0) {
- ERROR("[netlink.parse_addr] error setting family");
- goto ERR;
- }
- if (facelet_set_local_addr(*facelet, local_addr) < 0) {
- ERROR("[netlink.parse_addr] error setting local address");
- goto ERR;
- }
-
- netdevice_free(netdevice);
- return 0;
+int parse_addr(struct nlmsghdr *h, facelet_t **facelet, char *interface_name,
+ size_t interface_name_size, char *interface_address,
+ size_t interface_address_size) {
+ ip_address_t local_addr = IP_ADDRESS_EMPTY;
+ struct ifaddrmsg *ifa; // structure for network interface data
+ struct rtattr *tba[IFA_MAX + 1];
+
+ assert(facelet);
+
+ ifa =
+ (struct ifaddrmsg *)NLMSG_DATA(h); // get data from the network interface
+
+ parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0);
+
+ /* FIXME
+ *
+ * IFA_LOCAL ok for v4, not there for v6
+ *
+ * IFA_ADDRESS seems to work for both but with the following precaution
+ *
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ */
+ if (!tba[IFA_ADDRESS]) {
+ ERROR("[netlink.parse_addr] No local address");
+ return -1;
+ }
+
+ switch (ifa->ifa_family) {
+ case AF_INET:
+ local_addr.v4.as_inaddr = *(struct in_addr *)RTA_DATA(tba[IFA_ADDRESS]);
+ break;
+ case AF_INET6:
+ local_addr.v6.as_in6addr = *(struct in6_addr *)RTA_DATA(tba[IFA_ADDRESS]);
+ break;
+ default:
+ return 0;
+ }
+
+ /* See comment in parse_link */
+ if (interface_address) {
+ assert(tba[IFA_ADDRESS]);
+ ip_address_snprintf(interface_address, interface_address_size, &local_addr,
+ ifa->ifa_family);
+ }
+
+ netdevice_t *netdevice = netdevice_create_from_index(ifa->ifa_index);
+ if (!netdevice) {
+ ERROR("[netlink.parse_addr] error creating netdevice from index '%d'",
+ ifa->ifa_index);
+ goto ERR_ND;
+ }
+
+ if (interface_name) {
+ snprintf(interface_name, interface_name_size, "%s", netdevice->name);
+ }
+
+ *facelet = facelet_create();
+ if (!*facelet) {
+ ERROR("[netlink.parse_addr] error creating facelet");
+ goto ERR_FACELET;
+ }
+ if (facelet_set_netdevice(*facelet, *netdevice) < 0) {
+ ERROR("[netlink.parse_addr] error setting netdevice");
+ goto ERR;
+ }
+ if (facelet_set_family(*facelet, ifa->ifa_family) < 0) {
+ ERROR("[netlink.parse_addr] error setting family");
+ goto ERR;
+ }
+ if (facelet_set_local_addr(*facelet, local_addr) < 0) {
+ ERROR("[netlink.parse_addr] error setting local address");
+ goto ERR;
+ }
+
+ netdevice_free(netdevice);
+ return 0;
ERR:
- facelet_free(*facelet);
- *facelet = NULL;
+ facelet_free(*facelet);
+ *facelet = NULL;
ERR_FACELET:
- netdevice_free(netdevice);
+ netdevice_free(netdevice);
ERR_ND:
- return -1;
+ return -1;
}
-int nl_callback(interface_t * interface, int fd, void * unused)
-{
- nl_data_t * data = (nl_data_t*)interface->data;
+int nl_callback(interface_t *interface, int fd, void *unused) {
+ nl_data_t *data = (nl_data_t *)interface->data;
- struct sockaddr_nl local; // local addr struct
- memset(&local, 0, sizeof(local));
+ struct sockaddr_nl local; // local addr struct
+ memset(&local, 0, sizeof(local));
- char buf[8192]; // message buffer
- struct iovec iov; // message structure
- iov.iov_base = buf; // set message buffer as io
- iov.iov_len = sizeof(buf); // set size
+ char buf[8192]; // message buffer
+ struct iovec iov; // message structure
+ iov.iov_base = buf; // set message buffer as io
+ iov.iov_len = sizeof(buf); // set size
- // initialize protocol message header
- struct msghdr msg = {
- .msg_name = &local, // local address
- .msg_namelen = sizeof(local), // address size
- .msg_iov = &iov, // io vector
- .msg_iovlen = 1, // io size
- };
+ // initialize protocol message header
+ struct msghdr msg = {
+ .msg_name = &local, // local address
+ .msg_namelen = sizeof(local), // address size
+ .msg_iov = &iov, // io vector
+ .msg_iovlen = 1, // io size
+ };
- ssize_t status = recvmsg(data->fd, &msg, 0);
+ ssize_t status = recvmsg(data->fd, &msg, 0);
- // check status
- if (status < 0) {
-/*
- if (errno == EINTR || errno == EAGAIN)
- continue;
-*/
+ // check status
+ if (status < 0) {
+ /*
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ */
- printf("Failed to read netlink: %s", (char*)strerror(errno));
- return -1;
- }
+ printf("Failed to read netlink: %s", (char *)strerror(errno));
+ return -1;
+ }
- if (msg.msg_namelen != sizeof(local)) { // check message length, just in case
- printf("Invalid length of the sender address struct\n");
- return -1;
- }
+ if (msg.msg_namelen != sizeof(local)) { // check message length, just in case
+ printf("Invalid length of the sender address struct\n");
+ return -1;
+ }
- // message parser
- struct nlmsghdr *h;
+ // message parser
+ struct nlmsghdr *h;
- for (h = (struct nlmsghdr*)buf; status >= (ssize_t)sizeof(*h); ) { // read all messagess headers
- int len = h->nlmsg_len;
- int l = len - sizeof(*h);
+ for (h = (struct nlmsghdr *)buf;
+ status >= (ssize_t)sizeof(*h);) { // read all messagess headers
+ int len = h->nlmsg_len;
+ int l = len - sizeof(*h);
- if ((l < 0) || (len > status)) {
- printf("Invalid message length: %i\n", len);
- continue;
- }
+ if ((l < 0) || (len > status)) {
+ printf("Invalid message length: %i\n", len);
+ continue;
+ }
- switch(h->nlmsg_type) {
+ switch (h->nlmsg_type) {
#if 0
case RTM_NEWROUTE:
case RTM_DELROUTE:
@@ -413,147 +401,123 @@ int nl_callback(interface_t * interface, int fd, void * unused)
break;
#endif
- case RTM_DELADDR:
- {
- facelet_t * facelet = NULL;
- char interface_name[IFNAMSIZ];
- char interface_address[MAXSZ_IP_ADDRESS] = {0};
-
- if (parse_addr(h, &facelet, interface_name, IFNAMSIZ,
- interface_address, MAXSZ_IP_ADDRESS) < 0) {
- ERROR("Error parsing address message");
- break;
- }
-
- DEBUG("[NETLINK] Interface %s: address was removed", interface_name);
- if (facelet) {
- facelet_set_event(facelet, FACELET_EVENT_SET_DOWN);
- facelet_set_attr_clean(facelet);
- interface_raise_event(interface, facelet);
- }
- break;
- }
-
- case RTM_NEWADDR:
- {
- facelet_t * facelet = NULL;
- char interface_name[IFNAMSIZ];
- char interface_address[MAXSZ_IP_ADDRESS] = {0};
-
- if (parse_addr(h, &facelet, interface_name, IFNAMSIZ,
- interface_address, MAXSZ_IP_ADDRESS) < 0) {
- ERROR("Error parsing address message");
- break;
- }
-
- DEBUG("[NETLINK] Interface %s: new address was assigned: %s", interface_name, interface_address);
-
- if (facelet) {
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_set_attr_clean(facelet);
- interface_raise_event(interface, facelet);
- }
- break;
- }
+ case RTM_DELADDR: {
+ facelet_t *facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ char interface_address[MAXSZ_IP_ADDRESS] = {0};
- case RTM_DELLINK:
- {
- /* This does not always seem to be called, hence we rely on
- * down, not running */
- facelet_t * facelet = NULL;
- char interface_name[IFNAMSIZ];
- if (parse_link(h, &facelet, interface_name, IFNAMSIZ,
- NULL, NULL) < 0) {
- ERROR("Error parsing link message");
- break;
- }
+ if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, interface_address,
+ MAXSZ_IP_ADDRESS) < 0) {
+ ERROR("Error parsing address message");
+ break;
+ }
- DEBUG("[NETLINK] Network interface %s was removed", interface_name);
+ DEBUG("[NETLINK] Interface %s: address was removed", interface_name);
+ if (facelet) {
+ facelet_set_event(facelet, FACELET_EVENT_SET_DOWN);
+ facelet_set_attr_clean(facelet);
+ interface_raise_event(interface, facelet);
+ }
+ break;
+ }
+
+ case RTM_NEWADDR: {
+ facelet_t *facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ char interface_address[MAXSZ_IP_ADDRESS] = {0};
+
+ if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, interface_address,
+ MAXSZ_IP_ADDRESS) < 0) {
+ ERROR("Error parsing address message");
+ break;
+ }
- if (!facelet)
- break;
+ DEBUG("[NETLINK] Interface %s: new address was assigned: %s",
+ interface_name, interface_address);
- facelet_set_event(facelet, FACELET_EVENT_DELETE);
- facelet_set_attr_clean(facelet);
- interface_raise_event(interface, facelet);
+ if (facelet) {
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ facelet_set_attr_clean(facelet);
+ interface_raise_event(interface, facelet);
+ }
+ break;
+ }
+
+ case RTM_DELLINK: {
+ /* This does not always seem to be called, hence we rely on
+ * down, not running */
+ facelet_t *facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ if (parse_link(h, &facelet, interface_name, IFNAMSIZ, NULL, NULL) < 0) {
+ ERROR("Error parsing link message");
+ break;
+ }
- break;
- }
-
- case RTM_NEWLINK:
- {
- facelet_t * facelet = NULL;
- char interface_name[IFNAMSIZ];
- bool up, running;
-
- if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) < 0) {
- ERROR("Error parsing link message");
- break;
- }
-
- // UP RUNNING
- // UP NOT RUNNING
- // DOWN NOT RUNNING
-#if 1
- DEBUG("[NETLINK] New network interface %s, state: %s %s", interface_name,
- up ? "UP" : "DOWN",
- running ? "RUNNING" : "NOT_RUNNING");
-#endif
+ DEBUG("[NETLINK] Network interface %s was removed", interface_name);
- if (!facelet)
- break;
- if (up && running) {
- facelet_set_event(facelet, FACELET_EVENT_CREATE);
- //facelet_set_family(facelet, AF_INET);
- facelet_set_attr_clean(facelet);
- interface_raise_event(interface, facelet);
+ if (!facelet) break;
-#if 0
- facelet_t * facelet6 = facelet_dup(facelet);
- if (!facelet6) {
- ERROR("Could not duplicate face for v6");
- break;
- }
- facelet_set_family(facelet6, AF_INET6);
- interface_raise_event(interface, facelet6);
-#endif
-// } else {
-//#if 1
-// facelet_set_event(facelet, FACELET_EVENT_SET_DOWN);
-// facelet_set_attr_clean(facelet);
-// interface_raise_event(interface, facelet);
-//#else
-// facelet_free(facelet);
-//#endif
- }
- break;
- }
+ facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ facelet_set_attr_clean(facelet);
+ interface_raise_event(interface, facelet);
- case NLMSG_ERROR:
- break;
- case NLMSG_DONE:
- nl_process_state(interface);
- break;
- default:
- break;
+ break;
+ }
+
+ case RTM_NEWLINK: {
+ facelet_t *facelet = NULL;
+ char interface_name[IFNAMSIZ];
+ bool up, running;
+ if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) <
+ 0) {
+ ERROR("Error parsing link message");
+ break;
}
- status -= NLMSG_ALIGN(len); // align offsets by the message length, this is important
+ // UP RUNNING
+ // UP NOT RUNNING
+ // DOWN NOT RUNNING
+#if 1
+ DEBUG("[NETLINK] New network interface %s, state: %s %s",
+ interface_name, up ? "UP" : "DOWN",
+ running ? "RUNNING" : "NOT_RUNNING");
+#endif
- h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); // get next message
+ if (!facelet) break;
+ if (up && running) {
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ facelet_set_attr_clean(facelet);
+ interface_raise_event(interface, facelet);
+ } else {
+ facelet_free(facelet);
+ }
+ break;
+ }
+
+ case NLMSG_ERROR:
+ break;
+ case NLMSG_DONE:
+ nl_process_state(interface);
+ break;
+ default:
+ break;
}
- return 0;
-}
+ status -= NLMSG_ALIGN(
+ len); // align offsets by the message length, this is important
-int nl_finalize(interface_t * interface)
-{
- nl_data_t * data = (nl_data_t*)interface->data;
- close(data->fd);
- free(interface->data);
- return 0;
+ h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); // get next message
+ }
+
+ return 0;
+}
+int nl_finalize(interface_t *interface) {
+ nl_data_t *data = (nl_data_t *)interface->data;
+ close(data->fd);
+ free(interface->data);
+ return 0;
}
const interface_ops_t netlink_ops = {
diff --git a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt
index e8b0144b1..db96e390f 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
index 2c4bff513..3adba0969 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,7 +32,7 @@
#include <hicn/util/map.h>
#include "../../common.h"
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include "../../interface.h"
#include "network_framework.h"
@@ -41,7 +41,6 @@
#error "Network frameork requires MacOSX 10.14+"
#endif /* !defined(MAC_OS_X_VERSION_10_14) */
-
/*
* Bonjour service discovery for hICN forwarder
*
@@ -70,144 +69,147 @@
/* Generated variables */
#define BONJOUR_SERVICE_TYPE "_hicn._" STRINGIZE(BONJOUR_PROTOCOL)
#define BONJOUR_PROTOCOL_NAME STRINGIZE(BONJOUR_PROTOCOL)
-#define nw_parameters_create_fn PPCAT(nw_parameters_create_secure_, BONJOUR_PROTOCOL)
+#define nw_parameters_create_fn \
+ PPCAT(nw_parameters_create_secure_, BONJOUR_PROTOCOL)
#define DEFAULT_PORT 9695
typedef enum {
- INTERFACE_TYPE_OTHER,
- INTERFACE_TYPE_WIFI,
- INTERFACE_TYPE_CELLULAR,
- INTERFACE_TYPE_WIRED,
- INTERFACE_TYPE_LOOPBACK,
+ INTERFACE_TYPE_OTHER,
+ INTERFACE_TYPE_WIFI,
+ INTERFACE_TYPE_CELLULAR,
+ INTERFACE_TYPE_WIRED,
+ INTERFACE_TYPE_LOOPBACK,
} _nw_interface_type_t;
-const char * interface_type_str[] = {
+const char *interface_type_str[] = {
"OTHER", "WIFI", "CELLULAR", "WIRED", "LOOPBACK",
};
#if 1
typedef enum {
- PATH_STATUS_INVALID,
- PATH_STATUS_SATISTIED,
- PATH_STATUS_UNSATISFIED,
- PATH_STATUS_SATISFIABLE,
+ PATH_STATUS_INVALID,
+ PATH_STATUS_SATISTIED,
+ PATH_STATUS_UNSATISFIED,
+ PATH_STATUS_SATISFIABLE,
} _nw_path_status_t;
#endif
-const char * path_status_str[] = {
- "INVALID", "SATISFIED", "UNSATISFIED", "SATISFIABLE",
+const char *path_status_str[] = {
+ "INVALID",
+ "SATISFIED",
+ "UNSATISFIED",
+ "SATISFIABLE",
};
-const char * endpoint_type_str[] = {
- "INVALID", "ADDRESS", "HOST", "BONJOUR",
+const char *endpoint_type_str[] = {
+ "INVALID",
+ "ADDRESS",
+ "HOST",
+ "BONJOUR",
};
-const char * connection_state_str[] = {
+const char *connection_state_str[] = {
"INVALID", "WAITING", "PREPARING", "READY", "FAILED", "CANCELLED",
};
-int
-cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2)
-{
- return INT_CMP(nw_interface_get_index(iface1), nw_interface_get_index(iface2));
+int cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2) {
+ return INT_CMP(nw_interface_get_index(iface1),
+ nw_interface_get_index(iface2));
}
-//TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface);
+// TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface);
typedef struct {
- network_framework_cfg_t cfg;
- nw_path_monitor_t pm; /**< Main path monitor */
-// map_cnx_t map_cnx; /**< Map: interface -> connection for face status */
+ network_framework_cfg_t cfg;
+ nw_path_monitor_t pm; /**< Main path monitor */
+ // map_cnx_t map_cnx; /**< Map: interface -> connection for face status
+ // */
} nf_data_t;
-void
-dump_interface(nw_interface_t interface, int indent)
-{
- uint32_t index = nw_interface_get_index(interface);
- const char * name = nw_interface_get_name(interface);
- nw_interface_type_t type = nw_interface_get_type(interface);
+void dump_interface(nw_interface_t interface, int indent) {
+ uint32_t index = nw_interface_get_index(interface);
+ const char *name = nw_interface_get_name(interface);
+ nw_interface_type_t type = nw_interface_get_type(interface);
- printfi(indent+1, "%d: %s [%s]\n", index, name, interface_type_str[type]);
+ printfi(indent + 1, "%d: %s [%s]\n", index, name, interface_type_str[type]);
}
-void
-dump_endpoint(nw_endpoint_t endpoint, int indent)
-{
- if (!endpoint) {
- printfi(indent, "N/A\n");
- return;
- }
-
- nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint);
- const char * hostname = nw_endpoint_get_hostname(endpoint);
- short port = nw_endpoint_get_port(endpoint);
- const struct sockaddr * address = nw_endpoint_get_address(endpoint);
-
- printfi(indent, "Type: %s\n", endpoint_type_str[endpoint_type]);
- printfi(indent, "Hostname: %s\n", hostname);
- printfi(indent, "Port: %d\n", port);
-
- if (address) {
- char *s = NULL;
- switch(address->sa_family) {
- case AF_INET: {
- struct sockaddr_in *addr_in = (struct sockaddr_in *)address;
- s = malloc(INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
- break;
- }
- case AF_INET6: {
- struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address;
- s = malloc(INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
- break;
- }
- default:
- break;
- }
+void dump_endpoint(nw_endpoint_t endpoint, int indent) {
+ if (!endpoint) {
+ printfi(indent, "N/A\n");
+ return;
+ }
+
+ nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint);
+ const char *hostname = nw_endpoint_get_hostname(endpoint);
+ short port = nw_endpoint_get_port(endpoint);
+ const struct sockaddr *address = nw_endpoint_get_address(endpoint);
+
+ printfi(indent, "Type: %s\n", endpoint_type_str[endpoint_type]);
+ printfi(indent, "Hostname: %s\n", hostname);
+ printfi(indent, "Port: %d\n", port);
+
+ if (address) {
+ char *s = NULL;
+ switch (address->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)address;
+ s = malloc(INET_ADDRSTRLEN);
+ inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address;
+ s = malloc(INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
+ break;
+ default:
+ break;
+ }
printfi(indent, "IP address: %s\n", s);
free(s);
}
-}
+ }
-void
-dump_path(nw_path_t path, int indent)
-{
+ void dump_path(nw_path_t path, int indent) {
/* nw_path_enumerate_interfaces : not interesting */
nw_path_status_t path_status = nw_path_get_status(path);
printfi(indent, "Status: %s\n", path_status_str[path_status]);
- printfi(indent, "Expensive: %s\n", nw_path_is_expensive(path) ? "true" : "false");
- printfi(indent, "IPv4 enabled: %s\n", nw_path_has_ipv4(path) ? "true" : "false");
- printfi(indent, "IPv6 enabled: %s\n", nw_path_has_ipv6(path) ? "true" : "false");
+ printfi(indent, "Expensive: %s\n",
+ nw_path_is_expensive(path) ? "true" : "false");
+ printfi(indent, "IPv4 enabled: %s\n",
+ nw_path_has_ipv4(path) ? "true" : "false");
+ printfi(indent, "IPv6 enabled: %s\n",
+ nw_path_has_ipv6(path) ? "true" : "false");
printfi(indent, "DNS: %s\n", nw_path_has_dns(path) ? "true" : "false");
printfi(indent, "Interfaces:\n");
- nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) {
- dump_interface(interface, indent+1);
- return true;
- });
+ nw_path_enumerate_interfaces(
+ path,
+ (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) {
+ dump_interface(interface, indent + 1);
+ return true;
+ });
nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path);
printfi(indent, "Effective local endpoint:\n");
- dump_endpoint(local, indent+1);
+ dump_endpoint(local, indent + 1);
nw_release(local);
nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path);
printfi(indent, "Effective remote endpoint:\n");
- dump_endpoint(remote, indent+1);
+ dump_endpoint(remote, indent + 1);
nw_release(remote);
-}
+ }
-void
-dump_connection(nw_connection_t connection, int indent)
-{
+ void dump_connection(nw_connection_t connection, int indent) {
nw_endpoint_t remote = nw_connection_copy_endpoint(connection);
nw_path_t path = nw_connection_copy_current_path(connection);
printfi(indent, "Remote endpoint:\n");
- dump_endpoint(remote, indent+1);
+ dump_endpoint(remote, indent + 1);
printfi(indent, "Path:\n");
- dump_path(path, indent+1);
+ dump_path(path, indent + 1);
/*
nw_connection_copy_protocol_metadata();
@@ -216,34 +218,34 @@ dump_connection(nw_connection_t connection, int indent)
nw_release(remote);
nw_release(path);
-}
+ }
#if defined(MAC_OS_X_VERSION_10_15)
-void
-dump_browse_result(nw_browse_result_t result, int indent)
-{
+ void dump_browse_result(nw_browse_result_t result, int indent) {
/* Endpoint */
nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result);
if (!browse_endpoint) {
- ERROR("[network_framework.dump_result] Failed to retrieve endpoint from Bonjour browse result");
- return;
+ ERROR(
+ "[network_framework.dump_result] Failed to retrieve endpoint from "
+ "Bonjour browse result");
+ return;
}
printfi(indent + 1, "Endpoint:");
dump_endpoint(browse_endpoint, indent + 2);
/* Interfaces */
printfi(indent + 1, "Interfaces:");
- nw_browse_result_enumerate_interfaces(result, (nw_browse_result_enumerate_interface_t) ^(nw_interface_t interface) {
- dump_interface(interface, indent + 2);
- return true;
- });
-}
+ nw_browse_result_enumerate_interfaces(
+ result,
+ (nw_browse_result_enumerate_interface_t) ^ (nw_interface_t interface) {
+ dump_interface(interface, indent + 2);
+ return true;
+ });
+ }
#endif /* defined(MAC_OS_X_VERSION_10_15) */
-facelet_t *
-facelet_create_from_connection(nw_connection_t connection)
-{
- facelet_t * facelet;
+ facelet_t *facelet_create_from_connection(nw_connection_t connection) {
+ facelet_t *facelet;
ip_address_t local_addr, remote_addr;
uint16_t remote_port;
@@ -252,34 +254,36 @@ facelet_create_from_connection(nw_connection_t connection)
nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path);
__block nw_interface_t interface;
- const struct sockaddr * local_sa = nw_endpoint_get_address(local);
- const struct sockaddr * remote_sa = nw_endpoint_get_address(remote);
-
- assert (local_sa->sa_family == remote_sa->sa_family);
- switch(local_sa->sa_family) {
- case AF_INET:
- local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr;
- remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr;
- remote_port = ((struct sockaddr_in *)remote_sa)->sin_port;
- break;
- case AF_INET6:
- local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr;
- remote_addr.v6.as_in6addr = ((struct sockaddr_in6 *)remote_sa)->sin6_addr;
- remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port;
- break;
- default:
- ERROR("Unsupported address family: %d\n", local_sa->sa_family);
- return NULL;
+ const struct sockaddr *local_sa = nw_endpoint_get_address(local);
+ const struct sockaddr *remote_sa = nw_endpoint_get_address(remote);
+
+ assert(local_sa->sa_family == remote_sa->sa_family);
+ switch (local_sa->sa_family) {
+ case AF_INET:
+ local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr;
+ remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr;
+ remote_port = ((struct sockaddr_in *)remote_sa)->sin_port;
+ break;
+ case AF_INET6:
+ local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr;
+ remote_addr.v6.as_in6addr =
+ ((struct sockaddr_in6 *)remote_sa)->sin6_addr;
+ remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port;
+ break;
+ default:
+ ERROR("Unsupported address family: %d\n", local_sa->sa_family);
+ return NULL;
}
-
/* Retrieving path interface type (a single one expected */
- nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t path_interface) {
- interface = path_interface;
- return false;
- });
-
- const char * name = nw_interface_get_name(interface);
+ nw_path_enumerate_interfaces(
+ path, (nw_path_enumerate_interfaces_block_t) ^
+ (nw_interface_t path_interface) {
+ interface = path_interface;
+ return false;
+ });
+
+ const char *name = nw_interface_get_name(interface);
netdevice_t netdevice;
snprintf(netdevice.name, IFNAMSIZ, "%s", name);
netdevice_update_index(&netdevice);
@@ -287,25 +291,24 @@ facelet_create_from_connection(nw_connection_t connection)
netdevice_type_t netdevice_type;
nw_interface_type_t type = nw_interface_get_type(interface);
- switch(type) {
- case INTERFACE_TYPE_OTHER:
- netdevice_type = NETDEVICE_TYPE_UNDEFINED;
- break;
- case INTERFACE_TYPE_WIFI:
- netdevice_type = NETDEVICE_TYPE_WIFI;
- break;
- case INTERFACE_TYPE_CELLULAR:
- netdevice_type = NETDEVICE_TYPE_CELLULAR;
- break;
- case INTERFACE_TYPE_WIRED:
- netdevice_type = NETDEVICE_TYPE_WIRED;
- break;
- case INTERFACE_TYPE_LOOPBACK:
- netdevice_type = NETDEVICE_TYPE_LOOPBACK;
- break;
- default:
- break;
-
+ switch (type) {
+ case INTERFACE_TYPE_OTHER:
+ netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+ break;
+ case INTERFACE_TYPE_WIFI:
+ netdevice_type = NETDEVICE_TYPE_WIFI;
+ break;
+ case INTERFACE_TYPE_CELLULAR:
+ netdevice_type = NETDEVICE_TYPE_CELLULAR;
+ break;
+ case INTERFACE_TYPE_WIRED:
+ netdevice_type = NETDEVICE_TYPE_WIRED;
+ break;
+ case INTERFACE_TYPE_LOOPBACK:
+ netdevice_type = NETDEVICE_TYPE_LOOPBACK;
+ break;
+ default:
+ break;
}
nw_release(local);
@@ -313,8 +316,7 @@ facelet_create_from_connection(nw_connection_t connection)
nw_release(path);
facelet = facelet_create();
- if (!facelet)
- return NULL;
+ if (!facelet) return NULL;
facelet_set_netdevice(facelet, netdevice);
facelet_set_netdevice_type(facelet, netdevice_type);
@@ -324,20 +326,21 @@ facelet_create_from_connection(nw_connection_t connection)
facelet_set_remote_port(facelet, remote_port);
return facelet;
-}
+ }
-void
-on_connection_state_event(interface_t * interface, nw_interface_t iface,
- nw_connection_t cnx, nw_connection_state_t state, nw_error_t error)
-{
+ void on_connection_state_event(
+ interface_t * interface, nw_interface_t iface, nw_connection_t cnx,
+ nw_connection_state_t state, nw_error_t error) {
#if 1
DEBUG("Connection [new state = %s]:\n", connection_state_str[state]);
nw_path_t path = nw_connection_copy_current_path(cnx);
- nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) {
- const char * name = nw_interface_get_name(interface);
- printf("NAME=%s\n", name);
- return true;
- });
+ nw_path_enumerate_interfaces(
+ path,
+ (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) {
+ const char *name = nw_interface_get_name(interface);
+ printf("NAME=%s\n", name);
+ return true;
+ });
#endif
/* We should get enough information to create the face and set if up
@@ -346,84 +349,71 @@ on_connection_state_event(interface_t * interface, nw_interface_t iface,
nw_endpoint_t remote = nw_connection_copy_endpoint(cnx);
errno = error ? nw_error_get_error_code(error) : 0;
- switch(state) {
- case nw_connection_state_waiting:
- warn("connect to %s port %u (%s) failed, is waiting",
- nw_endpoint_get_hostname(remote),
- nw_endpoint_get_port(remote),
- BONJOUR_PROTOCOL_NAME);
- break;
-
- case nw_connection_state_preparing:
- break;
-
- case nw_connection_state_ready:
- {
- printf("info:\n");
- warn("connection ready");
+ switch (state) {
+ case nw_connection_state_waiting:
+ warn("connect to %s port %u (%s) failed, is waiting",
+ nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote),
+ BONJOUR_PROTOCOL_NAME);
+ break;
+
+ case nw_connection_state_preparing:
+ break;
+
+ case nw_connection_state_ready: {
+ printf("info:\n");
+ warn("connection ready");
#if 1
- WITH_DEBUG({
- dump_connection(cnx, 1);
- });
+ WITH_DEBUG({ dump_connection(cnx, 1); });
#endif
- facelet_t * facelet = facelet_create_from_connection(cnx);
- if (!facelet)
- return;
- facelet_set_event(facelet, FACELET_EVENT_CREATE);
- interface_raise_event(interface, facelet);
- break;
- }
- case nw_connection_state_failed:
- /* Can we fail with bonjour, or are we always waiting ? */
- warn("connect to %s port %u (%s) failed",
- nw_endpoint_get_hostname(remote),
- nw_endpoint_get_port(remote),
- BONJOUR_PROTOCOL_NAME);
- break;
-
- case nw_connection_state_cancelled:
- // Release the primary reference on the connection
- // that was taken at creation time
- nw_release(cnx);
- break;
-
- default: /* nw_connection_state_invalid */
- /* Should never be called */
- break;
-
+ facelet_t *facelet = facelet_create_from_connection(cnx);
+ if (!facelet) return;
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ interface_raise_event(interface, facelet);
+ break;
+ }
+ case nw_connection_state_failed:
+ /* Can we fail with bonjour, or are we always waiting ? */
+ warn("connect to %s port %u (%s) failed",
+ nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote),
+ BONJOUR_PROTOCOL_NAME);
+ break;
+
+ case nw_connection_state_cancelled:
+ // Release the primary reference on the connection
+ // that was taken at creation time
+ nw_release(cnx);
+ break;
+
+ default: /* nw_connection_state_invalid */
+ /* Should never be called */
+ break;
}
nw_release(remote);
+ }
-}
-
-void
-on_connection_path_event(interface_t * interface, nw_interface_t iface,
- nw_connection_t cnx, nw_path_t path)
-{
+ void on_connection_path_event(interface_t * interface, nw_interface_t iface,
+ nw_connection_t cnx, nw_path_t path) {
#if 1
DEBUG("Connection [path changed]:\n");
- WITH_DEBUG({
- dump_connection(cnx, 1);
- });
+ WITH_DEBUG({ dump_connection(cnx, 1); });
#endif
- /* redundant *//*
- DEBUG(1, "Path:\n");
- dump_path(path, 2);
- */
-}
-
-/**
- * Enumerate main path interfaces
- *
- * We need to create specific dummy connections for each newly discovered
- * interface
- *
- * Currently we only use Bonjour/TCP for remote hICN discovery and connection
- * path monitoring.
- */
-void on_interface_event(interface_t * interface, nw_interface_t iface)
-{
+ /* redundant */ /*
+ DEBUG(1, "Path:\n");
+ dump_path(path, 2);
+ */
+ }
+
+ /**
+ * Enumerate main path interfaces
+ *
+ * We need to create specific dummy connections for each newly discovered
+ * interface
+ *
+ * Currently we only use Bonjour/TCP for remote hICN discovery and connection
+ * path monitoring.
+ */
+ void on_interface_event(interface_t * interface, nw_interface_t iface) {
/* We can create an hICN face on this interface that will be down until
* connected
* It is however possible to have two default gateways on the same
@@ -452,11 +442,10 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
/* nw_parameters_create_secure_{udp,tcp} */
nw_parameters_t parameters = nw_parameters_create_fn(
- NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */
- NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */);
+ NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */
+ NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */);
- if (!parameters)
- goto ERR_PARAMETERS;
+ if (!parameters) goto ERR_PARAMETERS;
nw_parameters_require_interface(parameters, iface);
nw_parameters_set_reuse_local_address(parameters, true);
@@ -467,49 +456,60 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
* available services on the local network using the parameters specified
* before.
*/
- nw_browse_descriptor_t descriptor = nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN);
+ nw_browse_descriptor_t descriptor =
+ nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE,
+ BONJOUR_SERVICE_DOMAIN);
if (!descriptor) {
- ERROR("[network_framework.on_interface_event] Failed to create a bonjour browse descriptor");
- goto ERR_DESCRIPTOR;
+ ERROR(
+ "[network_framework.on_interface_event] Failed to create a bonjour "
+ "browse descriptor");
+ goto ERR_DESCRIPTOR;
}
nw_browser_t browser = nw_browser_create(descriptor, parameters);
nw_browser_set_queue(browser, dispatch_get_main_queue());
- nw_browser_set_browse_results_changed_handler(browser, ^(nw_browse_result_t result, nw_browse_result_t result2, bool flag) {
- /* Dump result */
- printfi(0, "NEW BROWSE RESULT");
- printfi(1, "Result:");
- dump_browse_result(result, 2);
- printfi(1, "Result2:");
- dump_browse_result(result2, 2);
- printfi(1, "Flag: %s\n", (flag?"ON":"OFF"));
-
- /* Changes */
- nw_browse_result_change_t change = nw_browse_result_get_changes(result, result2);
- switch(change) {
- case nw_browse_result_change_identical:
- printfi(2, "The compared services are identical.");
- break;
- case nw_browse_result_change_result_added:
- printfi(2, "A new service was discovered.");
- break;
-
- case nw_browse_result_change_result_removed:
- printfi(2, "A previously discovered service was removed.");
- break;
-
- case nw_browse_result_change_txt_record_changed:
- printfi(2, "The service's associated TXT record changed.");
- break;
-
- case nw_browse_result_change_interface_added:
- printfi(2, "The service was discovered over a new interface.");
- break;
-
- case nw_browse_result_change_interface_removed:
- printfi(2, "The service was no longer discovered over a certain interface.");
- break;
- }
+ nw_browser_set_browse_results_changed_handler(browser, ^(
+ nw_browse_result_t result,
+ nw_browse_result_t
+ result2,
+ bool flag) {
+ /* Dump result */
+ printfi(0, "NEW BROWSE RESULT");
+ printfi(1, "Result:");
+ dump_browse_result(result, 2);
+ printfi(1, "Result2:");
+ dump_browse_result(result2, 2);
+ printfi(1, "Flag: %s\n", (flag ? "ON" : "OFF"));
+
+ /* Changes */
+ nw_browse_result_change_t change =
+ nw_browse_result_get_changes(result, result2);
+ switch (change) {
+ case nw_browse_result_change_identical:
+ printfi(2, "The compared services are identical.");
+ break;
+ case nw_browse_result_change_result_added:
+ printfi(2, "A new service was discovered.");
+ break;
+
+ case nw_browse_result_change_result_removed:
+ printfi(2, "A previously discovered service was removed.");
+ break;
+
+ case nw_browse_result_change_txt_record_changed:
+ printfi(2, "The service's associated TXT record changed.");
+ break;
+
+ case nw_browse_result_change_interface_added:
+ printfi(2, "The service was discovered over a new interface.");
+ break;
+
+ case nw_browse_result_change_interface_removed:
+ printfi(
+ 2,
+ "The service was no longer discovered over a certain interface.");
+ break;
+ }
});
nw_browser_start(browser);
@@ -524,20 +524,20 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
nw_endpoint_t endpoint;
DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s",
- BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN);
+ BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN);
endpoint = nw_endpoint_create_bonjour_service(
- BONJOUR_SERVICE_NAME,
- BONJOUR_SERVICE_TYPE,
- BONJOUR_SERVICE_DOMAIN);
+ BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN);
if (!endpoint) {
- ERROR("[network_framework.on_interface_event] Failed to create bound Bonjour connection");
- goto ERR_ENDPOINT;
+ ERROR(
+ "[network_framework.on_interface_event] Failed to create bound "
+ "Bonjour "
+ "connection");
+ goto ERR_ENDPOINT;
}
nw_connection_t connection = nw_connection_create(endpoint, parameters);
- if (!connection)
- goto ERR_CONNECTION;
+ if (!connection) goto ERR_CONNECTION;
nw_release(endpoint);
nw_release(parameters);
@@ -547,108 +547,98 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
/* Setup connection handlers */
- nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) {
- on_connection_state_event(interface, iface, connection, state, error);
- });
+ nw_connection_set_state_changed_handler(
+ connection, ^(nw_connection_state_t state, nw_error_t error) {
+ on_connection_state_event(interface, iface, connection, state, error);
+ });
nw_connection_set_path_changed_handler(connection, ^(nw_path_t path) {
- on_connection_path_event(interface, iface, connection, path);
+ on_connection_path_event(interface, iface, connection, path);
});
nw_connection_set_better_path_available_handler(connection, ^(bool value) {
#if 1
- DEBUG("Connection [better path = %s]\n", (value ? "true" : "false"));
- WITH_DEBUG({
- dump_connection(connection, 1);
- });
+ DEBUG("Connection [better path = %s]\n", (value ? "true" : "false"));
+ WITH_DEBUG({ dump_connection(connection, 1); });
#endif
});
nw_connection_set_viability_changed_handler(connection, ^(bool value) {
#if 1
- DEBUG("Connection [viable = %s]\n", (value ? "true" : "false"));
- WITH_DEBUG({
- //dump_connection(connection, 1);
- });
+ DEBUG("Connection [viable = %s]\n", (value ? "true" : "false"));
+ WITH_DEBUG({
+ // dump_connection(connection, 1);
+ });
#endif
- /*
- * This is the first time we have a connection with address and port
- * and thus the full identification of an hICN face
- */
- facelet_t * facelet = facelet_create_from_connection(connection);
- if (!facelet)
- return;
- facelet_set_event(facelet, value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE);
- interface_raise_event(interface, facelet);
-
+ /*
+ * This is the first time we have a connection with address and port
+ * and thus the full identification of an hICN face
+ */
+ facelet_t *facelet = facelet_create_from_connection(connection);
+ if (!facelet) return;
+ facelet_set_event(facelet,
+ value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE);
+ interface_raise_event(interface, facelet);
});
nw_connection_start(connection);
nw_connection_set_queue(connection, dispatch_get_main_queue());
- nw_retain(connection); // Hold a reference until cancelled
+ nw_retain(connection); // Hold a reference until cancelled
#if 1
DEBUG("Created Bonjour cnx on interface:");
- WITH_DEBUG({
- dump_interface(iface, 1);
- });
+ WITH_DEBUG({ dump_interface(iface, 1); });
#endif
return;
- nw_release(connection);
-ERR_CONNECTION:
+ nw_release(connection);
+ ERR_CONNECTION:
nw_release(endpoint);
-ERR_ENDPOINT:
+ ERR_ENDPOINT:
#if defined(MAC_OS_X_VERSION_10_15)
nw_release(descriptor);
-ERR_DESCRIPTOR:
+ ERR_DESCRIPTOR:
#endif /* defined(MAC_OS_X_VERSION_10_15) */
nw_release(parameters);
-ERR_PARAMETERS:
+ ERR_PARAMETERS:
return;
-}
+ }
-void on_path_event(interface_t * interface, nw_path_t path)
-{
+ void on_path_event(interface_t * interface, nw_path_t path) {
/* Simplification: we handle path event only once.
* Ideally, test whether we discover new interfaces or not
*/
#if 1
DEBUG("Path [event]:\n");
- WITH_DEBUG({
- dump_path(path, 1);
- });
+ WITH_DEBUG({ dump_path(path, 1); });
#endif
- nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t iface) {
- on_interface_event(interface, iface);
- return true;
- });
-
-}
+ nw_path_enumerate_interfaces(
+ path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t iface) {
+ on_interface_event(interface, iface);
+ return true;
+ });
+ }
-int nf_initialize(interface_t * interface, void * cfg)
-{
- nf_data_t * data = malloc(sizeof(nf_data_t));
- if (!data)
- goto ERR_MALLOC;
+ int nf_initialize(interface_t * interface, void *cfg) {
+ nf_data_t *data = malloc(sizeof(nf_data_t));
+ if (!data) goto ERR_MALLOC;
- if (cfg)
- data->cfg = * (network_framework_cfg_t *)cfg;
+ if (cfg) data->cfg = *(network_framework_cfg_t *)cfg;
data->pm = nw_path_monitor_create();
- if (!data->pm)
- goto ERR_PM;
+ if (!data->pm) goto ERR_PM;
nw_path_monitor_set_queue(data->pm, dispatch_get_main_queue());
- nw_path_monitor_set_cancel_handler(data->pm, ^() { });
+ nw_path_monitor_set_cancel_handler(data->pm, ^(){
+ });
nw_path_monitor_set_update_handler(data->pm, ^(nw_path_t path) {
- on_path_event(interface, path);
- });
+ on_path_event(interface, path);
+ });
// XXX NEEDED ?
nw_retain(data->pm);
@@ -659,25 +649,24 @@ int nf_initialize(interface_t * interface, void * cfg)
interface->data = data;
return 0;
-ERR_PM:
+ ERR_PM:
free(data);
-ERR_MALLOC:
+ ERR_MALLOC:
return -1;
-}
+ }
-int nf_finalize(interface_t * interface)
-{
- nf_data_t * data = (nf_data_t*)interface->data;
+ int nf_finalize(interface_t * interface) {
+ nf_data_t *data = (nf_data_t *)interface->data;
if (data->pm) {
- nw_path_monitor_cancel(data->pm);
- data->pm = NULL;
+ nw_path_monitor_cancel(data->pm);
+ data->pm = NULL;
}
return 0;
-}
-
-const interface_ops_t network_framework_ops = {
- .type = "network_framework",
- .initialize = nf_initialize,
- .finalize = nf_finalize,
- .on_event = NULL,
-};
+ }
+
+ const interface_ops_t network_framework_ops = {
+ .type = "network_framework",
+ .initialize = nf_initialize,
+ .finalize = nf_finalize,
+ .on_event = NULL,
+ };
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.h b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h
index edb35e904..768edc253 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.h
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,4 +19,5 @@
*/
typedef struct {
+ void *_;
} network_framework_cfg_t;
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt b/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt
index 8d18800db..43ba31b0b 100644
--- a/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
index 67edc5e39..5d2f695f9 100644
--- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
+++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -34,20 +34,21 @@
#define PC_DEFAULT_PORT 9533
typedef struct {
- priority_controller_cfg_t cfg;
- int fd;
+ priority_controller_cfg_t cfg;
+ int fd;
#ifdef PRIORITY_CONTROLLER_INTERNAL
- unsigned state;
- JNIEnv * env;
- jclass cls;
- jmethodID mid;
+ unsigned state;
+ JNIEnv *env;
+ jclass cls;
+ jmethodID mid;
#endif /* PRIORITY_CONTROLLER_INTERNAL */
} pc_data_t;
#ifdef PRIORITY_CONTROLLER_INTERNAL
#include <jni.h>
-#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
+#define ERR_STR_JAVA \
+ "Java VM parameters are required in the interface configuration."
#define PREFER_CELLULAR 0
#define PREFER_WIFI 1
@@ -55,147 +56,146 @@ typedef struct {
#define INTERVAL_MS 500
-const char * prefer_str[] = { "Cellular", "WiFi", "both" };
+const char *prefer_str[] = {"Cellular", "WiFi", "both"};
-jclass find_class_global(JNIEnv* env, const char *name){
- jclass c = (*env)->FindClass(env, name);
- jclass c_global = 0;
- if (c){
- c_global = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- }
- return c_global;
+jclass find_class_global(JNIEnv *env, const char *name) {
+ jclass c = (*env)->FindClass(env, name);
+ jclass c_global = 0;
+ if (c) {
+ c_global = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return c_global;
}
+int priority_controller_tick(interface_t *interface, int fd, void *unused) {
+ pc_data_t *data = (pc_data_t *)interface->data;
+ unsigned new_state = PREFER_BOTH;
-int priority_controller_tick(interface_t * interface, int fd, void * unused)
-{
- pc_data_t * data = (pc_data_t*)interface->data;
- unsigned new_state = PREFER_BOTH;
-
- jint rssi = (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid);
- DEBUG("[priority_controller_tick] rssi=%d\n", rssi);
- if (rssi > -67) {
- new_state = PREFER_WIFI;
+ jint rssi =
+ (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid);
+ DEBUG("[priority_controller_tick] rssi=%d\n", rssi);
+ if (rssi > -67) {
+ new_state = PREFER_WIFI;
#if 0
} else if ((rssi < -67) && (rssi > -70)) {
new_state = PREFER_BOTH;
#endif
- } else { /* rssi < -70 */
- new_state = PREFER_CELLULAR;
- }
+ } else { /* rssi < -70 */
+ new_state = PREFER_CELLULAR;
+ }
- if (new_state == data->state)
- return 0;
+ if (new_state == data->state) return 0;
- ERROR("[priority_controller_tick] Setting priority to %s", prefer_str[new_state]);
+ ERROR("[priority_controller_tick] Setting priority to %s",
+ prefer_str[new_state]);
- /* XXX Factor this */
+ /* XXX Factor this */
- facelet_t * facelet_w = facelet_create();
- facelet_t * facelet_c = facelet_create();
- facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI);
- facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR);
- facelet_set_attr_clean(facelet_w);
- facelet_set_attr_clean(facelet_c);
+ facelet_t *facelet_w = facelet_create();
+ facelet_t *facelet_c = facelet_create();
+ facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI);
+ facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR);
+ facelet_set_attr_clean(facelet_w);
+ facelet_set_attr_clean(facelet_c);
- switch(new_state) {
- case PREFER_CELLULAR:
- facelet_set_priority(facelet_w, 0);
- facelet_set_priority(facelet_c, 10);
- break;
- case PREFER_WIFI:
- facelet_set_priority(facelet_w, 10);
- facelet_set_priority(facelet_c, 0);
- break;
- case PREFER_BOTH:
- facelet_set_priority(facelet_w, 0);
- facelet_set_priority(facelet_c, 0);
- break;
- }
+ switch (new_state) {
+ case PREFER_CELLULAR:
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 10);
+ break;
+ case PREFER_WIFI:
+ facelet_set_priority(facelet_w, 10);
+ facelet_set_priority(facelet_c, 0);
+ break;
+ case PREFER_BOTH:
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 0);
+ break;
+ }
- facelet_set_event(facelet_w, FACELET_EVENT_UPDATE);
- facelet_set_event(facelet_c, FACELET_EVENT_UPDATE);
+ facelet_set_event(facelet_w, FACELET_EVENT_UPDATE);
+ facelet_set_event(facelet_c, FACELET_EVENT_UPDATE);
- interface_raise_event(interface, facelet_w);
- interface_raise_event(interface, facelet_c);
+ interface_raise_event(interface, facelet_w);
+ interface_raise_event(interface, facelet_c);
- data->state = new_state;
+ data->state = new_state;
- return 0;
+ return 0;
}
#endif /* PRIORITY_CONTROLLER_INTERNAL */
-int priority_controller_initialize(interface_t * interface, void * cfg)
-{
- INFO("Initializing priority controller");
+int priority_controller_initialize(interface_t *interface, void *cfg) {
+ INFO("Initializing priority controller");
- pc_data_t * data = malloc(sizeof(pc_data_t));
- if (!data) {
- INFO("Priority controller data memory allocation error");
- goto ERR_MALLOC;
- }
+ pc_data_t *data = malloc(sizeof(pc_data_t));
+ if (!data) {
+ INFO("Priority controller data memory allocation error");
+ goto ERR_MALLOC;
+ }
- interface->data = data;
+ interface->data = data;
- data->cfg = * (priority_controller_cfg_t *) cfg;
+ data->cfg = *(priority_controller_cfg_t *)cfg;
#ifdef PRIORITY_CONTROLLER_INTERNAL
- if (!cfg) {
- ERROR(ERR_STR_JAVA);
- goto ERR_CFG;
- }
-
- /* Retrieve RSSI information from SDK through AndroidUtility class */
- (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL);
- data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS);
- if (data->cls == 0)
- goto ERR_JAVA;
- data->mid = (*data->env)->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I");
-
- data->fd = interface_register_timer(interface, INTERVAL_MS,
- priority_controller_tick, interface);
- if (data->fd < 0) {
- ERROR("[priority_controller_initialize] Could not initialize timer");
- goto ERR_FD;
- }
- data->state = PREFER_BOTH;
+ if (!cfg) {
+ ERROR(ERR_STR_JAVA);
+ goto ERR_CFG;
+ }
+
+ /* Retrieve RSSI information from SDK through AndroidUtility class */
+ (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL);
+ data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS);
+ if (data->cls == 0) goto ERR_JAVA;
+ data->mid =
+ (*data->env)
+ ->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I");
+
+ data->fd = interface_register_timer(interface, INTERVAL_MS,
+ priority_controller_tick, interface);
+ if (data->fd < 0) {
+ ERROR("[priority_controller_initialize] Could not initialize timer");
+ goto ERR_FD;
+ }
+ data->state = PREFER_BOTH;
#else /* PRIORITY_CONTROLLER_INTERNAL */
- struct sockaddr_in addr;
-
- data->fd = socket(AF_INET, SOCK_DGRAM, 0);
- //data->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (data->fd < 0) {
- INFO("Priority controller socket error");
- perror("socket error");
- goto ERR_SOCKET;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- addr.sin_port = htons(PC_DEFAULT_PORT);
-
- if (bind(data->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- INFO("Priority controller socket bind error");
- perror("bind error");
- goto ERR_BIND;
- }
-
- DEBUG("[priority_controller_initialize] register fd");
- if (interface_register_fd(interface, data->fd, NULL) < 0) {
- ERROR("[priority_controller_initialize] Error registering fd");
- goto ERR_FD;
- }
+ struct sockaddr_in addr;
+
+ data->fd = socket(AF_INET, SOCK_DGRAM, 0);
+ // data->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (data->fd < 0) {
+ INFO("Priority controller socket error");
+ perror("socket error");
+ goto ERR_SOCKET;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ addr.sin_port = htons(PC_DEFAULT_PORT);
+
+ if (bind(data->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ INFO("Priority controller socket bind error");
+ perror("bind error");
+ goto ERR_BIND;
+ }
+
+ DEBUG("[priority_controller_initialize] register fd");
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[priority_controller_initialize] Error registering fd");
+ goto ERR_FD;
+ }
#endif /* PRIORITY_CONTROLLER_INTERNAL */
- INFO("Priority controller successfully initialized");
- return 0;
+ INFO("Priority controller successfully initialized");
+ return 0;
#ifdef PRIORITY_CONTROLLER_INTERNAL
ERR_CFG:
@@ -204,86 +204,86 @@ ERR_JAVA:
ERR_FD:
#ifndef PRIORITY_CONTROLLER_INTERNAL
ERR_BIND:
- close(data->fd);
+ close(data->fd);
ERR_SOCKET:
#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
- free(data);
+ free(data);
ERR_MALLOC:
- return -1;
+ return -1;
}
-int priority_controller_finalize(interface_t * interface)
-{
- pc_data_t * data = (pc_data_t*)interface->data;
+int priority_controller_finalize(interface_t *interface) {
+ pc_data_t *data = (pc_data_t *)interface->data;
#ifdef PRIORITY_CONTROLLER_INTERNAL
- DEBUG("[priority_controller_finalize] unregister timer");
- interface_unregister_timer(interface, data->fd);
+ DEBUG("[priority_controller_finalize] unregister timer");
+ interface_unregister_timer(interface, data->fd);
#else
- if (data->fd > 0) {
- interface_unregister_fd(interface, data->fd);
- close(data->fd);
- }
- free(data);
+ if (data->fd > 0) {
+ interface_unregister_fd(interface, data->fd);
+ close(data->fd);
+ }
+ free(data);
#endif /* PRIORITY_CONTROLLER_INTERNAL */
- return 0;
+ return 0;
}
#ifndef PRIORITY_CONTROLLER_INTERNAL
-int priority_controller_callback(interface_t * interface, int fd, void * unused)
-{
- pc_data_t * data = (pc_data_t*)interface->data;
- char buf[100];
- int rc;
-
- INFO("Priority controller receiving command");
-
- rc = recv(data->fd, buf, 100, 0);
-
- if (rc < 0) {
- INFO("Priority controller read error");
- return -1;
- }
-
- INFO("Priority controller received command: %02X", buf[0]);
-
- facelet_t * facelet_w = facelet_create();
- facelet_t * facelet_c = facelet_create();
- facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI);
- facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR);
- facelet_set_attr_clean(facelet_w);
- facelet_set_attr_clean(facelet_c);
- switch(buf[0]) {
- case '\0':
- facelet_set_priority(facelet_w, 0);
- facelet_set_priority(facelet_c, 10);
- INFO("Priority controller configuring Cellular preferred");
- break;
- case '\1':
- facelet_set_priority(facelet_w, 10);
- facelet_set_priority(facelet_c, 0);
- INFO("Priority controller configuring Wi-Fi preferred");
- break;
- case '\2':
- facelet_set_priority(facelet_w, 0);
- facelet_set_priority(facelet_c, 0);
- INFO("Priority controller configuring both Cellular and Wi-Fi preferred");
- break;
- default:
- INFO("Priority controller invalid data received from updown server. Ignoring...");
- facelet_free(facelet_w);
- facelet_free(facelet_c);
- return 0;
- }
-
- facelet_set_event(facelet_w, FACELET_EVENT_UPDATE);
- facelet_set_event(facelet_c, FACELET_EVENT_UPDATE);
-
- interface_raise_event(interface, facelet_w);
- interface_raise_event(interface, facelet_c);
-
- return 0;
+int priority_controller_callback(interface_t *interface, int fd, void *unused) {
+ pc_data_t *data = (pc_data_t *)interface->data;
+ char buf[100];
+ int rc;
+
+ INFO("Priority controller receiving command");
+
+ rc = recv(data->fd, buf, 100, 0);
+
+ if (rc < 0) {
+ INFO("Priority controller read error");
+ return -1;
+ }
+
+ INFO("Priority controller received command: %02X", buf[0]);
+
+ facelet_t *facelet_w = facelet_create();
+ facelet_t *facelet_c = facelet_create();
+ facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI);
+ facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR);
+ facelet_set_attr_clean(facelet_w);
+ facelet_set_attr_clean(facelet_c);
+ switch (buf[0]) {
+ case '\0':
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 10);
+ INFO("Priority controller configuring Cellular preferred");
+ break;
+ case '\1':
+ facelet_set_priority(facelet_w, 10);
+ facelet_set_priority(facelet_c, 0);
+ INFO("Priority controller configuring Wi-Fi preferred");
+ break;
+ case '\2':
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 0);
+ INFO("Priority controller configuring both Cellular and Wi-Fi preferred");
+ break;
+ default:
+ INFO(
+ "Priority controller invalid data received from updown server. "
+ "Ignoring...");
+ facelet_free(facelet_w);
+ facelet_free(facelet_c);
+ return 0;
+ }
+
+ facelet_set_event(facelet_w, FACELET_EVENT_UPDATE);
+ facelet_set_event(facelet_c, FACELET_EVENT_UPDATE);
+
+ interface_raise_event(interface, facelet_w);
+ interface_raise_event(interface, facelet_c);
+
+ return 0;
}
#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
index 247fc3c57..7f257ffcf 100644
--- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
+++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -21,7 +21,8 @@
#ifndef FACEMGR_INTERFACE_PRIORITY_CONTROLLER
#define FACEMGR_INTERFACE_PRIORITY_CONTROLLER
-#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
+#define FACEMGR_UTILITY_CLASS \
+ "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
/*
* Uncomment this line to use a Priority controller interface internal to the
@@ -36,10 +37,9 @@
typedef struct {
#ifdef __ANDROID__
#ifdef PRIORITY_CONTROLLER_INTERNAL
- JavaVM * jvm;
+ JavaVM* jvm;
#endif /* PRIORITY_CONTROLLER_INTERNAL */
#endif /* __ANDROID__ */
} priority_controller_cfg_t;
-
#endif /* FACEMGR_INTERFACE_PRIORITY_CONTROLLER */
diff --git a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt
index e5fd2167e..4c6c0ea6c 100644
--- a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt
+++ b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/facemgr/src/interfaces/updown/updown.c b/ctrl/facemgr/src/interfaces/updown/updown.c
index 7d305a5cd..8d31f6cd4 100644
--- a/ctrl/facemgr/src/interfaces/updown/updown.c
+++ b/ctrl/facemgr/src/interfaces/updown/updown.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <hicn/facemgr.h>
+#include <hicn/util/sstrncpy.h>
#include "../../common.h"
#include "../../interface.h"
@@ -37,107 +38,101 @@
#define UNIX_PATH "\0updownsrv"
typedef struct {
- int fd; /* Unix client socket */
+ int fd; /* Unix client socket */
} updown_data_t;
-int updown_initialize(interface_t * interface, void * cfg)
-{
- struct sockaddr_un addr;
- char * socket_path = UNIX_PATH;
-
- updown_data_t * data = malloc(sizeof(updown_data_t));
- if (!data)
- goto ERR_MALLOC;
- interface->data = data;
-
- data->fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (data->fd == -1) {
- perror("socket error");
- goto ERR_SOCKET;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- if (*socket_path == '\0') {
- *addr.sun_path = '\0';
- strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2);
- } else {
- strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
- }
-
- if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
- perror("connect error");
- goto ERR_CONNECT;
- }
-
- if (interface_register_fd(interface, data->fd, NULL) < 0) {
- ERROR("[updown_initialize] Error registering fd");
- goto ERR_FD;
- }
-
- return 0;
+int updown_initialize(interface_t* interface, void* cfg) {
+ struct sockaddr_un addr;
+ char* socket_path = UNIX_PATH;
+
+ updown_data_t* data = malloc(sizeof(updown_data_t));
+ if (!data) goto ERR_MALLOC;
+ interface->data = data;
+
+ data->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (data->fd == -1) {
+ perror("socket error");
+ goto ERR_SOCKET;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (*socket_path == '\0') {
+ *addr.sun_path = '\0';
+ strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, socket_path + 1);
+ } else {
+ strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, socket_path);
+ }
+
+ if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ perror("connect error");
+ goto ERR_CONNECT;
+ }
+
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[updown_initialize] Error registering fd");
+ goto ERR_FD;
+ }
+
+ return 0;
ERR_FD:
ERR_CONNECT:
- close(data->fd);
+ close(data->fd);
ERR_SOCKET:
- free(data);
+ free(data);
ERR_MALLOC:
- return -1;
+ return -1;
}
-int updown_finalize(interface_t * interface)
-{
- updown_data_t * data = (updown_data_t*)interface->data;
+int updown_finalize(interface_t* interface) {
+ updown_data_t* data = (updown_data_t*)interface->data;
- if (data->fd > 0)
- close(data->fd);
- free(data);
+ if (data->fd > 0) close(data->fd);
+ free(data);
- return 0;
+ return 0;
}
-int updown_callback(interface_t * interface, int fd, void * unused)
-{
- updown_data_t * data = (updown_data_t*)interface->data;
- char buf[100];
- int rc;
-
- rc = read(data->fd, buf, sizeof(buf));
- if (rc < 0)
- return -1;
-
- /*
- * If the process is paused (eg. in a debugger, we might have more than one
- * read.
- * XXX how big is the buffer
- * XXX shall we drain the queue if it exceeds buffer size ?
- */
- //assert(rc == 1);
-
- /* Raise facelet update event */
- facelet_t * facelet = facelet_create();
- facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); //CELLULAR);
- facelet_set_attr_clean(facelet);
- switch(buf[0]) {
- case '\0':
- facelet_set_admin_state(facelet, FACE_STATE_DOWN);
- break;
- case '\1':
- facelet_set_admin_state(facelet, FACE_STATE_UP);
- break;
- break;
- default:
- ERROR("Invalid data received from updown server. Ignoring...");
- facelet_free(facelet);
- return -1;
- }
-
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
-
- interface_raise_event(interface, facelet);
-
- return 0;
+int updown_callback(interface_t* interface, int fd, void* unused) {
+ updown_data_t* data = (updown_data_t*)interface->data;
+ char buf[100];
+ int rc;
+
+ rc = read(data->fd, buf, sizeof(buf));
+ if (rc < 0) return -1;
+
+ /*
+ * If the process is paused (eg. in a debugger, we might have more than one
+ * read.
+ * XXX how big is the buffer
+ * XXX shall we drain the queue if it exceeds buffer size ?
+ */
+ // assert(rc == 1);
+
+ /* Raise facelet update event */
+ facelet_t* facelet = facelet_create();
+ facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); // CELLULAR);
+ facelet_set_attr_clean(facelet);
+ switch (buf[0]) {
+ case '\0':
+ facelet_set_admin_state(facelet, FACE_STATE_DOWN);
+ break;
+ case '\1':
+ facelet_set_admin_state(facelet, FACE_STATE_UP);
+ break;
+ break;
+ default:
+ ERROR("Invalid data received from updown server. Ignoring...");
+ facelet_free(facelet);
+ return -1;
+ }
+
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+
+ interface_raise_event(interface, facelet);
+
+ return 0;
}
interface_ops_t updown_ops = {
diff --git a/ctrl/facemgr/src/loop_dispatcher.c b/ctrl/facemgr/src/loop_dispatcher.c
index 499a1ccac..ed4540f5c 100644
--- a/ctrl/facemgr/src/loop_dispatcher.c
+++ b/ctrl/facemgr/src/loop_dispatcher.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -33,52 +33,36 @@
#include <hicn/facemgr/loop.h>
#include <hicn/util/log.h>
-struct loop_s {
-};
+struct loop_s {};
-loop_t *
-loop_create()
-{
- loop_t * loop = malloc(sizeof(loop_t));
- if (!loop) {
- ERROR("[loop_create] Failed to allocate memory");
- goto ERR_MALLOC;
- }
- return loop;
+loop_t* loop_create() {
+ loop_t* loop = malloc(sizeof(loop_t));
+ if (!loop) {
+ ERROR("[loop_create] Failed to allocate memory");
+ goto ERR_MALLOC;
+ }
+ return loop;
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-void
-loop_free(loop_t * loop)
-{
- /* Nothing to do */
+void loop_free(loop_t* loop) { /* Nothing to do */
}
-int
-loop_dispatch(loop_t * loop)
-{
- dispatch_main();
- return 0;
+int loop_dispatch(loop_t* loop) {
+ dispatch_main();
+ return 0;
}
-int
-loop_undispatch(loop_t * loop)
-{
- /* Nothing to do */
- return 0;
+int loop_undispatch(loop_t* loop) {
+ /* Nothing to do */
+ return 0;
}
-void
-loop_break(loop_t * loop)
-{
- exit(0);
-}
+void loop_break(loop_t* loop) { exit(0); }
-int
-loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data)
-{
- INFO("loop_callback not (yet) implemented");
- return 0;
+int loop_callback(loop_t* loop, facemgr_cb_type_t type, void* data) {
+ INFO("loop_callback not (yet) implemented");
+ return 0;
}
diff --git a/ctrl/facemgr/src/loop_libevent.c b/ctrl/facemgr/src/loop_libevent.c
index 674eee905..b619e02e6 100644
--- a/ctrl/facemgr/src/loop_libevent.c
+++ b/ctrl/facemgr/src/loop_libevent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,13 +25,13 @@
#include <assert.h>
#include <event2/event.h>
#include <event2/thread.h>
-#include <fcntl.h> // fcntl
+#include <fcntl.h> // fcntl
#ifdef WITH_THREAD
#include <pthread.h>
#endif /* WITH_THREAD */
#include <stdlib.h>
#include <sys/timerfd.h>
-#include <unistd.h> // fcntl
+#include <unistd.h> // fcntl
#include <hicn/facemgr/api.h>
#include <hicn/util/log.h>
@@ -43,160 +43,150 @@
* \brief Holds all callback parameters
*/
typedef struct {
- void * owner;
- fd_callback_t callback;
- void * data;
+ void *owner;
+ fd_callback_t callback;
+ void *data;
} cb_wrapper_args_t;
TYPEDEF_MAP_H(event_map, int, struct event *);
-TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf, generic_snprintf);
+TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf,
+ generic_snprintf);
/* Map that associates timer fds with their associated cb_wrapper_args_t */
TYPEDEF_MAP_H(timer_fd_map, int, cb_wrapper_args_t *);
-TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf, generic_snprintf);
+TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf,
+ generic_snprintf);
struct loop_s {
- struct event_base * event_base;
- event_map_t * event_map;
- timer_fd_map_t * timer_fd_map;
+ struct event_base *event_base;
+ event_map_t *event_map;
+ timer_fd_map_t *timer_fd_map;
#ifdef WITH_THREAD
- pthread_t thread;
+ pthread_t thread;
#endif /* WITH_THREAD */
};
/* Forward declarations */
-int _loop_unregister_fd(loop_t * loop, int fd);
-int _loop_unregister_timer(loop_t * loop, int fd);
-
-loop_t *
-loop_create()
-{
- loop_t * loop = malloc(sizeof(loop_t));
- if (!loop) {
- ERROR("[loop_create] Failed to allocate memory");
- goto ERR_MALLOC;
- }
+int _loop_unregister_fd(loop_t *loop, int fd);
+int _loop_unregister_timer(loop_t *loop, int fd);
+
+loop_t *loop_create() {
+ loop_t *loop = malloc(sizeof(loop_t));
+ if (!loop) {
+ ERROR("[loop_create] Failed to allocate memory");
+ goto ERR_MALLOC;
+ }
#ifdef WITH_THREAD
- evthread_use_pthreads();
+ evthread_use_pthreads();
#endif /* WITH_THREAD */
- loop->event_base = event_base_new();
- if (!loop)
- goto ERR_EVENT;
+ loop->event_base = event_base_new();
+ if (!loop) goto ERR_EVENT;
- loop->event_map = event_map_create();
- if (!loop->event_map) {
- ERROR("[loop_create] Failed to create event_map");
- goto ERR_EVENT_MAP;
- }
+ loop->event_map = event_map_create();
+ if (!loop->event_map) {
+ ERROR("[loop_create] Failed to create event_map");
+ goto ERR_EVENT_MAP;
+ }
- loop->timer_fd_map = timer_fd_map_create();
- if (!loop->timer_fd_map) {
- ERROR("[loop_create] Failed to create timer_fd_map");
- goto ERR_TIMER_FD_MAP;
- }
+ loop->timer_fd_map = timer_fd_map_create();
+ if (!loop->timer_fd_map) {
+ ERROR("[loop_create] Failed to create timer_fd_map");
+ goto ERR_TIMER_FD_MAP;
+ }
- event_set_log_callback(NULL);
+ event_set_log_callback(NULL);
- return loop;
+ return loop;
- timer_fd_map_free(loop->timer_fd_map);
ERR_TIMER_FD_MAP:
- event_map_free(loop->event_map);
+ event_map_free(loop->event_map);
ERR_EVENT_MAP:
- event_base_free(loop->event_base);
+ event_base_free(loop->event_base);
ERR_EVENT:
- free(loop);
+ free(loop);
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-void
-loop_free(loop_t * loop)
-{
- /*
- * Release all timer cb_wrapper_args_t
- *
- * We need to stop all timers, this should release associated fd events at
- * the same time... for that reason, this code has to be called before
- * releasing events
- */
-
- int * timer_fd_map_array;
- int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array);
- if (n < 0) {
- ERROR("[loop_free] Could not get event map array");
- } else {
- for (unsigned i = 0; i < n; i++) {
- int fd = timer_fd_map_array[i];
- if (_loop_unregister_timer(loop, fd) < 0) {
- ERROR("[loop_free] Could not unregister timer");
- }
- }
- free(timer_fd_map_array);
+void loop_free(loop_t *loop) {
+ /*
+ * Release all timer cb_wrapper_args_t
+ *
+ * We need to stop all timers, this should release associated fd events at
+ * the same time... for that reason, this code has to be called before
+ * releasing events
+ */
+
+ int *timer_fd_map_array;
+ int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array);
+ if (n < 0) {
+ ERROR("[loop_free] Could not get event map array");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ int fd = timer_fd_map_array[i];
+ if (_loop_unregister_timer(loop, fd) < 0) {
+ ERROR("[loop_free] Could not unregister timer");
+ }
}
- timer_fd_map_free(loop->timer_fd_map);
-
- /* Release all events */
-
- int * event_map_array;
- n = event_map_get_key_array(loop->event_map, &event_map_array);
- if (n < 0) {
- ERROR("[loop_free] Could not get event map array");
- } else {
- for (unsigned i = 0; i < n; i++) {
- int fd = event_map_array[i];
- if (_loop_unregister_fd(loop, fd) < 0) {
- ERROR("[loop_free] Could not unregister fd");
- }
- }
- free(event_map_array);
+ free(timer_fd_map_array);
+ }
+ timer_fd_map_free(loop->timer_fd_map);
+
+ /* Release all events */
+
+ int *event_map_array;
+ n = event_map_get_key_array(loop->event_map, &event_map_array);
+ if (n < 0) {
+ ERROR("[loop_free] Could not get event map array");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ int fd = event_map_array[i];
+ if (_loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[loop_free] Could not unregister fd");
+ }
}
- event_map_free(loop->event_map);
+ free(event_map_array);
+ }
+ event_map_free(loop->event_map);
- event_base_free(loop->event_base);
+ event_base_free(loop->event_base);
- free(loop);
+ free(loop);
}
-int
-loop_dispatch(loop_t * loop)
-{
+int loop_dispatch(loop_t *loop) {
#ifdef WITH_THREAD
- if (pthread_create(&loop->thread, NULL, (void * (*)(void *))event_base_dispatch, loop->event_base)) {
- fprintf(stderr, "Error creating thread\n");
- return -1;
- }
+ if (pthread_create(&loop->thread, NULL,
+ (void *(*)(void *))event_base_dispatch,
+ loop->event_base)) {
+ fprintf(stderr, "Error creating thread\n");
+ return -1;
+ }
#else
- event_base_dispatch(loop->event_base);
+ event_base_dispatch(loop->event_base);
#endif /* WITH_THREAD */
- return 0;
+ return 0;
}
-int
-loop_undispatch(loop_t * loop)
-{
+int loop_undispatch(loop_t *loop) {
#ifdef WITH_THREAD
- DEBUG("Waiting for loop to terminate...");
- if(pthread_join(loop->thread, NULL)) {
- fprintf(stderr, "Error joining thread\n");
- return -1;
- }
- DEBUG("Loop terminated !");
+ DEBUG("Waiting for loop to terminate...");
+ if (pthread_join(loop->thread, NULL)) {
+ ERROR("Error joining thread\n");
+ return -1;
+ }
+ DEBUG("Loop terminated !");
#endif /* WITH_THREAD */
- return 0;
+ return 0;
}
-void
-loop_break(loop_t * loop)
-{
- event_base_loopbreak(loop->event_base);
-}
+void loop_break(loop_t *loop) { event_base_loopbreak(loop->event_base); }
-void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
- cb_wrapper_args_t * cb_wrapper_args = arg;
- cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data);
+void cb_wrapper(evutil_socket_t fd, short what, void *arg) {
+ cb_wrapper_args_t *cb_wrapper_args = arg;
+ cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data);
}
/**
@@ -208,42 +198,41 @@ void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
* \param [in] callback_data - User data to pass alongside callback invocation
* \return 0 in case of success, -1 otherwise
*/
-int
-_loop_register_fd(loop_t * loop, int fd, void * callback_owner,
- fd_callback_t callback, void * callback_data)
-{
- /* This will be freed with the event */
- cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
- *cb_wrapper_args = (cb_wrapper_args_t) {
- .owner = callback_owner,
- .callback = callback,
- .data = callback_data,
- };
-
- evutil_make_socket_nonblocking(fd);
- struct event * event = event_new(loop->event_base, fd, EV_READ | EV_PERSIST, cb_wrapper, cb_wrapper_args);
- if (!event) {
- ERROR("[_loop_register_fd] event_new");
- goto ERR_EVENT_NEW;
- }
-
- if (event_add(event, NULL) < 0) {
- ERROR("[_loop_register_fd] event_add");
- goto ERR_EVENT_ADD;
- }
-
- if (event_map_add(loop->event_map, fd, event) < 0) {
- ERROR("[_loop_register_fd] event_map_add");
- goto ERR_EVENT_MAP;
- }
-
- return 0;
+int _loop_register_fd(loop_t *loop, int fd, void *callback_owner,
+ fd_callback_t callback, void *callback_data) {
+ /* This will be freed with the event */
+ cb_wrapper_args_t *cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t){
+ .owner = callback_owner,
+ .callback = callback,
+ .data = callback_data,
+ };
+
+ evutil_make_socket_nonblocking(fd);
+ struct event *event = event_new(loop->event_base, fd, EV_READ | EV_PERSIST,
+ cb_wrapper, cb_wrapper_args);
+ if (!event) {
+ ERROR("[_loop_register_fd] event_new");
+ goto ERR_EVENT_NEW;
+ }
+
+ if (event_add(event, NULL) < 0) {
+ ERROR("[_loop_register_fd] event_add");
+ goto ERR_EVENT_ADD;
+ }
+
+ if (event_map_add(loop->event_map, fd, event) < 0) {
+ ERROR("[_loop_register_fd] event_map_add");
+ goto ERR_EVENT_MAP;
+ }
+
+ return 0;
ERR_EVENT_MAP:
ERR_EVENT_ADD:
- event_free(event);
+ event_free(event);
ERR_EVENT_NEW:
- return -1;
+ return -1;
}
/**
@@ -251,183 +240,169 @@ ERR_EVENT_NEW:
* \param [in] fd - File descriptor to unregister
* \return 0 in case of success, -1 otherwise
*/
-int
-_loop_unregister_fd(loop_t * loop, int fd)
-{
- struct event * event = NULL;
+int _loop_unregister_fd(loop_t *loop, int fd) {
+ struct event *event = NULL;
- if (event_map_remove(loop->event_map, fd, &event) < 0) {
- ERROR("[_loop_unregister_fd] Error removing event associated to fd");
- return -1;
- }
+ if (event_map_remove(loop->event_map, fd, &event) < 0) {
+ ERROR("[_loop_unregister_fd] Error removing event associated to fd");
+ return -1;
+ }
- assert(event);
+ assert(event);
- cb_wrapper_args_t * cb_wrapper_args = event_get_callback_arg(event);
- free(cb_wrapper_args);
+ cb_wrapper_args_t *cb_wrapper_args = event_get_callback_arg(event);
+ free(cb_wrapper_args);
- event_del(event);
- event_free(event);
+ event_del(event);
+ event_free(event);
- return 0;
+ return 0;
}
-int
-loop_timer_callback(loop_t * loop, int fd, void * data)
-{
- char buf[1024]; /* size is not important */
- cb_wrapper_args_t * cb_wrapper_args = data;
- while (read(fd, &buf, sizeof(buf)) > 0)
- ;
+int loop_timer_callback(loop_t *loop, int fd, void *data) {
+ char buf[1024]; /* size is not important */
+ cb_wrapper_args_t *cb_wrapper_args = data;
+ while (read(fd, &buf, sizeof(buf)) > 0)
+ ;
- int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd,
- cb_wrapper_args->data);
+ int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd,
+ cb_wrapper_args->data);
- return rc;
+ return rc;
}
-int
-_loop_register_timer(loop_t * loop, timer_callback_data_t * timer_callback_data)
-{
- int fd = timerfd_create(CLOCK_MONOTONIC, 0);
- if (fd == -1) {
- perror("timerfd_create");
- return -1;
- }
+int _loop_register_timer(loop_t *loop,
+ timer_callback_data_t *timer_callback_data) {
+ int fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd == -1) {
+ perror("timerfd_create");
+ return -1;
+ }
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- perror("fcntl");
- return -1;
- }
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ return -1;
+ }
+
+ struct itimerspec ts = {
+ .it_interval =
+ {
+ .tv_sec = timer_callback_data->delay_ms / 1000,
+ .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000,
+ },
+ .it_value = {
+ .tv_sec = timer_callback_data->delay_ms / 1000,
+ .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000,
+ }};
+
+ if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
+ perror("timerfd_settime");
+ return -1;
+ }
+
+ /* This should be freed together with the timer release */
+ cb_wrapper_args_t *cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t){
+ .owner = timer_callback_data->owner,
+ .callback = timer_callback_data->callback,
+ .data = timer_callback_data->data,
+ };
+
+ if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) {
+ ERROR("[_loop_register_timer] Could not add cb_wrapper to timer map");
+ return -1;
+ }
- struct itimerspec ts = {
- .it_interval = {
- .tv_sec = timer_callback_data->delay_ms / 1000,
- .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000,
- },
- .it_value = {
- .tv_sec = timer_callback_data->delay_ms / 1000,
- .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000,
- }
- };
-
- if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
- perror("timerfd_settime");
- return -1;
- }
+ if (_loop_register_fd(loop, fd, loop, (fd_callback_t)loop_timer_callback,
+ cb_wrapper_args) < 0) {
+ ERROR("[_loop_register_timer] Error registering fd to event loop");
+ return -1;
+ }
- /* This should be freed together with the timer release */
- cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
- *cb_wrapper_args = (cb_wrapper_args_t) {
- .owner = timer_callback_data->owner,
- .callback = timer_callback_data->callback,
- .data = timer_callback_data->data,
- };
+ return fd;
+}
- if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) {
- ERROR("[_loop_register_timer] Could not add cb_wrapper to timer map");
- return -1;
- }
+int _loop_unregister_timer(loop_t *loop, int fd) {
+ struct itimerspec ts = {.it_interval =
+ {
+ .tv_sec = 0,
+ .tv_nsec = 0,
+ },
+ .it_value = {
+ /* This value disables the timer */
+ .tv_sec = 0,
+ .tv_nsec = 0,
+ }};
+ ts.it_value.tv_sec = 0;
+
+ if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
+ perror("timerfd_settime");
+ return -1;
+ }
- if (_loop_register_fd(loop, fd, loop,
- (fd_callback_t) loop_timer_callback, cb_wrapper_args) < 0) {
- ERROR("[_loop_register_timer] Error registering fd to event loop");
- return -1;
- }
+ cb_wrapper_args_t *cb_wrapper_args;
+ if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) {
+ ERROR(
+ "[_loop_unregister_timer] Could not remove cb_wrapper from timer map");
+ return -1;
+ }
+ assert(cb_wrapper_args);
+ free(cb_wrapper_args);
+
+ if (_loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[_loop_unregister_timer] Error unregistering fd from event loop");
+ return -1;
+ }
- return fd;
+ close(fd);
+
+ return 0;
}
-int
-_loop_unregister_timer(loop_t * loop, int fd)
-{
- struct itimerspec ts = {
- .it_interval = {
- .tv_sec = 0,
- .tv_nsec = 0,
- },
- .it_value = { /* This value disables the timer */
- .tv_sec = 0,
- .tv_nsec = 0,
- }
- };
- ts.it_value.tv_sec = 0;
-
- if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
- perror("timerfd_settime");
+int loop_callback(loop_t *loop, facemgr_cb_type_t type, void *data) {
+ switch (type) {
+ case FACEMGR_CB_TYPE_REGISTER_FD: {
+ fd_callback_data_t *fd_callback_data = (fd_callback_data_t *)data;
+ if (_loop_register_fd(loop, fd_callback_data->fd, fd_callback_data->owner,
+ fd_callback_data->callback,
+ fd_callback_data->data) < 0) {
+ ERROR("[loop_callback] Error registering fd to event loop");
return -1;
+ }
+ break;
}
- cb_wrapper_args_t * cb_wrapper_args;
- if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) {
- ERROR("[_loop_unregister_timer] Could not remove cb_wrapper from timer map");
+ case FACEMGR_CB_TYPE_UNREGISTER_FD: {
+ fd_callback_data_t *fd_callback_data = (fd_callback_data_t *)data;
+ /* We need a map to associate fd and events */
+ if (_loop_unregister_fd(loop, fd_callback_data->fd) < 0) {
+ ERROR("[loop_callback] Error unregistering fd from event loop");
return -1;
+ }
+ break;
}
- assert(cb_wrapper_args);
- free(cb_wrapper_args);
- if (_loop_unregister_fd(loop, fd) < 0) {
- ERROR("[_loop_unregister_timer] Error unregistering fd from event loop");
+ case FACEMGR_CB_TYPE_REGISTER_TIMER: {
+ timer_callback_data_t *timer_callback_data =
+ (timer_callback_data_t *)data;
+
+ int fd = _loop_register_timer(loop, timer_callback_data);
+ if (fd < 0) {
+ ERROR("[loop_callback] Error registering timer to event loop");
return -1;
+ }
+ return fd;
}
- return 0;
-}
+ case FACEMGR_CB_TYPE_UNREGISTER_TIMER: {
+ int fd = *(int *)data;
-int
-loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data)
-{
- switch(type) {
- case FACEMGR_CB_TYPE_REGISTER_FD:
- {
- fd_callback_data_t * fd_callback_data = (fd_callback_data_t *)data;
- if (_loop_register_fd(loop, fd_callback_data->fd,
- fd_callback_data->owner,
- fd_callback_data->callback,
- fd_callback_data->data) < 0) {
-
- ERROR("[loop_callback] Error registering fd to event loop");
- return -1;
- }
- break;
- }
-
- case FACEMGR_CB_TYPE_UNREGISTER_FD:
- {
- fd_callback_data_t * fd_callback_data = (fd_callback_data_t *)data;
- /* We need a map to associate fd and events */
- if (_loop_unregister_fd(loop, fd_callback_data->fd) < 0) {
- ERROR("[loop_callback] Error unregistering fd from event loop");
- return -1;
- }
- break;
- }
-
- case FACEMGR_CB_TYPE_REGISTER_TIMER:
- {
- timer_callback_data_t * timer_callback_data = (timer_callback_data_t *)data;
-
- int fd = _loop_register_timer(loop, timer_callback_data);
- if (fd < 0) {
- ERROR("[loop_callback] Error registering timer to event loop");
- return -1;
- }
- return fd;
-
- }
-
- case FACEMGR_CB_TYPE_UNREGISTER_TIMER:
- {
- int fd = *(int*)data;
-
- if (_loop_unregister_timer(loop, fd) < 0) {
- ERROR("[loop_callback] Error unregistering timer from event loop");
- return -1;
- }
- return 0;
-
- }
+ if (_loop_unregister_timer(loop, fd) < 0) {
+ ERROR("[loop_callback] Error unregistering timer from event loop");
+ return -1;
+ }
+ return 0;
}
- return 0;
+ }
+ return 0;
}
-
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index 344b034ae..18d2f8f7c 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,7 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <unistd.h> // sleep
+#include <unistd.h> // sleep
#include <hicn/facemgr.h>
#include <hicn/facemgr/cfg.h>
@@ -41,7 +41,7 @@
#if 0
static struct event_base * loop;
#endif
-static loop_t * loop = NULL;
+static loop_t* loop = NULL;
#ifdef __linux__
#ifdef WITH_THREAD
@@ -49,210 +49,193 @@ static bool stop = false;
#endif /* WITH_THREAD */
#endif /* __linux__ */
-static struct option long_options[] =
-{
- {"config", required_argument, 0, 'c'},
- {0, 0, 0, 0}
-};
+static struct option long_options[] = {{"config", required_argument, 0, 'c'},
+ {0, 0, 0, 0}};
typedef struct {
- char * cfgfile;
+ char* cfgfile;
} facemgr_options_t;
-void usage(const char * progname)
-{
- printf("%s: Face manager daemon\n", progname);
- printf("\n");
- printf("Usage: %s [OPTIONS]\n", progname);
- printf("\n");
- printf("OPTIONS:\n");
- printf(" -c --config [FILE|none] Sets the configuration file (unless none, default: /etc/facemgr.conf, ~/facemgr.conf)\n");
- printf("\n");
+void usage(const char* progname) {
+ printf("%s: Face manager daemon\n", progname);
+ printf("\n");
+ printf("Usage: %s [OPTIONS]\n", progname);
+ printf("\n");
+ printf("OPTIONS:\n");
+ printf(
+ " -c --config [FILE|none] Sets the configuration file (unless none, "
+ "default: /etc/facemgr.conf, ~/facemgr.conf)\n");
+ printf("\n");
}
void facemgr_signal_handler(int signal) {
- fprintf(stderr, "Received ^C... quitting !\n");
- if (loop) {
- loop_break(loop);
+ fprintf(stderr, "Received ^C... quitting !\n");
+ if (loop) {
+ loop_break(loop);
#ifdef __linux__
#ifdef WITH_THREAD
stop = true;
#endif /* WITH_THREAD */
#endif /* __linux__ */
- }
+ }
}
-int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
-{
- int c;
- while ((c = getopt_long(argc, argv, "c:", long_options, NULL)) != -1) {
- switch(c) {
- case 'c':
- opts->cfgfile = optarg;
- break;
- case ':':
- case '?':
- default:
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
+int parse_cmdline(int argc, char** argv, facemgr_options_t* opts) {
+ int c;
+ while ((c = getopt_long(argc, argv, "c:", long_options, NULL)) != -1) {
+ switch (c) {
+ case 'c':
+ opts->cfgfile = optarg;
+ break;
+ case ':':
+ case '?':
+ default:
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
}
- return 0;
+ }
+ return 0;
}
-#ifdef __linux__
-
-#endif /* __linux__ */
-
-int
-dump_facelet(const facemgr_t * facemgr, const facelet_t * facelet,
- void * user_data)
-{
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- DEBUG("%s", facelet_s);
- return 0;
+int dump_facelet(const facemgr_t* facemgr, const facelet_t* facelet,
+ void* user_data) {
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ DEBUG("%s", facelet_s);
+ return 0;
}
-int main(int argc, char ** argv)
-{
- facemgr_cfg_t * cfg = NULL;
- facemgr_t * facemgr;
+int main(int argc, char** argv) {
+ facemgr_cfg_t* cfg = NULL;
+ facemgr_t* facemgr;
- struct sigaction sigIntHandler;
- sigIntHandler.sa_handler = facemgr_signal_handler;
- sigemptyset(&sigIntHandler.sa_mask);
- sigIntHandler.sa_flags = 0;
- sigaction(SIGINT, &sigIntHandler, NULL);
+ struct sigaction sigIntHandler;
+ sigIntHandler.sa_handler = facemgr_signal_handler;
+ sigemptyset(&sigIntHandler.sa_mask);
+ sigIntHandler.sa_flags = 0;
+ sigaction(SIGINT, &sigIntHandler, NULL);
- char cfgfile[PATH_MAX];
+ char cfgfile[PATH_MAX];
- // TODO: default < config < commandline on a per option basis
+ // TODO: default < config < commandline on a per option basis
- /* Commandline */
- facemgr_options_t cmdline_opts = {0};
- if (parse_cmdline(argc, argv, &cmdline_opts) < 0) {
- ERROR("Error parsing commandline");
- goto ERR_CMDLINE;
- }
+ /* Commandline */
+ facemgr_options_t cmdline_opts = {0};
+ if (parse_cmdline(argc, argv, &cmdline_opts) < 0) {
+ ERROR("Error parsing commandline");
+ goto ERR_CMDLINE;
+ }
- /* Configuration file */
- //facemgr_options_t cfgfile_opts;
+ /* Configuration file */
+ // facemgr_options_t cfgfile_opts;
- if (cmdline_opts.cfgfile) {
- if (strcasecmp(cmdline_opts.cfgfile, "none") == 0)
- goto NO_CFGFILE;
+ if (cmdline_opts.cfgfile) {
+ if (strcasecmp(cmdline_opts.cfgfile, "none") == 0) goto NO_CFGFILE;
- if (!realpath(cmdline_opts.cfgfile, (char*)&cfgfile))
- goto ERR_PATH;
+ if (!realpath(cmdline_opts.cfgfile, (char*)&cfgfile)) goto ERR_PATH;
- goto PARSE_CFGFILE;
- }
+ goto PARSE_CFGFILE;
+ }
- /* No commandline path specifed, probe default locations... */
+ /* No commandline path specifed, probe default locations... */
- if (probe_cfgfile(cfgfile) < 0)
- goto NO_CFGFILE;
+ if (probe_cfgfile(cfgfile) < 0) goto NO_CFGFILE;
PARSE_CFGFILE:
- DEBUG("Using configuration file %s", cfgfile);
- cfg = facemgr_cfg_create();
- if (!cfg)
- goto ERR_FACEMGR_CFG;
+ DEBUG("Using configuration file %s", cfgfile);
+ cfg = facemgr_cfg_create();
+ if (!cfg) goto ERR_FACEMGR_CFG;
- if (parse_config_file(cfgfile, cfg) < 0) {
- ERROR("Error parsing configuration file %s", cfgfile);
- goto ERR_PARSE;
- }
+ if (parse_config_file(cfgfile, cfg) < 0) {
+ ERROR("Error parsing configuration file %s", cfgfile);
+ goto ERR_PARSE;
+ }
- facemgr = facemgr_create_with_config(cfg);
- if (!facemgr)
- goto ERR_FACEMGR_CONFIG;
+ facemgr = facemgr_create_with_config(cfg);
+ if (!facemgr) goto ERR_FACEMGR_CONFIG;
- goto MAIN_LOOP;
+ goto MAIN_LOOP;
NO_CFGFILE:
- facemgr = facemgr_create();
- if (!facemgr)
- goto ERR_FACEMGR;
+ facemgr = facemgr_create();
+ if (!facemgr) goto ERR_FACEMGR;
MAIN_LOOP:
- /* Main loop */
- loop = loop_create();
- facemgr_set_callback(facemgr, loop, (void*)loop_callback);
+ /* Main loop */
+ loop = loop_create();
+ if (!loop) {
+ ERROR("Failed to create main loop");
+ goto ERR_LOOP;
+ }
+ facemgr_set_callback(facemgr, loop, (void*)loop_callback);
#ifdef __ANDROID__
- facemgr_set_jvm(facemgr, NULL);
+ facemgr_set_jvm(facemgr, NULL);
#endif /* __ ANDROID__ */
- DEBUG("Bootstrap...");
+ DEBUG("Bootstrap...");
- if (facemgr_bootstrap(facemgr) < 0 )
- goto ERR_BOOTSTRAP;
+ if (facemgr_bootstrap(facemgr) < 0) goto ERR_BOOTSTRAP;
- if (loop_dispatch(loop) < 0) {
- ERROR("Failed to run main loop");
- return EXIT_FAILURE;
- }
+ if (loop_dispatch(loop) < 0) {
+ ERROR("Failed to run main loop");
+ goto ERR_DISPATCH;
+ }
#ifdef __linux__
#ifdef WITH_THREAD
- unsigned cpt = 0;
- while(!stop) {
- if (cpt == 10) {
- DEBUG("<facelets>");
+ unsigned cpt = 0;
+ while (!stop) {
+ if (cpt == 10) {
+ DEBUG("<facelets>");
#if 1
- facemgr_list_facelets(facemgr, dump_facelet, NULL);
+ facemgr_list_facelets(facemgr, dump_facelet, NULL);
#else
- char * buffer;
- int n = facemgr_list_facelets_json(facemgr, &buffer);
- printf("%s\n", buffer);
- free(buffer);
+ char* buffer;
+ int n = facemgr_list_facelets_json(facemgr, &buffer);
+ printf("%s\n", buffer);
+ free(buffer);
#endif
- DEBUG("</facelets>");
- cpt = 0;
- }
- usleep(500000);
- cpt++;
+ DEBUG("</facelets>");
+ cpt = 0;
}
+ usleep(500000);
+ cpt++;
+ }
#endif /* WITH_THREAD */
#endif /* __linux__ */
- facemgr_stop(facemgr);
+ facemgr_stop(facemgr);
- if (loop_undispatch(loop) < 0) {
- ERROR("Failed to terminate main loop");
- return EXIT_FAILURE;
- }
+ if (loop_undispatch(loop) < 0) {
+ ERROR("Failed to terminate main loop");
+ }
- facemgr_free(facemgr);
+ facemgr_free(facemgr);
- if (cfg)
- facemgr_cfg_free(cfg);
+ if (cfg) facemgr_cfg_free(cfg);
- loop_free(loop);
+ loop_free(loop);
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
ERR_BOOTSTRAP:
+ facemgr_free(facemgr);
+ERR_DISPATCH:
+ loop_free(loop);
+ERR_LOOP:
- facemgr_free(facemgr);
- loop_free(loop);
ERR_FACEMGR_CONFIG:
ERR_FACEMGR:
ERR_PARSE:
- if (cfg)
- facemgr_cfg_free(cfg);
+ if (cfg) facemgr_cfg_free(cfg);
ERR_FACEMGR_CFG:
ERR_PATH:
ERR_CMDLINE:
- return EXIT_FAILURE;
-
-
+ return EXIT_FAILURE;
}
diff --git a/ctrl/libhicnctrl/CMakeLists.txt b/ctrl/libhicnctrl/CMakeLists.txt
index 22f81401f..bf5ffd699 100644
--- a/ctrl/libhicnctrl/CMakeLists.txt
+++ b/ctrl/libhicnctrl/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,50 +11,65 @@
# 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(libhicnctrl)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif()
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
-include(BuildMacros)
-
-set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_STANDARD_REQUIRED ON)
-
-set(CMAKE_MACOSX_RPATH ON)
-
+##############################################################
+# Libs and Bins names
+##############################################################
set(LIBHICNCTRL hicnctrl)
-
set(LIBHICNCTRL ${LIBHICNCTRL} CACHE INTERNAL "" FORCE)
set(LIBHICNCTRL_SHARED ${LIBHICNCTRL}.shared CACHE INTERNAL "" FORCE)
set(LIBHICNCTRL_STATIC ${LIBHICNCTRL}.static CACHE INTERNAL "" FORCE)
set(HICNCTRL hicnctrl CACHE INTERNAL "" FORCE)
-set(LIBHICNCTRL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes CACHE INTERNAL "" FORCE)
+set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL})
+set(LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules)
+
+
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
+
+##############################################################
+# C Standard
+##############################################################
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+
+set(CMAKE_MACOSX_RPATH ON)
+
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- find_package_wrapper(HicnPlugin REQUIRED)
- endif()
+ include(CommonSetup)
- find_package_wrapper(Libhicn REQUIRED)
- list(APPEND HICN_LIBRARIES ${LIBHICN_SHARED})
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
- set(HICN_INCLUDE_DIRS
- ${HICN_INCLUDE_DIRS}
- ${HICNPLUGIN_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS})
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+ list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE})
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
@@ -65,36 +80,21 @@ else()
list(APPEND DEPENDENCIES
${LIBHICN_STATIC}
)
- elseif (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- set(
- HICN_INCLUDE_DIRS
- ${HICN_INCLUDE_DIRS}
- ${HICNPLUGIN_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
- )
-
- list(APPEND DEPENDENCIES
- hicn_plugin
- ${SAFE_VAPI_SHARED}
- )
else ()
set(HICN_LIBRARIES ${LIBHICN_SHARED})
list(APPEND DEPENDENCIES
${LIBHICN_SHARED}
)
endif ()
-
endif()
-set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL})
-set (LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules)
+##############################################################
+# Include directories
+##############################################################
add_subdirectory(includes)
add_subdirectory(src)
-include(Packaging)
-
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
- make_packages()
+ make_packages()
endif()
diff --git a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake b/ctrl/libhicnctrl/cmake/packaging.cmake
index 2851375be..74905d6c4 100644
--- a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
+++ b/ctrl/libhicnctrl/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -31,7 +31,7 @@ set(${LIBHICNCTRL_COMPONENT}_DEB_DEPENDENCIES
)
set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} (>= stable_version)"
+ "${LIBHICNCTRL_COMPONENT} (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
@@ -41,16 +41,16 @@ set(${LIBHICNCTRL_COMPONENT}_RPM_DEPENDENCIES
)
set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} >= stable_version"
+ "${LIBHICNCTRL_COMPONENT} = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBHICNCTRL_COMPONENT_MODULES}_DEB_DEPENDENCIES
- "hicn-plugin (>= stable_version)"
+ "hicn-plugin (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBHICNCTRL_COMPONENT_MODULES}_RPM_DEPENDENCIES
- "hicn-plugin >= stable_version"
+ "hicn-plugin = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/ctrl/libhicnctrl/examples/create_face.c b/ctrl/libhicnctrl/examples/create_face.c
index 5f92f5906..ebd451de1 100644
--- a/ctrl/libhicnctrl/examples/create_face.c
+++ b/ctrl/libhicnctrl/examples/create_face.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,125 +22,122 @@
*/
#include <stdlib.h>
-#include <sys/types.h> // getifaddrs
-#include <ifaddrs.h> // getifaddrs
+#include <sys/types.h> // getifaddrs
+#include <ifaddrs.h> // getifaddrs
#include <stdio.h>
-#include <string.h> /* for strncpy */
-#include <sys/socket.h> // socket
-#include <sys/ioctl.h> // ioctl
+#include <sys/socket.h> // socket
+#include <sys/ioctl.h> // ioctl
#include <unistd.h>
#include <hicn/ctrl.h>
#include <hicn/util/log.h>
-int get_local_info(char * if_name, ip_address_t * local_ip) {
- struct ifaddrs *addrs;
- struct ifreq ifr = {
- .ifr_addr.sa_family = AF_INET,
- };
- int ret = -1;
-
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
-
- getifaddrs(&addrs);
-
- for (struct ifaddrs * tmp = addrs; tmp; tmp = tmp->ifa_next) {
- if (!tmp->ifa_addr || tmp->ifa_addr->sa_family != AF_PACKET)
- continue;
- if (strcmp(tmp->ifa_name, "lo") == 0)
- continue;
- snprintf(if_name, IFNAMSIZ, "%s", tmp->ifa_name);
-
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tmp->ifa_name);
- if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
- //perror("ioctl");
- continue;
- }
-
- *local_ip = IP_ADDRESS_EMPTY;
- local_ip->v4.as_inaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
- if (ip_address_empty(local_ip))
- continue;
-
- ret = 0;
- break;
- }
-
- freeifaddrs(addrs);
- close(fd);
- return ret;
-}
+int get_local_info(char *if_name, ip_address_t *local_ip) {
+ struct ifaddrs *addrs;
+ struct ifreq ifr = {
+ .ifr_addr.sa_family = AF_INET,
+ };
+ int ret = -1;
-int main() {
- char remote_ip_str[INET_ADDRSTRLEN] = "1.1.1.1";
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
- ip_address_t local_ip;
- ip_address_t remote_ip;
- char if_name[IFNAMSIZ];
+ getifaddrs(&addrs);
- /* Retrieving local info */
+ for (struct ifaddrs *tmp = addrs; tmp; tmp = tmp->ifa_next) {
+ if (!tmp->ifa_addr || tmp->ifa_addr->sa_family != AF_PACKET) continue;
+ if (strcmp(tmp->ifa_name, "lo") == 0) continue;
+ snprintf(if_name, IFNAMSIZ, "%s", tmp->ifa_name);
- if (get_local_info(if_name, &local_ip) < 0) {
- DEBUG("Error getting local information");
- goto ERR_INIT;
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tmp->ifa_name);
+ if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
+ // perror("ioctl");
+ continue;
}
- char local_ip_str[MAXSZ_IP_ADDRESS];
- ip_address_snprintf(local_ip_str, MAXSZ_IP_ADDRESS, &local_ip, AF_INET);
- DEBUG("Local information :");
- DEBUG(" - Interface name : %s", if_name);
- DEBUG(" - IP address : %s", local_ip_str);
+ *local_ip = IP_ADDRESS_EMPTY;
+ local_ip->v4.as_inaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+ if (ip_address_empty(local_ip)) continue;
- if (ip_address_pton (remote_ip_str, &remote_ip) < 0){
- DEBUG("Error parsing remote IP address");
- goto ERR_INIT;
- }
+ ret = 0;
+ break;
+ }
+
+ freeifaddrs(addrs);
+ close(fd);
+ return ret;
+}
- /* Filling face information */
- hc_face_t face = {
- .face = {
- .type = FACE_TYPE_UDP,
- .family = AF_INET,
- .local_addr = local_ip,
- .remote_addr = remote_ip,
- .local_port = 6000,
- .remote_port = 6000,
- .admin_state = FACE_STATE_UNDEFINED,
- .state = FACE_STATE_UNDEFINED,
+int main() {
+ char remote_ip_str[INET_ADDRSTRLEN] = "1.1.1.1";
+
+ ip_address_t local_ip;
+ ip_address_t remote_ip;
+ char if_name[IFNAMSIZ];
+
+ /* Retrieving local info */
+
+ if (get_local_info(if_name, &local_ip) < 0) {
+ DEBUG("Error getting local information");
+ goto ERR_INIT;
+ }
+
+ char local_ip_str[MAXSZ_IP_ADDRESS];
+ ip_address_snprintf(local_ip_str, MAXSZ_IP_ADDRESS, &local_ip, AF_INET);
+ DEBUG("Local information :");
+ DEBUG(" - Interface name : %s", if_name);
+ DEBUG(" - IP address : %s", local_ip_str);
+
+ if (ip_address_pton(remote_ip_str, &remote_ip) < 0) {
+ DEBUG("Error parsing remote IP address");
+ goto ERR_INIT;
+ }
+
+ /* Filling face information */
+ hc_face_t face = {
+ .face =
+ {
+ .type = FACE_TYPE_UDP,
+ .family = AF_INET,
+ .local_addr = local_ip,
+ .remote_addr = remote_ip,
+ .local_port = 6000,
+ .remote_port = 6000,
+ .admin_state = FACE_STATE_UNDEFINED,
+ .state = FACE_STATE_UNDEFINED,
#ifdef WITH_POLICY
- .priority = 0,
- .tags = POLICY_TAGS_EMPTY,
+ .priority = 0,
+ .tags = POLICY_TAGS_EMPTY,
#endif /* WITH_POLICY */
- },
- };
- if (netdevice_set_name(&face.face.netdevice, if_name) < 0) {
- DEBUG("Error setting face netdevice name");
- goto ERR_INIT;
- }
+ },
+ };
+ if (netdevice_set_name(&face.face.netdevice, if_name) < 0) {
+ DEBUG("Error setting face netdevice name");
+ goto ERR_INIT;
+ }
- /* Connecting to socket and creating face */
+ /* Connecting to socket and creating face */
- hc_sock_t * socket = hc_sock_create();
- if (!socket){
- DEBUG("Error creating libhicnctrl socket");
- goto ERR_SOCK;
- }
+ hc_sock_t *socket = hc_sock_create();
+ if (!socket) {
+ DEBUG("Error creating libhicnctrl socket");
+ goto ERR_SOCK;
+ }
- if (hc_sock_connect(socket) < 0){
- DEBUG("Error connecting to forwarder");
- goto ERR;
- }
+ if (hc_sock_connect(socket) < 0) {
+ DEBUG("Error connecting to forwarder");
+ goto ERR;
+ }
- if (hc_face_create(socket, &face) < 0){
- DEBUG("Error creating face");
- goto ERR;
- }
+ if (hc_face_create(socket, &face) < 0) {
+ DEBUG("Error creating face");
+ goto ERR;
+ }
- DEBUG("Face created successfully");
+ DEBUG("Face created successfully");
ERR:
- hc_sock_free(socket);
+ hc_sock_free(socket);
ERR_SOCK:
ERR_INIT:
- return 0;
+ return 0;
}
diff --git a/ctrl/libhicnctrl/examples/update_priority.c b/ctrl/libhicnctrl/examples/update_priority.c
index d350f71c9..bbe174c2f 100644
--- a/ctrl/libhicnctrl/examples/update_priority.c
+++ b/ctrl/libhicnctrl/examples/update_priority.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,37 +24,36 @@
#include <hicn/ctrl.h>
#include <hicn/util/log.h>
-int main(int argc, char **argv)
-{
- if (argc != 3) {
- fprintf(stderr, "Usage: %s FACE_ID PRIORITY\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- unsigned face_id = atoi(argv[1]);
- unsigned priority = atoi(argv[2]);
- char face_id_s[SYMBOLIC_NAME_LEN];
-
- hc_sock_t * socket = hc_sock_create();
- if (!socket){
- DEBUG("Error creating libhicnctrl socket");
- goto ERR_SOCK;
- }
-
- if (hc_sock_connect(socket) < 0){
- DEBUG("Error connecting to forwarder");
- goto ERR;
- }
-
- snprintf(face_id_s, SYMBOLIC_NAME_LEN, "%d", face_id);
- if (hc_face_set_priority(socket, face_id_s, priority) < 0) {
- DEBUG("Error setting face priority");
- goto ERR;
- }
-
- DEBUG("Face priority updated successfully");
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s FACE_ID PRIORITY\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ unsigned face_id = atoi(argv[1]);
+ unsigned priority = atoi(argv[2]);
+ char face_id_s[SYMBOLIC_NAME_LEN];
+
+ hc_sock_t *socket = hc_sock_create();
+ if (!socket) {
+ DEBUG("Error creating libhicnctrl socket");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(socket) < 0) {
+ DEBUG("Error connecting to forwarder");
+ goto ERR;
+ }
+
+ snprintf(face_id_s, SYMBOLIC_NAME_LEN, "%d", face_id);
+ if (hc_face_set_priority(socket, face_id_s, priority) < 0) {
+ DEBUG("Error setting face priority");
+ goto ERR;
+ }
+
+ DEBUG("Face priority updated successfully");
ERR:
- hc_sock_free(socket);
+ hc_sock_free(socket);
ERR_SOCK:
- return 0;
+ return 0;
}
diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt
index 50cfa4ad5..1a90690a4 100644
--- a/ctrl/libhicnctrl/includes/CMakeLists.txt
+++ b/ctrl/libhicnctrl/includes/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,17 +11,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(LIBHICNCTRL_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR} ""
+##############################################################
+# Public headers directory
+##############################################################
+set(Libhicnctrl_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
CACHE INTERNAL
"" FORCE
)
+
+##############################################################
+# To install header files
+##############################################################
set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ctrl.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/commands.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/face.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light-ng.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h
PARENT_SCOPE
)
diff --git a/ctrl/libhicnctrl/includes/ctrl.h b/ctrl/libhicnctrl/includes/ctrl.h
index e61b7a482..477afd152 100644
--- a/ctrl/libhicnctrl/includes/ctrl.h
+++ b/ctrl/libhicnctrl/includes/ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl.h b/ctrl/libhicnctrl/includes/hicn/ctrl.h
index e61b7a482..477afd152 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index b5a968800..8a59cf4d8 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -67,15 +67,24 @@
#include <stdbool.h>
#include <stdint.h>
+#include <stddef.h> // object_offset_t
#include <hicn/util/ip_address.h>
-#include <hicn/ctrl/commands.h>
-#include "face.h"
+#include <hicn/face.h>
+#include <hicn/strategy.h>
+/*
+ * This has to be common between hicn-light and hicn-plugin. We now we keep the
+ * minimum of the two
+ */
+#define SYMBOLIC_NAME_LEN 16
#define HICN_DEFAULT_PORT 9695
#define HOTFIXMARGIN 0
+#define INVALID_FACE_ID ~0
+#define INVALID_NETDEVICE_ID ~0
+
/**
* \brief Defines the default size for the allocated data arrays holding the
* results of API calls.
@@ -99,26 +108,70 @@
* Message helper types and aliases
******************************************************************************/
-#define foreach_command \
- _(UNDEFINED) \
- _(CREATE) \
- _(UPDATE) \
- _(DELETE) \
- _(LIST) \
- _(SET) \
+/* Action */
+
+#define foreach_action \
+ _(UNDEFINED) \
+ _(CREATE) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(LIST) \
+ _(SET) \
+ _(SERVE) \
+ _(STORE) \
+ _(CLEAR) \
_(N)
typedef enum {
#define _(x) ACTION_##x,
- foreach_command
+ foreach_action
#undef _
} hc_action_t;
+extern const char *action_str[];
+
+#define action_str(x) action_str[x]
+
+hc_action_t action_from_str(const char *action_str);
+
+/* Object type */
+
+#define foreach_object \
+ _(UNDEFINED) \
+ _(CONNECTION) \
+ _(LISTENER) \
+ _(ROUTE) \
+ _(FACE) \
+ _(STRATEGY) \
+ _(PUNTING) \
+ _(POLICY) \
+ _(CACHE) \
+ _(MAPME) \
+ _(LOCAL_PREFIX) \
+ _(PROBE) \
+ _(SUBSCRIPTION) \
+ _(N)
+
+typedef enum {
+#define _(x) OBJECT_##x,
+ foreach_object
+#undef _
+} hc_object_type_t;
+
+extern const char *object_str[];
+
+#define object_str(x) object_str[x]
+
+hc_object_type_t object_from_str(const char *object_str);
+
+#define IS_VALID_OBJECT_TYPE(x) IS_VALID_ENUM_TYPE(OBJECT, x)
+#define IS_VALID_ACTION(x) IS_VALID_ENUM_TYPE(ACTION, x)
+
/**
* \brief hICN control message header
*/
typedef struct hc_msg_s hc_msg_t;
-
+typedef struct hc_result_s hc_result_t;
/******************************************************************************
* Control Data
******************************************************************************/
@@ -140,7 +193,8 @@ typedef struct hc_data_s {
bool complete;
/* Callbacks */
- data_callback_t complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data);
+ data_callback_t
+ complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data);
void *complete_cb_data;
int ret;
} hc_data_t;
@@ -149,7 +203,8 @@ typedef struct hc_data_s {
* Create a structure holding the results of an hICN control request.
* \result The newly create data structure.
*/
-hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size, data_callback_t complete_cb);
+hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size,
+ data_callback_t complete_cb);
/**
* Free a structure holding the results of an hICN control request.
@@ -214,38 +269,49 @@ int hc_data_reset(hc_data_t *data);
* \param [out] found - A pointer to the element, or NULL if not found.
* \return Error code
*/
-#define GENERATE_FIND_HEADER(TYPE) \
-int \
-hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
- hc_ ## TYPE ## _t **found)
-
-#define GENERATE_FIND(TYPE) \
-int \
-hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
- hc_ ## TYPE ## _t **found) \
-{ \
- foreach_type(hc_ ## TYPE ## _t, x, data) { \
- if (hc_ ## TYPE ## _cmp(x, element) == 0) { \
- *found = x; \
- return 0; \
- } \
- }; \
- *found = NULL; /* this is optional */ \
- return 0; \
-}
+#define GENERATE_FIND_HEADER(TYPE) \
+ int hc_##TYPE##_find(hc_data_t *data, const hc_##TYPE##_t *element, \
+ hc_##TYPE##_t **found)
+
+#define GENERATE_FIND(TYPE) \
+ int hc_##TYPE##_find(hc_data_t *data, const hc_##TYPE##_t *element, \
+ hc_##TYPE##_t **found) { \
+ foreach_type(hc_##TYPE##_t, x, data) { \
+ if (hc_##TYPE##_cmp(x, element) == 0) { \
+ *found = x; \
+ return 0; \
+ } \
+ }; \
+ *found = NULL; /* this is optional */ \
+ return 0; \
+ }
/******************************************************************************
* Control socket
******************************************************************************/
-/* This should be at least equal to the maximum packet size */
-#define RECV_BUFLEN 8192
+/* With UDP, the buffer should be able to receieve a full packet, and thus MTU
+ * (max 9000) is sufficient. Messages will be received fully one by one.
+ * With TCP, the buffer should be at least able to receive a message header and
+ * the maximum size of a data element, so any reasonable size will be correct,
+ * it might just optimize performance. Messages might arrive in chunks that the
+ * library is able to parse.
+ */
+#define JUMBO_MTU 9000
+#define RECV_BUFLEN 65535
+
+#define foreach_forwarder_type \
+ _(UNDEFINED) \
+ _(HICNLIGHT) \
+ _(HICNLIGHT_NG) \
+ _(VPP) \
+ _(N)
typedef enum {
- HICNLIGHT,
- VPP,
- UNDEFINED
-} forwarder_t;
+#define _(x) x,
+ foreach_forwarder_type
+#undef _
+} forwarder_type_t;
/**
* \brief Holds the state of an hICN control socket
@@ -257,22 +323,26 @@ typedef struct hc_sock_s hc_sock_t;
* \param [in] url - The URL to connect to.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create_url(const char * url);
+hc_sock_t *hc_sock_create_url(const char *url);
/**
* \brief Create an hICN control socket using the provided forwarder.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create_forwarder(forwarder_t forwarder);
+hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder);
+
+/**
+ * \brief Create an hICN control socket using the provided forwarder and a URL.
+ * \return an hICN control socket
+ */
+hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder,
+ const char *url);
/**
* \brief Create an hICN control socket using the default connection type.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create(void);
+hc_sock_t *hc_sock_create(void);
/**
* \brief Frees an hICN control socket
@@ -324,7 +394,7 @@ int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size);
* \param [in] msglen - Length of the message to send
* \return Error code
*/
-int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq);
+int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq);
/**
* \brief Helper for reading socket contents
@@ -356,6 +426,13 @@ int hc_sock_callback(hc_sock_t *s, hc_data_t **data);
*/
int hc_sock_reset(hc_sock_t *s);
+void hc_sock_increment_woff(hc_sock_t *s, size_t bytes);
+
+int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result,
+ data_callback_t complete_cb, void *complete_cb_data);
+
+int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms);
+
/******************************************************************************
* Command-specific structures and functions
******************************************************************************/
@@ -420,50 +497,11 @@ int hc_sock_reset(hc_sock_t *s);
VAR < (TYPE *)(data->buffer + data->size * data->out_element_size); \
VAR++)
-/**
- * New type is defined to reconciliate different enum for add and list.
- * Also, values not implemented have been removed for clarity.
- */
-#define foreach_connection_type \
- _(UNDEFINED) \
- _(TCP) \
- _(UDP) \
- _(HICN) \
- _(N)
-
-typedef enum {
-#define _(x) CONNECTION_TYPE_##x,
- foreach_connection_type
-#undef _
-} hc_connection_type_t;
-
-#define MAXSZ_HC_CONNECTION_TYPE_ 9
-#define MAXSZ_HC_CONNECTION_TYPE MAXSZ_HC_CONNECTION_TYPE_ + NULLTERM + HOTFIXMARGIN
-
-extern const char *connection_type_str[];
-
-hc_connection_type_t connection_type_from_str(const char *str);
-
-/* Same order as connection_state_t in hicn/core/connectionState.h */
-#define foreach_connection_state \
- _(UNDEFINED) \
- _(DOWN) \
- _(UP) \
- _(N)
-
-typedef enum {
-#define _(x) HC_CONNECTION_STATE_##x,
- foreach_connection_state
-#undef _
-} hc_connection_state_t;
-
-#define MAXSZ_HC_CONNECTION_STATE_ 9
-#define MAXSZ_HC_CONNECTION_STATE MAXSZ_HC_CONNECTION_STATE_ + NULLTERM
-
-extern const char *connection_state_str[];
-
typedef int (*HC_PARSE)(const u8 *, u8 *);
+#define INPUT_ERROR -2
+#define UNSUPPORTED_CMD_ERROR -3
+
/*----------------------------------------------------------------------------*
* Listeners
*----------------------------------------------------------------------------*/
@@ -473,27 +511,28 @@ typedef struct {
char name[SYMBOLIC_NAME_LEN]; /* K.w */ // XXX clarify what used for
char interface_name[INTERFACE_LEN]; /* Kr. */
u32 id;
- hc_connection_type_t type; /* .rw */
- int family; /* .rw */
- ip_address_t local_addr; /* .rw */
- u16 local_port; /* .rw */
+ face_type_t type; /* .rw */
+ int family; /* .rw */
+ ip_address_t local_addr; /* .rw */
+ u16 local_port; /* .rw */
} hc_listener_t;
int hc_listener_create(hc_sock_t *s, hc_listener_t *listener);
/* listener_found might eventually be allocated, and needs to be freed */
+hc_result_t *hc_listener_create_conf(hc_sock_t *s, hc_listener_t *listener);
int hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
hc_listener_t **listener_found);
int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener);
int hc_listener_list(hc_sock_t *s, hc_data_t **pdata);
+hc_result_t *hc_listener_list_conf(hc_sock_t *s);
int hc_listener_validate(const hc_listener_t *listener);
int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2);
-int hc_listener_parse(void *in, hc_listener_t *listener);
#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data)
#define MAXSZ_HC_LISTENER_ \
- INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_
+ INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_FACE_TYPE_
#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM
GENERATE_FIND_HEADER(listener);
@@ -506,28 +545,30 @@ int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener);
/*
* NOTE :
- * - interface_name is mainly used to derive listeners from connections, but is
- * not itself used to create connections.
+ * - interface_name is mainly used to derive listeners from connections,
+ * but is not itself used to create connections.
*/
typedef struct {
u32 id; /* Kr. */
char name[SYMBOLIC_NAME_LEN]; /* K.w */
char interface_name[INTERFACE_LEN]; /* Kr. */
- hc_connection_type_t type; /* .rw */
+ face_type_t type; /* .rw */
int family; /* .rw */
ip_address_t local_addr; /* .rw */
u16 local_port; /* .rw */
ip_address_t remote_addr; /* .rw */
u16 remote_port; /* .rw */
- hc_connection_state_t admin_state; /* .rw */
+ face_state_t admin_state; /* .rw */
#ifdef WITH_POLICY
- uint32_t priority; /* .rw */
- policy_tags_t tags; /* .rw */
-#endif /* WITH_POLICY */
- hc_connection_state_t state; /* .r. */
+ uint32_t priority; /* .rw */
+ policy_tags_t tags; /* .rw */
+#endif /* WITH_POLICY */
+ face_state_t state; /* .r. */
} hc_connection_t;
int hc_connection_create(hc_sock_t *s, hc_connection_t *connection);
+hc_result_t *hc_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection);
/* connection_found will be allocated, and must be freed */
int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
hc_connection_t **connection_found);
@@ -536,6 +577,8 @@ int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
hc_connection_t *connection_updated);
int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection);
+hc_result_t *hc_connection_delete_conf(hc_sock_t *s,
+ hc_connection_t *connection);
/*
int hc_connection_remove_by_id(hc_sock_t * s, char * name);
int hc_connection_remove_by_name(hc_sock_t * s, char * name);
@@ -544,19 +587,21 @@ int hc_connection_list(hc_sock_t *s, hc_data_t **pdata);
int hc_connection_validate(const hc_connection_t *connection);
int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2);
-int hc_connection_parse(void *in, hc_connection_t *connection);
-int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
-int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
-int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
#endif /* WITH_POLICY */
#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data)
-#define MAXSZ_HC_CONNECTION_ \
- MAXSZ_HC_CONNECTION_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \
- MAXSZ_HC_CONNECTION_TYPE_ + SPACES(3)
+#define MAXSZ_HC_CONNECTION_ \
+ MAXSZ_FACE_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \
+ MAXSZ_FACE_TYPE_ + SPACES(3)
#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM
GENERATE_FIND_HEADER(connection);
@@ -591,14 +636,17 @@ typedef struct {
*/
int hc_face_create(hc_sock_t *s, hc_face_t *face);
int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found);
-int hc_face_delete(hc_sock_t *s, hc_face_t *face);
+int hc_face_delete(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener);
int hc_face_list(hc_sock_t *s, hc_data_t **pdata);
int hc_face_list_async(hc_sock_t *s); //, hc_data_t ** pdata);
-int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
-int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
-int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
#endif /* WITH_POLICY */
#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data)
@@ -609,7 +657,8 @@ int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t
#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN
#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM
-#define MAXSZ_HC_FACE_ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN
+#define MAXSZ_HC_FACE_ \
+ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN
#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM
int hc_face_snprintf(char *s, size_t size, hc_face_t *face);
@@ -619,20 +668,20 @@ int hc_face_snprintf(char *s, size_t size, hc_face_t *face);
*----------------------------------------------------------------------------*/
typedef struct {
- face_id_t face_id; /* Kr. */
- int family; /* Krw */
- ip_address_t remote_addr; /* krw */
- u8 len; /* krw */
- u16 cost; /* .rw */
- hc_face_t face;
+ face_id_t face_id; /* Kr. use when name == NULL */
+ char name[SYMBOLIC_NAME_LEN]; /* Kr. use by default vs face_id */
+ int family; /* Krw */
+ ip_address_t remote_addr; /* krw */
+ u8 len; /* krw */
+ u16 cost; /* .rw */
+ hc_face_t face; /* TODO remove, used by hicn_plugin_api */
} hc_route_t;
-int hc_route_parse(void *in, hc_route_t *route);
-
-int hc_route_create(hc_sock_t * s, hc_route_t * route);
-int hc_route_delete(hc_sock_t * s, hc_route_t * route);
-int hc_route_list(hc_sock_t * s, hc_data_t ** pdata);
-int hc_route_list_async(hc_sock_t * s);
+int hc_route_create(hc_sock_t *s, hc_route_t *route);
+hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route);
+int hc_route_delete(hc_sock_t *s, hc_route_t *route);
+int hc_route_list(hc_sock_t *s, hc_data_t **pdata);
+int hc_route_list_async(hc_sock_t *s);
#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data)
@@ -646,6 +695,7 @@ int hc_route_list_async(hc_sock_t * s);
#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM
int hc_route_snprintf(char *s, size_t size, hc_route_t *route);
+int hc_route_validate(const hc_route_t *route);
/*----------------------------------------------------------------------------*
* Punting
@@ -653,9 +703,9 @@ int hc_route_snprintf(char *s, size_t size, hc_route_t *route);
typedef struct {
face_id_t face_id; /* Kr. */ // XXX listener id, could be NULL for all ?
- int family; /* Krw */
- ip_address_t prefix; /* krw */
- u8 prefix_len; /* krw */
+ int family; /* Krw */
+ ip_address_t prefix; /* krw */
+ u8 prefix_len; /* krw */
} hc_punting_t;
int hc_punting_create(hc_sock_t *s, hc_punting_t *punting);
@@ -666,7 +716,6 @@ int hc_punting_list(hc_sock_t *s, hc_data_t **pdata);
int hc_punting_validate(const hc_punting_t *punting);
int hc_punting_cmp(const hc_punting_t *c1, const hc_punting_t *c2);
-int hc_punting_parse(void *in, hc_punting_t *punting);
#define foreach_punting(VAR, data) foreach_type(hc_punting_t, VAR, data)
@@ -681,8 +730,23 @@ int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting);
* Cache
*----------------------------------------------------------------------------*/
-int hc_cache_set_store(hc_sock_t *s, int enabled);
-int hc_cache_set_serve(hc_sock_t *s, int enabled);
+typedef struct {
+ uint8_t serve; // 1 = on, 0 = off
+ uint8_t store; // 1 = on, 0 = off
+} hc_cache_t;
+
+typedef struct {
+ bool store;
+ bool serve;
+ size_t cs_size;
+ size_t num_stale_entries;
+} hc_cache_info_t;
+
+int hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache);
+int hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache);
+int hc_cache_clear(hc_sock_t *s, hc_cache_t *cache);
+int hc_cache_list(hc_sock_t *s, hc_data_t **pdata);
+int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info);
/*----------------------------------------------------------------------------*
* Strategy
@@ -691,7 +755,13 @@ int hc_cache_set_serve(hc_sock_t *s, int enabled);
#define MAXSZ_STRATEGY_NAME 255
typedef struct {
+ // The name is not set by the controller
+ // but populated by the daemon
char name[MAXSZ_STRATEGY_NAME];
+ strategy_type_t type;
+ ip_address_t address, local_address;
+ int family, local_family;
+ u8 len, local_len;
} hc_strategy_t;
int hc_strategy_list(hc_sock_t *s, hc_data_t **data);
@@ -704,8 +774,11 @@ int hc_strategy_list(hc_sock_t *s, hc_data_t **data);
int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy);
// per prefix
-int hc_strategy_set(hc_sock_t *s /* XXX */);
-
+int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy);
+hc_result_t *hc_strategy_set_conf(hc_sock_t *s, hc_strategy_t *strategy);
+int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy);
+hc_result_t *hc_strategy_add_local_prefix_conf(hc_sock_t *s,
+ hc_strategy_t *strategy);
/*----------------------------------------------------------------------------*
* WLDR
*----------------------------------------------------------------------------*/
@@ -717,10 +790,45 @@ int hc_wldr_set(hc_sock_t *s /* XXX */);
* MAP-Me
*----------------------------------------------------------------------------*/
-int hc_mapme_set(hc_sock_t *s, int enabled);
-int hc_mapme_set_discovery(hc_sock_t *s, int enabled);
-int hc_mapme_set_timescale(hc_sock_t *s, double timescale);
-int hc_mapme_set_retx(hc_sock_t *s, double timescale);
+typedef enum {
+ MAPME_TARGET_ENABLE,
+ MAPME_TARGET_DISCOVERY,
+ MAPME_TARGET_TIMESCALE,
+ MAPME_TARGET_RETX,
+} mapme_target_t;
+
+static inline mapme_target_t mapme_target_from_str(char *mapme_target_str) {
+ if (strcasecmp(mapme_target_str, "enable") == 0)
+ return MAPME_TARGET_ENABLE;
+ else if (strcasecmp(mapme_target_str, "discovery") == 0)
+ return MAPME_TARGET_DISCOVERY;
+ else if (strcasecmp(mapme_target_str, "timescale") == 0)
+ return MAPME_TARGET_TIMESCALE;
+ else
+ return MAPME_TARGET_RETX;
+}
+
+#define MAX_MAPME_ARG_LEN 30
+
+typedef struct {
+ mapme_target_t target;
+ // Command argument stored as a string
+ // before being parsed into 'enabled' or 'timescale'
+ char unparsed_arg[MAX_MAPME_ARG_LEN];
+
+ uint8_t enabled; // 1 = on, 0 = off
+ uint32_t timescale; // Milliseconds
+
+ ip_address_t address;
+ int family;
+ u8 len;
+} hc_mapme_t;
+
+int hc_mapme_set(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_set_discovery(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_set_timescale(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_set_retx(hc_sock_t *s, hc_mapme_t *mapme);
+int hc_mapme_send_update(hc_sock_t *s, hc_mapme_t *mapme);
/*----------------------------------------------------------------------------*
* Policies
@@ -732,11 +840,9 @@ typedef struct {
int family; /* Krw */
ip_address_t remote_addr; /* krw */
u8 len; /* krw */
- hicn_policy_t policy; /* .rw */
+ hicn_policy_t policy; /* .rw */
} hc_policy_t;
-int hc_policy_parse(void *in, hc_policy_t *policy);
-
int hc_policy_create(hc_sock_t *s, hc_policy_t *policy);
int hc_policy_delete(hc_sock_t *s, hc_policy_t *policy);
int hc_policy_list(hc_sock_t *s, hc_data_t **pdata);
@@ -748,7 +854,114 @@ int hc_policy_list(hc_sock_t *s, hc_data_t **pdata);
#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM
int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy);
+int hc_policy_validate(const hc_policy_t *policy);
#endif /* WITH_POLICY */
+/*----------------------------------------------------------------------------*
+ * Subscription
+ *----------------------------------------------------------------------------*/
+// Topics
+
+#undef PUNTING // TODO(eloparco): Undefined to avoid collisions
+ // Fix the collision
+
+// Used only to create 'hc_topic_t'
+typedef struct {
+#define _(x) char x;
+ foreach_object
+#undef _
+} object_offset_t;
+
+// Flags for topic subscriptions
+typedef enum {
+#define _(x) TOPIC_##x = (1 << offsetof(object_offset_t, x)),
+ foreach_object
+#undef _
+} hc_topic_t;
+
+static inline hc_object_type_t object_from_topic(hc_topic_t topic) {
+#define _(x) \
+ if (topic == TOPIC_##x) return OBJECT_##x;
+ foreach_object
+#undef _
+ return OBJECT_UNDEFINED;
+}
+
+#define NUM_TOPICS OBJECT_N // Because a topic is created for each object
+#define ALL_TOPICS ~0
+
+// Subscriptions
+typedef uint32_t hc_topics_t;
+typedef struct {
+ hc_topics_t topics;
+} hc_subscription_t;
+
+int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription);
+int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription);
+hc_result_t *hc_subscription_create_conf(hc_sock_t *s,
+ hc_subscription_t *subscription);
+hc_result_t *hc_subscription_delete_conf(hc_sock_t *s,
+ hc_subscription_t *subscription);
+
+/*----------------------------------------------------------------------------*
+ * Events
+ *----------------------------------------------------------------------------*/
+#define foreach_event_type \
+ _(UNDEFINED) \
+ _(INTERFACE_UPDATE) \
+ _(N)
+typedef enum {
+#define _(x) EVENT_##x,
+ foreach_event_type
+#undef _
+} event_type_t;
+
+extern const char *event_str[];
+#define event_str(x) event_str[x]
+
+typedef enum {
+ FLAG_INTERFACE_TYPE_WIRED = 0x1,
+ FLAG_INTERFACE_TYPE_WIFI = 0x2,
+ FLAG_INTERFACE_TYPE_CELLULAR = 0x4,
+} flag_interface_type_t;
+
+typedef struct {
+ flag_interface_type_t interface_type;
+} hc_event_interface_update_t;
+
+/* Result */
+
+hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result);
+int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result);
+bool hc_result_get_success(hc_sock_t *s, hc_result_t *result);
+void hc_result_free(hc_result_t *result);
+
+/* Object */
+
+typedef struct {
+ hc_object_type_t type;
+ union {
+ hc_connection_t connection;
+ hc_listener_t listener;
+ hc_route_t route;
+ hc_face_t face;
+ // hc_data_t *data;
+ hc_punting_t punting;
+ hc_strategy_t strategy;
+#ifdef WITH_POLICY
+ hc_policy_t policy;
+#endif /* WITH_POLICY */
+ hc_subscription_t subscription;
+ hc_cache_t cache;
+ hc_mapme_t mapme;
+ uint8_t as_uint8;
+ };
+} hc_object_t;
+
+typedef struct {
+ hc_action_t action;
+ hc_object_t object;
+} hc_command_t;
+
#endif /* HICNTRL_API */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
deleted file mode 100644
index 3758f0f41..000000000
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * @file commands.h
- * @brief All hicn-light commands: 14 in total.
- *
- * Header and payload in binary format.
- */
-
-#ifndef commands_h
-#define commands_h
-
-#ifndef _WIN32
-#include <netinet/in.h>
-#include <sys/socket.h>
-#endif
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <hicn/util/ip_address.h>
-#ifdef WITH_POLICY
-#include <hicn/policy.h>
-#endif /* WITH_POLICY */
-
-#define SYMBOLIC_NAME_LEN 16
-#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
-
-typedef struct in6_addr ipv6_addr_t;
-typedef uint32_t ipv4_addr_t;
-
-typedef enum {
- REQUEST_LIGHT = 0xc0, // this is a command
- RESPONSE_LIGHT,
- ACK_LIGHT,
- NACK_LIGHT,
- LAST_MSG_TYPE_VALUE
-} message_type;
-
-typedef enum {
- ADD_LISTENER = 0,
- ADD_CONNECTION,
- LIST_CONNECTIONS,
- ADD_ROUTE,
- LIST_ROUTES,
- REMOVE_CONNECTION,
- REMOVE_LISTENER,
- REMOVE_ROUTE,
- CACHE_STORE,
- CACHE_SERVE,
- CACHE_CLEAR,
- SET_STRATEGY,
- SET_WLDR,
- ADD_PUNTING,
- LIST_LISTENERS,
- MAPME_ENABLE,
- MAPME_DISCOVERY,
- MAPME_TIMESCALE,
- MAPME_RETX,
- MAPME_SEND_UPDATE,
- CONNECTION_SET_ADMIN_STATE,
-#ifdef WITH_POLICY
- ADD_POLICY,
- LIST_POLICIES,
- REMOVE_POLICY,
- UPDATE_CONNECTION,
- CONNECTION_SET_PRIORITY,
- CONNECTION_SET_TAGS,
-#endif /* WITH_POLICY */
- LAST_COMMAND_VALUE
-} command_id;
-
-typedef enum {
- ADDR_INET = 1,
- ADDR_INET6,
- ADDR_LINK,
- ADDR_IFACE,
- ADDR_UNIX /* PF_UNIX */
-} address_type;
-
-typedef enum {
- UDP_CONN,
- TCP_CONN,
- GRE_CONN, // not implemented
- HICN_CONN
-} connection_type;
-
-typedef enum { ACTIVATE_ON, ACTIVATE_OFF } activate_type;
-
-//========== HEADER ==========
-
-typedef struct {
- uint8_t messageType;
- uint8_t commandID;
- uint16_t length; // tells the number of structures in the payload
- uint32_t seqNum;
-} header_control_message;
-// for the moment has to be at least 8 bytes
-
-// SIZE=8
-
-//========== [00] ADD LISTENER ==========
-
-typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode;
-
-typedef struct {
- char symbolic[SYMBOLIC_NAME_LEN];
- char interfaceName[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint16_t port;
- // uint16_t etherType;
- uint8_t addressType;
- uint8_t listenerMode;
- uint8_t connectionType;
-} add_listener_command;
-
-// SIZE=56
-
-//========== [01] ADD CONNECTION ==========
-
-typedef struct {
- char symbolic[SYMBOLIC_NAME_LEN];
- //char interfaceName[SYMBOLIC_NAME_LEN];
- ip_address_t remoteIp;
- ip_address_t localIp;
- uint16_t remotePort;
- uint16_t localPort;
- uint8_t ipType;
- uint8_t connectionType;
- uint8_t admin_state;
-#ifdef WITH_POLICY
- uint32_t priority;
- policy_tags_t tags;
-#endif /* WITH_POLICY */
-} add_connection_command;
-
-// SIZE=56
-
-//========== [02] LIST CONNECTIONS ==========
-
-typedef enum {
- CONN_GRE,
- CONN_TCP,
- CONN_UDP,
- CONN_MULTICAST,
- CONN_L2,
- CONN_HICN
-} list_connections_type;
-
-typedef enum {
- IFACE_UP = 0,
- IFACE_DOWN = 1,
- IFACE_UNKNOWN = 2 // not used actually
-} connection_state;
-
-typedef struct {
- add_connection_command connectionData;
- uint32_t connid;
- uint8_t state;
- char interfaceName[SYMBOLIC_NAME_LEN];
- char connectionName[SYMBOLIC_NAME_LEN];
-} list_connections_command;
-
-// SIZE=80
-
-//========== [03] ADD ROUTE ==========
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint16_t cost;
- uint8_t addressType;
- uint8_t len;
-} add_route_command;
-
-// SIZE=36
-
-//========== [04] LIST ROUTE ==========
-
-typedef struct {
- ip_address_t address;
- uint32_t connid;
- uint16_t cost;
- uint8_t addressType;
- uint8_t len;
-} list_routes_command;
-
-// SIZE=24
-
-//========== [05] REMOVE CONNECTION ==========
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
-} remove_connection_command;
-
-//========== [06] REMOVE LISTENER ==========
-typedef struct {
- char symbolicOrListenerid[SYMBOLIC_NAME_LEN];
-} remove_listener_command;
-
-// SIZE=16
-
-//========== [07] REMOVE ROUTE ==========
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
-} remove_route_command;
-
-// SIZE=36
-
-//========== [08] CACHE STORE ==========
-
-typedef struct {
- uint8_t activate;
-} cache_store_command;
-
-// SIZE=1
-
-//========== [09] CACHE SERVE ==========
-
-typedef struct {
- uint8_t activate;
-} cache_serve_command;
-
-// SIZE=1
-
-//========== [10] SET STRATEGY ==========
-
-typedef enum {
- SET_STRATEGY_LOADBALANCER,
- SET_STRATEGY_RANDOM,
- SET_STRATEGY_LOW_LATENCY,
- LAST_STRATEGY_VALUE
-} strategy_type;
-
-typedef struct {
- ip_address_t address;
- uint8_t strategyType;
- uint8_t addressType;
- uint8_t len;
- uint8_t related_prefixes;
- ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- uint8_t addresses_type[MAX_FWD_STRATEGY_RELATED_PREFIXES];
-} set_strategy_command;
-
-// SIZE=208
-
-//========== [11] SET WLDR ==========
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint8_t activate;
-} set_wldr_command;
-
-// SIZE=17
-
-//========== [12] ADD PUNTING ==========
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
-} add_punting_command;
-
-// SIZE=36
-
-//========== [13] LIST LISTENER ==========
-
-typedef struct {
- ip_address_t address;
- char listenerName[SYMBOLIC_NAME_LEN];
- char interfaceName[SYMBOLIC_NAME_LEN];
- uint32_t connid;
- uint16_t port;
- uint8_t addressType;
- uint8_t encapType;
-} list_listeners_command;
-
-// SIZE=56
-
-//========== [14] MAPME ==========
-
-// (enable/discovery/timescale/retx)
-
-typedef struct {
- uint8_t activate;
-} mapme_activator_command;
-
-// SIZE=1
-
-typedef struct {
- uint32_t timePeriod;
-} mapme_timing_command;
-
-typedef struct {
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
-} mapme_send_update_command;
-
-// SIZE=1
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint8_t admin_state;
- uint8_t pad8[3];
-} connection_set_admin_state_command;
-
-#ifdef WITH_POLICY
-
-typedef struct {
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
- hicn_policy_t policy;
-} add_policy_command;
-
-typedef struct {
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
- hicn_policy_t policy;
-} list_policies_command;
-
-typedef struct {
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
-} remove_policy_command;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint8_t admin_state;
- uint32_t priority;
- policy_tags_t tags;
-} update_connection_command;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint32_t priority;
-} connection_set_priority_command;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- policy_tags_t tags;
-} connection_set_tags_command;
-
-#endif /* WITH_POLICY */
-
-//===== size of commands ======
-// REMINDER: when a new_command is added, the following switch has to be
-// updated.
-static inline int payloadLengthDaemon(command_id id) {
- switch (id) {
- case ADD_LISTENER:
- return sizeof(add_listener_command);
- case ADD_CONNECTION:
- return sizeof(add_connection_command);
- case LIST_CONNECTIONS:
- return 0; // list connections: payload always 0
- case ADD_ROUTE:
- return sizeof(add_route_command);
- case LIST_ROUTES:
- return 0; // list routes: payload always 0
- case REMOVE_CONNECTION:
- return sizeof(remove_connection_command);
- case REMOVE_LISTENER:
- return sizeof(remove_listener_command);
- case REMOVE_ROUTE:
- return sizeof(remove_route_command);
- case CACHE_STORE:
- return sizeof(cache_store_command);
- case CACHE_SERVE:
- return sizeof(cache_serve_command);
- case CACHE_CLEAR:
- return 0; // cache clear
- case SET_STRATEGY:
- return sizeof(set_strategy_command);
- case SET_WLDR:
- return sizeof(set_wldr_command);
- case ADD_PUNTING:
- return sizeof(add_punting_command);
- case LIST_LISTENERS:
- return 0; // list listeners: payload always 0
- case MAPME_ENABLE:
- return sizeof(mapme_activator_command);
- case MAPME_DISCOVERY:
- return sizeof(mapme_activator_command);
- case MAPME_TIMESCALE:
- return sizeof(mapme_timing_command);
- case MAPME_RETX:
- return sizeof(mapme_timing_command);
- case MAPME_SEND_UPDATE:
- return sizeof(mapme_send_update_command);
- case CONNECTION_SET_ADMIN_STATE:
- return sizeof(connection_set_admin_state_command);
-#ifdef WITH_POLICY
- case ADD_POLICY:
- return sizeof(add_policy_command);
- case LIST_POLICIES:
- return 0; // list policies: payload always 0
- case REMOVE_POLICY:
- return sizeof(remove_policy_command);
- case UPDATE_CONNECTION:
- return sizeof(update_connection_command);
- case CONNECTION_SET_PRIORITY:
- return sizeof(connection_set_priority_command);
- case CONNECTION_SET_TAGS:
- return sizeof(connection_set_tags_command);
-#endif /* WITH_POLICY */
- case LAST_COMMAND_VALUE:
- return 0;
- default:
- return 0;
- }
-}
-#endif
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
deleted file mode 100644
index 49a6a783c..000000000
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * \file face.h
- * \brief Face abstraction
- */
-#ifndef HICN_FACE_H
-#define HICN_FACE_H
-
-#ifndef SPACES
-#define SPACES(x) x
-#endif
-#ifndef SPACE
-#define SPACE 1
-#endif
-#ifndef NULLTERM
-#define NULLTERM 1
-#endif
-
-#include <hicn/policy.h>
-
-#include <hicn/util/ip_address.h>
-
-//typedef unsigned int hash_t; //incompatible with vpp
-
-/* Netdevice type */
-
-#include <net/if.h> // IFNAMSIZ
-
-#define foreach_netdevice_type \
- _(UNDEFINED) \
- _(LOOPBACK) \
- _(WIRED) \
- _(WIFI) \
- _(CELLULAR) \
- _(VPN) \
- _(N)
-
-#define MAXSZ_NETDEVICE_TYPE_ 9
-#define MAXSZ_NETDEVICE_TYPE MAXSZ_NETDEVICE_TYPE_ + NULLTERM
-
-typedef enum {
-#define _(x) NETDEVICE_TYPE_ ## x,
-foreach_netdevice_type
-#undef _
-} netdevice_type_t;
-
-extern const char * netdevice_type_str[];
-
-
-/* Netdevice */
-
-/**
- * \brief Netdevice type
- *
- * NOTE
- * - This struct cannot be made opaque as it is currently part of face_t
- * - We recommand using the API as to keep redundant attributes consistent
- */
-typedef struct {
- u32 index;
- char name[IFNAMSIZ];
-} netdevice_t;
-
-#define NETDEVICE_EMPTY (netdevice_t) { \
- .index = 0, \
- .name = {0}, \
-}
-
-netdevice_t * netdevice_create_from_index(u32 index);
-netdevice_t * netdevice_create_from_name(const char * name);
-#define netdevice_initialize_from_index netdevice_set_index
-#define netdevice_initialize_from_name netdevice_set_name
-void netdevice_free(netdevice_t * netdevice);
-int netdevice_get_index(const netdevice_t * netdevice, u32 * index);
-int netdevice_set_index(netdevice_t * netdevice, u32 index);
-int netdevice_get_name(const netdevice_t * netdevice, const char ** name);
-int netdevice_set_name(netdevice_t * netdevice, const char * name);
-int netdevice_update_index(netdevice_t * netdevice);
-int netdevice_update_name(netdevice_t * netdevice);
-int netdevice_cmp(const netdevice_t * nd1, const netdevice_t * nd2);
-
-#define NETDEVICE_UNDEFINED_INDEX 0
-
-/* Face state */
-
-#define foreach_face_state \
- _(UNDEFINED) \
- _(DOWN) \
- _(UP) \
- _(N)
-
-
-#define MAXSZ_FACE_STATE_ 9
-#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1
-
-typedef enum {
-#define _(x) FACE_STATE_ ## x,
-foreach_face_state
-#undef _
-} face_state_t;
-
-extern const char * face_state_str[];
-
-
-/* Face type */
-
-#define foreach_face_type \
- _(UNDEFINED) \
- _(HICN) \
- _(HICN_LISTENER) \
- _(TCP) \
- _(TCP_LISTENER) \
- _(UDP) \
- _(UDP_LISTENER) \
- _(N)
-
-#define MAXSZ_FACE_TYPE_ 13
-#define MAXSZ_FACE_TYPE MAXSZ_FACE_TYPE_ + 1
-
-typedef enum {
-#define _(x) FACE_TYPE_ ## x,
-foreach_face_type
-#undef _
-} face_type_t;
-
-extern const char * face_type_str[];
-
-#ifdef WITH_POLICY
-#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + MAXSZ_POLICY_TAGS_ + 7
-#else
-#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + 4
-#endif /* WITH_POLICY */
-#define MAXSZ_FACE MAXSZ_FACE_ + 1
-
-/* Face */
-
-typedef u32 face_id_t;
-
-typedef struct {
- face_type_t type;
- face_state_t admin_state;
- face_state_t state;
-#ifdef WITH_POLICY
- uint32_t priority;
- policy_tags_t tags; /**< \see policy_tag_t */
-#endif /* WITH_POLICY */
-
- /*
- * Depending on the face type, some of the following fields will be unused
- */
- netdevice_t netdevice;
- int family; /* To access family independently of face type */
- ip_address_t local_addr;
- ip_address_t remote_addr;
- u16 local_port;
- u16 remote_port;
-} face_t;
-
-int face_initialize(face_t * face);
-int face_initialize_udp(face_t * face, const char * interface_name,
- const ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port,
- int family);
-int face_initialize_udp_sa(face_t * face,
- const char * interface_name,
- const struct sockaddr * local_addr, const struct sockaddr * remote_addr);
-
-face_t * face_create();
-face_t * face_create_udp(const char * interface_name,
- const ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port, int family);
-face_t * face_create_udp_sa(const char * interface_name,
- const struct sockaddr * local_addr,
- const struct sockaddr * remote_addr);
-
-int face_finalize(face_t * face);
-
-void face_free(face_t * face);
-
-typedef int (*face_cmp_t)(const face_t * f1, const face_t * f2);
-
-int face_cmp(const face_t * f1, const face_t * f2);
-unsigned int face_hash(const face_t * face);
-
-size_t
-face_snprintf(char * s, size_t size, const face_t * face);
-
-policy_tags_t face_get_tags(const face_t * face);
-int face_set_tags(face_t * face, policy_tags_t tags);
-
-#endif /* HICN_FACE_H */
-
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
new file mode 100644
index 000000000..7d105a84b
--- /dev/null
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
@@ -0,0 +1,427 @@
+/*
+ * 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 commands.h
+ * @brief All hicn-light commands: 14 in total.
+ *
+ * Header and payload in binary format.
+ */
+
+#ifndef HICN_CTRL_HICNLIGHTNG_H
+#define HICN_CTRL_HICNLIGHTNG_H
+
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <hicn/policy.h>
+#include <hicn/strategy.h>
+#include <hicn/util/ip_address.h>
+
+#define SYMBOLIC_NAME_LEN 16
+
+typedef struct in6_addr ipv6_addr_t;
+typedef uint32_t ipv4_addr_t;
+
+typedef enum {
+ MESSAGE_COMMAND_SUBTYPE_UNDEFINED,
+ REQUEST_LIGHT = 0xc0, // this is a command
+ RESPONSE_LIGHT,
+ ACK_LIGHT,
+ NACK_LIGHT,
+ NOTIFICATION_LIGHT,
+ MESSAGE_COMMAND_SUBTYPE_N
+} message_command_subtype_t;
+
+#define message_type_is_valid(message_type) \
+ ((message_type != MESSAGE_TYPE_UNDEFINED) && \
+ (message_type != MESSAGE_COMMAND_SUBTYPE_N))
+
+#define message_type_from_uchar(x) \
+ (((x) < REQUEST_LIGHT) || (((x) >= MESSAGE_COMMAND_SUBTYPE_N)) \
+ ? MESSAGE_COMMAND_SUBTYPE_N \
+ : (message_command_subtype_t)(x))
+
+#define foreach_command_type \
+ _(listener_add, LISTENER_ADD) \
+ _(listener_remove, LISTENER_REMOVE) \
+ _(listener_list, LISTENER_LIST) \
+ _(connection_add, CONNECTION_ADD) \
+ _(connection_remove, CONNECTION_REMOVE) \
+ _(connection_list, CONNECTION_LIST) \
+ _(connection_set_admin_state, CONNECTION_SET_ADMIN_STATE) \
+ _(connection_update, CONNECTION_UPDATE) \
+ _(connection_set_priority, CONNECTION_SET_PRIORITY) \
+ _(connection_set_tags, CONNECTION_SET_TAGS) \
+ _(route_add, ROUTE_ADD) \
+ _(route_remove, ROUTE_REMOVE) \
+ _(route_list, ROUTE_LIST) \
+ _(cache_set_store, CACHE_SET_STORE) \
+ _(cache_set_serve, CACHE_SET_SERVE) \
+ _(cache_clear, CACHE_CLEAR) \
+ _(cache_list, CACHE_LIST) \
+ _(strategy_set, STRATEGY_SET) \
+ _(strategy_add_local_prefix, STRATEGY_ADD_LOCAL_PREFIX) \
+ _(wldr_set, WLDR_SET) \
+ _(punting_add, PUNTING_ADD) \
+ _(mapme_enable, MAPME_ENABLE) \
+ _(mapme_set_discovery, MAPME_SET_DISCOVERY) \
+ _(mapme_set_timescale, MAPME_SET_TIMESCALE) \
+ _(mapme_set_retx, MAPME_SET_RETX) \
+ _(mapme_send_update, MAPME_SEND_UPDATE) \
+ _(policy_add, POLICY_ADD) \
+ _(policy_remove, POLICY_REMOVE) \
+ _(policy_list, POLICY_LIST) \
+ _(subscription_add, SUBSCRIPTION_ADD) \
+ _(subscription_remove, SUBSCRIPTION_REMOVE)
+
+typedef enum {
+ COMMAND_TYPE_UNDEFINED,
+#define _(l, u) COMMAND_TYPE_##u,
+ foreach_command_type
+#undef _
+ COMMAND_TYPE_N,
+} command_type_t;
+
+extern const char *command_type_str[];
+
+#define command_type_str(x) command_type_str[x]
+
+#define command_type_is_valid(command_type) \
+ ((command_type != COMMAND_TYPE_UNDEFINED) && (command_type != COMMAND_TYPE_N))
+
+#define command_type_from_uchar(x) \
+ (((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x))
+
+/* Should be at least 8 bytes */
+typedef struct {
+ uint8_t message_type;
+ uint8_t command_id;
+ uint16_t length; /* Number of structures in the payload */
+ uint32_t seq_num;
+} cmd_header_t;
+
+typedef struct {
+ cmd_header_t header;
+} msg_header_t;
+
+/* Listener */
+
+typedef struct {
+ char symbolic[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint16_t port;
+ uint8_t family;
+ uint8_t type;
+} cmd_listener_add_t;
+
+typedef struct {
+ char symbolicOrListenerid[SYMBOLIC_NAME_LEN];
+} cmd_listener_remove_t;
+
+typedef struct {
+ void *_; // Otherwise empty structs result in clang build error
+} cmd_listener_list_t;
+
+// Sync this struct with `hc_listener_t` in `api.h`
+typedef struct {
+ char name[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
+ uint32_t id;
+ uint8_t type;
+ uint8_t family;
+ ip_address_t address;
+ uint16_t port;
+} cmd_listener_list_item_t;
+
+/* Connection */
+
+typedef struct {
+ char symbolic[SYMBOLIC_NAME_LEN];
+ // char interface_name[SYMBOLIC_NAME_LEN];
+ ip_address_t remote_ip;
+ ip_address_t local_ip;
+ uint16_t remote_port;
+ uint16_t local_port;
+ uint8_t family;
+ uint8_t type;
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+} cmd_connection_add_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+} cmd_connection_remove_t;
+
+typedef struct {
+ void *_;
+} cmd_connection_list_t;
+
+// Sync this struct with `hc_connection_t` in `api.h`
+typedef struct {
+ uint32_t id;
+ char name[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
+ uint8_t type;
+ uint8_t family;
+ ip_address_t local_addr;
+ uint16_t local_port;
+ ip_address_t remote_addr;
+ uint16_t remote_port;
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+ uint8_t state;
+} cmd_connection_list_item_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint8_t admin_state;
+ uint8_t pad8[3];
+} cmd_connection_set_admin_state_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint8_t admin_state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags;
+#endif /* WITH_POLICY */
+} cmd_connection_update_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint32_t priority;
+} cmd_connection_set_priority_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ policy_tags_t tags;
+} cmd_connection_set_tags_t;
+
+/* Route */
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint16_t cost;
+ uint8_t family;
+ uint8_t len;
+} cmd_route_add_t;
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+} cmd_route_remove_t;
+
+typedef struct {
+ void *_;
+} cmd_route_list_t;
+
+// Sync this struct with `hc_route_t` in `api.h`
+typedef struct {
+ ip_address_t address;
+ uint32_t connection_id;
+ uint16_t cost;
+ uint8_t family;
+ uint8_t len;
+} cmd_route_list_item_t;
+
+/* Cache */
+
+typedef struct {
+ uint8_t activate;
+} cmd_cache_set_store_t;
+
+typedef struct {
+ uint8_t activate;
+} cmd_cache_set_serve_t;
+
+typedef struct {
+ void *_;
+} cmd_cache_clear_t;
+
+typedef struct {
+ void *_;
+} cmd_cache_list_t;
+
+typedef struct {
+ uint8_t store_in_cs;
+ uint8_t serve_from_cs;
+ uint32_t cs_size;
+ uint32_t num_stale_entries;
+} cmd_cache_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_cache_list_reply_t payload;
+} msg_cache_list_reply_t;
+
+/* WLDR */
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ uint8_t activate;
+} cmd_wldr_set_t;
+
+/* Strategy */
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ uint8_t type;
+ uint8_t related_prefixes;
+ union {
+ struct {
+ ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ uint8_t families[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ } low_latency;
+ };
+} cmd_strategy_set_t;
+
+typedef struct {
+ uint8_t type;
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ ip_address_t local_address;
+ uint8_t local_family;
+ uint8_t local_len;
+} cmd_strategy_add_local_prefix_t;
+
+/* Punting */
+
+typedef struct {
+ char symbolic_or_connid[SYMBOLIC_NAME_LEN];
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+} cmd_punting_add_t;
+
+/* MAP-Me */
+
+typedef struct {
+ uint8_t activate;
+} cmd_mapme_activator_t;
+
+typedef cmd_mapme_activator_t cmd_mapme_enable_t;
+typedef cmd_mapme_activator_t cmd_mapme_set_discovery_t;
+
+typedef struct {
+ uint32_t timePeriod;
+} cmd_mapme_timing_t;
+
+typedef cmd_mapme_timing_t cmd_mapme_set_timescale_t;
+typedef cmd_mapme_timing_t cmd_mapme_set_retx_t;
+
+typedef struct {
+ void *_;
+} cmd_mapme_send_update_t;
+
+/* Policy */
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ hicn_policy_t policy;
+} cmd_policy_add_t;
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+} cmd_policy_remove_t;
+
+typedef struct {
+ void *_;
+} cmd_policy_list_t;
+
+typedef struct {
+ ip_address_t address;
+ uint8_t family;
+ uint8_t len;
+ hicn_policy_t policy;
+} cmd_policy_list_item_t;
+
+/* Subscription */
+
+typedef struct {
+ uint32_t topics;
+} cmd_subscription_add_t;
+
+typedef struct {
+ uint32_t topics;
+} cmd_subscription_remove_t;
+
+/* Full messages */
+
+#define _(l, u) \
+ typedef struct { \
+ cmd_header_t header; \
+ cmd_##l##_t payload; \
+ } msg_##l##_t;
+foreach_command_type
+#undef _
+
+ typedef struct {
+ cmd_header_t header;
+ cmd_listener_list_item_t payload;
+} msg_listener_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_connection_list_item_t payload;
+} msg_connection_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_route_list_item_t payload;
+} msg_route_list_reply_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_policy_list_item_t payload;
+} msg_policy_list_reply_t;
+
+//===== size of commands ======
+// REMINDER: when a new_command is added, the following switch has to be
+// updated.
+static inline int command_get_payload_len(command_type_t command_type) {
+ switch (command_type) {
+#define _(l, u) \
+ case COMMAND_TYPE_##u: \
+ return sizeof(cmd_##l##_t);
+ foreach_command_type
+#undef _
+ case COMMAND_TYPE_UNDEFINED : case COMMAND_TYPE_N : return 0;
+ }
+}
+#endif /* HICN_CTRL_HICNLIGHTNG_H */
diff --git a/hicn-light/src/hicn/utils/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h
index 3758f0f41..69ede1985 100644
--- a/hicn-light/src/hicn/utils/commands.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,8 +20,8 @@
* Header and payload in binary format.
*/
-#ifndef commands_h
-#define commands_h
+#ifndef HICN_CTRL_HICNLIGHT_H
+#define HICN_CTRL_HICNLIGHT_H
#ifndef _WIN32
#include <netinet/in.h>
@@ -43,7 +43,7 @@ typedef struct in6_addr ipv6_addr_t;
typedef uint32_t ipv4_addr_t;
typedef enum {
- REQUEST_LIGHT = 0xc0, // this is a command
+ REQUEST_LIGHT = 0xc0, // this is a command
RESPONSE_LIGHT,
ACK_LIGHT,
NACK_LIGHT,
@@ -133,7 +133,7 @@ typedef struct {
typedef struct {
char symbolic[SYMBOLIC_NAME_LEN];
- //char interfaceName[SYMBOLIC_NAME_LEN];
+ // char interfaceName[SYMBOLIC_NAME_LEN];
ip_address_t remoteIp;
ip_address_t localIp;
uint16_t remotePort;
@@ -415,7 +415,7 @@ static inline int payloadLengthDaemon(command_id id) {
case ADD_POLICY:
return sizeof(add_policy_command);
case LIST_POLICIES:
- return 0; // list policies: payload always 0
+ return 0; // list policies: payload always 0
case REMOVE_POLICY:
return sizeof(remove_policy_command);
case UPDATE_CONNECTION:
@@ -431,4 +431,4 @@ static inline int payloadLengthDaemon(command_id id) {
return 0;
}
}
-#endif
+#endif /* HICN_CTRL_HICNLIGHT_H */
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
index d7ef6a26f..81f011d4d 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,7 +21,7 @@
#define HICN_ROUTE_H
#include <hicn/util/ip_address.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
typedef u16 route_cost_t;
@@ -30,18 +30,23 @@ typedef struct hicn_route_s hicn_route_t;
#define MAXSZ_ROUTE_ MAXSZ_PREFIX + 3 + MAXSZ_COST
#define MAXSZ_ROUTE MAXSZ_ROUTE_ + NULLTERM
-hicn_route_t * hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost);
-hicn_route_t * hicn_route_dup(const hicn_route_t * route);
-void hicn_route_free(hicn_route_t * route);
+#define MIN_ROUTE_COST 1
+#define MAX_ROUTE_COST 255
+#define IS_VALID_ROUTE_COST(x) ((x >= MIN_ROUTE_COST) && (x <= MAX_ROUTE_COST))
-int hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2);
+hicn_route_t* hicn_route_create(ip_prefix_t* prefix, face_id_t face_id,
+ route_cost_t cost);
+hicn_route_t* hicn_route_dup(const hicn_route_t* route);
+void hicn_route_free(hicn_route_t* route);
-int hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix);
-int hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix);
+int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2);
-int hicn_route_get_cost(const hicn_route_t * route, int * cost);
-int hicn_route_set_cost(hicn_route_t * route, const int cost);
+int hicn_route_get_prefix(const hicn_route_t* route, ip_prefix_t* prefix);
+int hicn_route_set_prefix(hicn_route_t* route, const ip_prefix_t prefix);
-size_t hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route);
+int hicn_route_get_cost(const hicn_route_t* route, int* cost);
+int hicn_route_set_cost(hicn_route_t* route, const int cost);
+
+size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route);
#endif
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index f9934d70e..c8a93c56c 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,80 +11,127 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-list(APPEND COMPILER_DEFINITIONS
- "-DWITH_POLICY"
-)
-
+##############################################################
+# Source files
+##############################################################
set(SOURCE_FILES
- face.c
- route.c
- api.c
+ route.c
+ api.c
)
set(HEADER_FILES
- api_private.h
+ api_private.h
)
+
+##############################################################
+# Libraries to link
+##############################################################
set(LIBRARIES
- m
- dl
- ${HICN_LIBRARIES}
+ m
+ dl
+ ${HICN_LIBRARIES}
)
+
+##############################################################
+# Include directories
+##############################################################
set(INCLUDE_DIRS
+ PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/../includes/
- ${HICN_INCLUDE_DIRS}
+ PUBLIC
+ $<BUILD_INTERFACE:${Libhicnctrl_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
-# Android requires static libraries
+
+##############################################################
+# Library type
+##############################################################
if (DISABLE_SHARED_LIBRARIES)
- set(LIBRARIES ${LIBRARIES} ${LIBHICN_STATIC})
- set(LINK_TYPE STATIC)
+ set(LIBRARIES ${LIBRARIES} ${LIBHICN_STATIC})
+ set(LINK_TYPE STATIC)
else ()
- set(LINK_TYPE SHARED STATIC)
+ set(LINK_TYPE SHARED STATIC)
endif ()
+
+##############################################################
+# Do not use modules if Android
+##############################################################
if (${CMAKE_SYSTEM_NAME} MATCHES Android)
- list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_api.c
- )
+ list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_common.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_ng_api.c
+ )
else()
- add_subdirectory(modules)
+ add_subdirectory(modules)
endif()
+
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build main hicnctrl library
+##############################################################
build_library(${LIBHICNCTRL}
- ${LINK_TYPE}
- SOURCES ${SOURCE_FILES} ${HEADER_FILES}
- INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
+ ${LINK_TYPE}
+ SOURCES ${SOURCE_FILES} ${HEADER_FILES}
+ INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ DEFINITIONS PUBLIC ${COMPILER_DEFINITIONS}
+ VERSION ${CURRENT_VERSION}
+ EXPORT_NAME "${LIBHICNCTRL_COMPONENT}"
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Cmake config files
+##############################################################
+create_cmake_config (
+ ${LIBHICNCTRL_COMPONENT}
+ INCLUDE_DIRS ${Libhicnctrl_INCLUDE_DIRS}
+ VERSION ${CURRENT_VERSION}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ NAMESPACE hicn
+)
+
+
+##############################################################
+# Build executables
+##############################################################
+if (NOT DISABLE_EXECUTABLES)
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC})
+ set(DEPENDENCIES ${LIBHICNCTRL_STATIC})
+ else ()
+ set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
+ set(DEPENDENCIES ${LIBHICNCTRL_SHARED})
+ endif ()
+
+ list(APPEND DAEMON_SRC
+ hicnctrl.c
+ )
+
+ build_executable(${HICNCTRL}
+ SOURCES ${DAEMON_SRC}
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBHICNCTRL_COMPONENT}
INCLUDE_DIRS ${INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
-)
-
-if (NOT DISABLE_EXECUTABLES)
- if (DISABLE_SHARED_LIBRARIES)
- set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC})
- set(DEPENDENCIES ${LIBHICNCTRL_STATIC})
- else ()
- set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
- set(DEPENDENCIES ${LIBHICNCTRL_SHARED})
- endif ()
-
- list(APPEND DAEMON_SRC
- cli.c
- )
-
- build_executable(${HICNCTRL}
- SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${LIBRARIES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${LIBHICNCTRL_COMPONENT}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- LINK_FLAGS ${LINK_FLAGS}
- )
+ LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ )
endif ()
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 4bb66c784..4156ceff9 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,22 +18,26 @@
* \brief Implementation of hICN control library API
*/
+#include <assert.h>
+#include <dlfcn.h> // dlopen
+#include <hicn/strategy.h>
#include <hicn/util/log.h>
-#include "api_private.h"
+#include <hicn/ctrl/route.h>
+#include <math.h> // log2
-#include <math.h> // log2
-#include <dlfcn.h> // dlopen
+#include "api_private.h"
+#if 0
/* /!\ Please update constants in public header file upon changes */
const char * connection_state_str[] = {
-#define _(x) [HC_CONNECTION_STATE_ ## x] = STRINGIZE(x),
+#define _(x) [HC_CONNECTION_STATE_##x] = STRINGIZE(x),
foreach_connection_state
#undef _
};
/* /!\ Please update constants in public header file upon changes */
const char * connection_type_str[] = {
-#define _(x) [CONNECTION_TYPE_ ## x] = STRINGIZE(x),
+#define _(x) [CONNECTION_TYPE_##x] = STRINGIZE(x),
foreach_connection_type
#undef _
};
@@ -48,151 +52,72 @@ connection_type_from_str(const char * str)
else if (strcasecmp(str, "HICN") == 0)
return CONNECTION_TYPE_HICN;
else
- return CONNECTION_TYPE_UNDEFINED;
+ return CONNECTION_TYPE_UNDEFINED;
}
-
-/* Conversions to shield lib user from heterogeneity */
-
-#define IS_VALID_LIST_CONNECTIONS_TYPE(x) ((x >= CONN_GRE) && (x <= CONN_HICN))
-
-const hc_connection_type_t map_from_list_connections_type[] = {
- [CONN_GRE] = CONNECTION_TYPE_UNDEFINED,
- [CONN_TCP] = CONNECTION_TYPE_TCP,
- [CONN_UDP] = CONNECTION_TYPE_UDP,
- [CONN_MULTICAST] = CONNECTION_TYPE_UNDEFINED,
- [CONN_L2] = CONNECTION_TYPE_UNDEFINED,
- [CONN_HICN] = CONNECTION_TYPE_HICN,
-};
-
-#define IS_VALID_LIST_LISTENERS_TYPE(x) ((x >= ENCAP_TCP) && (x <= ENCAP_HICN))
-
-const hc_connection_type_t map_from_encap_type[] = {
- [ENCAP_TCP] = CONNECTION_TYPE_TCP,
- [ENCAP_UDP] = CONNECTION_TYPE_UDP,
- [ENCAP_ETHER] = CONNECTION_TYPE_UNDEFINED,
- [ENCAP_LOCAL] = CONNECTION_TYPE_UNDEFINED,
- [ENCAP_HICN] = CONNECTION_TYPE_HICN,
-};
-
-const connection_type map_to_connection_type[] = {
- [CONNECTION_TYPE_TCP] = TCP_CONN,
- [CONNECTION_TYPE_UDP] = UDP_CONN,
- [CONNECTION_TYPE_HICN] = HICN_CONN,
-};
-
-const listener_mode map_to_listener_mode[] = {
- [CONNECTION_TYPE_TCP] = IP_MODE,
- [CONNECTION_TYPE_UDP] = IP_MODE,
- [CONNECTION_TYPE_HICN] = HICN_MODE,
-};
-
-#define IS_VALID_LIST_CONNECTIONS_STATE(x) ((x >= IFACE_UP) && (x <= IFACE_UNKNOWN))
-
-/*
-#define IS_VALID_CONNECTION_STATE(x) IS_VALID_ENUM_TYPE(CONNECTION_STATE, x)
-
-static const connection_state map_to_connection_state[] = {
- [HC_CONNECTION_STATE_UP] = IFACE_UP,
- [HC_CONNECTION_STATE_DOWN] = IFACE_DOWN,
-};
-
-*/
-
-const hc_connection_state_t map_from_list_connections_state[] = {
- [IFACE_UP] = HC_CONNECTION_STATE_UP,
- [IFACE_DOWN] = HC_CONNECTION_STATE_DOWN,
- [IFACE_UNKNOWN] = HC_CONNECTION_STATE_UNDEFINED,
-};
-
-
-const int map_from_addr_type[] = {
- [ADDR_INET] = AF_INET,
- [ADDR_INET6] = AF_INET6,
- [ADDR_LINK] = AF_UNSPEC,
- [ADDR_IFACE] = AF_UNSPEC,
- [ADDR_UNIX] = AF_UNSPEC,
-};
-
-const address_type map_to_addr_type[] = {
- [AF_INET] = ADDR_INET,
- [AF_INET6] = ADDR_INET6,
-};
+#endif
/******************************************************************************
* Control Data
******************************************************************************/
-hc_data_t *
-hc_data_create(size_t in_element_size, size_t out_element_size, data_callback_t complete_cb)
-{
- hc_data_t * data = malloc(sizeof(hc_data_t));
- if (!data)
- goto ERR_MALLOC;
-
- /* FIXME Could be NULL thanks to realloc provided size is 0 */
- data->max_size_log = DEFAULT_SIZE_LOG;
- data->in_element_size = in_element_size;
- data->out_element_size = out_element_size;
- data->size = 0;
- data->complete = false;
- data->command_id = 0; // TODO this could also be a busy mark in the socket
- /* No callback needed in blocking code for instance */
- data->complete_cb = complete_cb;
-
- data->buffer = malloc((1 << data->max_size_log) * data->out_element_size);
- if (!data->buffer)
- goto ERR_BUFFER;
- data->ret = 0;
-
- return data;
+hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size,
+ data_callback_t complete_cb) {
+ hc_data_t *data = malloc(sizeof(hc_data_t));
+ if (!data) goto ERR_MALLOC;
+
+ /* FIXME Could be NULL thanks to realloc provided size is 0 */
+ data->max_size_log = DEFAULT_SIZE_LOG;
+ data->in_element_size = in_element_size;
+ data->out_element_size = out_element_size;
+ data->size = 0;
+ data->complete = false;
+ data->command_id = 0; // TODO this could also be a busy mark in the socket
+ /* No callback needed in blocking code for instance */
+ data->complete_cb = complete_cb;
+
+ data->buffer = malloc((1 << data->max_size_log) * data->out_element_size);
+ if (!data->buffer) goto ERR_BUFFER;
+ data->ret = 0;
+ data->current = 0;
+
+ return data;
ERR_BUFFER:
- hc_data_free(data);
+ hc_data_free(data);
ERR_MALLOC:
- return NULL;
+ return NULL;
}
-void
-hc_data_free(hc_data_t * data)
-{
- if (data->buffer)
- free(data->buffer);
- free(data);
+void hc_data_free(hc_data_t *data) {
+ if (data) free(data->buffer);
+ free(data);
}
-int
-hc_data_ensure_available(hc_data_t * data, size_t count)
-{
- size_t new_size_log = (data->size + count - 1 > 0)
- ? log2(data->size + count - 1) + 1
- : 0;
- if (new_size_log > data->max_size_log) {
- data->max_size_log = new_size_log;
- data->buffer = realloc(data->buffer, (1 << new_size_log) * data->out_element_size);
- if (!data->buffer)
- return -1;
- }
+int hc_data_ensure_available(hc_data_t *data, size_t count) {
+ size_t new_size_log =
+ (data->size + count - 1 > 0) ? log2(data->size + count - 1) + 1 : 0;
+ if (new_size_log > data->max_size_log) {
+ data->max_size_log = new_size_log;
+ data->buffer =
+ realloc(data->buffer, (1 << new_size_log) * data->out_element_size);
+ if (!data->buffer) return -1;
+ }
- return 0;
+ return 0;
}
-int
-hc_data_push_many(hc_data_t * data, const void * elements, size_t count)
-{
- if (hc_data_ensure_available(data, count) < 0)
- return -1;
+int hc_data_push_many(hc_data_t *data, const void *elements, size_t count) {
+ if (hc_data_ensure_available(data, count) < 0) return -1;
- memcpy(data->buffer + data->size * data->out_element_size, elements,
- count * data->out_element_size);
- data->size += count;
+ memcpy(data->buffer + data->size * data->out_element_size, elements,
+ count * data->out_element_size);
+ data->size += count;
- return 0;
+ return 0;
}
-int
-hc_data_push(hc_data_t * data, const void * element)
-{
- return hc_data_push_many(data, element, 1);
+int hc_data_push(hc_data_t *data, const void *element) {
+ return hc_data_push_many(data, element, 1);
}
/**
@@ -200,61 +125,48 @@ hc_data_push(hc_data_t * data, const void * element)
* NOTE: This function make sure there is enough room available in the data
* structure.
*/
-u8 *
-hc_data_get_next(hc_data_t * data)
-{
- if (hc_data_ensure_available(data, 1) < 0)
- return NULL;
+u8 *hc_data_get_next(hc_data_t *data) {
+ if (hc_data_ensure_available(data, 1) < 0) return NULL;
- return data->buffer + data->size * data->out_element_size;
+ return data->buffer + data->size * data->out_element_size;
}
-int
-hc_data_set_callback(hc_data_t * data, data_callback_t cb, void * cb_data)
-{
- data->complete_cb = cb;
- data->complete_cb_data = cb_data;
- return 0;
+int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data) {
+ data->complete_cb = cb;
+ data->complete_cb_data = cb_data;
+ return 0;
}
-int
-hc_data_set_complete(hc_data_t * data)
-{
- data->complete = true;
- data->ret = 0;
- if (data->complete_cb)
- return data->complete_cb(data, data->complete_cb_data);
- return 0;
+int hc_data_set_complete(hc_data_t *data) {
+ data->complete = true;
+ data->ret = 0;
+ if (data->complete_cb) return data->complete_cb(data, data->complete_cb_data);
+ return 0;
}
-int
-hc_data_set_error(hc_data_t * data)
-{
- data->ret = -1;
- return 0;
+int hc_data_set_error(hc_data_t *data) {
+ data->ret = -1;
+ return 0;
}
-int
-hc_data_reset(hc_data_t * data)
-{
- data->size = 0;
- return 0;
+int hc_data_reset(hc_data_t *data) {
+ data->size = 0;
+ return 0;
}
-static hc_sock_t * _open_module(const char *name)
-{
+static hc_sock_t *_open_module(const char *name, const char *url) {
char complete_name[128];
#ifdef __APPLE__
- sprintf(complete_name, "%s.dylib", name);
+ snprintf(complete_name, 128, "%s.dylib", name);
#elif defined(__linux__)
- sprintf(complete_name, "%s.so", name);
+ snprintf(complete_name, 128, "%s.so", name);
#else
- #error "System not supported for dynamic lynking"
+#error "System not supported for dynamic lynking"
#endif
void *handle = 0;
const char *error = 0;
- hc_sock_t *(*creator)(void) = 0;
+ hc_sock_t *(*creator)(const char *) = 0;
hc_sock_t *ret = 0;
// open module
@@ -263,307 +175,305 @@ static hc_sock_t * _open_module(const char *name)
if ((error = dlerror()) != 0) {
ERROR("%s", error);
}
-
return 0;
}
// get factory method
- creator = (hc_sock_t * (*)(void)) dlsym(handle, "_hc_sock_create");
+ creator =
+ (hc_sock_t * (*)(const char *)) dlsym(handle, "_hc_sock_create_url");
if (!creator) {
if ((error = dlerror()) != 0) {
ERROR("%s", error);
- return 0;
}
+ return 0;
}
- ret = (*creator)();
+ ret = (*creator)(NULL);
ret->handle = handle;
return ret;
}
-hc_sock_t *hc_sock_create_forwarder(forwarder_t forwarder)
-{
- switch (forwarder)
- {
- case HICNLIGHT:
- return _open_module("hicnlightctrl_module");
- case VPP:
- return _open_module("vppctrl_module");
- default:
- return NULL;
- }
+hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder,
+ const char *url) {
+ switch (forwarder) {
+ case HICNLIGHT:
+ return _open_module("hicnlightctrl_module", url);
+ case HICNLIGHT_NG:
+ return _open_module("hicnlightngctrl_module", url);
+ case VPP:
+ return _open_module("vppctrl_module", url);
+ default:
+ return NULL;
+ }
}
#ifdef ANDROID
// In android we do not load a module at runtime
// but we link the hicnlight implmentation directly
// to the main library
-extern hc_sock_t *_hc_sock_create();
+extern hc_sock_t *_hc_sock_create_url(const char *url);
#endif
-hc_sock_t *hc_sock_create(void)
-{
+hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder) {
#ifdef ANDROID
- hc_sock_t *ret = _hc_sock_create();
- ret->handle = NULL;
- return ret;
+ assert(forwarder == HICNLIGHT_NG);
+ hc_sock_t *ret = _hc_sock_create_url(NULL);
+ ret->handle = NULL;
+ return ret;
#else
- return hc_sock_create_forwarder(HICNLIGHT);
+ return hc_sock_create_forwarder_url(forwarder, NULL);
#endif
}
-void hc_sock_free(hc_sock_t *s)
-{
- void *handle = s->handle;
- s->hc_sock_free(s);
-
- if (handle) {
- dlclose(handle);
- }
+hc_sock_t *hc_sock_create(void) {
+ return hc_sock_create_forwarder(HICNLIGHT_NG);
}
-int hc_sock_get_next_seq(hc_sock_t *s)
-{
- return s->hc_sock_get_next_seq(s);
-}
+void hc_sock_free(hc_sock_t *s) {
+ void *handle = s->handle;
+ s->hc_sock_free(s);
-int hc_sock_set_nonblocking(hc_sock_t *s)
-{
- return s->hc_sock_get_next_seq(s);
+ if (handle) {
+ dlclose(handle);
+ }
}
-int hc_sock_get_fd(hc_sock_t *s)
-{
- return s->hc_sock_get_fd(s);
+int hc_sock_get_next_seq(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); }
+
+int hc_sock_set_nonblocking(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); }
+
+int hc_sock_get_fd(hc_sock_t *s) { return s->hc_sock_get_fd(s); }
+
+int hc_sock_connect(hc_sock_t *s) { return s->hc_sock_connect(s); }
+
+int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size) {
+ return s->hc_sock_get_available(s, buffer, size);
}
-int hc_sock_connect(hc_sock_t *s)
-{
- return s->hc_sock_connect(s);
+int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq) {
+ return s->hc_sock_send(s, msg, msglen, seq);
}
-int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size)
-{
- return s->hc_sock_get_available(s, buffer, size);
+int hc_sock_recv(hc_sock_t *s) { return s->hc_sock_recv(s); }
+
+int hc_sock_process(hc_sock_t *s, hc_data_t **data) {
+ return s->hc_sock_process(s, data);
}
-int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq)
-{
- return s->hc_sock_send(s, msg, msglen, seq);
+int hc_sock_callback(hc_sock_t *s, hc_data_t **data) {
+ return s->hc_sock_callback(s, data);
}
-int hc_sock_recv(hc_sock_t *s)
-{
- return s->hc_sock_recv(s);
+int hc_sock_reset(hc_sock_t *s) { return s->hc_sock_reset(s); }
+
+void hc_sock_increment_woff(hc_sock_t *s, size_t bytes) {
+ s->hc_sock_increment_woff(s, bytes);
}
-int hc_sock_process(hc_sock_t *s, hc_data_t **data)
-{
- return s->hc_sock_process(s, data);
+int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result,
+ data_callback_t complete_cb, void *complete_cb_data) {
+ return s->hc_sock_prepare_send(s, result, complete_cb, complete_cb_data);
}
-int hc_sock_callback(hc_sock_t *s, hc_data_t **data)
-{
- return s->hc_sock_callback(s, data);
+int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms) {
+ return s->hc_sock_set_recv_timeout_ms(s, timeout_ms);
}
-int hc_sock_reset(hc_sock_t *s)
-{
- return s->hc_sock_reset(s);
+/*----------------------------------------------------------------------------*
+ * LISTENER
+ *----------------------------------------------------------------------------*/
+
+int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) {
+ return s->hc_listener_create(s, listener);
}
-int hc_listener_create(hc_sock_t *s, hc_listener_t *listener)
-{
- return s->hc_listener_create(s, listener);
+hc_result_t *hc_listener_create_conf(hc_sock_t *s, hc_listener_t *listener) {
+ return s->hc_listener_create_conf(s, listener);
}
int hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
- hc_listener_t **listener_found)
-{
- return s->hc_listener_get(s, listener, listener_found);
+ hc_listener_t **listener_found) {
+ return s->hc_listener_get(s, listener, listener_found);
}
-int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener)
-{
- return s->hc_listener_delete(s, listener);
+int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
+ return s->hc_listener_delete(s, listener);
}
-int hc_listener_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_listener_list(s, pdata);
+int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_listener_list(s, pdata);
}
GENERATE_FIND(listener);
/* LISTENER VALIDATE */
-int
-hc_listener_validate(const hc_listener_t * listener)
-{
- if (!IS_VALID_FAMILY(listener->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return -1;
+int hc_listener_validate(const hc_listener_t *listener) {
+ if (!IS_VALID_NAME(listener->name)) {
+ ERROR("[hc_listener_validate] Invalid name specified");
+ return -1;
+ }
+ if (!IS_VALID_INTERFACE_NAME(listener->interface_name)) {
+ ERROR("[hc_listener_validate] Invalid interface_name specified");
+ return -1;
+ }
+ if (!IS_VALID_TYPE(listener->type)) {
+ ERROR("[hc_listener_validate] Invalid type specified");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(listener->family)) {
+ ERROR("[hc_listener_validate] Invalid family specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&listener->local_addr, listener->family)) {
+ ERROR("[hc_listener_validate] Invalid local_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(listener->local_port)) {
+ ERROR("[hc_listener_validate] Invalid local_port specified");
+ return -1;
+ }
- return 0;
+ return 0;
}
/* LISTENER CMP */
-int
-hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2)
-{
- int rc;
-
- rc = INT_CMP(l1->type, l2->type);
- if (rc != 0)
- return rc;
-
- rc = INT_CMP(l1->family, l2->family);
- if (rc != 0)
- return rc;
+int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) {
+ int rc;
- rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(l1->type, l2->type);
+ if (rc != 0) return rc;
- rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(l1->family, l2->family);
+ if (rc != 0) return rc;
- rc = INT_CMP(l1->local_port, l2->local_port);
- if (rc != 0)
- return rc;
+ rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN);
+ if (rc != 0) return rc;
- return rc;
-}
+ rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family);
+ if (rc != 0) return rc;
-/* LISTENER PARSE */
+ rc = INT_CMP(l1->local_port, l2->local_port);
+ if (rc != 0) return rc;
-int
-hc_listener_parse(void * in, hc_listener_t * listener)
-{
- int rc;
-
- list_listeners_command * cmd = (list_listeners_command *)in;
-
- if (!IS_VALID_LIST_LISTENERS_TYPE(cmd->encapType))
- return -1;
-
- hc_connection_type_t type = map_from_encap_type[cmd->encapType];
- if (type == CONNECTION_TYPE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return -1;
-
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family))
- return -1;
-
- *listener = (hc_listener_t) {
- .id = cmd->connid,
- .type = type,
- .family = family,
- .local_addr = UNION_CAST(cmd->address, ip_address_t),
- .local_port = ntohs(cmd->port),
- };
- rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", cmd->listenerName);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_listener_parse] Unexpected truncation of symbolic name string");
- rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_listener_parse] Unexpected truncation of interface name string");
- return 0;
+ return rc;
}
/* LISTENER SNPRINTF */
/* /!\ Please update constants in header file upon changes */
-int
-hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener)
-{
- char local[MAXSZ_URL];
- int rc;
- rc = url_snprintf(local, MAXSZ_URL,
- listener->family, &listener->local_addr, listener->local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_listener_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
+int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener) {
+ char local[MAXSZ_URL];
+ int rc;
+ rc = url_snprintf(local, MAXSZ_URL, listener->family, &listener->local_addr,
+ listener->local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_listener_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
- return snprintf(s, size, "%s %s %s", listener->interface_name, local,
- connection_type_str[listener->type]);
+ return snprintf(s, size, "%s %s %s interface=%s", listener->name, local,
+ face_type_str(listener->type), listener->interface_name);
}
-int hc_connection_create(hc_sock_t *s, hc_connection_t *connection)
-{
- return s->hc_connection_create(s, connection);
+/*----------------------------------------------------------------------------*
+ * CONNECTION
+ *----------------------------------------------------------------------------*/
+
+int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
+ return s->hc_connection_create(s, connection);
+}
+
+hc_result_t *hc_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return s->hc_connection_create_conf(s, connection);
}
int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
- hc_connection_t **connection_found)
-{
- return s->hc_connection_get(s, connection, connection_found);
+ hc_connection_t **connection_found) {
+ return s->hc_connection_get(s, connection, connection_found);
}
int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
- hc_connection_t *connection)
-{
- return s->hc_connection_update_by_id(s, hc_connection_id, connection);
+ hc_connection_t *connection) {
+ return s->hc_connection_update_by_id(s, hc_connection_id, connection);
}
int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
- hc_connection_t *connection_updated)
-{
- return s->hc_connection_update(s, connection_current, connection_updated);
+ hc_connection_t *connection_updated) {
+ return s->hc_connection_update(s, connection_current, connection_updated);
}
-int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection)
-{
- return s->hc_connection_delete(s, connection);
+int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
+ return s->hc_connection_delete(s, connection);
}
-int hc_connection_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_connection_list(s, pdata);
+hc_result_t *hc_connection_delete_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return s->hc_connection_delete_conf(s, connection);
}
-int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state)
-{
- return s->hc_connection_set_admin_state(s, conn_id_or_name, state);
+int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_connection_list(s, pdata);
+}
+
+int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state) {
+ return s->hc_connection_set_admin_state(s, conn_id_or_name, state);
}
#ifdef WITH_POLICY
-int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority)
-{
- return s->hc_connection_set_priority(s, conn_id_or_name, priority);
+int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return s->hc_connection_set_priority(s, conn_id_or_name, priority);
}
-int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags)
-{
- return s->hc_connection_set_tags(s, conn_id_or_name, tags);
+int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return s->hc_connection_set_tags(s, conn_id_or_name, tags);
}
-#endif // WITH_POLICY
+#endif // WITH_POLICY
GENERATE_FIND(connection);
/* CONNECTION VALIDATE */
-int
-hc_connection_validate(const hc_connection_t * connection)
-{
- if (!IS_VALID_FAMILY(connection->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(connection->type))
- return -1;
-
- /* TODO assert both local and remote have the right family */
+int hc_connection_validate(const hc_connection_t *connection) {
+ if (!IS_VALID_NAME(connection->name)) {
+ ERROR("[hc_connection_validate] Invalid name specified");
+ return -1;
+ }
+ if (!IS_VALID_INTERFACE_NAME(connection->interface_name)) {
+ ERROR("[hc_connection_validate] Invalid interface_name specified");
+ return -1;
+ }
+ if (!IS_VALID_TYPE(connection->type)) {
+ ERROR("[hc_connection_validate] Invalid type specified");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(connection->family)) {
+ ERROR("[hc_connection_validate] Invalid family specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&connection->local_addr, connection->family)) {
+ ERROR("[hc_connection_validate] Invalid local_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(connection->local_port)) {
+ ERROR("[hc_connection_validate] Invalid local_port specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&connection->remote_addr, connection->family)) {
+ ERROR("[hc_connection_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_PORT(connection->remote_port)) {
+ ERROR("[hc_connection_validate] Invalid remote_port specified");
+ return -1;
+ }
- return 0;
+ return 0;
}
/* CONNECTION CMP */
@@ -573,719 +483,692 @@ hc_connection_validate(const hc_connection_t * connection)
* As connections are specific to hicn-light, we can safely use IP and ports for
* comparison independently of the face type.
*/
-int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2)
-{
- int rc;
+int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2) {
+ int rc;
- rc = INT_CMP(c1->type, c2->type);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->type, c2->type);
+ if (rc != 0) return rc;
- rc = INT_CMP(c1->family, c2->family);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->family, c2->family);
+ if (rc != 0) return rc;
- rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN);
- if (rc != 0)
- return rc;
+ rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN);
+ if (rc != 0) return rc;
- rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family);
- if (rc != 0)
- return rc;
+ rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family);
+ if (rc != 0) return rc;
- rc = INT_CMP(c1->local_port, c2->local_port);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->local_port, c2->local_port);
+ if (rc != 0) return rc;
- rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family);
- if (rc != 0)
- return rc;
+ rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family);
+ if (rc != 0) return rc;
- rc = INT_CMP(c1->remote_port, c2->remote_port);
- if (rc != 0)
- return rc;
+ rc = INT_CMP(c1->remote_port, c2->remote_port);
+ if (rc != 0) return rc;
- return rc;
-}
-
-/* CONNECTION PARSE */
-
-int
-hc_connection_parse(void * in, hc_connection_t * connection)
-{
- int rc;
- list_connections_command * cmd = (list_connections_command *)in;
-
- if (!IS_VALID_LIST_CONNECTIONS_TYPE(cmd->connectionData.connectionType))
- return -1;
-
- hc_connection_type_t type = map_from_list_connections_type[cmd->connectionData.connectionType];
- if (type == CONNECTION_TYPE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_LIST_CONNECTIONS_STATE(cmd->state))
- return -1;
-
- hc_connection_state_t state = map_from_list_connections_state[cmd->state];
- if (state == HC_CONNECTION_STATE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_ADDR_TYPE(cmd->connectionData.ipType))
- return -1;
-
- int family = map_from_addr_type[cmd->connectionData.ipType];
- if (!IS_VALID_FAMILY(family))
- return -1;
-
- *connection = (hc_connection_t) {
- .id = cmd->connid,
- .type = type,
- .family = family,
- .local_addr = cmd->connectionData.localIp,
- //.local_addr = UNION_CAST(cmd->connectionData.localIp, ip_address_t),
- .local_port = ntohs(cmd->connectionData.localPort),
- .remote_addr = cmd->connectionData.remoteIp,
- //.remote_addr = UNION_CAST(cmd->connectionData.remoteIp, ip_address_t),
- .remote_port = ntohs(cmd->connectionData.remotePort),
- .admin_state = cmd->connectionData.admin_state,
-#ifdef WITH_POLICY
- .priority = cmd->connectionData.priority,
- .tags = cmd->connectionData.tags,
-#endif /* WITH_POLICY */
- .state = state,
- };
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", cmd->connectionData.symbolic);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_connection_parse] Unexpected truncation of symbolic name string");
- rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_connection_parse] Unexpected truncation of interface name string");
- return 0;
+ return rc;
}
/* CONNECTION SNPRINTF */
/* /!\ Please update constants in header file upon changes */
-int
-hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection)
-{
- char local[MAXSZ_URL];
- char remote[MAXSZ_URL];
- int rc;
-
- // assert(connection->connection_state)
-
- rc = url_snprintf(local, MAXSZ_URL, connection->family,
- &connection->local_addr, connection->local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = url_snprintf(remote, MAXSZ_URL, connection->family,
- &connection->remote_addr, connection->remote_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
-
- return snprintf(s, size, "%s %s %s %s %s",
- connection_state_str[connection->state],
- connection->interface_name,
- local,
- remote,
- connection_type_str[connection->type]);
-}
-
-int hc_face_create(hc_sock_t *s, hc_face_t *face)
-{
- return s->hc_face_create(s, face);
+int hc_connection_snprintf(char *s, size_t size,
+ const hc_connection_t *connection) {
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
+ int rc;
+
+ // assert(connection->connection_state)
+ if (strcmp(connection->name, "SELF") == 0) {
+ return snprintf(s, size, "%s", connection->name);
+ }
+
+ rc = url_snprintf(local, MAXSZ_URL, connection->family,
+ &connection->local_addr, connection->local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = url_snprintf(remote, MAXSZ_URL, connection->family,
+ &connection->remote_addr, connection->remote_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_connection_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+
+ return snprintf(s, size, "%s %s %s %s", connection->name, local, remote,
+ face_type_str(connection->type));
}
-int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found)
-{
- return s->hc_face_get(s, face, face_found);
+int hc_face_create(hc_sock_t *s, hc_face_t *face) {
+ return s->hc_face_create(s, face);
}
-int hc_face_delete(hc_sock_t *s, hc_face_t *face)
-{
- return s->hc_face_delete(s, face);
+int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found) {
+ return s->hc_face_get(s, face, face_found);
}
-int hc_face_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_face_list(s, pdata);
+int hc_face_delete(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener) {
+ return s->hc_face_delete(s, face, delete_listener);
}
-int hc_face_list_async(hc_sock_t *s)
-{
- return s->hc_face_list_async(s);
+int hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_face_list(s, pdata);
}
-int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state)
-{
- return s->hc_face_set_admin_state(s, conn_id_or_name, state);
+int hc_face_list_async(hc_sock_t *s) { return s->hc_face_list_async(s); }
+
+int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state) {
+ return s->hc_face_set_admin_state(s, conn_id_or_name, state);
}
#ifdef WITH_POLICY
-int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority)
-{
- return s->hc_face_set_priority(s, conn_id_or_name, priority);
+int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return s->hc_face_set_priority(s, conn_id_or_name, priority);
}
-int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags)
-{
- return s->hc_face_set_tags(s, conn_id_or_name, tags);
+int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return s->hc_face_set_tags(s, conn_id_or_name, tags);
}
#endif /* WITH_POLICY */
/* /!\ Please update constants in header file upon changes */
-int
-hc_face_snprintf(char * s, size_t size, hc_face_t * face)
-{
- /* URLs are also big enough to contain IP addresses in the hICN case */
- char local[MAXSZ_URL];
- char remote[MAXSZ_URL];
+int hc_face_snprintf(char *s, size_t size, hc_face_t *face) {
+ /* URLs are also big enough to contain IP addresses in the hICN case */
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
#ifdef WITH_POLICY
- char tags[MAXSZ_POLICY_TAGS];
+ char tags[MAXSZ_POLICY_TAGS];
#endif /* WITH_POLICY */
- int rc;
-
- switch(face->face.type) {
- case FACE_TYPE_HICN:
- case FACE_TYPE_HICN_LISTENER:
- rc = ip_address_snprintf(local, MAXSZ_URL,
- &face->face.local_addr,
- face->face.family);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = ip_address_snprintf(remote, MAXSZ_URL,
- &face->face.remote_addr,
- face->face.family);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- break;
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- rc = url_snprintf(local, MAXSZ_URL, face->face.family,
- &face->face.local_addr,
- face->face.local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
- &face->face.remote_addr,
- face->face.remote_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- break;
- default:
- return -1;
- }
+ int rc;
+
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ rc = ip_address_snprintf(local, MAXSZ_URL, &face->face.local_addr,
+ face->face.family);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = ip_address_snprintf(remote, MAXSZ_URL, &face->face.remote_addr,
+ face->face.family);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ break;
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ rc = url_snprintf(local, MAXSZ_URL, face->face.family,
+ &face->face.local_addr, face->face.local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
+ &face->face.remote_addr, face->face.remote_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0) return rc;
+ break;
+ default:
+ return -1;
+ }
// [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS)
#ifdef WITH_POLICY
- rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
- if (rc >= MAXSZ_POLICY_TAGS)
- WARN("[hc_face_snprintf] Unexpected truncation of policy tags string");
- if (rc < 0)
- return rc;
-
- return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)",
- face->id,
- face->name,
- face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
- local,
- remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state],
- face->face.priority,
- tags);
+ rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
+ if (rc >= MAXSZ_POLICY_TAGS)
+ WARN("[hc_face_snprintf] Unexpected truncation of policy tags string");
+ if (rc < 0) return rc;
+
+ return snprintf(
+ s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", face->id, face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX
+ ? face->face.netdevice.name
+ : "*",
+ face_type_str(face->face.type), local, remote,
+ face_state_str(face->face.state), face_state_str(face->face.admin_state),
+ face->face.priority, tags);
#else
- return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s",
- face->id,
- face->name,
- face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
- local,
- remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state]);
+ return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s", face->id, face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX
+ ? face->face.netdevice.name
+ : "*",
+ face_type_str(face->face.type), local, remote,
+ face_state_str(face->face.state),
+ face_state_str(face->face.admin_state));
#endif /* WITH_POLICY */
}
-int
-hc_connection_parse_to_face(void * in, hc_face_t * face)
-{
- hc_connection_t connection;
-
- if (hc_connection_parse(in, &connection) < 0) {
- ERROR("[hc_connection_parse_to_face] Could not parse connection");
- return -1;
- }
+/*----------------------------------------------------------------------------*
+ * ROUTE
+ *----------------------------------------------------------------------------*/
- if (hc_connection_to_face(&connection, face) < 0) {
- ERROR("[hc_connection_parse_to_face] Could not convert connection to face.");
- return -1;
- }
-
- return 0;
+int hc_route_create(hc_sock_t *s, hc_route_t *route) {
+ return s->hc_route_create(s, route);
}
-int hc_route_create(hc_sock_t * s, hc_route_t * route)
-{
- return s->hc_route_create(s, route);
+hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route) {
+ return s->hc_route_create_conf(s, route);
}
-int hc_route_delete(hc_sock_t * s, hc_route_t * route)
-{
- return s->hc_route_delete(s, route);
+int hc_route_delete(hc_sock_t *s, hc_route_t *route) {
+ return s->hc_route_delete(s, route);
}
-int hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return s->hc_route_list(s, pdata);
+int hc_route_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_route_list(s, pdata);
}
-int hc_route_list_async(hc_sock_t * s)
-{
- return s->hc_route_list_async(s);
-}
+int hc_route_list_async(hc_sock_t *s) { return s->hc_route_list_async(s); }
-/* ROUTE PARSE */
+/* ROUTE SNPRINTF */
-int
-hc_route_parse(void * in, hc_route_t * route)
-{
- list_routes_command * cmd = (list_routes_command *) in;
+/* /!\ Please update constants in header file upon changes */
+int hc_route_snprintf(char *s, size_t size, hc_route_t *route) {
+ /* interface cost prefix length */
- if (!IS_VALID_ADDR_TYPE(cmd->addressType)) {
- ERROR("[hc_route_parse] Invalid address type");
- return -1;
- }
+ char prefix[MAXSZ_IP_ADDRESS];
+ int rc;
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family)) {
- ERROR("[hc_route_parse] Invalid address family");
- return -1;
- }
+ rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr,
+ route->family);
+ if (rc >= MAXSZ_IP_ADDRESS)
+ ;
+ if (rc < 0) return rc;
- *route = (hc_route_t) {
- .face_id = cmd->connid,
- .family = family,
- .remote_addr = UNION_CAST(cmd->address, ip_address_t),
- .len = cmd->len,
- .cost = cmd->cost,
- };
- return 0;
+ return snprintf(s, size, "%s %*d %s %*d conn_id=%d", route->name, MAXSZ_COST,
+ route->cost, prefix, MAXSZ_LEN, route->len, route->face_id);
}
-/* ROUTE SNPRINTF */
-
-/* /!\ Please update constants in header file upon changes */
-int
-hc_route_snprintf(char * s, size_t size, hc_route_t * route)
-{
- /* interface cost prefix length */
-
- char prefix[MAXSZ_IP_ADDRESS];
- int rc;
-
- rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr,
- route->family);
- if (rc >= MAXSZ_IP_ADDRESS)
- ;
- if (rc < 0)
- return rc;
+int hc_route_validate(const hc_route_t *route) {
+ if (!IS_VALID_ID(route->connection_id)) {
+ ERROR("[hc_route_validate] Invalid connection id");
+ return -1;
+ }
+ if (!IS_VALID_NAME(route->name) && !IS_VALID_STR_ID(route->name)) {
+ ERROR("[hc_route_validate] Invalid name specified");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(route->family)) {
+ ERROR("[hc_route_validate] Invalid family specified");
+ return -1;
+ }
+ if (!IS_VALID_ADDRESS(&route->remote_addr, route->family)) {
+ ERROR("[hc_route_validate] Invalid remote_addr specified");
+ return -1;
+ }
+ if (!IS_VALID_ROUTE_COST(route->cost)) {
+ ERROR("[hc_route_validate] Invalid cost");
+ return -1;
+ }
+ if (!IS_VALID_PREFIX_LEN(route->len)) {
+ ERROR("[hc_route_validate] Invalid len");
+ return -1;
+ }
- return snprintf(s, size, "%*d %*d %s %*d", MAXSZ_FACE_ID, route->face_id,
- MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, route->len);
+ return 0;
}
+/*----------------------------------------------------------------------------*
+ * FACE
+ *----------------------------------------------------------------------------*/
+
/* FACE -> LISTENER */
-int
-hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener)
-{
- const face_t * f = &face->face;
-
- switch(f->type) {
- case FACE_TYPE_HICN_LISTENER:
- break;
- case FACE_TYPE_TCP_LISTENER:
- break;
- case FACE_TYPE_UDP_LISTENER:
- break;
- default:
- return -1;
- }
- return -1; /* XXX Not implemented */
+int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) {
+ const face_t *f = &face->face;
+
+ switch (f->type) {
+ case FACE_TYPE_HICN_LISTENER:
+ break;
+ case FACE_TYPE_TCP_LISTENER:
+ break;
+ case FACE_TYPE_UDP_LISTENER:
+ break;
+ default:
+ return -1;
+ }
+ return -1; /* XXX Not implemented */
}
/* LISTENER -> FACE */
-int
-hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face)
-{
- return -1; /* XXX Not implemented */
+int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face) {
+ return -1; /* XXX Not implemented */
}
/* FACE -> CONNECTION */
-int
-hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name)
-{
- int rc;
- const face_t * f = &face->face;
-
- switch(f->type) {
- case FACE_TYPE_HICN:
- *connection = (hc_connection_t) {
- .type = CONNECTION_TYPE_HICN,
- .family = f->family,
- .local_addr = f->local_addr,
- .local_port = 0,
- .remote_addr = f->remote_addr,
- .remote_port = 0,
- .admin_state = face_state_to_connection_state(f->admin_state),
- .state = face_state_to_connection_state(f->state),
+int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection,
+ bool generate_name) {
+ int rc;
+
+ const face_t *f = &face->face;
+ switch (f->type) {
+ case FACE_TYPE_HICN:
+ *connection = (hc_connection_t){
+ .type = FACE_TYPE_HICN,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = 0,
+ .remote_addr = f->remote_addr,
+ .remote_port = 0,
+ .admin_state = f->admin_state,
+ .state = f->state,
#ifdef WITH_POLICY
- .priority = f->priority,
- .tags = f->tags,
+ .priority = f->priority,
+ .tags = f->tags,
#endif /* WITH_POLICY */
- };
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s",
+ };
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s",
f->netdevice.name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string");
- break;
- case FACE_TYPE_TCP:
- *connection = (hc_connection_t) {
- .type = CONNECTION_TYPE_TCP,
- .family = f->family,
- .local_addr = f->local_addr,
- .local_port = f->local_port,
- .remote_addr = f->remote_addr,
- .remote_port = f->remote_port,
- .admin_state = face_state_to_connection_state(f->admin_state),
- .state = face_state_to_connection_state(f->state),
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_face_to_connection] Unexpected truncation of symbolic "
+ "name string");
+ break;
+ case FACE_TYPE_TCP:
+ *connection = (hc_connection_t){
+ .type = FACE_TYPE_TCP,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = f->local_port,
+ .remote_addr = f->remote_addr,
+ .remote_port = f->remote_port,
+ .admin_state = f->admin_state,
+ .state = f->state,
#ifdef WITH_POLICY
- .priority = f->priority,
- .tags = f->tags,
+ .priority = f->priority,
+ .tags = f->tags,
#endif /* WITH_POLICY */
- };
- if (generate_name) {
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE());
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string");
- } else {
- memset(connection->name, 0, SYMBOLIC_NAME_LEN);
- }
- break;
- case FACE_TYPE_UDP:
- *connection = (hc_connection_t) {
- .type = CONNECTION_TYPE_UDP,
- .family = AF_INET,
- .local_addr = f->local_addr,
- .local_port = f->local_port,
- .remote_addr = f->remote_addr,
- .remote_port = f->remote_port,
- .admin_state = face_state_to_connection_state(f->admin_state),
- .state = face_state_to_connection_state(f->state),
+ };
+ if (generate_name) {
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE());
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_face_to_connection] Unexpected truncation of "
+ "symbolic name string");
+ } else {
+ memset(connection->name, 0, SYMBOLIC_NAME_LEN);
+ }
+ break;
+ case FACE_TYPE_UDP:
+ *connection = (hc_connection_t){
+ .type = FACE_TYPE_UDP,
+ .family = f->family,
+ .local_addr = f->local_addr,
+ .local_port = f->local_port,
+ .remote_addr = f->remote_addr,
+ .remote_port = f->remote_port,
+ .admin_state = f->admin_state,
+ .state = f->state,
#ifdef WITH_POLICY
- .priority = f->priority,
- .tags = f->tags,
+ .priority = f->priority,
+ .tags = f->tags,
#endif /* WITH_POLICY */
- };
- if (generate_name) {
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE());
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_face_to_connection] Unexpected truncation of symbolic name string");
- } else {
- memset(connection->name, 0, SYMBOLIC_NAME_LEN);
- }
- snprintf(connection->interface_name, INTERFACE_LEN, "%s",
- f->netdevice.name);
- break;
- default:
- return -1;
- }
+ };
+ if (generate_name) {
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE());
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_face_to_connection] Unexpected truncation of "
+ "symbolic name string");
+ } else {
+ memset(connection->name, 0, SYMBOLIC_NAME_LEN);
+ }
+ snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
+ break;
+ default:
+ return -1;
+ }
- rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s",
- f->netdevice.name);
- if (rc >= INTERFACE_LEN)
- WARN("hc_face_to_connection] Unexpected truncation of interface name string");
+ connection->id = face->id;
+ rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ f->netdevice.name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "hc_face_to_connection] Unexpected truncation of interface name "
+ "string");
- return 0;
+ return 0;
}
/* CONNECTION -> FACE */
-int
-hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
-{
- int rc;
- switch (connection->type) {
- case CONNECTION_TYPE_TCP:
- *face = (hc_face_t) {
- .id = connection->id,
- .face = {
- .type = FACE_TYPE_TCP,
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- .remote_addr = connection->remote_addr,
- .remote_port = connection->remote_port,
- .admin_state = connection_state_to_face_state(connection->admin_state),
- .state = connection_state_to_face_state(connection->state),
+int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face) {
+ int rc;
+ switch (connection->type) {
+ case FACE_TYPE_TCP:
+ *face = (hc_face_t){
+ .id = connection->id,
+ .face =
+ {
+ .type = FACE_TYPE_TCP,
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ .remote_addr = connection->remote_addr,
+ .remote_port = connection->remote_port,
+ .admin_state = connection->admin_state,
+ .state = connection->state,
#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
+ .priority = connection->priority,
+ .tags = connection->tags,
#endif /* WITH_POLICY */
- },
- };
- break;
- case CONNECTION_TYPE_UDP:
- *face = (hc_face_t) {
- .id = connection->id,
- .face = {
- .type = FACE_TYPE_UDP,
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- .remote_addr = connection->remote_addr,
- .remote_port = connection->remote_port,
- .admin_state = connection_state_to_face_state(connection->admin_state),
- .state = connection_state_to_face_state(connection->state),
+ },
+ };
+ break;
+ case FACE_TYPE_UDP:
+ *face = (hc_face_t){
+ .id = connection->id,
+ .face =
+ {
+ .type = FACE_TYPE_UDP,
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ .remote_addr = connection->remote_addr,
+ .remote_port = connection->remote_port,
+ .admin_state = connection->admin_state,
+ .state = connection->state,
#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
+ .priority = connection->priority,
+ .tags = connection->tags,
#endif /* WITH_POLICY */
- },
- };
- break;
- case CONNECTION_TYPE_HICN:
- *face = (hc_face_t) {
- .id = connection->id,
- .face = {
- .type = FACE_TYPE_HICN,
- .family = connection->family,
- .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX
- .local_addr = connection->local_addr,
- .remote_addr = connection->remote_addr,
- .admin_state = connection_state_to_face_state(connection->admin_state),
- .state = connection_state_to_face_state(connection->state),
+ },
+ };
+ break;
+ case FACE_TYPE_HICN:
+ *face = (hc_face_t){
+ .id = connection->id,
+ .face =
+ {
+ .type = FACE_TYPE_HICN,
+ .family = connection->family,
+ .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX
+ .local_addr = connection->local_addr,
+ .remote_addr = connection->remote_addr,
+ .admin_state = connection->admin_state,
+ .state = connection->state,
#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
+ .priority = connection->priority,
+ .tags = connection->tags,
#endif /* WITH_POLICY */
- },
- };
- break;
- default:
- return -1;
- }
- face->face.netdevice.name[0] = '\0';
- face->face.netdevice.index = 0;
- rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_connection_to_face] Unexpected truncation of symbolic name string");
- rc = snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s", connection->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_connection_to_face] Unexpected truncation of interface name string");
- netdevice_update_index(&face->face.netdevice);
- return 0;
+ },
+ };
+ break;
+ default:
+ return -1;
+ }
+ face->face.netdevice.name[0] = '\0';
+ face->face.netdevice.index = 0;
+ rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_connection_to_face] Unexpected truncation of symbolic name "
+ "string");
+ rc = snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s",
+ connection->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[hc_connection_to_face] Unexpected truncation of interface name "
+ "string");
+ netdevice_update_index(&face->face.netdevice);
+ return 0;
}
/* CONNECTION -> LISTENER */
-int
-hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener)
-{
- int rc;
- *listener = (hc_listener_t) {
- .id = ~0,
- .type = connection->type,
- .family = connection->family,
- .local_addr = connection->local_addr,
- .local_port = connection->local_port,
- };
- rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", RANDBYTE()); // generate name
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[hc_connection_to_local_listener] Unexpected truncation of symbolic name string");
- rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", connection->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[hc_connection_to_local_listener] Unexpected truncation of interface name string");
+int hc_connection_to_local_listener(const hc_connection_t *connection,
+ hc_listener_t *listener) {
+ int rc;
+
+ face_type_t listener_type;
+ switch (connection->type) {
+ case FACE_TYPE_UDP:
+ listener_type = FACE_TYPE_UDP_LISTENER;
+ break;
+ case FACE_TYPE_TCP:
+ listener_type = FACE_TYPE_TCP_LISTENER;
+ break;
+ default:
+ return -1;
+ }
- return 0;
+ *listener = (hc_listener_t){
+ .id = ~0,
+ .type = listener_type,
+ .family = connection->family,
+ .local_addr = connection->local_addr,
+ .local_port = connection->local_port,
+ };
+ rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u",
+ RANDBYTE()); // generate name
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_connection_to_local_listener] Unexpected truncation of "
+ "symbolic name string");
+ rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s",
+ connection->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[hc_connection_to_local_listener] Unexpected truncation of "
+ "interface name string");
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * Punting
+ *----------------------------------------------------------------------------*/
+
+int hc_punting_create(hc_sock_t *s, hc_punting_t *punting) {
+ return s->hc_punting_create(s, punting);
}
-int hc_punting_create(hc_sock_t *s, hc_punting_t *punting)
-{
- return s->hc_punting_create(s, punting);
+int hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
+ hc_punting_t **punting_found) {
+ return s->hc_punting_get(s, punting, punting_found);
}
-int hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
- hc_punting_t **punting_found)
-{
- return s->hc_punting_get(s, punting, punting_found);
+int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) {
+ return s->hc_punting_delete(s, punting);
}
-int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting)
-{
- return s->hc_punting_delete(s, punting);
+int hc_punting_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_punting_list(s, pdata);
}
-int hc_punting_list(hc_sock_t *s, hc_data_t **pdata)
-{
- return s->hc_punting_list(s, pdata);
+int hc_punting_validate(const hc_punting_t *punting) {
+ if (!IS_VALID_FAMILY(punting->family)) return -1;
+
+ /*
+ * We might use the zero value to add punting on all faces but this is not
+ * (yet) implemented
+ */
+ if (punting->face_id == 0) {
+ ERROR("Punting on all faces is not (yet) implemented.");
+ return -1;
+ }
+
+ return 0;
}
-int hc_punting_validate(const hc_punting_t * punting)
-{
- if (!IS_VALID_FAMILY(punting->family))
- return -1;
-
- /*
- * We might use the zero value to add punting on all faces but this is not
- * (yet) implemented
- */
- if (punting->face_id == 0) {
- ERROR("Punting on all faces is not (yet) implemented.");
- return -1;
- }
+int hc_punting_cmp(const hc_punting_t *p1, const hc_punting_t *p2) {
+ int rc;
- return 0;
+ rc = INT_CMP(p1->face_id, p2->face_id);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(p1->family, p2->family);
+ if (rc != 0) return rc;
+
+ rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family);
+ if (rc != 0) return rc;
+
+ rc = INT_CMP(p1->prefix_len, p2->prefix_len);
+ if (rc != 0) return rc;
+
+ return rc;
}
-int hc_punting_cmp(const hc_punting_t * p1, const hc_punting_t * p2)
-{
- int rc;
+int hc_punting_parse(void *in, hc_punting_t *punting) {
+ ERROR("hc_punting_parse not (yet) implemented.");
+ return -1;
+}
- rc = INT_CMP(p1->face_id, p2->face_id);
- if (rc != 0)
- return rc;
+int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting) {
+ ERROR("hc_punting_snprintf not (yet) implemented.");
+ return -1;
+}
- rc = INT_CMP(p1->family, p2->family);
- if (rc != 0)
- return rc;
+/*----------------------------------------------------------------------------*
+ * Cache
+ *----------------------------------------------------------------------------*/
- rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family);
- if (rc != 0)
- return rc;
+int hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache) {
+ return s->hc_cache_set_store(s, cache);
+}
- rc = INT_CMP(p1->prefix_len, p2->prefix_len);
- if (rc != 0)
- return rc;
+int hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) {
+ return s->hc_cache_set_serve(s, cache);
+}
- return rc;
+int hc_cache_clear(hc_sock_t *s, hc_cache_t *cache) {
+ return s->hc_cache_clear(s, cache);
}
-int hc_punting_parse(void * in, hc_punting_t * punting)
-{
- ERROR("hc_punting_parse not (yet) implemented.");
- return -1;
+int hc_cache_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_cache_list(s, pdata);
}
-int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting)
-{
- ERROR("hc_punting_snprintf not (yet) implemented.");
- return -1;
+int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info) {
+ return snprintf(
+ s, size, "Cache set_store=%s set_serve=%s size=%lu stale_entries=%lu",
+ cache_info->store ? "true" : "false",
+ cache_info->serve ? "true" : "false", (unsigned long)cache_info->cs_size,
+ (unsigned long)cache_info->num_stale_entries);
}
-int hc_cache_set_store(hc_sock_t *s, int enabled)
-{
- return s->hc_cache_set_store(s, enabled);
+/*----------------------------------------------------------------------------*
+ * Strategy
+ *----------------------------------------------------------------------------*/
+
+int hc_strategy_list(hc_sock_t *s, hc_data_t **data) {
+ return s->hc_strategy_list(s, data);
}
-int hc_cache_set_serve(hc_sock_t *s, int enabled)
-{
- return s->hc_cache_set_serve(s, enabled);
+int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_set(s, strategy);
}
-int hc_strategy_list(hc_sock_t *s, hc_data_t **data)
-{
- return s->hc_strategy_list(s, data);
+int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_add_local_prefix(s, strategy);
}
-int hc_strategy_set(hc_sock_t *s /* XXX */)
-{
- return s->hc_strategy_set(s);
+hc_result_t *hc_strategy_set_conf(hc_sock_t *s, hc_strategy_t *strategy) {
+ return s->hc_strategy_set_conf(s, strategy);
+}
+
+hc_result_t *hc_strategy_add_local_prefix_conf(hc_sock_t *s,
+ hc_strategy_t *strategy) {
+ return s->hc_strategy_add_local_prefix_conf(s, strategy);
}
/* /!\ Please update constants in header file upon changes */
-int
-hc_strategy_snprintf(char * s, size_t size, hc_strategy_t * strategy)
-{
- return snprintf(s, size, "%s", strategy->name);
+int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy) {
+ return snprintf(s, size, "%s", strategy->name);
}
-int hc_wldr_set(hc_sock_t *s /* XXX */)
-{
- return s->hc_wldr_set(s);
+/*----------------------------------------------------------------------------*
+ * WLDR
+ *----------------------------------------------------------------------------*/
+
+int hc_wldr_set(hc_sock_t *s /* XXX */) { return s->hc_wldr_set(s); }
+
+/*----------------------------------------------------------------------------*
+ * MAP-Me
+ *----------------------------------------------------------------------------*/
+
+int hc_mapme_set(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set(s, mapme->enabled);
}
-int hc_mapme_set(hc_sock_t *s, int enabled)
-{
- return s->hc_mapme_set(s, enabled);
+int hc_mapme_set_discovery(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set_discovery(s, mapme->enabled);
}
-int hc_mapme_set_discovery(hc_sock_t *s, int enabled)
-{
- return s->hc_mapme_set_discovery(s, enabled);
+int hc_mapme_set_timescale(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set_timescale(s, mapme->timescale);
}
-int hc_mapme_set_timescale(hc_sock_t *s, double timescale)
-{
- return s->hc_mapme_set_timescale(s, timescale);
+int hc_mapme_set_retx(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_set_retx(s, mapme->timescale);
}
-int hc_mapme_set_retx(hc_sock_t *s, double timescale)
-{
- return s->hc_mapme_set_retx(s, timescale);
+int hc_mapme_send_update(hc_sock_t *s, hc_mapme_t *mapme) {
+ return s->hc_mapme_send_update(s, mapme);
}
+/*----------------------------------------------------------------------------*
+ * Policy
+ *----------------------------------------------------------------------------*/
+
#ifdef WITH_POLICY
-/* POLICY PARSE */
+/* POLICY SNPRINTF */
-int
-hc_policy_parse(void * in, hc_policy_t * policy)
-{
- list_policies_command * cmd = (list_policies_command *) in;
+/* /!\ Please update constants in header file upon changes */
+int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy) { return 0; }
- if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return -1;
+int hc_policy_validate(const hc_policy_t *policy) {
+ if (!IS_VALID_FAMILY(policy->family)) return -1;
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family))
- return -1;
+ return 0;
+}
- *policy = (hc_policy_t) {
- .family = family,
- .remote_addr = UNION_CAST(cmd->address, ip_address_t),
- .len = cmd->len,
- .policy = cmd->policy,
- };
- return 0;
+#endif /* WITH_POLICY */
+
+/*----------------------------------------------------------------------------*
+ * SUBSCRIPTION
+ *----------------------------------------------------------------------------*/
+int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription) {
+ return s->hc_subscription_create(s, subscription);
}
-/* POLICY SNPRINTF */
+int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription) {
+ return s->hc_subscription_delete(s, subscription);
+}
-/* /!\ Please update constants in header file upon changes */
-int
-hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy)
-{
- return 0;
+hc_result_t *hc_subscription_create_conf(hc_sock_t *s,
+ hc_subscription_t *subscription) {
+ return s->hc_subscription_create_conf(s, subscription);
+}
+
+hc_result_t *hc_subscription_delete_conf(hc_sock_t *s,
+ hc_subscription_t *subscription) {
+ return s->hc_subscription_delete_conf(s, subscription);
+}
+
+/*----------------------------------------------------------------------------*
+ * Result
+ *----------------------------------------------------------------------------*/
+
+hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result) {
+ return s->hc_result_get_msg(result);
+}
+
+int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result) {
+ return s->hc_result_get_cmd_id(result);
+}
+
+bool hc_result_get_success(hc_sock_t *s, hc_result_t *result) {
+ return s->hc_result_get_success(result);
}
-#endif /* WITH_POLICY */ \ No newline at end of file
+void hc_result_free(hc_result_t *result) { free(result); }
diff --git a/ctrl/libhicnctrl/src/api_private.h b/ctrl/libhicnctrl/src/api_private.h
index 3922e1f3c..11cb2e00e 100644
--- a/ctrl/libhicnctrl/src/api_private.h
+++ b/ctrl/libhicnctrl/src/api_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,10 +17,12 @@
#define HICN_API_PRIVATE_H
#include <hicn/ctrl/api.h>
-#include <hicn/ctrl/commands.h>
#include <hicn/util/token.h>
#include <hicn/util/log.h>
#include <hicn/util/map.h>
+#include <hicn/util/sstrncpy.h>
+#include <hicn/validation.h>
+#include <ctype.h>
#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0)
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
@@ -34,57 +36,64 @@
#endif
#define RANDBYTE() (u8)(rand() & 0xFF)
-hc_connection_type_t
-connection_type_from_str(const char * str);
-
-extern const hc_connection_type_t map_from_list_connections_type[];
-extern const hc_connection_type_t map_from_encap_type[];
-extern const connection_type map_to_connection_type[];
-extern const listener_mode map_to_listener_mode[];
-extern const hc_connection_state_t map_from_list_connections_state[];
-extern const int map_from_addr_type[];
-extern const address_type map_to_addr_type[];
-extern const char * connection_state_str[];
-extern const char * connection_type_str[];
-
-typedef enum {
- ENCAP_TCP,
- ENCAP_UDP,
- ENCAP_ETHER,
- ENCAP_LOCAL,
- ENCAP_HICN
-} EncapType;
-
-#define connection_state_to_face_state(x) ((face_state_t)(x))
-#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
+/*
+ * Input validation
+ */
+
+static inline bool IS_VALID_ADDRESS(const ip_address_t *addr, int family) {
+ char addr_str[INET6_ADDRSTRLEN];
+ return !ip_address_empty(addr) &&
+ ip_address_ntop(addr, addr_str, INET6_ADDRSTRLEN, family) >= 0;
+}
+
+static inline bool IS_VALID_PREFIX_LEN(u8 len) {
+ return len <= MAX_IPV6_PREFIX_LEN;
+}
+
+// https://github.com/shemminger/iproute2/blob/50b668bdbf0ebc270495eb4b352d0c3982159d0a/lib/utils.c#L825
+static inline bool IS_VALID_INTERFACE_NAME(const char *name) {
+ size_t len = strnlen_s(name, INTERFACE_LEN);
+ if (len == 0 || len >= IFNAMSIZ) return true;
+
+ while (*name) {
+ if (*name == '/' || isspace(*name)) return false;
+ ++name;
+ }
+ return true;
+}
+
+static inline bool IS_VALID_NAME(const char *name) {
+ return is_symbolic_name(name, SYMBOLIC_NAME_LEN);
+}
+
+static inline bool IS_VALID_STR_ID(const char *name) {
+ return is_number(name, SYMBOLIC_NAME_LEN);
+}
+
+#define IS_VALID_TYPE(x) IS_VALID_ENUM_TYPE(FACE_TYPE, x)
#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX))
-#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x)
+#define IS_VALID_ID(x) (1)
+#define IS_VALID_POLICY(x) (1)
typedef struct hc_sock_impl_s hc_sock_impl_t;
-int hc_data_ensure_available(hc_data_t * data, size_t count);
-u8 *hc_data_get_next(hc_data_t * data);
-int hc_data_set_error(hc_data_t * data);
+int hc_data_ensure_available(hc_data_t *data, size_t count);
+u8 *hc_data_get_next(hc_data_t *data);
+int hc_data_set_error(hc_data_t *data);
-int
-hc_connection_parse_to_face(void * in, hc_face_t * face);
+int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face);
-int
-hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face);
+int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face);
-int
-hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face);
+int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener);
-int
-hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener);
+int hc_connection_to_local_listener(const hc_connection_t *connection,
+ hc_listener_t *listener);
-int
-hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener);
-
-int
-hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name);
+int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection,
+ bool generate_name);
struct hc_sock_s {
int (*hc_sock_get_next_seq)(hc_sock_t *s);
@@ -92,17 +101,21 @@ struct hc_sock_s {
int (*hc_sock_get_fd)(hc_sock_t *s);
int (*hc_sock_connect)(hc_sock_t *s);
int (*hc_sock_get_available)(hc_sock_t *s, u8 **buffer, size_t *size);
- int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq);
+ int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq);
int (*hc_sock_recv)(hc_sock_t *s);
int (*hc_sock_process)(hc_sock_t *s, hc_data_t **data);
int (*hc_sock_callback)(hc_sock_t *s, hc_data_t **data);
int (*hc_sock_reset)(hc_sock_t *s);
void (*hc_sock_free)(hc_sock_t *s);
-
+ void (*hc_sock_increment_woff)(hc_sock_t *s, size_t bytes);
+ int (*hc_sock_prepare_send)(hc_sock_t *s, hc_result_t *result,
+ data_callback_t complete_cb,
+ void *complete_cb_data);
+ int (*hc_sock_set_recv_timeout_ms)(hc_sock_t *s, long timeout_ms);
int (*hc_listener_create)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_create_async)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_get)(hc_sock_t *s, hc_listener_t *listener,
- hc_listener_t **listener_found);
+ hc_listener_t **listener_found);
int (*hc_listener_delete)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_delete_async)(hc_sock_t *s, hc_listener_t *listener);
int (*hc_listener_list)(hc_sock_t *s, hc_data_t **pdata);
@@ -114,81 +127,105 @@ struct hc_sock_s {
int (*hc_connection_create)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_create_async)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_get)(hc_sock_t *s, hc_connection_t *connection,
- hc_connection_t **connection_found);
+ hc_connection_t **connection_found);
int (*hc_connection_update_by_id)(hc_sock_t *s, int hc_connection_id,
- hc_connection_t *connection);
+ hc_connection_t *connection);
int (*hc_connection_update)(hc_sock_t *s, hc_connection_t *connection_current,
- hc_connection_t *connection_updated);
+ hc_connection_t *connection_updated);
int (*hc_connection_delete)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_delete_async)(hc_sock_t *s, hc_connection_t *connection);
int (*hc_connection_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_connection_list_async)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_connection_validate)(const hc_connection_t *connection);
- int (*hc_connection_cmp)(const hc_connection_t *c1, const hc_connection_t *c2);
+ int (*hc_connection_cmp)(const hc_connection_t *c1,
+ const hc_connection_t *c2);
int (*hc_connection_parse)(void *in, hc_connection_t *connection);
- int (*hc_connection_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
- int (*hc_connection_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+ int (*hc_connection_set_admin_state)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state);
+ int (*hc_connection_set_admin_state_async)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
- int (*hc_connection_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_connection_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_connection_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
- int (*hc_connection_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
-#endif // WITH_POLICY
+ int (*hc_connection_set_priority)(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_connection_set_priority_async)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_connection_set_tags)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+ int (*hc_connection_set_tags_async)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+#endif // WITH_POLICY
int (*hc_connection_snprintf)(char *s, size_t size,
- const hc_connection_t *connection);
+ const hc_connection_t *connection);
int (*hc_face_create)(hc_sock_t *s, hc_face_t *face);
int (*hc_face_get)(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found);
- int (*hc_face_delete)(hc_sock_t *s, hc_face_t *face);
+ int (*hc_face_delete)(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener);
int (*hc_face_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_face_list_async)(hc_sock_t *s);
- int (*hc_face_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
- int (*hc_face_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+ int (*hc_face_set_admin_state)(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state);
+ int (*hc_face_set_admin_state_async)(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state);
#ifdef WITH_POLICY
- int (*hc_face_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_face_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
- int (*hc_face_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
- int (*hc_face_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
-#endif // WITH_POLICY
+ int (*hc_face_set_priority)(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_face_set_priority_async)(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority);
+ int (*hc_face_set_tags)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+ int (*hc_face_set_tags_async)(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags);
+#endif // WITH_POLICY
int (*hc_face_snprintf)(char *s, size_t size, hc_face_t *face);
int (*hc_route_parse)(void *in, hc_route_t *route);
- int (*hc_route_create)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_create_async)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_delete)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_delete_async)(hc_sock_t * s, hc_route_t * route);
- int (*hc_route_list)(hc_sock_t * s, hc_data_t ** pdata);
- int (*hc_route_list_async)(hc_sock_t * s);
+ int (*hc_route_create)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_create_async)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_delete)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_delete_async)(hc_sock_t *s, hc_route_t *route);
+ int (*hc_route_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_route_list_async)(hc_sock_t *s);
int (*hc_punting_create)(hc_sock_t *s, hc_punting_t *punting);
int (*hc_punting_create_async)(hc_sock_t *s, hc_punting_t *punting);
int (*hc_punting_get)(hc_sock_t *s, hc_punting_t *punting,
- hc_punting_t **punting_found);
+ hc_punting_t **punting_found);
int (*hc_punting_delete)(hc_sock_t *s, hc_punting_t *punting);
int (*hc_punting_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_punting_validate)(const hc_punting_t *punting);
int (*hc_punting_cmp)(const hc_punting_t *c1, const hc_punting_t *c2);
int (*hc_punting_parse)(void *in, hc_punting_t *punting);
- int (*hc_cache_set_store)(hc_sock_t *s, int enabled);
- int (*hc_cache_set_serve)(hc_sock_t *s, int enabled);
- int (*hc_cache_set_store_async)(hc_sock_t *s, int enabled);
- int (*hc_cache_set_serve_async)(hc_sock_t *s, int enabled);
+ int (*hc_cache_parse)(void *in, hc_cache_info_t *cache_info);
+ int (*hc_cache_set_store)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_set_serve)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_clear)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_cache_set_store_async)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_set_serve_async)(hc_sock_t *s, hc_cache_t *cache);
+ int (*hc_cache_snprintf)(char *s, size_t size,
+ const hc_cache_info_t *cache_info);
int (*hc_strategy_list)(hc_sock_t *s, hc_data_t **data);
int (*hc_strategy_snprintf)(char *s, size_t size, hc_strategy_t *strategy);
- int (*hc_strategy_set)(hc_sock_t *s /* XXX */);
+ int (*hc_strategy_set)(hc_sock_t *s, hc_strategy_t *strategy);
+ int (*hc_strategy_add_local_prefix)(hc_sock_t *s, hc_strategy_t *strategy);
int (*hc_wldr_set)(hc_sock_t *s /* XXX */);
int (*hc_mapme_set)(hc_sock_t *s, int enabled);
int (*hc_mapme_set_discovery)(hc_sock_t *s, int enabled);
- int (*hc_mapme_set_timescale)(hc_sock_t *s, double timescale);
- int (*hc_mapme_set_retx)(hc_sock_t *s, double timescale);
+ int (*hc_mapme_set_timescale)(hc_sock_t *s, uint32_t timescale);
+ int (*hc_mapme_set_retx)(hc_sock_t *s, uint32_t timescale);
+ int (*hc_mapme_send_update)(hc_sock_t *s, hc_mapme_t *mapme);
#ifdef WITH_POLICY
int (*hc_policy_parse)(void *in, hc_policy_t *policy);
@@ -199,10 +236,34 @@ struct hc_sock_s {
int (*hc_policy_list)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_policy_list_async)(hc_sock_t *s, hc_data_t **pdata);
int (*hc_policy_snprintf)(char *s, size_t size, hc_policy_t *policy);
-#endif // WITH_POLICY
+#endif // WITH_POLICY
+
+ int (*hc_subscription_create)(hc_sock_t *s, hc_subscription_t *subscription);
+ int (*hc_subscription_delete)(hc_sock_t *s, hc_subscription_t *subscription);
+
+ 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);
+ hc_result_t *(*hc_connection_create_conf)(hc_sock_t *s,
+ hc_connection_t *connection);
+ hc_result_t *(*hc_connection_delete_conf)(hc_sock_t *s,
+ hc_connection_t *connection);
+ hc_result_t *(*hc_route_create_conf)(hc_sock_t *s, hc_route_t *route);
+ hc_result_t *(*hc_strategy_set_conf)(hc_sock_t *s, hc_strategy_t *strategy);
+ hc_result_t *(*hc_strategy_add_local_prefix_conf)(hc_sock_t *s,
+ hc_strategy_t *strategy);
+ hc_result_t *(*hc_subscription_create_conf)(hc_sock_t *s,
+ hc_subscription_t *subscription);
+ hc_result_t *(*hc_subscription_delete_conf)(hc_sock_t *s,
+ hc_subscription_t *subscription);
+
+ hc_msg_t *(*hc_result_get_msg)(hc_result_t *result);
+ bool (*hc_result_get_success)(hc_result_t *result);
+ int (*hc_result_get_cmd_id)(hc_result_t *result);
+ void (*hc_result_free)(hc_result_t *result);
// Reference to module containing the implementation
void *handle;
};
-#endif // HICN_API_PRIVATE_H \ No newline at end of file
+#endif // HICN_API_PRIVATE_H
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
deleted file mode 100644
index 064eb77e3..000000000
--- a/ctrl/libhicnctrl/src/cli.c
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * \file cli.c
- * \brief Command line interface
- */
-#include <ctype.h> // isalpha isalnum
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h> // getopt
-
-#include <hicn/ctrl.h>
-#include <hicn/util/ip_address.h>
-#include <hicn/util/token.h>
-
-
-#define die(LABEL, MESSAGE) do { \
- printf(MESSAGE "\n"); \
- rc = -1; \
- goto ERR_ ## LABEL; \
-} while(0)
-
-#define foreach_object \
- _(UNDEFINED) \
- _(FACE) \
- _(ROUTE) \
- _(STRATEGY) \
- _(LISTENER) \
- _(CONNECTION) \
- _(N)
-
-typedef enum {
-#define _(x) OBJECT_ ## x,
-foreach_object
-#undef _
-} hc_object_t;
-
-#define HICNLIGHT_PARAM "hicnlight"
-#define VPP_PARAM "vpp"
-
-void
-usage_header()
-{
- fprintf(stderr, "Usage:\n");
-}
-
-void
-usage_face_create(const char * prog, bool header, bool verbose)
-{
-
- if (header)
- usage_header();
- fprintf(stderr, "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a face on specified address and port.\n");
-}
-
-void
-usage_face_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -df ID\n", prog);
- //fprintf(stderr, "%s -df NAME\n", prog);
- fprintf(stderr, "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a face...\n");
-}
-
-void
-usage_face_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -F\n", prog);
- if (verbose)
- fprintf(stderr, " List all faces.\n");
-}
-
-void
-usage_face(const char * prog, bool header, bool verbose)
-{
- usage_face_create(prog, header, verbose);
- usage_face_delete(prog, header, verbose);
- usage_face_list(prog, header, verbose);
-}
-
-void
-usage_route_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog);
- //fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a route...\n");
-}
-
-void
-usage_route_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog);
- //fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a route...\n");
-}
-
-void
-usage_route_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -R\n", prog);
- if (verbose)
- fprintf(stderr, " List all routes.\n");
-}
-
-void
-usage_route(const char * prog, bool header, bool verbose)
-{
- usage_route_create(prog, header, verbose);
- usage_route_delete(prog, header, verbose);
- usage_route_list(prog, header, verbose);
-}
-
-void
-usage_forwarding_strategy_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
-}
-void
-usage_forwarding_strategy_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
-}
-
-void
-usage_forwarding_strategy_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -S\n", prog);
- if (verbose)
- fprintf(stderr, " List all availble forwarding strategies.\n");
-}
-
-void
-usage_forwarding_strategy(const char * prog, bool header, bool verbose)
-{
- usage_forwarding_strategy_create(prog, header, verbose);
- usage_forwarding_strategy_delete(prog, header, verbose);
- usage_forwarding_strategy_list(prog, header, verbose);
-}
-
-void
-usage_listener_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a listener on specified address and port.\n");
-}
-
-void
-usage_listener_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dl ID\n", prog);
- fprintf(stderr, "%s -dl NAME\n", prog);
- fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a listener...\n");
-}
-
-void
-usage_listener_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -L\n", prog);
- if (verbose)
- fprintf(stderr, " List all listeners.\n");
-}
-
-void
-usage_listener(const char * prog, bool header, bool verbose)
-{
- usage_listener_create(prog, header, verbose);
- usage_listener_delete(prog, header, verbose);
- usage_listener_list(prog, header, verbose);
-}
-void
-usage_connection_create(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Create a connection on specified address and port.\n");
-}
-
-void
-usage_connection_delete(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -dc ID\n", prog);
- fprintf(stderr, "%s -dc NAME\n", prog);
- fprintf(stderr, "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", prog);
- if (verbose)
- fprintf(stderr, " Delete a connection...\n");
-}
-
-void
-usage_connection_list(const char * prog, bool header, bool verbose)
-{
- if (header)
- usage_header();
- fprintf(stderr, "%s -C\n", prog);
- if (verbose)
- fprintf(stderr, " List all connections.\n");
-}
-
-void
-usage_connection(const char * prog, bool header, bool verbose)
-{
- usage_connection_create(prog, header, verbose);
- usage_connection_delete(prog, header, verbose);
- usage_connection_list(prog, header, verbose);
-}
-
-void usage(const char * prog)
-{
- fprintf(stderr, "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
- fprintf(stderr, "\n");
- fprintf(stderr, "High-level commands\n");
- fprintf(stderr, "\n");
- usage_face(prog, false, true);
- usage_route(prog, false, true);
- usage_forwarding_strategy(prog, false, true);
- fprintf(stderr, "\n");
- fprintf(stderr, "Low level commands (hicn-light specific)\n");
- fprintf(stderr, "\n");
- usage_listener(prog, false, true);
- usage_connection(prog, false, true);
-}
-
-typedef struct {
- hc_action_t action;
- hc_object_t object;
- union {
- hc_face_t face;
- hc_route_t route;
- hc_connection_t connection;
- hc_listener_t listener;
- };
-} hc_command_t;
-
-/**
- * Return true if string is purely an integer
- */
-static inline
-bool
-is_number(const char *string) {
- size_t len = strlen(string);
- for (size_t i = 0; i < len; i++)
- if (!isdigit(string[i]))
- return false;
- return true;
-}
-
-/**
- * A symbolic name must be at least 1 character and must begin with an alpha.
- * The remainder must be an alphanum.
- */
-static inline
-bool
-is_symbolic_name(const char *name)
-{
- size_t len = strlen(name);
- if (len <= 0)
- return false;
- if (!isalpha(name[0]))
- return false;
- for (size_t i = 1; i < len; i++) {
- if (!isalnum(name[i]))
- return false;
- }
- return true;
-}
-
-face_type_t
-face_type_from_str(const char * str)
-{
-#define _(x) \
- if (strcasecmp(str, STRINGIZE(x)) == 0) \
- return FACE_TYPE_ ## x; \
- else
-foreach_face_type
-#undef _
- return FACE_TYPE_UNDEFINED;
-}
-
-
-int
-parse_options(int argc, char *argv[], hc_command_t * command, forwarder_t *forwarder)
-{
- command->object = OBJECT_UNDEFINED;
- command->action = ACTION_CREATE;
- int opt;
- int family;
-
- while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) {
- switch (opt) {
- case 'z' :
- if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) {
- *forwarder = VPP;
- } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) {
- *forwarder = HICNLIGHT;
- } else {
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- break;
- case 'd':
- command->action = ACTION_DELETE;
- break;
- case 'f':
- command->object = OBJECT_FACE;
- break;
- case 'l':
- command->object = OBJECT_LISTENER;
- break;
- case 'c':
- command->object = OBJECT_CONNECTION;
- break;
- case 'r':
- command->object = OBJECT_ROUTE;
- break;
- case 'F':
- command->action = ACTION_LIST;
- command->object = OBJECT_FACE;
- break;
- case 'L':
- command->action = ACTION_LIST;
- command->object = OBJECT_LISTENER;
- break;
- case 'C':
- command->action = ACTION_LIST;
- command->object = OBJECT_CONNECTION;
- break;
- case 'R':
- command->action = ACTION_LIST;
- command->object = OBJECT_ROUTE;
- break;
- case 'S':
- command->action = ACTION_LIST;
- command->object = OBJECT_STRATEGY;
- break;
- default: /* "h" */
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- }
- }
-
- if (command->object == OBJECT_UNDEFINED) {
- fprintf(stderr, "Missing object specification: connection | listener | route\n");
- return -1;
- }
-
- /* Parse and validate parameters for add/delete */
- switch(command->object) {
- case OBJECT_FACE:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 5) && (argc - optind != 6)) {
- usage_face_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- /* NAME will be autogenerated (and currently not used) */
- //snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->face.face.type = face_type_from_str(argv[optind++]);
- if (command->face.face.type == FACE_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->face.face.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->face.face.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
- goto ERR_PARAM;
- command->face.face.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
- goto ERR_PARAM;
- command->face.face.remote_port = atoi(argv[optind++]);
- if (argc != optind) {
- //netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
- command->face.face.netdevice.index = atoi(argv[optind++]);
- }
-
- break;
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
- usage_face_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->face.id = atoi(argv[optind++]);
- snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- //} else if (is_symbolic_name(argv[optind])) {
- // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->face.face.type = face_type_from_str(argv[optind++]);
- if (command->face.face.type == FACE_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->face.face.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->face.face.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
- goto ERR_PARAM;
- command->face.face.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
- goto ERR_PARAM;
- command->face.face.remote_port = atoi(argv[optind++]);
- if (argc != optind) {
- command->face.face.netdevice.index = atoi(argv[optind++]);
- //netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
- }
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_face_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_ROUTE:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 2) && (argc - optind != 3)) {
- usage_route_create(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- command->route.face_id = atoi(argv[optind++]);
-
- {
- ip_prefix_t prefix;
- ip_prefix_pton(argv[optind++], &prefix);
- command->route.family = prefix.family;
- command->route.remote_addr = prefix.address;
- command->route.len = prefix.len;
- }
-
- if (argc != optind) {
- printf("parse cost\n");
- command->route.cost = atoi(argv[optind++]);
- }
- break;
-
- case ACTION_DELETE:
- if (argc - optind != 2) {
- usage_route_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- command->route.face_id = atoi(argv[optind++]);
-
- {
- ip_prefix_t prefix;
- ip_prefix_pton(argv[optind++], &prefix);
- command->route.family = prefix.family;
- command->route.remote_addr = prefix.address;
- command->route.len = prefix.len;
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_route_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_STRATEGY:
- switch(command->action) {
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_forwarding_strategy_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_LISTENER:
- switch(command->action) {
- case ACTION_CREATE:
- if ((argc - optind != 4) && (argc - optind != 5)) {
- usage_listener_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->listener.type = connection_type_from_str(argv[optind++]);
- if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->listener.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->listener.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
- goto ERR_PARAM;
- command->listener.local_port = atoi(argv[optind++]);
- if (argc != optind) {
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
- }
- break;
-
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 3) && (argc - optind != 4)) {
- usage_listener_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->listener.id = atoi(argv[optind++]);
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else if (is_symbolic_name(argv[optind])) {
- snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->listener.type = connection_type_from_str(argv[optind++]);
- if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->listener.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->listener.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
- goto ERR_PARAM;
- command->listener.local_port = atoi(argv[optind++]);
- if (argc != optind) {
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
- }
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_listener_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- case OBJECT_CONNECTION:
- switch(command->action) {
- case ACTION_CREATE:
- /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
- if ((argc - optind != 6) && (argc - optind != 7)) {
- usage_connection_create(argv[0], true, false);
- goto ERR_PARAM;
- }
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- command->connection.type = connection_type_from_str(argv[optind++]);
- if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->connection.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->connection.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
- goto ERR_PARAM;
- command->connection.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
- goto ERR_PARAM;
- command->connection.remote_port = atoi(argv[optind++]);
-
- break;
-
- case ACTION_DELETE:
- if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
- usage_connection_delete(argv[0], true, false);
- goto ERR_PARAM;
- }
-
- if (argc - optind == 1) {
- /* Id or name */
- if (is_number(argv[optind])) {
- command->connection.id = atoi(argv[optind++]);
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else if (is_symbolic_name(argv[optind])) {
- snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
- } else {
- fprintf(stderr, "Invalid argument\n");
- goto ERR_PARAM;
- }
- } else {
- command->connection.type = connection_type_from_str(argv[optind++]);
- if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
- goto ERR_PARAM;
- command->connection.family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(command->connection.family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
- goto ERR_PARAM;
- command->connection.local_port = atoi(argv[optind++]);
- family = ip_address_get_family(argv[optind]);
- if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
- goto ERR_PARAM;
- if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
- goto ERR_PARAM;
- command->connection.remote_port = atoi(argv[optind++]);
- }
- break;
-
- case ACTION_LIST:
- if (argc - optind != 0) {
- usage_connection_list(argv[0], true, false);
- goto ERR_PARAM;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
-
- default:
- goto ERR_COMMAND;
- break;
- }
-
- return 0;
-
-ERR_PARAM:
-ERR_COMMAND:
- return -1;
-}
-
-int main(int argc, char *argv[])
-{
- hc_data_t * data;
- int rc = 1;
- hc_command_t command = {0};
- char buf_listener[MAXSZ_HC_LISTENER];
- char buf_connection[MAXSZ_HC_CONNECTION];
- char buf_route[MAXSZ_HC_ROUTE];
- char buf_strategy[MAXSZ_HC_STRATEGY];
-
- forwarder_t forwarder = HICNLIGHT;
-
- if (parse_options(argc, argv, &command, &forwarder) < 0)
- die(OPTIONS, "Bad arguments");
-
- hc_sock_t * s = hc_sock_create_forwarder(forwarder);
- if (!s)
- die(SOCKET, "Error creating socket.");
-
- if (hc_sock_connect(s) < 0)
- die(CONNECT, "Error connecting to the forwarder.");
-
- switch(command.object) {
- case OBJECT_FACE:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_face_create(s, &command.face) < 0)
- die(COMMAND, "Error creating face");
- printf("OK\n");
- break;
-
- case ACTION_DELETE:
- if (hc_face_delete(s, &command.face) < 0)
- die(COMMAND, "Error creating face");
- printf("OK\n");
- break;
-
- case ACTION_LIST:
- if (hc_face_list(s, &data) < 0)
- die(COMMAND, "Error getting connections.");
-
- printf("Faces:\n");
- foreach_face(f, data) {
- if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= MAXSZ_HC_FACE)
- die(COMMAND, "Display error");
- printf("[%s] %s\n", f->name, buf_connection);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for connection");
- break;
- }
- break;
-
- case OBJECT_ROUTE:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_route_create(s, &command.route) < 0)
- die(COMMAND, "Error creating route");
- printf("OK\n");
- break;
-
- case ACTION_DELETE:
- if (hc_route_delete(s, &command.route) < 0)
- die(COMMAND, "Error creating route");
- printf("OK\n");
- break;
-
- case ACTION_LIST:
- if (hc_route_list(s, &data) < 0)
- die(COMMAND, "Error getting routes.");
-
- printf("Routes:\n");
- foreach_route(r, data) {
- if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= MAXSZ_HC_ROUTE)
- die(COMMAND, "Display error");
- printf("%s\n", buf_route);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for route");
- break;
- }
- break;
-
- case OBJECT_STRATEGY:
- switch(command.action) {
- case ACTION_LIST:
- if (hc_strategy_list(s, &data) < 0)
- die(COMMAND, "Error getting routes.");
-
- printf("Forwarding strategies:\n");
- foreach_strategy(st, data) {
- if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >= MAXSZ_HC_STRATEGY)
- die(COMMAND, "Display error");
- printf("%s\n", buf_strategy);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for strategy");
- break;
- }
- break;
-
- case OBJECT_LISTENER:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_listener_create(s, &command.listener) < 0)
- die(COMMAND, "Error creating listener");
- printf("OK\n");
- break;
- case ACTION_DELETE:
- if (hc_listener_delete(s, &command.listener) < 0)
- die(COMMAND, "Error deleting listener");
- printf("OK\n");
- break;
- break;
- case ACTION_LIST:
- if (hc_listener_list(s, &data) < 0)
- die(COMMAND, "Error getting listeners.");
-
- printf("Listeners:\n");
- foreach_listener(l, data) {
- if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER)
- die(COMMAND, "Display error");
- printf("[%d] %s\n", l->id, buf_listener);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for listener");
- break;
- }
- break;
-
- case OBJECT_CONNECTION:
- switch(command.action) {
- case ACTION_CREATE:
- if (hc_connection_create(s, &command.connection) < 0)
- die(COMMAND, "Error creating connection");
- printf("OK\n");
- break;
- case ACTION_DELETE:
- if (hc_connection_delete(s, &command.connection) < 0)
- die(COMMAND, "Error creating connection");
- printf("OK\n");
- break;
- case ACTION_LIST:
- if (hc_connection_list(s, &data) < 0)
- die(COMMAND, "Error getting connections.");
-
- printf("Connections:\n");
- foreach_connection(c, data) {
- if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION)
- die(COMMAND, "Display error");
- printf("[%s] %s\n", c->name, buf_connection);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for connection");
- break;
- }
- break;
-
- default:
- die(COMMAND, "Unsupported object");
- break;
- }
-
-ERR_COMMAND:
-ERR_CONNECT:
- hc_sock_free(s);
-ERR_SOCKET:
-ERR_OPTIONS:
- return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/ctrl/libhicnctrl/src/face.c b/ctrl/libhicnctrl/src/face.c
deleted file mode 100644
index e617ff8a4..000000000
--- a/ctrl/libhicnctrl/src/face.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * \file face.c
- * \brief Implementation of face abstraction
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <hicn/util/token.h>
-
-#include <hicn/ctrl/face.h>
-#include "util/hash.h"
-
-#define member_size(type, member) sizeof(((type *)0)->member)
-
-
-/* Netdevice */
-
-const char * netdevice_type_str[] = {
-#define _(x) [NETDEVICE_TYPE_ ## x] = STRINGIZE(x),
-foreach_netdevice_type
-#undef _
-};
-
-netdevice_t *
-netdevice_create_from_index(u32 index)
-{
- netdevice_t * netdevice = malloc(sizeof(netdevice_t));
- if (!netdevice)
- goto ERR_MALLOC;
-
- int rc = netdevice_set_index(netdevice, index);
- if (rc < 0)
- goto ERR_INIT;
-
- return netdevice;
-
-ERR_INIT:
- free(netdevice);
-ERR_MALLOC:
- return NULL;
-}
-
-netdevice_t *
-netdevice_create_from_name(const char * name)
-{
- netdevice_t * netdevice = malloc(sizeof(netdevice_t));
- if (!netdevice)
- goto ERR_MALLOC;
-
- int rc = netdevice_set_name(netdevice, name);
- if (rc < 0)
- goto ERR_INIT;
-
- return netdevice;
-
-ERR_INIT:
- free(netdevice);
-ERR_MALLOC:
- return NULL;
-}
-
-/**
- * \brief Update the index of the netdevice based on the name
- */
-int
-netdevice_update_index(netdevice_t * netdevice)
-{
- netdevice->index = if_nametoindex(netdevice->name);
- if (netdevice->index == 0)
- return -1;
- return 0;
-}
-
-int
-netdevice_update_name(netdevice_t * netdevice)
-{
- if (!if_indextoname(netdevice->index, netdevice->name))
- return -1;
- return 0;
-}
-
-void
-netdevice_free(netdevice_t * netdevice)
-{
- free(netdevice);
-}
-
-int
-netdevice_get_index(const netdevice_t * netdevice, u32 * index)
-{
- if (netdevice->index == 0)
- return -1;
- *index = netdevice->index;
- return 0;
-}
-
-int
-netdevice_set_index(netdevice_t * netdevice, u32 index)
-{
- netdevice->index = index;
- return netdevice_update_name(netdevice);
-}
-
-int
-netdevice_get_name(const netdevice_t * netdevice, const char ** name)
-{
- if (netdevice->name[0] == '\0')
- return -1;
- *name = netdevice->name;
- return 0;
-}
-
-int
-netdevice_set_name(netdevice_t * netdevice, const char * name)
-{
- memset(netdevice->name, 0, sizeof(netdevice->name));
- int rc = snprintf(netdevice->name, IFNAMSIZ, "%s", name);
- if (rc < 0)
- return -1;
- if (rc >= IFNAMSIZ)
- return -2; /* truncated */
- return netdevice_update_index(netdevice);
-}
-
-int
-netdevice_cmp(const netdevice_t * nd1, const netdevice_t * nd2)
-{
- return (nd1->index - nd2->index);
-}
-
-
-/* Face state */
-
-const char * face_state_str[] = {
-#define _(x) [FACE_STATE_ ## x] = STRINGIZE(x),
-foreach_face_state
-#undef _
-};
-
-
-/* Face type */
-
-const char * face_type_str[] = {
-#define _(x) [FACE_TYPE_ ## x] = STRINGIZE(x),
-foreach_face_type
-#undef _
-};
-
-
-/* Face */
-
-int
-face_initialize(face_t * face)
-{
- memset(face, 0, sizeof(face_t)); /* 0'ed for hash */
- return 1;
-}
-
-int
-face_initialize_udp(face_t * face, const char * interface_name, const
- ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port,
- int family)
-{
- if (!local_addr)
- return -1;
-
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .family = family,
- .local_addr = *local_addr,
- .local_port = local_port,
- .remote_addr = remote_addr ? *remote_addr : IP_ADDRESS_EMPTY,
- .remote_port = remote_port,
- };
-
- snprintf(face->netdevice.name, IFNAMSIZ, "%s", interface_name);
-
- return 1;
-}
-
-int
-face_initialize_udp_sa(face_t * face, const char * interface_name,
- const struct sockaddr * local_addr,
- const struct sockaddr * remote_addr)
-{
- if (!local_addr)
- return -1;
-
- if (remote_addr && (local_addr->sa_family != remote_addr->sa_family))
- return -1;
-
- switch (local_addr->sa_family) {
- case AF_INET:
- {
- struct sockaddr_in *lsai = (struct sockaddr_in *)local_addr;
- struct sockaddr_in *rsai = (struct sockaddr_in *)remote_addr;
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .family = AF_INET,
- .local_addr.v4.as_inaddr = lsai->sin_addr,
- .local_port = lsai ? ntohs(lsai->sin_port) : 0,
- .remote_addr = IP_ADDRESS_EMPTY,
- .remote_port = rsai ? ntohs(rsai->sin_port) : 0,
- };
- if (rsai)
- face->remote_addr.v4.as_inaddr = rsai->sin_addr;
- }
- break;
- case AF_INET6:
- {
- struct sockaddr_in6 *lsai = (struct sockaddr_in6 *)local_addr;
- struct sockaddr_in6 *rsai = (struct sockaddr_in6 *)remote_addr;
- *face = (face_t) {
- .type = FACE_TYPE_UDP,
- .family = AF_INET6,
- .local_addr.v6.as_in6addr = lsai->sin6_addr,
- .local_port = lsai ? ntohs(lsai->sin6_port) : 0,
- .remote_addr = IP_ADDRESS_EMPTY,
- .remote_port = rsai ? ntohs(rsai->sin6_port) : 0,
- };
- if (rsai)
- face->remote_addr.v6.as_in6addr = rsai->sin6_addr;
- }
- break;
- default:
- return -1;
- }
-
- snprintf(face->netdevice.name, IFNAMSIZ, "%s", interface_name);
-
- return 1;
-}
-
-face_t * face_create()
-{
- face_t * face = calloc(1, sizeof(face_t)); /* 0'ed for hash */
- return face;
-}
-
-face_t * face_create_udp(const char * interface_name,
- const ip_address_t * local_addr, u16 local_port,
- const ip_address_t * remote_addr, u16 remote_port, int family)
-{
- face_t * face = face_create();
- if (face_initialize_udp(face, interface_name, local_addr, local_port, remote_addr, remote_port, family) < 0)
- goto ERR_INIT;
- return face;
-
-ERR_INIT:
- free(face);
- return NULL;
-}
-
-face_t * face_create_udp_sa(const char * interface_name,
- const struct sockaddr * local_addr,
- const struct sockaddr * remote_addr)
-{
- face_t * face = face_create();
- if (face_initialize_udp_sa(face, interface_name, local_addr, remote_addr) < 0)
- goto ERR_INIT;
- return face;
-
-ERR_INIT:
- free(face);
- return NULL;
-}
-
-void face_free(face_t * face)
-{
- free(face);
-}
-
-/**
- * \brief Compare two faces
- * \param [in] f1 - First face
- * \param [in] f2 - Second face
- * \return whether faces are equal, ie both their types are parameters are
- * equal.
- *
- * NOTE: this function implements a partial order.
- */
-int
-face_cmp(const face_t * f1, const face_t * f2)
-{
-
- int ret = f1->type - f2->type;
- if (ret != 0)
- return ret;
-
- ret = f1->family - f2->family;
- if (ret != 0)
- return ret;
-
- /*
- * FIXME As hicn-light API might not return the netdevice, we can discard the
- * comparison when one of the two is not set for now...
- */
- if ((f1->netdevice.index != 0) && (f2->netdevice.index != 0)) {
- ret = netdevice_cmp(&f1->netdevice, &f2->netdevice);
- if (ret != 0)
- return ret;
- }
-
- switch(f1->type) {
- case FACE_TYPE_HICN:
- ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family);
- if (ret != 0)
- return ret;
-
- ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family);
- if (ret != 0)
- return ret;
-
- break;
-
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- ret = ip_address_cmp(&f1->local_addr, &f2->local_addr, f1->family);
- if (ret != 0)
- return ret;
-
- ret = f1->local_port - f2->local_port;
- if (ret != 0)
- return ret;
-
- ret = ip_address_cmp(&f1->remote_addr, &f2->remote_addr, f1->family);
- if (ret != 0)
- return ret;
-
- ret = f1->remote_port - f2->remote_port;
- if (ret != 0)
- return ret;
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-unsigned int
-face_hash(const face_t * face)
-{
- /* Assuming the unused part of the struct is set to zero */
- return hash_struct(face);
-}
-
-/* /!\ Please update constants in header file upon changes */
-size_t
-face_snprintf(char * s, size_t size, const face_t * face)
-{
- switch(face->type) {
- case FACE_TYPE_HICN:
- {
- char local[MAXSZ_IP_ADDRESS];
- char remote[MAXSZ_IP_ADDRESS];
- char tags[MAXSZ_POLICY_TAGS];
-
- ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
- &face->local_addr,
- face->family);
- ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
- &face->remote_addr,
- face->family);
- policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
- return snprintf(s, size, "%s [%s -> %s] [%s]",
- face_type_str[face->type],
- local,
- remote,
- tags);
- }
- case FACE_TYPE_UNDEFINED:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- {
- char local[MAXSZ_IP_ADDRESS];
- char remote[MAXSZ_IP_ADDRESS];
- char tags[MAXSZ_POLICY_TAGS];
-
- ip_address_snprintf(local, MAXSZ_IP_ADDRESS,
- &face->local_addr,
- face->family);
- ip_address_snprintf(remote, MAXSZ_IP_ADDRESS,
- &face->remote_addr,
- face->family);
- policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags);
-
- return snprintf(s, size, "%s [%s:%d -> %s:%d] [%s]",
- face_type_str[face->type],
- local,
- face->local_port,
- remote,
- face->remote_port,
- tags);
- }
- default:
- return -1;
- }
-
-}
-
-policy_tags_t face_get_tags(const face_t * face)
-{
- return face->tags;
-}
-
-int
-face_set_tags(face_t * face, policy_tags_t tags)
-{
- face->tags = tags;
- return 1;
-}
diff --git a/ctrl/libhicnctrl/src/hicnctrl.c b/ctrl/libhicnctrl/src/hicnctrl.c
new file mode 100644
index 000000000..99d67b19f
--- /dev/null
+++ b/ctrl/libhicnctrl/src/hicnctrl.c
@@ -0,0 +1,805 @@
+/*
+ * 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 cli.c
+ * \brief Command line interface
+ */
+#include <ctype.h> // isalpha isalnum
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h> // getopt
+
+#include <hicn/ctrl.h>
+#include <hicn/util/ip_address.h>
+#include <hicn/util/token.h>
+#include <hicn/validation.h>
+
+#define die(LABEL, MESSAGE) \
+ do { \
+ printf(MESSAGE "\n"); \
+ rc = -1; \
+ goto ERR_##LABEL; \
+ } while (0)
+
+const char HICNLIGHT_PARAM[] = "hicnlight";
+const char HICNLIGHT_NG_PARAM[] = "hicnlightng";
+const char VPP_PARAM[] = "vpp";
+
+void usage_header() { fprintf(stderr, "Usage:\n"); }
+
+void usage_face_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr,
+ "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose)
+ fprintf(stderr, " Create a face on specified address and port.\n");
+}
+
+void usage_face_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -df ID\n", prog);
+ // fprintf(stderr, "%s -df NAME\n", prog);
+ fprintf(stderr,
+ "%s -df TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose) fprintf(stderr, " Delete a face...\n");
+}
+
+void usage_face_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -F\n", prog);
+ if (verbose) fprintf(stderr, " List all faces.\n");
+}
+
+void usage_face(const char *prog, bool header, bool verbose) {
+ usage_face_create(prog, header, verbose);
+ usage_face_delete(prog, header, verbose);
+ usage_face_list(prog, header, verbose);
+}
+
+void usage_route_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -r FACE_ID PREFIX [COST]\n", prog);
+ // fprintf(stderr, "%s -r [FACE_ID|NAME] PREFIX [COST]\n", prog);
+ if (verbose) fprintf(stderr, " Create a route...\n");
+}
+
+void usage_route_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -dr FACE_ID PREFIX\n", prog);
+ // fprintf(stderr, "%s -dr [FACE_ID|NAME] PREFIX\n", prog);
+ if (verbose) fprintf(stderr, " Delete a route...\n");
+}
+
+void usage_route_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -R\n", prog);
+ if (verbose) fprintf(stderr, " List all routes.\n");
+}
+
+void usage_route(const char *prog, bool header, bool verbose) {
+ usage_route_create(prog, header, verbose);
+ usage_route_delete(prog, header, verbose);
+ usage_route_list(prog, header, verbose);
+}
+
+void usage_forwarding_strategy_create(const char *prog, bool header,
+ bool verbose) {
+ if (header) usage_header();
+}
+void usage_forwarding_strategy_delete(const char *prog, bool header,
+ bool verbose) {
+ if (header) usage_header();
+}
+
+void usage_forwarding_strategy_list(const char *prog, bool header,
+ bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -S\n", prog);
+ if (verbose)
+ fprintf(stderr, " List all availble forwarding strategies.\n");
+}
+
+void usage_forwarding_strategy(const char *prog, bool header, bool verbose) {
+ usage_forwarding_strategy_create(prog, header, verbose);
+ usage_forwarding_strategy_delete(prog, header, verbose);
+ usage_forwarding_strategy_list(prog, header, verbose);
+}
+
+void usage_listener_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n",
+ prog);
+ if (verbose)
+ fprintf(stderr, " Create a listener on specified address and port.\n");
+}
+
+void usage_listener_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -dl ID\n", prog);
+ fprintf(stderr, "%s -dl NAME\n", prog);
+ fprintf(stderr, "%s -dl TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n",
+ prog);
+ if (verbose) fprintf(stderr, " Delete a listener...\n");
+}
+
+void usage_listener_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -L\n", prog);
+ if (verbose) fprintf(stderr, " List all listeners.\n");
+}
+
+void usage_listener(const char *prog, bool header, bool verbose) {
+ usage_listener_create(prog, header, verbose);
+ usage_listener_delete(prog, header, verbose);
+ usage_listener_list(prog, header, verbose);
+}
+void usage_connection_create(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr,
+ "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose)
+ fprintf(stderr, " Create a connection on specified address and port.\n");
+}
+
+void usage_connection_delete(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -dc ID\n", prog);
+ fprintf(stderr, "%s -dc NAME\n", prog);
+ fprintf(stderr,
+ "%s -dc TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT "
+ "[INTERFACE_NAME]\n",
+ prog);
+ if (verbose) fprintf(stderr, " Delete a connection...\n");
+}
+
+void usage_connection_list(const char *prog, bool header, bool verbose) {
+ if (header) usage_header();
+ fprintf(stderr, "%s -C\n", prog);
+ if (verbose) fprintf(stderr, " List all connections.\n");
+}
+
+void usage_connection(const char *prog, bool header, bool verbose) {
+ usage_connection_create(prog, header, verbose);
+ usage_connection_delete(prog, header, verbose);
+ usage_connection_list(prog, header, verbose);
+}
+
+void usage(const char *prog) {
+ fprintf(stderr,
+ "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] "
+ "PARAMETERS | [-F|-L|-C|-R] ]\n",
+ prog);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "High-level commands\n");
+ fprintf(stderr, "\n");
+ usage_face(prog, false, true);
+ usage_route(prog, false, true);
+ usage_forwarding_strategy(prog, false, true);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Low level commands (hicn-light specific)\n");
+ fprintf(stderr, "\n");
+ usage_listener(prog, false, true);
+ usage_connection(prog, false, true);
+}
+
+#if 0
+typedef struct {
+ hc_action_t action;
+ hc_object_t object;
+ union {
+ hc_face_t face;
+ hc_route_t route;
+ hc_connection_t connection;
+ hc_listener_t listener;
+ };
+} hc_command_t;
+#endif
+
+int parse_options(int argc, char *argv[], hc_command_t *command,
+ forwarder_type_t *forwarder) {
+ command->object.type = OBJECT_UNDEFINED;
+ command->action = ACTION_CREATE;
+ int opt;
+ int family;
+
+ while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) {
+ switch (opt) {
+ case 'z':
+ if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) {
+ *forwarder = VPP;
+ } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) {
+ *forwarder = HICNLIGHT;
+ } else if (strncmp(optarg, HICNLIGHT_NG_PARAM,
+ strlen(HICNLIGHT_NG_PARAM))) {
+ *forwarder = HICNLIGHT_NG;
+ } else {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'd':
+ command->action = ACTION_DELETE;
+ break;
+ case 'f':
+ command->object.type = OBJECT_FACE;
+ break;
+ case 'c':
+ command->object.type = OBJECT_CONNECTION;
+ break;
+ case 'F':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_FACE;
+ break;
+ case 'L':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_LISTENER;
+ break;
+ case 'C':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_CONNECTION;
+ break;
+ case 'R':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_ROUTE;
+ break;
+ case 'S':
+ command->action = ACTION_LIST;
+ command->object.type = OBJECT_STRATEGY;
+ break;
+ default: /* "h" */
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ if (command->object.type == OBJECT_UNDEFINED) {
+ fprintf(stderr,
+ "Missing object specification: connection | listener | route\n");
+ return -1;
+ }
+
+ /* Parse and validate parameters for add/delete */
+ switch (command->object.type) {
+ case OBJECT_FACE:
+ switch (command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 5) && (argc - optind != 6)) {
+ usage_face_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ /* NAME will be autogenerated (and currently not used) */
+ // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s",
+ // argv[optind++]);
+ command->object.face.face.type = face_type_from_str(argv[optind++]);
+ if (command->object.face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.face.face.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ // netdevice_set_name(&command->object.face.face.netdevice,
+ // argv[optind++]);
+ command->object.face.face.netdevice.index = atoi(argv[optind++]);
+ }
+
+ break;
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) &&
+ (argc - optind != 6)) {
+ usage_face_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) {
+ command->object.face.id = atoi(argv[optind++]);
+ snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ //} else if (is_symbolic_name(argv[optind])) {
+ // snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s",
+ // argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.face.face.type = face_type_from_str(argv[optind++]);
+ if (command->object.face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.face.face.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ command->object.face.face.netdevice.index = atoi(argv[optind++]);
+ // netdevice_set_name(&command->object.face.face.netdevice,
+ // argv[optind++]);
+ }
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_face_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch (command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 2) && (argc - optind != 3)) {
+ usage_route_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ command->object.route.face_id = atoi(argv[optind++]);
+
+ {
+ ip_prefix_t prefix;
+ ip_prefix_pton(argv[optind++], &prefix);
+ command->object.route.family = prefix.family;
+ command->object.route.remote_addr = prefix.address;
+ command->object.route.len = prefix.len;
+ }
+
+ if (argc != optind) {
+ printf("parse cost\n");
+ command->object.route.cost = atoi(argv[optind++]);
+ }
+ break;
+
+ case ACTION_DELETE:
+ if (argc - optind != 2) {
+ usage_route_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ command->object.route.face_id = atoi(argv[optind++]);
+
+ {
+ ip_prefix_t prefix;
+ ip_prefix_pton(argv[optind++], &prefix);
+ command->object.route.family = prefix.family;
+ command->object.route.remote_addr = prefix.address;
+ command->object.route.len = prefix.len;
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_route_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch (command->action) {
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_forwarding_strategy_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch (command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 4) && (argc - optind != 5)) {
+ usage_listener_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ command->object.listener.type = face_type_from_str(argv[optind++]);
+ if (command->object.listener.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.listener.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.listener.family)) goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->object.listener.interface_name, INTERFACE_LEN,
+ "%s", argv[optind++]);
+ }
+ break;
+
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 3) &&
+ (argc - optind != 4)) {
+ usage_listener_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) {
+ command->object.listener.id = atoi(argv[optind++]);
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else if (is_symbolic_name(argv[optind], SYMBOLIC_NAME_LEN)) {
+ snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.listener.type = face_type_from_str(argv[optind++]);
+ if (command->object.listener.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.listener.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.listener.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->object.listener.interface_name, INTERFACE_LEN,
+ "%s", argv[optind++]);
+ }
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_listener_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch (command->action) {
+ case ACTION_CREATE:
+ /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
+ if ((argc - optind != 6) && (argc - optind != 7)) {
+ usage_connection_create(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ command->object.connection.type = face_type_from_str(argv[optind++]);
+ if (command->object.connection.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.connection.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.remote_port = atoi(argv[optind++]);
+
+ break;
+
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) &&
+ (argc - optind != 6)) {
+ usage_connection_delete(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) {
+ command->object.connection.id = atoi(argv[optind++]);
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else if (is_symbolic_name(argv[optind], SYMBOLIC_NAME_LEN)) {
+ snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s",
+ argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->object.connection.type =
+ face_type_from_str(argv[optind++]);
+ if (command->object.connection.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->object.connection.family =
+ ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->object.connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) ||
+ (command->object.connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++],
+ &command->object.connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->object.connection.remote_port = atoi(argv[optind++]);
+ }
+ break;
+
+ case ACTION_LIST:
+ if (argc - optind != 0) {
+ usage_connection_list(argv[0], true, false);
+ goto ERR_PARAM;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+ break;
+
+ default:
+ goto ERR_COMMAND;
+ }
+
+ return 0;
+
+ERR_PARAM:
+ERR_COMMAND:
+ return -1;
+}
+
+int main(int argc, char *argv[]) {
+ hc_data_t *data;
+ int rc = 1;
+ hc_command_t command = {0};
+ char buf_listener[MAXSZ_HC_LISTENER];
+ char buf_connection[MAXSZ_HC_CONNECTION];
+ char buf_route[MAXSZ_HC_ROUTE];
+ char buf_strategy[MAXSZ_HC_STRATEGY];
+
+ forwarder_type_t forwarder = HICNLIGHT;
+
+ if (parse_options(argc, argv, &command, &forwarder) < 0)
+ die(OPTIONS, "Bad arguments");
+
+ hc_sock_t *s = hc_sock_create_forwarder(forwarder);
+ if (!s) die(SOCKET, "Error creating socket.");
+
+ if (hc_sock_connect(s) < 0)
+ die(CONNECT, "Error connecting to the forwarder.");
+
+ switch (command.object.type) {
+ case OBJECT_FACE:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_face_create(s, &command.object.face) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
+ break;
+
+ case ACTION_DELETE:
+ if (hc_face_delete(s, &command.object.face, 1) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
+ break;
+
+ case ACTION_LIST:
+ if (hc_face_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Faces:\n");
+ foreach_face(f, data) {
+ if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >=
+ MAXSZ_HC_FACE)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", f->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_route_create(s, &command.object.route) < 0)
+ die(COMMAND, "Error creating route");
+ printf("OK\n");
+ break;
+
+ case ACTION_DELETE:
+ if (hc_route_delete(s, &command.object.route) < 0)
+ die(COMMAND, "Error creating route");
+ printf("OK\n");
+ break;
+
+ case ACTION_LIST:
+ if (hc_route_list(s, &data) < 0)
+ die(COMMAND, "Error getting routes.");
+
+ printf("Routes:\n");
+ foreach_route(r, data) {
+ if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >=
+ MAXSZ_HC_ROUTE)
+ die(COMMAND, "Display error");
+ printf("%s\n", buf_route);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for route");
+ break;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch (command.action) {
+ case ACTION_LIST:
+ if (hc_strategy_list(s, &data) < 0)
+ die(COMMAND, "Error getting routes.");
+
+ printf("Forwarding strategies:\n");
+ foreach_strategy(st, data) {
+ if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >=
+ MAXSZ_HC_STRATEGY)
+ die(COMMAND, "Display error");
+ printf("%s\n", buf_strategy);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for strategy");
+ break;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_listener_create(s, &command.object.listener) < 0)
+ die(COMMAND, "Error creating listener");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_listener_delete(s, &command.object.listener) < 0)
+ die(COMMAND, "Error deleting listener");
+ printf("OK\n");
+ break;
+ case ACTION_LIST:
+ if (hc_listener_list(s, &data) < 0)
+ die(COMMAND, "Error getting listeners.");
+
+ printf("Listeners:\n");
+ foreach_listener(l, data) {
+ if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER + 17, l) >=
+ MAXSZ_HC_LISTENER)
+ die(COMMAND, "Display error");
+ printf("[%d] %s\n", l->id, buf_listener);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for listener");
+ break;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch (command.action) {
+ case ACTION_CREATE:
+ if (hc_connection_create(s, &command.object.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_connection_delete(s, &command.object.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_LIST:
+ if (hc_connection_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Connections:\n");
+ foreach_connection(c, data) {
+ if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION,
+ c) >= MAXSZ_HC_CONNECTION)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", c->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
+ default:
+ die(COMMAND, "Unsupported object");
+ break;
+ }
+
+ERR_COMMAND:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCKET:
+ERR_OPTIONS:
+ return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in b/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in
new file mode 100644
index 000000000..a27d85cde
--- /dev/null
+++ b/ctrl/libhicnctrl/src/libhicnctrl-config.cmake.in
@@ -0,0 +1,8 @@
+@PACKAGE_INIT@
+
+set(Libhicnctrl_VERSION_MAJOR "@VERSION_MAJOR@")
+set(Libhicnctrl_VERSION_MINOR "@VERSION_MINOR@")
+set(Libhicnctrl_VERSION_PATCH "@VERSION_PATCH@")
+
+set_and_check(Libhicnctrl_INCLUDE_DIRS "@PACKAGE_Libhicnctrl_INCLUDE_DIRS@")
+include("${CMAKE_CURRENT_LIST_DIR}/libhicnctrl-targets.cmake")
diff --git a/ctrl/libhicnctrl/src/modules/CMakeLists.txt b/ctrl/libhicnctrl/src/modules/CMakeLists.txt
index e07ab8c99..8f7916d14 100644
--- a/ctrl/libhicnctrl/src/modules/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/modules/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,38 +11,53 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-
-list(APPEND HICNLIGHT_MODULE_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_api.c
+##############################################################
+# Hicn Light NG Module
+##############################################################
+list(APPEND HICNLIGHTNG_MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_common.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_ng_api.c
)
-build_module(hicnlightctrl_module
- SHARED
- SOURCES ${HICNLIGHT_MODULE_SOURCE_FILES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${LIBHICNCTRL_COMPONENT}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+build_module(hicnlightngctrl_module
+ SOURCES ${HICNLIGHTNG_MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES}
+ INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS}
+ DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS PRIVATE ${COMPILE_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
+
+##############################################################
+# VPP Module
+##############################################################
if(BUILD_HICNPLUGIN AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- list(APPEND HICNLIGHT_PLUGIN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c
+ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
+ find_package(Safevapi ${CURRENT_VERSION} REQUIRED)
+ else()
+ list(APPEND DEPENDENCIES
+ ${SAFE_VAPI_SHARED}
+ )
+ endif()
+
+ list(APPEND HICN_PLUGIN_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c
)
build_module(vppctrl_module
- SHARED
- SOURCES ${HICNLIGHT_PLUGIN_SOURCE_FILES}
- DEPENDS ${DEPENDENCIES}
- LINK_LIBRARIES ${HICNPLUGIN_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
- COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
- LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs"
+ SOURCES ${HICN_PLUGIN_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ LINK_LIBRARIES
+ PRIVATE ${HICN_LIBRARIES}
+ PRIVATE ${HICNPLUGIN_LIBRARIES}
+ PRIVATE ${SAFE_VAPI_LIBRARIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES}
+ INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS}
+ DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS} ${MARCH_COMPILER_OPTIONS}
)
-
-endif() \ No newline at end of file
+endif()
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_api.c
deleted file mode 100644
index d1a055777..000000000
--- a/ctrl/libhicnctrl/src/modules/hicn_light_api.c
+++ /dev/null
@@ -1,2278 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * \file api.c
- * \brief Implementation of hICN control library API
- */
-
-#include "api_private.h"
-
-#include <assert.h> // assert
-#include <stdbool.h>
-#include <stdio.h> // snprintf
-#include <string.h> // memmove, strcasecmp
-#include <sys/socket.h> // socket
-#include <unistd.h> // close, fcntl
-#include <fcntl.h> // fcntl
-#include <sys/types.h> // getpid
-#include <unistd.h> // getpid
-#ifdef __linux__
-#include <sys/syscall.h>
-#define gettid() syscall(SYS_gettid)
-#endif /* __linux__ */
-#include <strings.h>
-
-#define PORT 9695
-
-#define BOOLSTR(x) ((x) ? "true" : "false")
-
-/*
- * Internal state associated to a pending request
- */
-typedef struct {
- int seq;
- hc_data_t * data;
- /* Information used to process results */
- int size_in;
- int (*parse)(const u8 * src, u8 * dst);
-} hc_sock_request_t;
-
-/**
- * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
- * the header_control_message structure. The forwarder simply answers back the
- * original sequence number. We maintain a map of such sequence number to
- * outgoing queries so that replied can be demultiplexed and treated
- * appropriately.
- */
-TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
-TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, generic_snprintf);
-
-struct hc_sock_light_s {
- /* This must be the first element of the struct */
- hc_sock_t vft;
-
- char * url;
- int fd;
-
- /* Partial receive buffer */
- u8 buf[RECV_BUFLEN];
- size_t roff; /**< Read offset */
- size_t woff; /**< Write offset */
-
- /*
- * Because received messages are potentially unbounded in size, we might not
- * guarantee that we can store a full packet before processing it. We must
- * implement a very simple state machine remembering the current parsing
- * status in order to partially process the packet.
- */
- size_t remaining;
- u32 send_id;
-
- /* Next sequence number to be used for requests */
- int seq;
-
- /* Request being parsed (NULL if none) */
- hc_sock_request_t * cur_request;
-
- bool async;
- hc_sock_map_t * map;
-};
-
-typedef struct hc_sock_light_s hc_sock_light_t;
-
-#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t*)(s)
-
-hc_sock_request_t *
-hc_sock_request_create(int seq, hc_data_t * data, HC_PARSE parse)
-{
- assert(data);
-
- hc_sock_request_t * request = malloc(sizeof(hc_sock_request_t));
- if (!request)
- return NULL;
- request->seq = seq;
- request->data = data;
- request->parse = parse;
- return request;
-}
-
-void
-hc_sock_light_request_free(hc_sock_request_t * request)
-{
- free(request);
-}
-
-/*
- * list was working with all seq set to 0, but it seems hicnLightControl uses
- * 1, and replies with the same seqno
- */
-#define HICN_CTRL_SEND_SEQ_INIT 1
-#define HICN_CTRL_RECV_SEQ_INIT 1
-
-#define MAX(x, y) ((x > y) ? x : y)
-
-/**
- * In practise, we want to preserve enough room to store a full packet of
- * average expected size (say a header + N payload elements).
- */
-#define AVG_ELEMENTS (1 << DEFAULT_SIZE_LOG)
-#define AVG_BUFLEN (sizeof(hc_msg_header_t) + AVG_ELEMENTS * sizeof(hc_msg_payload_t))
-
-/*
- * We should at least have buffer space allowing to store one processable unit
- * of data, either the header of the maximum possible payload
- */
-#define MIN_BUFLEN MAX(sizeof(hc_msg_header_t), sizeof(hc_msg_payload_t))
-
-static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
-
-/******************************************************************************
- * Message helper types and aliases
- ******************************************************************************/
-
-#define foreach_hc_command \
- _(add_connection) \
- _(remove_connection) \
- _(list_connections) \
- _(add_listener) \
- _(remove_listener) \
- _(list_listeners) \
- _(add_route) \
- _(remove_route) \
- _(list_routes) \
- _(cache_store) \
- _(cache_serve) \
- /*_(cache_clear) */ \
- _(set_strategy) \
- _(set_wldr) \
- _(add_punting) \
- _(mapme_activator) \
- _(mapme_timing)
-
-typedef header_control_message hc_msg_header_t;
-
-typedef union {
-#define _(x) x ## _command x;
- foreach_hc_command
-#undef _
-} hc_msg_payload_t;
-
-
-typedef struct hc_msg_s {
- hc_msg_header_t hdr;
- hc_msg_payload_t payload;
-} hc_msg_t;
-
-/******************************************************************************
- * Control socket
- ******************************************************************************/
-
-/**
- * \brief Parse a connection URL into a sockaddr
- * \param [in] url - URL
- * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
- * \return 0 if parsing succeeded, a negative error value otherwise.
- */
-static int
-_hc_sock_light_parse_url(const char * url, struct sockaddr * sa)
-{
- /* FIXME URL parsing is currently not implemented */
- assert(!url);
-
-#ifdef __linux__
- srand(time(NULL) ^ getpid() ^ gettid());
-#else
- srand((unsigned int )(time(NULL) ^ getpid()));
-#endif /* __linux__ */
-
- /*
- * A temporary solution is to inspect the sa_family fields of the passed in
- * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
- * connection to localhost.
- */
- switch (sa->sa_family) {
- case AF_UNSPEC:
- case AF_INET:
- {
- struct sockaddr_in * sai = (struct sockaddr_in *)sa;
- sai->sin_family = AF_INET;
- sai->sin_port = htons(PORT);
- sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- break;
- }
- case AF_INET6:
- {
- struct sockaddr_in6 * sai6 = (struct sockaddr_in6 *)sa;
- sai6->sin6_family = AF_INET6;
- sai6->sin6_port = htons(PORT);
- sai6->sin6_addr = loopback_addr;
- break;
- }
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int
-_hc_sock_light_reset(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- s->roff = s->woff = 0;
- s->remaining = 0;
- return 0;
-}
-
-void
-_hc_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);
- if (s->url)
- free(s->url);
- close(s->fd);
- free(s);
-}
-
-static int
-_hc_sock_light_get_next_seq(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- return s->seq++;
-}
-
-static int
-_hc_sock_light_set_nonblocking(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
-}
-
-static int
-_hc_sock_light_get_fd(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- return s->fd;
-}
-
-static int
-_hc_sock_light_connect(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- struct sockaddr_storage ss;
- memset(&ss, 0, sizeof(struct sockaddr_storage));
-
- if (_hc_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0)
- goto ERR_PARSE;
-
- size_t size = ss.ss_family == AF_INET
- ? sizeof(struct sockaddr_in)
- : sizeof(struct sockaddr_in6);
- if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) //sizeof(struct sockaddr)) < 0)
- goto ERR_CONNECT;
-
- return 0;
-
-ERR_CONNECT:
-ERR_PARSE:
- return -1;
-}
-
-static int
-_hc_sock_light_send(hc_sock_t * socket, hc_msg_t * msg, size_t msglen, int seq)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int rc;
- msg->hdr.seqNum = seq;
- rc = (int)send(s->fd, msg, msglen, 0);
- if (rc < 0) {
- perror("hc_sock_light_send");
- return -1;
- }
- return 0;
-}
-
-static int
-_hc_sock_light_get_available(hc_sock_t * socket, u8 ** buffer, size_t * size)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- *buffer = s->buf + s->woff;
- *size = RECV_BUFLEN - s->woff;
-
- return 0;
-}
-
-static int
-_hc_sock_light_recv(hc_sock_t * socket)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int rc;
-
- /*
- * This condition should be ensured to guarantee correct processing of
- * messages
- */
- assert(RECV_BUFLEN - s->woff > MIN_BUFLEN);
-
- rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
- if (rc == 0) {
- /* Connection has been closed */
- return 0;
- }
- if (rc < 0) {
- /*
- * Let's not return 0 which currently means the socket has been closed
- */
- if (errno == EWOULDBLOCK)
- return -1;
- perror("hc_sock_light_recv");
- return -1;
- }
- s->woff += rc;
- return rc;
-}
-
-/*
- * Returns -99 in case of internal error, -1 in case of API command failure
- */
-static int
-_hc_sock_light_process(hc_sock_t * socket, hc_data_t ** data)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int err = 0;
-
- /* We must have received at least one byte */
- size_t available = s->woff - s->roff;
-
- while(available > 0) {
-
- if (!s->cur_request) { // No message being parsed, alternatively (remaining == 0)
- hc_msg_t * msg = (hc_msg_t*)(s->buf + s->roff);
-
- /* We expect a message header */
- if (available < sizeof(hc_msg_header_t)) {
- break;
- }
-
- hc_sock_request_t * request = NULL;
- if (hc_sock_map_get(s->map, msg->hdr.seqNum, &request) < 0) {
- ERROR("[hc_sock_light_process] Error searching for matching request");
- return -99;
- }
- if (!request) {
- ERROR("[hc_sock_light_process] No request matching received sequence number");
- return -99;
- }
-
- s->remaining = msg->hdr.length;
- switch(msg->hdr.messageType) {
- case ACK_LIGHT:
- assert(s->remaining == 1);
- assert(!data);
- s->cur_request = request;
- break;
- case NACK_LIGHT:
- assert(s->remaining == 1);
- assert(!data);
- hc_data_set_error(request->data);
- s->cur_request = request;
- err = -1;
- break;
- case RESPONSE_LIGHT:
- assert(data);
- if (s->remaining == 0) {
- hc_data_set_complete(request->data);
- *data = request->data;
- 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);
- } else {
- /* We only remember it if there is still data to parse */
- s->cur_request = request;
- }
- break;
- default:
- ERROR("[hc_sock_light_process] Invalid response received");
- return -99;
- }
-
- available -= sizeof(hc_msg_header_t);
- s->roff += sizeof(hc_msg_header_t);
- } else {
- /* We expect the complete payload, or at least a chunk of it */
- size_t num_chunks = available / s->cur_request->data->in_element_size;
- if (num_chunks == 0)
- break;
- if (num_chunks > s->remaining)
- num_chunks = s->remaining;
-
- if (!s->cur_request->parse) {
- /* If we don't need to parse results, then we can directly push
- * all of them into the result data structure */
- hc_data_push_many(s->cur_request->data, s->buf + s->roff, num_chunks);
- } else {
- int rc;
- rc = hc_data_ensure_available(s->cur_request->data, num_chunks);
- if (rc < 0) {
- ERROR("[hc_sock_light_process] Error in hc_data_ensure_available");
- return -99;
- }
- for (int i = 0; i < num_chunks; i++) {
- u8 * dst = hc_data_get_next(s->cur_request->data);
- if (!dst) {
- ERROR("[hc_sock_light_process] Error in hc_data_get_next");
- return -99;
- }
-
- rc = s->cur_request->parse(s->buf + s->roff + i * s->cur_request->data->in_element_size, dst);
- if (rc < 0) {
- ERROR("[hc_sock_light_process] Error in parse");
- err = -99; /* FIXME we let the loop complete (?) */
- }
- s->cur_request->data->size++;
- }
- }
-
- s->remaining -= num_chunks;
- available -= num_chunks * s->cur_request->data->in_element_size;
- s->roff += num_chunks * s->cur_request->data->in_element_size;
- if (s->remaining == 0) {
- if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
- ERROR("[hc_sock_light_process] Error removing request from map");
- return -99;
- }
- hc_data_set_complete(s->cur_request->data);
- if (data)
- *data = s->cur_request->data;
- hc_sock_light_request_free(s->cur_request);
- s->cur_request = NULL;
- }
-
- }
- }
-
- /* Make sure there is enough remaining space in the buffer */
- if (RECV_BUFLEN - s->woff < AVG_BUFLEN) {
- /*
- * There should be no overlap provided a sufficiently large BUFLEN, but
- * who knows.
- */
- memmove(s->buf, s->buf + s->roff, s->woff - s->roff);
- s->woff -= s->roff;
- s->roff = 0;
- }
-
- return err;
-}
-
-static int
-_hc_sock_light_callback(hc_sock_t * socket, hc_data_t ** pdata)
-{
- hc_data_t * data;
-
- for (;;) {
- int n = _hc_sock_light_recv(socket);
- if (n == 0)
- goto ERR_EOF;
- if (n < 0) {
- switch(errno) {
- case ECONNRESET:
- case ENODEV:
- /* Forwarder restarted */
- WARN("Forwarder likely restarted: not (yet) implemented");
- goto ERR;
- case EWOULDBLOCK:
- //DEBUG("Would block... stop reading from socket");
- goto END;
- default:
- perror("hc_sock_light_recv");
- goto ERR;
- }
- }
- if (_hc_sock_light_process(socket, &data) < 0) {
- goto ERR;
- }
- }
-END:
- if (pdata)
- *pdata = data;
- else
- hc_data_free(data);
- return 0;
-
-ERR:
- hc_data_free(data);
-ERR_EOF:
- return -1;
-}
-
-/******************************************************************************
- * Command-specific structures and functions
- ******************************************************************************/
-
-typedef int (*HC_PARSE)(const u8 *, u8 *);
-
-typedef struct {
- hc_action_t cmd;
- command_id cmd_id;
- size_t size_in;
- size_t size_out;
- HC_PARSE parse;
-} hc_command_params_t;
-
-static int
-_hc_execute_command(hc_sock_t * socket, hc_msg_t * msg, size_t msg_len,
- hc_command_params_t * params, hc_data_t ** pdata, bool async)
-{
- hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- int ret;
- if (async)
- assert(!pdata);
-
- /* Sanity check */
- switch(params->cmd) {
- case ACTION_CREATE:
- assert(params->size_in != 0); /* payload repeated */
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- case ACTION_DELETE:
- assert(params->size_in != 0); /* payload repeated */
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- case ACTION_LIST:
- assert(params->size_in != 0);
- assert(params->size_out != 0);
- assert(params->parse != NULL);
- break;
- case ACTION_SET:
- assert(params->size_in != 0);
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- default:
- return -1;
- }
-
- //hc_sock_light_reset(s);
-
- /* XXX data will at least store the result (complete) */
- hc_data_t * data = hc_data_create(params->size_in, params->size_out, NULL);
- if (!data) {
- ERROR("[_hc_execute_command] Could not create data storage");
- goto ERR_DATA;
- }
-
- int seq = _hc_sock_light_get_next_seq(socket);
-
- /* Create state used to process the request */
- hc_sock_request_t * request = NULL;
- request = hc_sock_request_create(seq, data, params->parse);
- if (!request) {
- ERROR("[_hc_execute_command] Could not create request state");
- goto ERR_REQUEST;
- }
-
- /* Add state to map */
- if (hc_sock_map_add(s->map, seq, request) < 0) {
- ERROR("[_hc_execute_command] Error adding request state to map");
- goto ERR_MAP;
- }
-
- if (_hc_sock_light_send(socket, msg, msg_len, seq) < 0) {
- ERROR("[_hc_execute_command] Error sending message");
- goto ERR_PROCESS;
- }
-
- if (async)
- return 0;
-
- while(!data->complete) {
- /*
- * As the socket is non blocking it might happen that we need to read
- * several times before success... shall we alternate between blocking
- * and non-blocking mode ?
- */
- int n = _hc_sock_light_recv(socket);
- if (n == 0)
- goto ERR_EOF;
- if (n < 0)
- continue; //break;
- int rc = _hc_sock_light_process(socket, pdata);
- switch(rc) {
- case 0:
- break;
- case -1:
- ret = rc;
- break;
- case -99:
- ERROR("[_hc_execute_command] Error processing socket results");
- goto ERR;
- break;
- default:
- ERROR("[_hc_execute_command] Unexpected return value");
- goto ERR;
- }
- }
-
-ERR_EOF:
- ret = data->ret;
- if (!data->complete)
- return -1;
- if (!pdata)
- hc_data_free(data);
-
- return ret;
-
-ERR_PROCESS:
-ERR_MAP:
- hc_sock_light_request_free(request);
-ERR:
-ERR_REQUEST:
- hc_data_free(data);
-ERR_DATA:
- return -99;
-}
-
-/*----------------------------------------------------------------------------*
- * Listeners
- *----------------------------------------------------------------------------*/
-
-/* LISTENER CREATE */
-
-static int
-_hc_listener_create_internal(hc_sock_t * socket, hc_listener_t * listener, bool async)
-{
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[_hc_listener_create] Unexpected truncation of listener string");
- DEBUG("[_hc_listener_create] listener=%s async=%s", listener_s,
- BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(listener->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return -1;
-
- struct {
- header_control_message hdr;
- add_listener_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_LISTENER,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = listener->local_addr,
- .port = htons(listener->local_port),
- .addressType = (u8)map_to_addr_type[listener->family],
- .listenerMode = (u8)map_to_listener_mode[listener->type],
- .connectionType = (u8)map_to_connection_type[listener->type],
- }
- };
-
- rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_create] Unexpected truncation of symbolic name string");
-
- rc = snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[_hc_listener_create] Unexpected truncation of interface name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_LISTENER,
- .size_in = sizeof(add_listener_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_create_internal(s, listener, false);
-}
-
-static int
-_hc_listener_create_async(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_create_internal(s, listener, true);
-}
-
-/* LISTENER LIST */
-
-static int
-_hc_listener_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- DEBUG("[hc_listener_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_LISTENERS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_LISTENERS,
- .size_in = sizeof(list_listeners_command),
- .size_out = sizeof(hc_listener_t),
- .parse = (HC_PARSE)hc_listener_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_listener_list_internal(s, pdata, false);
-}
-
-static int
-_hc_listener_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_listener_list_internal(s, pdata, true);
-}
-
-/* LISTENER GET */
-
-static int
-_hc_listener_get(hc_sock_t * socket, hc_listener_t * listener,
- hc_listener_t ** listener_found)
-{
- hc_data_t * listeners;
- hc_listener_t * found;
-
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[hc_listener_get] Unexpected truncation of listener string");
- DEBUG("[hc_listener_get] listener=%s", listener_s);
-
- if (_hc_listener_list(socket, &listeners) < 0)
- return -1;
-
- /* Test */
- if (hc_listener_find(listeners, listener, &found) < 0) {
- hc_data_free(listeners);
- return -1;
- }
-
- if (found) {
- *listener_found = malloc(sizeof(hc_listener_t));
- if (!*listener_found)
- return -1;
- **listener_found = *found;
- } else {
- *listener_found = NULL;
- }
-
- hc_data_free(listeners);
-
- return 0;
-}
-
-
-/* LISTENER DELETE */
-
-static int
-_hc_listener_delete_internal(hc_sock_t * socket, hc_listener_t * listener, bool async)
-{
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[_hc_listener_delete] Unexpected truncation of listener string");
- DEBUG("[_hc_listener_delete] listener=%s async=%s", listener_s,
- BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- remove_listener_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_LISTENER,
- .length = 1,
- .seqNum = 0,
- },
- };
-
- if (listener->id) {
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- } else if (*listener->name) {
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listener->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- } else {
- hc_listener_t * listener_found;
- if (_hc_listener_get(socket, listener, &listener_found) < 0)
- return -1;
- if (!listener_found)
- return -1;
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener_found->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- free(listener_found);
- }
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_LISTENER,
- .size_in = sizeof(remove_listener_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_delete_internal(s, listener, false);
-}
-
-static int
-_hc_listener_delete_async(hc_sock_t * s, hc_listener_t * listener)
-{
- return _hc_listener_delete_internal(s, listener, true);
-}
-
-/*----------------------------------------------------------------------------*
- * CONNECTION
- *----------------------------------------------------------------------------*/
-
-/* CONNECTION CREATE */
-
-static int
-_hc_connection_create_internal(hc_sock_t * socket, hc_connection_t * connection, bool async)
-{
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[_hc_connection_create] Unexpected truncation of connection string");
- DEBUG("[_hc_connection_create] connection=%s async=%s", connection_s, BOOLSTR(async));
-
- if (hc_connection_validate(connection) < 0)
- return -1;
-
- struct {
- header_control_message hdr;
- add_connection_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_CONNECTION,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .remoteIp = connection->remote_addr,
- .localIp = connection->local_addr,
- .remotePort = htons(connection->remote_port),
- .localPort = htons(connection->local_port),
- .ipType = (u8)map_to_addr_type[connection->family],
- .connectionType = (u8)map_to_connection_type[connection->type],
- .admin_state = connection->admin_state,
-#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
-#endif /* WITH_POLICY */
- }
- };
- rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_create] Unexpected truncation of symbolic name string");
- //snprintf(msg.payload.interfaceName, INTERFACE_NAME_LEN, "%s", connection->interface_name);
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_CONNECTION,
- .size_in = sizeof(add_connection_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_create_internal(s, connection, false);
-}
-
-static int
-_hc_connection_create_async(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_create_internal(s, connection, true);
-}
-
-/* CONNECTION LIST */
-
-static int
-_hc_connection_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- DEBUG("[hc_connection_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_CONNECTIONS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_CONNECTIONS,
- .size_in = sizeof(list_connections_command),
- .size_out = sizeof(hc_connection_t),
- .parse = (HC_PARSE)hc_connection_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_connection_list_internal(s, pdata, false);
-}
-
-static int
-_hc_connection_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_connection_list_internal(s, pdata, true);
-}
-
-/* CONNECTION GET */
-
-static int
-_hc_connection_get(hc_sock_t * socket, hc_connection_t * connection,
- hc_connection_t ** connection_found)
-{
- hc_data_t * connections;
- hc_connection_t * found;
-
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[hc_connection_get] Unexpected truncation of connection string");
- DEBUG("[hc_connection_get] connection=%s", connection_s);
-
- if (_hc_connection_list(socket, &connections) < 0)
- return -1;
-
- /* Test */
- if (hc_connection_find(connections, connection, &found) < 0) {
- hc_data_free(connections);
- return -1;
- }
-
- if (found) {
- *connection_found = malloc(sizeof(hc_connection_t));
- if (!*connection_found)
- return -1;
- **connection_found = *found;
- } else {
- *connection_found = NULL;
- }
-
- hc_data_free(connections);
-
- return 0;
-}
-
-
-/* CONNECTION DELETE */
-
-static int
-_hc_connection_delete_internal(hc_sock_t * socket, hc_connection_t * connection, bool async)
-{
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[_hc_connection_delete] Unexpected truncation of connection string");
- DEBUG("[_hc_connection_delete] connection=%s async=%s", connection_s, BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- remove_connection_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_CONNECTION,
- .length = 1,
- .seqNum = 0,
- },
- };
-
- if (connection->id) {
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- } else if (*connection->name) {
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- } else {
- hc_connection_t * connection_found;
- if (_hc_connection_get(socket, connection, &connection_found) < 0)
- return -1;
- if (!connection_found)
- return -1;
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection_found->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- free(connection_found);
- }
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_CONNECTION,
- .size_in = sizeof(remove_connection_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_delete_internal(s, connection, false);
-}
-
-static int
-_hc_connection_delete_async(hc_sock_t * s, hc_connection_t * connection)
-{
- return _hc_connection_delete_internal(s, connection, true);
-}
-
-static int
-_hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
- hc_connection_t *connection)
-{
- // Not implemented
- return -1;
-}
-
-static int
-_hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
- hc_connection_t *connection_updated)
-{
- // Not implemented
- return -1;
-}
-
-/* CONNECTION SET ADMIN STATE */
-
-static int
-_hc_connection_set_admin_state_internal(hc_sock_t * socket, const char * conn_id_or_name,
- face_state_t state, bool async)
-{
- int rc;
- DEBUG("[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s async=%s",
- conn_id_or_name, face_state_str[state], BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_admin_state_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_ADMIN_STATE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .admin_state = state,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_admin_state] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_ADMIN_STATE,
- .size_in = sizeof(connection_set_admin_state_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
-{
- return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, false);
-}
-
-static int
-_hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
-{
- return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, true);
-}
-
-#ifdef WITH_POLICY
-
-static int
-_hc_connection_set_priority_internal(hc_sock_t * socket, const char * conn_id_or_name,
- uint32_t priority, bool async)
-{
- int rc;
- DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s",
- conn_id_or_name, priority, BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_priority_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_PRIORITY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .priority = priority,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_PRIORITY,
- .size_in = sizeof(connection_set_priority_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, false);
-}
-
-static int
-_hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, true);
-}
-
-#endif // WITH_POLICY
-
-static int
-_hc_connection_set_tags_internal(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags, bool async)
-{
- int rc;
- DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s",
- conn_id_or_name, tags, BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_tags_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_TAGS,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .tags = tags,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_tags] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_TAGS,
- .size_in = sizeof(connection_set_tags_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, false);
-}
-
-static int
-_hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Routes
- *----------------------------------------------------------------------------*/
-
-/* ROUTE CREATE */
-
-static int
-_hc_route_create_internal(hc_sock_t * socket, hc_route_t * route, bool async)
-{
- char route_s[MAXSZ_HC_ROUTE];
- int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
- if (rc >= MAXSZ_HC_ROUTE)
- WARN("[_hc_route_create] Unexpected truncation of route string");
- if (rc < 0)
- WARN("[_hc_route_create] Error building route string");
- else
- DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(route->family))
- return -1;
-
- struct {
- header_control_message hdr;
- add_route_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_ROUTE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = route->remote_addr,
- .cost = route->cost,
- .addressType = (u8)map_to_addr_type[route->family],
- .len = route->len,
- }
- };
-
- /*
- * The route commands expects the ID (or name that we don't use) as part of
- * the symbolicOrConnid attribute.
- */
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_route_create] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_ROUTE,
- .size_in = sizeof(add_route_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_route_create(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_create_internal(s, route, false);
-}
-
-static int
-_hc_route_create_async(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_create_internal(s, route, true);
-}
-
-/* ROUTE DELETE */
-
-static int
-_hc_route_delete_internal(hc_sock_t * socket, hc_route_t * route, bool async)
-{
- char route_s[MAXSZ_HC_ROUTE];
- int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
- if (rc >= MAXSZ_HC_ROUTE)
- WARN("[_hc_route_delete] Unexpected truncation of route string");
- DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(route->family))
- return -1;
-
- struct {
- header_control_message hdr;
- remove_route_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_ROUTE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = route->remote_addr,
- .addressType = (u8)map_to_addr_type[route->family],
- .len = route->len,
- }
- };
-
- /*
- * The route commands expects the ID (or name that we don't use) as part of
- * the symbolicOrConnid attribute.
- */
- snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_ROUTE,
- .size_in = sizeof(remove_route_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_route_delete(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_delete_internal(s, route, false);
-}
-
-static int
-_hc_route_delete_async(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_delete_internal(s, route, true);
-}
-
-/* ROUTE LIST */
-
-static int
-_hc_route_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- //DEBUG("[hc_route_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_ROUTES,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_ROUTES,
- .size_in = sizeof(list_routes_command),
- .size_out = sizeof(hc_route_t),
- .parse = (HC_PARSE)hc_route_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_route_list_internal(s, pdata, false);
-}
-
-static int
-_hc_route_list_async(hc_sock_t * s)
-{
- return _hc_route_list_internal(s, NULL, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Face
- *
- * Face support is not directly available in hicn-light, but we can offer such
- * an interface through a combination of listeners and connections. The code
- * starts with some conversion functions between faces/listeners/connections.
- *
- * We also need to make sure that there always exist a (single) listener when a
- * connection is created, and in the hICN face case, that there is a single
- * connection attached to this listener.
- *
- *----------------------------------------------------------------------------*/
-
-/* FACE CREATE */
-
-static int
-_hc_face_create(hc_sock_t * socket, hc_face_t * face)
-{
- hc_listener_t listener;
- hc_listener_t * listener_found;
-
- hc_connection_t connection;
- hc_connection_t * connection_found;
-
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_create] Unexpected truncation of face string");
- DEBUG("[hc_face_create] face=%s", face_s);
-
- switch(face->face.type)
- {
- case FACE_TYPE_HICN:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, true) < 0) {
- ERROR("[hc_face_create] Could not convert face to connection.");
- return -1;
- }
-
- /* Ensure we have a corresponding local listener */
- if (hc_connection_to_local_listener(&connection, &listener) < 0) {
- ERROR("[hc_face_create] Could not convert face to local listener.");
- return -1;
- }
-
- if (_hc_listener_get(socket, &listener, &listener_found) < 0) {
- ERROR("[hc_face_create] Could not retrieve listener");
- return -1;
- }
-
- if (!listener_found) {
- /* We need to create the listener if it does not exist */
- if (_hc_listener_create(socket, &listener) < 0) {
- ERROR("[hc_face_create] Could not create listener.");
- free(listener_found);
- return -1;
- }
- } else {
- free(listener_found);
- }
-
- /* Create corresponding connection */
- if (_hc_connection_create(socket, &connection) < 0) {
- ERROR("[hc_face_create] Could not create connection.");
- return -1;
- }
-
- /*
- * Once the connection is created, we need to list all connections
- * and compare with the current one to find the created face ID.
- */
- if (_hc_connection_get(socket, &connection, &connection_found) < 0) {
- ERROR("[hc_face_create] Could not retrieve connection");
- return -1;
- }
-
- if (!connection_found) {
- ERROR("[hc_face_create] Could not find newly created connection.");
- return -1;
- }
-
- face->id = connection_found->id;
- free(connection_found);
-
- break;
-
- case FACE_TYPE_HICN_LISTENER:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- if (hc_face_to_listener(face, &listener) < 0) {
- ERROR("Could not convert face to listener.");
- return -1;
- }
- if (_hc_listener_create(socket, &listener) < 0) {
- ERROR("[hc_face_create] Could not create listener.");
- return -1;
- }
- return -1;
- break;
- default:
- ERROR("[hc_face_create] Unknwon face type.");
-
- return -1;
- };
-
- return 0;
-}
-
-static int
-_hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found)
-{
- hc_listener_t listener;
- hc_listener_t * listener_found;
-
- hc_connection_t connection;
- hc_connection_t * connection_found;
-
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_get] Unexpected truncation of face string");
- DEBUG("[hc_face_get] face=%s", face_s);
-
- switch(face->face.type)
- {
- case FACE_TYPE_HICN:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, false) < 0)
- return -1;
- if (_hc_connection_get(socket, &connection, &connection_found) < 0)
- return -1;
- if (!connection_found) {
- *face_found = NULL;
- return 0;
- }
- *face_found = malloc(sizeof(hc_face_t));
- hc_connection_to_face(connection_found, *face_found);
- free(connection_found);
- break;
-
- case FACE_TYPE_HICN_LISTENER:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- if (hc_face_to_listener(face, &listener) < 0)
- return -1;
- if (_hc_listener_get(socket, &listener, &listener_found) < 0)
- return -1;
- if (!listener_found) {
- *face_found = NULL;
- return 0;
- }
- *face_found = malloc(sizeof(hc_face_t));
- hc_listener_to_face(listener_found, *face_found);
- free(listener_found);
- break;
-
- default:
- return -1;
- }
-
- return 0;
-
-}
-
-/* FACE DELETE */
-
-static int
-_hc_face_delete(hc_sock_t * socket, hc_face_t * face)
-{
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_delete] Unexpected truncation of face string");
- DEBUG("[hc_face_delete] face=%s", face_s);
-
- hc_connection_t connection;
- if (hc_face_to_connection(face, &connection, false) < 0) {
- ERROR("[hc_face_delete] Could not convert face to connection.");
- return -1;
- }
-
- if (_hc_connection_delete(socket, &connection) < 0) {
- ERROR("[hc_face_delete] Error removing connection");
- return -1;
- }
-
- /* If this is the last connection attached to the listener, remove it */
-
- hc_data_t * connections;
- hc_listener_t listener = {{0}};
-
- /*
- * Ensure we have a corresponding local listener
- * NOTE: hc_face_to_listener is not appropriate
- */
- if (hc_connection_to_local_listener(&connection, &listener) < 0) {
- ERROR("[hc_face_create] Could not convert face to local listener.");
- return -1;
- }
-#if 1
- /*
- * The name is generated to prepare listener creation, we need it to be
- * empty for deletion. The id should not need to be reset though.
- */
- listener.id = 0;
- memset(listener.name, 0, sizeof(listener.name));
-#endif
- if (_hc_connection_list(socket, &connections) < 0) {
- ERROR("[hc_face_delete] Error getting the list of listeners");
- return -1;
- }
-
- bool delete = true;
- foreach_connection(c, connections) {
- if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == 0) &&
- (c->local_port == listener.local_port) &&
- (strcmp(c->interface_name, listener.interface_name) == 0)) {
- delete = false;
- }
- }
-
- if (delete) {
- if (_hc_listener_delete(socket, &listener) < 0) {
- ERROR("[hc_face_delete] Error removing listener");
- return -1;
- }
- }
-
- hc_data_free(connections);
-
- return 0;
-
-
-}
-
-/* FACE LIST */
-
-static int
-_hc_face_list(hc_sock_t * socket, hc_data_t ** pdata)
-{
- hc_data_t * connection_data;
- hc_face_t face;
-
- //DEBUG("[hc_face_list]");
-
- if (_hc_connection_list(socket, &connection_data) < 0) {
- ERROR("[hc_face_list] Could not list connections.");
- return -1;
- }
-
- hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL);
- foreach_connection(c, connection_data) {
- if (hc_connection_to_face(c, &face) < 0) {
- ERROR("[hc_face_list] Could not convert connection to face.");
- goto ERR;
- }
- hc_data_push(face_data, &face);
- }
-
- *pdata = face_data;
- hc_data_free(connection_data);
- return 0;
-
-ERR:
- hc_data_free(connection_data);
- return -1;
-}
-
-static int
-_hc_face_list_async(hc_sock_t * socket)
-{
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_CONNECTIONS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_CONNECTIONS,
- .size_in = sizeof(list_connections_command),
- .size_out = sizeof(hc_face_t),
- .parse = (HC_PARSE)hc_connection_parse_to_face,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, true);
-}
-
-static int
-_hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t admin_state)
-{
- return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
-}
-
-#ifdef WITH_POLICY
-static int
-_hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return hc_connection_set_priority(s, conn_id_or_name, priority);
-}
-
-static int
-_hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return hc_connection_set_tags(s, conn_id_or_name, tags);
-}
-#endif // WITH_POLICY
-
-/*----------------------------------------------------------------------------*
- * Punting
- *----------------------------------------------------------------------------*/
-
-static int
-_hc_punting_create_internal(hc_sock_t * socket, hc_punting_t * punting, bool async)
-{
- int rc;
-
- if (hc_punting_validate(punting) < 0)
- return -1;
-
- struct {
- header_control_message hdr;
- add_punting_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_PUNTING,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = punting->prefix,
- .addressType = (u8)map_to_addr_type[punting->family],
- .len = punting->prefix_len,
- }
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", punting->face_id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_punting_create] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_PUNTING,
- .size_in = sizeof(add_punting_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
-{
- return _hc_punting_create_internal(s, punting, false);
-}
-
-static int
-_hc_punting_create_async(hc_sock_t * s, hc_punting_t * punting)
-{
- return _hc_punting_create_internal(s, punting, true);
-}
-
-static int
-_hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found)
-{
- ERROR("hc_punting_get not (yet) implemented.");
- return -1;
-}
-
-static int
-_hc_punting_delete(hc_sock_t * s, hc_punting_t * punting)
-{
- ERROR("hc_punting_delete not (yet) implemented.");
- return -1;
-}
-
-static int
-_hc_punting_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- ERROR("hc_punting_list not (yet) implemented.");
- return -1;
-}
-
-
-/*----------------------------------------------------------------------------*
- * Cache
- *----------------------------------------------------------------------------*/
-
-static int
-_hc_cache_set_store_internal(hc_sock_t * socket, int enabled, bool async)
-{
- struct {
- header_control_message hdr;
- cache_store_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CACHE_STORE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .activate = enabled,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CACHE_STORE,
- .size_in = sizeof(cache_store_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_cache_set_store(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_store_internal(s, enabled, false);
-}
-
-static int
-_hc_cache_set_store_async(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_store_internal(s, enabled, true);
-}
-
-static int
-_hc_cache_set_serve_internal(hc_sock_t * socket, int enabled, bool async)
-{
- struct {
- header_control_message hdr;
- cache_serve_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CACHE_SERVE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .activate = enabled,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CACHE_SERVE,
- .size_in = sizeof(cache_serve_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_cache_set_serve(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_serve_internal(s, enabled, false);
-}
-
-static int
-_hc_cache_set_serve_async(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_serve_internal(s, enabled, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Strategy
- *----------------------------------------------------------------------------*/
-
-// per prefix
-static int
-_hc_strategy_set(hc_sock_t * s /* XXX */)
-{
- return 0;
-}
-
-/* How to retrieve that from the forwarder ? */
-static const char * strategies[] = {
- "random",
- "load_balancer",
-};
-
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
-
-static int
-_hc_strategy_list(hc_sock_t * s, hc_data_t ** data)
-{
- int rc;
-
- *data = hc_data_create(0, sizeof(hc_strategy_t), NULL);
-
- for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
- hc_strategy_t * strategy = (hc_strategy_t*)hc_data_get_next(*data);
- if (!strategy)
- return -1;
- rc = snprintf(strategy->name, MAXSZ_HC_STRATEGY, "%s", strategies[i]);
- if (rc >= MAXSZ_HC_STRATEGY)
- WARN("[hc_strategy_list] Unexpected truncation of strategy name string");
- (*data)->size++;
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*
- * WLDR
- *----------------------------------------------------------------------------*/
-
-// per connection
-static int
-_hc_wldr_set(hc_sock_t * s /* XXX */)
-{
- return 0;
-}
-
-/*----------------------------------------------------------------------------*
- * MAP-Me
- *----------------------------------------------------------------------------*/
-
-static int
-_hc_mapme_set(hc_sock_t * s, int enabled)
-{
- return 0;
-}
-
-static int
-_hc_mapme_set_discovery(hc_sock_t * s, int enabled)
-{
- return 0;
-}
-
-static int
-_hc_mapme_set_timescale(hc_sock_t * s, double timescale)
-{
- return 0;
-}
-
-static int
-_hc_mapme_set_retx(hc_sock_t * s, double timescale)
-{
- return 0;
-}
-
-/*----------------------------------------------------------------------------*
- * Policy
- *----------------------------------------------------------------------------*/
-
-#ifdef WITH_POLICY
-
-/* POLICY CREATE */
-
-static int
-_hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async)
-{
- if (!IS_VALID_FAMILY(policy->family))
- return -1;
-
- struct {
- header_control_message hdr;
- add_policy_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_POLICY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
- .len = policy->len,
- .policy = policy->policy,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_POLICY,
- .size_in = sizeof(add_policy_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_create_internal(s, policy, false);
-}
-
-static int
-_hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_create_internal(s, policy, true);
-}
-
-/* POLICY DELETE */
-
-static int
-_hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async)
-{
- if (!IS_VALID_FAMILY(policy->family))
- return -1;
-
- struct {
- header_control_message hdr;
- remove_policy_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_POLICY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
- .len = policy->len,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_POLICY,
- .size_in = sizeof(remove_policy_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-static int
-_hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_delete_internal(s, policy, false);
-}
-
-static int
-_hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_delete_internal(s, policy, true);
-}
-
-/* POLICY LIST */
-
-static int
-_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
-{
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_POLICIES,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_POLICIES,
- .size_in = sizeof(list_policies_command),
- .size_out = sizeof(hc_policy_t),
- .parse = (HC_PARSE)hc_policy_parse,
- };
-
- return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-static int
-_hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_policy_list_internal(s, pdata, false);
-}
-
-static int
-_hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_policy_list_internal(s, pdata, true);
-}
-
-#endif /* WITH_POLICY */
-
-static hc_sock_t hc_sock_light_interface = (hc_sock_t) {
- .hc_sock_get_next_seq = _hc_sock_light_get_next_seq,
- .hc_sock_set_nonblocking = _hc_sock_light_set_nonblocking,
- .hc_sock_get_fd = _hc_sock_light_get_fd,
- .hc_sock_connect = _hc_sock_light_connect,
- .hc_sock_get_available = _hc_sock_light_get_available,
- .hc_sock_send = _hc_sock_light_send,
- .hc_sock_recv = _hc_sock_light_recv,
- .hc_sock_process = _hc_sock_light_process,
- .hc_sock_callback = _hc_sock_light_callback,
- .hc_sock_reset = _hc_sock_light_reset,
- .hc_sock_free = _hc_sock_light_free,
- .hc_listener_create = _hc_listener_create,
- .hc_listener_create_async = _hc_listener_create_async,
- .hc_listener_get = _hc_listener_get,
- .hc_listener_delete = _hc_listener_delete,
- .hc_listener_delete_async = _hc_listener_delete_async,
- .hc_listener_list = _hc_listener_list,
- .hc_listener_list_async = _hc_listener_list_async,
- .hc_connection_create = _hc_connection_create,
- .hc_connection_create_async = _hc_connection_create_async,
- .hc_connection_get = _hc_connection_get,
- .hc_connection_update_by_id = _hc_connection_update_by_id,
- .hc_connection_update = _hc_connection_update,
- .hc_connection_delete = _hc_connection_delete,
- .hc_connection_delete_async = _hc_connection_delete_async,
- .hc_connection_list = _hc_connection_list,
- .hc_connection_list_async = _hc_connection_list_async,
- .hc_connection_set_admin_state = _hc_connection_set_admin_state,
- .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async,
-
-#ifdef WITH_POLICY
- .hc_connection_set_priority = _hc_connection_set_priority,
- .hc_connection_set_priority_async = _hc_connection_set_priority_async,
- .hc_connection_set_tags = _hc_connection_set_tags,
- .hc_connection_set_tags_async = _hc_connection_set_tags_async,
-#endif // WITH_POLICY
-
- .hc_face_create = _hc_face_create,
- .hc_face_get = _hc_face_get,
- .hc_face_delete = _hc_face_delete,
- .hc_face_list = _hc_face_list,
- .hc_face_list_async = _hc_face_list_async,
- .hc_face_set_admin_state = _hc_face_set_admin_state,
-
-#ifdef WITH_POLICY
- .hc_face_set_priority = _hc_face_set_priority,
- .hc_face_set_tags = _hc_face_set_tags,
-#endif // WITH_POLICY
-
- .hc_route_create = _hc_route_create,
- .hc_route_create_async = _hc_route_create_async,
- .hc_route_delete = _hc_route_delete,
- .hc_route_delete_async = _hc_route_delete_async,
- .hc_route_list = _hc_route_list,
- .hc_route_list_async = _hc_route_list_async,
-
- .hc_punting_create = _hc_punting_create,
- .hc_punting_create_async = _hc_punting_create_async,
- .hc_punting_get = _hc_punting_get,
- .hc_punting_delete = _hc_punting_delete,
- .hc_punting_list = _hc_punting_list,
-
- .hc_cache_set_store = _hc_cache_set_store,
- .hc_cache_set_store_async = _hc_cache_set_store_async,
- .hc_cache_set_serve = _hc_cache_set_serve,
- .hc_cache_set_serve_async = _hc_cache_set_serve_async,
-
- .hc_strategy_list = _hc_strategy_list,
- .hc_strategy_set = _hc_strategy_set,
- .hc_wldr_set = _hc_wldr_set,
-
- .hc_mapme_set = _hc_mapme_set,
- .hc_mapme_set_discovery = _hc_mapme_set_discovery,
- .hc_mapme_set_timescale = _hc_mapme_set_timescale,
- .hc_mapme_set_retx = _hc_mapme_set_retx,
-
-#ifdef WITH_POLICY
- .hc_policy_create = _hc_policy_create,
- .hc_policy_create_async = _hc_policy_create_async,
- .hc_policy_delete = _hc_policy_delete,
- .hc_policy_delete_async = _hc_policy_delete_async,
- .hc_policy_list = _hc_policy_list,
- .hc_policy_list_async = _hc_policy_list_async
-#endif // WITH_POLICY
-};
-
-// Public contructors
-
-hc_sock_t *
-_hc_sock_create_url(const char * url)
-{
- hc_sock_light_t * s = malloc(sizeof(hc_sock_light_t));
- if (!s)
- goto ERR_MALLOC;
-
- s->vft = hc_sock_light_interface;
- s->url = url ? strdup(url) : NULL;
-
- s->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (s->fd < 0)
- goto ERR_SOCKET;
-
- if (_hc_sock_light_reset((hc_sock_t*)s) < 0)
- goto ERR_RESET;
-
- s->seq = 0;
- s->cur_request = NULL;
-
- s->map = hc_sock_map_create();
- if (!s->map)
- goto ERR_MAP;
-
- return (hc_sock_t*)(s);
-
- //hc_sock_light_map_free(s->map);
-ERR_MAP:
-ERR_RESET:
- if (s->url)
- free(s->url);
- close(s->fd);
-ERR_SOCKET:
- free(s);
-ERR_MALLOC:
- return NULL;
-}
-
-hc_sock_t *
-_hc_sock_create(void)
-{
- return _hc_sock_create_url(NULL);
-}
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.c b/ctrl/libhicnctrl/src/modules/hicn_light_common.c
new file mode 100644
index 000000000..bc04404bf
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_common.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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);
+
+ hc_sock_request_t *request = malloc(sizeof(hc_sock_request_t));
+ if (!request) return NULL;
+ request->seq = seq;
+ request->data = data;
+ request->parse = parse;
+ return request;
+}
+
+void hc_sock_light_request_free(hc_sock_request_t *request) { free(request); }
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.h b/ctrl/libhicnctrl/src/modules/hicn_light_common.h
new file mode 100644
index 000000000..4749474c8
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_common.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.
+ */
+#ifndef HICNCTRL_HICN_LIGHT_COMMON
+#define HICNCTRL_HICN_LIGHT_COMMON
+
+#include <assert.h> // assert
+
+#include "api_private.h"
+
+#define PORT 9695
+
+#define BOOLSTR(x) ((x) ? "true" : "false")
+
+/*
+ * Internal state associated to a pending request
+ */
+typedef struct {
+ int seq;
+ hc_data_t *data;
+ int (*parse)(const u8 *src, u8 *dst);
+} hc_sock_request_t;
+
+/**
+ * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
+ * the header_control_message structure. The forwarder simply answers back the
+ * original sequence number. We maintain a map of such sequence number to
+ * outgoing queries so that replied can be demultiplexed and treated
+ * appropriately.
+ */
+TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
+
+struct hc_sock_light_s {
+ /* This must be the first element of the struct */
+ hc_sock_t vft;
+
+ char *url;
+ int fd;
+
+ /* Partial receive buffer */
+ u8 buf[RECV_BUFLEN];
+ size_t roff; /**< Read offset */
+ size_t woff; /**< Write offset */
+
+ /*
+ * Because received messages are potentially unbounded in size, we might not
+ * guarantee that we can store a full packet before processing it. We must
+ * implement a very simple state machine remembering the current parsing
+ * status in order to partially process the packet.
+ */
+ size_t remaining;
+ u32 send_id;
+
+ /* Next sequence number to be used for requests */
+ int seq;
+
+ /* Request being parsed (NULL if none) */
+ hc_sock_request_t *cur_request;
+
+ bool async;
+ hc_sock_map_t *map;
+};
+
+typedef struct hc_sock_light_s hc_sock_light_t;
+
+#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t *)(s)
+
+hc_sock_request_t *hc_sock_request_create(int seq, hc_data_t *data,
+ HC_PARSE parse);
+
+void hc_sock_light_request_free(hc_sock_request_t *request);
+
+/*
+ * list was working with all seq set to 0, but it seems hicnLightControl uses
+ * 1, and replies with the same seqno
+ */
+#define HICN_CTRL_SEND_SEQ_INIT 1
+#define HICN_CTRL_RECV_SEQ_INIT 1
+
+#define MAX(x, y) ((x > y) ? x : y)
+
+static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
+
+#endif /* HICNCTRL_HICN_LIGHT_COMMON */
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
new file mode 100644
index 000000000..a58ee909e
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
@@ -0,0 +1,3111 @@
+/*
+ * 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 api.c
+ * \brief Implementation of hICN control library API
+ */
+
+#include <assert.h> // assert
+#include <fcntl.h> // fcntl
+#include <stdbool.h>
+#include <stdio.h> // snprintf
+#include <string.h> // memmove, strcasecmp
+#include <sys/socket.h> // socket
+#include <sys/types.h> // getpid
+#include <unistd.h> // close, fcntl
+#include <unistd.h> // getpid
+
+#include "api_private.h"
+#ifdef __linux__
+#include <sys/syscall.h>
+#define gettid() syscall(SYS_gettid)
+#endif /* __linux__ */
+#include <hicn/ctrl/hicn-light-ng.h>
+#include <strings.h>
+
+#include "hicn_light_common.h"
+#include <hicn/util/sstrncpy.h>
+
+#pragma GCC diagnostic ignored "-Warray-bounds"
+
+#if 0
+#ifdef __APPLE__
+#define RANDBYTE() (u8)(arc4random() & 0xFF)
+#else
+#define RANDBYTE() (u8)(random() & 0xFF)
+#endif
+#endif
+#define RANDBYTE() (u8)(rand() & 0xFF)
+
+/**
+ * \brief Defines the default size for the allocated data arrays holding the
+ * results of API calls.
+ *
+ * This size should not be too small to avoid wasting memoyy, but also not too
+ * big to avoid unnecessary realloc's. Later on this size is doubled at each
+ * reallocation.
+ */
+#define DEFAULT_SIZE_LOG 3
+
+#define connection_state_to_face_state(x) ((face_state_t)(x))
+#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
+
+/******************************************************************************
+ * Message helper types and aliases
+ ******************************************************************************/
+
+#define foreach_hc_command \
+ _(connection_add) \
+ _(connection_remove) \
+ _(connection_list) \
+ _(listener_add) \
+ _(listener_remove) \
+ _(listener_list) \
+ _(route_add) \
+ _(route_remove) \
+ _(route_list) \
+ _(cache_set_store) \
+ _(cache_set_serve) \
+ _(cache_clear) \
+ _(cache_list) \
+ _(strategy_set) \
+ _(strategy_add_local_prefix) \
+ _(wldr_set) \
+ _(punting_add) \
+ _(mapme_activator) \
+ _(mapme_timing) \
+ _(subscription_add) \
+ _(subscription_remove)
+
+const char *command_type_str[] = {
+#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u),
+ foreach_command_type
+#undef _
+};
+
+typedef cmd_header_t hc_msg_header_t;
+
+typedef union {
+#define _(x) cmd_##x##_t x;
+ foreach_hc_command
+#undef _
+} hc_msg_payload_t;
+
+typedef struct hc_msg_s {
+ hc_msg_header_t hdr;
+ hc_msg_payload_t payload;
+} hc_msg_t;
+
+/******************************************************************************
+ * Control socket
+ ******************************************************************************/
+
+#define AVAILABLE(s) ((s)->woff - (s)->roff)
+#define DEFAULT_SOCK_RECV_TIMEOUT_MS 100
+
+/**
+ * \brief Parse a connection URL into a sockaddr
+ * \param [in] url - URL
+ * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
+ * \return 0 if parsing succeeded, a negative error value otherwise.
+ */
+static int _hcng_sock_light_parse_url(const char *url, struct sockaddr *sa) {
+ /* FIXME URL parsing is currently not implemented */
+ assert(!url);
+
+#ifdef __linux__
+ srand(time(NULL) ^ getpid() ^ gettid());
+#else
+ srand((unsigned int)(time(NULL) ^ getpid()));
+#endif /* __linux__ */
+
+ /*
+ * A temporary solution is to inspect the sa_family fields of the passed in
+ * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
+ * connection to localhost.
+ */
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ case AF_INET: {
+ struct sockaddr_in *sai = (struct sockaddr_in *)sa;
+ sai->sin_family = AF_INET;
+ sai->sin_port = htons(PORT);
+ sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa;
+ sai6->sin6_family = AF_INET6;
+ sai6->sin6_port = htons(PORT);
+ sai6->sin6_addr = loopback_addr;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _hcng_sock_light_reset(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ s->roff = s->woff = 0;
+ s->remaining = 0;
+ return 0;
+}
+
+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);
+ if (s->url) free(s->url);
+ close(s->fd);
+ free(s);
+}
+
+static void _hcng_sock_increment_woff(hc_sock_t *socket, size_t bytes) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ s->woff += bytes;
+}
+
+static int _hcng_sock_light_get_next_seq(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return s->seq++;
+}
+
+static int _hcng_sock_light_set_nonblocking(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
+}
+
+static int _hcng_sock_light_get_fd(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return s->fd;
+}
+
+static int _hcng_sock_light_connect(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ struct sockaddr_storage ss;
+ memset(&ss, 0, sizeof(struct sockaddr_storage));
+
+ if (_hcng_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0)
+ goto ERR_PARSE;
+
+ size_t size = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6);
+ if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) {
+ perror("connect error");
+ goto ERR_CONNECT;
+ }
+ return 0;
+
+ERR_CONNECT:
+ERR_PARSE:
+ return -1;
+}
+
+static int _hcng_sock_light_send(hc_sock_t *socket, hc_msg_t *msg,
+ size_t msglen, uint32_t seq) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc;
+ msg->hdr.seq_num = seq;
+ rc = (int)send(s->fd, msg, msglen, 0);
+ if (rc < 0) {
+ perror("hc_sock_light_send");
+ return -1;
+ }
+ return 0;
+}
+
+static int _hcng_sock_light_get_available(hc_sock_t *socket, u8 **buffer,
+ size_t *size) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ *buffer = s->buf + s->woff;
+ *size = RECV_BUFLEN - s->woff;
+
+ return 0;
+}
+
+static int _hcng_sock_light_recv(hc_sock_t *socket) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc;
+
+ /*
+ * This condition should be ensured to guarantee correct processing of
+ * messages. With TCP, we need at least a header as we will receive part of
+ * the stream. With UDP, we need the be able to receive the full datagram,
+ * otherwise the rest will be lost.
+ *
+ * Let's be sure to always be able to receive at least 1 JUMBO_MTU, which
+ * should be fine for al situations.
+ */
+ assert(RECV_BUFLEN - s->woff > JUMBO_MTU);
+
+ rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
+ if (rc == 0) {
+ /* Connection has been closed */
+ return 0;
+ }
+ if (rc < 0) {
+ /*
+ * Let's not return 0 which currently means the socket has been closed
+ */
+ if (errno == EWOULDBLOCK) return -1;
+ if (errno == EINTR) {
+ WARN("recv has been stopped by signal");
+ return -1;
+ }
+ perror("hc_sock_light_recv");
+ return -1;
+ }
+ s->woff += rc;
+ return rc;
+}
+
+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) {
+ ERROR("[hc_sock_light_mark_complete] Error removing request from map");
+ }
+ hc_data_set_complete(data);
+ if (pdata) *pdata = data;
+
+ /* Free current request */
+ hc_sock_light_request_free(s->cur_request);
+ s->cur_request = NULL;
+}
+
+static int _hcng_sock_light_process_notification(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ /* For now, notifications are not associated to requests */
+ assert(!s->cur_request);
+
+ /*
+ * Assumption: the whole notification data is returned in a single read and we
+ * immediately parse it.
+ *
+ * XXX This is only valid for UDP sockets.
+ */
+ size_t notification_size = AVAILABLE(s);
+
+ *pdata = hc_data_create(0, /* in_element_size, 0 = no parsing */
+ notification_size, /* out_element_size */
+ NULL); /* complete_cb */
+
+ /* 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;
+}
+
+/*
+ * Notifications have no sequence number and are not linked to any request
+ */
+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");
+ return NULL;
+ }
+ if (!request) {
+ ERROR("[hc_sock_light_process] No request matching sequence number");
+ return NULL;
+ }
+ return request;
+}
+
+/*
+ * Return codes:
+ * 0 success, or not enough data yet to do something
+ * > 0 : notification type
+ * -99 invalid buffer data -> flush
+ */
+static int _hcng_sock_light_process_header(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ int rc;
+
+ /* Check we have at least a header's worth of data, and consume it */
+ if (AVAILABLE(s) < sizeof(hc_msg_header_t)) return 0;
+
+ hc_msg_t *msg = (hc_msg_t *)(s->buf + s->roff);
+
+ // INFO("Processing header header %s", command_type_str(msg->hdr.command_id));
+ s->roff += sizeof(hc_msg_header_t);
+
+ if (msg->hdr.message_type != NOTIFICATION_LIGHT) {
+ s->cur_request = _hcng_sock_light_get_request(s, msg->hdr.seq_num);
+ if (!s->cur_request) return -99;
+ }
+
+ /* How many elements are we expecting in the reply ? */
+ s->remaining = msg->hdr.length;
+ hc_data_t *request_data;
+
+ switch (msg->hdr.message_type) {
+ case ACK_LIGHT:
+ assert(s->remaining == 1); // sic
+ assert(!pdata);
+ _hcng_sock_light_mark_complete(s, pdata);
+ break;
+
+ case NACK_LIGHT:
+ assert(!pdata);
+ assert(s->remaining == 1); // sic
+ request_data = s->cur_request->data;
+ _hcng_sock_light_mark_complete(s, pdata);
+ hc_data_set_error(request_data);
+ break;
+
+ case RESPONSE_LIGHT:
+ assert(pdata);
+
+ if (s->remaining == 0) {
+ /* Empty response (i.e. containing 0 elements) */
+ _hcng_sock_light_mark_complete(s, pdata);
+ return 0;
+ }
+
+ /* Make room in hc_data_t... to avoid multiple calls */
+ rc = hc_data_ensure_available(s->cur_request->data, s->remaining);
+ if (rc < 0) {
+ ERROR("[hc_sock_light_process] Error in hc_data_ensure_available");
+ return -99;
+ }
+ break;
+
+ case NOTIFICATION_LIGHT: {
+ assert(pdata);
+ assert(s->remaining == 0);
+
+ /* This returns the notification size */
+ size_t notification_size =
+ _hcng_sock_light_process_notification(s, pdata);
+ s->roff += notification_size;
+ return msg->hdr.command_id;
+ }
+
+ default:
+ ERROR("[hc_sock_light_process] Invalid response received");
+ return -99;
+ }
+
+ return 0;
+}
+
+static int _hcng_sock_light_process_payload(hc_sock_light_t *s,
+ hc_data_t **pdata) {
+ int err = 0;
+ int rc;
+
+ hc_data_t *data = s->cur_request->data;
+
+ /* We only process full elements (size is stored in data) */
+ size_t num_chunks = AVAILABLE(s) / data->in_element_size;
+
+ /* Check whether we have enough data to process */
+ if (num_chunks == 0) return 0;
+
+ /* Safeguard: assert(num_chunks < s->remaining); */
+ if (num_chunks > s->remaining) {
+ WARN(
+ "[_hcng_sock_light_process_payload] Unexpected num_chunks > "
+ "s->remaining");
+ num_chunks = s->remaining;
+ }
+
+ if (!s->cur_request->parse) {
+ /* If we don't need to parse results, then we can directly push
+ * all of them into the result data structure */
+ hc_data_push_many(data, s->buf + s->roff, num_chunks);
+ } else {
+ /* Iterate on chunks of data */
+ for (int i = 0; i < num_chunks; i++) {
+ /* Get storage offset in hc_data_t */
+ u8 *dst = hc_data_get_next(data);
+ if (!dst) {
+ ERROR("[hc_sock_light_process] Error in hc_data_get_next");
+ err = -2;
+ break;
+ }
+
+ /* Parse element #i */
+ rc = s->cur_request->parse(s->buf + s->roff + i * data->in_element_size,
+ dst);
+ if (rc < 0) {
+ ERROR("[hc_sock_light_process] Error in parse");
+ err = -1;
+ /* In this case we let the loop complete to collect other results */
+ }
+ data->size++;
+ }
+ }
+
+ s->roff += num_chunks * data->in_element_size;
+
+ /*
+ * If we are not expecting any more data, mark the reply as complete
+ */
+ s->remaining -= num_chunks;
+ if (s->remaining == 0) _hcng_sock_light_mark_complete(s, pdata);
+
+ return err;
+}
+
+/*
+ * Process messages as they are received in the ring buffer. There can be
+ * interleaved queries and replies (they are identified by sequence number),
+ * and the assumption is that a reply can arrive over mutiple packets (in
+ * other terms, it is possible that not all data from the reply is available
+ * in the buffer at a given time). However, we assume that a full query is
+ * received at once.
+ */
+static int _hcng_sock_light_process(hc_sock_t *socket, hc_data_t **data) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc = 0;
+
+ /*
+ * We loop consuming messages until there is no more data in the buffer,
+ * or that we can find an entire message. Messages are received
+ * sequentially, and we keep track of incomplete requests in s->cur_request.
+ */
+ while (AVAILABLE(s) > 0) {
+ if (!s->cur_request) {
+ rc = _hcng_sock_light_process_header(s, data);
+ } else {
+ rc = _hcng_sock_light_process_payload(s, data);
+ }
+ if (rc < 0) break;
+ }
+
+ if ((rc == -99) || (s->roff == s->woff)) {
+ /* Flush buffer */
+ s->woff = 0;
+ } else {
+ /* Clean up read data from buffer */
+ memmove(s->buf, s->buf + s->roff, AVAILABLE(s));
+ s->woff -= s->roff;
+ }
+ s->roff = 0;
+
+ return rc;
+}
+
+static int _hcng_sock_light_callback(hc_sock_t *socket, hc_data_t **pdata) {
+ hc_data_t *data = NULL;
+ int rc = 0;
+
+ for (;;) {
+ int n = _hcng_sock_light_recv(socket);
+ if (n == 0) goto ERR_EOF;
+ if (n < 0) {
+ switch (errno) {
+ case ECONNRESET:
+ case ENODEV:
+ /* Forwarder restarted */
+ WARN("Forwarder likely restarted: not (yet) implemented");
+ goto ERR;
+ case EWOULDBLOCK:
+ // DEBUG("Would block... stop reading from socket");
+ goto END;
+ case EINTR:
+ WARN("callback has been stopped by signal");
+ goto ERR;
+ default:
+ perror("hc_sock_light_callback");
+ goto ERR;
+ }
+ }
+ rc = _hcng_sock_light_process(socket, &data);
+ if (rc < 0) goto ERR;
+ if (rc > 0) // i.e. rc = notification type
+ goto END;
+ }
+END:
+ if (pdata)
+ *pdata = data;
+ else
+ hc_data_free(data);
+ return rc;
+
+ERR:
+ hc_data_free(data);
+ERR_EOF:
+ return -1;
+}
+
+/******************************************************************************
+ * Command-specific structures and functions
+ ******************************************************************************/
+
+typedef int (*HC_PARSE)(const u8 *, u8 *);
+
+typedef struct {
+ hc_action_t cmd;
+ command_type_t cmd_id;
+ size_t size_in;
+ size_t size_out;
+ HC_PARSE parse;
+} hc_command_params_t;
+
+typedef struct hc_result_s {
+ hc_msg_t msg;
+ hc_command_params_t params;
+ bool async;
+ bool success;
+} hc_result_t;
+
+int _hcng_sock_prepare_send(hc_sock_t *socket, hc_result_t *result,
+ data_callback_t complete_cb,
+ void *complete_cb_data) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+
+ // Prepare data
+ 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");
+ goto ERR_DATA;
+ }
+ hc_data_set_callback(data, complete_cb, complete_cb_data);
+
+ // Update the sequence number
+ int seq = _hcng_sock_light_get_next_seq(socket);
+ result->msg.hdr.seq_num = seq; // Like in _hcng_sock_light_send
+
+ // Create state used to process the request
+ 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");
+ 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");
+ goto ERR_MAP;
+ }
+
+ return sizeof(result->msg);
+
+ERR_MAP:
+ hc_sock_light_request_free(request);
+ERR_REQUEST:
+ hc_data_free(data);
+ERR_DATA:
+ return -99;
+}
+
+int _hcng_sock_set_recv_timeout_ms(hc_sock_t *socket, long timeout_ms) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout_ms * 1000; // Convert ms into us
+ if (setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _hcng_execute_command(hc_sock_t *socket, hc_msg_t *msg,
+ size_t msg_len, hc_command_params_t *params,
+ hc_data_t **pdata, bool async) {
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int ret;
+ if (async) assert(!pdata);
+
+ /* Sanity check */
+ switch (params->cmd) {
+ case ACTION_CREATE:
+ assert(params->size_in != 0); /* payload repeated */
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_DELETE:
+ assert(params->size_in != 0); /* payload repeated */
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_LIST:
+ assert(params->size_in != 0);
+ assert(params->size_out != 0);
+ assert(params->parse != NULL);
+ break;
+ case ACTION_SET:
+ case ACTION_SERVE:
+ case ACTION_STORE:
+ case ACTION_UPDATE:
+ assert(params->size_in != 0);
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_CLEAR:
+ assert(params->size_in == 0);
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ default:
+ return -1;
+ }
+
+ // hc_sock_light_reset(s);
+
+ /* XXX data will at least store the result (complete) */
+ hc_data_t *data = hc_data_create(params->size_in, params->size_out, NULL);
+ if (!data) {
+ ERROR("[_hcng_execute_command] Could not create data storage");
+ goto ERR_DATA;
+ }
+
+ int seq = _hcng_sock_light_get_next_seq(socket);
+
+ /* Create state used to process the request */
+ hc_sock_request_t *request = NULL;
+ request = hc_sock_request_create(seq, data, params->parse);
+ if (!request) {
+ ERROR("[_hcng_execute_command] 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");
+ goto ERR_MAP;
+ }
+
+ if (_hcng_sock_light_send(socket, msg, msg_len, seq) < 0) {
+ ERROR("[_hcng_execute_command] Error sending message");
+ goto ERR_PROCESS;
+ }
+
+ if (async) return 0;
+
+ /*
+ * Dangerous zone, we might be doing blocking operations on a non-blocking
+ * UDP socket
+ */
+ int retries = 0;
+ while (!data->complete) {
+ /*
+ * As the socket is non blocking it might happen that we need to read
+ * several times before success...
+ */
+ int n = _hcng_sock_light_recv(socket);
+ if (n == 0) goto ERR_EOF;
+ if (n < 0) {
+ if ((errno == EWOULDBLOCK) && (retries < 10)) { /* Max 500ms */
+ DEBUG("read = EWOULDBLOCK... sleeping for 50ms (max 500ms)");
+ usleep(50000); /* 50ms */
+ retries++;
+ continue;
+ }
+ break;
+ }
+ int rc = _hcng_sock_light_process(socket, pdata);
+ switch (rc) {
+ case 0:
+ case -1:
+ break;
+ case -99:
+ ERROR("[_hcng_execute_command] Error processing socket results");
+ goto ERR;
+ default:
+ ERROR("[_hcng_execute_command] Unexpected return value");
+ goto ERR;
+ }
+ }
+
+ERR_EOF:
+ ret = data->ret;
+ if (!data->complete) return -1;
+ if (!pdata) hc_data_free(data);
+
+ return ret;
+
+ERR_PROCESS:
+ERR_MAP:
+ hc_sock_light_request_free(request);
+ERR:
+ERR_REQUEST:
+ hc_data_free(data);
+ERR_DATA:
+ return -99;
+}
+
+/*----------------------------------------------------------------------------*
+ * Listeners
+ *----------------------------------------------------------------------------*/
+
+/* LISTENER CREATE */
+
+static hc_result_t *_listener_create_serialize(hc_sock_t *s,
+ hc_listener_t *listener,
+ bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[_hcng_listener_create] Unexpected truncation of listener string");
+ DEBUG("[_hcng_listener_create] listener=%s async=%s", listener_s,
+ BOOLSTR(async));
+
+ if (hc_listener_validate(listener) < 0) {
+ res->success = false;
+ return res;
+ }
+
+ msg_listener_add_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = listener->local_addr,
+ .port = htons(listener->local_port),
+ .family = listener->family,
+ .type = listener->type,
+ }};
+
+ rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_create] Unexpected truncation of symbolic name "
+ "string");
+
+ rc = snprintf(msg.payload.interface_name, INTERFACE_LEN, "%s",
+ listener->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[_hc_listener_create] Unexpected truncation of interface name "
+ "string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_LISTENER_ADD,
+ .size_in = sizeof(cmd_listener_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.listener_add = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_listener_create_conf(hc_sock_t *s,
+ hc_listener_t *listener) {
+ return _listener_create_serialize(s, listener, false);
+}
+
+static int _hcng_listener_create_internal(hc_sock_t *socket,
+ hc_listener_t *listener, bool async) {
+ hc_result_t *result = _listener_create_serialize(socket, listener, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ free(result);
+ DEBUG("[_hcng_listener_create] done or error");
+ return ret;
+}
+
+static int _hcng_listener_create(hc_sock_t *s, hc_listener_t *listener) {
+ DEBUG("[_hcng_listener_create]");
+ return _hcng_listener_create_internal(s, listener, false);
+}
+
+static int _hcng_listener_create_async(hc_sock_t *s, hc_listener_t *listener) {
+ DEBUG("[_hcng_listener_create_async]");
+ return _hcng_listener_create_internal(s, listener, true);
+}
+
+/* LISTENER PARSE */
+
+static int hc_listener_parse(void *in, hc_listener_t *listener) {
+ int rc;
+ cmd_listener_list_item_t *item = (cmd_listener_list_item_t *)in;
+
+ if (!IS_VALID_ID(item->id)) {
+ ERROR("[hc_listener_parse] Invalid id received");
+ return -1;
+ }
+
+ *listener = (hc_listener_t){
+ .id = item->id,
+ .type = item->type,
+ .family = item->family,
+ .local_addr = UNION_CAST(item->address, ip_address_t),
+ .local_port = ntohs(item->port),
+ };
+ rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", item->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[hc_listener_parse] Unexpected truncation of symbolic name string");
+ rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s",
+ item->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN("[hc_listener_parse] Unexpected truncation of interface name string");
+
+ if (hc_listener_validate(listener) < 0) return -1;
+ return 0;
+}
+
+/* LISTENER LIST */
+
+static hc_result_t *_hcng_listener_list_serialize(hc_sock_t *socket,
+ hc_data_t **pdata,
+ bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ DEBUG("[hc_listener_list] async=%s", BOOLSTR(async));
+
+ msg_listener_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_LISTENER_LIST,
+ .size_in = sizeof(cmd_listener_list_item_t),
+ .size_out = sizeof(hc_listener_t),
+ .parse = (HC_PARSE)hc_listener_parse,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.listener_list = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_listener_list_conf(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_listener_list_serialize(s, pdata, false);
+}
+
+static int _hcng_listener_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ hc_result_t *result = _hcng_listener_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_listener_list] done or error");
+ return ret;
+}
+
+static int _hcng_listener_list(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[_hcng_listener_list]");
+ return _hcng_listener_list_internal(s, pdata, false);
+}
+
+static int _hcng_listener_list_async(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[_hcng_listener_list_as-nc]");
+ return _hcng_listener_list_internal(s, pdata, true);
+}
+
+/* LISTENER GET */
+
+static int _hcng_listener_get(hc_sock_t *socket, hc_listener_t *listener,
+ hc_listener_t **listener_found) {
+ hc_data_t *listeners;
+ hc_listener_t *found;
+
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[hc_listener_get] Unexpected truncation of listener string");
+ DEBUG("[hc_listener_get] listener=%s", listener_s);
+
+ if (_hcng_listener_list(socket, &listeners) < 0) return -1;
+
+ /* Test */
+ if (hc_listener_find(listeners, listener, &found) < 0) {
+ hc_data_free(listeners);
+ return -1;
+ }
+
+ if (found) {
+ *listener_found = malloc(sizeof(hc_listener_t));
+ if (!*listener_found) return -1;
+ **listener_found = *found;
+ } else {
+ *listener_found = NULL;
+ }
+
+ hc_data_free(listeners);
+
+ return 0;
+}
+
+/* LISTENER DELETE */
+
+static int _hcng_listener_delete_internal(hc_sock_t *socket,
+ hc_listener_t *listener, bool async) {
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[_hcng_listener_delete] Unexpected truncation of listener string");
+ DEBUG("[_hcng_listener_delete] listener=%s async=%s", listener_s,
+ BOOLSTR(async));
+
+ msg_listener_remove_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ }};
+
+ if (listener->id) {
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d",
+ listener->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else if (*listener->name) {
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s",
+ listener->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else {
+ hc_listener_t *listener_found;
+ if (_hcng_listener_get(socket, listener, &listener_found) < 0) return -1;
+ if (!listener_found) return -1;
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d",
+ listener_found->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_listener_delete] Unexpected truncation of symbolic name "
+ "string");
+ free(listener_found);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_LISTENER_REMOVE,
+ .size_in = sizeof(cmd_listener_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
+ return _hcng_listener_delete_internal(s, listener, false);
+}
+
+static int _hcng_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) {
+ return _hcng_listener_delete_internal(s, listener, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * CONNECTION
+ *----------------------------------------------------------------------------*/
+
+/* CONNECTION CREATE */
+
+static hc_result_t *_connection_create_serialize(hc_sock_t *socket,
+ hc_connection_t *connection,
+ bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc =
+ hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN(
+ "[_hcng_connection_create] Unexpected truncation of connection "
+ "string");
+ DEBUG("[_hcng_connection_create] connection=%s async=%s", connection_s,
+ BOOLSTR(async));
+
+ if (hc_connection_validate(connection) < 0) {
+ res->success = false;
+ return res;
+ }
+
+ msg_connection_add_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .remote_ip = connection->remote_addr,
+ .local_ip = connection->local_addr,
+ .remote_port = htons(connection->remote_port),
+ .local_port = htons(connection->local_port),
+ .family = connection->family,
+ .type = connection->type,
+ .admin_state = connection->admin_state,
+#ifdef WITH_POLICY
+ .priority = connection->priority,
+ .tags = connection->tags,
+#endif /* WITH_POLICY */
+ }};
+ rc =
+ snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_create] Unexpected truncation of symbolic name "
+ "string");
+ // snprintf(msg.payload.interface_name, INTERFACE_NAME_LEN, "%s",
+ // connection->interface_name);
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_CONNECTION_ADD,
+ .size_in = sizeof(cmd_connection_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.connection_add = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return _connection_create_serialize(s, connection, false);
+}
+
+static int _hcng_connection_create_internal(hc_sock_t *socket,
+ hc_connection_t *connection,
+ bool async) {
+ hc_result_t *result = _connection_create_serialize(socket, connection, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ DEBUG("[_hcng_connection_create] done or error");
+ return ret;
+}
+
+static int _hcng_connection_create(hc_sock_t *s, hc_connection_t *connection) {
+ DEBUG("[_hcng_connection_create]");
+ return _hcng_connection_create_internal(s, connection, false);
+}
+
+static int _hcng_connection_create_async(hc_sock_t *s,
+ hc_connection_t *connection) {
+ DEBUG("[_hcng_connection_create_async]");
+ return _hcng_connection_create_internal(s, connection, true);
+}
+
+/* CONNECTION PARSE */
+
+static int hc_connection_parse(void *in, hc_connection_t *connection) {
+ int rc;
+ cmd_connection_list_item_t *item = (cmd_connection_list_item_t *)in;
+
+ if (!IS_VALID_ID(item->id)) {
+ ERROR("[hc_connection_parse] Invalid id received");
+ return -1;
+ }
+
+ *connection = (hc_connection_t){
+ .id = item->id,
+ .type = item->type,
+ .family = item->family,
+ .local_addr = item->local_addr,
+ .local_port = ntohs(item->local_port),
+ .remote_addr = item->remote_addr,
+ .remote_port = ntohs(item->remote_port),
+ .admin_state = item->admin_state,
+#ifdef WITH_POLICY
+ .priority = item->priority,
+ .tags = item->tags,
+#endif /* WITH_POLICY */
+ .state = item->state,
+ };
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", item->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[hc_connection_parse] Unexpected truncation of symbolic name "
+ "string");
+ rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s",
+ item->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN(
+ "[hc_connection_parse] Unexpected truncation of interface name "
+ "string");
+
+ if (hc_connection_validate(connection) < 0) return -1;
+ return 0;
+}
+
+/* CONNECTION LIST */
+
+static int _hcng_connection_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ DEBUG("[hc_connection_list] async=%s", BOOLSTR(async));
+
+ msg_connection_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_CONNECTION_LIST,
+ .size_in = sizeof(cmd_connection_list_item_t),
+ .size_out = sizeof(hc_connection_t),
+ .parse = (HC_PARSE)hc_connection_parse,
+ };
+
+ int ret = _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg),
+ &params, pdata, async);
+
+ DEBUG("[hc_connection_list] done or error");
+ return ret;
+}
+
+static int _hcng_connection_list(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[hc_connection_list]");
+ return _hcng_connection_list_internal(s, pdata, false);
+}
+
+static int _hcng_connection_list_async(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[hc_connection_list_async]");
+ return _hcng_connection_list_internal(s, pdata, true);
+}
+
+/* CONNECTION GET */
+
+static int _hcng_connection_get(hc_sock_t *socket, hc_connection_t *connection,
+ hc_connection_t **connection_found) {
+ hc_data_t *connections;
+ hc_connection_t *found;
+
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc =
+ hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN("[hc_connection_get] Unexpected truncation of connection string");
+ DEBUG("[hc_connection_get] connection=%s", connection_s);
+
+ if (_hcng_connection_list(socket, &connections) < 0) return -1;
+
+ /* Test */
+ if (hc_connection_find(connections, connection, &found) < 0) {
+ hc_data_free(connections);
+ return -1;
+ }
+
+ if (found) {
+ *connection_found = malloc(sizeof(hc_connection_t));
+ if (!*connection_found) return -1;
+ **connection_found = *found;
+ } else {
+ *connection_found = NULL;
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+}
+
+/* CONNECTION DELETE */
+
+static hc_result_t *_hcng_connection_delete_serialize(
+ hc_sock_t *socket, hc_connection_t *connection, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ res->success = false;
+
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc =
+ hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN(
+ "[_hcng_connection_delete] Unexpected truncation of connection "
+ "string");
+ DEBUG("[_hcng_connection_delete] connection=%s async=%s", connection_s,
+ BOOLSTR(async));
+
+ msg_connection_remove_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ };
+
+ if (connection->id) {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ connection->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else if (*connection->name) {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_delete] Unexpected truncation of symbolic name "
+ "string");
+ } else {
+ hc_connection_t *connection_found;
+ if (hc_connection_get(socket, connection, &connection_found) < 0)
+ return res;
+ if (!connection_found) return res;
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ connection_found->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_delete] Unexpected truncation of symbolic name "
+ "string");
+ free(connection_found);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_CONNECTION_REMOVE,
+ .size_in = sizeof(cmd_connection_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.connection_remove = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_connection_delete_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return _hcng_connection_delete_serialize(s, connection, false);
+}
+
+static int _hcng_connection_delete_internal(hc_sock_t *socket,
+ hc_connection_t *connection,
+ bool async) {
+ hc_result_t *result =
+ _hcng_connection_delete_serialize(socket, connection, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static int _hcng_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
+ return _hcng_connection_delete_internal(s, connection, false);
+}
+
+static int _hcng_connection_delete_async(hc_sock_t *s,
+ hc_connection_t *connection) {
+ return _hcng_connection_delete_internal(s, connection, true);
+}
+
+/* CONNECTION UPDATE */
+
+static int _hcng_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection) {
+ // Not implemented
+ return -1;
+}
+
+static int _hcng_connection_update(hc_sock_t *s,
+ hc_connection_t *connection_current,
+ hc_connection_t *connection_updated) {
+ // Not implemented
+ return -1;
+}
+
+/* CONNECTION SET ADMIN STATE */
+
+static int _hcng_connection_set_admin_state_internal(
+ hc_sock_t *socket, const char *conn_id_or_name, face_state_t state,
+ bool async) {
+ int rc;
+ DEBUG(
+ "[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s "
+ "async=%s",
+ conn_id_or_name, face_state_str(state), BOOLSTR(async));
+
+ struct {
+ cmd_header_t hdr;
+ cmd_connection_set_admin_state_t payload;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .admin_state = state,
+ },
+ };
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_set_admin_state] Unexpected truncation of symbolic "
+ "name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE,
+ .size_in = sizeof(cmd_connection_set_admin_state_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_connection_set_admin_state(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
+ return _hcng_connection_set_admin_state_internal(s, conn_id_or_name, state,
+ false);
+}
+
+static int _hcng_connection_set_admin_state_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
+ return _hcng_connection_set_admin_state_internal(s, conn_id_or_name, state,
+ true);
+}
+
+#ifdef WITH_POLICY
+
+static int _hcng_connection_set_priority_internal(hc_sock_t *socket,
+ const char *conn_id_or_name,
+ uint32_t priority,
+ bool async) {
+ int rc;
+ DEBUG(
+ "[hc_connection_set_priority] connection_id/name=%s priority=%d "
+ "async=%s",
+ conn_id_or_name, priority, BOOLSTR(async));
+ struct {
+ cmd_header_t hdr;
+ cmd_connection_set_priority_t payload;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .priority = priority,
+ },
+ };
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_set_priority] Unexpected truncation of symbolic "
+ "name "
+ "string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY,
+ .size_in = sizeof(cmd_connection_set_priority_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_connection_set_priority(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
+ return _hcng_connection_set_priority_internal(s, conn_id_or_name, priority,
+ false);
+}
+
+static int _hcng_connection_set_priority_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
+ return _hcng_connection_set_priority_internal(s, conn_id_or_name, priority,
+ true);
+}
+
+#endif // WITH_POLICY
+
+static int _hcng_connection_set_tags_internal(hc_sock_t *s,
+ const char *conn_id_or_name,
+ policy_tags_t tags, bool async) {
+ int rc;
+ DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s",
+ conn_id_or_name, tags, BOOLSTR(async));
+ struct {
+ cmd_header_t hdr;
+ cmd_connection_set_tags_t payload;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_TAGS,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .tags = tags,
+ },
+ };
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN(
+ "[_hc_connection_set_tags] Unexpected truncation of symbolic name "
+ "string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_CONNECTION_SET_TAGS,
+ .size_in = sizeof(cmd_connection_set_tags_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), &params, NULL,
+ async);
+}
+
+static int _hcng_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return _hcng_connection_set_tags_internal(s, conn_id_or_name, tags, false);
+}
+
+static int _hcng_connection_set_tags_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return _hcng_connection_set_tags_internal(s, conn_id_or_name, tags, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Routes
+ *----------------------------------------------------------------------------*/
+
+/* ROUTE CREATE */
+
+static hc_result_t *_route_create_serialize(hc_sock_t *socket,
+ hc_route_t *route, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ char route_s[MAXSZ_HC_ROUTE];
+ int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
+ if (rc >= MAXSZ_HC_ROUTE)
+ WARN("[_hc_route_create] Unexpected truncation of route string");
+ if (rc < 0)
+ WARN("[_hc_route_create] Error building route string");
+ else
+ DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async));
+
+ if (hc_route_validate(route) < 0) {
+ res->success = false;
+ return res;
+ }
+
+ msg_route_add_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = route->remote_addr,
+ .cost = route->cost,
+ .family = route->family,
+ .len = route->len,
+ }};
+
+ /*
+ * The route commands expects the ID or name as part of the
+ * symbolic_or_connid attribute.
+ */
+ if (route->name[0] != '\0') {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ route->name);
+ } else {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ route->face_id);
+ }
+
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_route_create] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_ROUTE_ADD,
+ .size_in = sizeof(cmd_route_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.route_add = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_route_create_conf(hc_sock_t *s, hc_route_t *route) {
+ return _route_create_serialize(s, route, false);
+}
+
+static int _hcng_route_create_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
+ hc_result_t *result = _route_create_serialize(socket, route, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static int _hcng_route_create(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_create_internal(s, route, false);
+}
+
+static int _hcng_route_create_async(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_create_internal(s, route, true);
+}
+
+/* ROUTE DELETE */
+
+static int _hcng_route_delete_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
+ char route_s[MAXSZ_HC_ROUTE];
+ int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
+ if (rc >= MAXSZ_HC_ROUTE)
+ WARN("[_hc_route_delete] Unexpected truncation of route string");
+ DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async));
+
+ if (!IS_VALID_FAMILY(route->family)) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_route_remove_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = route->remote_addr,
+ .family = route->family,
+ .len = route->len,
+ }};
+
+ /*
+ * The route commands expects the ID or name as part of the
+ * symbolic_or_connid attribute.
+ */
+ if (route->name[0] != '\0') {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ route->name);
+ } else {
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ route->face_id);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_ROUTE_REMOVE,
+ .size_in = sizeof(cmd_route_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_route_delete(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_delete_internal(s, route, false);
+}
+
+static int _hcng_route_delete_async(hc_sock_t *s, hc_route_t *route) {
+ return _hcng_route_delete_internal(s, route, true);
+}
+
+/* ROUTE PARSE */
+
+static int hc_route_parse(void *in, hc_route_t *route) {
+ cmd_route_list_item_t *item = (cmd_route_list_item_t *)in;
+
+ *route = (hc_route_t){
+ .name = "", /* This is not reported back */
+ .face_id = item->connection_id,
+ .family = item->family,
+ .remote_addr = item->address,
+ .len = item->len,
+ .cost = item->cost,
+ };
+
+ if (hc_route_validate(route) < 0) return -1;
+ return 0;
+}
+
+/* ROUTE LIST */
+
+static int _hcng_route_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ // DEBUG("[hc_route_list] async=%s", BOOLSTR(async));
+ msg_route_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_ROUTE_LIST,
+ .size_in = sizeof(cmd_route_list_item_t),
+ .size_out = sizeof(hc_route_t),
+ .parse = (HC_PARSE)hc_route_parse,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ pdata, async);
+}
+
+static int _hcng_route_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_route_list_internal(s, pdata, false);
+}
+
+static int _hcng_route_list_async(hc_sock_t *s) {
+ return _hcng_route_list_internal(s, NULL, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Face
+ *
+ * Face support is not directly available in hicn-light, but we can offer such
+ * an interface through a combination of listeners and connections. The code
+ * starts with some conversion functions between faces/listeners/connections.
+ *
+ * We also need to make sure that there always exist a (single) listener when
+ *a connection is created, and in the hICN face case, that there is a single
+ * connection attached to this listener.
+ *
+ *----------------------------------------------------------------------------*/
+
+/* FACE CREATE */
+
+static int _hcng_face_create(hc_sock_t *socket, hc_face_t *face) {
+ hc_listener_t listener;
+ hc_listener_t *listener_found;
+
+ hc_connection_t connection;
+ hc_connection_t *connection_found;
+
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_create] Unexpected truncation of face string");
+ DEBUG("[hc_face_create] face=%s", face_s);
+
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ if (hc_face_to_connection(face, &connection, true) < 0) {
+ ERROR("[hc_face_create] Could not convert face to connection.");
+ return -1;
+ }
+
+ /* Ensure we have a corresponding local listener */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+
+ if (_hcng_listener_get(socket, &listener, &listener_found) < 0) {
+ ERROR("[hc_face_create] Could not retrieve listener");
+ return -1;
+ }
+
+ if (!listener_found) {
+ /* We need to create the listener if it does not exist */
+ if (hc_listener_create(socket, &listener) < 0) {
+ ERROR("[hc_face_create] Could not create listener.");
+ free(listener_found);
+ return -1;
+ }
+ } else {
+ free(listener_found);
+ }
+
+ /* Create corresponding connection */
+ if (_hcng_connection_create(socket, &connection) < 0) {
+ ERROR("[hc_face_create] Could not create connection.");
+ return -1;
+ }
+
+ /*
+ * Once the connection is created, we need to list all connections
+ * and compare with the current one to find the created face ID.
+ */
+ if (_hcng_connection_get(socket, &connection, &connection_found) < 0) {
+ ERROR("[hc_face_create] Could not retrieve connection");
+ return -1;
+ }
+
+ if (!connection_found) {
+ ERROR("[hc_face_create] Could not find newly created connection.");
+ return -1;
+ }
+
+ face->id = connection_found->id;
+ free(connection_found);
+
+ break;
+
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ if (hc_face_to_listener(face, &listener) < 0) {
+ ERROR("Could not convert face to listener.");
+ return -1;
+ }
+ if (hc_listener_create(socket, &listener) < 0) {
+ ERROR("[hc_face_create] Could not create listener.");
+ return -1;
+ }
+ break;
+ default:
+ ERROR("[hc_face_create] Unknwon face type.");
+
+ return -1;
+ };
+
+ return 0;
+}
+
+static int _hcng_face_get(hc_sock_t *socket, hc_face_t *face,
+ hc_face_t **face_found) {
+ hc_listener_t listener;
+ hc_listener_t *listener_found;
+
+ hc_connection_t connection;
+ hc_connection_t *connection_found;
+
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_get] Unexpected truncation of face string");
+ DEBUG("[hc_face_get] face=%s", face_s);
+
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ if (hc_face_to_connection(face, &connection, false) < 0) return -1;
+ if (_hcng_connection_get(socket, &connection, &connection_found) < 0)
+ return -1;
+ if (!connection_found) {
+ *face_found = NULL;
+ return 0;
+ }
+ *face_found = malloc(sizeof(hc_face_t));
+ hc_connection_to_face(connection_found, *face_found);
+ free(connection_found);
+ break;
+
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ if (hc_face_to_listener(face, &listener) < 0) return -1;
+ if (_hcng_listener_get(socket, &listener, &listener_found) < 0) return -1;
+ if (!listener_found) {
+ *face_found = NULL;
+ return 0;
+ }
+ *face_found = malloc(sizeof(hc_face_t));
+ hc_listener_to_face(listener_found, *face_found);
+ free(listener_found);
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* FACE DELETE */
+
+static int _hcng_face_delete(hc_sock_t *socket, hc_face_t *face,
+ uint8_t delete_listener) {
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_delete] Unexpected truncation of face string");
+ DEBUG("[hc_face_delete] face=%s", face_s);
+
+ hc_connection_t connection;
+ if (hc_face_to_connection(face, &connection, false) < 0) {
+ ERROR("[hc_face_delete] Could not convert face to connection.");
+ return -1;
+ }
+
+ if (_hcng_connection_delete(socket, &connection) < 0) {
+ ERROR("[hc_face_delete] Error removing connection");
+ return -1;
+ }
+
+ if (!delete_listener) {
+ return 0;
+ }
+
+ /* If this is the last connection attached to the listener, remove it */
+
+ hc_data_t *connections;
+ hc_listener_t listener = {{0}};
+
+ /*
+ * Ensure we have a corresponding local listener
+ * NOTE: hc_face_to_listener is not appropriate
+ */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+#if 1
+ /*
+ * The name is generated to prepare listener creation, we need it to be
+ * empty for deletion. The id should not need to be reset though.
+ */
+ listener.id = 0;
+ memset(listener.name, 0, sizeof(listener.name));
+#endif
+ if (_hcng_connection_list(socket, &connections) < 0) {
+ ERROR("[hc_face_delete] Error getting the list of listeners");
+ return -1;
+ }
+
+ bool delete = true;
+ foreach_connection(c, connections) {
+ if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) ==
+ 0) &&
+ (c->local_port == listener.local_port) &&
+ (strcmp(c->interface_name, listener.interface_name) == 0)) {
+ delete = false;
+ }
+ }
+
+ if (delete) {
+ if (_hcng_listener_delete(socket, &listener) < 0) {
+ ERROR("[hc_face_delete] Error removing listener");
+ return -1;
+ }
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+}
+
+/* FACE LIST */
+
+static int _hcng_face_list(hc_sock_t *socket, hc_data_t **pdata) {
+ hc_data_t *connection_data;
+ hc_face_t face;
+
+ DEBUG("[hc_face_list]");
+
+ if (_hcng_connection_list(socket, &connection_data) < 0) {
+ ERROR("[hc_face_list] Could not list connections.");
+ return -1;
+ }
+
+ hc_data_t *face_data =
+ hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL);
+ foreach_connection(c, connection_data) {
+ if (hc_connection_to_face(c, &face) < 0) {
+ ERROR("[hc_face_list] Could not convert connection to face.");
+ goto ERR;
+ }
+ hc_data_push(face_data, &face);
+ }
+
+ *pdata = face_data;
+ hc_data_free(connection_data);
+ DEBUG("[hc_face_list] done");
+ return 0;
+
+ERR:
+ hc_data_free(connection_data);
+ DEBUG("[hc_face_list] error");
+ return -1;
+}
+
+static int hc_connection_parse_to_face(void *in, hc_face_t *face) {
+ hc_connection_t connection;
+
+ if (hc_connection_parse(in, &connection) < 0) {
+ ERROR("[hc_connection_parse_to_face] Could not parse connection");
+ return -1;
+ }
+
+ if (hc_connection_to_face(&connection, face) < 0) {
+ ERROR(
+ "[hc_connection_parse_to_face] Could not convert connection to "
+ "face.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _hcng_face_list_async(hc_sock_t *socket) {
+ struct {
+ cmd_header_t hdr;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_LIST,
+ .length = 0,
+ .seq_num = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_CONNECTION_LIST,
+ .size_in = sizeof(cmd_connection_list_item_t),
+ .size_out = sizeof(hc_face_t),
+ .parse = (HC_PARSE)hc_connection_parse_to_face,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, true);
+}
+
+static int _hcng_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t admin_state) {
+ return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
+}
+
+#ifdef WITH_POLICY
+static int _hcng_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
+ return hc_connection_set_priority(s, conn_id_or_name, priority);
+}
+
+static int _hcng_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
+ return hc_connection_set_tags(s, conn_id_or_name, tags);
+}
+#endif // WITH_POLICY
+
+/*----------------------------------------------------------------------------*
+ * Punting
+ *----------------------------------------------------------------------------*/
+
+static int _hcng_punting_create_internal(hc_sock_t *socket,
+ hc_punting_t *punting, bool async) {
+ int rc;
+
+ if (hc_punting_validate(punting) < 0) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_punting_add_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_PUNTING_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = punting->prefix,
+ .family = punting->family,
+ .len = punting->prefix_len,
+ }};
+ rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d",
+ punting->face_id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_punting_create] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_PUNTING_ADD,
+ .size_in = sizeof(cmd_punting_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_punting_create(hc_sock_t *s, hc_punting_t *punting) {
+ return _hcng_punting_create_internal(s, punting, false);
+}
+
+static int _hcng_punting_create_async(hc_sock_t *s, hc_punting_t *punting) {
+ return _hcng_punting_create_internal(s, punting, true);
+}
+
+static int _hcng_punting_get(hc_sock_t *s, hc_punting_t *punting,
+ hc_punting_t **punting_found) {
+ ERROR("hc_punting_get not (yet) implemented.");
+ return -1;
+}
+
+static int _hcng_punting_delete(hc_sock_t *s, hc_punting_t *punting) {
+ ERROR("hc_punting_delete not (yet) implemented.");
+ return -1;
+}
+
+#if 0
+static int hc_punting_parse(void * in, hc_punting_t * punting)
+{
+ ERROR("hc_punting_parse not (yet) implemented.");
+ return -1;
+}
+#endif
+
+static int _hcng_punting_list(hc_sock_t *s, hc_data_t **pdata) {
+ ERROR("hc_punting_list not (yet) implemented.");
+ return -1;
+}
+
+/*----------------------------------------------------------------------------*
+ * Cache
+ *----------------------------------------------------------------------------*/
+
+/* CACHE SET STORE */
+
+static int _hcng_cache_set_store_internal(hc_sock_t *socket, hc_cache_t *cache,
+ bool async) {
+ msg_cache_set_store_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_SET_STORE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = cache->store,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_STORE,
+ .cmd_id = COMMAND_TYPE_CACHE_SET_STORE,
+ .size_in = sizeof(cmd_cache_set_store_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_cache_set_store(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_store_internal(s, cache, false);
+}
+
+static int _hcng_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_store_internal(s, cache, true);
+}
+
+/* CACHE SET SERVE */
+
+static int _hcng_cache_set_serve_internal(hc_sock_t *socket, hc_cache_t *cache,
+ bool async) {
+ msg_cache_set_serve_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_SET_SERVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = cache->serve,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SERVE,
+ .cmd_id = COMMAND_TYPE_CACHE_SET_SERVE,
+ .size_in = sizeof(cmd_cache_set_serve_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_serve_internal(s, cache, false);
+}
+
+static int _hcng_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_set_serve_internal(s, cache, true);
+}
+
+/* CACHE CLEAR */
+
+static int _hcng_cache_clear_internal(hc_sock_t *socket, hc_cache_t *cache,
+ bool async) {
+ msg_cache_clear_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_CLEAR,
+ .length = 1,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CLEAR,
+ .cmd_id = COMMAND_TYPE_CACHE_CLEAR,
+ .size_in = sizeof(cmd_cache_clear_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_cache_clear(hc_sock_t *s, hc_cache_t *cache) {
+ return _hcng_cache_clear_internal(s, cache, false);
+}
+
+/* CACHE PARSE */
+
+static int hc_cache_parse(void *in, hc_cache_info_t *cache_info) {
+ cmd_cache_list_reply_t *item = (cmd_cache_list_reply_t *)in;
+ *cache_info = (hc_cache_info_t){.store = item->store_in_cs,
+ .serve = item->serve_from_cs,
+ .cs_size = item->cs_size,
+ .num_stale_entries = item->num_stale_entries};
+
+ return 0;
+}
+
+/* CACHE LIST */
+
+static hc_result_t *_hcng_cache_list_serialize(hc_sock_t *socket,
+ hc_data_t **pdata, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ DEBUG("[hc_cache_list] async=%s", BOOLSTR(async));
+
+ msg_cache_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_CACHE_LIST,
+ .size_in = sizeof(cmd_cache_list_reply_t),
+ .size_out = sizeof(hc_cache_info_t),
+ .parse = (HC_PARSE)hc_cache_parse,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.cache_list = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static int _hcng_cache_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ hc_result_t *result = _hcng_cache_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);
+ return ret;
+}
+
+static int _hcng_cache_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_cache_list_internal(s, pdata, false);
+}
+
+/*----------------------------------------------------------------------------*
+ * Strategy
+ *----------------------------------------------------------------------------*/
+
+// per prefix
+static hc_result_t *_strategy_set_serialize(hc_sock_t *socket,
+ hc_strategy_t *strategy) {
+ hc_result_t *res = malloc(sizeof(*res));
+
+ char strategy_s[MAXSZ_HC_STRATEGY];
+ int rc = strcpy_s(strategy->name, MAXSZ_STRATEGY_NAME,
+ strategy_str(strategy->type));
+ if (rc != EOK) goto ERR;
+ rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy);
+ if (rc >= MAXSZ_HC_STRATEGY)
+ WARN("[_hcng_strategy_create] Unexpected truncation of strategy string");
+ DEBUG("[_hcng_strategy_create] strategy=%s", strategy_s);
+
+ if (!IS_VALID_FAMILY(strategy->family) ||
+ !IS_VALID_STRATEGY_TYPE(strategy->type)) {
+ goto ERR;
+ }
+
+ msg_strategy_set_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STRATEGY_SET,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = strategy->address,
+ .family = strategy->family,
+ .len = strategy->len,
+ .type = strategy->type,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_STRATEGY_SET,
+ .size_in = sizeof(cmd_strategy_set_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.strategy_set = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+
+ERR:
+ res->success = false;
+ return res;
+}
+
+static hc_result_t *_strategy_add_local_prefix_serialize(
+ hc_sock_t *socket, hc_strategy_t *strategy) {
+ hc_result_t *res = malloc(sizeof(*res));
+
+ char strategy_s[MAXSZ_HC_STRATEGY];
+ int rc = strcpy_s(strategy->name, MAXSZ_STRATEGY_NAME,
+ strategy_str(strategy->type));
+ if (rc != EOK) goto ERR;
+ rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy);
+ if (rc >= MAXSZ_HC_STRATEGY)
+ WARN("[_hcng_strategy_create] Unexpected truncation of strategy string");
+ DEBUG("[_hcng_strategy_create] strategy=%s", strategy_s);
+
+ if (!IS_VALID_FAMILY(strategy->family) ||
+ !IS_VALID_STRATEGY_TYPE(strategy->type) ||
+ !IS_VALID_FAMILY(strategy->local_family)) {
+ goto ERR;
+ }
+
+ msg_strategy_add_local_prefix_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .type = strategy->type,
+ .address = strategy->address,
+ .family = strategy->family,
+ .len = strategy->len,
+ .local_address = strategy->local_address,
+ .local_family = strategy->local_family,
+ .local_len = strategy->local_len,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX,
+ .size_in = sizeof(cmd_strategy_add_local_prefix_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.strategy_add_local_prefix = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+
+ERR:
+ res->success = false;
+ return res;
+}
+
+static hc_result_t *_hcng_strategy_set_conf(hc_sock_t *s,
+ hc_strategy_t *strategy) {
+ return _strategy_set_serialize(s, strategy);
+}
+
+static int _hcng_strategy_set(hc_sock_t *socket, hc_strategy_t *strategy) {
+ hc_result_t *result = _strategy_set_serialize(socket, strategy);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+static hc_result_t *_hcng_strategy_add_local_prefix_conf(
+ hc_sock_t *s, hc_strategy_t *strategy) {
+ return _strategy_add_local_prefix_serialize(s, strategy);
+}
+
+static int _hcng_strategy_add_local_prefix(hc_sock_t *socket,
+ hc_strategy_t *strategy) {
+ hc_result_t *result = _strategy_add_local_prefix_serialize(socket, strategy);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+/* How to retrieve that from the forwarder ? */
+static const char *strategies[] = {
+ "random",
+ "load_balancer",
+};
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
+
+static int _hcng_strategy_list(hc_sock_t *s, hc_data_t **data) {
+ int rc;
+
+ *data = hc_data_create(0, sizeof(hc_strategy_t), NULL);
+
+ for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
+ hc_strategy_t *strategy = (hc_strategy_t *)hc_data_get_next(*data);
+ if (!strategy) return -1;
+ rc = snprintf(strategy->name, MAXSZ_STRATEGY_NAME, "%s", strategies[i]);
+ if (rc >= MAXSZ_STRATEGY_NAME)
+ WARN("[hc_strategy_list] Unexpected truncation of strategy name string");
+ (*data)->size++;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * WLDR
+ *----------------------------------------------------------------------------*/
+
+// per connection
+static int _hcng_wldr_set(hc_sock_t *s /* XXX */) { return 0; }
+
+/*----------------------------------------------------------------------------*
+ * MAP-Me
+ *----------------------------------------------------------------------------*/
+
+static int _hcng_mapme_set(hc_sock_t *socket, int enabled) {
+ msg_mapme_enable_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_ENABLE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = enabled,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_ENABLE,
+ .size_in = sizeof(cmd_mapme_enable_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_set_discovery(hc_sock_t *socket, int enabled) {
+ msg_mapme_enable_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SET_DISCOVERY,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .activate = enabled,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_SET_DISCOVERY,
+ .size_in = sizeof(cmd_mapme_set_discovery_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_set_timescale(hc_sock_t *socket, uint32_t timescale) {
+ msg_mapme_set_timescale_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SET_TIMESCALE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .timePeriod = timescale,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_SET_TIMESCALE,
+ .size_in = sizeof(cmd_mapme_set_timescale_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_set_retx(hc_sock_t *socket, uint32_t timescale) {
+ msg_mapme_set_retx_t msg = {.header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SET_RETX,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .timePeriod = timescale,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = COMMAND_TYPE_MAPME_SET_RETX,
+ .size_in = sizeof(msg_mapme_set_retx_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+static int _hcng_mapme_send_update(hc_sock_t *socket, hc_mapme_t *mapme) {
+ if (!IS_VALID_FAMILY(mapme->family)) return -1;
+
+ msg_mapme_send_update_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SEND_UPDATE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_UPDATE,
+ .cmd_id = COMMAND_TYPE_MAPME_SEND_UPDATE,
+ .size_in = sizeof(msg_mapme_send_update_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, false);
+}
+
+/*----------------------------------------------------------------------------*
+ * Policy
+ *----------------------------------------------------------------------------*/
+
+#ifdef WITH_POLICY
+
+/* POLICY CREATE */
+
+static int _hcng_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
+ if (!IS_VALID_FAMILY(policy->family)) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_policy_add_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ COMMAND_TYPE_POLICY_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = policy->remote_addr,
+ .family = policy->family,
+ .len = policy->len,
+ .policy = policy->policy,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_POLICY_ADD,
+ .size_in = sizeof(cmd_policy_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_policy_create(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_create_internal(s, policy, false);
+}
+
+static int _hcng_policy_create_async(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_create_internal(s, policy, true);
+}
+
+/* POLICY DELETE */
+
+static int _hcng_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
+ if (!IS_VALID_FAMILY(policy->family)) return -1;
+
+ struct {
+ cmd_header_t hdr;
+ cmd_policy_remove_t payload;
+ } msg = {.hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_POLICY_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {
+ .address = policy->remote_addr,
+ .family = policy->family,
+ .len = policy->len,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_POLICY_REMOVE,
+ .size_in = sizeof(cmd_policy_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ NULL, async);
+}
+
+static int _hcng_policy_delete(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_delete_internal(s, policy, false);
+}
+
+static int _hcng_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) {
+ return _hcng_policy_delete_internal(s, policy, true);
+}
+
+/* POLICY PARSE */
+
+static int hc_policy_parse(void *in, hc_policy_t *policy) {
+ cmd_policy_list_item_t *item = (cmd_policy_list_item_t *)in;
+
+ if (!IS_VALID_ADDRESS(&item->address, item->family)) {
+ ERROR("[hc_policy_parse] Invalid address");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(item->family)) {
+ ERROR("[hc_policy_parse] Invalid family");
+ return -1;
+ }
+ if (!IS_VALID_PREFIX_LEN(item->len)) {
+ ERROR("[hc_policy_parse] Invalid len");
+ return -1;
+ }
+ if (!IS_VALID_POLICY(item->policy)) {
+ ERROR("[hc_policy_parse] Invalid policy");
+ return -1;
+ }
+
+ *policy = (hc_policy_t){
+ .family = item->family,
+ .remote_addr = item->address,
+ .len = item->len,
+ .policy = item->policy,
+ };
+ return 0;
+}
+
+/* POLICY LIST */
+
+static int _hcng_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ struct {
+ cmd_header_t hdr;
+ } msg = {
+ .hdr =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_POLICY_LIST,
+ .length = 0,
+ .seq_num = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_POLICY_LIST,
+ .size_in = sizeof(cmd_policy_list_item_t),
+ .size_out = sizeof(hc_policy_t),
+ .parse = (HC_PARSE)hc_policy_parse,
+ };
+
+ return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), &params,
+ pdata, async);
+}
+
+static int _hcng_policy_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_policy_list_internal(s, pdata, false);
+}
+
+static int _hcng_policy_list_async(hc_sock_t *s, hc_data_t **pdata) {
+ return _hcng_policy_list_internal(s, pdata, true);
+}
+
+#endif /* WITH_POLICY */
+
+/*----------------------------------------------------------------------------*
+ * Subscriptioins
+ *----------------------------------------------------------------------------*/
+
+/* SUBSCRIPTION CREATE */
+
+static hc_result_t *_subscription_create_serialize(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ msg_subscription_add_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_SUBSCRIPTION_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {.topics = subscription->topics}};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = COMMAND_TYPE_SUBSCRIPTION_ADD,
+ .size_in = sizeof(cmd_subscription_add_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ hc_result_t *res = malloc(sizeof(*res));
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.subscription_add = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_subscription_create_conf(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ return _subscription_create_serialize(s, subscription);
+}
+
+static int _hcng_subscription_create(hc_sock_t *socket,
+ hc_subscription_t *subscriiption) {
+ hc_result_t *result = _subscription_create_serialize(socket, subscriiption);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+/* SUBSCRIPTION DELETE */
+
+static hc_result_t *_subscription_delete_serialize(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ msg_subscription_remove_t msg = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {.topics = subscription->topics}};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE,
+ .size_in = sizeof(cmd_subscription_remove_t),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ hc_result_t *res = malloc(sizeof(*res));
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.subscription_remove = msg.payload,
+ },
+ .params = params,
+ .async = false,
+ .success = true,
+ };
+ return res;
+}
+
+static hc_result_t *_hcng_subscription_delete_conf(
+ hc_sock_t *s, hc_subscription_t *subscription) {
+ return _subscription_delete_serialize(s, subscription);
+}
+
+static int _hcng_subscription_delete(hc_sock_t *socket,
+ hc_subscription_t *subscriiption) {
+ hc_result_t *result = _subscription_delete_serialize(socket, subscriiption);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, NULL,
+ result->async);
+ }
+
+ hc_result_free(result);
+ return ret;
+}
+
+/* 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) {
+ return result->params.cmd_id;
+}
+bool _hcng_result_get_success(hc_result_t *result) { return result->success; }
+
+static hc_sock_t hc_sock_light_ng_interface = (hc_sock_t){
+ .hc_sock_get_next_seq = _hcng_sock_light_get_next_seq,
+ .hc_sock_set_nonblocking = _hcng_sock_light_set_nonblocking,
+ .hc_sock_get_fd = _hcng_sock_light_get_fd,
+ .hc_sock_connect = _hcng_sock_light_connect,
+ .hc_sock_get_available = _hcng_sock_light_get_available,
+ .hc_sock_send = _hcng_sock_light_send,
+ .hc_sock_recv = _hcng_sock_light_recv,
+ .hc_sock_process = _hcng_sock_light_process,
+ .hc_sock_callback = _hcng_sock_light_callback,
+ .hc_sock_reset = _hcng_sock_light_reset,
+ .hc_sock_free = _hcng_sock_light_free,
+ .hc_sock_increment_woff = _hcng_sock_increment_woff,
+ .hc_sock_prepare_send = _hcng_sock_prepare_send,
+ .hc_sock_set_recv_timeout_ms = _hcng_sock_set_recv_timeout_ms,
+ .hc_listener_create = _hcng_listener_create,
+ .hc_listener_create_async = _hcng_listener_create_async,
+ .hc_listener_get = _hcng_listener_get,
+ .hc_listener_delete = _hcng_listener_delete,
+ .hc_listener_delete_async = _hcng_listener_delete_async,
+ .hc_listener_list = _hcng_listener_list,
+ .hc_listener_list_async = _hcng_listener_list_async,
+ .hc_connection_create = _hcng_connection_create,
+ .hc_connection_create_async = _hcng_connection_create_async,
+ .hc_connection_get = _hcng_connection_get,
+ .hc_connection_update_by_id = _hcng_connection_update_by_id,
+ .hc_connection_update = _hcng_connection_update,
+ .hc_connection_delete = _hcng_connection_delete,
+ .hc_connection_delete_async = _hcng_connection_delete_async,
+ .hc_connection_list = _hcng_connection_list,
+ .hc_connection_list_async = _hcng_connection_list_async,
+ .hc_connection_set_admin_state = _hcng_connection_set_admin_state,
+ .hc_connection_set_admin_state_async =
+ _hcng_connection_set_admin_state_async,
+
+#ifdef WITH_POLICY
+ .hc_connection_set_priority = _hcng_connection_set_priority,
+ .hc_connection_set_priority_async = _hcng_connection_set_priority_async,
+ .hc_connection_set_tags = _hcng_connection_set_tags,
+ .hc_connection_set_tags_async = _hcng_connection_set_tags_async,
+#endif // WITH_POLICY
+
+ .hc_face_create = _hcng_face_create,
+ .hc_face_get = _hcng_face_get,
+ .hc_face_delete = _hcng_face_delete,
+ .hc_face_list = _hcng_face_list,
+ .hc_face_list_async = _hcng_face_list_async,
+ .hc_face_set_admin_state = _hcng_face_set_admin_state,
+
+#ifdef WITH_POLICY
+ .hc_face_set_priority = _hcng_face_set_priority,
+ .hc_face_set_tags = _hcng_face_set_tags,
+#endif // WITH_POLICY
+ .hc_subscription_create = _hcng_subscription_create,
+ .hc_subscription_delete = _hcng_subscription_delete,
+
+ .hc_route_create = _hcng_route_create,
+ .hc_route_create_async = _hcng_route_create_async,
+ .hc_route_delete = _hcng_route_delete,
+ .hc_route_delete_async = _hcng_route_delete_async,
+ .hc_route_list = _hcng_route_list,
+ .hc_route_list_async = _hcng_route_list_async,
+
+ .hc_punting_create = _hcng_punting_create,
+ .hc_punting_create_async = _hcng_punting_create_async,
+ .hc_punting_get = _hcng_punting_get,
+ .hc_punting_delete = _hcng_punting_delete,
+ .hc_punting_list = _hcng_punting_list,
+
+ .hc_cache_set_store = _hcng_cache_set_store,
+ .hc_cache_set_store_async = _hcng_cache_set_store_async,
+ .hc_cache_set_serve = _hcng_cache_set_serve,
+ .hc_cache_set_serve_async = _hcng_cache_set_serve_async,
+ .hc_cache_clear = _hcng_cache_clear,
+ .hc_cache_list = _hcng_cache_list,
+
+ .hc_strategy_list = _hcng_strategy_list,
+ .hc_strategy_set = _hcng_strategy_set,
+ .hc_strategy_add_local_prefix = _hcng_strategy_add_local_prefix,
+ .hc_wldr_set = _hcng_wldr_set,
+
+ .hc_mapme_set = _hcng_mapme_set,
+ .hc_mapme_set_discovery = _hcng_mapme_set_discovery,
+ .hc_mapme_set_timescale = _hcng_mapme_set_timescale,
+ .hc_mapme_set_retx = _hcng_mapme_set_retx,
+ .hc_mapme_send_update = _hcng_mapme_send_update,
+
+#ifdef WITH_POLICY
+ .hc_policy_create = _hcng_policy_create,
+ .hc_policy_create_async = _hcng_policy_create_async,
+ .hc_policy_delete = _hcng_policy_delete,
+ .hc_policy_delete_async = _hcng_policy_delete_async,
+ .hc_policy_list = _hcng_policy_list,
+ .hc_policy_list_async = _hcng_policy_list_async,
+#endif // WITH_POLICY
+
+ .hc_listener_create_conf = _hcng_listener_create_conf,
+ .hc_listener_list_conf = _hcng_listener_list_conf,
+ .hc_connection_create_conf = _hcng_connection_create_conf,
+ .hc_connection_delete_conf = _hcng_connection_delete_conf,
+ .hc_route_create_conf = _hcng_route_create_conf,
+ .hc_strategy_set_conf = _hcng_strategy_set_conf,
+ .hc_strategy_add_local_prefix_conf = _hcng_strategy_add_local_prefix_conf,
+ .hc_subscription_create_conf = _hcng_subscription_create_conf,
+ .hc_subscription_delete_conf = _hcng_subscription_delete_conf,
+
+ .hc_result_get_msg = _hcng_result_get_msg,
+ .hc_result_get_cmd_id = _hcng_result_get_cmd_id,
+ .hc_result_get_success = _hcng_result_get_success,
+};
+
+// Public contructors
+
+hc_sock_t *_hc_sock_create_url(const char *url) {
+ hc_sock_light_t *s = malloc(sizeof(hc_sock_light_t));
+ if (!s) goto ERR_MALLOC;
+
+ s->vft = hc_sock_light_ng_interface;
+ s->url = url ? strdup(url) : NULL;
+
+ s->fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s->fd < 0) goto ERR_SOCKET;
+
+ if (_hcng_sock_set_recv_timeout_ms((hc_sock_t *)s,
+ DEFAULT_SOCK_RECV_TIMEOUT_MS) < 0)
+ goto ERR_SOCKET;
+
+ if (_hcng_sock_light_reset((hc_sock_t *)s) < 0) goto ERR_RESET;
+
+ s->seq = 0;
+ s->cur_request = NULL;
+
+ s->map = hc_sock_map_create();
+ if (!s->map) goto ERR_MAP;
+
+ return (hc_sock_t *)(s);
+
+ // hc_sock_light_map_free(s->map);
+ERR_MAP:
+ERR_RESET:
+ if (s->url) free(s->url);
+ close(s->fd);
+ERR_SOCKET:
+ free(s);
+ERR_MALLOC:
+ return NULL;
+}
diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
index e59a2e41e..6d1baa786 100644
--- a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
+++ b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -18,8 +18,6 @@
* \brief Implementation of hICN control library API
*/
-#include "api_private.h"
-
#include <assert.h> // assert
#include <fcntl.h> // fcntl
#include <math.h> // log2
@@ -29,40 +27,10 @@
#include <sys/socket.h> // socket
#include <unistd.h> // close, fcntl
#include <vapi/vapi_safe.h>
-#include <vapi/hicn.api.vapi.h>
-#include <vapi/ip.api.vapi.h>
-#include <vapi/udp.api.vapi.h>
-#include <vapi/interface.api.vapi.h>
-
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
-#endif
-
-#include <vnet/ip/ip46_address.h>
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic pop
-#endif
-
-#define APP_NAME "hicn_plugin"
-#define MAX_OUTSTANDING_REQUESTS 4
-#define RESPONSE_QUEUE_SIZE 2
-
-DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
-DEFINE_VAPI_MSG_IDS_IP_API_JSON
-DEFINE_VAPI_MSG_IDS_UDP_API_JSON
+#include <vppinfra/clib.h>
+#include <vpp_plugins/hicn/error.h>
-typedef struct {
- vapi_ctx_t g_vapi_ctx_instance;
- bool async;
-} vapi_skc_ctx_t;
-
-vapi_skc_ctx_t vapi_skc = {
- .g_vapi_ctx_instance = NULL,
- .async = false,
-};
+#include "api_private.h"
/**
* Messages to the forwarder might be multiplexed thanks to the seqNum fields in
@@ -81,7 +49,6 @@ struct hc_sock_vpp_s {
vapi_ctx_t g_vapi_ctx_instance;
char *url;
- int fd;
size_t roff; /**< Read offset */
size_t woff; /**< Write offset */
@@ -94,43 +61,42 @@ struct hc_sock_vpp_s {
typedef struct hc_sock_vpp_s hc_sock_vpp_t;
-#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t*)(s)
+#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t *)(s)
/******************************************************************************
* Message helper types and aliases
******************************************************************************/
-#define foreach_hc_command \
- _(hicn_api_node_params_set) \
- _(hicn_api_node_params_set_reply) \
- _(hicn_api_node_params_get_reply) \
- _(hicn_api_node_stats_get_reply) \
- _(hicn_api_face_get) \
- _(hicn_api_faces_details) \
- _(hicn_api_face_stats_details) \
- _(hicn_api_face_get_reply) \
- _(hicn_api_route_get) \
- _(hicn_api_route_get_reply) \
- _(hicn_api_routes_details) \
- _(hicn_api_strategies_get_reply) \
- _(hicn_api_strategy_get) \
+#define foreach_hc_command \
+ _(hicn_api_node_params_set) \
+ _(hicn_api_node_params_set_reply) \
+ _(hicn_api_node_params_get_reply) \
+ _(hicn_api_node_stats_get_reply) \
+ _(hicn_api_face_get) \
+ _(hicn_api_faces_details) \
+ _(hicn_api_face_stats_details) \
+ _(hicn_api_face_get_reply) \
+ _(hicn_api_route_get) \
+ _(hicn_api_route_get_reply) \
+ _(hicn_api_routes_details) \
+ _(hicn_api_strategies_get_reply) \
+ _(hicn_api_strategy_get) \
_(hicn_api_strategy_get_reply)
-
typedef vapi_type_msg_header2_t hc_msg_header_t;
typedef union {
-#define _(a) vapi_payload_ ## a a;
+#define _(a) vapi_payload_##a a;
foreach_hc_command
#undef _
} hc_msg_payload_t;
-typedef struct __attribute__ ((__packed__)) {
+typedef struct __attribute__((__packed__)) {
hc_msg_header_t hdr;
hc_msg_payload_t payload;
} hc_hicnp_t;
-typedef void (* NTOH)(void *msg);
+typedef void (*NTOH)(void *msg);
typedef struct __attribute__((__packed__)) {
hc_data_t *data;
@@ -138,7 +104,7 @@ typedef struct __attribute__((__packed__)) {
} callback_ctx_t;
typedef struct __attribute__((__packed__)) {
- hc_hicnp_t * hicnp_msg;
+ hc_hicnp_t *hicnp_msg;
vapi_cb_t callback;
callback_ctx_t *callback_ctx;
NTOH ntoh;
@@ -151,11 +117,9 @@ typedef struct __attribute__((__packed__)) {
static void _hc_sock_vpp_free(hc_sock_t *socket) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
if (s->url) free(s->url);
- close(s->fd);
free(s);
vapi_disconnect_safe();
- vapi_skc.g_vapi_ctx_instance = NULL;
}
static int _hc_sock_vpp_get_next_seq(hc_sock_t *socket) {
@@ -174,8 +138,7 @@ static int _hc_sock_vpp_get_fd(hc_sock_t *s) { return 1; }
static int _hc_sock_vpp_connect(hc_sock_t *socket) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_error_e rv = vapi_connect_safe(&s->g_vapi_ctx_instance, s->async);
- if (rv != VAPI_OK)
- goto ERR_CONNECT;
+ if (rv != VAPI_OK) goto ERR_CONNECT;
return 0;
@@ -184,7 +147,8 @@ ERR_CONNECT:
return -1;
}
-static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) {
+static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen,
+ uint32_t seq) {
return -1;
}
@@ -199,16 +163,16 @@ static int _hc_sock_vpp_recv(hc_sock_t *s) {
}
static int _hc_sock_vpp_process(hc_sock_t *s, hc_data_t **pdata) {
- //NOT IMPLEMENTED
+ // NOT IMPLEMENTED
return -1;
}
-static int _hc_sock_vpp_callback(hc_sock_t * socket, hc_data_t ** pdata) {
+static int _hc_sock_vpp_callback(hc_sock_t *socket, hc_data_t **pdata) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_sock_vpp_reset(hc_sock_t * socket) {
+static int _hc_sock_vpp_reset(hc_sock_t *socket) {
// NOT IMPLEMENTED
return -1;
}
@@ -217,7 +181,6 @@ static int _hc_sock_vpp_reset(hc_sock_t * socket) {
* Command-specific structures and functions
******************************************************************************/
-
/*----------------------------------------------------------------------------*
* Listeners
*----------------------------------------------------------------------------*/
@@ -236,7 +199,7 @@ static int _hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) {
/* LISTENER GET */
static int _hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
- hc_listener_t **listener_found) {
+ hc_listener_t **listener_found) {
// NOT IMPLEMENTED
return -1;
}
@@ -253,33 +216,32 @@ static int _hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) {
return -1;
}
-static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
+static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
vapi_payload_ip_address_details *reply) {
-
- if (is_last)
- return 0;
+ if (is_last) return 0;
hc_data_t *data = (hc_data_t *)callback_ctx;
if (data->size == data->current) {
- data->buffer = realloc(data->buffer, sizeof(hc_listener_t) * data->size * 2);
+ data->buffer =
+ realloc(data->buffer, sizeof(hc_listener_t) * data->size * 2);
- if (!data->buffer)
- return VAPI_ENOMEM;
+ if (!data->buffer) return VAPI_ENOMEM;
- data->size *=2;
+ data->size *= 2;
}
- hc_listener_t * listener = (hc_listener_t *)(data->buffer + data->current * sizeof(hc_listener_t));
+ hc_listener_t *listener =
+ (hc_listener_t *)(data->buffer + data->current * sizeof(hc_listener_t));
+ memset(listener, 0, sizeof(hc_listener_t));
- if(reply->prefix.address.af == ADDRESS_IP4) {
- memcpy(listener->local_addr.v4.as_u8, reply->prefix.address.un.ip4, IPV4_ADDR_LEN);
+ if (reply->prefix.address.af == ADDRESS_IP4) {
+ memcpy(listener->local_addr.v4.as_u8, reply->prefix.address.un.ip4,
+ IPV4_ADDR_LEN);
listener->family = AF_INET;
- }
- else {
- memcpy(listener->local_addr.v6.as_u8, reply->prefix.address.un.ip6, IPV6_ADDR_LEN);
+ } else {
+ memcpy(listener->local_addr.v6.as_u8, reply->prefix.address.un.ip6,
+ IPV6_ADDR_LEN);
listener->family = AF_INET6;
}
@@ -293,31 +255,26 @@ typedef struct {
char interface_name[INTERFACE_LEN];
} hc_vapi_interface_t;
-static vapi_error_e listener_list_complete_cb (
- struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_sw_interface_details *reply) {
+static vapi_error_e listener_list_complete_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_sw_interface_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply == NULL || rv != VAPI_OK)
- return rv;
-
- if (is_last)
- return 0;
+ if (is_last) return 0;
hc_data_t *data = (hc_data_t *)callback_ctx;
if (data->size == data->current) {
- data->buffer = realloc(data->buffer, sizeof(hc_vapi_interface_t) * data->size * 2);
+ data->buffer =
+ realloc(data->buffer, sizeof(hc_vapi_interface_t) * data->size * 2);
- if (!data->buffer)
- return VAPI_ENOMEM;
+ if (!data->buffer) return VAPI_ENOMEM;
- data->size *=2;
+ data->size *= 2;
}
- hc_vapi_interface_t *swif = &((hc_vapi_interface_t*)data->buffer)[data->current];
+ hc_vapi_interface_t *swif =
+ &((hc_vapi_interface_t *)data->buffer)[data->current];
swif[0].swif = reply->sw_if_index;
memcpy(swif[0].interface_name, reply->interface_name, INTERFACE_LEN);
@@ -327,7 +284,6 @@ static vapi_error_e listener_list_complete_cb (
return rv;
}
-
/* LISTENER LIST */
static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
@@ -344,14 +300,14 @@ static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
hicnp_msg->payload.sw_if_index = ~0;
hicnp_msg->payload.name_filter_valid = 0;
- hc_data_t *data = hc_data_create(0, sizeof(hc_vapi_interface_t),NULL);
+ hc_data_t *data = hc_data_create(0, sizeof(hc_vapi_interface_t), NULL);
if (!data) {
retval = -1;
goto END;
}
- hc_data_t *data2 = hc_data_create(0, 1,NULL);
+ hc_data_t *data2 = hc_data_create(0, 1, NULL);
if (!data2) {
retval = -1;
@@ -362,12 +318,13 @@ static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
data->size = 1;
if (!data->buffer) {
- free (data);
+ free(data);
retval = -1;
goto FREE_DATA;
}
- int ret = vapi_sw_interface_dump(s->g_vapi_ctx_instance, hicnp_msg, listener_list_complete_cb, data);
+ int ret = vapi_sw_interface_dump(s->g_vapi_ctx_instance, hicnp_msg,
+ listener_list_complete_cb, data);
if (ret != VAPI_OK) {
free(data->buffer);
@@ -381,28 +338,34 @@ static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
data2->out_element_size = 1;
if (!data2->buffer) {
- free (data2->buffer);
- retval =1 -1;
+ free(data2->buffer);
+ retval = -1;
goto CLEAN;
}
/* Query the forwarder for each interface */
- for(int i = 0; i < data->current; i++) {
+ for (int i = 0; i < data->current; i++) {
int index = data2->current;
- vapi_msg_ip_address_dump* msg = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
+ vapi_msg_ip_address_dump *msg =
+ vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
msg->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif;
msg->payload.is_ipv6 = 0;
- retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info, data2);
- vapi_msg_ip_address_dump* msg2 = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
+ retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info,
+ data2);
+ vapi_msg_ip_address_dump *msg2 =
+ vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance);
if (retval) goto CLEAN;
msg2->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif;
msg2->payload.is_ipv6 = 1;
- retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info, data2);
+ retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info,
+ data2);
for (size_t j = index; j < data2->current; j++) {
- memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name, ((hc_vapi_interface_t*)(data->buffer))[i].interface_name, INTERFACE_LEN);
- ((hc_listener_t *)(data2->buffer))[j].type = CONNECTION_TYPE_HICN;
+ memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name,
+ ((hc_vapi_interface_t *)(data->buffer))[i].interface_name,
+ INTERFACE_LEN);
+ ((hc_listener_t *)(data2->buffer))[j].type = FACE_TYPE_HICN;
}
if (retval) goto CLEAN;
@@ -417,7 +380,7 @@ FREE_DATA:
data2->size = data2->current;
data2->out_element_size = sizeof(hc_listener_t);
*pdata = data2;
- END:
+END:
vapi_unlock();
return retval;
}
@@ -438,7 +401,8 @@ static int _hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
return -1;
}
-static int _hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_create_async(hc_sock_t *s,
+ hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
@@ -446,17 +410,20 @@ static int _hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection
/* CONNECTION GET */
static int _hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
- hc_connection_t **connection_found) {
+ hc_connection_t **connection_found) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, hc_connection_t *connection) {
+static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection) {
// Not implemented
return -1;
}
-static int _hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, hc_connection_t *connection_updated) {
+static int _hc_connection_update(hc_sock_t *s,
+ hc_connection_t *connection_current,
+ hc_connection_t *connection_updated) {
// Not implemented
return -1;
}
@@ -468,7 +435,8 @@ static int _hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
return -1;
}
-static int _hc_connection_delete_async(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_delete_async(hc_sock_t *s,
+ hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
@@ -487,39 +455,47 @@ static int _hc_connection_list_async(hc_sock_t *s, hc_data_t **pdata) {
/* CONNECTION SET ADMIN STATE */
-static int _hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
- face_state_t state) {
+static int _hc_connection_set_admin_state(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
// NOT IMPLEMENTED
return -1;
}
static int _hc_connection_set_admin_state_async(hc_sock_t *s,
- const char *conn_id_or_name,
- face_state_t state) {
+ const char *conn_id_or_name,
+ face_state_t state) {
// NOT IMPLEMENTED
return -1;
}
#ifdef WITH_POLICY
-static int _hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+static int _hc_connection_set_priority(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+static int _hc_connection_set_priority_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ uint32_t priority) {
// NOT IMPLEMENTED
return -1;
}
-#endif // WITH_POLICY
+#endif // WITH_POLICY
-static int _hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+static int _hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
// NOT IMPLEMENTED
return -1;
}
-static int _hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+static int _hc_connection_set_tags_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ policy_tags_t tags) {
// NOT IMPLEMENTED
return -1;
}
@@ -528,66 +504,65 @@ static int _hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_
* Routes
*----------------------------------------------------------------------------*/
-static vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e create_udp_tunnel_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ if (reply->retval != VAPI_OK) return reply->retval;
- u32 * uei = (u32*) callback_ctx;
+ u32 *uei = (u32 *)callback_ctx;
*uei = reply->uei;
return reply->retval;
}
/* ROUTE CREATE */
-static vapi_error_e parse_route_create( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_route_add_del_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_route_create(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ if (reply->retval != VAPI_OK) return reply->retval;
return reply->retval;
}
-static vapi_error_e hicn_enable_cb( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_enable_disable_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e hicn_enable_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_enable_disable_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
+ face_id_t *faceid = (face_id_t *)callback_ctx;
+
+ if (reply->nfaces) {
+ *faceid = reply->faceids[0];
+ }
return reply->retval;
}
-static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool async) {
+static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
- int ret;
+ int ret = -1;
vapi_lock();
- vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
+ vapi_msg_ip_route_add_del *hicnp_msg =
+ vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
hicnp_msg->payload.is_add = 1;
if (route->family == AF_INET) {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0],
+ &route->remote_addr.v4, 4);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4;
- }
- else {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0],
+ &route->remote_addr.v6, 16);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6;
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
}
hicnp_msg->payload.route.prefix.len = route->len;
@@ -596,87 +571,101 @@ static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool
hicnp_msg->payload.route.paths[0].table_id = 0;
hc_face_t *face = &(route->face);
- switch (face->face.type) {
- case FACE_TYPE_HICN:
- {
- if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) {
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
- }
- else{
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
- }
-
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
-
- break;
- }
- case FACE_TYPE_UDP:
- {
- vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL;
- u32 uei = ~0;
-
- if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr))) &&
- ip46_address_is_ip4((ip46_address_t *)(&(face->face.local_addr)))) {
- msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
- memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4, sizeof(ip4_address_t));
- msg->payload.src_addr.af = ADDRESS_IP4;
+ face->face.netdevice.index = ~0;
+ face->id = INVALID_FACE_ID;
- memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4, sizeof(ip4_address_t));
- msg->payload.dst_addr.af = ADDRESS_IP4;
+ switch (face->face.type) {
+ case FACE_TYPE_HICN: {
+ if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr)))) {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4),
+ &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6),
+ &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
+ }
- } else if (!ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.remote_addr))) &&
- !ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.local_addr)))) {
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
- memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6, sizeof(ip6_address_t));
- msg->payload.src_addr.af = ADDRESS_IP4;
+ break;
+ }
+ case FACE_TYPE_UDP: {
+ vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL;
+ u32 uei = ~0;
+
+ if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr))) &&
+ ip_address_is_v4((ip_address_t *)(&(face->face.local_addr)))) {
+ msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
+ memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4,
+ sizeof(ip4_address_t));
+ msg->payload.src_addr.af = ADDRESS_IP4;
+
+ memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4,
+ sizeof(ip4_address_t));
+ msg->payload.dst_addr.af = ADDRESS_IP4;
+
+ } else if (!ip_address_is_v4(
+ (ip_address_t *)(&(route->face.face.remote_addr))) &&
+ !ip_address_is_v4(
+ (ip_address_t *)(&(route->face.face.local_addr)))) {
+ msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
+ memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6,
+ sizeof(ip6_address_t));
+ msg->payload.src_addr.af = ADDRESS_IP6;
+
+ memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6,
+ sizeof(ip6_address_t));
+ msg->payload.dst_addr.af = ADDRESS_IP6;
+ } else {
+ // NOT IMPLEMENTED
+ ret = -1;
+ goto done;
+ }
- memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6, sizeof(ip6_address_t));
- msg->payload.dst_addr.af = ADDRESS_IP6;
+ msg->payload.src_port = face->face.local_port;
+ msg->payload.dst_port = face->face.remote_port;
+ msg->payload.is_add = 1;
- } else {
- //NOT IMPLEMENTED
- ret = -1;
- goto done;
- }
+ int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg,
+ create_udp_tunnel_cb, &uei);
- msg->payload.src_port = face->face.local_port;
- msg->payload.dst_port = face->face.remote_port;
- msg->payload.is_add = 1;
+ if (ret) {
+ ERROR("Error in vapi_hicn_api_udp_tunnel_add_del");
+ vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg);
+ goto done;
+ }
- int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg, create_udp_tunnel_cb, &uei);
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].nh.obj_id = uei;
- if(ret) {
- vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg);
- goto done;
- }
+ face->face.netdevice.index = uei;
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].nh.obj_id = uei;
- break;
- }
+ break;
+ }
default:
ret = -1;
goto done;
}
- ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_create, NULL);
+ ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg,
+ parse_route_create, NULL);
- if (ret)
+ if (ret) {
+ ERROR("Error in vapi_ip_route_add_del");
goto done;
+ }
- vapi_msg_hicn_api_enable_disable *msg = vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
+ vapi_msg_hicn_api_enable_disable *msg =
+ vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
if (route->family == AF_INET) {
memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
msg->payload.prefix.address.af = ADDRESS_IP4;
- }
- else {
+ } else {
memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
msg->payload.prefix.address.af = ADDRESS_IP6;
}
@@ -684,7 +673,13 @@ static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool
msg->payload.prefix.len = route->len;
msg->payload.enable_disable = 1;
- ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, hicn_enable_cb, NULL);
+ ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg,
+ hicn_enable_cb, &face->id);
+
+ if (ret) {
+ ERROR("Error in vapi_hicn_api_enable_disable");
+ }
+
done:
vapi_unlock();
return ret;
@@ -699,32 +694,63 @@ static int _hc_route_create_async(hc_sock_t *s, hc_route_t *route) {
}
/* ROUTE DELETE */
-static vapi_error_e parse_route_delete( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_route_add_del_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_route_delete(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
+
+ return reply->retval;
+}
+
+static vapi_error_e hicn_disable_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_enable_disable_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
return reply->retval;
}
-static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, bool async) {
+static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route,
+ bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_lock();
- vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
+
+ vapi_msg_hicn_api_enable_disable *msg =
+ vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
+
+ if (route->family == AF_INET) {
+ memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ msg->payload.prefix.address.af = ADDRESS_IP4;
+ } else {
+ memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ msg->payload.prefix.address.af = ADDRESS_IP6;
+ }
+
+ msg->payload.prefix.len = route->len;
+ msg->payload.enable_disable = 0;
+
+ vapi_error_e ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg,
+ hicn_disable_cb, NULL);
+
+ if (ret) {
+ ERROR("Error in vapi_hicn_api_enable_disable in route delete");
+ goto done;
+ }
+
+ vapi_msg_ip_route_add_del *hicnp_msg =
+ vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
hicnp_msg->payload.is_add = 0;
if (route->family == AF_INET) {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0],
+ &route->remote_addr.v4, 4);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4;
- }
- else {
- memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ } else {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0],
+ &route->remote_addr.v6, 16);
hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6;
}
@@ -735,34 +761,41 @@ static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, bool
hc_face_t *face = &(route->face);
switch (face->face.type) {
- case FACE_TYPE_HICN:
- {
- if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) {
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
- }
- else{
- memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t));
- hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
- }
-
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
-
- break;
- }
- case FACE_TYPE_UDP:
- {
- hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
- hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index;
- break;
+ case FACE_TYPE_HICN: {
+ if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr)))) {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4),
+ &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6),
+ &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
}
+
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+
+ break;
+ }
+ case FACE_TYPE_UDP: {
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index;
+ break;
+ }
default:
return -1;
}
- vapi_error_e ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_delete, NULL);
+ ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg,
+ parse_route_delete, NULL);
+
+ if (ret) {
+ ERROR("Error in vapi_ip_route_add_del in route delete");
+ goto done;
+ }
+
+done:
vapi_unlock();
return ret;
@@ -776,33 +809,31 @@ static int _hc_route_delete_async(hc_sock_t *s, hc_route_t *route) {
return _hc_route_delete_internal(s, route, true);
}
-static vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_udp_encap_details *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_udp_encap_list(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_udp_encap_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- hc_face_t * face = (hc_face_t *)callback_ctx;
+ hc_face_t *face = (hc_face_t *)callback_ctx;
- if (face->face.netdevice.index == reply->udp_encap.id)
- {
- switch(reply->udp_encap.src_ip.af) {
- case ADDRESS_IP4:
- {
- memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), sizeof(ip4_address_t));
- memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), sizeof(ip4_address_t));
+ if (face->face.netdevice.index == reply->udp_encap.id) {
+ switch (reply->udp_encap.src_ip.af) {
+ case ADDRESS_IP4: {
+ memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4),
+ sizeof(ip4_address_t));
+ memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4),
+ sizeof(ip4_address_t));
break;
}
- case ADDRESS_IP6:
- {
- memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), sizeof(ip6_address_t));
- memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), sizeof(ip6_address_t));
+ case ADDRESS_IP6: {
+ memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6),
+ sizeof(ip6_address_t));
+ memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6),
+ sizeof(ip6_address_t));
break;
}
default:
- break;
+ break;
}
face->face.local_port = reply->udp_encap.src_port;
@@ -811,35 +842,35 @@ static vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
return rv;
}
-static int _fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s) {
- switch(path->type){
- case FIB_API_PATH_FLAG_NONE:
- {
+static int _fill_face_with_info(hc_face_t *face, vapi_type_fib_path *path,
+ hc_sock_t *s) {
+ switch (path->type) {
+ case FIB_API_PATH_FLAG_NONE: {
face->face.type = FACE_TYPE_HICN;
- switch(path->proto){
+ switch (path->proto) {
case FIB_API_PATH_NH_PROTO_IP4:
- memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4), sizeof(ip4_address_t));
- break;
+ memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4),
+ sizeof(ip4_address_t));
+ break;
case FIB_API_PATH_NH_PROTO_IP6:
- memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6), sizeof(ip6_address_t));
- break;
+ memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6),
+ sizeof(ip6_address_t));
+ break;
default:
- break;
+ break;
}
face->face.netdevice.index = path->sw_if_index;
- }
- break;
- case FIB_API_PATH_TYPE_UDP_ENCAP:
- {
+ } break;
+ case FIB_API_PATH_TYPE_UDP_ENCAP: {
face->face.type = FACE_TYPE_UDP;
face->face.netdevice.index = clib_net_to_host_u32(path->nh.obj_id);
// Let's make the compiler happy
(void)parse_udp_encap_list;
- //vapi_msg_udp_encap_dump *msg;
- //msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance);
- //vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, face);
- }
- break;
+ // vapi_msg_udp_encap_dump *msg;
+ // msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance);
+ // vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list,
+ // face);
+ } break;
default:
return -1;
}
@@ -852,32 +883,33 @@ typedef struct hicn_route_socket_s {
hc_sock_t *s;
} hicn_route_socket_t;
-static vapi_error_e parse_route_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_route_details *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_route_list(vapi_ctx_t ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
hicn_route_socket_t *rs = (hicn_route_socket_t *)callback_ctx;
hc_data_t *data = rs->data;
u8 found = false;
- for (int j = 0; j < reply->route.n_paths; j++){
+ for (int j = 0; j < reply->route.n_paths; j++) {
for (int i = 0; i < data->size && !found; i++) {
- hc_route_t * route = &((hc_route_t*)(data->buffer))[i];
-
- if(ip46_address_is_ip4((ip46_address_t *)&(route->remote_addr)) &&
- memcmp(route->remote_addr.v4.as_u8, reply->route.prefix.address.un.ip4, sizeof(ip4_address_t)) == 0 &&
- route->len == reply->route.prefix.len && route->face_id == ~0) {
- _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
- found = true;
- } else if (memcmp(route->remote_addr.v6.as_u8, reply->route.prefix.address.un.ip6, sizeof(ip6_address_t)) == 0 &&
- route->len == reply->route.prefix.len && route->face_id == ~0) {
- _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
- found = true;
+ hc_route_t *route = &((hc_route_t *)(data->buffer))[i];
+
+ if (ip_address_is_v4((ip_address_t *)&(route->remote_addr)) &&
+ memcmp(route->remote_addr.v4.as_u8,
+ reply->route.prefix.address.un.ip4,
+ sizeof(ip4_address_t)) == 0 &&
+ route->len == reply->route.prefix.len && route->face_id == ~0) {
+ _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ found = true;
+ } else if (memcmp(route->remote_addr.v6.as_u8,
+ reply->route.prefix.address.un.ip6,
+ sizeof(ip6_address_t)) == 0 &&
+ route->len == reply->route.prefix.len &&
+ route->face_id == ~0) {
+ _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ found = true;
}
}
}
@@ -885,14 +917,10 @@ static vapi_error_e parse_route_list( vapi_ctx_t ctx,
return rv;
}
-static vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_routes_details *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_hicn_route_list(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_routes_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
hc_data_t *data = (hc_data_t *)callback_ctx;
@@ -900,43 +928,41 @@ static vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
if (empty_spots < reply->nfaces) {
int new_size = data->size + (reply->nfaces - empty_spots);
data->buffer = realloc(data->buffer, sizeof(hc_route_t) * (new_size));
- if (!data->buffer)
- return VAPI_ENOMEM;
+ if (!data->buffer) return VAPI_ENOMEM;
- data->size =new_size;
+ data->size = new_size;
}
for (int i = 0; i < reply->nfaces; i++) {
- hc_route_t * route = &((hc_route_t*)(data->buffer))[data->current];
+ hc_route_t *route = &((hc_route_t *)(data->buffer))[data->current];
route->face_id = ~0;
route->cost = 1;
route->len = reply->prefix.len;
- if (reply->prefix.address.af == ADDRESS_IP6)
- {
- memcpy(route->remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16);
- }
- else
- {
- memcpy(route->remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4);
- }
- route->family = reply->prefix.address.af == ADDRESS_IP6? AF_INET6 : AF_INET;
+ if (reply->prefix.address.af == ADDRESS_IP6) {
+ memcpy(route->remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16);
+ } else {
+ memcpy(route->remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4);
+ }
+ route->family =
+ reply->prefix.address.af == ADDRESS_IP6 ? AF_INET6 : AF_INET;
data->current++;
}
return rv;
}
-static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool async) {
+static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_lock();
vapi_msg_hicn_api_routes_dump *msg;
msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance);
- hc_data_t *data = hc_data_create(0, sizeof(hc_route_t),NULL);
+ hc_data_t *data = hc_data_create(0, sizeof(hc_route_t), NULL);
int ret = VAPI_OK;
- if (!data){
+ if (!data) {
ret = -1;
goto err;
}
@@ -949,10 +975,10 @@ static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool as
goto err_free;
}
- ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, parse_hicn_route_list, data);
+ ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg,
+ parse_hicn_route_list, data);
- if (ret != VAPI_OK)
- goto err_free;
+ if (ret != VAPI_OK) goto err_free;
vapi_msg_ip_route_dump *hicnp_msg;
hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance);
@@ -960,29 +986,30 @@ static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool as
hicnp_msg->payload.table.is_ip6 = 1;
hicn_route_socket_t ctx = {
- .data = data,
- .s = socket,
+ .data = data,
+ .s = socket,
};
- ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
+ ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list,
+ &ctx);
hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance);
hicnp_msg->payload.table.table_id = 0;
hicnp_msg->payload.table.is_ip6 = 0;
- ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
+ ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list,
+ &ctx);
- if (ret != VAPI_OK)
- goto err_free;
+ if (ret != VAPI_OK) goto err_free;
*pdata = data;
vapi_unlock();
return ret;
- err_free:
+err_free:
free(data);
- err:
+err:
vapi_unlock();
return ret;
}
@@ -1008,17 +1035,19 @@ static int _hc_route_list_async(hc_sock_t *s) {
*
*----------------------------------------------------------------------------*/
-static int _hc_face_create(hc_sock_t *s, hc_face_t *face) {
- ERROR("Face creation implemented.");
+static int _hc_face_create(hc_sock_t *socket, hc_face_t *face) {
+ ERROR("Face creation not implemented.");
return -1;
}
-static int _hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found) {
+static int _hc_face_get(hc_sock_t *socket, hc_face_t *face,
+ hc_face_t **face_found) {
ERROR("Face deletion not implemented.");
return -1;
}
-static int _hc_face_delete(hc_sock_t *s, hc_face_t *face) {
+static int _hc_face_delete(hc_sock_t *s, hc_face_t *face,
+ uint8_t delete_listener) {
ERROR("Face deletion not implemented.");
return -1;
}
@@ -1030,9 +1059,7 @@ static int _hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
return -1;
}
-static int _hc_face_list_async(hc_sock_t *s) {
- return 0;
-}
+static int _hc_face_list_async(hc_sock_t *s) { return 0; }
static int _hc_face_set_admin_state(
hc_sock_t *s, const char *conn_id_or_name, // XXX wrong identifier
@@ -1041,22 +1068,25 @@ static int _hc_face_set_admin_state(
}
#ifdef WITH_POLICY
-static int _hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+static int _hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name,
+ uint32_t priority) {
ERROR("Face set priority not implemented.");
return -1;
}
-static int _hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+static int _hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name,
+ policy_tags_t tags) {
ERROR("Face set tags not implemented.");
return -1;
}
-#endif // WITH_POLICY
+#endif // WITH_POLICY
/*----------------------------------------------------------------------------*
* Punting
*----------------------------------------------------------------------------*/
-static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting, bool async) {
+static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting,
+ bool async) {
return -1;
}
@@ -1069,7 +1099,7 @@ static int _hc_punting_create_async(hc_sock_t *s, hc_punting_t *punting) {
}
static int _hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
- hc_punting_t **punting_found) {
+ hc_punting_t **punting_found) {
ERROR("hc_punting_get not (yet) implemented.");
return -1;
}
@@ -1088,28 +1118,30 @@ static int _hc_punting_list(hc_sock_t *s, hc_data_t **pdata) {
* Cache
*----------------------------------------------------------------------------*/
-static int _hc_cache_set_store_internal(hc_sock_t *s, int enabled, bool async) {
+static int _hc_cache_set_store_internal(hc_sock_t *s, hc_cache_t *cache,
+ bool async) {
return 0;
}
-static int _hc_cache_set_store(hc_sock_t *s, int enabled) {
- return _hc_cache_set_store_internal(s, enabled, false);
+static int _hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_store_internal(s, cache, false);
}
-static int _hc_cache_set_store_async(hc_sock_t *s, int enabled) {
- return _hc_cache_set_store_internal(s, enabled, true);
+static int _hc_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_store_internal(s, cache, true);
}
-static int _hc_cache_set_serve_internal(hc_sock_t *s, int enabled, bool async) {
+static int _hc_cache_set_serve_internal(hc_sock_t *s, hc_cache_t *cache,
+ bool async) {
return 0;
}
-static int _hc_cache_set_serve(hc_sock_t *s, int enabled) {
- return _hc_cache_set_serve_internal(s, enabled, false);
+static int _hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_serve_internal(s, cache, false);
}
-static int _hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
- return _hc_cache_set_serve_internal(s, enabled, true);
+static int _hc_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) {
+ return _hc_cache_set_serve_internal(s, cache, true);
}
/*----------------------------------------------------------------------------*
@@ -1117,12 +1149,15 @@ static int _hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
*----------------------------------------------------------------------------*/
// per prefix
-static int _hc_strategy_set(hc_sock_t *s /* XXX */) { return 0; }
+static int _hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) { return 0; }
-static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) {
+static int _hc_strategy_add_local_prefix(hc_sock_t *s,
+ hc_strategy_t *strategy) {
return 0;
}
+static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) { return 0; }
+
/*----------------------------------------------------------------------------*
* WLDR
*----------------------------------------------------------------------------*/
@@ -1138,9 +1173,11 @@ static int _hc_mapme_set(hc_sock_t *s, int enabled) { return 0; }
static int _hc_mapme_set_discovery(hc_sock_t *s, int enabled) { return 0; }
-static int _hc_mapme_set_timescale(hc_sock_t *s, double timescale) { return 0; }
+static int _hc_mapme_set_timescale(hc_sock_t *s, uint32_t timescale) {
+ return 0;
+}
-static int _hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; }
+static int _hc_mapme_set_retx(hc_sock_t *s, uint32_t timescale) { return 0; }
/*----------------------------------------------------------------------------*
* Policy
@@ -1150,51 +1187,99 @@ static int _hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; }
/* POLICY CREATE */
-static int _hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) {
+static int _hc_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
return -1;
}
-static int
-_hc_policy_create(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_create(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_create_internal(s, policy, false);
}
-static int _hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_create_async(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_create_internal(s, policy, true);
}
/* POLICY DELETE */
-static int _hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) {
+static int _hc_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy,
+ bool async) {
return -1;
}
-static int _hc_policy_delete(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_delete(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_delete_internal(s, policy, false);
}
-static int _hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy) {
+static int _hc_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) {
return _hc_policy_delete_internal(s, policy, true);
}
/* POLICY LIST */
-static int
-_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) {
+static int _hc_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
return -1;
}
-static int _hc_policy_list(hc_sock_t * s, hc_data_t ** pdata) {
+static int _hc_policy_list(hc_sock_t *s, hc_data_t **pdata) {
return _hc_policy_list_internal(s, pdata, false);
}
-static int _hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata) {
+static int _hc_policy_list_async(hc_sock_t *s, hc_data_t **pdata) {
return _hc_policy_list_internal(s, pdata, true);
}
#endif /* WITH_POLICY */
-static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
+/*----------------------------------------------------------------------------*
+ * Configuration
+ *----------------------------------------------------------------------------*/
+
+typedef struct hc_result_s {
+ void *_;
+} hc_result_t;
+
+static hc_result_t *_hc_listener_create_conf(hc_sock_t *s,
+ hc_listener_t *listener) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_connection_create_conf(hc_sock_t *s,
+ hc_connection_t *connection) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_route_create_conf(hc_sock_t *s, hc_route_t *route) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_strategy_set_conf(hc_sock_t *s,
+ hc_strategy_t *strategy) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+static hc_result_t *_hc_strategy_add_local_prefix_conf(
+ hc_sock_t *s, hc_strategy_t *strategy) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+
+hc_msg_t *_hc_result_get_msg(hc_result_t *result) {
+ ERROR("Not implemented.");
+ return NULL;
+}
+int _hc_result_get_cmd_id(hc_result_t *result) {
+ ERROR("Not implemented.");
+ return -1;
+}
+bool _hc_result_get_success(hc_result_t *result) {
+ ERROR("Not implemented.");
+ return false;
+}
+void _hc_result_free(hc_result_t *result) { free(result); }
+
+static hc_sock_t hc_sock_vpp_interface = (hc_sock_t){
.hc_sock_get_next_seq = _hc_sock_vpp_get_next_seq,
.hc_sock_set_nonblocking = _hc_sock_vpp_set_nonblocking,
.hc_sock_get_fd = _hc_sock_vpp_get_fd,
@@ -1230,7 +1315,7 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
.hc_connection_set_priority_async = _hc_connection_set_priority_async,
.hc_connection_set_tags = _hc_connection_set_tags,
.hc_connection_set_tags_async = _hc_connection_set_tags_async,
-#endif // WITH_POLICY
+#endif // WITH_POLICY
.hc_face_create = _hc_face_create,
.hc_face_get = _hc_face_get,
@@ -1242,7 +1327,7 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
#ifdef WITH_POLICY
.hc_face_set_priority = _hc_face_set_priority,
.hc_face_set_tags = _hc_face_set_tags,
-#endif // WITH_POLICY
+#endif // WITH_POLICY
.hc_route_create = _hc_route_create,
.hc_route_create_async = _hc_route_create_async,
@@ -1264,6 +1349,7 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
.hc_strategy_list = _hc_strategy_list,
.hc_strategy_set = _hc_strategy_set,
+ .hc_strategy_add_local_prefix = _hc_strategy_add_local_prefix,
.hc_wldr_set = _hc_wldr_set,
.hc_mapme_set = _hc_mapme_set,
@@ -1277,16 +1363,27 @@ static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
.hc_policy_delete = _hc_policy_delete,
.hc_policy_delete_async = _hc_policy_delete_async,
.hc_policy_list = _hc_policy_list,
- .hc_policy_list_async = _hc_policy_list_async
-#endif // WITH_POLICY
+ .hc_policy_list_async = _hc_policy_list_async,
+#endif // WITH_POLICY
+
+ .hc_listener_create_conf = _hc_listener_create_conf,
+ .hc_connection_create_conf = _hc_connection_create_conf,
+ .hc_route_create_conf = _hc_route_create_conf,
+ .hc_strategy_set_conf = _hc_strategy_set_conf,
+ .hc_strategy_add_local_prefix_conf = _hc_strategy_add_local_prefix_conf,
+
+ .hc_result_get_msg = _hc_result_get_msg,
+ .hc_result_get_cmd_id = _hc_result_get_cmd_id,
+ .hc_result_get_success = _hc_result_get_success,
+ .hc_result_free = _hc_result_free,
};
hc_sock_t *_hc_sock_create_url(const char *url) {
- // NOT IMPLEMENTED
- return NULL;
-}
+ if (url) {
+ // NOT IMPLEMENTED
+ return NULL;
+ }
-hc_sock_t *_hc_sock_create(void) {
hc_sock_vpp_t *s = malloc(sizeof(hc_sock_vpp_t));
if (!s) goto ERR_SOCK;
@@ -1302,4 +1399,4 @@ hc_sock_t *_hc_sock_create(void) {
ERR_SOCK:
return NULL;
-} \ No newline at end of file
+}
diff --git a/ctrl/libhicnctrl/src/route.c b/ctrl/libhicnctrl/src/route.c
index 703b4763f..f59dbce7c 100644
--- a/ctrl/libhicnctrl/src/route.c
+++ b/ctrl/libhicnctrl/src/route.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,84 +25,64 @@
#define DEFAULT_HICN_ROUTE_COST 1
struct hicn_route_s {
- ip_prefix_t prefix;
- face_id_t face_id;
- route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */
+ ip_prefix_t prefix;
+ face_id_t face_id;
+ route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */
};
-hicn_route_t *
-hicn_route_create(ip_prefix_t * prefix, face_id_t face_id, route_cost_t cost)
-{
- hicn_route_t * route = malloc(sizeof(hicn_route_t));
- if (!route)
- return NULL;
- route->prefix = *prefix;
- route->face_id = face_id;
- route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST;
+hicn_route_t* hicn_route_create(ip_prefix_t* prefix, face_id_t face_id,
+ route_cost_t cost) {
+ hicn_route_t* route = malloc(sizeof(hicn_route_t));
+ if (!route) return NULL;
+ route->prefix = *prefix;
+ route->face_id = face_id;
+ route->cost = cost != 0 ? cost : DEFAULT_HICN_ROUTE_COST;
- return route;
+ return route;
}
-hicn_route_t *
-hicn_route_dup(const hicn_route_t * route)
-{
- hicn_route_t * new_route = malloc(sizeof(hicn_route_t));
- if (!route)
- return NULL;
- memcpy(new_route, route, sizeof(hicn_route_t));
- return new_route;
+hicn_route_t* hicn_route_dup(const hicn_route_t* route) {
+ hicn_route_t* new_route = malloc(sizeof(hicn_route_t));
+ if (!route) return NULL;
+ memcpy(new_route, route, sizeof(hicn_route_t));
+ return new_route;
}
-void hicn_route_free(hicn_route_t * route)
-{
- free(route);
-}
+void hicn_route_free(hicn_route_t* route) { free(route); }
-int
-hicn_route_cmp(const hicn_route_t * route1, const hicn_route_t * route2)
-{
- int rc;
- rc = ip_prefix_cmp(&route1->prefix, &route2->prefix);
- if (rc != 0)
- return rc;
+int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2) {
+ int rc;
+ rc = ip_prefix_cmp(&route1->prefix, &route2->prefix);
+ if (rc != 0) return rc;
- return (route1->face_id > route2->face_id) ? 1 :
- (route1->face_id < route2->face_id) ? -1 : 0;
+ return (route1->face_id > route2->face_id) ? 1
+ : (route1->face_id < route2->face_id) ? -1
+ : 0;
}
-int
-hicn_route_get_prefix(const hicn_route_t * route, ip_prefix_t * prefix)
-{
- *prefix = route->prefix;
- return 0;
+int hicn_route_get_prefix(const hicn_route_t* route, ip_prefix_t* prefix) {
+ *prefix = route->prefix;
+ return 0;
}
-int
-hicn_route_set_prefix(hicn_route_t * route, const ip_prefix_t prefix)
-{
- route->prefix = prefix;
- return 0;
+int hicn_route_set_prefix(hicn_route_t* route, const ip_prefix_t prefix) {
+ route->prefix = prefix;
+ return 0;
}
-int
-hicn_route_get_cost(const hicn_route_t * route, int * cost)
-{
- *cost = route->cost;
- return 0;
+int hicn_route_get_cost(const hicn_route_t* route, int* cost) {
+ *cost = route->cost;
+ return 0;
}
-int
-hicn_route_set_cost(hicn_route_t * route, const int cost)
-{
- route->cost = cost;
- return 0;
+int hicn_route_set_cost(hicn_route_t* route, const int cost) {
+ route->cost = cost;
+ return 0;
}
/* /!\ Please update constants in header file upon changes */
-size_t
-hicn_route_snprintf(char * s, size_t size, const hicn_route_t * route)
-{
- char prefix_s[MAXSZ_PREFIX];
- ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_PREFIX);
- return snprintf(s, size, "%s [%d]", prefix_s, route->cost);
+size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route) {
+ char prefix_s[MAXSZ_IP_PREFIX];
+ ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_IP_PREFIX);
+ return snprintf(s, size, "%s [%d]", prefix_s, route->cost);
}
diff --git a/ctrl/libhicnctrl/src/util/hash.h b/ctrl/libhicnctrl/src/util/hash.h
index 7c7bb1e3a..f3a1eedcc 100644
--- a/ctrl/libhicnctrl/src/util/hash.h
+++ b/ctrl/libhicnctrl/src/util/hash.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -27,67 +27,88 @@
#ifndef UTIL_HASH_H
#define UTIL_HASH_H
-#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
- __BYTE_ORDER == __LITTLE_ENDIAN) || \
+#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
+ 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
+ __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
+#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 hashsize(n) ((uint32_t)1 << (n))
+#define hashmask(n) (hashsize(n) - 1)
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
-#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); \
-}
+#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; \
+ }
-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 */
+#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 */
+ 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)
- {
+ while (length > 12) {
a += k[0];
b += k[1];
c += k[2];
- mix(a,b,c);
+ mix(a, b, c);
length -= 12;
k += 3;
}
@@ -104,136 +125,214 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
*/
#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 */
+ 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;
+ 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;
+ 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);
+ 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 */
+ 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 */
+ } 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)
- {
+ while (length > 12) {
a += k[0];
- a += ((uint32_t)k[1])<<8;
- a += ((uint32_t)k[2])<<16;
- a += ((uint32_t)k[3])<<24;
+ 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;
+ 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);
+ 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 */
+ 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;
+ 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);
+ final(a, b, c);
return c;
}
@@ -241,7 +340,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
#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(buf, len) hashlittle(buf, len, HASH_INITVAL)
#define hash_struct(buf) hash(buf, sizeof(buf))
#endif /* UTIL_JENKINS_HASH_H */
diff --git a/ctrl/sysrepo-plugins/CMakeLists.txt b/ctrl/sysrepo-plugins/CMakeLists.txt
index 2412d5688..0765f75d8 100644
--- a/ctrl/sysrepo-plugins/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -41,13 +41,13 @@ if (NOT SRPD_PLUGINS_PATH)
message(FATAL_ERROR "Cannot get sysrepo plugins directory due to missing pkg-config, set SRPD_PLUGINS_PATH manually.")
endif()
-find_package(Vpp REQUIRED)
+find_package(Vpp ${VPP_DEFAULT_VERSION} REQUIRED)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(HicnPlugin REQUIRED)
+ find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
else()
list(APPEND DEPENDENCIES
- hicn_plugin
+ ${HICNPLUGIN_SHARED}
)
endif()
diff --git a/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake b/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake
index 323c9d01a..cba9adf1f 100644
--- a/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake
+++ b/ctrl/sysrepo-plugins/cmake/Modules/Packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -15,17 +15,22 @@
# Packages section
######################
+##############################################################
+# Get VPP version
+##############################################################
+list(GET VPP_DEFAULT_VERSION 0 VPP_VERSION)
+
set(hicn-sysrepo-plugin_DESCRIPTION
"A Plugin to enable hICN VPP in sysrepo."
CACHE STRING "Description for deb/rpm package."
)
set(hicn-sysrepo-plugin_DEB_DEPENDENCIES
- "hicn-plugin (>= stable_version-release), sysrepo (>= 1.0)"
+ "hicn-plugin (= ${VPP_VERSION}-release), sysrepo (>= 1.0)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(hicn-sysrepo-plugin_RPM_DEPENDENCIES
- "hicn-plugin >= stable_version-release, sysrepo >= 1.0"
+ "hicn-plugin = ${VPP_VERSION}-release, sysrepo >= 1.0"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
index 5ba7045c1..f8a1e64aa 100644
--- a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
index 85da0d3e9..b5faab705 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c
index 6cfc0b52b..b2495f730 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,8 +21,6 @@
#include "hicn_light.h"
#include "model/hicn_model.h"
-
-
sr_subscription_ctx_t *subscription = NULL;
volatile int exit_application = 0;
@@ -37,7 +35,6 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) {
hicn_subscribe_events(session, &subscription);
-
/* set subscription as our private context */
*private_ctx = subscription;
return SR_ERR_OK;
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h
index 16f65e5c4..cea2851c9 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c
index 6c4f938ce..08551b470 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,20 +14,17 @@
*/
#include "hicn_light_comm.h"
-hc_sock_t * hsocket;
+hc_sock_t* hsocket;
int hicn_connect_light() {
-
- hsocket = hc_sock_create();
- if (!hsocket)
- HICN_LOG_ERR_MSG("Error creating socket\n");
- if (hc_sock_connect(hsocket) < 0)
- HICN_LOG_ERR_MSG("Error connecting to the forwarder\n");
- return 0;
-
+ hsocket = hc_sock_create();
+ if (!hsocket) HICN_LOG_ERR_MSG("Error creating socket\n");
+ if (hc_sock_connect(hsocket) < 0)
+ HICN_LOG_ERR_MSG("Error connecting to the forwarder\n");
+ return 0;
}
int hicn_disconnect_light() {
- hc_sock_free(hsocket);
+ hc_sock_free(hsocket);
return 0;
} \ No newline at end of file
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h
index ca67cf0b7..c03d59c30 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/hicn_light_comm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,7 +18,6 @@
#include <sysrepo.h>
#include <sysrepo/values.h>
-
#include <hicn/ctrl/api.h>
#ifndef HICN_THIS_FUNC
@@ -37,23 +36,20 @@
} \
} while (0)
-
-
#define ARG_CHECK2(retval, arg1, arg2) \
- ARG_CHECK(retval, arg1); \
- ARG_CHECK(retval, arg2)
+ ARG_CHECK(retval, arg1); \
+ ARG_CHECK(retval, arg2)
#define ARG_CHECK5(retval, arg1, arg2, arg3, arg4, arg5) \
- ARG_CHECK(retval, arg1); \
- ARG_CHECK(retval, arg2); \
- ARG_CHECK(retval, arg3); \
- ARG_CHECK(retval, arg4); \
- ARG_CHECK(retval, arg5)
-
+ ARG_CHECK(retval, arg1); \
+ ARG_CHECK(retval, arg2); \
+ ARG_CHECK(retval, arg3); \
+ ARG_CHECK(retval, arg4); \
+ ARG_CHECK(retval, arg5)
#define MEM_ALIGN 4096
int hicn_connect_light();
int hicn_disconnect_light();
-extern hc_sock_t * hsocket;
+extern hc_sock_t* hsocket;
#endif //__HICN_LIGHT_COMMM_H__
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c b/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c
index 47e07d196..d32fd55ef 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,72 +22,67 @@
#include "tlock.h"
#include "../hicn_light.h"
#include "../hicn_light_comm.h"
-
-
+#include <hicn/util/sstrncpy.h>
/**
* @brief API to add hicn face ip in hicn-light.
*/
-static int hicn_face_ip_add_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
+static int hicn_face_ip_add_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input, const size_t input_cnt,
+ sr_event_t event, uint32_t request_id,
+ sr_val_t **output, size_t *output_cnt,
+ void *private_data) {
SRP_LOG_DBGMSG("hicn face ip add received successfully");
hc_face_t face;
- if(strcmp(input[0].data.string_val,"-1")){
-
- struct sockaddr_in sa;
- // store this IP address in sa:
- inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
- face.face.family=AF_INET;
- face.face.local_addr.v4.as_inaddr=sa.sin_addr;
-
-
- }else if(strcmp(input[1].data.string_val,"-1")){
-
+ if (strcmp(input[0].data.string_val, "-1")) {
+ struct sockaddr_in sa;
+ // store this IP address in sa:
+ inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
+ face.face.family = AF_INET;
+ face.face.local_addr.v4.as_inaddr = sa.sin_addr;
+
+ } else if (strcmp(input[1].data.string_val, "-1")) {
struct in6_addr *dst = malloc(sizeof(struct in6_addr));
inet_pton(AF_INET6, input[1].data.string_val, dst);
- face.face.family=AF_INET6;
+ face.face.family = AF_INET6;
face.face.local_addr.v6.as_in6addr = *dst;
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
+ } else {
+ SRP_LOG_DBGMSG("Invalid local IP address");
+ return SR_ERR_OPERATION_FAILED;
}
- if(strcmp(input[2].data.string_val,"-1")){
-
- struct sockaddr_in sa;
- // store this IP address in sa:
- inet_pton(AF_INET, input[2].data.string_val, &(sa.sin_addr));
- face.face.family=AF_INET;
- face.face.remote_addr.v4.as_inaddr=sa.sin_addr;
-
-
- }else if(strcmp(input[3].data.string_val,"-1")){
+ if (strcmp(input[2].data.string_val, "-1")) {
+ struct sockaddr_in sa;
+ // store this IP address in sa:
+ inet_pton(AF_INET, input[2].data.string_val, &(sa.sin_addr));
+ face.face.family = AF_INET;
+ face.face.remote_addr.v4.as_inaddr = sa.sin_addr;
+ } else if (strcmp(input[3].data.string_val, "-1")) {
struct in6_addr *dst = malloc(sizeof(struct in6_addr));
inet_pton(AF_INET6, input[3].data.string_val, dst);
- face.face.family=AF_INET6;
+ face.face.family = AF_INET6;
face.face.remote_addr.v6.as_in6addr = *dst;
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
+ } else {
+ SRP_LOG_DBGMSG("Invalid local IP address");
+ return SR_ERR_OPERATION_FAILED;
}
-
- face.face.netdevice.index = input[4].data.uint32_val; // This is the idx number of interface
-
-
- face.id=0;//can be empty
- strcpy(face.name,"hicn_face");
- face.face.type=1;
+ face.face.netdevice.index =
+ input[4].data.uint32_val; // This is the idx number of interface
int rc;
+ face.id = 0; // can be empty
+ rc = strcpy_s(face.name, sizeof(face.name), "hicn_face");
+ if (rc != EOK) return SR_ERR_OPERATION_FAILED;
+ face.face.type = 1;
+
rc = hc_face_create(hsocket, &face);
if (rc > 0) {
- SRP_LOG_DBGMSG("Face added successfully");
- return SR_ERR_OK;
+ SRP_LOG_DBGMSG("Face added successfully");
+ return SR_ERR_OK;
}
SRP_LOG_DBGMSG("Operation Failed");
@@ -97,92 +92,84 @@ static int hicn_face_ip_add_cb(sr_session_ctx_t *session, const char *path, cons
/**
* @brief API to del hicn face ip in vpp.
*/
-static int hicn_face_ip_del_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
+static int hicn_face_ip_del_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input, const size_t input_cnt,
+ sr_event_t event, uint32_t request_id,
+ sr_val_t **output, size_t *output_cnt,
+ void *private_data) {
SRP_LOG_DBGMSG("hicn face ip del received successfully");
- face_t * face=NULL;
-
+ face_t *face = NULL;
face_free(face);
-
-
SRP_LOG_DBGMSG("Operation Failed");
return SR_ERR_OPERATION_FAILED;
-
}
-
/**
* @brief API to del hicn face ip in vpp.
*/
-static int hicn_route_add_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+static int hicn_route_add_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input, const size_t input_cnt,
+ sr_event_t event, uint32_t request_id,
+ sr_val_t **output, size_t *output_cnt,
+ void *private_data) {
+ /*
-/*
+ SRP_LOG_DBG_MSG("hicn route add received successfully");
- SRP_LOG_DBG_MSG("hicn route add received successfully");
+ hc_route_t * route;
- hc_route_t * route;
+ if(strcmp(input[0].data.string_val,"-1")){
- if(strcmp(input[0].data.string_val,"-1")){
+ struct sockaddr_in sa;
+ // store this IP address in sa:
+ inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
+ route.family=AF_INET;
+ route.face.hicn.local_addr.v4.as_inaddr=sa.sin_addr;
- struct sockaddr_in sa;
- // store this IP address in sa:
- inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
- route.family=AF_INET;
- route.face.hicn.local_addr.v4.as_inaddr=sa.sin_addr;
+ }else if(strcmp(input[1].data.string_val,"-1")){
- }else if(strcmp(input[1].data.string_val,"-1")){
+ struct in6_addr *dst = malloc(sizeof(struct in6_addr));
+ inet_pton(AF_INET6, input[1].data.string_val, dst);
+ face.face.hicn.family=AF_INET6;
+ face.face.hicn.local_addr.v6.as_in6addr = *dst;
- struct in6_addr *dst = malloc(sizeof(struct in6_addr));
- inet_pton(AF_INET6, input[1].data.string_val, dst);
- face.face.hicn.family=AF_INET6;
- face.face.hicn.local_addr.v6.as_in6addr = *dst;
-
- }else{
- SRP_LOG_DBG_MSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
- }
+ }else{
+ SRP_LOG_DBG_MSG("Invalid local IP address");
+ return SR_ERR_OPERATION_FAILED;
+ }
-hc_route_create(hsocket, route);
-*/
- return SR_ERR_OK;
+ hc_route_create(hsocket, route);
+ */
+ return SR_ERR_OK;
}
-
-
int hicn_subscribe_events(sr_session_ctx_t *session,
sr_subscription_ctx_t **subscription) {
-
-
int rc;
- rc = sr_rpc_subscribe(session, "/hicn:face-ip-add", hicn_face_ip_add_cb,
- session, 100,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription stat-get\n");
- goto error;
- }
-
-
- rc = sr_rpc_subscribe(session, "/hicn:face-ip-del", hicn_face_ip_del_cb,
- session, 100,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription face-ip-del\n");
- goto error;
- }
-
+ rc = sr_rpc_subscribe(session, "/hicn:face-ip-add", hicn_face_ip_add_cb,
+ session, 100, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription stat-get\n");
+ goto error;
+ }
- rc = sr_rpc_subscribe(session, "/hicn:route-nhops-add",
- hicn_route_add_cb, session, 100,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc!= SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription route-nhops-add\n");
- goto error;
- }
+ rc = sr_rpc_subscribe(session, "/hicn:face-ip-del", hicn_face_ip_del_cb,
+ session, 100, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription face-ip-del\n");
+ goto error;
+ }
+ rc = sr_rpc_subscribe(session, "/hicn:route-nhops-add", hicn_route_add_cb,
+ session, 100, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription route-nhops-add\n");
+ goto error;
+ }
SRP_LOG_DBGMSG("hicn light initialized successfully.");
return SR_ERR_OK;
@@ -191,5 +178,4 @@ error:
SRP_LOG_ERRMSG("Error by initialization of the hicn plugin.");
sr_plugin_cleanup_cb(session, hsocket);
return rc;
-
}
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h b/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h
index e6e857bff..be70bc711 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/model/hicn_model.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,7 +18,6 @@
#include "../hicn_light_comm.h"
-
#define MEM_ALIGN 4096
// Number of locks is equal to number of nodes in hicn-state
@@ -27,8 +26,7 @@
#define NLOCKS 5
#define LOCK_INIT 0
-
-enum locks_name {lstate, lstrategy, lstrategies, lroute, lface_ip_params};
+enum locks_name { lstate, lstrategy, lstrategies, lroute, lface_ip_params };
#define NSTATE_LEAVES 15
#define NSTRATEGY_LEAVES 1
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c b/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c
index 2f7b11efa..ba788d3a0 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.c
@@ -1,21 +1,16 @@
-#include"tlock.h"
+#include "tlock.h"
-
-void Ticket_init ( int Lock_Number , long int init ){
-
-__atomic_store( &En[Lock_Number] , &init , __ATOMIC_SEQ_CST );
-__atomic_store( &De[Lock_Number] , &init , __ATOMIC_SEQ_CST );
-//En[Lock_Number]=init;
-//De[Lock_Number]=init;
+void Ticket_init(int Lock_Number, long int init) {
+ __atomic_store(&En[Lock_Number], &init, __ATOMIC_SEQ_CST);
+ __atomic_store(&De[Lock_Number], &init, __ATOMIC_SEQ_CST);
+ // En[Lock_Number]=init;
+ // De[Lock_Number]=init;
}
-void Ticket_Lock(int Lock_Number ){
-
- int my_ticket = __sync_fetch_and_add(&En[Lock_Number] , 1 );
- while ( my_ticket != De[ Lock_Number ] ) {};
-
+void Ticket_Lock(int Lock_Number) {
+ int my_ticket = __sync_fetch_and_add(&En[Lock_Number], 1);
+ while (my_ticket != De[Lock_Number]) {
+ };
}
-void Ticket_Unlock(int Lock_Number ){
-De[Lock_Number]++;
-}
+void Ticket_Unlock(int Lock_Number) { De[Lock_Number]++; }
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h b/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h
index 36698115a..6840be1c0 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/model/tlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,19 +13,17 @@
* limitations under the License.
*/
-
#ifndef __TLOCK_H__
#define __TLOCK_H__
+// limit on the number of locks: it shoud be matched with the number of
+// hicn-state leaves
+#define MAX_LOCK_SIZE 5
-// limit on the number of locks: it shoud be matched with the number of hicn-state leaves
-#define MAX_LOCK_SIZE 5
-
-volatile long int En[MAX_LOCK_SIZE] , De[MAX_LOCK_SIZE] ; // For Ticket Algorithm
-
+volatile long int En[MAX_LOCK_SIZE], De[MAX_LOCK_SIZE]; // For Ticket Algorithm
-void Ticket_init ( int Lock_Number , long int init );
-void Ticket_Lock(int Lock_Number );
-void Ticket_Unlock(int Lock_Number );
+void Ticket_init(int Lock_Number, long int init);
+void Ticket_Lock(int Lock_Number);
+void Ticket_Unlock(int Lock_Number);
#endif /* __IETF_HICN_H__ */ \ No newline at end of file
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
index 10e106f51..9204e2766 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# 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:
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c
index bbcc2e9bf..fe2e6350f 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Cisco and/or its affiliates.
+ * 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:
@@ -22,12 +22,10 @@
#include "model/hicn_model.h"
#include "ietf/ietf_interface.h"
-
sr_subscription_ctx_t *subscription = NULL;
volatile int exit_application = 0;
int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) {
-
sr_subscription_ctx_t *subscription = NULL;
int rc = SR_ERR_OK;
rc = hicn_connect_vpp();
@@ -38,11 +36,10 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) {
// HICN subscribe
hicn_subscribe_events(session, &subscription);
- //sr_subscription_ctx_t *subscription2 = NULL;
+ // sr_subscription_ctx_t *subscription2 = NULL;
// IETF subscribe
- //ietf_subscribe_events(session, &subscription2);
-
+ // ietf_subscribe_events(session, &subscription2);
/* set subscription as our private context */
*private_ctx = subscription;
@@ -51,7 +48,6 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) {
}
void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx) {
-
/* subscription was set as our private context */
sr_unsubscribe(private_ctx);
hicn_disconnect_vpp();
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h
index 0890c3f03..15aea72d6 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,7 +23,6 @@
#include "hicn_vpp_comm.h"
-
/**
* @brief initialize function for sysrepo plugin,
* In this function we connect to vpp from one side
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c
index 73eab66ea..41ab3d057 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,15 +19,9 @@
#define MAX_OUTSTANDING_REQUESTS 4
#define RESPONSE_QUEUE_SIZE 2
-
-vapi_ctx_t g_vapi_ctx_instance=NULL;
-
-
-
-
+vapi_ctx_t g_vapi_ctx_instance = NULL;
int hicn_connect_vpp() {
-
if (g_vapi_ctx_instance == NULL) {
vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance);
rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL,
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h
index 9abe4e5d4..cb5eefcbe 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,13 +13,11 @@
* limitations under the License.
*/
-
/**
* @file hicn_vpp_comm.h
* @brief This file contains binary api to connect to the VPP.
*/
-
#ifndef __HICN_VPP_COMMM_H__
#define __HICN_VPP_COMMM_H__
#include <sysrepo.h>
@@ -40,7 +38,6 @@
extern vapi_ctx_t g_vapi_ctx_instance;
-
/**
* @brief This macro is interface.c to communicate with vpp
*/
@@ -48,36 +45,34 @@ extern vapi_ctx_t g_vapi_ctx_instance;
#define VPP_MAC_ADDRESS_LEN 8
#define VPP_IP6_ADDRESS_LEN 16
-
-
/**
- * @brief This macro checks the arg is NULL or not, if the arg is NULL it returns retval
+ * @brief This macro checks the arg is NULL or not, if the arg is NULL it
+ * returns retval
*/
-#define ARG_CHECK(retval, arg) \
- do { \
- if (NULL == (arg)) { \
- SRP_LOG_DBGMSG("NULL pointer passed."); \
- return (retval); \
- } \
+#define ARG_CHECK(retval, arg) \
+ do { \
+ if (NULL == (arg)) { \
+ SRP_LOG_DBGMSG("NULL pointer passed."); \
+ return (retval); \
+ } \
} while (0)
-
/**
* @brief Please check ARG_CHECK
*/
#define ARG_CHECK2(retval, arg1, arg2) \
- ARG_CHECK(retval, arg1); \
- ARG_CHECK(retval, arg2)
+ ARG_CHECK(retval, arg1); \
+ ARG_CHECK(retval, arg2)
/**
* @brief This Macro is the multiple check of ARG_CHECK
*/
#define ARG_CHECK5(retval, arg1, arg2, arg3, arg4, arg5) \
- ARG_CHECK(retval, arg1); \
- ARG_CHECK(retval, arg2); \
- ARG_CHECK(retval, arg3); \
- ARG_CHECK(retval, arg4); \
- ARG_CHECK(retval, arg5)
+ ARG_CHECK(retval, arg1); \
+ ARG_CHECK(retval, arg2); \
+ ARG_CHECK(retval, arg3); \
+ ARG_CHECK(retval, arg4); \
+ ARG_CHECK(retval, arg5)
/**
* @brief This function is used to connect to the vpp
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c
index 3e0c90cf9..9a74e6280 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020 Cisco and/or its affiliates.
+ * 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:
@@ -29,11 +29,9 @@
#include "ietf_interface.h"
#include "../hicn_vpp_comm.h"
-
DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
-typedef struct hicn_interface_
-{
+typedef struct hicn_interface_ {
u32 sw_if_index;
char interface_name[VPP_INTFC_NAME_LEN];
u8 l2_address[VPP_MAC_ADDRESS_LEN];
@@ -44,207 +42,202 @@ typedef struct hicn_interface_
u8 link_up_down;
} hicnIntfc;
-typedef struct _ietf_sw_interface_dump_ctx
-{
+typedef struct _ietf_sw_interface_dump_ctx {
u8 last_called;
int num_ifs;
int capacity;
- hicnIntfc * intfcArray;
+ hicnIntfc *intfcArray;
} ietf_sw_interface_dump_ctx;
static i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down);
-static i32 ietf_interface_name2index(const char *name, u32* if_index);
+static i32 ietf_interface_name2index(const char *name, u32 *if_index);
static i32 ietf_interface_add_del_addr(u32 sw_if_index, u8 is_add, u8 is_ipv6,
u8 del_all, u8 address_length,
u8 address[VPP_IP6_ADDRESS_LEN]);
-static int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx);
-static int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx);
+static int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx *dctx);
+static int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx *dctx);
/**
* @brief Helper function for converting netmask into prefix length.
*/
-static uint8_t
-netmask_to_prefix(const char *netmask)
-{
- in_addr_t n = 0;
- uint8_t i = 0;
+static uint8_t netmask_to_prefix(const char *netmask) {
+ in_addr_t n = 0;
+ uint8_t i = 0;
- inet_pton(AF_INET, netmask, &n);
+ inet_pton(AF_INET, netmask, &n);
- while (n > 0) {
- n = n >> 1;
- i++;
- }
+ while (n > 0) {
+ n = n >> 1;
+ i++;
+ }
- return i;
+ return i;
}
/**
- * @brief Helper function for converting IPv4/IPv6 address string into binary representation.
+ * @brief Helper function for converting IPv4/IPv6 address string into binary
+ * representation.
*/
-static int
-ip_addr_str_to_binary(const char *ip_address_str, uint8_t *ip_address_bin, bool is_ipv6)
-{
- struct in6_addr addr6 = { 0, };
- struct in_addr addr4 = { 0, };
- int ret = 0;
-
- if (is_ipv6) {
- ret = inet_pton(AF_INET6, ip_address_str, &(addr6));
- if (1 == ret)
- {
- memcpy(ip_address_bin, &addr6, sizeof(addr6));
- }
- } else {
- ret = inet_pton(AF_INET, ip_address_str, &(addr4));
- if (1 == ret)
- {
- memcpy(ip_address_bin, &addr4, sizeof(addr4));
- }
+static int ip_addr_str_to_binary(const char *ip_address_str,
+ uint8_t *ip_address_bin, bool is_ipv6) {
+ struct in6_addr addr6 = {
+ 0,
+ };
+ struct in_addr addr4 = {
+ 0,
+ };
+ int ret = 0;
+
+ if (is_ipv6) {
+ ret = inet_pton(AF_INET6, ip_address_str, &(addr6));
+ if (1 == ret) {
+ memcpy(ip_address_bin, &addr6, sizeof(addr6));
+ }
+ } else {
+ ret = inet_pton(AF_INET, ip_address_str, &(addr4));
+ if (1 == ret) {
+ memcpy(ip_address_bin, &addr4, sizeof(addr4));
}
+ }
- return ret;
+ return ret;
}
/**
* @brief Enable or disable given interface.
*/
-static int
-interface_enable_disable(const char *if_name, bool enable)
-{
- uint32_t if_index = ~0;
- int rc = 0;
-
-
- /* get interface index */
- rc = ietf_interface_name2index(if_name, &if_index);
- if (0 != rc) {
- SRP_LOG_ERRMSG("Invalid interface name");
- return SR_ERR_INVAL_ARG;
- }
+static int interface_enable_disable(const char *if_name, bool enable) {
+ uint32_t if_index = ~0;
+ int rc = 0;
+
+ /* get interface index */
+ rc = ietf_interface_name2index(if_name, &if_index);
+ if (0 != rc) {
+ SRP_LOG_ERRMSG("Invalid interface name");
+ return SR_ERR_INVAL_ARG;
+ }
- /* enable/disable interface */
- rc = ietf_setInterfaceFlags(if_index, (uint8_t)enable);
- if (0 != rc) {
- SRP_LOG_ERRMSG("Error by processing of the sw_interface_set_flags request");
- return SR_ERR_OPERATION_FAILED;
- } else {
- return SR_ERR_OK;
- }
+ /* enable/disable interface */
+ rc = ietf_setInterfaceFlags(if_index, (uint8_t)enable);
+ if (0 != rc) {
+ SRP_LOG_ERRMSG("Error by processing of the sw_interface_set_flags request");
+ return SR_ERR_OPERATION_FAILED;
+ } else {
+ return SR_ERR_OK;
+ }
}
-
-vapi_error_e call_sw_interface_add_del_address(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_sw_interface_add_del_address_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
+vapi_error_e call_sw_interface_add_del_address(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_sw_interface_add_del_address_reply *reply) {
+ if (!reply->retval) {
+ SRP_LOG_DBGMSG("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
}
-vapi_error_e call_sw_interface_set_flags(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_sw_interface_set_flags_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
+vapi_error_e call_sw_interface_set_flags(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_sw_interface_set_flags_reply *reply) {
+ if (!reply->retval) {
+ SRP_LOG_DBGMSG("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
}
-
-
/**
- * @brief Callback to be called by any config change of "/ietf-interfaces:interfaces/interface/enabled" leaf.
+ * @brief Callback to be called by any config change of
+ * "/ietf-interfaces:interfaces/interface/enabled" leaf.
*/
-static int
-ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event,
- uint32_t request_id, void *private_data)
-{
- char *if_name = NULL;
- sr_change_iter_t *iter = NULL;
- sr_change_oper_t op = SR_OP_CREATED;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
- sr_xpath_ctx_t xpath_ctx = { 0, };
- int rc = SR_ERR_OK, op_rc = SR_ERR_OK;
-
- /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */
- if (SR_EV_DONE == event) {
- return SR_ERR_OK;
- }
+static int ietf_interface_enable_disable_cb(sr_session_ctx_t *session,
+ const char *module_name,
+ const char *xpath, sr_event_t event,
+ uint32_t request_id,
+ void *private_data) {
+ char *if_name = NULL;
+ sr_change_iter_t *iter = NULL;
+ sr_change_oper_t op = SR_OP_CREATED;
+ sr_val_t *old_val = NULL;
+ sr_val_t *new_val = NULL;
+ sr_xpath_ctx_t xpath_ctx = {
+ 0,
+ };
+ int rc = SR_ERR_OK, op_rc = SR_ERR_OK;
+
+ /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY,
+ * SR_EV_ABORT */
+ if (SR_EV_DONE == event) {
+ return SR_ERR_OK;
+ }
- /* get changes iterator */
- rc = sr_get_changes_iter(session, xpath, &iter);
- if (SR_ERR_OK != rc) {
- SRP_LOG_ERRMSG("Unable to retrieve change iterator");
- return rc;
- }
+ /* get changes iterator */
+ rc = sr_get_changes_iter(session, xpath, &iter);
+ if (SR_ERR_OK != rc) {
+ SRP_LOG_ERRMSG("Unable to retrieve change iterator");
+ return rc;
+ }
- /* iterate over all changes */
- while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) &&
- (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) {
-
- SRP_LOG_DBGMSG("A change detected");
- if_name = sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx);
- switch (op) {
- case SR_OP_CREATED:
- case SR_OP_MODIFIED:
- op_rc = interface_enable_disable(if_name, new_val->data.bool_val);
- break;
- case SR_OP_DELETED:
- op_rc = interface_enable_disable(if_name, false /* !enable */);
- break;
- default:
- break;
- }
- sr_xpath_recover(&xpath_ctx);
- if (SR_ERR_INVAL_ARG == op_rc) {
- sr_set_error(session, "Invalid interface name.", new_val ? new_val->xpath : old_val->xpath);
- }
- sr_free_val(old_val);
- sr_free_val(new_val);
+ /* iterate over all changes */
+ while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) &&
+ (SR_ERR_OK ==
+ (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) {
+ SRP_LOG_DBGMSG("A change detected");
+ if_name = sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath,
+ "interface", "name", &xpath_ctx);
+ switch (op) {
+ case SR_OP_CREATED:
+ case SR_OP_MODIFIED:
+ op_rc = interface_enable_disable(if_name, new_val->data.bool_val);
+ break;
+ case SR_OP_DELETED:
+ op_rc = interface_enable_disable(if_name, false /* !enable */);
+ break;
+ default:
+ break;
}
- sr_free_change_iter(iter);
+ sr_xpath_recover(&xpath_ctx);
+ if (SR_ERR_INVAL_ARG == op_rc) {
+ sr_set_error(session, "Invalid interface name.",
+ new_val ? new_val->xpath : old_val->xpath);
+ }
+ sr_free_val(old_val);
+ sr_free_val(new_val);
+ }
+ sr_free_change_iter(iter);
- return op_rc;
+ return op_rc;
}
/**
* @brief Add or remove IPv4/IPv6 address to/from an interface.
*/
-static int
-interface_ipv46_config_add_remove(const char *if_name, uint8_t *addr, uint8_t prefix, bool is_ipv6, bool add)
-{
- uint32_t if_index = ~0;
- int rc = 0;
-
- /* get interface index */
- rc = ietf_interface_name2index(if_name, &if_index);
- if (0 != rc) {
- SRP_LOG_ERRMSG("Invalid interface name");
- return SR_ERR_INVAL_ARG;
- }
+static int interface_ipv46_config_add_remove(const char *if_name, uint8_t *addr,
+ uint8_t prefix, bool is_ipv6,
+ bool add) {
+ uint32_t if_index = ~0;
+ int rc = 0;
+
+ /* get interface index */
+ rc = ietf_interface_name2index(if_name, &if_index);
+ if (0 != rc) {
+ SRP_LOG_ERRMSG("Invalid interface name");
+ return SR_ERR_INVAL_ARG;
+ }
- /* add del addr */
- rc = ietf_interface_add_del_addr(if_index, (uint8_t)add, (uint8_t)is_ipv6, 0, prefix, addr);
- if (0 != rc) {
- SRP_LOG_ERRMSG("Error by processing of the sw_interface_set_flags request");
- return SR_ERR_OPERATION_FAILED;
- } else {
- return SR_ERR_OK;
- }
+ /* add del addr */
+ rc = ietf_interface_add_del_addr(if_index, (uint8_t)add, (uint8_t)is_ipv6, 0,
+ prefix, addr);
+ if (0 != rc) {
+ SRP_LOG_ERRMSG("Error by processing of the sw_interface_set_flags request");
+ return SR_ERR_OPERATION_FAILED;
+ } else {
+ return SR_ERR_OK;
+ }
}
-int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx)
-{
- if(dctx == NULL)
- return -1;
+int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx *dctx) {
+ if (dctx == NULL) return -1;
dctx->intfcArray = NULL;
dctx->last_called = false;
@@ -252,66 +245,56 @@ int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx)
dctx->num_ifs = 0;
return 0;
}
-int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx)
-{
- if(dctx == NULL)
- return -1;
-
- if(dctx->intfcArray != NULL)
- {
- free(dctx->intfcArray);
- }
+int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx *dctx) {
+ if (dctx == NULL) return -1;
+
+ if (dctx->intfcArray != NULL) {
+ free(dctx->intfcArray);
+ }
return ietf_initSwInterfaceDumpCTX(dctx);
}
-vapi_error_e
-ietf_sw_interface_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
+vapi_error_e ietf_sw_interface_dump_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_sw_interface_details *reply) {
ietf_sw_interface_dump_ctx *dctx = callback_ctx;
- if (is_last)
- {
- dctx->last_called = true;
+ if (is_last) {
+ dctx->last_called = true;
+ } else {
+ if (dctx->capacity == 0 && dctx->intfcArray == NULL) {
+ dctx->capacity = 10;
+ dctx->intfcArray =
+ (hicnIntfc *)malloc(sizeof(hicnIntfc) * dctx->capacity);
+ }
+ if (dctx->num_ifs >= dctx->capacity - 1) {
+ dctx->capacity += 10;
+ dctx->intfcArray = (hicnIntfc *)realloc(
+ dctx->intfcArray, sizeof(hicnIntfc) * dctx->capacity);
}
- else
- {
- if(dctx->capacity == 0 && dctx->intfcArray == NULL)
- {
- dctx->capacity = 10;
- dctx->intfcArray = (hicnIntfc*)malloc( sizeof(hicnIntfc)*dctx->capacity );
- }
- if(dctx->num_ifs >= dctx->capacity-1)
- {
-
- dctx->capacity += 10;
- dctx->intfcArray = (hicnIntfc*)realloc(dctx->intfcArray, sizeof(hicnIntfc)*dctx->capacity );
- }
- hicnIntfc * thisIntfc = &dctx->intfcArray[dctx->num_ifs];
+ hicnIntfc *thisIntfc = &dctx->intfcArray[dctx->num_ifs];
- thisIntfc->sw_if_index = reply->sw_if_index;
- memcpy(thisIntfc->interface_name, reply->interface_name, VPP_INTFC_NAME_LEN);
- memcpy(thisIntfc->l2_address, reply->l2_address, VPP_MAC_ADDRESS_LEN );
- //thisIntfc->link_speed = reply->link_speed;
+ thisIntfc->sw_if_index = reply->sw_if_index;
+ memcpy(thisIntfc->interface_name, reply->interface_name,
+ VPP_INTFC_NAME_LEN);
+ memcpy(thisIntfc->l2_address, reply->l2_address, VPP_MAC_ADDRESS_LEN);
+ // thisIntfc->link_speed = reply->link_speed;
#define ONE_MEGABIT (uint64_t)1000000
- switch (reply->link_speed << VNET_HW_INTERFACE_FLAG_SPEED_SHIFT)
- {
- default:
- thisIntfc->link_speed = 0;
- break;
- }
+ switch (reply->link_speed << VNET_HW_INTERFACE_FLAG_SPEED_SHIFT) {
+ default:
+ thisIntfc->link_speed = 0;
+ break;
+ }
- thisIntfc->link_mtu = reply->link_mtu;
- thisIntfc->flags = reply->flags;
+ thisIntfc->link_mtu = reply->link_mtu;
+ thisIntfc->flags = reply->flags;
- dctx->num_ifs += 1;
- }
+ dctx->num_ifs += 1;
+ }
return VAPI_OK;
}
-static i32 ietf_interface_name2index(const char *name, u32* if_index)
-{
+static i32 ietf_interface_name2index(const char *name, u32 *if_index) {
ARG_CHECK2(-1, name, if_index);
i32 ret = -1;
@@ -324,14 +307,14 @@ static i32 ietf_interface_name2index(const char *name, u32* if_index)
dump->payload.name_filter_valid = true;
memcpy(&dump->payload.name_filter, name, sizeof(dump->payload.name_filter));
- while (VAPI_EAGAIN == (rv = vapi_sw_interface_dump(g_vapi_ctx_instance, dump, ietf_sw_interface_dump_cb, &dctx)))
+ while (VAPI_EAGAIN ==
+ (rv = vapi_sw_interface_dump(g_vapi_ctx_instance, dump,
+ ietf_sw_interface_dump_cb, &dctx)))
;
int i = 0;
- for (; i < dctx.num_ifs; ++i)
- {
- if (strcmp(dctx.intfcArray[i].interface_name, name) == 0)
- {
+ for (; i < dctx.num_ifs; ++i) {
+ if (strcmp(dctx.intfcArray[i].interface_name, name) == 0) {
*if_index = dctx.intfcArray[i].sw_if_index;
ret = 0;
break;
@@ -342,11 +325,12 @@ static i32 ietf_interface_name2index(const char *name, u32* if_index)
return ret;
}
-i32 ietf_interface_add_del_addr( u32 sw_if_index, u8 is_add, u8 is_ipv6, u8 del_all,
- u8 address_length, u8 address[VPP_IP6_ADDRESS_LEN] )
-{
+i32 ietf_interface_add_del_addr(u32 sw_if_index, u8 is_add, u8 is_ipv6,
+ u8 del_all, u8 address_length,
+ u8 address[VPP_IP6_ADDRESS_LEN]) {
i32 ret = -1;
- vapi_msg_sw_interface_add_del_address *msg = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance);
+ vapi_msg_sw_interface_add_del_address *msg =
+ vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance);
msg->payload.sw_if_index = sw_if_index;
msg->payload.is_add = is_add;
msg->payload.prefix.address.af = is_ipv6 ? ADDRESS_IP6 : ADDRESS_IP4;
@@ -354,7 +338,9 @@ i32 ietf_interface_add_del_addr( u32 sw_if_index, u8 is_add, u8 is_ipv6, u8 del_
msg->payload.prefix.len = address_length;
memcpy(msg->payload.prefix.address.un.ip6, address, VPP_IP6_ADDRESS_LEN);
- if(vapi_sw_interface_add_del_address(g_vapi_ctx_instance,msg,call_sw_interface_add_del_address,NULL)!=VAPI_OK){
+ if (vapi_sw_interface_add_del_address(g_vapi_ctx_instance, msg,
+ call_sw_interface_add_del_address,
+ NULL) != VAPI_OK) {
SRP_LOG_DBGMSG("Operation failed");
return SR_ERR_OPERATION_FAILED;
}
@@ -362,246 +348,274 @@ i32 ietf_interface_add_del_addr( u32 sw_if_index, u8 is_add, u8 is_ipv6, u8 del_
return ret;
}
-i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down)
-{
+i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down) {
i32 ret = -1;
- vapi_msg_sw_interface_set_flags *msg = vapi_alloc_sw_interface_set_flags(g_vapi_ctx_instance);
+ vapi_msg_sw_interface_set_flags *msg =
+ vapi_alloc_sw_interface_set_flags(g_vapi_ctx_instance);
msg->payload.sw_if_index = sw_if_index;
- msg->payload.flags = admin_up_down? IF_STATUS_API_FLAG_ADMIN_UP : 0;
+ msg->payload.flags = admin_up_down ? IF_STATUS_API_FLAG_ADMIN_UP : 0;
- if(vapi_sw_interface_set_flags(g_vapi_ctx_instance,msg,call_sw_interface_set_flags,NULL)!=VAPI_OK){
+ if (vapi_sw_interface_set_flags(g_vapi_ctx_instance, msg,
+ call_sw_interface_set_flags,
+ NULL) != VAPI_OK) {
SRP_LOG_DBGMSG("Operation failed");
return SR_ERR_OPERATION_FAILED;
}
-
return ret;
}
-
/**
* @brief Modify existing IPv4/IPv6 config on an interface.
*/
-static int
-interface_ipv46_config_modify(sr_session_ctx_t *session, const char *if_name,
- sr_val_t *old_val, sr_val_t *new_val, bool is_ipv6)
-{
- sr_xpath_ctx_t xpath_ctx = { 0, };
- char *addr_str = NULL;
- uint8_t addr[16] = { 0, };
- uint8_t prefix = 0;
- int rc = SR_ERR_OK;
-
- SRP_LOG_DBGMSG("Updating IP config on interface");
-
- /* get old config to be deleted */
- if (SR_UINT8_T == old_val->type) {
- prefix = old_val->data.uint8_val;
- } else if (SR_STRING_T == old_val->type) {
- prefix = netmask_to_prefix(old_val->data.string_val);
- } else {
- return SR_ERR_INVAL_ARG;
- }
- addr_str = sr_xpath_key_value((char*)old_val->xpath, "address", "ip", &xpath_ctx);
- ip_addr_str_to_binary(addr_str, addr, is_ipv6);
- sr_xpath_recover(&xpath_ctx);
-
- /* delete old IP config */
- rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, false /* remove */);
- if (SR_ERR_OK != rc) {
- SRP_LOG_ERRMSG("Unable to remove old IP address config");
- return rc;
- }
-
- /* update the config with the new value */
- if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) {
- prefix = new_val->data.uint8_val;
- } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) {
- prefix = netmask_to_prefix(new_val->data.string_val);
- }
+static int interface_ipv46_config_modify(sr_session_ctx_t *session,
+ const char *if_name, sr_val_t *old_val,
+ sr_val_t *new_val, bool is_ipv6) {
+ sr_xpath_ctx_t xpath_ctx = {
+ 0,
+ };
+ char *addr_str = NULL;
+ uint8_t addr[16] = {
+ 0,
+ };
+ uint8_t prefix = 0;
+ int rc = SR_ERR_OK;
+
+ SRP_LOG_DBGMSG("Updating IP config on interface");
+
+ /* get old config to be deleted */
+ if (SR_UINT8_T == old_val->type) {
+ prefix = old_val->data.uint8_val;
+ } else if (SR_STRING_T == old_val->type) {
+ prefix = netmask_to_prefix(old_val->data.string_val);
+ } else {
+ return SR_ERR_INVAL_ARG;
+ }
+ addr_str =
+ sr_xpath_key_value((char *)old_val->xpath, "address", "ip", &xpath_ctx);
+ ip_addr_str_to_binary(addr_str, addr, is_ipv6);
+ sr_xpath_recover(&xpath_ctx);
+
+ /* delete old IP config */
+ rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6,
+ false /* remove */);
+ if (SR_ERR_OK != rc) {
+ SRP_LOG_ERRMSG("Unable to remove old IP address config");
+ return rc;
+ }
- /* set new IP config */
- rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, true /* add */);
- if (SR_ERR_OK != rc) {
- SRP_LOG_ERRMSG("Unable to remove old IP address config");
- return rc;
- }
+ /* update the config with the new value */
+ if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) {
+ prefix = new_val->data.uint8_val;
+ } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) {
+ prefix = netmask_to_prefix(new_val->data.string_val);
+ }
+ /* set new IP config */
+ rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6,
+ true /* add */);
+ if (SR_ERR_OK != rc) {
+ SRP_LOG_ERRMSG("Unable to remove old IP address config");
return rc;
+ }
+
+ return rc;
}
/**
- * @brief Callback to be called by any config change in subtrees "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address"
- * or "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address".
+ * @brief Callback to be called by any config change in subtrees
+ * "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address" or
+ * "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address".
*/
-static int
-ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event,
- uint32_t request_id, void *private_data)
-{
- sr_change_iter_t *iter = NULL;
- sr_change_oper_t op = SR_OP_CREATED;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
- sr_xpath_ctx_t xpath_ctx = { 0 };
- bool is_ipv6 = false, has_addr = false, has_prefix = false;
- uint8_t addr[16] = { 0, };
- uint8_t prefix = 0;
- char *node_name = NULL, *if_name = NULL;
- int rc = SR_ERR_OK, op_rc = SR_ERR_OK;
-
- /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */
- if (SR_EV_DONE == event) {
- return SR_ERR_OK;
- }
+static int ietf_interface_ipv46_address_change_cb(
+ sr_session_ctx_t *session, const char *module_name, const char *xpath,
+ sr_event_t event, uint32_t request_id, void *private_data) {
+ sr_change_iter_t *iter = NULL;
+ sr_change_oper_t op = SR_OP_CREATED;
+ sr_val_t *old_val = NULL;
+ sr_val_t *new_val = NULL;
+ sr_xpath_ctx_t xpath_ctx = {0};
+ bool is_ipv6 = false, has_addr = false, has_prefix = false;
+ uint8_t addr[16] = {
+ 0,
+ };
+ uint8_t prefix = 0;
+ char *node_name = NULL, *if_name = NULL;
+ int rc = SR_ERR_OK, op_rc = SR_ERR_OK;
+
+ /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY,
+ * SR_EV_ABORT */
+ if (SR_EV_DONE == event) {
+ return SR_ERR_OK;
+ }
- /* check whether we are handling ipv4 or ipv6 config */
- node_name = sr_xpath_node_idx((char*)xpath, 2, &xpath_ctx);
- if (NULL != node_name && 0 == strcmp(node_name, "ipv6")) {
- is_ipv6 = true;
- }
- sr_xpath_recover(&xpath_ctx);
+ /* check whether we are handling ipv4 or ipv6 config */
+ node_name = sr_xpath_node_idx((char *)xpath, 2, &xpath_ctx);
+ if (NULL != node_name && 0 == strcmp(node_name, "ipv6")) {
+ is_ipv6 = true;
+ }
+ sr_xpath_recover(&xpath_ctx);
- /* get changes iterator */
- rc = sr_get_changes_iter(session, xpath, &iter);
- if (SR_ERR_OK != rc) {
- // SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc));
- return rc;
- }
+ /* get changes iterator */
+ rc = sr_get_changes_iter(session, xpath, &iter);
+ if (SR_ERR_OK != rc) {
+ // SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc));
+ return rc;
+ }
- /* iterate over all changes */
- while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) &&
- (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) {
-
- if_name = strdup(sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx));
- sr_xpath_recover(&xpath_ctx);
-
- switch (op) {
- case SR_OP_CREATED:
- if (SR_LIST_T == new_val->type) {
- /* create on list item - reset state vars */
- has_addr = has_prefix = false;
- } else {
- if (sr_xpath_node_name_eq(new_val->xpath, "ip")) {
- ip_addr_str_to_binary(new_val->data.string_val, addr, is_ipv6);
- has_addr = true;
- } else if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) {
- prefix = new_val->data.uint8_val;
- has_prefix = true;
- } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) {
- prefix = netmask_to_prefix(new_val->data.string_val);
- has_prefix = true;
- }
- if (has_addr && has_prefix) {
- op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, true /* add */);
- }
- }
- break;
- case SR_OP_MODIFIED:
- op_rc = interface_ipv46_config_modify(session, if_name, old_val, new_val, is_ipv6);
- break;
- case SR_OP_DELETED:
- if (SR_LIST_T == old_val->type) {
- /* delete on list item - reset state vars */
- has_addr = has_prefix = false;
- } else {
- if (sr_xpath_node_name_eq(old_val->xpath, "ip")) {
- ip_addr_str_to_binary(old_val->data.string_val, addr, is_ipv6);
- has_addr = true;
- } else if (sr_xpath_node_name_eq(old_val->xpath, "prefix-length")) {
- prefix = old_val->data.uint8_val;
- has_prefix = true;
- } else if (sr_xpath_node_name_eq(old_val->xpath, "netmask")) {
- prefix = netmask_to_prefix(old_val->data.string_val);
- has_prefix = true;
- }
- if (has_addr && has_prefix) {
- op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, false /* !add */);
- }
- }
- break;
- default:
- break;
+ /* iterate over all changes */
+ while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) &&
+ (SR_ERR_OK ==
+ (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) {
+ if_name =
+ strdup(sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath,
+ "interface", "name", &xpath_ctx));
+ sr_xpath_recover(&xpath_ctx);
+
+ switch (op) {
+ case SR_OP_CREATED:
+ if (SR_LIST_T == new_val->type) {
+ /* create on list item - reset state vars */
+ has_addr = has_prefix = false;
+ } else {
+ if (sr_xpath_node_name_eq(new_val->xpath, "ip")) {
+ ip_addr_str_to_binary(new_val->data.string_val, addr, is_ipv6);
+ has_addr = true;
+ } else if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) {
+ prefix = new_val->data.uint8_val;
+ has_prefix = true;
+ } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) {
+ prefix = netmask_to_prefix(new_val->data.string_val);
+ has_prefix = true;
+ }
+ if (has_addr && has_prefix) {
+ op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix,
+ is_ipv6, true /* add */);
+ }
}
- if (SR_ERR_INVAL_ARG == op_rc) {
- sr_set_error(session, "Invalid interface name.", new_val ? new_val->xpath : old_val->xpath);
+ break;
+ case SR_OP_MODIFIED:
+ op_rc = interface_ipv46_config_modify(session, if_name, old_val,
+ new_val, is_ipv6);
+ break;
+ case SR_OP_DELETED:
+ if (SR_LIST_T == old_val->type) {
+ /* delete on list item - reset state vars */
+ has_addr = has_prefix = false;
+ } else {
+ if (sr_xpath_node_name_eq(old_val->xpath, "ip")) {
+ ip_addr_str_to_binary(old_val->data.string_val, addr, is_ipv6);
+ has_addr = true;
+ } else if (sr_xpath_node_name_eq(old_val->xpath, "prefix-length")) {
+ prefix = old_val->data.uint8_val;
+ has_prefix = true;
+ } else if (sr_xpath_node_name_eq(old_val->xpath, "netmask")) {
+ prefix = netmask_to_prefix(old_val->data.string_val);
+ has_prefix = true;
+ }
+ if (has_addr && has_prefix) {
+ op_rc = interface_ipv46_config_add_remove(
+ if_name, addr, prefix, is_ipv6, false /* !add */);
+ }
}
- free(if_name);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ break;
+ default:
+ break;
+ }
+ if (SR_ERR_INVAL_ARG == op_rc) {
+ sr_set_error(session, "Invalid interface name.",
+ new_val ? new_val->xpath : old_val->xpath);
}
- sr_free_change_iter(iter);
+ free(if_name);
+ sr_free_val(old_val);
+ sr_free_val(new_val);
+ }
+ sr_free_change_iter(iter);
- return op_rc;
+ return op_rc;
}
/**
- * @brief Callback to be called by any config change under "/ietf-interfaces:interfaces-state/interface" path.
- * Does not provide any functionality, needed just to cover not supported config leaves.
+ * @brief Callback to be called by any config change under
+ * "/ietf-interfaces:interfaces-state/interface" path. Does not provide any
+ * functionality, needed just to cover not supported config leaves.
*/
-static int
-ietf_interface_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event,
- uint32_t request_id, void *private_data)
-{
- return SR_ERR_OK;
+static int ietf_interface_change_cb(sr_session_ctx_t *session,
+ const char *module_name, const char *xpath,
+ sr_event_t event, uint32_t request_id,
+ void *private_data) {
+ return SR_ERR_OK;
}
-
int ietf_subscribe_events(sr_session_ctx_t *session,
- sr_subscription_ctx_t **subscription){
-
- int rc = SR_ERR_OK;
- SRP_LOG_DBGMSG("Subscriging ietf.");
-
- //
- rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface", ietf_interface_change_cb,
- NULL,
- 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
-
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface\n");
- goto error;
- }
-
- rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/enabled", ietf_interface_enable_disable_cb,
- NULL,
- 100, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/enabled\n");
- goto error;
- }
-
- //rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", ietf_interface_ipv46_address_change_cb,
- rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces", ietf_interface_ipv46_address_change_cb,
- NULL,
- 99, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
-
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address\n");
- goto error;
- }
+ sr_subscription_ctx_t **subscription) {
+ int rc = SR_ERR_OK;
+ SRP_LOG_DBGMSG("Subscriging ietf.");
+
+ //
+ rc = sr_module_change_subscribe(
+ session, "ietf-interfaces", "/ietf-interfaces:interfaces/interface",
+ ietf_interface_change_cb, NULL, 0,
+ SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
+
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG(
+ "Problem in subscription /ietf-interfaces:interfaces/interface\n");
+ goto error;
+ }
- //rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", ietf_interface_ipv46_address_change_cb,
- // NULL,
- // 98, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
+ rc = sr_module_change_subscribe(
+ session, "ietf-interfaces",
+ "/ietf-interfaces:interfaces/interface/enabled",
+ ietf_interface_enable_disable_cb, NULL, 100,
+ SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG(
+ "Problem in subscription "
+ "/ietf-interfaces:interfaces/interface/enabled\n");
+ goto error;
+ }
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address\n");
- goto error;
- }
+ // rc = sr_module_change_subscribe(session,
+ // "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address",
+ // ietf_interface_ipv46_address_change_cb,
+ rc = sr_module_change_subscribe(
+ session, "ietf-interfaces", "/ietf-interfaces:interfaces",
+ ietf_interface_ipv46_address_change_cb, NULL, 99,
+ SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
+
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG(
+ "Problem in subscription "
+ "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address\n");
+ goto error;
+ }
- /* rc = sr_dp_get_items_subscribe(session, "/ietf-interfaces:interfaces-state", ietf_interface_state_cb,
- NULL, SR_SUBSCR_CTX_REUSE,
- subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces-state\n");
+ // rc = sr_module_change_subscribe(session,
+ // "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address",
+ // ietf_interface_ipv46_address_change_cb,
+ // NULL,
+ // 98, SR_SUBSCR_CTX_REUSE |
+ // SR_SUBSCR_ENABLED, subscription);
+
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG(
+ "Problem in subscription "
+ "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address\n");
goto error;
- }*/
+ }
+ /* rc = sr_dp_get_items_subscribe(session,
+ "/ietf-interfaces:interfaces-state", ietf_interface_state_cb, NULL,
+ SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription
+ /ietf-interfaces:interfaces-state\n"); goto error;
+ }*/
SRP_LOG_INFMSG("ietf initialized successfully.");
return SR_ERR_OK;
- error:
+error:
SRP_LOG_ERRMSG("Error by initialization of the ietf.");
return rc;
}
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h
index 0f6c7f8b4..cf5430464 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 HUACHENTEL and/or its affiliates.
+ * Copyright (c) 2021 HUACHENTEL and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,5 +19,4 @@
int ietf_subscribe_events(sr_session_ctx_t *session,
sr_subscription_ctx_t **subscription);
-
#endif /* __IETF_INTERFACE_H__ */
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c
index 63685e10a..f1b804267 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h
index 62fb15340..866eafd5e 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h
@@ -1,21 +1,22 @@
/*
-* Copyright (c) 2019 Cisco and/or its affiliates.
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at:
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * 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 hicn_model.h
- * @brief This file contains main calls for hICN events coresponding to the hICN yang models
+ * @brief This file contains main calls for hICN events coresponding to the hICN
+ * yang models
*/
#ifndef __IETF_HICN_H__
@@ -55,12 +56,10 @@
/**
* @brief enumeration for the locks
*/
-enum locks_name {lstate, lstrategy, lstrategies, lroute, lfaces};
-
+enum locks_name { lstate, lstrategy, lstrategies, lroute, lfaces };
// It is a coarse grain approach later can be changed to fine grained
-
/**
* @brief This indicates the number of leaves for the hICN state
*/
@@ -78,61 +77,60 @@ enum locks_name {lstate, lstrategy, lstrategies, lroute, lfaces};
*/
#define MAX_FACE_POOL 100
/**
- * @brief This indicates the maximum routes which can be read as operational data
+ * @brief This indicates the maximum routes which can be read as operational
+ * data
*/
#define MAX_ROUTE_POOL 100
/**
* @brief This indicates the number of leaves for faces
*/
-#define FACES_CHILDREN 9 /*this is the number of children of each leave in face except the key*/
+#define FACES_CHILDREN \
+ 9 /*this is the number of children of each leave in face except the key*/
/**
* @brief This indicates the number of leaves for routes
*/
-#define ROUTES_CHILDREN 2 /*this is the number of children of each leave in face except the key*/
-
-typedef struct __attribute__ ((__packed__)) {
- int32_t retval;
- uint64_t pkts_processed;
- uint64_t pkts_interest_count;
- uint64_t pkts_data_count;
- uint64_t pkts_from_cache_count;
- uint64_t pkts_no_pit_count;
- uint64_t pit_expired_count;
- uint64_t cs_expired_count;
- uint64_t cs_lru_count;
- uint64_t pkts_drop_no_buf;
- uint64_t interests_aggregated;
- uint64_t interests_retx;
- uint64_t interests_hash_collision;
- uint64_t pit_entries_count;
- uint64_t cs_entries_count;
- uint64_t cs_entries_ntw_count;
+#define ROUTES_CHILDREN \
+ 2 /*this is the number of children of each leave in face except the key*/
+
+typedef struct __attribute__((__packed__)) {
+ int32_t retval;
+ uint64_t pkts_processed;
+ uint64_t pkts_interest_count;
+ uint64_t pkts_data_count;
+ uint64_t pkts_from_cache_count;
+ uint64_t pkts_no_pit_count;
+ uint64_t pit_expired_count;
+ uint64_t cs_expired_count;
+ uint64_t cs_lru_count;
+ uint64_t pkts_drop_no_buf;
+ uint64_t interests_aggregated;
+ uint64_t interests_retx;
+ uint64_t interests_hash_collision;
+ uint64_t pit_entries_count;
+ uint64_t cs_entries_count;
+ uint64_t cs_entries_ntw_count;
} hicn_state_t;
-
-typedef struct __attribute__ ((__packed__)) {
-
- uint8_t n_strategies;
- uint32_t strategy_id[256];
- int32_t retval;
+typedef struct __attribute__((__packed__)) {
+ uint8_t n_strategies;
+ uint32_t strategy_id[256];
+ int32_t retval;
} hicn_strategies_t;
-
-typedef struct __attribute__ ((__packed__)) {
- uint32_t faceid;
- uint32_t intfc;
- uint64_t irx_packets;
- uint64_t irx_bytes;
- uint64_t itx_packets;
- uint64_t itx_bytes;
- uint64_t drx_packets;
- uint64_t drx_bytes;
- uint64_t dtx_packets;
- uint64_t dtx_bytes;
+typedef struct __attribute__((__packed__)) {
+ uint32_t faceid;
+ uint32_t intfc;
+ uint64_t irx_packets;
+ uint64_t irx_bytes;
+ uint64_t itx_packets;
+ uint64_t itx_bytes;
+ uint64_t drx_packets;
+ uint64_t drx_bytes;
+ uint64_t dtx_packets;
+ uint64_t dtx_bytes;
} hicn_face_inf_t;
-
-typedef struct __attribute__ ((__packed__)) {
+typedef struct __attribute__((__packed__)) {
u32 route_id;
vapi_type_prefix prefix;
u32 faceids[5];
@@ -143,29 +141,27 @@ typedef struct __attribute__ ((__packed__)) {
/**
* @brief This is the link list to maintain the statistics of the faces
*/
-struct hicn_faces_s{
- hicn_face_inf_t face;
- struct hicn_faces_s * next;
+struct hicn_faces_s {
+ hicn_face_inf_t face;
+ struct hicn_faces_s *next;
};
-
-typedef struct __attribute__ ((__packed__)) {
- uint32_t nface;
- struct hicn_faces_s * next;
+typedef struct __attribute__((__packed__)) {
+ uint32_t nface;
+ struct hicn_faces_s *next;
} hicn_faces_t;
/**
* @brief This is the link list to maintain the route informations
*/
-struct hicn_routes_s{
- hicn_route_inf_t route;
- struct hicn_routes_s * next;
+struct hicn_routes_s {
+ hicn_route_inf_t route;
+ struct hicn_routes_s *next;
};
-
-typedef struct __attribute__ ((__packed__)) {
- uint32_t nroute;
- struct hicn_routes_s * next;
+typedef struct __attribute__((__packed__)) {
+ uint32_t nroute;
+ struct hicn_routes_s *next;
} hicn_routes_t;
/**
@@ -173,6 +169,6 @@ typedef struct __attribute__ ((__packed__)) {
* as well as operational data
*/
int hicn_subscribe_events(sr_session_ctx_t *session,
- sr_subscription_ctx_t **subscription);
+ sr_subscription_ctx_t **subscription);
#endif /* __IETF_HICN_H__ */
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c
index d27ae6492..c3c225ef7 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c
@@ -1,21 +1,16 @@
-#include"tlock.h"
+#include "tlock.h"
-
-void ticket_init ( int Lock_Number , long int init ){
-
-//__atomic_store( &En[Lock_Number] , &init , __ATOMIC_SEQ_CST );
-//__atomic_store( &De[Lock_Number] , &init , __ATOMIC_SEQ_CST );
-En[Lock_Number]=init;
-De[Lock_Number]=init;
+void ticket_init(int Lock_Number, long int init) {
+ //__atomic_store( &En[Lock_Number] , &init , __ATOMIC_SEQ_CST );
+ //__atomic_store( &De[Lock_Number] , &init , __ATOMIC_SEQ_CST );
+ En[Lock_Number] = init;
+ De[Lock_Number] = init;
}
-void tlock(int Lock_Number ){
-
- int my_ticket = __sync_fetch_and_add(&En[Lock_Number] , 1 );
- while ( my_ticket != De[ Lock_Number ] ) {};
-
+void tlock(int Lock_Number) {
+ int my_ticket = __sync_fetch_and_add(&En[Lock_Number], 1);
+ while (my_ticket != De[Lock_Number]) {
+ };
}
-void tunlock(int Lock_Number ){
-De[Lock_Number]++;
-}
+void tunlock(int Lock_Number) { De[Lock_Number]++; }
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h
index a871705a3..be3342d3f 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,8 +13,6 @@
* limitations under the License.
*/
-
-
/**
* @file tlock.h
* @brief This file contains ticket lock APIs.
@@ -23,42 +21,40 @@
#ifndef __TLOCK_H__
#define __TLOCK_H__
-
/**
* @brief limit the number of locks: it shoud be matched with the
* number of hicn-state leaves
*/
-#define MAX_LOCK_SIZE 5
+#define MAX_LOCK_SIZE 5
/**
* @brief Ticket lock counters
*/
-volatile long int En[MAX_LOCK_SIZE] ;
+volatile long int En[MAX_LOCK_SIZE];
/**
* @brief Ticket lock counters
*/
-volatile long int De[MAX_LOCK_SIZE] ;
-
+volatile long int De[MAX_LOCK_SIZE];
/**
* @brief This function initialize the ticket lock
* @param Lock_Number describes the number of locks need to be initialized
* @param init describes the init number
*/
-void ticket_init ( int Lock_Number , long int init );
+void ticket_init(int Lock_Number, long int init);
/**
* @brief this function acquire the lock
* Description of what the function does. This part may refer to the parameters
* @param Lock_Number pass the lock
*/
-void tlock(int Lock_Number );
+void tlock(int Lock_Number);
/**
* @briefthis function release the lock
* @param Lock_Number lock number
*/
-void tunlock(int Lock_Number );
+void tunlock(int Lock_Number);
#endif /* __IETF_HICN_H__ */ \ No newline at end of file
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c b/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c
index f7b92c3c5..d3e47c970 100755..100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/test/vapi-test/test.c
@@ -5,177 +5,149 @@
#include <signal.h>
#include <inttypes.h>
-#include<vapi/hicn.api.vapi.h>
-
+#include <vapi/hicn.api.vapi.h>
DEFINE_VAPI_MSG_IDS_HICN_API_JSON;
vapi_ctx_t g_vapi_ctx_instance;
-
#define APP_NAME "test_hicn_plugin"
#define MAX_OUTSTANDING_REQUESTS 4
#define RESPONSE_QUEUE_SIZE 2
vapi_ctx_t g_vapi_ctx_instance = NULL;
-
-void usage(){
- printf("choose the test [route_add [4|6], punt_add [4|6], face_add [4|6], route_dump, face_dump]\n");
+void usage() {
+ printf(
+ "choose the test [route_add [4|6], punt_add [4|6], face_add [4|6], "
+ "route_dump, face_dump]\n");
}
-static vapi_error_e call_hicn_api_punting_add(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_punting_add_reply *reply){
-if(!reply->retval){
- printf("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
+static vapi_error_e call_hicn_api_punting_add(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_punting_add_reply *reply) {
+ if (!reply->retval) {
+ printf("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
}
-static vapi_error_e call_hicn_api_face_ip_add(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_ip_add_reply *reply){
-if(!reply->retval){
- printf("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-
+static vapi_error_e call_hicn_api_face_ip_add(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_ip_add_reply *reply) {
+ if (!reply->retval) {
+ printf("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
}
-static vapi_error_e call_hicn_api_route_nhops_add(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_route_nhops_add_reply *reply){
-if(!reply->retval){
- printf("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
+static vapi_error_e call_hicn_api_route_nhops_add(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_route_nhops_add_reply *reply) {
+ if (!reply->retval) {
+ printf("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
}
-static vapi_error_e
-hicn_api_routes_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_routes_details *reply)
-{
-
- char buf[20];
- if (reply!=NULL){
- memset(buf, 0x00, 20);
- if (reply->prefix.address.af==ADDRESS_IP4){
- struct sockaddr_in sa;
- memcpy(&sa.sin_addr.s_addr, reply->prefix.address.un.ip4, 4);
- inet_ntop(AF_INET, &(sa.sin_addr.s_addr), buf, INET_ADDRSTRLEN);
- printf("Prefix:%s\n",buf);
- }else{
- struct sockaddr_in6 sa;
- memcpy(&sa.sin6_addr,reply->prefix.address.un.ip6,6);
- inet_ntop(AF_INET6, &(sa.sin6_addr), buf, INET6_ADDRSTRLEN);
- printf("Prefix:%s\n",buf);
- }
- }else
- {
- printf("---------Routes------- \n");
- }
- return 0;
-
+static vapi_error_e hicn_api_routes_dump_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_routes_details *reply) {
+ char buf[20];
+ if (reply != NULL) {
+ memset(buf, 0x00, 20);
+ if (reply->prefix.address.af == ADDRESS_IP4) {
+ struct sockaddr_in sa;
+ memcpy(&sa.sin_addr.s_addr, reply->prefix.address.un.ip4, 4);
+ inet_ntop(AF_INET, &(sa.sin_addr.s_addr), buf, INET_ADDRSTRLEN);
+ printf("Prefix:%s\n", buf);
+ } else {
+ struct sockaddr_in6 sa;
+ memcpy(&sa.sin6_addr, reply->prefix.address.un.ip6, 6);
+ inet_ntop(AF_INET6, &(sa.sin6_addr), buf, INET6_ADDRSTRLEN);
+ printf("Prefix:%s\n", buf);
+ }
+ } else {
+ printf("---------Routes------- \n");
+ }
+ return 0;
}
-
-
-static vapi_error_e
-hicn_api_face_stats_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_face_stats_details *reply)
-{
- if (reply!=NULL){
-
- printf("face_id:%d \n", reply->faceid);
- printf("irx_packets:%" PRId64 "\n", reply->irx_packets);
- printf("irx_bytes:%" PRId64 "\n", reply->irx_bytes);
- printf("itx_packets:%" PRId64 "\n", reply->itx_packets);
- printf("itx_bytes:%" PRId64 "\n", reply->itx_bytes);
- printf("drx_packets:%" PRId64 "\n", reply->drx_packets);
- printf("drx_bytes:%" PRId64 "\n", reply->drx_bytes);
- printf("dtx_packets:%" PRId64 "\n", reply->dtx_packets);
- printf("dtx_bytes:%" PRId64 "\n", reply->dtx_bytes);
-
- }else
- {
- printf("---------Facees------- \n");
- }
- return 0;
+static vapi_error_e hicn_api_face_stats_dump_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_stats_details *reply) {
+ if (reply != NULL) {
+ printf("face_id:%d \n", reply->faceid);
+ printf("irx_packets:%" PRId64 "\n", reply->irx_packets);
+ printf("irx_bytes:%" PRId64 "\n", reply->irx_bytes);
+ printf("itx_packets:%" PRId64 "\n", reply->itx_packets);
+ printf("itx_bytes:%" PRId64 "\n", reply->itx_bytes);
+ printf("drx_packets:%" PRId64 "\n", reply->drx_packets);
+ printf("drx_bytes:%" PRId64 "\n", reply->drx_bytes);
+ printf("dtx_packets:%" PRId64 "\n", reply->dtx_packets);
+ printf("dtx_bytes:%" PRId64 "\n", reply->dtx_bytes);
+
+ } else {
+ printf("---------Facees------- \n");
+ }
+ return 0;
}
-
-int hicn_connect_vpp()
-{
-
- if (g_vapi_ctx_instance == NULL)
- {
- vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance);
- rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL, MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE, VAPI_MODE_BLOCKING, true);
- if (rv != VAPI_OK)
- {
- vapi_ctx_free(g_vapi_ctx_instance);
- return -1;
- }
- }
- else
- {
- }
- return 0;
+int hicn_connect_vpp() {
+ if (g_vapi_ctx_instance == NULL) {
+ vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance);
+ rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL,
+ MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE,
+ VAPI_MODE_BLOCKING, true);
+ if (rv != VAPI_OK) {
+ vapi_ctx_free(g_vapi_ctx_instance);
+ return -1;
+ }
+ } else {
+ }
+ return 0;
}
-int hicn_disconnect_vpp()
-{
- if (NULL != g_vapi_ctx_instance)
- {
- vapi_disconnect(g_vapi_ctx_instance);
- vapi_ctx_free(g_vapi_ctx_instance);
- g_vapi_ctx_instance = NULL;
- }
- return 0;
+int hicn_disconnect_vpp() {
+ if (NULL != g_vapi_ctx_instance) {
+ vapi_disconnect(g_vapi_ctx_instance);
+ vapi_ctx_free(g_vapi_ctx_instance);
+ g_vapi_ctx_instance = NULL;
+ }
+ return 0;
}
-int main(int argc, char **argv)
-{
-
- if (argc<2){
+int main(int argc, char **argv) {
+ if (argc < 2) {
usage();
return 1;
}
- /* connect to vpp */
+ /* connect to vpp */
int rc = hicn_connect_vpp();
- if (-1 == rc){
+ if (-1 == rc) {
perror("vpp connect error");
return -1;
}
- if (!strcmp(argv[1],"route_add")){
+ if (!strcmp(argv[1], "route_add")) {
vapi_msg_hicn_api_route_nhops_add *msg;
msg = vapi_alloc_hicn_api_route_nhops_add(g_vapi_ctx_instance);
- if (!strcmp(argv[2],"4")){
+ if (!strcmp(argv[2], "4")) {
struct sockaddr_in sa;
- inet_pton(AF_INET, "192.168.10.10", &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&msg->payload.prefix.address.un.ip4[0],tmp,4);
+ inet_pton(AF_INET, "192.168.10.10", &(sa.sin_addr));
+ unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr;
+ memcpy(&msg->payload.prefix.address.un.ip4[0], tmp, 4);
msg->payload.prefix.address.af = ADDRESS_IP4;
- }else{
+ } else {
void *dst = malloc(sizeof(struct in6_addr));
inet_pton(AF_INET6, "2001::1", dst);
- unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&msg->payload.prefix.address.un.ip6[0],tmp,16);
+ unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr;
+ memcpy(&msg->payload.prefix.address.un.ip6[0], tmp, 16);
msg->payload.prefix.address.af = ADDRESS_IP6;
}
@@ -189,97 +161,93 @@ int main(int argc, char **argv)
msg->payload.face_ids[6] = 0;
msg->payload.n_faces = 1;
- if(vapi_hicn_api_route_nhops_add(g_vapi_ctx_instance,msg,call_hicn_api_route_nhops_add,NULL)!=VAPI_OK){
+ if (vapi_hicn_api_route_nhops_add(g_vapi_ctx_instance, msg,
+ call_hicn_api_route_nhops_add,
+ NULL) != VAPI_OK) {
perror("Operation failed");
return -1;
}
- }else if (!strcmp(argv[1],"face_add")){
-
+ } else if (!strcmp(argv[1], "face_add")) {
vapi_msg_hicn_api_face_ip_add *fmsg;
fmsg = vapi_alloc_hicn_api_face_ip_add(g_vapi_ctx_instance);
-
- if (!strcmp(argv[2],"4")){
+ if (!strcmp(argv[2], "4")) {
struct sockaddr_in sa;
- inet_pton(AF_INET, "192.168.50.19", &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&fmsg->payload.face.local_addr.un.ip4[0],tmp,4);
+ inet_pton(AF_INET, "192.168.50.19", &(sa.sin_addr));
+ unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr;
+ memcpy(&fmsg->payload.face.local_addr.un.ip4[0], tmp, 4);
fmsg->payload.face.local_addr.af = ADDRESS_IP4;
-
- inet_pton(AF_INET, "192.168.60.10", &(sa.sin_addr));
+ inet_pton(AF_INET, "192.168.60.10", &(sa.sin_addr));
tmp = (unsigned char *)&sa.sin_addr.s_addr;
- memcpy(&fmsg->payload.face.remote_addr.un.ip4[0],tmp,4);
+ memcpy(&fmsg->payload.face.remote_addr.un.ip4[0], tmp, 4);
fmsg->payload.face.remote_addr.af = ADDRESS_IP4;
- }else{
-
+ } else {
void *dst = malloc(sizeof(struct in6_addr));
inet_pton(AF_INET6, "2001::1", dst);
- unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&fmsg->payload.face.local_addr.un.ip6[0],tmp,16);
+ unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr;
+ memcpy(&fmsg->payload.face.local_addr.un.ip6[0], tmp, 16);
fmsg->payload.face.local_addr.af = ADDRESS_IP6;
-
inet_pton(AF_INET6, "3001::1", dst);
- tmp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&fmsg->payload.face.remote_addr.un.ip6[0],tmp,16);
+ tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr;
+ memcpy(&fmsg->payload.face.remote_addr.un.ip6[0], tmp, 16);
fmsg->payload.face.remote_addr.af = ADDRESS_IP6;
}
- fmsg->payload.face.swif = 0; // This is the idx number of interface
+ fmsg->payload.face.swif = 0; // This is the idx number of interface
- if(vapi_hicn_api_face_ip_add(g_vapi_ctx_instance,fmsg,call_hicn_api_face_ip_add,NULL)!=VAPI_OK){
- perror("Operation failed");
- return -1;
+ if (vapi_hicn_api_face_ip_add(g_vapi_ctx_instance, fmsg,
+ call_hicn_api_face_ip_add, NULL) != VAPI_OK) {
+ perror("Operation failed");
+ return -1;
}
- }else if (!strcmp(argv[1],"route_dump")){
- // routes dump
+ } else if (!strcmp(argv[1], "route_dump")) {
+ // routes dump
vapi_msg_hicn_api_routes_dump *rmsg;
rmsg = vapi_alloc_hicn_api_routes_dump(g_vapi_ctx_instance);
- vapi_hicn_api_routes_dump(g_vapi_ctx_instance, rmsg, hicn_api_routes_dump_cb, NULL);
+ vapi_hicn_api_routes_dump(g_vapi_ctx_instance, rmsg,
+ hicn_api_routes_dump_cb, NULL);
- }else if (!strcmp(argv[1],"face_dump")){
- // faces dump
+ } else if (!strcmp(argv[1], "face_dump")) {
+ // faces dump
vapi_msg_hicn_api_face_stats_dump *fmsg;
fmsg = vapi_alloc_hicn_api_face_stats_dump(g_vapi_ctx_instance);
- vapi_hicn_api_face_stats_dump(g_vapi_ctx_instance, fmsg, hicn_api_face_stats_dump_cb, NULL);
- }else if (!strcmp(argv[1],"punt_add")){
-
+ vapi_hicn_api_face_stats_dump(g_vapi_ctx_instance, fmsg,
+ hicn_api_face_stats_dump_cb, NULL);
+ } else if (!strcmp(argv[1], "punt_add")) {
vapi_msg_hicn_api_punting_add *pmsg;
pmsg = vapi_alloc_hicn_api_punting_add(g_vapi_ctx_instance);
- pmsg->payload.type=IP_PUNT;
-
- if(!strcmp(argv[2],"4")){
+ pmsg->payload.type = IP_PUNT;
+ if (!strcmp(argv[2], "4")) {
struct sockaddr_in sa;
// store this IP address in sa:
- inet_pton(AF_INET, "192.168.10.20", &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&pmsg->payload.rule.ip.prefix.address.un.ip4[0],tmp,4);
+ inet_pton(AF_INET, "192.168.10.20", &(sa.sin_addr));
+ unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr;
+ memcpy(&pmsg->payload.rule.ip.prefix.address.un.ip4[0], tmp, 4);
pmsg->payload.rule.ip.prefix.address.af = ADDRESS_IP4;
-
- }else{
-
+ } else {
void *dst = malloc(sizeof(struct in6_addr));
inet_pton(AF_INET6, "3001::1", dst);
- unsigned char * tmp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&pmsg->payload.rule.ip.prefix.address.un.ip6[0],tmp,16);
+ unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr;
+ memcpy(&pmsg->payload.rule.ip.prefix.address.un.ip6[0], tmp, 16);
pmsg->payload.rule.ip.prefix.address.af = ADDRESS_IP6;
}
pmsg->payload.rule.ip.prefix.len = 24;
pmsg->payload.rule.ip.swif = 0;
- if (vapi_hicn_api_punting_add(g_vapi_ctx_instance, pmsg, call_hicn_api_punting_add, NULL)!=VAPI_OK){
- perror("Operation failed");
- return -1;
+ if (vapi_hicn_api_punting_add(g_vapi_ctx_instance, pmsg,
+ call_hicn_api_punting_add, NULL) != VAPI_OK) {
+ perror("Operation failed");
+ return -1;
}
- }else
- {
+ } else {
usage();
return 1;
}
diff --git a/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang b/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang
index f66c205ce..a9251d14d 100644
--- a/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang
+++ b/ctrl/sysrepo-plugins/yang/ietf/ietf-interfaces.yang
@@ -21,7 +21,7 @@ module ietf-interfaces {
"This module contains a collection of YANG definitions for
managing network interfaces.
- Copyright (c) 2018 IETF Trust and the persons identified as
+ Copyright (c) 2021 IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or
diff --git a/docs/etc/requirements.txt b/docs/etc/requirements.txt
index 5b037c693..3ce3a7e00 100644
--- a/docs/etc/requirements.txt
+++ b/docs/etc/requirements.txt
@@ -1,27 +1,5 @@
-alabaster==0.7.12
-Babel==2.8.0
-certifi==2019.11.28
-chardet==3.0.4
-commonmark==0.9.1
-docutils==0.16
-idna==2.8
-imagesize==1.2.0
-Jinja2==2.10.3
-MarkupSafe==1.1.1
-packaging==20.0
-Pygments==2.5.2
-pyparsing==2.4.6
-pytz==2019.3
-recommonmark==0.6.0
-requests==2.22.0
-six==1.14.0
-snowballstemmer==2.0.0
-Sphinx==2.3.1
-sphinx-rtd-theme==0.4.3
-sphinxcontrib-applehelp==1.0.1
-sphinxcontrib-devhelp==1.0.1
-sphinxcontrib-htmlhelp==1.0.2
-sphinxcontrib-jsmath==1.0.1
-sphinxcontrib-qthelp==1.0.2
-sphinxcontrib-serializinghtml==1.1.3
-urllib3==1.25.8
+pip-tools==6.5.0 # BSD
+sphinx # BSD
+sphinx-rtd-theme # MIT
+sphinx-markdown-tables # GPLv3
+recommonmark # MIT \ No newline at end of file
diff --git a/docs/source/1-architecture.md b/docs/source/1-architecture.md
new file mode 100644
index 000000000..8f3cfc78a
--- /dev/null
+++ b/docs/source/1-architecture.md
@@ -0,0 +1,42 @@
+# Data identifiers and locators
+
+Hybrid ICN makes use of data identifiers to name the data produced by an end
+host. Data identifiers are encoded using a routable name prefix and a non
+routable name suffix to provide the ability to index a single IP packet in an
+prefix is unambigous manner. A full data name is composed of 160 bits. A
+routable name prefix in IPv4 network is 32 bits long while in IPv6 is 128 bits
+long. A name prefix is a valid IPv4 or IPv6 address. The 32 rightmost bits are
+used by the applications to index data within the same stream.
+
+A data source that is using the hicn stack is reacheable through IP routing
+where a producer socket is listening as the producer name prefix is IP routable.
+
+Locators are IP interface identifiers and are IPv4 or IPv6 addresses. Data
+consumers are reacheable through IP routing over their locators.
+
+For requests, the name prefix is stored in the destination address field of the
+IP header while the source address field stored the locator of the consumer.
+
+
+# Producer/Consumer Architecture
+Applications make use of the hicn network architecture by using a Prod/Cons API.
+Each communication socket is connection-less as a data producer makes data
+available to data consumer by pushing data into a named buffer. Consumers are
+responsible for pulling data from data producers by sending requests indexing
+the full data name which index a single MTU sized data packet. The core
+
+# Packet forwarding
+Packet forwarding leverages IP routing as requests are forwarded using name
+prefixes and replies using locators.
+
+# Relay nodes
+A relay node is implemented by using a packet cache which is used to temporarily
+store requests and replies. The relay node acts as a virtual proxy for the data
+producers as it caches data packets which can be sent back to data consumer by
+using the full name as an index. Requests must be cached and forwarded upstream
+towards data producers which will be able reach back the relay nodes by using
+the IP locators of the relays. Cached requests store all locators as currently
+written in the source address field of the request while requests forwarded
+upstream will get the source address rewritten with the relay node locator. Data
+packets can reach the original consumers via the relay nodes by using the
+requence of cached locators.
diff --git a/docs/source/apps.md b/docs/source/apps.md
index 64c3d9a68..4131eba82 100644
--- a/docs/source/apps.md
+++ b/docs/source/apps.md
@@ -18,7 +18,6 @@ Basic dependencies:
- OpenSSL
- pthreads
- libevent
-- libparc
- libcurl
- libhicntransport
diff --git a/docs/source/conf.py b/docs/source/conf.py
index bb6715564..d00e821ab 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -19,13 +19,13 @@
# -- Project information -----------------------------------------------------
project = u'Hybrid ICN'
-copyright = u'(c) 2017-2020 Cisco and/or its affiliates.'
-author = u'Luca Muscariello'
+copyright = u'(c) 2018-2022 Cisco and/or its affiliates.'
+author = u'HICN Team Members'
# The short X.Y version
version = u''
# The full version, including alpha/beta/rc tags
-release = u'20.01'
+release = u'22.02'
# -- General configuration ---------------------------------------------------
@@ -37,7 +37,7 @@ release = u'20.01'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = ['recommonmark']
+extensions = ['recommonmark', 'sphinx_markdown_tables']
# Prefix document path to section labels, otherwise autogenerated labels would look like 'heading'
# rather than 'path/to/file:heading'
@@ -88,7 +88,7 @@ html_theme = "sphinx_rtd_theme"
html_static_path = ['_static']
def setup(app):
- app.add_stylesheet('css/rules.css')
+ app.add_css_file('css/rules.css')
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
diff --git a/docs/source/control.md b/docs/source/control.md
index 9564a23af..f4dc4f22b 100644
--- a/docs/source/control.md
+++ b/docs/source/control.md
@@ -23,26 +23,12 @@ The YANG model for the VPP based hICN vSwitch is based the full hICN C API
exported by the VPP plugin with the addition of some VPP APIs such as
interface and FIB management which are required by the hICN plugin.
-To install libyang, sysrepo, libnetconf and netopeer2 for Ubuntu18 amd64/arm64
-or CentOS 7 and ad-hoc repository is available and maintained in bintray
-at <https://dl.bintray.com/icn-team/apt-hicn-extras>.
+The dependencies libyang, sysrepo, libnetconf and netopeer2 for Ubuntu20.04
+amd64/arm64 are built from sources. See the following Dockerfile for
+reference:
-For instance in Ubuntu 18 LTS:
+<https://github.com/icn-team/vSwitch/blob/master/Dockerfile>
-Install the sysrepo YANG data store and a NETCONF server:
-
-```bash
-echo "deb [trusted=yes] https://dl.bintray.com/icn-team/apt-hicn-extras bionic main" \
- | tee -a /etc/apt/sources.list
-apt-get update && apt-get install -y libyang sysrepo libnetconf2 netopeer2-server
-```
-
-Install the VPP based hICN virtual switch:
-
-```bash
-curl -s https://packagecloud.io/install/repositories/fdio/release/script.deb.sh | bash
-apt-get update && apt-get install -y hicn-plugin vpp-plugin-dpdk hicn-sysrepo-plugin
-```
The hICN YANG models are installed under `/usr/lib/$(uname -m)-linux-gnu/modules_yang`.
diff --git a/docs/source/hicn-light.md b/docs/source/hicn-light.md
index 90e0afc91..f5012f8e9 100644
--- a/docs/source/hicn-light.md
+++ b/docs/source/hicn-light.md
@@ -11,15 +11,14 @@ to communicate.
Build dependencies:
-- C99 ( clang / gcc )
-- CMake 3.4
+- C11 ( clang / gcc )
+- CMake 3.10
Basic dependencies:
- OpenSSL
- pthreads
- libevent
-- libparc
## hicn-light executables
@@ -37,31 +36,27 @@ The command `hicn-light-daemon` runs the hicn-light forwarder. The forwarder can
with the following options:
```bash
-hicn-light-daemon [--port port] [--daemon] [--capacity objectStoreSize] [--log facility=level]
+hicn-light-daemon [--port port] [--daemon] [--capacity objectStoreSize] [--log level]
[--log-file filename] [--config file]
Options:
---port <tcp_port> = tcp port for local in-bound connections
---daemon = start as daemon process
---capacity <capacity> = maximum number of content objects to cache. To disable the cache
- objectStoreSize must be 0.
- Default vaule for objectStoreSize is 100000
---log <log_granularity> = sets a facility to a given log level. You can have multiple of these.
- facilities: all, config, core, io, message, processor
- levels: debug, info, notice, warning, error, critical, alert, off
- example: hicn-light-daemon --log io=debug --log core=off
---log-file <output_logfile> = file to write log messages to (required in daemon mode)
---config <config_path> = configuration filename
+--port <tcp_port> = tcp port for local in-bound connections
+--daemon = start as daemon process
+--capacity <objectStoreSize> = maximum number of content objects to cache. To disable the cache
+ objectStoreSize must be 0.
+ Default vaule for objectStoreSize is 100000
+--log <log_granularity> = sets the log level. Available levels: trace, debug, info, warn, error, fatal
+--log-file <output_logfile> = file to write log messages to (required in daemon mode)
+--config <config_path> = configuration filename
```
The configuration file contains configuration lines as per hicn-light-control (see below for all
the available commands). If logging level or content store capacity is set in the configuration
-file, it overrides the command_line. When a configuration file is specified, no default listeners
-are setup. Only 'add listener' lines in the configuration file matter.
+file, it overrides the command_line.
-If no configuration file is specified, hicn-light-daemon will listen on TCP and UDP ports specified
-by the --port flag (or default port). It will listen on both IPv4 and IPv6 if available. The
-default port for hicn-light is 9695. Commands are expected on port 2001.
+In addition to the listeners setup in the configuration file, hicn-light-daemon will listen
+on TCP and UDP ports specified by the --port flag (or default port).
+It will listen on both IPv4 and IPv6 if available. The default port for hicn-light is 9695.
### hicn-light-control
@@ -82,28 +77,20 @@ This is the full list of available commands in `hicn-light-control`. This comman
from the command line running `hicn-light-control` as explained before, or listing them in a
configuration file.
-Information about the commands are also available in the `hicn-light-control` help message.
+The list of commands can be navigated using `hicn-light-control help`, `hicn-light-control help <object>`, `hicn-light-control help <object> <action>`.
`add listener`: creates a TCP or UDP listener with the specified options on the local forwarder.
For local connections (application to hicn-light) we expect a TCP listener. The default port for
the local listener is 9695.
```bash
-add listener <protocol> <symbolic> <local_adress> <local_port>
+add listener <protocol> <symbolic> <local_address> <local_port> <interface>
<symbolic> :User defined name for listener, must start with alpha and bealphanum
<protocol> :tcp | udp
<localAddress> :IPv4 or IPv6 address
<local_port> :TCP/UDP port
-```
-
-`add listener hicn`: creates a hicn listener with the specified options on the local forwarder.
-
-```bash
-add listener hicn <symbolic> <local_adress>
-
- <symbolic> :User defined name for listener, must start with alpha and be alphanum
- <localAddress> :IPv4 or IPv6 address
+ <interface> :interface on which to bind
```
`add connection`: creates a TCP or UDP connection on the local forwarder with the specified options.
@@ -119,17 +106,6 @@ add connection <protocol> <symbolic> <remote_ip> <remote_port> <local_ip> <local
<local_port> : local TCP/UDP port
```
-`add connection hicn`: creates an hicn connection on the local forwarder with the specified options.
-
-```bash
-add connection hicn <symbolic> <remote_ip> <local_ip>
-
- <symbolic> : symbolic name, e.g. 'conn1' (must be unique, start with alpha)
- <remote_ip> : the IPv4 or IPv6 of the remote system
- <local_ip> : local IP address to bind to
-
-```
-
`list`: lists the connections, routes or listeners available on the local hicn-light forwarder.
```bash
@@ -142,7 +118,7 @@ list <connections | routes | listeners>
add route <symbolic | connid> <prefix> <cost>
<symbolic> :The symbolic name for an exgress (must be unique, start with alpha)
- <connid>: :The egress connection id (see 'help list connections')
+ <connid>: :The egress connection id (see 'list connection' command)
<prefix>: :ipAddress/netmask
<cost>: :positive integer representing cost
```
@@ -151,11 +127,10 @@ add route <symbolic | connid> <prefix> <cost>
only for UDP connections, TCP is ignored.
```bash
-remove connection <protocol> <symbolic | connid>
+remove connection <symbolic | connid>
- <protocol> : tcp | upd. This is the protocol used to create the connection.
<symbolic> :The symbolic name for an exgress (must be unique, start with alpha)
- <connid>: :The egress connection id (see 'help list connections')
+ <connid>: :The egress connection id (see 'list connection' command)
```
@@ -168,24 +143,24 @@ remove route <symbolic | connid> <prefix>
<prefix> : the prefix (ipAddress/netmask) to remove
```
-`cache serve`: enables/disables replies from local content store (if available).
+`serve cache`: enables/disables replies from local content store (if available).
```bash
-cache serve <on|off>
+serve cache <on|off>
```
-`cache store`: enables/disables the storage of incoming data packets in the local content store
+`store cache`: enables/disables the storage of incoming data packets in the local content store
(if available).
```bash
-cache store <on|off>
+store cache <on|off>
```
-`cache clear`: removes all the cached data form the local content store (if available).
+`clear cache`: removes all the cached data form the local content store (if available).
```bash
-cache clear
+clear cache
```
`set strategy`: sets the forwarding strategy for a give prefix. There are 4 different strategies
@@ -200,12 +175,14 @@ implemented in hicn-light:
ICNP 2013.
- **low_latency**: uses the face with the lowest latency. In case more faces have similar
latency the strategy uses them in parallel.
+- **replication**
+- **bastpath**
```bash
set strategy <prefix> <strategy>
<preifx> : the prefix to which apply the forwarding strategy
- <strategy> : random | loadbalancer | low_latency
+ <strategy> : random | loadbalancer | low_latency | replication | bestpath
```
`set wldr`: turns on/off WLDR on the specified connection. WLDR (Wireless Loss Detiection and
@@ -224,36 +201,13 @@ set wldr <on|off> <symbolic | connid>
```
-`add punting`: add punting rules to the forwarders.
-
-```bash
-add punting <symbolic> <prefix>
-
- <symbolic> : listener symbolic name
- <address> : prefix to add as a punting rule. (example 1234::0/64)
-```
-
-`mapme enable`: enables/disables mapme.
-
-```bash
-mapme enable <on|off>
-```
-`mapme discovery`: enables/disables mapme discovery.
-
-```bash
-mapme discovery <on|off>
-```
-
-`mapme timescale`: set the timescale value expressed in milliseconds.
-
-```bash
-mapme timescale <milliseconds>
-```
-
-`mapme retx`: set the retransmission time value expressed in millisecond.
+`set mapme`: enables/disables mapme, enables/disables mapme discovery, set the timescale value (expressed in milliseconds), set the retransmission time value (expressed in milliseconds).
```bash
-mapme retx <milliseconds>
+mapme set enable <on|off>
+mapme set discovery <on|off>
+mapme set timescale <milliseconds>
+mapme set retx <milliseconds>
```
`quit`: exits the interactive bash.
@@ -264,13 +218,12 @@ This is an example of a simple configuration file for hicn-light. It can be load
the command `hicn-light-daemon --config configFile.cfg`, assuming the file name is `configFile.cfg`.
```bash
-#create a local listener on port 9199. This will be used by the applications to talk
-with the forwarder
-add listener udp local0 192.168.0.1 9199
+# Create a local listener on port 9199. This will be used by the applications to talk with the forwarder
+add listener udp local0 192.168.0.1 9199 eth0
-#create a connection with a remote hicn-light-daemon, with a listener on 192.168.0.20 12345
-add connection udp conn0 192.168.0.20 12345 192.168.0.1 9199
+# Create a connection with a remote hicn-light-daemon, with a listener on 192.168.0.20 12345
+add connection udp conn0 192.168.0.20 12345 192.168.0.1 9199 eth0
-#add a route toward the remote node
+# Add a route toward the remote node
add route conn0 c001::/64 1
```
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 99ea39afa..c41df95ca 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,27 +1,76 @@
Hybrid Information-Centric Networking
=====================================
-Hybrid Information-Centric Networking (hICN) is a network architecture that makes
-use of IPv6 or IPv4 to realize location-independent communications. It is largely
-inspired by the pioneer work of Van Jacobson on Content-Centric Networking, that was
-a clean-slate architecture whereas hICN is based on the Internet protocol and easy to
-deploy in today networks and applications. hICN brings many-to-many communications,
-multi-homing, multi-path, multi-source, group communications to the Internet protocol
-without replicated unicast. The project implements novel transport protocols, with a socket API,
-for real-time and capacity seeking applications. A scalable stack is available based
-on VPP and a client stack is provided to support any mobile and desktop operating system.
+Hybrid Information-Centric Networking (hICN) is a network architecture that
+makes use of IPv6 or IPv4 to implement location-independent communications. It
+is largely inspired by the pioneer work of Van Jacobson on Content-Centric
+Networking (RFC 8569, RFC 8609) that is a clean-slate architecture. hICN is
+based on the Internet protocol and easyier to deploy in today networks and
+applications. hICN brings many-to-many communications, multi-homing, multi-path,
+multi-source, group communications to the Internet protocol. The current code
+implements also transport protocols, with a socket API, for real-time and
+capacity seeking applications. A scalable stack is available based on VPP and a
+client stack is provided to support mobile and desktop operating systems.
+
+A detailed description of the architecture is described in the paper
+
+Giovanna Carofiglio, Luca Muscariello, Jordan Augé, Michele Papalini, Mauro
+Sardara, and Alberto Compagno. 2019. Enabling ICN in the Internet Protocol:
+Analysis and Evaluation of the Hybrid-ICN Architecture. In Proceedings of the
+6th ACM SIGCOMM Conference on Information-Centric Networking (ICN '19).
+Association for Computing Machinery, New York, NY, USA, 55–66. DOI:
+https://doi.org/10.1145/3357150.3357394
+
+The project wiki page is full of resources https://wiki.fd.io/view/HICN
+
+.. toctree::
+ :caption: Architecture
+
+ 1-architecture
+
.. toctree::
+ :caption: Getting started
+ :maxdepth: 1
started
+
+.. toctree::
+ :caption: Core library
+ :maxdepth: 1
+
lib
+
+.. toctree::
+ :caption: The VPP Plugin
+ :maxdepth: 1
+
vpp-plugin
+
+.. toctree::
+ :caption: The Transport Library
+ :maxdepth: 1
+
transport
+
+.. toctree::
+ :caption: The Portable Forwarder
+ :maxdepth: 1
+
hicn-light
+
+.. toctree::
+ :caption: Network Control and Management
+ :maxdepth: 1
+
interface
control
telemetry
- utils
- apps
+.. toctree::
+ :caption: Applications and Tools
+ :maxdepth: 1
+ utils
+ apps
+ packethicn \ No newline at end of file
diff --git a/docs/source/interface.md b/docs/source/interface.md
index cf05a5c7b..909f60bfa 100644
--- a/docs/source/interface.md
+++ b/docs/source/interface.md
@@ -45,35 +45,6 @@ interfaces:
link and address information, interface types, and bonjour service
discovery.
-### Architectural overview
-
-#### Facelets
-
-TODO:
-
-```text
-- Key attributes (netdevice and protocol family)
-- Facelet API
-```
-
-#### Events
-
-TODO
-
-#### Facelet cache & event scheduling
-
-TODO:
-
-```text
- - Facelet cache
- - Joins
- - How synchronization work
-```
-
-### Interface API
-
-TODO
-
## Developing a new interface
### Dummy template
@@ -261,7 +232,7 @@ error.
```
While support for multiple file descriptors might be added in the future, an
-alternative short-term implementation might consider the instanciation of
+alternative short-term implementation might consider the instantiation of
multiple interface, as is done for Bonjour in the current codebase, in
`src/api.c`.
@@ -304,8 +275,6 @@ The build system is based on CMake. Each interface should declare its source
files, private and public header files, as well as link dependencies in the
local `CMakeLists.txt` file.
-TODO: detail the structure of the file
-
### Hands-on
#### Architecture
diff --git a/docs/source/packethicn.md b/docs/source/packethicn.md
index cf4976837..acf2d7cc9 100644
--- a/docs/source/packethicn.md
+++ b/docs/source/packethicn.md
@@ -1,11 +1,13 @@
HICN Plugin for Wireshark
===================
-The `packethicn` plugin adds support to Wireshark to parse and dissect HICN traffic.
+The `packethicn` plugin adds support to Wireshark to parse and dissect HICN
+traffic.
`packethicn` can be compiled and installed in two ways:
-1. Alongside HICN, from the HICN root dir (see [Build with HICN](#Build-with-HICN))
+1. Alongside HICN, from the HICN root dir (see [Build with
+ HICN](#Build-with-HICN))
2. As a standalone component (see [Standalone build](#Standalone-build))
@@ -14,13 +16,12 @@ The second one is preferred if HICN is already installed in the system.
# Supported platforms
`packethicn` has been tested in
-- Ubuntu 18.04
- Ubuntu 20.04
-- macOS 11.2
+- macOS 12.3
Other platforms and architectures may work.
-# Installation
+# Installation
## Build with HICN
### Dependencies
@@ -38,15 +39,10 @@ From the root HICN dir add the `-DBUILD_WSPLUGIN` flag to cmake.
```bash
$ cd hicn
-
$ mkdir build; cd build
-
-$ cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl\@1.1 -DBUILD_APPS=ON -DBUILD_WSPLUGIN=ON ..
-
+$ cmake -DBUILD_APPS=ON -DBUILD_WSPLUGIN=ON ..
$ make -j`nproc`
-
$ sudo make install
-
```
## Standalone build
@@ -55,22 +51,16 @@ $ sudo make install
#### Install dependencies
```bash
$ sudo add-apt-repository ppa:wireshark-dev/stable
-
$ curl -s https://packagecloud.io/install/repositories/fdio/release/script.deb.sh | sudo bash
-
$ sudo apt install -y build-essential cmake libhicn-dev wireshark wireshark-dev libgcrypt-dev libgnutls28-dev
```
-#### Compile and install HICN plugin
+#### Compile and install HICN wireshark plugin
```bash
$ cd packethicn
-
$ mkdir build; cd build
-
$ cmake ..
-
$ make
-
$ sudo make install
```
@@ -80,15 +70,10 @@ If installing wireshark via brew use the `./install_macos.sh` script as shown be
```bash
$ brew tap icn-team/hicn-tap
-
$ brew install hicn
-
$ brew install wireshark
-
$ brew install cask wireshark
-
$ cd packethicn
-
$ ./install_macos.sh
```
@@ -96,13 +81,9 @@ Otherwise (if wireshark was compiled from sources) you can follow the setup for
```bash
$ cd packethicn
-
$ mkdir build; cd build
-
$ cmake ..
-
$ make
-
$ sudo make install
```
@@ -110,6 +91,7 @@ $ sudo make install
## Filters
+
| Filter | Description | Example |
| --- | --- | --- |
| `hicn` | HICN traffic only | *hicn* |
diff --git a/docs/source/started.md b/docs/source/started.md
index ef3763366..dd2f83bab 100644
--- a/docs/source/started.md
+++ b/docs/source/started.md
@@ -1,15 +1,16 @@
-# Getting started
+# Code structure
## Introduction
-hicn is an open source implementation of Cisco's hICN. It includes a network stack, that implements
-ICN forwarding path in IPv6, and a transport stack that implements two main transport protocols and
-a socket API. The transport protocols provide one reliable transport service implementation and a
-real-time transport service for audio/video media.
+hicn is an open source implementation of Cisco's hICN. It includes a network
+stack, that implements ICN forwarding path in IPv6, and a transport stack that
+implements two main transport protocols and a socket API. The transport
+protocols provide one reliable transport service implementation and a real-time
+transport service for audio/video media.
## Directory layout
-```text
+
| Directory name | Description |
| -------------- | --------------------------------------------------------- |
| lib | Core support library |
@@ -19,39 +20,36 @@ real-time transport service for audio/video media.
| utils | Tools for testing |
| apps | Application examples using hicn stack |
| ctrl | Tools and libraries for network management and control |
-```
-hicn plugin is a VPP plugin that implement hicn packet processing as specified in
-<https://datatracker.ietf.org/doc/draft-muscariello-intarea-hicn/.> The transport library is used to
-implement the hicn host stack and makes use of libmemif as high performance connector between
-transport and the network stack. The transport library makes use of VPP binary API to configure the
-local namespace (local face management).
+hicn plugin is a VPP plugin that implement hicn packet processing as specified
+in [1] The transport library is used to implement the hicn host stack and makes
+use of libmemif as high performance connector between transport and the network
+stack. The transport library makes use of VPP binary API to configure the local
+namespace (local face management).
## Release note
-The current master branch provides the latest release which is compatible with the latest VPP stable.
-No other VPP releases are supported nor maintained. At every new VPP release distribution hicn
-master branch is updated to work with the latest stable release. All previous stable releases
-are discontinued and not maintained. The user who is interested in a specific release can always
-checkout the right code tree by searching the latest commit under a given git tag carrying the
-release version.
+The current master branch provides the latest release which is compatible with
+the latest VPP stable. No other VPP releases are supported nor maintained. At
+every new VPP release distribution hicn master branch is updated to work with
+the latest stable release. All previous stable releases are discontinued and not
+maintained. The user who is interested in a specific release can always checkout
+the right code tree by searching the latest commit under a given git tag
+carrying the release version.
-The Hybrid ICN software distribution can be installed for several platforms.
-The network stack comes in two different implementations: one scalable based
-on VPP and one portable based on IPC and sockets.
+The Hybrid ICN software distribution can be installed for several platforms. The
+network stack comes in two different implementations: one scalable based on VPP
+and one portable based on IPC and sockets.
-The transport stack is a unique library that is used for both the scalable
-and portable network stacks.
+The transport stack is a unique library that is used for both the scalable and
+portable network stacks.
## Supported platforms
-- Ubuntu 18.04 LTS (amd64, arm64)
-- Debian Stable/Testing
-- Red Hat Enterprise Linux 7
-- CentOS 7
+- Ubuntu 20.04 LTS (amd64, arm64)
- Android 10 (amd64, arm64)
-- iOS 13
-- macOS 10.15
+- iOS 15
+- macOS 12.3
- Windows 10
Other platforms and architectures may work.
@@ -63,35 +61,97 @@ You can either use released packages, or compile hicn from sources.
curl -s https://packagecloud.io/install/repositories/fdio/release/script.deb.sh | sudo bash
```
-### CentOS
+The following debian packages for Ubuntu are available dor amd64 and arm64
```bash
-curl -s https://packagecloud.io/install/repositories/fdio/release/script.rpm.sh | sudo bash
+facemgr-dev
+facemgr
+hicn-apps-dev
+hicn-apps
+hicn-light
+hicn-plugin-dev
+hicn-plugin
+libhicn-dev
+libhicn
+libhicnctrl-dev
+libhicnctrl-modules
+libhicnctrl
+libhicntransport-dev
+libhicntransport-io-modules
+libhicntransport
```
### macOS
```bash
+brew tap icn-team/hicn-tap
brew install hicn
```
+or
+
+```bash
+git clone https://github.com/FDio/hicn.git
+$ cd hicn
+$ OPENSSL_ROOT_DIR=/usr/local/opt/openssl\@1.1 make build-release
+```
+
### Android
+hICN is built as a native library for the Android NDK which are packaged
+as Android archives AAR and made available in a Maven repository in
+Github Packages in
+
+<https://github.com/orgs/icn-team/packages>
+
+To build from sources, refer to the Android SDK in
+
+<https://github.com/icn-team/android-sdk>
Install the applications via the Google Play Store
+
<https://play.google.com/store/apps/developer?id=ICN+Team>
### iOS
-Coming soon.
+Clone this distro
+
+```bash
+git clone https://github.com/icn-team/ios-sdk.git
+cd ios-sdk
+```
+Compile everything (dependencies and hICN modules)
+
+```bash
+make update
+make all
+```
+Compile everything with Qt (dependencies, hICN modules and Viper dependencies)
+
+```bash
+make update
+make all_qt
+```
### Windows
-Coming soon.
+Install vcpkg
+
+```bash
+git clone https://github.com/icn-team/windows-sdk
+.\windows-sdk\scripts\init.bat
+```
+
+
+```bash
+cd windows-sdk
+make all
+```
### Docker
-Several docker images are nightly built with the latest software for Ubuntu 18 LTS (amd64/arm64),
-and available on docker hub at <https://hub.docker.com/u/icnteam>.
+Several docker images are nightly built with the latest software for Ubuntu 18
+LTS (amd64/arm64), and available on docker hub at
+<https://hub.docker.com/u/icnteam>.
The following images are nightly built and maintained.
@@ -106,6 +166,8 @@ docker pull icnteam/vhttpproxy:amd64
docker pull icnteam/vhttpproxy:arm64
```
+Other Dockerfiles are included in the main git repo for development.
+
### Vagrant
Vagrant boxes for a virtual switch are available at
@@ -117,12 +179,21 @@ vagrant box add icnteam/vswitch
Supported providers are libvirt, vmware and virtualbox.
+## References
+
+Giovanna Carofiglio, Luca Muscariello, Jordan Augé, Michele Papalini, Mauro
+Sardara, and Alberto Compagno. 2019. Enabling ICN in the Internet Protocol:
+Analysis and Evaluation of the Hybrid-ICN Architecture. In Proceedings of the
+6th ACM Conference on Information-Centric Networking (ICN '19). Association for
+Computing Machinery, New York, NY, USA, 55–66.
+DOI: https://doi.org/10.1145/3357150.3357394
+
## License
This software is distributed under the following license:
```bash
-Copyright (c) 2017-2020 Cisco and/or its affiliates.
+Copyright (c) 2019-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:
diff --git a/docs/source/telemetry.md b/docs/source/telemetry.md
index 8887b8f1f..f81d21ee1 100644
--- a/docs/source/telemetry.md
+++ b/docs/source/telemetry.md
@@ -31,17 +31,14 @@ sudo make install
hICN collectd plugins have been tested in:
-- Ubuntu 16.04 LTS (x86_64)
-- Ubuntu 18.04 LTS (x86_64)
-- Debian Stable/Testing
-- Red Hat Enterprise Linux 7
-- CentOS 7
+- Ubuntu 20.04 LTS
### Dependencies
Build dependencies:
-- VPP 20.01, Debian packages can be found on [packagecloud](https://packagecloud.io/fdio/release/install):
+VPP 22.02, Debian packages can be found on
+[packagecloud](https://packagecloud.io/fdio/release/install):
- vpp
- libvppinfra-dev
- vpp-dev
@@ -62,14 +59,18 @@ Before running collectd, a vpp forwarder must be started. If the vpp-hicn plugin
is used, the hicn-plugin must be available in the vpp forwarder.
If you need the custom types that the two plugins define, they are present in
-`telemetry/custom_types.db`. It is useful if you are using InfluxDB as it requires
-the type database for multi-value metrics
-(see [CollectD protocol support in InfluxDB](https://docs.influxdata.com/influxdb/v1.7/supported_protocols/collectd/)).
+`telemetry/custom_types.db`. It is useful if you are using InfluxDB as it
+requires the type database for multi-value metrics (see [CollectD protocol
+support in
+InfluxDB](https://docs.influxdata.com/influxdb/v1.7/supported_protocols/collectd/)).
## Plugin options
`vpp` and `vpp-hicn` have the same two options:
-- `Verbose` enables additional statistics. You can check the sources to have an exact list of available metrics.
-- `Tag` tags the data with the given string. Useful for identifying the context in which the data was retrieved in InfluxDB for instance. If the tag value is `None`, no tag is applied.
+- `Verbose` enables additional statistics. You can check the sources to have an
+ exact list of available metrics.
+- `Tag` tags the data with the given string. Useful for identifying the context
+ in which the data was retrieved in InfluxDB for instance. If the tag value is
+ `None`, no tag is applied.
### Example: storing statistics from vpp and vpp-hicn
diff --git a/docs/source/transport.md b/docs/source/transport.md
index 3e7844ad5..eb5b9d71a 100644
--- a/docs/source/transport.md
+++ b/docs/source/transport.md
@@ -1,38 +1,51 @@
-# Transport library
-
## Introduction
-This library provides transport services and socket API for applications willing to communicate
-using the hICN protocol stack.
+The transport library provides transport services and socket API for
+applications willing to communicate using the hICN protocol stack.
Overview:
- Implementation of the hICN core objects (interest, data, name..) exploiting
- the API provided by [libhicn](../lib).
-- Connectors for connecting the application to either the hicn-plugin or the
- hicn-light forwarder.
+ the API provided by [libhicn](./lib.md).
+- IO modules for seamlessly connecting the application to the hicn-plugin for [VPP](https://github.com/FDio/vpp) or the
+ [hicn-light](./hicn-light.md) forwarder.
- Transport protocols (RAAQM, CBR, RTC)
-- Transport services (authentication, integrity, segmentation, reassembly, naming)
+- Transport services (authentication, integrity, segmentation, reassembly,
+ naming)
- Interfaces for applications (from low-level interfaces for interest-data
interaction to high level interfaces for Application Data Unit interaction)
+
## Build dependencies
### Ubuntu
-- libparc
-- libmemif (linux only, if compiling with VPP support)
-- libasio
+```bash
+sudo apt install libasio-dev libconfig++-dev libssl-dev
+```
If you wish to use the library for connecting to the vpp hicn-plugin, you will
-need to also install vpp, the vpp libraries and the libmemif libraries:
+need to also install vpp and its libraries.
-- DEB packages:
- - vpp
- - vpp-lib
- - vpp-dev
+```bash
+# Prevent vpp to set sysctl
+export VPP_INSTALL_SKIP_SYSCTL=1
+VPP_VERSION=$(cat "${VERSION_PATH}" | grep VPP_DEFAULT_VERSION | cut -d ' ' -f 2 | tr -d '"' | grep -Po '\d\d.\d\d')
-You can get them either from from the vpp packages or the source code. Check
-the [VPP wiki](https://wiki.fd.io/view/VPP) for instructions.
+curl -s https://packagecloud.io/install/repositories/fdio/${VPP_VERSION//./}/script.deb.sh | bash
+curl -L https://packagecloud.io/fdio/${VPP_VERSION//./}/gpgkey | apt-key add -
+sed -E -i 's/(deb.*)(\[.*\])(.*)/\1\3/g' /etc/apt/sources.list.d/fdio_${VPP_VERSION//./}.list
+apt-get update
+
+apt-get install -y \
+ vpp-dev \
+ libvppinfra-dev \
+ vpp-plugin-core \
+ vpp \
+ libvppinfra
+```
+
+You can get them either from from the vpp packages or the source code. Check the
+[VPP wiki](https://wiki.fd.io/view/VPP) for instructions.
### macOS
@@ -40,31 +53,23 @@ We recommend to use [HomeBrew](https://brew.sh/) for installing the libasio
dependency:
```bash
-brew install asio
+brew install asio libconfig openssl@1.1
```
-Download, compile and install libparc:
+Since VPP does not support macOS, the IO module memif is not built.
-```bash
-git clone -b cframework/master https://gerrit.fd.io/r/cicn cframework && cd cframework
-mkdir -p libparc.build && cd libparc.build
-cmake ../libparc
-make
-make install
-```
-
-Libparc will be installed by default under `/usr/local/lib` and `/usr/local/include`.
-Since VPP does not support macOS, the hicn-plugin connector is not built.
## Build the library
-From the project root folder:
+The library is built by default from the main CMakeLists.txt.
+If you have all the dependencies installed, including [libhicn](./lib.md),
+you can also build libtransport alone:
```bash
cd libtransport
mkdir build && cd build
cmake ..
-make
+cmake --build .
```
### Compile options
@@ -75,11 +80,7 @@ The build process can be customized with the following options:
- `CMAKE_BUILD_TYPE`: The build configuration. Options: `Release`, `Debug`.
Default is `Release`.
- `ASIO_HOME`: The folder containing the libasio headers.
-- `LIBPARC_HOME`: The folder containing the libparc headers and libraries.
- `VPP_HOME`: The folder containing the installation of VPP.
-- `LIBMEMIF_HOME`: The folder containing the libmemif headers and libraries.
-- `BUILD_MEMIF_CONNECTOR`: On linux, set this value to `ON` for building the
- VPP connector.
An option can be set using cmake -D`OPTION`=`VALUE`.
@@ -88,5 +89,245 @@ An option can be set using cmake -D`OPTION`=`VALUE`.
For installing the library, from the cmake build folder:
```bash
-sudo make install
+cmake --build . -- install
+```
+
+
+## Usage
+
+Examples on how to use the library can be found in the apps folder of the project.
+In particular you can check the **hiperf** application, which demonstrates
+how to use the API to interact with the hicn transport, both for consumer and producer.
+
+### Configuration file
+
+The transport can be configured using a configuration file. There are two ways
+to tell libransport where to find the configuration file:
+
+- programmatically - you set the configuration file path in your application:
+```cpp
+// Set conf file path
+std::string conf_file = "/opt/hicn/etc/transport.config"
+// Parse config file
+transport::interface::global_config::parseConfigurationFile(conf_file);
+```
+
+- using the environment variable `TRANSPORT_CONFIG`:
+```bash
+export TRANSPORT_CONFIG=/opt/hicn/etc/transport.config
+./hiperf -C b001::1
```
+
+Here is an example of configuration file:
+
+```
+// Configuration for io_module
+io_module = {
+ path = [];
+ name = "forwarder_module";
+};
+
+// Configuration for forwarder io_module
+forwarder = {
+ n_threads = 1;
+
+ connectors = {
+ c0 = {
+ /* local_address and local_port are optional */
+ local_address = "127.0.0.1";
+ local_port = 33436;
+ remote_address = "127.0.0.1";
+ remote_port = 33436;
+ }
+ };
+
+ listeners = {
+ l0 = {
+ local_address = "127.0.0.1";
+ local_port = 33437;
+ }
+ };
+};
+
+// Logging
+log = {
+ // Log level (INFO (0), WARNING (1), ERROR (2), FATAL (3))
+ minloglevel = 0;
+
+ // Verbosity level for debug logs
+ v= 2;
+
+ // Log to stderr
+ logtostderr = true;
+
+ // Get fancy colored logs
+ colorlogtostderr = true;
+
+ // Log messages above this level also to stderr
+ stderrthreshold = 2;
+
+ // Set log prefix for each line log
+ log_prefix = true;
+
+ // Log dir
+ log_dir = "/tmp";
+
+ // Log only specific modules.
+ // Example: "membuf=2,rtc=3"
+ vmodule = "";
+
+ // Max log size in MB
+ max_log_size = 10;
+
+ // Log rotation
+ stop_logging_if_full_disk = true;
+};
+```
+
+
+## Security
+
+hICN has built-in authentication and integrity features by either:
+* Cryptographically signing all packets using an asymmetric key (like RSA) or a
+ symmetric one (like HMAC). The latter requires that all parties have prior
+ access to the same key. Beware that this method is computationally expensive
+ and impacts max throughput and CPU usage.
+* Using manifests. Manifests are special packets that holds the digests of a
+ group of data packets. Only the manifest needs to be signed and authenticated;
+ other packets are authenticated simply by verifying that their digest is
+ present in a manifest.
+
+### Per-packet signatures
+
+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);
+ ```
+* On the producer, instantiate an `AsymmetricSigner` object by passing either an
+ asymmetric pair of keys as
+ [EVP_KEY](https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_new.html) object
+ or a keystore path and password as strings:
+ ```cpp
+ std::shared_ptr<Signer> signer = std::make_shared<AsymmetricSigner>("./rsa.p12", "hunter2");
+ ```
+* Pass the signer object to libtransport:
+ ```cpp
+ producer_socket->setSocketOption(GeneralTransportOptions::SIGNER, signer);
+ ```
+* On the consumer, instantiate an `AsymmetricVerifer` object by passing either a
+ certificate as a [X509](https://www.openssl.org/docs/man1.0.2/man3/x509.html)
+ object, an asymmetric public key as a
+ [EVP_KEY](https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_new.html) object
+ or a certificate path as a string:
+ ```cpp
+ std::shared_ptr<Verifier> verifier = std::make_shared<Verifier>("./rsa.crt");
+ ```
+* Pass the verifier object to libtransport:
+ ```cpp
+ consumer_socket->setSocketOption(GeneralTransportOptions::VERIFIER, verifier);
+ ```
+
+To enable per-packet signature with symmetric signing, follow the above steps
+replacing `AsymmetricSigner` with `SymmetricSigner` and `AsymmetricVerifer` with
+`SymmetricSigner`. A `SymmetricSigner` only has one constructor which expects a
+`CryptoSuite` and a passphrase. A `SymmetricVerifier` also has a single
+constructor which expects a passphrase:
+```cpp
+std::shared_ptr<Signer> signer = std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, "hunter2");
+std::shared_ptr<Verifier> verifier = std::make_shared<SymmetricVerifier>("hunter2");
+```
+
+Check [Supported crypto suites](#supported-crypto-suites) for the list of
+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:
+ ```cpp
+ producer_socket->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, 20);
+ ```
+
+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:
+```
+T(t) = producer_rate(t) * max_unverified_time
+```
+
+`max_unverified_time` is a consumer socket option, in milliseconds. It is set
+to `2000` by default. To change it:
+```cpp
+consumer_socket_->setSocketOption(GeneralTransportOptions::MAX_UNVERIFIED_TIME, 4000);
+```
+
+### Handling authentication failures
+
+When a data packet fails authentication, or when the unverified buffer is full
+in the case of RTC, an alert is triggered by the verifier object. By default
+libtransport aborts the connection upon reception of that alert. You may want to
+intercept authentication failures in your application:
+* Define a callback with arguments an `uint32_t` integer, which will be set to
+ the suffix of the faulty packet, and a `auth::VerificationPolicy`, which will
+ be set to the action suggested by the verifier object. The callback must
+ return another `auth::VerificationPolicy` which will be the actual action
+ taken by libtransport:
+ ```cpp
+ auth::VerificationPolicy onAuthFailed(uint32_t suffix, auth::VerificationPolicy policy) {
+ std::cout << "auth failed for packet " << suffix << std::endl;
+ return auth::VerificationPolicy::ACCEPT;
+ }
+ ```
+* Give that callback to your `Verifier` object as well as a list of
+ `auth::VerificationPolicy` to intercept (if left empty, will be set by
+ default to `{ABORT, DROP}`):
+ ```cpp
+ verifier->setVerificationFailedCallback(&onAuthFailed, {
+ auth::VerificationPolicy::ABORT,
+ auth::VerificationPolicy::DROP,
+ auth::VerificationPolicy::UNKNOWN,
+ });
+ ```
+
+### Supported crypto suites
+
+The following `CryptoSuite` are supported by libtransport:
+```
+ECDSA_BLAKE2B512
+ECDSA_BLAKE2S256
+ECDSA_SHA256
+ECDSA_SHA512
+RSA_BLAKE2B512
+RSA_BLAKE2S256
+RSA_SHA256
+RSA_SHA512
+HMAC_BLAKE2B512
+HMAC_BLAKE2S256
+HMAC_SHA256
+HMAC_SHA512
+DSA_BLAKE2B512
+DSA_BLAKE2S256
+DSA_SHA256
+DSA_SHA512
+```
+
+
+## Logging
+
+Internally libtransport uses glog as logging library. If you want to have a more
+verbose transport log when launching a test or an app, you can set environment
+variables in this way:
+
+```
+GLOG_v=4 hiperf -S b001::/64
+```
+
+For a more exhaustive list of options, please check the instructions in the glog
+[README](https://github.com/google/glog#setting-flags).
+
+Useful options include enabling logging *per module*. Also you can compile out
+useless messages in release builds.
diff --git a/docs/source/utils.md b/docs/source/utils.md
index 79ada8985..d6044821a 100644
--- a/docs/source/utils.md
+++ b/docs/source/utils.md
@@ -19,7 +19,6 @@ Basic dependencies:
- OpenSSL
- pthreads
- libevent
-- libparc
- libhicntransport
## Executables
@@ -92,45 +91,59 @@ The command `hiperf` is a tool for performing network throughput measurements
with hicn. It can be executed as server or client using the following options:
```bash
+HIPERF - Instrumentation tool for performing active networkmeasurements with hICN
usage: hiperf [-S|-C] [options] [prefix|name]
SERVER OR CLIENT:
--D = Run as a daemon
--R = Run RTC protocol (client or server)
--f <filename> = Log file
+-D Run as a daemon
+-R Run RTC protocol (client or server)
+-f <filename> Log file
+-z <io_module> IO module to use. Default: hicnlightng_module
+-F <conf_file> Path to optional configuration file for libtransport
+-a Enables data packet aggregation. Works only in RTC mode
+-X <param> Set FEC params. Options are Rely_K#_N# or RS_K#_N#
SERVER SPECIFIC:
--A <content_size> = Size of the content to publish. This is not the size of the packet (see -s for it).
--s <packet_size> = Size of the payload of each data packet.
--r = Produce real content of <content_size> bytes
--m = Produce transport manifest
--l = Start producing content upon the reception of the first interest
--K <keystore_path> = Path of p12 file containing the crypto material used for signing packets
--k <passphrase> = String from which a 128-bit symmetric key will be derived for signing packets
--y <hash_algorithm> = Use the selected hash algorithm for calculating manifest digests
--p <password> = Password for p12 keystore
--x = Produce a content of <content_size>, then after downloading it produce a new content of <content_size> without resetting the suffix to 0.
--B <bitrate> = Bitrate for RTC producer, to be used with the -R option.
--I = Interactive mode, start/stop real time content production by pressing return. To be used with the -R option
--E = Enable encrypted communication. Requires the path to a p12 file containing the crypto material used for the TLS handshake
+-A <content_size> Sends an application data unit in bytes that is published once before exit
+-s <packet_size> Data packet payload size.
+-r Produce real content of <content_size> bytes
+-m <manifest_capacity> Produce transport manifest
+-l Start producing content upon the reception of the first interest
+-K <keystore_path> Path of p12 file containing the crypto material used for signing packets
+-k <passphrase> String from which a 128-bit symmetric key will be derived for signing packets
+-p <password> Password for p12 keystore
+-y <hash_algorithm> Use the selected hash algorithm for computing manifest digests (default: SHA256)
+-x Produces application data units of size <content_size> without resetting the name suffix to 0.
+-B <bitrate> RTC producer data bitrate, to be used with the -R option.
+-I Interactive mode, start/stop real time content production by pressing return. To be used with the -R option
+-T <filename> Trace based mode, hiperf takes as input a file with a trace. Each line of the file indicates the timestamp and the size of the packet to generate. To be used with the -R option. -B and -I will be ignored.
+-E Enable encrypted communication. Requires the path to a p12 file containing the crypto material used for the TLS handshake
+-G <port> Input stream from localhost at the specified port
CLIENT SPECIFIC:
--b <beta_parameter> = RAAQM beta parameter
--d <drop_factor_parameter> = RAAQM drop factor parameter
--L <interest lifetime> = Set interest lifetime.
--M <Download for real> = Store the content downloaded.
--W <window_size> = Use a fixed congestion window for retrieving the data.
--i <stats_interval> = Show the statistics every <stats_interval> milliseconds.
--v = Enable verification of received data
--c <certificate_path> = Path of the producer certificate to be used for verifying the origin of the packets received. Must be used with -v.
--k <passphrase> = String from which is derived the symmetric key used by the producer to sign packets and by the consumer to verify them. Must be used with -v.
--t = Test mode, check if the client is receiving the correct data. This is an RTC specific option, to be used with the -R (default false)
--P = Prefix of the producer where to do the handshake
+-b <beta_parameter> RAAQM beta parameter
+-d <drop_factor_parameter> RAAQM drop factor parameter
+-L <interest lifetime> Set interest lifetime.
+-u <delay> Set max lifetime of unverified packets.
+-M <input_buffer_size> Size of consumer input buffer. If 0, reassembly of packets will be disabled.
+-W <window_size> Use a fixed congestion window for retrieving the data.
+-i <stats_interval> Show the statistics every <stats_interval> milliseconds.
+-c <certificate_path> Path of the producer certificate to be used for verifying the origin of the packets received.
+-k <passphrase> String from which is derived the symmetric key used by the producer to sign packets and by the consumer to verify them.
+-t Test mode, check if the client is receiving the correct data. This is an RTC specific option, to be used with the -R (default: false)
+-P Prefix of the producer where to do the handshake
+-j <relay_name> Publish received content under the name relay_name.This is an RTC specific option, to be used with the -R (default: false)
+-g <port> Output stream to localhost at the specified port
+-e <strategy> Enance the network with a realiability 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)
+-H Disable periodic print headers in stats report.
+-n <nb_iterations> Print the stats report <nb_iterations> times and exit.
+ This option limits the duration of the run to <nb_iterations> * <stats_interval> milliseconds.
```
Example:
```
-hiperf -S c001::/64
+hiperf -S b001::/64
+hiperf -C b001::
```
## Client/Server benchmarking using `hiperf`
@@ -161,8 +174,7 @@ apt-get install -y git \
build-essential \
libasio-dev \
libcurl4-openssl-dev \
- --no-install-recommends \
- libparc-dev
+ --no-install-recommends
mkdir hicn-suite && cd hicn-suite
git clone https://github.com/FDio/hicn.git hicn-src
mkdir hicn-build && cd hicn-build
@@ -289,8 +301,7 @@ apt-get install -y git \
vpp vpp-dev vpp-plugin-core libvppinfra \
libmemif libmemif-dev \
python3-ply \
- --no-install-recommends \
- libparc-dev
+ --no-install-recommends
mkdir hicn-suite && cd hicn-suite
git clone https://github.com/FDio/hicn.git hicn-src
mkdir hicn-build && cd hicn-build
diff --git a/docs/source/vpp-plugin.md b/docs/source/vpp-plugin.md
index 7f49cd8b9..b6b469494 100644
--- a/docs/source/vpp-plugin.md
+++ b/docs/source/vpp-plugin.md
@@ -22,7 +22,7 @@ mkdir -p build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make
-sudo make install
+sudo cmake --build . -- install
```
VPP source code - build type `RELEASE`:
@@ -32,7 +32,7 @@ mkdir -p build
cd build
cmake .. -DVPP_HOME=<vpp dir>/build-root/install-vpp-native/vpp -DCMAKE_INSTALL_PREFIX=<vpp src>/build-root/install-vpp-native/vpp
make
-sudo make install
+cmake --build . -- install
```
VPP source code - build type `DEBUG`:
@@ -42,7 +42,7 @@ mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DVPP_HOME=<vpp dir>/build-root/install-vpp_debug-native/vpp -DCMAKE_INSTALL_PREFIX=<vpp src>/build-root/install-vpp_debug-native/vpp
make
-sudo make install
+cmake --build . -- install
```
CMAKE variables:
@@ -57,7 +57,7 @@ CMAKE variables:
Build dependencies:
-- VPP 20.01
+- VPP 22.02
- DEB packages (can be found <https://packagecloud.io/fdio/release/install):>
- vpp
- libvppinfra-dev
@@ -65,11 +65,11 @@ Build dependencies:
Runtime dependencies:
-- VPP 20.01
+- VPP 22.02
- DEB packages (can be found <https://packagecloud.io/fdio/release/install):>
- vpp
- vpp-plugin-core
- - vpp-plugin-dpdk (only to use DPDK compatible nics)
+ - vpp-plugin-dpdk (optional - only to use DPDK compatible nics)
Hardware support (not mandatory):
@@ -91,7 +91,7 @@ Detailed information for configuring VPP can be found at
### Setup the host for VPP
-Hugepages must be enabled in the system.
+It is preferable to have hugepages enabled in the system, although it is not a requirement:
```bash
sudo sysctl -w vm.nr_hugepages=1024
@@ -163,7 +163,7 @@ interface.
VPP can be started as a process or a service:
-Start VPP as a service in Ubuntu 16.04+:
+Start VPP as a service in Ubuntu 20.04+:
```bash
sudo systemctl start vpp
```
@@ -299,22 +299,22 @@ vpp# set interface ip address TenGigabitEtherneta/0/1 2001::3/64
vpp# set interface state TenGigabitEtherneta/0/1 up
```
-Once the two forwarder are started, run the `ping_server` application on the
+Once the two forwarder are started, run the `hicn-ping-server` application on the
host where the forwarder B is running:
```bash
-sudo ping_server -n b002::1
+sudo hicn-ping-server -n b002::1/128 -z memif_module
```
-Then `ping_client` on the host where forwarder B is running:
+Then `hicn-ping-client` on the host where forwarder B is running:
```bash
-sudo ping_client -n b002::1
+sudo hicn-ping-client -n b002::1 -z memif_module
```
### Example: packet generator
-The packet generator can be used to test the performace of the hICN plugin, as
+The packet generator can be used to test the performance of the hICN plugin, as
well as a tool to inject packet in a forwarder or network for other test use
cases It is made of two entities, a client that inject interest into a vpp
forwarder and a server that replies to any interest with the corresponding
diff --git a/extras/CMakeLists.txt b/extras/CMakeLists.txt
index 4cda43992..1683902db 100644
--- a/extras/CMakeLists.txt
+++ b/extras/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -17,6 +17,7 @@ list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules
)
+include("${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake")
set (DESTDIR ${CMAKE_BINARY_DIR}/extras-root)
# add_subdirectory(router-plugin)
diff --git a/extras/libmemif/CMakeLists.txt b/extras/libmemif/CMakeLists.txt
deleted file mode 100644
index dab69c56f..000000000
--- a/extras/libmemif/CMakeLists.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-cmake_minimum_required(VERSION 3.10)
-project(libmemif)
-
-list(APPEND MODULE_PATH
- ${CMAKE_MODULE_PATH}
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
-)
-
-string(REPLACE ";" "|" MODULE_PATH "${MODULE_PATH}")
-
-include(ExternalProject)
-
-ExternalProject_Add(libmemif
- GIT_REPOSITORY https://github.com/FDio/vpp.git
- GIT_TAG v21.06
- GIT_SHALLOW TRUE
- PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libmemif
- PATCH_COMMAND bash -c "cp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists1.patch ./extras/libmemif/CMakeLists.txt && cp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists2.patch ./extras/libmemif/src/CMakeLists.txt"
- # Use the alternate list separator
- # (https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#lists)
- LIST_SEPARATOR |
- CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_MODULE_PATH=${MODULE_PATH}
- SOURCE_SUBDIR ./extras/libmemif
- BUILD_COMMAND ${CMAKE_COMMAND} --build . -- package
-)
-
-if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
- make_packages()
-endif()
diff --git a/extras/libmemif/CMakeLists1.patch b/extras/libmemif/CMakeLists1.patch
deleted file mode 100644
index adf41a417..000000000
--- a/extras/libmemif/CMakeLists1.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright (c) 2017 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-project(memif)
-set(CMAKE_C_STANDARD 11)
-
-list(APPEND CMAKE_MODULE_PATH
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake
-)
-
-include(CheckCCompilerFlag)
-include(CheckFunctionExists)
-
-execute_process(
- COMMAND find ${VPP_SRC} -type d -name "cmake"
- OUTPUT_VARIABLE CMAKE_DEPS_FOLDER
- OUTPUT_STRIP_TRAILING_WHITESPACE
-)
-include(BuildMacros)
-
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif ()
-
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -DMEMIF_DBG -DICMP_DBG")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
-set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
-set(CMAKE_INSTALL_MESSAGE NEVER)
-
-find_package(Threads REQUIRED)
-include_directories(${CMAKE_THREADS_INCLUDE_DIRS})
-
-check_function_exists(memfd_create HAVE_MEMFD_CREATE)
-if(${HAVE_MEMFD_CREATE})
- add_definitions(-DHAVE_MEMFD_CREATE)
-endif()
-
-include_directories(src)
-set(LIBMEMIF memif)
-set(COMPONENT libmemif)
-set(LIBMEMIF_SHARED ${LIBMEMIF}.shared)
-
-set(LIBMEMIF_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR}
- "" CACHE INTERNAL
- "" FORCE
-)
-
-set(LIBMEMIF_LIBRARIES
- ${LIBMEMIF_SHARED}
- "" CACHE INTERNAL
- "" FORCE
-)
-
-include (Packaging)
-
-add_subdirectory(src)
-
-if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
- make_packages()
-endif() \ No newline at end of file
diff --git a/extras/libmemif/CMakeLists2.patch b/extras/libmemif/CMakeLists2.patch
deleted file mode 100644
index 1a02cd725..000000000
--- a/extras/libmemif/CMakeLists2.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (c) 2017 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-
-list(APPEND MEMIF_HEADERS
- libmemif.h
- memif.h
-)
-
-list(APPEND MEMIF_PRIVATE_HEADERS
- memif_private.h
- socket.h
-)
-
-list(APPEND MEMIF_SOURCES
- main.c
- socket.c
-)
-
-include_directories(${HEADERS_DIR})
-
-build_library(${LIBMEMIF}
- SHARED
- SOURCES ${MEMIF_SOURCES}
- INSTALL_HEADERS ${MEMIF_HEADERS}
- LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}
- HEADER_ROOT_DIR memif
- COMPONENT ${COMPONENT}
-)
-
-remove_flag_from_target(${LIBMEMIF_SHARED} -Werror) \ No newline at end of file
diff --git a/extras/libmemif/cmake/Modules/Packaging.cmake b/extras/libmemif/cmake/Modules/Packaging.cmake
deleted file mode 100644
index 2b0f54200..000000000
--- a/extras/libmemif/cmake/Modules/Packaging.cmake
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-######################
-# Packages section
-######################
-
-set(${COMPONENT}_DESCRIPTION
- "Libmemif, shared memory interface"
- CACHE STRING "Description for deb/rpm package."
-)
-
-set(${COMPONENT}_DEB_DEPENDENCIES
- "" CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${COMPONENT}_RPM_DEPENDENCIES
- "" CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${COMPONENT}-dev_DESCRIPTION
- "Libmemif, shared memory interface header files"
- CACHE STRING "Description for deb/rpm package."
-)
-
-set(${COMPONENT}-dev_DEB_DEPENDENCIES
- "${COMPONENT} (>= stable_version)"
- CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${COMPONENT}-dev_RPM_DEPENDENCIES
- "${COMPONENT} >= stable_version"
- CACHE STRING "Dependencies for deb/rpm package."
-)
diff --git a/extras/libyang/CMakeLists.txt b/extras/libyang/CMakeLists.txt
index 1956d185a..3dec9c5fb 100644
--- a/extras/libyang/CMakeLists.txt
+++ b/extras/libyang/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# 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:
diff --git a/extras/libyang/cmake/Modules/Packaging.cmake b/extras/libyang/cmake/Modules/Packaging.cmake
index 853b18e58..9a7738196 100644
--- a/extras/libyang/cmake/Modules/Packaging.cmake
+++ b/extras/libyang/cmake/Modules/Packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/extras/packethicn/CMakeLists.txt b/extras/packethicn/CMakeLists.txt
index cb168ae1f..a4615708a 100644
--- a/extras/packethicn/CMakeLists.txt
+++ b/extras/packethicn/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,19 +11,39 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5)
+##############################################################
+# Project and cmake version
+##############################################################
+cmake_minimum_required(VERSION 3.10)
cmake_policy(SET CMP0048 NEW)
-
project(packethicn VERSION 0.0.1 DESCRIPTION "hICN protocol plugin" LANGUAGES C)
+
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
)
+
+##############################################################
+# Naming
+##############################################################
set(PACKETHICN packethicn)
+
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
+
+
+##############################################################
+# Dependencies and third party libs
+##############################################################
if(APPLE)
find_package(Wireshark CONFIG REQUIRED
PATHS /usr/local/opt/wireshark/lib/wireshark/cmake/ /usr/local/Cellar/wireshark/*/lib/wireshark/cmake
@@ -35,8 +55,21 @@ endif()
MATH(EXPR Wireshark_PATCH_NEXT_VERSION "${Wireshark_PATCH_VERSION}+1")
set(Wireshark_NEXT_VERSION ${Wireshark_MAJOR_VERSION}.${Wireshark_MINOR_VERSION}.${Wireshark_PATCH_NEXT_VERSION})
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(Libhicn REQUIRED)
+ include(CommonSetup)
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
+
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+
+ list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE})
else()
if(DISABLE_SHARED_LIBRARIES)
if(WIN32)
@@ -55,39 +88,56 @@ else()
endif()
endif()
+
+##############################################################
+# Check if wiresharks supports plugins
+##############################################################
if(NOT Wireshark_PLUGINS_ENABLED)
message(FATAL_ERROR "Wireshark was compiled without support for plugins")
endif()
+
+##############################################################
+# Compilaer flags
+##############################################################
set(CMAKE_C_VISIBILITY_PRESET hidden)
-if (CMAKE_COMPILER_IS_GNUCC)
- set(CMAKE_C_FLAGS "-Wall -Wextra ${CMAKE_C_FLAGS}")
-endif()
+
+##############################################################
+# Compiler definitions
+##############################################################
set(COMPILER_DEFINITIONS -DVERSION=\"${PROJECT_VERSION}\")
+
+##############################################################
+# Sources
+##############################################################
set(SOURCE_FILES
packet-hicn.c
)
+
+##############################################################
+# Include dirs
+##############################################################
list(APPEND PACKETHICN_INCLUDE_DIRS
${HICN_INCLUDE_DIRS}
)
+
+##############################################################
+# Libraries
+##############################################################
list(APPEND LIBRARIES
${HICN_LIBRARIES}
epan
)
-if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- set(LIBHICN hicn CACHE INTERNAL "" FORCE)
-endif()
-
-include(Packaging)
-include(BuildMacros)
+##############################################################
+# Build library
+##############################################################
build_library(${PACKETHICN}
- MODULE
SOURCES ${SOURCE_FILES}
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
@@ -95,10 +145,12 @@ build_library(${PACKETHICN}
INCLUDE_DIRS ${PACKETHICN_INCLUDE_DIRS}
INSTALL_FULL_PATH_DIR ${Wireshark_PLUGIN_INSTALL_DIR}/epan
DEFINITIONS ${COMPILER_DEFINITIONS}
- EMPTY_PREFIX true
)
+
+##############################################################
+# Make package if needed
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
make_packages()
endif() \ No newline at end of file
diff --git a/extras/packethicn/cmake/Modules/Packaging.cmake b/extras/packethicn/cmake/packaging.cmake
index 5bea05c3c..b7a7f4552 100644
--- a/extras/packethicn/cmake/Modules/Packaging.cmake
+++ b/extras/packethicn/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -21,11 +21,11 @@ set(${PACKETHICN}_DESCRIPTION
)
set(${PACKETHICN}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), wireshark (>= ${Wireshark_VERSION}), wireshark (<< ${Wireshark_NEXT_VERSION})"
+ "lib${LIBHICN} (= stable_version), wireshark (>= ${Wireshark_VERSION}), wireshark (<< ${Wireshark_NEXT_VERSION})"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${PACKETHICN}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, wireshark >= ${Wireshark_VERSION}, wireshark < ${Wireshark_NEXT_VERSION}"
+ "lib${LIBHICN} = stable_version, wireshark >= ${Wireshark_VERSION}, wireshark < ${Wireshark_NEXT_VERSION}"
CACHE STRING "Dependencies for deb/rpm package."
) \ No newline at end of file
diff --git a/extras/packethicn/packet-hicn.c b/extras/packethicn/packet-hicn.c
index c17252bb7..87466fdbf 100644
--- a/extras/packethicn/packet-hicn.c
+++ b/extras/packethicn/packet-hicn.c
@@ -17,11 +17,11 @@
#include <gmodule.h>
#define WS_BUILD_DLL
-#include "ws_symbol_export.h"
#include "config.h"
+#include "ws_symbol_export.h"
-#include "epan/proto.h"
#include "epan/etypes.h"
+#include "epan/proto.h"
#include <hicn/hicn.h>
@@ -36,14 +36,14 @@
/* TCP-HICN flags */
#define FLAGS_BITS_LEN 8
#define FLAGS_MASK 0xFF
-#define TH_FIN 0x01
-#define TH_SYN 0x02
-#define TH_RST 0x04
-#define TH_ACK 0x10
-#define TH_CWR 0x80
-#define TH_ID 0x40
-#define TH_MAN 0x20
-#define TH_SIG 0x08
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_ACK 0x10
+#define TH_CWR 0x80
+#define TH_ID 0x40
+#define TH_MAN 0x20
+#define TH_SIG 0x08
#define HICN_PORT 9695
@@ -84,7 +84,6 @@ static gint ett_hicn_l3 = -1;
static gint ett_hicn_l4 = -1;
static gint ett_hicn_l4_flags = -1;
-
static uint8_t *_p_hdr = NULL;
bool is_interest(const hicn_header_t *header) {
@@ -97,39 +96,38 @@ bool is_interest(const hicn_header_t *header) {
// TODO: HANDLE ERRORS
-hicn_header_t *get_header(tvbuff_t *tvb, const gint offset, const gint length){
+hicn_header_t *get_header(tvbuff_t *tvb, const gint offset, const gint length) {
tvb_ensure_bytes_exist(tvb, offset, length);
- hicn_header_t *pkt_hdr = (hicn_header_t *) tvb_get_ptr(tvb, offset, length);
- _p_hdr = (uint8_t *) pkt_hdr;
+ hicn_header_t *pkt_hdr = (hicn_header_t *)tvb_get_ptr(tvb, offset, length);
+ _p_hdr = (uint8_t *)pkt_hdr;
return pkt_hdr;
}
-uint32_t get_offset(uint8_t *data_addr){
- return data_addr - _p_hdr;
-}
+uint32_t get_offset(uint8_t *data_addr) { return data_addr - _p_hdr; }
-static int
-dissect_hicn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
-{
+static int dissect_hicn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ void *data _U_) {
gint i = 0;
guint bpos;
hicn_header_t *pkt_hdr = get_header(tvb, 0, HICN_V6_TCP_HDRLEN);
wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
- static const gchar *flags[] = {"_FIN", "_SYN", "_RST", "SIG", "_ACK", "MAN", "ID", "_CWR"};
+ static const gchar *flags[] = {"_FIN", "_SYN", "_RST", "SIG",
+ "_ACK", "MAN", "ID", "_CWR"};
wmem_strbuf_append(flags_strbuf, "<None>");
- uint32_t flags_offset = get_offset((uint8_t *) &(pkt_hdr->v6.tcp.flags));
+ uint32_t flags_offset = get_offset((uint8_t *)&(pkt_hdr->v6.tcp.flags));
gboolean first_flag = TRUE;
- for(i=0; i<9; i++) {
+ for (i = 0; i < 9; i++) {
bpos = 1 << i;
- if(pkt_hdr->v6.tcp.flags & bpos) {
- if(first_flag) {
+ if (pkt_hdr->v6.tcp.flags & bpos) {
+ if (first_flag) {
wmem_strbuf_truncate(flags_strbuf, 0);
}
- wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]);
+ wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ",
+ flags[i]);
first_flag = FALSE;
}
}
@@ -138,99 +136,176 @@ dissect_hicn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
col_set_str(pinfo->cinfo, COL_PROTOCOL, "HICN");
col_clear(pinfo->cinfo, COL_INFO);
- proto_item *ti = proto_tree_add_item(tree, proto_hicn, tvb, 0, HICN_V6_TCP_HDRLEN, ENC_NA);
+ proto_item *ti =
+ proto_tree_add_item(tree, proto_hicn, tvb, 0, HICN_V6_TCP_HDRLEN, ENC_NA);
proto_tree *hicn_tree = proto_item_add_subtree(ti, ett_hicn);
// L3
proto_item *ti_l3;
- proto_tree *hicn_l3_tree = proto_tree_add_subtree(hicn_tree, tvb, 0, IPV6_HDRLEN, ett_hicn_l3, &ti_l3, "HICN Layer 3");
+ proto_tree *hicn_l3_tree = proto_tree_add_subtree(
+ hicn_tree, tvb, 0, IPV6_HDRLEN, ett_hicn_l3, &ti_l3, "HICN Layer 3");
- if(is_interest(pkt_hdr)){
+ if (is_interest(pkt_hdr)) {
proto_item_append_text(ti, ", Interest Packet");
col_set_str(pinfo->cinfo, COL_INFO, "Interest Packet");
- proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_src, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.saddr)), sizeof(pkt_hdr->v6.ip.saddr), ENC_BIG_ENDIAN);
- proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_dst_interest, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.daddr)), sizeof(pkt_hdr->v6.ip.daddr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_src, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.ip.saddr)),
+ sizeof(pkt_hdr->v6.ip.saddr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_dst_interest, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.ip.daddr)),
+ sizeof(pkt_hdr->v6.ip.daddr), ENC_BIG_ENDIAN);
} else {
// TODO: NEW LABEL FOR NACKS
proto_item_append_text(ti, ", Data Packet");
col_set_str(pinfo->cinfo, COL_INFO, "Data Packet");
- proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_src_data, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.saddr)), sizeof(pkt_hdr->v6.ip.saddr), ENC_BIG_ENDIAN);
- proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_dst, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.daddr)), sizeof(pkt_hdr->v6.ip.daddr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_src_data, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.ip.saddr)),
+ sizeof(pkt_hdr->v6.ip.saddr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_dst, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.ip.daddr)),
+ sizeof(pkt_hdr->v6.ip.daddr), ENC_BIG_ENDIAN);
}
// L4
proto_item *ti_l4;
- proto_tree *hicn_l4_tree = proto_tree_add_subtree(hicn_tree, tvb, IPV6_HDRLEN, TCP_HDRLEN, ett_hicn_l4, &ti_l4, "HICN Layer 4");
-
- proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_namesuffix, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.name_suffix)), sizeof(pkt_hdr->v6.tcp.name_suffix), ENC_BIG_ENDIAN);
- proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_pathlabel, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.pathlabel))+PATHLABEL_PAD_LEN, sizeof(pkt_hdr->v6.tcp.pathlabel), ENC_BIG_ENDIAN);
- proto_item *ti_l4_ts = proto_tree_add_bits_item(hicn_l4_tree, hf_hicn_tcp_timescale, tvb,
- get_offset((uint8_t *) &(pkt_hdr->v6.tcp.data_offset_and_reserved))*8 + TIMESCALE_BITS_OFFSET, TIMESCALE_BITS_LENGTH, ENC_BIG_ENDIAN);
- proto_item_append_text(ti_l4_ts, " (Lifetime scaling factor: %dx)", pkt_hdr->v6.tcp.timescale+1);
- proto_item *hicn_l4_flags_tree = proto_tree_add_uint_format_value(hicn_l4_tree, hf_hicn_tcp_flags, tvb,
- get_offset((uint8_t *) &(pkt_hdr->v6.tcp.flags)), 1, pkt_hdr->v6.tcp.flags, "0x%02x (%s)", pkt_hdr->v6.tcp.flags, wmem_strbuf_get_str(flags_strbuf)
- );
- proto_tree *field_tree = proto_item_add_subtree(hicn_l4_flags_tree, ett_hicn_l4_flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_cwr, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_id, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_man, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_ack, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_sig, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_rst, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_syn, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_fin, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
- proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_ldr, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.ldr)), sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
- proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_csum, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.csum)), sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
- proto_item *ti_l4_lt = proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_lifetime, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.lifetime)), sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
+ proto_tree *hicn_l4_tree =
+ proto_tree_add_subtree(hicn_tree, tvb, IPV6_HDRLEN, TCP_HDRLEN,
+ ett_hicn_l4, &ti_l4, "HICN Layer 4");
+
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_namesuffix, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.name_suffix)),
+ sizeof(pkt_hdr->v6.tcp.name_suffix), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_pathlabel, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.pathlabel)) +
+ PATHLABEL_PAD_LEN,
+ sizeof(pkt_hdr->v6.tcp.pathlabel), ENC_BIG_ENDIAN);
+ proto_item *ti_l4_ts = proto_tree_add_bits_item(
+ hicn_l4_tree, hf_hicn_tcp_timescale, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.data_offset_and_reserved)) * 8 +
+ TIMESCALE_BITS_OFFSET,
+ TIMESCALE_BITS_LENGTH, ENC_BIG_ENDIAN);
+ proto_item_append_text(ti_l4_ts, " (Lifetime scaling factor: %dx)",
+ pkt_hdr->v6.tcp.timescale + 1);
+ proto_item *hicn_l4_flags_tree = proto_tree_add_uint_format_value(
+ hicn_l4_tree, hf_hicn_tcp_flags, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.flags)), 1, pkt_hdr->v6.tcp.flags,
+ "0x%02x (%s)", pkt_hdr->v6.tcp.flags, wmem_strbuf_get_str(flags_strbuf));
+ proto_tree *field_tree =
+ proto_item_add_subtree(hicn_l4_flags_tree, ett_hicn_l4_flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_cwr, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_id, tvb, flags_offset, 1,
+ pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_man, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_ack, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_sig, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_rst, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_syn, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_fin, tvb, flags_offset,
+ 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_ldr, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.ldr)),
+ sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_csum, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.csum)),
+ sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
+ proto_item *ti_l4_lt =
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_lifetime, tvb,
+ get_offset((uint8_t *)&(pkt_hdr->v6.tcp.lifetime)),
+ sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
proto_item_append_text(ti_l4_lt, " milliseconds");
dissector_handle_t data_handle = find_dissector("data");
- call_dissector(data_handle, tvb_new_subset_remaining(tvb, HICN_V6_TCP_HDRLEN), pinfo, tree);
+ call_dissector(data_handle, tvb_new_subset_remaining(tvb, HICN_V6_TCP_HDRLEN),
+ pinfo, tree);
return tvb_captured_length(tvb);
}
-static void
-proto_register_hicn(void)
-{
+static void proto_register_hicn(void) {
static hf_register_info hf[] = {
- { &hf_hicn_ipv6_src, { "Source Address", "hicn.l3.src", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_ipv6_src_data, { "Name Prefix", "hicn.l3.src", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_ipv6_dst, { "Destination Address", "hicn.l3.dst", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_ipv6_dst_interest, { "Name Prefix", "hicn.l3.dst", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_namesuffix, { "Name Suffix", "hicn.l4.namesuffix", FT_UINT32, BASE_HEX_DEC , NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_pathlabel, { "Path Label", "hicn.l4.pathlabel", FT_UINT8, BASE_HEX_DEC , NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_hdrlen_timescale, { "Header length and Timescale", "hicn.l4.hdrlen_ts", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_hdrlen, { "Header length", "hicn.l4.hdrlen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_timescale, { "Timescale", "hicn.l4.timescale", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_flags, { "Flags", "hicn.l4.flags", FT_UINT8, BASE_HEX, NULL, FLAGS_MASK, NULL, HFILL }},
- { &hf_hicn_tcp_flags_cwr, { "_CWR", "hicn.l4.flags.cwr", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_CWR, NULL, HFILL }},
- { &hf_hicn_tcp_flags_id, { "ID", "hicn.l4.flags.id", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset),TH_ID, NULL, HFILL }},
- { &hf_hicn_tcp_flags_man, { "MAN", "hicn.l4.flags.man", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_MAN, NULL, HFILL }},
- { &hf_hicn_tcp_flags_ack, { "_ACK", "hicn.l4.flags.ack", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_ACK, NULL, HFILL }},
- { &hf_hicn_tcp_flags_sig, { "SIG", "hicn.l4.flags.sig", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_SIG, NULL, HFILL }},
- { &hf_hicn_tcp_flags_rst, { "_RST", "hicn.l4.flags.reset", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_RST, NULL, HFILL }},
- { &hf_hicn_tcp_flags_syn, { "_SYN", "hicn.l4.flags.syn", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_SYN, NULL, HFILL }},
- { &hf_hicn_tcp_flags_fin, { "_FIN", "hicn.l4.flags.fin", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_FIN, NULL, HFILL }},
- { &hf_hicn_tcp_ldr, { "Loss Detection and Recovery", "hicn.l4.ldr", FT_UINT16, BASE_HEX , NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_csum, { "Checksum", "hicn.l4.csum", FT_UINT16, BASE_HEX , NULL, 0x0, NULL, HFILL }},
- { &hf_hicn_tcp_lifetime, { "Lifetime", "hicn.l4.lifetime", FT_UINT16, BASE_DEC , NULL, 0x0, NULL, HFILL }}
- };
+ {&hf_hicn_ipv6_src,
+ {"Source Address", "hicn.l3.src", FT_IPv6, BASE_NONE, NULL, 0x0, NULL,
+ HFILL}},
+ {&hf_hicn_ipv6_src_data,
+ {"Name Prefix", "hicn.l3.src", FT_IPv6, BASE_NONE, NULL, 0x0, NULL,
+ HFILL}},
+ {&hf_hicn_ipv6_dst,
+ {"Destination Address", "hicn.l3.dst", FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_hicn_ipv6_dst_interest,
+ {"Name Prefix", "hicn.l3.dst", FT_IPv6, BASE_NONE, NULL, 0x0, NULL,
+ HFILL}},
+ {&hf_hicn_tcp_namesuffix,
+ {"Name Suffix", "hicn.l4.namesuffix", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_hicn_tcp_pathlabel,
+ {"Path Label", "hicn.l4.pathlabel", FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_hicn_tcp_hdrlen_timescale,
+ {"Header length and Timescale", "hicn.l4.hdrlen_ts", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL}},
+ {&hf_hicn_tcp_hdrlen,
+ {"Header length", "hicn.l4.hdrlen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL,
+ HFILL}},
+ {&hf_hicn_tcp_timescale,
+ {"Timescale", "hicn.l4.timescale", FT_UINT8, BASE_DEC, NULL, 0x0, NULL,
+ HFILL}},
+ {&hf_hicn_tcp_flags,
+ {"Flags", "hicn.l4.flags", FT_UINT8, BASE_HEX, NULL, FLAGS_MASK, NULL,
+ HFILL}},
+ {&hf_hicn_tcp_flags_cwr,
+ {"_CWR", "hicn.l4.flags.cwr", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_CWR, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_id,
+ {"ID", "hicn.l4.flags.id", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_ID, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_man,
+ {"MAN", "hicn.l4.flags.man", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_MAN, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_ack,
+ {"_ACK", "hicn.l4.flags.ack", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_ACK, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_sig,
+ {"SIG", "hicn.l4.flags.sig", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_SIG, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_rst,
+ {"_RST", "hicn.l4.flags.reset", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_RST, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_syn,
+ {"_SYN", "hicn.l4.flags.syn", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_SYN, NULL, HFILL}},
+ {&hf_hicn_tcp_flags_fin,
+ {"_FIN", "hicn.l4.flags.fin", FT_BOOLEAN, FLAGS_BITS_LEN,
+ TFS(&tfs_set_notset), TH_FIN, NULL, HFILL}},
+ {&hf_hicn_tcp_ldr,
+ {"Loss Detection and Recovery", "hicn.l4.ldr", FT_UINT16, BASE_HEX, NULL,
+ 0x0, NULL, HFILL}},
+ {&hf_hicn_tcp_csum,
+ {"Checksum", "hicn.l4.csum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL,
+ HFILL}},
+ {&hf_hicn_tcp_lifetime,
+ {"Lifetime", "hicn.l4.lifetime", FT_UINT16, BASE_DEC, NULL, 0x0, NULL,
+ HFILL}}};
static gint *ett[] = {
- &ett_hicn,
- &ett_hicn_l3,
- &ett_hicn_l4,
- &ett_hicn_l4_flags,
+ &ett_hicn,
+ &ett_hicn_l3,
+ &ett_hicn_l4,
+ &ett_hicn_l4_flags,
};
- proto_hicn = proto_register_protocol ("Hybrid Information-Centric Networking Protocol", "HICN", "hicn");
+ proto_hicn = proto_register_protocol(
+ "Hybrid Information-Centric Networking Protocol", "HICN", "hicn");
proto_register_field_array(proto_hicn, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
-static void
-proto_reg_handoff_hicn(void)
-{
+static void proto_reg_handoff_hicn(void) {
static dissector_handle_t hicn_handle;
hicn_handle = create_dissector_handle(dissect_hicn, proto_hicn);
@@ -239,8 +314,7 @@ proto_reg_handoff_hicn(void)
dissector_add_uint("ethertype", ETHERTYPE_IPv6, hicn_handle);
}
-void plugin_register(void)
-{
+void plugin_register(void) {
static proto_plugin plug_hicn;
plug_hicn.register_protoinfo = proto_register_hicn;
plug_hicn.register_handoff = proto_reg_handoff_hicn;
diff --git a/extras/router-plugin/.clang-format b/extras/router-plugin/.clang-format
new file mode 100644
index 000000000..351a70e20
--- /dev/null
+++ b/extras/router-plugin/.clang-format
@@ -0,0 +1,20 @@
+# Minimal clang-format version is 8
+
+BasedOnStyle: GNU
+UseTab: Always
+SpaceAfterCStyleCast: true
+SortIncludes: false
+AlignConsecutiveMacros: true
+BreakBeforeTernaryOperators: false
+BreakBeforeBinaryOperators: None
+ContinuationIndentWidth: 2
+
+ForEachMacros:
+ - 'clib_bitmap_foreach'
+ - 'pool_foreach'
+ - 'pool_foreach_index'
+ - 'vec_foreach'
+ - 'vec_foreach_backwards'
+ - 'vec_foreach_index'
+ - 'vec_foreach_index_backwards'
+ - 'vlib_foreach_rx_tx'
diff --git a/extras/router-plugin/CMakeLists.txt b/extras/router-plugin/CMakeLists.txt
index 81ad2e628..63594297a 100644
--- a/extras/router-plugin/CMakeLists.txt
+++ b/extras/router-plugin/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -29,7 +29,7 @@ set(HICN_EXTRA_PLUGIN hicn-router-plugin)
# Dependencies
-find_package(Vpp REQUIRED)
+find_package(Vpp ${VPP_DEFAULT_VERSION} REQUIRED)
include_directories(${VPP_INCLUDE_DIR})
@@ -66,7 +66,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wall -march=native -O3 -g")
elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -march=native -O0 -g")
- add_definitions(-DCLIB_DEBUG -fPIC -fstack-protector-all)
+ add_definitions(-DHICN_DDEBUG -DCLIB_DEBUG -fPIC -fstack-protector-all)
endif()
include_directories(SYSTEM)
diff --git a/extras/router-plugin/cmake/Modules/Packaging.cmake b/extras/router-plugin/cmake/Modules/Packaging.cmake
index 69f63971f..15a4f68b8 100644
--- a/extras/router-plugin/cmake/Modules/Packaging.cmake
+++ b/extras/router-plugin/cmake/Modules/Packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -15,17 +15,22 @@
# Packages section
######################
+##############################################################
+# Get VPP version
+##############################################################
+list(GET VPP_DEFAULT_VERSION 0 VPP_VERSION)
+
set(${HICN_EXTRA_PLUGIN}_DESCRIPTION
"A extra plugin to VPP."
CACHE STRING "Description for deb/rpm package."
)
set(${HICN_EXTRA_PLUGIN}_DEB_DEPENDENCIES
- "vpp (>= stable_version-release), vpp (<< next_version-release), vpp-plugin-core (>= stable_version-release), vpp-plugin-core (<< next_version-release)"
+ "vpp (= ${VPP_VERSION}-release), vpp-plugin-core (= ${VPP_VERSION}-release)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_EXTRA_PLUGIN}_RPM_DEPENDENCIES
- "vpp >= stable_version-release, vpp < next_version-release, vpp-plugins >= stable_version-release, vpp-plugins < next_version-release"
+ "vpp = ${VPP_VERSION}-release, vpp-plugins = ${VPP_VERSION}-release"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/extras/router-plugin/devices/rtnetlink/mapper.c b/extras/router-plugin/devices/rtnetlink/mapper.c
index ed4fa5634..410d5527d 100644
--- a/extras/router-plugin/devices/rtnetlink/mapper.c
+++ b/extras/router-plugin/devices/rtnetlink/mapper.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,254 +13,273 @@
* limitations under the License.
*/
+#include <vnet/fib/fib.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/lookup.h>
-#include <vnet/fib/fib.h>
-#include "netns.h"
#include "mapper.h"
+#include "netns.h"
+#include <hicn/util/sstrncpy.h>
-typedef struct {
+typedef struct
+{
int linux_ifindex;
u32 sw_if_index;
} mapper_map_t;
-typedef struct {
+typedef struct
+{
char nsname[RTNL_NETNS_NAMELEN + 1];
mapper_map_t *mappings;
- u32 netns_handle; //Used to receive notifications
- u32 v4fib_index; //One fib index for the namespace
+ u32 netns_handle; // Used to receive notifications
+ u32 v4fib_index; // One fib index for the namespace
u32 v6fib_index;
} mapper_ns_t;
-typedef struct {
+typedef struct
+{
mapper_ns_t *namespaces;
} mapper_main_t;
static mapper_main_t mapper_main;
-mapper_map_t *mapper_get_by_ifindex(mapper_ns_t *ns, int ifindex)
+mapper_map_t *
+mapper_get_by_ifindex (mapper_ns_t *ns, int ifindex)
{
mapper_map_t *map;
- pool_foreach(map, ns->mappings, {
- if (ifindex == map->linux_ifindex)
- return map;
- });
+ pool_foreach (map, ns->mappings, {
+ if (ifindex == map->linux_ifindex)
+ return map;
+ })
+ ;
return NULL;
}
-int mapper_add_del_route(mapper_ns_t *ns, ns_route_t *route, int del)
+int
+mapper_add_del_route (mapper_ns_t *ns, ns_route_t *route, int del)
{
mapper_main_t *mm = &mapper_main;
- clib_warning("NS %d %s %U", ns - mm->namespaces, del?"del":"add", format_ns_route, route);
+ clib_warning ("NS %d %s %U", ns - mm->namespaces, del ? "del" : "add",
+ format_ns_route, route);
- mapper_map_t *map = mapper_get_by_ifindex(ns, route->oif);
+ mapper_map_t *map = mapper_get_by_ifindex (ns, route->oif);
if (!map)
return 0;
- if (route->rtm.rtm_family == AF_INET6) {
-
- //Filter-out multicast
- if (route->rtm.rtm_dst_len >= 8 && route->dst[0] == 0xff)
- return 0;
-
- fib_prefix_t prefix;
- ip46_address_t nh;
-
- memset (&prefix, 0, sizeof (prefix));
- prefix.fp_len = route->rtm.rtm_dst_len;
- prefix.fp_proto = FIB_PROTOCOL_IP6;
- clib_memcpy (&prefix.fp_addr.ip6, route->dst, sizeof (prefix.fp_addr.ip6));
-
- memset (&nh, 0, sizeof (nh));
- clib_memcpy (&nh.ip6, route->gateway, sizeof (nh.ip6));
-
- fib_table_entry_path_add (ns->v6fib_index, &prefix, FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE, prefix.fp_proto,
- &nh, map->sw_if_index, ns->v6fib_index,
- 0 /* weight */,
- (fib_mpls_label_t *) MPLS_LABEL_INVALID,
- FIB_ROUTE_PATH_FLAG_NONE);
- } else {
- fib_prefix_t prefix;
- ip46_address_t nh;
-
- memset (&prefix, 0, sizeof (prefix));
- prefix.fp_len = route->rtm.rtm_dst_len;
- prefix.fp_proto = FIB_PROTOCOL_IP4;
- clib_memcpy (&prefix.fp_addr.ip4, route->dst, sizeof (prefix.fp_addr.ip4));
-
- memset (&nh, 0, sizeof (nh));
- clib_memcpy (&nh.ip4, route->gateway, sizeof (nh.ip4));
-
- fib_table_entry_path_add (ns->v4fib_index, &prefix, FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE, prefix.fp_proto,
- &nh, map->sw_if_index, ns->v4fib_index,
- 0 /* weight */,
- (fib_mpls_label_t *) MPLS_LABEL_INVALID,
- FIB_ROUTE_PATH_FLAG_NONE);
- }
+ if (route->rtm.rtm_family == AF_INET6)
+ {
+
+ // Filter-out multicast
+ if (route->rtm.rtm_dst_len >= 8 && route->dst[0] == 0xff)
+ return 0;
+
+ fib_prefix_t prefix;
+ ip_address_t nh;
+
+ memset (&prefix, 0, sizeof (prefix));
+ prefix.fp_len = route->rtm.rtm_dst_len;
+ prefix.fp_proto = FIB_PROTOCOL_IP6;
+ clib_memcpy (&prefix.fp_addr.ip6, route->dst,
+ sizeof (prefix.fp_addr.ip6));
+
+ memset (&nh, 0, sizeof (nh));
+ clib_memcpy (&nh.ip6, route->gateway, sizeof (nh.ip6));
+
+ fib_table_entry_path_add (
+ ns->v6fib_index, &prefix, FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE,
+ prefix.fp_proto, &nh, map->sw_if_index, ns->v6fib_index,
+ 0 /* weight */, (fib_mpls_label_t *) MPLS_LABEL_INVALID,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ }
+ else
+ {
+ fib_prefix_t prefix;
+ ip_address_t nh;
+
+ memset (&prefix, 0, sizeof (prefix));
+ prefix.fp_len = route->rtm.rtm_dst_len;
+ prefix.fp_proto = FIB_PROTOCOL_IP4;
+ clib_memcpy (&prefix.fp_addr.ip4, route->dst,
+ sizeof (prefix.fp_addr.ip4));
+
+ memset (&nh, 0, sizeof (nh));
+ clib_memcpy (&nh.ip4, route->gateway, sizeof (nh.ip4));
+
+ fib_table_entry_path_add (
+ ns->v4fib_index, &prefix, FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE,
+ prefix.fp_proto, &nh, map->sw_if_index, ns->v4fib_index,
+ 0 /* weight */, (fib_mpls_label_t *) MPLS_LABEL_INVALID,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ }
return 0;
}
static void
-mapper_netns_notify_cb(void *obj, netns_type_t type,
- u32 flags, uword opaque)
+mapper_netns_notify_cb (void *obj, netns_type_t type, u32 flags, uword opaque)
{
mapper_main_t *mm = &mapper_main;
mapper_ns_t *ns = &mm->namespaces[(u32) opaque];
- ASSERT(!pool_is_free_index(mm->namespaces, (u32) opaque));
+ ASSERT (!pool_is_free_index (mm->namespaces, (u32) opaque));
if (type != NETNS_TYPE_ROUTE)
- return; //For now...
+ return; // For now...
ns_route_t *route = obj;
- if (flags & NETNS_F_DEL) {
- mapper_add_del_route(ns, route, 1);
- } else if (flags & NETNS_F_ADD) {
- mapper_add_del_route(ns, route, 0);
- }
+ if (flags & NETNS_F_DEL)
+ {
+ mapper_add_del_route (ns, route, 1);
+ }
+ else if (flags & NETNS_F_ADD)
+ {
+ mapper_add_del_route (ns, route, 0);
+ }
}
void
-mapper_delmap(mapper_ns_t*ns, mapper_map_t *map)
+mapper_delmap (mapper_ns_t *ns, mapper_map_t *map)
{
ns_route_t *route;
- netns_t *netns = netns_getns(ns->netns_handle);
- pool_foreach(route, netns->routes, {
- if (route->oif == map->linux_ifindex)
- mapper_add_del_route(ns, route, 1);
- });
- pool_put(ns->mappings, map);
+ netns_t *netns = netns_getns (ns->netns_handle);
+ pool_foreach (route, netns->routes, {
+ if (route->oif == map->linux_ifindex)
+ mapper_add_del_route (ns, route, 1);
+ })
+ ;
+ pool_put (ns->mappings, map);
}
mapper_map_t *
-mapper_getmap(mapper_ns_t*ns, u32 sw_if_index,
- int linux_ifindex, int create)
+mapper_getmap (mapper_ns_t *ns, u32 sw_if_index, int linux_ifindex, int create)
{
mapper_map_t *map;
- pool_foreach(map, ns->mappings, {
- if (linux_ifindex == map->linux_ifindex) {
- if (sw_if_index != map->sw_if_index)
- return NULL; //Cannot have multiple mapping with the same ifindex
- else
- return map;
+ pool_foreach (map, ns->mappings, {
+ if (linux_ifindex == map->linux_ifindex)
+ {
+ if (sw_if_index != map->sw_if_index)
+ return NULL; // Cannot have multiple mapping with the same ifindex
+ else
+ return map;
}
- });
+ })
+ ;
if (!create)
return NULL;
- pool_get(ns->mappings, map);
+ pool_get (ns->mappings, map);
map->linux_ifindex = linux_ifindex;
map->sw_if_index = sw_if_index;
ip6_main.fib_index_by_sw_if_index[sw_if_index] = ns->v6fib_index;
ip4_main.fib_index_by_sw_if_index[sw_if_index] = ns->v4fib_index;
- //Load available routes
+ // Load available routes
ns_route_t *route;
- netns_t *netns = netns_getns(ns->netns_handle);
- pool_foreach(route, netns->routes, {
- if (route->oif == map->linux_ifindex)
- mapper_add_del_route(ns, route, 0);
- });
+ netns_t *netns = netns_getns (ns->netns_handle);
+ pool_foreach (route, netns->routes, {
+ if (route->oif == map->linux_ifindex)
+ mapper_add_del_route (ns, route, 0);
+ })
+ ;
return map;
}
u32
-mapper_get_ns(char *nsname)
+mapper_get_ns (char *nsname)
{
mapper_main_t *mm = &mapper_main;
mapper_ns_t *ns;
- pool_foreach(ns, mm->namespaces, {
- if (!strcmp(nsname, ns->nsname))
- return ns - mm->namespaces;
- });
+ pool_foreach (ns, mm->namespaces, {
+ if (!strcmp (nsname, ns->nsname))
+ return ns - mm->namespaces;
+ })
+ ;
return ~0;
}
int
-mapper_add_del(u32 nsindex, int linux_ifindex,
- u32 sw_if_index, int del)
+mapper_add_del (u32 nsindex, int linux_ifindex, u32 sw_if_index, int del)
{
mapper_main_t *mm = &mapper_main;
- //ip6_main_t *im6 = &ip6_main;
+ // ip6_main_t *im6 = &ip6_main;
mapper_ns_t *ns = &mm->namespaces[nsindex];
mapper_map_t *map;
- //vnet_sw_interface_t *iface = vnet_get_sw_interface(vnet_get_main(), sw_if_index);
+ // vnet_sw_interface_t *iface = vnet_get_sw_interface(vnet_get_main(),
+ // sw_if_index);
- if (pool_is_free(mm->namespaces, ns))
+ if (pool_is_free (mm->namespaces, ns))
return -1;
/*if (!del) {
if ((iface->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) &&
- im6->fib_index_by_sw_if_index[sw_if_index] != ~0) {
+ im6->fib_index_by_sw_if_index[sw_if_index] != ~0) {
//A custom fib index will be used...
- clib_warning("Cannot add interface with a custom fib index (current is %d)",
- im6->fib_index_by_sw_if_index[sw_if_index]);
- return -1;
+ clib_warning("Cannot add interface with a custom fib index (current is
+ %d)", im6->fib_index_by_sw_if_index[sw_if_index]); return -1;
}
}*/
- if (!(map = mapper_getmap(ns, sw_if_index, linux_ifindex, !del)))
+ if (!(map = mapper_getmap (ns, sw_if_index, linux_ifindex, !del)))
return -1;
if (del)
- mapper_delmap(ns, map);
+ mapper_delmap (ns, map);
return 0;
}
int
-mapper_add_ns(char *nsname, u32 v4fib_index, u32 v6fib_index, u32 *nsindex)
+mapper_add_ns (char *nsname, u32 v4fib_index, u32 v6fib_index, u32 *nsindex)
{
mapper_main_t *mm = &mapper_main;
mapper_ns_t *ns;
- if (mapper_get_ns(nsname) != ~0)
- return -1; //Already exists
+ if (mapper_get_ns (nsname) != ~0)
+ return -1; // Already exists
- pool_get(mm->namespaces, ns);
- strcpy(ns->nsname, nsname);
+ pool_get (mm->namespaces, ns);
+ int rc = strcpy_s (ns->nsname, sizeof (ns->nsname), nsname);
+ if (rc != EOK)
+ return -1;
ns->v4fib_index = v4fib_index;
ns->v6fib_index = v6fib_index;
ns->mappings = 0;
netns_sub_t sub;
sub.notify = mapper_netns_notify_cb;
- sub.opaque = (uword)(ns - mm->namespaces);
- if ((ns->netns_handle = netns_open(ns->nsname, &sub)) == ~0) {
- pool_put(mm->namespaces, ns);
- return -1;
- }
+ sub.opaque = (uword) (ns - mm->namespaces);
+ if ((ns->netns_handle = netns_open (ns->nsname, &sub)) == ~0)
+ {
+ pool_put (mm->namespaces, ns);
+ return -1;
+ }
*nsindex = ns - mm->namespaces;
return 0;
}
int
-mapper_del_ns(u32 nsindex)
+mapper_del_ns (u32 nsindex)
{
mapper_main_t *mm = &mapper_main;
mapper_ns_t *ns = &mm->namespaces[nsindex];
- if (pool_is_free(mm->namespaces, ns))
+ if (pool_is_free (mm->namespaces, ns))
return -1;
- //Remove all existing mappings
+ // Remove all existing mappings
int i, *indexes = 0;
- pool_foreach_index(i, ns->mappings, {
- vec_add1(indexes, i);
- });
- vec_foreach_index(i, indexes) {
- mapper_delmap(ns, &ns->mappings[indexes[i]]);
- }
- vec_free(indexes);
-
- netns_close(ns->netns_handle);
- pool_put(mm->namespaces, ns);
+ pool_foreach_index (i, ns->mappings, { vec_add1 (indexes, i); })
+ ;
+ vec_foreach_index (i, indexes)
+ {
+ mapper_delmap (ns, &ns->mappings[indexes[i]]);
+ }
+ vec_free (indexes);
+
+ netns_close (ns->netns_handle);
+ pool_put (mm->namespaces, ns);
return 0;
}
clib_error_t *
-mapper_init (vlib_main_t * vm)
+mapper_init (vlib_main_t *vm)
{
mapper_main_t *mm = &mapper_main;
mm->namespaces = 0;
diff --git a/extras/router-plugin/devices/rtnetlink/mapper.h b/extras/router-plugin/devices/rtnetlink/mapper.h
index 32e95d48f..436e5dc4d 100644
--- a/extras/router-plugin/devices/rtnetlink/mapper.h
+++ b/extras/router-plugin/devices/rtnetlink/mapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -28,8 +28,9 @@
* A mapped VPP interface must not have any configured fib.
*/
-int mapper_add_ns(char *nsname, u32 v4fib_index, u32 v6fib_index, u32 *nsindex);
-int mapper_del_ns(u32 nsindex);
-int mapper_add_del(u32 nsindex, int linux_ifindex, u32 sw_if_index, int del);
+int mapper_add_ns (char *nsname, u32 v4fib_index, u32 v6fib_index,
+ u32 *nsindex);
+int mapper_del_ns (u32 nsindex);
+int mapper_add_del (u32 nsindex, int linux_ifindex, u32 sw_if_index, int del);
#endif /* MAPPER_H_ */
diff --git a/extras/router-plugin/devices/rtnetlink/netns.c b/extras/router-plugin/devices/rtnetlink/netns.c
index 19adb469a..0d9986185 100644
--- a/extras/router-plugin/devices/rtnetlink/netns.c
+++ b/extras/router-plugin/devices/rtnetlink/netns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,190 +13,197 @@
* limitations under the License.
*/
-
-#include <vlib/vlib.h>
+#include <stddef.h>
#include <vlib/unix/unix.h>
+#include <vlib/vlib.h>
#include <vnet/ethernet/ethernet.h>
+#include <vnet/ip/format.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
-#include <vnet/ip/format.h>
-#include <stddef.h>
#include "netns.h"
+#include <hicn/util/sstrncpy.h>
/* Enable some RTA values debug */
//#define RTNL_CHECK
-#define is_nonzero(x) \
- ({ \
- u8 __is_zero_zero[sizeof(x)] = {}; \
- memcmp(__is_zero_zero, &x, sizeof(x)); \
+#define is_nonzero(x) \
+ ({ \
+ u8 __is_zero_zero[sizeof (x)] = {}; \
+ memcmp (__is_zero_zero, &x, sizeof (x)); \
})
-typedef struct {
- u8 type; //Attribute identifier
- u8 unique; //Part of the values uniquely identifying an entry
- u16 offset; //Offset where stored in struct
- u16 size; //Length of the attribute
+typedef struct
+{
+ u8 type; // Attribute identifier
+ u8 unique; // Part of the values uniquely identifying an entry
+ u16 offset; // Offset where stored in struct
+ u16 size; // Length of the attribute
} rtnl_mapping_t;
-#define ns_foreach_ifla \
- _(IFLA_ADDRESS, hwaddr) \
- _(IFLA_BROADCAST, broadcast) \
- _(IFLA_IFNAME, ifname) \
- _(IFLA_MASTER, master) \
- _(IFLA_MTU, mtu) \
- _(IFLA_QDISC, qdisc)
+#define ns_foreach_ifla \
+ _ (IFLA_ADDRESS, hwaddr) \
+ _ (IFLA_BROADCAST, broadcast) \
+ _ (IFLA_IFNAME, ifname) \
+ _ (IFLA_MASTER, master) \
+ _ (IFLA_MTU, mtu) \
+ _ (IFLA_QDISC, qdisc)
static rtnl_mapping_t ns_ifmap[] = {
-#define _(t, e) \
- { \
- .type = t, \
- .offset = offsetof(ns_link_t, e), \
- .size = sizeof(((ns_link_t*)0)->e) \
- },
+#define _(t, e) \
+ { .type = t, \
+ .offset = offsetof (ns_link_t, e), \
+ .size = sizeof (((ns_link_t *) 0)->e) },
ns_foreach_ifla
#undef _
{ .type = 0 }
};
-u8 *format_ns_link (u8 *s, va_list *args)
+u8 *
+format_ns_link (u8 *s, va_list *args)
{
- ns_link_t *l = va_arg(*args, ns_link_t *);
- s = format(s, "%s index %u", l->ifname, l->ifi.ifi_index);
+ ns_link_t *l = va_arg (*args, ns_link_t *);
+ s = format (s, "%s index %u", l->ifname, l->ifi.ifi_index);
return s;
}
-#define ns_foreach_rta \
- _(RTA_DST, dst, 1) \
- _(RTA_SRC, src, 1) \
- _(RTA_GATEWAY, gateway, 1) \
- _(RTA_IIF, iif, 1) \
- _(RTA_OIF, oif, 1) \
- _(RTA_PREFSRC, prefsrc, 0) \
- _(RTA_TABLE, table, 0) \
- _(RTA_PRIORITY, priority, 0) \
- _(RTA_CACHEINFO, cacheinfo, 0) \
- _(RTA_ENCAP, encap, 1)
+#define ns_foreach_rta \
+ _ (RTA_DST, dst, 1) \
+ _ (RTA_SRC, src, 1) \
+ _ (RTA_GATEWAY, gateway, 1) \
+ _ (RTA_IIF, iif, 1) \
+ _ (RTA_OIF, oif, 1) \
+ _ (RTA_PREFSRC, prefsrc, 0) \
+ _ (RTA_TABLE, table, 0) \
+ _ (RTA_PRIORITY, priority, 0) \
+ _ (RTA_CACHEINFO, cacheinfo, 0) \
+ _ (RTA_ENCAP, encap, 1)
static rtnl_mapping_t ns_routemap[] = {
-#define _(t, e, u) \
- { \
- .type = t, .unique = u, \
- .offset = offsetof(ns_route_t, e), \
- .size = sizeof(((ns_route_t*)0)->e) \
- },
+#define _(t, e, u) \
+ { .type = t, \
+ .unique = u, \
+ .offset = offsetof (ns_route_t, e), \
+ .size = sizeof (((ns_route_t *) 0)->e) },
ns_foreach_rta
#undef _
{ .type = 0 }
};
-u8 *format_ns_route (u8 *s, va_list *args)
+u8 *
+format_ns_route (u8 *s, va_list *args)
{
- ns_route_t *r = va_arg(*args, ns_route_t *);
- void *format_ip = r->rtm.rtm_family == AF_INET ? format_ip4_address : format_ip6_address;
- s = format(s, "%U/%d", format_ip, r->dst, r->rtm.rtm_dst_len);
+ ns_route_t *r = va_arg (*args, ns_route_t *);
+ void *format_ip =
+ r->rtm.rtm_family == AF_INET ? format_ip4_address : format_ip6_address;
+ s = format (s, "%U/%d", format_ip, r->dst, r->rtm.rtm_dst_len);
if (r->rtm.rtm_src_len)
- s = format(s, " from %U/%d", format_ip, r->src, r->rtm.rtm_src_len);
- if (is_nonzero(r->gateway))
- s = format(s, " via %U", format_ip, r->gateway);
+ s = format (s, " from %U/%d", format_ip, r->src, r->rtm.rtm_src_len);
+ if (is_nonzero (r->gateway))
+ s = format (s, " via %U", format_ip, r->gateway);
if (r->iif)
- s = format(s, " iif %d", r->iif);
+ s = format (s, " iif %d", r->iif);
if (r->oif)
- s = format(s, " oif %d", r->oif);
- if (is_nonzero(r->prefsrc))
- s = format(s, " src %U", format_ip, r->prefsrc);
+ s = format (s, " oif %d", r->oif);
+ if (is_nonzero (r->prefsrc))
+ s = format (s, " src %U", format_ip, r->prefsrc);
if (r->table)
- s = format(s, " table %d", r->table);
+ s = format (s, " table %d", r->table);
if (r->priority)
- s = format(s, " priority %u", r->priority);
+ s = format (s, " priority %u", r->priority);
return s;
}
-#define ns_foreach_ifaddr \
- _(IFA_ADDRESS, addr, 1) \
- _(IFA_LOCAL, local, 1) \
- _(IFA_LABEL, label, 0) \
- _(IFA_BROADCAST, broadcast, 0) \
- _(IFA_ANYCAST, anycast, 0) \
- _(IFA_CACHEINFO, cacheinfo, 0)
+#define ns_foreach_ifaddr \
+ _ (IFA_ADDRESS, addr, 1) \
+ _ (IFA_LOCAL, local, 1) \
+ _ (IFA_LABEL, label, 0) \
+ _ (IFA_BROADCAST, broadcast, 0) \
+ _ (IFA_ANYCAST, anycast, 0) \
+ _ (IFA_CACHEINFO, cacheinfo, 0)
static rtnl_mapping_t ns_addrmap[] = {
-#define _(t, e, u) \
- { \
- .type = t, .unique = u, \
- .offset = offsetof(ns_addr_t, e), \
- .size = sizeof(((ns_addr_t*)0)->e) \
- },
+#define _(t, e, u) \
+ { .type = t, \
+ .unique = u, \
+ .offset = offsetof (ns_addr_t, e), \
+ .size = sizeof (((ns_addr_t *) 0)->e) },
ns_foreach_ifaddr
#undef _
{ .type = 0 }
};
-u8 *format_ns_addr (u8 *s, va_list *args)
-{
- ns_addr_t *a = va_arg(*args, ns_addr_t *);
- void *format_ip = a->ifaddr.ifa_family == AF_INET ? format_ip4_address : format_ip6_address;
- s = format(s, "%U/%d", format_ip, a->addr, a->ifaddr.ifa_prefixlen);
- if (is_nonzero(a->label))
- s = format(s, " dev %s", a->label);
- if (is_nonzero(a->broadcast))
- s = format(s, " broadcast %U", format_ip, a->broadcast);
- if (is_nonzero(a->anycast))
- s = format(s, " anycast %U", format_ip, a->anycast);
- if (is_nonzero(a->local))
- s = format(s, " local %U", format_ip, a->local);
+u8 *
+format_ns_addr (u8 *s, va_list *args)
+{
+ ns_addr_t *a = va_arg (*args, ns_addr_t *);
+ void *format_ip =
+ a->ifaddr.ifa_family == AF_INET ? format_ip4_address : format_ip6_address;
+ s = format (s, "%U/%d", format_ip, a->addr, a->ifaddr.ifa_prefixlen);
+ if (is_nonzero (a->label))
+ s = format (s, " dev %s", a->label);
+ if (is_nonzero (a->broadcast))
+ s = format (s, " broadcast %U", format_ip, a->broadcast);
+ if (is_nonzero (a->anycast))
+ s = format (s, " anycast %U", format_ip, a->anycast);
+ if (is_nonzero (a->local))
+ s = format (s, " local %U", format_ip, a->local);
return s;
}
#ifndef NDA_RTA
-#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
-#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
+#define NDA_RTA(r) \
+ ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN (sizeof (struct ndmsg))))
+#define NDA_PAYLOAD(n) NLMSG_PAYLOAD (n, sizeof (struct ndmsg))
#endif
-#define ns_foreach_neigh \
- _(NDA_DST, dst, 1) \
- _(NDA_LLADDR, lladdr, 0) \
- _(NDA_PROBES, probes, 0) \
- _(NDA_CACHEINFO, cacheinfo, 0)
+#define ns_foreach_neigh \
+ _ (NDA_DST, dst, 1) \
+ _ (NDA_LLADDR, lladdr, 0) \
+ _ (NDA_PROBES, probes, 0) \
+ _ (NDA_CACHEINFO, cacheinfo, 0)
static rtnl_mapping_t ns_neighmap[] = {
-#define _(t, e, u) \
- { \
- .type = t, .unique = u, \
- .offset = offsetof(ns_neigh_t, e), \
- .size = sizeof(((ns_neigh_t*)0)->e) \
- },
+#define _(t, e, u) \
+ { .type = t, \
+ .unique = u, \
+ .offset = offsetof (ns_neigh_t, e), \
+ .size = sizeof (((ns_neigh_t *) 0)->e) },
ns_foreach_neigh
#undef _
{ .type = 0 }
};
-u8 *format_ns_neigh (u8 *s, va_list *args)
+u8 *
+format_ns_neigh (u8 *s, va_list *args)
{
- ns_neigh_t *n = va_arg(*args, ns_neigh_t *);
- void *format_ip = n->nd.ndm_family == AF_INET ? format_ip4_address : format_ip6_address;
- s = format(s, "%U", format_ip, n->dst);
- if (is_nonzero(n->lladdr))
- s = format(s, " lladdr %U", format_ethernet_address, n->lladdr);
+ ns_neigh_t *n = va_arg (*args, ns_neigh_t *);
+ void *format_ip =
+ n->nd.ndm_family == AF_INET ? format_ip4_address : format_ip6_address;
+ s = format (s, "%U", format_ip, n->dst);
+ if (is_nonzero (n->lladdr))
+ s = format (s, " lladdr %U", format_ethernet_address, n->lladdr);
if (n->probes)
- s = format(s, " probes %d", n->probes);
+ s = format (s, " probes %d", n->probes);
return s;
}
-typedef struct {
- void (*notify)(void *obj, netns_type_t type, u32 flags, uword opaque);
+typedef struct
+{
+ void (*notify) (void *obj, netns_type_t type, u32 flags, uword opaque);
uword opaque;
u32 netns_index;
} netns_handle_t;
-typedef struct {
+typedef struct
+{
netns_t netns;
u32 rtnl_handle;
u32 subscriber_count;
} netns_p;
-typedef struct {
+typedef struct
+{
netns_p *netnss;
netns_handle_t *handles;
} netns_main_t;
@@ -204,22 +211,25 @@ typedef struct {
netns_main_t netns_main;
static int
-rtnl_parse_rtattr(struct rtattr *db[], size_t max,
- struct rtattr *rta, size_t len) {
- for(; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
- if (rta->rta_type <= max)
- db[rta->rta_type] = rta;
+rtnl_parse_rtattr (struct rtattr *db[], size_t max, struct rtattr *rta,
+ size_t len)
+{
+ for (; RTA_OK (rta, len); rta = RTA_NEXT (rta, len))
+ {
+ if (rta->rta_type <= max)
+ db[rta->rta_type] = rta;
#ifdef RTNL_CHECK
- else
- clib_warning("RTA type too high: %d", rta->rta_type);
+ else
+ clib_warning ("RTA type too high: %d", rta->rta_type);
#endif
- }
+ }
- if(len) {
- clib_warning("rattr lenght mistmatch %d %d len",
- (int) len, (int) rta->rta_len);
- return -1;
- }
+ if (len)
+ {
+ clib_warning ("rattr lenght mistmatch %d %d len", (int) len,
+ (int) rta->rta_len);
+ return -1;
+ }
return 0;
}
@@ -230,24 +240,24 @@ rtnl_parse_rtattr(struct rtattr *db[], size_t max,
*/
#ifdef RTNL_CHECK
static void
-rtnl_entry_check(struct rtattr *rtas[],
- size_t rta_len,
- rtnl_mapping_t map[],
- char *logstr)
+rtnl_entry_check (struct rtattr *rtas[], size_t rta_len, rtnl_mapping_t map[],
+ char *logstr)
{
int i;
- for (i=0; i<rta_len; i++) {
- if (!rtas[i])
- continue;
-
- rtnl_mapping_t *m = map;
- for (m = map; m->type; m++) {
- if (m->type == rtas[i]->rta_type)
- break;
+ for (i = 0; i < rta_len; i++)
+ {
+ if (!rtas[i])
+ continue;
+
+ rtnl_mapping_t *m = map;
+ for (m = map; m->type; m++)
+ {
+ if (m->type == rtas[i]->rta_type)
+ break;
+ }
+ if (!m->type)
+ clib_warning ("Unknown RTA type %d (%s)", rtas[i]->rta_type, logstr);
}
- if (!m->type)
- clib_warning("Unknown RTA type %d (%s)", rtas[i]->rta_type, logstr);
- }
}
#endif
@@ -255,433 +265,469 @@ rtnl_entry_check(struct rtattr *rtas[],
* Check if the provided entry matches the parsed and unique rtas
*/
static int
-rtnl_entry_match(void *entry,
- struct rtattr *rtas[],
- rtnl_mapping_t map[])
+rtnl_entry_match (void *entry, struct rtattr *rtas[], rtnl_mapping_t map[])
{
u8 zero[1024] = {};
- for ( ;map->type != 0; map++) {
- struct rtattr *rta = rtas[map->type];
- size_t rta_len = rta?RTA_PAYLOAD(rta):0;
- if (!map->unique)
- continue;
-
- if (rta && RTA_PAYLOAD(rta) > map->size) {
- clib_warning("rta (type=%d len=%d) too long (max %d)",
- rta->rta_type, rta->rta_len, map->size);
- return -1;
- }
-
- if ((rta && memcmp(RTA_DATA(rta), entry + map->offset, rta_len)) ||
- memcmp(entry + map->offset + rta_len, zero, map->size - rta_len)) {
- return 0;
+ for (; map->type != 0; map++)
+ {
+ struct rtattr *rta = rtas[map->type];
+ size_t rta_len = rta ? RTA_PAYLOAD (rta) : 0;
+ if (!map->unique)
+ continue;
+
+ if (rta && RTA_PAYLOAD (rta) > map->size)
+ {
+ clib_warning ("rta (type=%d len=%d) too long (max %d)",
+ rta->rta_type, rta->rta_len, map->size);
+ return -1;
+ }
+
+ if ((rta && memcmp (RTA_DATA (rta), entry + map->offset, rta_len)) ||
+ memcmp (entry + map->offset + rta_len, zero, map->size - rta_len))
+ {
+ return 0;
+ }
}
- }
return 1;
}
static int
-rtnl_entry_set(void *entry,
- struct rtattr *rtas[],
- rtnl_mapping_t map[],
- int init)
-{
- for (; map->type != 0; map++) {
-
- struct rtattr *rta = rtas[map->type];
-
- if(map->type == RTA_ENCAP && rta) {
- /*Data of RTA_ENCAP is a pointer to rta attributes for MPLS*/
- rta = (struct rtattr*)RTA_DATA(rta);
- if (RTA_PAYLOAD(rta) > map->size) {
- clib_warning("rta (type=%d len=%d) too long (max %d)", rta->rta_type, rta->rta_len, map->size);
- return -1;
- }
- memcpy(entry + map->offset, RTA_DATA(rta), map->size);
- memset(entry + map->offset + map->size, 0, 0);
- } else if (rta) {
- if (RTA_PAYLOAD(rta) > map->size) {
- clib_warning("rta (type=%d len=%d) too long (max %d)", rta->rta_type, rta->rta_len, map->size);
- return -1;
- }
- memcpy(entry + map->offset, RTA_DATA(rta), RTA_PAYLOAD(rta));
- memset(entry + map->offset + RTA_PAYLOAD(rta), 0, map->size - RTA_PAYLOAD(rta));
- } else if (init) {
- memset(entry + map->offset, 0, map->size);
+rtnl_entry_set (void *entry, struct rtattr *rtas[], rtnl_mapping_t map[],
+ int init)
+{
+ for (; map->type != 0; map++)
+ {
+
+ struct rtattr *rta = rtas[map->type];
+
+ if (map->type == RTA_ENCAP && rta)
+ {
+ /*Data of RTA_ENCAP is a pointer to rta attributes for MPLS*/
+ rta = (struct rtattr *) RTA_DATA (rta);
+ if (RTA_PAYLOAD (rta) > map->size)
+ {
+ clib_warning ("rta (type=%d len=%d) too long (max %d)",
+ rta->rta_type, rta->rta_len, map->size);
+ return -1;
+ }
+ memcpy (entry + map->offset, RTA_DATA (rta), map->size);
+ memset (entry + map->offset + map->size, 0, 0);
+ }
+ else if (rta)
+ {
+ if (RTA_PAYLOAD (rta) > map->size)
+ {
+ clib_warning ("rta (type=%d len=%d) too long (max %d)",
+ rta->rta_type, rta->rta_len, map->size);
+ return -1;
+ }
+ memcpy (entry + map->offset, RTA_DATA (rta), RTA_PAYLOAD (rta));
+ memset (entry + map->offset + RTA_PAYLOAD (rta), 0,
+ map->size - RTA_PAYLOAD (rta));
+ }
+ else if (init)
+ {
+ memset (entry + map->offset, 0, map->size);
+ }
}
- }
return 0;
}
void
-netns_notify(netns_p *ns, void *obj, netns_type_t type, u32 flags)
+netns_notify (netns_p *ns, void *obj, netns_type_t type, u32 flags)
{
netns_main_t *nm = &netns_main;
netns_handle_t *h;
- pool_foreach(h, nm->handles, {
- if (h->netns_index == (ns - nm->netnss) && h->notify)
- h->notify(obj, type, flags, h->opaque);
- });
+ pool_foreach (h, nm->handles, {
+ if (h->netns_index == (ns - nm->netnss) && h->notify)
+ h->notify (obj, type, flags, h->opaque);
+ })
+ ;
}
static_always_inline int
-mask_match(void *a, void *b, void *mask, size_t len)
+mask_match (void *a, void *b, void *mask, size_t len)
{
u8 *va = (u8 *) a;
u8 *vb = (u8 *) b;
u8 *vm = (u8 *) mask;
- while (len--) {
- if ((va[len] ^ vb[len]) & vm[len])
- return 0;
- }
+ while (len--)
+ {
+ if ((va[len] ^ vb[len]) & vm[len])
+ return 0;
+ }
return 1;
}
static ns_link_t *
-ns_get_link(netns_p *ns, struct ifinfomsg *ifi, struct rtattr *rtas[])
+ns_get_link (netns_p *ns, struct ifinfomsg *ifi, struct rtattr *rtas[])
{
ns_link_t *link;
- pool_foreach(link, ns->netns.links, {
- if(ifi->ifi_index == link->ifi.ifi_index)
- return link;
- });
+ pool_foreach (link, ns->netns.links, {
+ if (ifi->ifi_index == link->ifi.ifi_index)
+ return link;
+ })
+ ;
return NULL;
}
static int
-ns_rcv_link(netns_p *ns, struct nlmsghdr *hdr)
+ns_rcv_link (netns_p *ns, struct nlmsghdr *hdr)
{
ns_link_t *link;
struct ifinfomsg *ifi;
struct rtattr *rtas[IFLA_MAX + 1] = {};
- size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr));
+ size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr));
- if(datalen < sizeof(*ifi))
+ if (datalen < sizeof (*ifi))
return -1;
- ifi = NLMSG_DATA(hdr);
- if((datalen > NLMSG_ALIGN(sizeof(*ifi))) &&
- rtnl_parse_rtattr(rtas, IFLA_MAX, IFLA_RTA(ifi),
- IFLA_PAYLOAD(hdr))) {
- return -1;
- }
+ ifi = NLMSG_DATA (hdr);
+ if ((datalen > NLMSG_ALIGN (sizeof (*ifi))) &&
+ rtnl_parse_rtattr (rtas, IFLA_MAX, IFLA_RTA (ifi), IFLA_PAYLOAD (hdr)))
+ {
+ return -1;
+ }
#ifdef RTNL_CHECK
- rtnl_entry_check(rtas, IFLA_MAX + 1, ns_ifmap, "link");
+ rtnl_entry_check (rtas, IFLA_MAX + 1, ns_ifmap, "link");
#endif
- link = ns_get_link(ns, ifi, rtas);
+ link = ns_get_link (ns, ifi, rtas);
- if (hdr->nlmsg_type == RTM_DELLINK) {
- if (!link)
- return -1;
- pool_put(ns->netns.links, link);
- netns_notify(ns, link, NETNS_TYPE_LINK, NETNS_F_DEL);
- return 0;
- }
-
- if (!link) {
- pool_get(ns->netns.links, link);
- rtnl_entry_set(link, rtas, ns_ifmap, 1);
- } else {
- rtnl_entry_set(link, rtas, ns_ifmap, 0);
- }
+ if (hdr->nlmsg_type == RTM_DELLINK)
+ {
+ if (!link)
+ return -1;
+ pool_put (ns->netns.links, link);
+ netns_notify (ns, link, NETNS_TYPE_LINK, NETNS_F_DEL);
+ return 0;
+ }
+
+ if (!link)
+ {
+ pool_get (ns->netns.links, link);
+ rtnl_entry_set (link, rtas, ns_ifmap, 1);
+ }
+ else
+ {
+ rtnl_entry_set (link, rtas, ns_ifmap, 0);
+ }
link->ifi = *ifi;
- link->last_updated = vlib_time_now(vlib_get_main());
- netns_notify(ns, link, NETNS_TYPE_LINK, NETNS_F_ADD);
+ link->last_updated = vlib_time_now (vlib_get_main ());
+ netns_notify (ns, link, NETNS_TYPE_LINK, NETNS_F_ADD);
return 0;
}
static ns_route_t *
-ns_get_route(netns_p *ns, struct rtmsg *rtm, struct rtattr *rtas[])
+ns_get_route (netns_p *ns, struct rtmsg *rtm, struct rtattr *rtas[])
{
ns_route_t *route;
- //This describes the values which uniquely identify a route
- struct rtmsg msg = {
- .rtm_family = 0xff,
- .rtm_dst_len = 0xff,
- .rtm_src_len = 0xff,
- .rtm_table = 0xff,
- .rtm_protocol = 0xff,
- .rtm_type = 0xff
- };
-
- pool_foreach(route, ns->netns.routes, {
- if(mask_match(&route->rtm, rtm, &msg, sizeof(struct rtmsg)) &&
- rtnl_entry_match(route, rtas, ns_routemap))
- return route;
- });
+ // This describes the values which uniquely identify a route
+ struct rtmsg msg = { .rtm_family = 0xff,
+ .rtm_dst_len = 0xff,
+ .rtm_src_len = 0xff,
+ .rtm_table = 0xff,
+ .rtm_protocol = 0xff,
+ .rtm_type = 0xff };
+
+ pool_foreach (route, ns->netns.routes, {
+ if (mask_match (&route->rtm, rtm, &msg, sizeof (struct rtmsg)) &&
+ rtnl_entry_match (route, rtas, ns_routemap))
+ return route;
+ })
+ ;
return NULL;
}
static int
-ns_rcv_route(netns_p *ns, struct nlmsghdr *hdr)
+ns_rcv_route (netns_p *ns, struct nlmsghdr *hdr)
{
ns_route_t *route;
struct rtmsg *rtm;
struct rtattr *rtas[RTA_MAX + 1] = {};
- size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr));
+ size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr));
- if(datalen < sizeof(*rtm))
+ if (datalen < sizeof (*rtm))
return -1;
- rtm = NLMSG_DATA(hdr);
- if((datalen > NLMSG_ALIGN(sizeof(*rtm))) &&
- rtnl_parse_rtattr(rtas, RTA_MAX, RTM_RTA(rtm),
- RTM_PAYLOAD(hdr))) {
- return -1;
- }
+ rtm = NLMSG_DATA (hdr);
+ if ((datalen > NLMSG_ALIGN (sizeof (*rtm))) &&
+ rtnl_parse_rtattr (rtas, RTA_MAX, RTM_RTA (rtm), RTM_PAYLOAD (hdr)))
+ {
+ return -1;
+ }
#ifdef RTNL_CHECK
- rtnl_entry_check(rtas, RTA_MAX + 1, ns_routemap, "route");
+ rtnl_entry_check (rtas, RTA_MAX + 1, ns_routemap, "route");
#endif
- route = ns_get_route(ns, rtm, rtas);
+ route = ns_get_route (ns, rtm, rtas);
+
+ if (hdr->nlmsg_type == RTM_DELROUTE)
+ {
+ if (!route)
+ return -1;
+ pool_put (ns->netns.routes, route);
+ netns_notify (ns, route, NETNS_TYPE_ROUTE, NETNS_F_DEL);
+ return 0;
+ }
- if (hdr->nlmsg_type == RTM_DELROUTE) {
- if (!route)
- return -1;
- pool_put(ns->netns.routes, route);
- netns_notify(ns, route, NETNS_TYPE_ROUTE, NETNS_F_DEL);
- return 0;
- }
-
- if (!route) {
- pool_get(ns->netns.routes, route);
- memset(route, 0, sizeof(*route));
- rtnl_entry_set(route, rtas, ns_routemap, 1);
- } else {
- rtnl_entry_set(route, rtas, ns_routemap, 0);
- }
+ if (!route)
+ {
+ pool_get (ns->netns.routes, route);
+ memset (route, 0, sizeof (*route));
+ rtnl_entry_set (route, rtas, ns_routemap, 1);
+ }
+ else
+ {
+ rtnl_entry_set (route, rtas, ns_routemap, 0);
+ }
route->rtm = *rtm;
- route->last_updated = vlib_time_now(vlib_get_main());
- netns_notify(ns, route, NETNS_TYPE_ROUTE, NETNS_F_ADD);
+ route->last_updated = vlib_time_now (vlib_get_main ());
+ netns_notify (ns, route, NETNS_TYPE_ROUTE, NETNS_F_ADD);
return 0;
}
static ns_addr_t *
-ns_get_addr(netns_p *ns, struct ifaddrmsg *ifaddr, struct rtattr *rtas[])
+ns_get_addr (netns_p *ns, struct ifaddrmsg *ifaddr, struct rtattr *rtas[])
{
ns_addr_t *addr;
- //This describes the values which uniquely identify a route
+ // This describes the values which uniquely identify a route
struct ifaddrmsg msg = {
.ifa_family = 0xff,
.ifa_prefixlen = 0xff,
};
- pool_foreach(addr, ns->netns.addresses, {
- if(mask_match(&addr->ifaddr, ifaddr, &msg, sizeof(struct ifaddrmsg)) &&
- rtnl_entry_match(addr, rtas, ns_addrmap))
- return addr;
- });
+ pool_foreach (addr, ns->netns.addresses, {
+ if (mask_match (&addr->ifaddr, ifaddr, &msg, sizeof (struct ifaddrmsg)) &&
+ rtnl_entry_match (addr, rtas, ns_addrmap))
+ return addr;
+ })
+ ;
return NULL;
}
static int
-ns_rcv_addr(netns_p *ns, struct nlmsghdr *hdr)
+ns_rcv_addr (netns_p *ns, struct nlmsghdr *hdr)
{
ns_addr_t *addr;
struct ifaddrmsg *ifaddr;
struct rtattr *rtas[IFA_MAX + 1] = {};
- size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr));
+ size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr));
- if(datalen < sizeof(*ifaddr))
+ if (datalen < sizeof (*ifaddr))
return -1;
- ifaddr = NLMSG_DATA(hdr);
- if((datalen > NLMSG_ALIGN(sizeof(*ifaddr))) &&
- rtnl_parse_rtattr(rtas, IFA_MAX, IFA_RTA(ifaddr),
- IFA_PAYLOAD(hdr))) {
- return -1;
- }
+ ifaddr = NLMSG_DATA (hdr);
+ if ((datalen > NLMSG_ALIGN (sizeof (*ifaddr))) &&
+ rtnl_parse_rtattr (rtas, IFA_MAX, IFA_RTA (ifaddr), IFA_PAYLOAD (hdr)))
+ {
+ return -1;
+ }
#ifdef RTNL_CHECK
- rtnl_entry_check(rtas, IFA_MAX + 1, ns_addrmap, "addr");
+ rtnl_entry_check (rtas, IFA_MAX + 1, ns_addrmap, "addr");
#endif
- addr = ns_get_addr(ns, ifaddr, rtas);
+ addr = ns_get_addr (ns, ifaddr, rtas);
+
+ if (hdr->nlmsg_type == RTM_DELADDR)
+ {
+ if (!addr)
+ return -1;
+ pool_put (ns->netns.addresses, addr);
+ netns_notify (ns, addr, NETNS_TYPE_ADDR, NETNS_F_DEL);
+ return 0;
+ }
- if (hdr->nlmsg_type == RTM_DELADDR) {
- if (!addr)
- return -1;
- pool_put(ns->netns.addresses, addr);
- netns_notify(ns, addr, NETNS_TYPE_ADDR, NETNS_F_DEL);
- return 0;
- }
-
- if (!addr) {
- pool_get(ns->netns.addresses, addr);
- memset(addr, 0, sizeof(*addr));
- rtnl_entry_set(addr, rtas, ns_addrmap, 1);
- } else {
- rtnl_entry_set(addr, rtas, ns_addrmap, 0);
- }
+ if (!addr)
+ {
+ pool_get (ns->netns.addresses, addr);
+ memset (addr, 0, sizeof (*addr));
+ rtnl_entry_set (addr, rtas, ns_addrmap, 1);
+ }
+ else
+ {
+ rtnl_entry_set (addr, rtas, ns_addrmap, 0);
+ }
addr->ifaddr = *ifaddr;
- addr->last_updated = vlib_time_now(vlib_get_main());
- netns_notify(ns, addr, NETNS_TYPE_ADDR, NETNS_F_ADD);
+ addr->last_updated = vlib_time_now (vlib_get_main ());
+ netns_notify (ns, addr, NETNS_TYPE_ADDR, NETNS_F_ADD);
return 0;
}
static ns_neigh_t *
-ns_get_neigh(netns_p *ns, struct ndmsg *nd, struct rtattr *rtas[])
+ns_get_neigh (netns_p *ns, struct ndmsg *nd, struct rtattr *rtas[])
{
ns_neigh_t *neigh;
- //This describes the values which uniquely identify a route
+ // This describes the values which uniquely identify a route
struct ndmsg msg = {
.ndm_family = 0xff,
.ndm_ifindex = 0xff,
};
- pool_foreach(neigh, ns->netns.neighbors, {
- if(mask_match(&neigh->nd, nd, &msg, sizeof(&msg)) &&
- rtnl_entry_match(neigh, rtas, ns_neighmap))
- return neigh;
- });
+ pool_foreach (neigh, ns->netns.neighbors, {
+ if (mask_match (&neigh->nd, nd, &msg, sizeof (&msg)) &&
+ rtnl_entry_match (neigh, rtas, ns_neighmap))
+ return neigh;
+ })
+ ;
return NULL;
}
static int
-ns_rcv_neigh(netns_p *ns, struct nlmsghdr *hdr)
+ns_rcv_neigh (netns_p *ns, struct nlmsghdr *hdr)
{
ns_neigh_t *neigh;
struct ndmsg *nd;
struct rtattr *rtas[NDA_MAX + 1] = {};
- size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr));
+ size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr));
- if(datalen < sizeof(*nd))
+ if (datalen < sizeof (*nd))
return -1;
- nd = NLMSG_DATA(hdr);
- if((datalen > NLMSG_ALIGN(sizeof(*nd))) &&
- rtnl_parse_rtattr(rtas, NDA_MAX, NDA_RTA(nd),
- NDA_PAYLOAD(hdr))) {
- return -1;
- }
+ nd = NLMSG_DATA (hdr);
+ if ((datalen > NLMSG_ALIGN (sizeof (*nd))) &&
+ rtnl_parse_rtattr (rtas, NDA_MAX, NDA_RTA (nd), NDA_PAYLOAD (hdr)))
+ {
+ return -1;
+ }
#ifdef RTNL_CHECK
- rtnl_entry_check(rtas, NDA_MAX + 1, ns_neighmap, "nd");
+ rtnl_entry_check (rtas, NDA_MAX + 1, ns_neighmap, "nd");
#endif
- neigh = ns_get_neigh(ns, nd, rtas);
+ neigh = ns_get_neigh (ns, nd, rtas);
+
+ if (hdr->nlmsg_type == RTM_DELNEIGH)
+ {
+ if (!neigh)
+ return -1;
+ pool_put (ns->netns.neighbors, neigh);
+ netns_notify (ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_DEL);
+ return 0;
+ }
- if (hdr->nlmsg_type == RTM_DELNEIGH) {
- if (!neigh)
- return -1;
- pool_put(ns->netns.neighbors, neigh);
- netns_notify(ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_DEL);
- return 0;
- }
-
- if (!neigh) {
- pool_get(ns->netns.neighbors, neigh);
- memset(neigh, 0, sizeof(*neigh));
- rtnl_entry_set(neigh, rtas, ns_neighmap, 1);
- } else {
- rtnl_entry_set(neigh, rtas, ns_neighmap, 0);
- }
+ if (!neigh)
+ {
+ pool_get (ns->netns.neighbors, neigh);
+ memset (neigh, 0, sizeof (*neigh));
+ rtnl_entry_set (neigh, rtas, ns_neighmap, 1);
+ }
+ else
+ {
+ rtnl_entry_set (neigh, rtas, ns_neighmap, 0);
+ }
neigh->nd = *nd;
- neigh->last_updated = vlib_time_now(vlib_get_main());
- netns_notify(ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_ADD);
+ neigh->last_updated = vlib_time_now (vlib_get_main ());
+ netns_notify (ns, neigh, NETNS_TYPE_NEIGH, NETNS_F_ADD);
return 0;
}
-#define ns_object_foreach \
- _(neighbors, NETNS_TYPE_NEIGH) \
- _(routes, NETNS_TYPE_ROUTE) \
- _(addresses, NETNS_TYPE_ADDR) \
- _(links, NETNS_TYPE_LINK)
+#define ns_object_foreach \
+ _ (neighbors, NETNS_TYPE_NEIGH) \
+ _ (routes, NETNS_TYPE_ROUTE) \
+ _ (addresses, NETNS_TYPE_ADDR) \
+ _ (links, NETNS_TYPE_LINK)
static void
-ns_recv_error(rtnl_error_t err, uword o)
+ns_recv_error (rtnl_error_t err, uword o)
{
- //An error was received. Reset everything.
+ // An error was received. Reset everything.
netns_p *ns = &netns_main.netnss[o];
u32 *indexes = 0;
u32 *i = 0;
-#define _(pool, type) \
- pool_foreach_index(*i, ns->netns.pool, { \
- vec_add1(indexes, *i); \
- }) \
- vec_foreach(i, indexes) { \
- pool_put_index(ns->netns.pool, *i); \
- netns_notify(ns, &ns->netns.pool[*i], type, NETNS_F_DEL); \
- } \
- vec_reset_length(indexes);
+#define _(pool, type) \
+ pool_foreach_index (*i, ns->netns.pool, { vec_add1 (indexes, *i); }) \
+ vec_foreach (i, indexes) \
+ { \
+ pool_put_index (ns->netns.pool, *i); \
+ netns_notify (ns, &ns->netns.pool[*i], type, NETNS_F_DEL); \
+ } \
+ vec_reset_length (indexes);
ns_object_foreach
#undef _
- vec_free(indexes);
+ vec_free (indexes);
}
static void
-ns_recv_rtnl(struct nlmsghdr *hdr, uword o)
+ns_recv_rtnl (struct nlmsghdr *hdr, uword o)
{
netns_p *ns = &netns_main.netnss[o];
- switch (hdr->nlmsg_type) {
- case RTM_NEWROUTE:
- case RTM_DELROUTE:
- ns_rcv_route(ns, hdr);
- break;
- case RTM_NEWLINK:
- case RTM_DELLINK:
- ns_rcv_link(ns, hdr);
- break;
- case RTM_NEWADDR:
- case RTM_DELADDR:
- ns_rcv_addr(ns, hdr);
- break;
- case RTM_NEWNEIGH:
- case RTM_DELNEIGH:
- ns_rcv_neigh(ns, hdr);
- break;
- default:
- clib_warning("unknown rtnl type %d", hdr->nlmsg_type);
- break;
- }
+ switch (hdr->nlmsg_type)
+ {
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ ns_rcv_route (ns, hdr);
+ break;
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ ns_rcv_link (ns, hdr);
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ ns_rcv_addr (ns, hdr);
+ break;
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ ns_rcv_neigh (ns, hdr);
+ break;
+ default:
+ clib_warning ("unknown rtnl type %d", hdr->nlmsg_type);
+ break;
+ }
}
static void
-netns_destroy(netns_p *ns)
+netns_destroy (netns_p *ns)
{
netns_main_t *nm = &netns_main;
- rtnl_stream_close(ns->rtnl_handle);
- pool_put(nm->netnss, ns);
- pool_free(ns->netns.links);
- pool_free(ns->netns.addresses);
- pool_free(ns->netns.routes);
- pool_free(ns->netns.neighbors);
+ rtnl_stream_close (ns->rtnl_handle);
+ pool_put (nm->netnss, ns);
+ pool_free (ns->netns.links);
+ pool_free (ns->netns.addresses);
+ pool_free (ns->netns.routes);
+ pool_free (ns->netns.neighbors);
}
static netns_p *
-netns_get(char *name)
+netns_get (char *name)
{
netns_main_t *nm = &netns_main;
netns_p *ns;
- pool_foreach(ns, nm->netnss, {
- if (!strcmp(name, ns->netns.name))
- return ns;
- });
+ pool_foreach (ns, nm->netnss, {
+ if (!strcmp (name, ns->netns.name))
+ return ns;
+ })
+ ;
- if (strlen(name) > RTNL_NETNS_NAMELEN)
+ if (strlen (name) > RTNL_NETNS_NAMELEN)
return NULL;
- pool_get(nm->netnss, ns);
+ pool_get (nm->netnss, ns);
rtnl_stream_t s = {
.recv_message = ns_recv_rtnl,
.error = ns_recv_error,
- .opaque = (uword)(ns - nm->netnss),
+ .opaque = (uword) (ns - nm->netnss),
};
- strcpy(s.name, name);
+ int rc = strcpy_s (s.name, sizeof (s.name), name);
+ if (rc != EOK)
+ return NULL;
u32 handle;
- if ((handle = rtnl_stream_open(&s)) == ~0) {
- pool_put(nm->netnss, ns);
- return NULL;
- }
+ if ((handle = rtnl_stream_open (&s)) == ~0)
+ {
+ pool_put (nm->netnss, ns);
+ return NULL;
+ }
- strcpy(ns->netns.name, name);
+ rc = strcpy_s (ns->netns.name, sizeof (ns->netns.name), name);
+ if (rc != EOK)
+ return NULL;
ns->netns.addresses = 0;
ns->netns.links = 0;
ns->netns.neighbors = 0;
@@ -691,15 +737,16 @@ netns_get(char *name)
return ns;
}
-u32 netns_open(char *name, netns_sub_t *sub)
+u32
+netns_open (char *name, netns_sub_t *sub)
{
netns_main_t *nm = &netns_main;
netns_p *ns;
netns_handle_t *p;
- if (!(ns = netns_get(name)))
+ if (!(ns = netns_get (name)))
return ~0;
- pool_get(nm->handles, p);
+ pool_get (nm->handles, p);
p->netns_index = ns - nm->netnss;
p->notify = sub->notify;
p->opaque = sub->opaque;
@@ -707,76 +754,82 @@ u32 netns_open(char *name, netns_sub_t *sub)
return p - nm->handles;
}
-netns_t *netns_getns(u32 handle)
+netns_t *
+netns_getns (u32 handle)
{
netns_main_t *nm = &netns_main;
- netns_handle_t *h = pool_elt_at_index(nm->handles, handle);
- netns_p *ns = pool_elt_at_index(nm->netnss, h->netns_index);
+ netns_handle_t *h = pool_elt_at_index (nm->handles, handle);
+ netns_p *ns = pool_elt_at_index (nm->netnss, h->netns_index);
return &ns->netns;
}
-void netns_close(u32 handle)
+void
+netns_close (u32 handle)
{
netns_main_t *nm = &netns_main;
- netns_handle_t *h = pool_elt_at_index(nm->handles, handle);
- netns_p *ns = pool_elt_at_index(nm->netnss, h->netns_index);
- pool_put(h, nm->handles);
+ netns_handle_t *h = pool_elt_at_index (nm->handles, handle);
+ netns_p *ns = pool_elt_at_index (nm->netnss, h->netns_index);
+ pool_put (h, nm->handles);
ns->subscriber_count--;
if (!ns->subscriber_count)
- netns_destroy(ns);
+ netns_destroy (ns);
}
-void netns_callme(u32 handle, char del)
+void
+netns_callme (u32 handle, char del)
{
netns_main_t *nm = &netns_main;
- netns_handle_t *h = pool_elt_at_index(nm->handles, handle);
- netns_p *ns = pool_elt_at_index(nm->netnss, h->netns_index);
+ netns_handle_t *h = pool_elt_at_index (nm->handles, handle);
+ netns_p *ns = pool_elt_at_index (nm->netnss, h->netns_index);
u32 i = 0;
if (!h->notify)
return;
-#define _(pool, type) \
- pool_foreach_index(i, ns->netns.pool, { \
- h->notify(&ns->netns.pool[i], type, \
- del?NETNS_F_DEL:NETNS_F_ADD, h->opaque); \
- });
+#define _(pool, type) \
+ pool_foreach_index (i, ns->netns.pool, { \
+ h->notify (&ns->netns.pool[i], type, del ? NETNS_F_DEL : NETNS_F_ADD, \
+ h->opaque); \
+ }) \
+ ;
ns_object_foreach
#undef _
+}
+u8 *
+format_ns_object (u8 *s, va_list *args)
+{
+ netns_type_t t = va_arg (*args, netns_type_t);
+ void *o = va_arg (*args, void *);
+ switch (t)
+ {
+ case NETNS_TYPE_ADDR:
+ return format (s, "addr %U", format_ns_addr, o);
+ case NETNS_TYPE_ROUTE:
+ return format (s, "route %U", format_ns_route, o);
+ case NETNS_TYPE_LINK:
+ return format (s, "link %U", format_ns_link, o);
+ case NETNS_TYPE_NEIGH:
+ return format (s, "neigh %U", format_ns_neigh, o);
}
-
-u8 *format_ns_object(u8 *s, va_list *args)
-{
- netns_type_t t = va_arg(*args, netns_type_t);
- void *o = va_arg(*args, void *);
- switch (t) {
- case NETNS_TYPE_ADDR:
- return format(s, "addr %U", format_ns_addr, o);
- case NETNS_TYPE_ROUTE:
- return format(s, "route %U", format_ns_route, o);
- case NETNS_TYPE_LINK:
- return format(s, "link %U", format_ns_link, o);
- case NETNS_TYPE_NEIGH:
- return format(s, "neigh %U", format_ns_neigh, o);
- }
return s;
}
-u8 *format_ns_flags(u8 *s, va_list *args)
+u8 *
+format_ns_flags (u8 *s, va_list *args)
{
- u32 flags = va_arg(*args, u32);
+ u32 flags = va_arg (*args, u32);
if (flags & NETNS_F_ADD)
- s = format(s, "add");
+ s = format (s, "add");
else if (flags & NETNS_F_DEL)
- s = format(s, "del");
+ s = format (s, "del");
else
- s = format(s, "mod");
+ s = format (s, "mod");
return s;
}
clib_error_t *
-netns_init (vlib_main_t * vm)
+netns_init (vlib_main_t *vm)
{
netns_main_t *nm = &netns_main;
nm->netnss = 0;
diff --git a/extras/router-plugin/devices/rtnetlink/netns.h b/extras/router-plugin/devices/rtnetlink/netns.h
index 53effe5ce..b94356c3b 100644
--- a/extras/router-plugin/devices/rtnetlink/netns.h
+++ b/extras/router-plugin/devices/rtnetlink/netns.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,10 +18,10 @@
#include <vlib/vlib.h>
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
#include <net/if.h>
+#include <sys/socket.h>
#include "rtnl.h"
@@ -30,7 +30,8 @@
/*so far depth is fixed, looking into ways to be dynamic*/
#define MPLS_STACK_DEPTH 7
-typedef struct {
+typedef struct
+{
struct ifinfomsg ifi;
u8 hwaddr[IFHWADDRLEN];
u8 broadcast[IFHWADDRLEN];
@@ -38,11 +39,13 @@ typedef struct {
u32 mtu;
u32 master;
u8 qdisc[IFNAMSIZ];
- struct rtnl_link_stats stats; //This struct is big and only comes as a response to a request
+ struct rtnl_link_stats
+ stats; // This struct is big and only comes as a response to a request
f64 last_updated;
} ns_link_t;
-typedef struct {
+typedef struct
+{
struct rtmsg rtm;
u8 dst[16];
u8 src[16];
@@ -58,7 +61,8 @@ typedef struct {
f64 last_updated;
} ns_route_t;
-typedef struct {
+typedef struct
+{
struct ifaddrmsg ifaddr;
u8 addr[16];
u8 local[16];
@@ -69,7 +73,8 @@ typedef struct {
f64 last_updated;
} ns_addr_t;
-typedef struct {
+typedef struct
+{
struct ndmsg nd;
u8 dst[16];
u8 lladdr[IFHWADDRLEN];
@@ -78,28 +83,30 @@ typedef struct {
f64 last_updated;
} ns_neigh_t;
-typedef struct {
+typedef struct
+{
char name[RTNL_NETNS_NAMELEN + 1];
- ns_link_t *links;
+ ns_link_t *links;
ns_route_t *routes;
- ns_addr_t *addresses;
+ ns_addr_t *addresses;
ns_neigh_t *neighbors;
} netns_t;
-
-typedef enum {
+typedef enum
+{
NETNS_TYPE_LINK,
NETNS_TYPE_ROUTE,
NETNS_TYPE_ADDR,
NETNS_TYPE_NEIGH,
} netns_type_t;
-//Flags used in notification functions call
-#define NETNS_F_ADD 0x01
-#define NETNS_F_DEL 0x02
+// Flags used in notification functions call
+#define NETNS_F_ADD 0x01
+#define NETNS_F_DEL 0x02
-typedef struct {
- void (*notify)(void *obj, netns_type_t type, u32 flags, uword opaque);
+typedef struct
+{
+ void (*notify) (void *obj, netns_type_t type, u32 flags, uword opaque);
uword opaque;
} netns_sub_t;
@@ -110,36 +117,36 @@ typedef struct {
* existing routes (This is to protect against
* synch. Vs asynch. issues).
*/
-u32 netns_open(char *name, netns_sub_t *sub);
+u32 netns_open (char *name, netns_sub_t *sub);
/*
* Retrieves the namespace structure associated with a
* given namespace handler.
*/
-netns_t *netns_getns(u32 handle);
+netns_t *netns_getns (u32 handle);
/*
* Terminates a subscriber session.
*/
-void netns_close(u32 handle);
+void netns_close (u32 handle);
/*
* Calls the callback associated with the handle
* for all existing objects with the flags
* set to (del?NETNS_F_DEL:NETNS_F_ADD).
*/
-void netns_callme(u32 handle, char del);
+void netns_callme (u32 handle, char del);
/*
* netns struct format functions.
* Taking the struct as single argument.
*/
-u8 *format_ns_neigh(u8 *s, va_list *args);
-u8 *format_ns_addr(u8 *s, va_list *args);
-u8 *format_ns_route(u8 *s, va_list *args);
-u8 *format_ns_link(u8 *s, va_list *args);
+u8 *format_ns_neigh (u8 *s, va_list *args);
+u8 *format_ns_addr (u8 *s, va_list *args);
+u8 *format_ns_route (u8 *s, va_list *args);
+u8 *format_ns_link (u8 *s, va_list *args);
-u8 *format_ns_object(u8 *s, va_list *args);
-u8 *format_ns_flags(u8 *s, va_list *args);
+u8 *format_ns_object (u8 *s, va_list *args);
+u8 *format_ns_flags (u8 *s, va_list *args);
#endif
diff --git a/extras/router-plugin/devices/rtnetlink/rtnl.c b/extras/router-plugin/devices/rtnetlink/rtnl.c
index ed3db9e72..9c4757b17 100644
--- a/extras/router-plugin/devices/rtnetlink/rtnl.c
+++ b/extras/router-plugin/devices/rtnetlink/rtnl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,20 +16,20 @@
#define _GNU_SOURCE
#include <sched.h>
-#include <vlib/vlib.h>
#include <vlib/unix/unix.h>
+#include <vlib/vlib.h>
#include <vppinfra/error.h>
-#include <sys/socket.h>
+#include <fcntl.h>
+#include <float.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
-#include <float.h>
-#include <fcntl.h>
+#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include "netns.h"
#include "rtnl.h"
@@ -37,19 +37,22 @@
#undef DBL_MAX
#define DBL_MAX 1000000000.0
-typedef enum {
+typedef enum
+{
RTNL_E_OPEN,
RTNL_E_CLOSE,
RTNL_E_READ,
} rtnl_event_t;
-typedef enum {
+typedef enum
+{
RTNL_S_INIT,
RTNL_S_SYNC,
RTNL_S_READY,
} rtnl_state_t;
-typedef enum {
+typedef enum
+{
RTNL_SS_OPENING,
RTNL_SS_LINK,
RTNL_SS_ADDR,
@@ -58,7 +61,8 @@ typedef enum {
RTNL_SS_NEIGH,
} rtnl_sync_state_t;
-typedef struct {
+typedef struct
+{
rtnl_stream_t stream;
rtnl_state_t state;
rtnl_sync_state_t sync_state;
@@ -69,7 +73,8 @@ typedef struct {
f64 timeout;
} rtnl_ns_t;
-typedef struct {
+typedef struct
+{
f64 now;
rtnl_ns_t *streams;
} rtnl_main_t;
@@ -77,204 +82,227 @@ typedef struct {
static rtnl_main_t rtnl_main;
static vlib_node_registration_t rtnl_process_node;
-#define RTNL_BUFFSIZ 16384
+#define RTNL_BUFFSIZ 16384
#define RTNL_DUMP_TIMEOUT 1
-static inline u32 grpmask(u32 g)
+static inline u32
+grpmask (u32 g)
{
ASSERT (g <= 31);
- if (g) {
- return 1 << (g - 1);
- } else
+ if (g)
+ {
+ return 1 << (g - 1);
+ }
+ else
return 0;
}
-
-u8 *format_rtnl_nsname2path(u8 *s, va_list *args)
+u8 *
+format_rtnl_nsname2path (u8 *s, va_list *args)
{
- char *nsname = va_arg(*args, char *);
- if (!nsname || !strlen(nsname)) {
- return format(s, "/proc/self/ns/net");
- } else if (strpbrk(nsname, "/") != NULL) {
- return format(s, "%s", nsname);
- } else {
- return format(s, "/var/run/netns/%s", nsname);
- }
+ char *nsname = va_arg (*args, char *);
+ if (!nsname || !strlen (nsname))
+ {
+ return format (s, "/proc/self/ns/net");
+ }
+ else if (strpbrk (nsname, "/") != NULL)
+ {
+ return format (s, "%s", nsname);
+ }
+ else
+ {
+ return format (s, "/var/run/netns/%s", nsname);
+ }
}
static_always_inline void
-rtnl_schedule_timeout(rtnl_ns_t *ns, f64 when)
+rtnl_schedule_timeout (rtnl_ns_t *ns, f64 when)
{
ns->timeout = when;
}
static_always_inline void
-rtnl_cancel_timeout(rtnl_ns_t *ns)
+rtnl_cancel_timeout (rtnl_ns_t *ns)
{
ns->timeout = DBL_MAX;
}
-static clib_error_t *rtnl_read_cb(struct clib_file * f)
+static clib_error_t *
+rtnl_read_cb (struct clib_file *f)
{
rtnl_main_t *rm = &rtnl_main;
- vlib_main_t *vm = vlib_get_main();
+ vlib_main_t *vm = vlib_get_main ();
rtnl_ns_t *ns = &rm->streams[f->private_data];
- vlib_process_signal_event(vm, rtnl_process_node.index, RTNL_E_READ, (uword)(ns - rm->streams));
+ vlib_process_signal_event (vm, rtnl_process_node.index, RTNL_E_READ,
+ (uword) (ns - rm->streams));
return 0;
}
-int rtnl_dump_request(rtnl_ns_t *ns, int type, void *req, size_t len)
+int
+rtnl_dump_request (rtnl_ns_t *ns, int type, void *req, size_t len)
{
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
struct nlmsghdr nlh = {
- .nlmsg_len = NLMSG_LENGTH(len),
+ .nlmsg_len = NLMSG_LENGTH (len),
.nlmsg_type = type,
- .nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST,
+ .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
.nlmsg_pid = 0,
.nlmsg_seq = ++ns->rtnl_seq,
};
- struct iovec iov[2] = {
- { .iov_base = &nlh, .iov_len = sizeof(nlh) },
- { .iov_base = req, .iov_len = len }
- };
+ struct iovec iov[2] = { { .iov_base = &nlh, .iov_len = sizeof (nlh) },
+ { .iov_base = req, .iov_len = len } };
struct msghdr msg = {
.msg_name = &nladdr,
- .msg_namelen = sizeof(nladdr),
+ .msg_namelen = sizeof (nladdr),
.msg_iov = iov,
.msg_iovlen = 2,
};
- if(sendmsg(ns->rtnl_socket, &msg, 0) < 0) {
- clib_warning("sendmsg error: %s", strerror(errno));
- return -1;
- }
+ if (sendmsg (ns->rtnl_socket, &msg, 0) < 0)
+ {
+ clib_warning ("sendmsg error: %s", strerror (errno));
+ return -1;
+ }
return 0;
}
-static void rtnl_socket_close(rtnl_ns_t *ns)
+static void
+rtnl_socket_close (rtnl_ns_t *ns)
{
- clib_file_del(&file_main, &file_main.file_pool[ns->unix_index]);
- close(ns->rtnl_socket);
+ clib_file_del (&file_main, &file_main.file_pool[ns->unix_index]);
+ close (ns->rtnl_socket);
}
-struct rtnl_thread_exec {
+struct rtnl_thread_exec
+{
int fd;
- void *(*fn)(void *);
+ void *(*fn) (void *);
void *arg;
void **ret;
};
-static void *rtnl_exec_in_thread_fn(void *p)
+static void *
+rtnl_exec_in_thread_fn (void *p)
{
struct rtnl_thread_exec *ex = (struct rtnl_thread_exec *) p;
- if (setns(ex->fd, 0))
+ if (setns (ex->fd, 0))
return (void *) ((uword) (-errno));
- *ex->ret = ex->fn(ex->arg);
+ *ex->ret = ex->fn (ex->arg);
return NULL;
}
-static int rtnl_exec_in_namespace_byfd(int fd, void *(*fn)(void *), void *arg, void **ret)
+static int
+rtnl_exec_in_namespace_byfd (int fd, void *(*fn) (void *), void *arg,
+ void **ret)
{
pthread_t thread;
void *thread_ret;
- struct rtnl_thread_exec ex = {
- .fd = fd,
- .fn = fn,
- .arg = arg,
- .ret = ret
- };
- if(pthread_create(&thread, NULL, rtnl_exec_in_thread_fn, &ex))
+ struct rtnl_thread_exec ex = { .fd = fd, .fn = fn, .arg = arg, .ret = ret };
+ if (pthread_create (&thread, NULL, rtnl_exec_in_thread_fn, &ex))
return -errno;
- if(pthread_join(thread, &thread_ret))
+ if (pthread_join (thread, &thread_ret))
return -errno;
if (thread_ret)
- return (int) ((uword)thread_ret);
+ return (int) ((uword) thread_ret);
return 0;
}
-int rtnl_exec_in_namespace(u32 stream_index, void *(*fn)(void *), void *arg, void **ret)
+int
+rtnl_exec_in_namespace (u32 stream_index, void *(*fn) (void *), void *arg,
+ void **ret)
{
rtnl_main_t *rm = &rtnl_main;
- if (pool_is_free_index(rm->streams, stream_index))
+ if (pool_is_free_index (rm->streams, stream_index))
return -EBADR;
- rtnl_ns_t *ns = pool_elt_at_index(rm->streams, stream_index);
- return rtnl_exec_in_namespace_byfd(ns->ns_fd, fn, arg, ret);
+ rtnl_ns_t *ns = pool_elt_at_index (rm->streams, stream_index);
+ return rtnl_exec_in_namespace_byfd (ns->ns_fd, fn, arg, ret);
}
-int rtnl_exec_in_namespace_by_name(char *nsname, void *(*fn)(void *), void *arg, void **ret)
+int
+rtnl_exec_in_namespace_by_name (char *nsname, void *(*fn) (void *), void *arg,
+ void **ret)
{
int fd;
- u8 *s = format((u8 *)0, "%U", format_rtnl_nsname2path, nsname);
+ u8 *s = format ((u8 *) 0, "%U", format_rtnl_nsname2path, nsname);
- if ((fd = open((char *)s, O_RDONLY)) < 0) {
- vec_free(s);
- return -errno;
- }
+ if ((fd = open ((char *) s, O_RDONLY)) < 0)
+ {
+ vec_free (s);
+ return -errno;
+ }
- int r = rtnl_exec_in_namespace_byfd(fd, fn, arg, ret);
- vec_free(s);
- close(fd);
+ int r = rtnl_exec_in_namespace_byfd (fd, fn, arg, ret);
+ vec_free (s);
+ close (fd);
return r;
}
/* this function is run by the second thread */
-static void *rtnl_thread_fn(void *p)
+static void *
+rtnl_thread_fn (void *p)
{
rtnl_ns_t *ns = (rtnl_ns_t *) p;
- if (setns(ns->ns_fd, 0)) {
- clib_warning("setns(%d, %d) error %d", ns->ns_fd, CLONE_NEWNET, errno);
- return (void *) -1;
- }
+ if (setns (ns->ns_fd, 0))
+ {
+ clib_warning ("setns(%d, %d) error %d", ns->ns_fd, CLONE_NEWNET, errno);
+ return (void *) -1;
+ }
- if ((ns->rtnl_socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
- clib_warning("Cannot open socket");
- return (void *) -2;
- }
+ if ((ns->rtnl_socket = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
+ {
+ clib_warning ("Cannot open socket");
+ return (void *) -2;
+ }
return NULL;
}
-static int rtnl_socket_open(rtnl_ns_t *ns)
+static int
+rtnl_socket_open (rtnl_ns_t *ns)
{
rtnl_main_t *rm = &rtnl_main;
pthread_t thread;
void *thread_ret;
- if(pthread_create(&thread, NULL, rtnl_thread_fn, ns)) {
- clib_warning("Can't create opening thread");
- return -1;
- }
+ if (pthread_create (&thread, NULL, rtnl_thread_fn, ns))
+ {
+ clib_warning ("Can't create opening thread");
+ return -1;
+ }
- if(pthread_join(thread, &thread_ret)) {
- clib_warning("Can't join opening thread");
- return -2;
- }
+ if (pthread_join (thread, &thread_ret))
+ {
+ clib_warning ("Can't join opening thread");
+ return -2;
+ }
- if (thread_ret) {
- clib_warning("Could not open netlink socket");
- return -3;
- }
+ if (thread_ret)
+ {
+ clib_warning ("Could not open netlink socket");
+ return -3;
+ }
struct sockaddr_nl addr = {
.nl_family = AF_NETLINK,
.nl_pad = 0,
.nl_pid = 0,
/*add mpls message group*/
- .nl_groups = grpmask(RTNLGRP_LINK)| grpmask(RTNLGRP_IPV6_IFADDR) |
- grpmask(RTNLGRP_IPV4_IFADDR) | grpmask(RTNLGRP_IPV4_ROUTE) |
- grpmask(RTNLGRP_IPV6_ROUTE) | grpmask(RTNLGRP_NEIGH) |
- grpmask(RTNLGRP_NOTIFY) /* | grpmask(RTNLGRP_MPLS_ROUTE)*/,
+ .nl_groups = grpmask (RTNLGRP_LINK) | grpmask (RTNLGRP_IPV6_IFADDR) |
+ grpmask (RTNLGRP_IPV4_IFADDR) | grpmask (RTNLGRP_IPV4_ROUTE) |
+ grpmask (RTNLGRP_IPV6_ROUTE) | grpmask (RTNLGRP_NEIGH) |
+ grpmask (RTNLGRP_NOTIFY) /* | grpmask(RTNLGRP_MPLS_ROUTE)*/,
};
- if (bind(ns->rtnl_socket, (struct sockaddr*) &addr, sizeof(addr))) {
- close(ns->rtnl_socket);
- return -3;
- }
+ if (bind (ns->rtnl_socket, (struct sockaddr *) &addr, sizeof (addr)))
+ {
+ close (ns->rtnl_socket);
+ return -3;
+ }
- clib_file_t template = {0};
+ clib_file_t template = { 0 };
template.read_function = rtnl_read_cb;
template.file_descriptor = ns->rtnl_socket;
template.private_data = (uword) (ns - rm->streams);
@@ -283,11 +311,11 @@ static int rtnl_socket_open(rtnl_ns_t *ns)
}
static int
-rtnl_rcv_error(rtnl_ns_t *ns, struct nlmsghdr *hdr, int *error)
+rtnl_rcv_error (rtnl_ns_t *ns, struct nlmsghdr *hdr, int *error)
{
- struct nlmsgerr *err = NLMSG_DATA(hdr);
- size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN(sizeof(*hdr));
- if(datalen < sizeof(*err))
+ struct nlmsgerr *err = NLMSG_DATA (hdr);
+ size_t datalen = hdr->nlmsg_len - NLMSG_ALIGN (sizeof (*hdr));
+ if (datalen < sizeof (*err))
return -1;
*error = err->error;
@@ -295,142 +323,152 @@ rtnl_rcv_error(rtnl_ns_t *ns, struct nlmsghdr *hdr, int *error)
}
static void
-rtnl_sync_reset(rtnl_ns_t *ns)
+rtnl_sync_reset (rtnl_ns_t *ns)
{
if (ns->sync_state == RTNL_SS_OPENING)
return;
- rtnl_socket_close(ns);
+ rtnl_socket_close (ns);
ns->sync_state = RTNL_SS_OPENING;
}
static void
-rtnl_sync_done(rtnl_ns_t *ns)
+rtnl_sync_done (rtnl_ns_t *ns)
{
rtnl_main_t *rm = &rtnl_main;
struct ifaddrmsg addrmsg;
struct rtmsg rtmsg;
struct ndmsg ndmsg;
- switch (ns->sync_state) {
- case RTNL_SS_OPENING:
- //Cannot happen here
- break;
- case RTNL_SS_LINK:
- memset(&addrmsg, 0, sizeof(addrmsg));
- addrmsg.ifa_family = AF_UNSPEC;
- if(rtnl_dump_request(ns, RTM_GETADDR, &addrmsg, sizeof(addrmsg))) {
- rtnl_sync_reset(ns);
- rtnl_schedule_timeout(ns, rm->now + 1);
- return;
- }
- rtnl_schedule_timeout(ns, rm->now + RTNL_DUMP_TIMEOUT);
- ns->sync_state = RTNL_SS_ADDR;
- break;
- case RTNL_SS_ADDR:
- case RTNL_SS_ROUTE4:
- memset(&rtmsg, 0, sizeof(rtmsg));
- rtmsg.rtm_family = (ns->sync_state == RTNL_SS_ADDR)?AF_INET:AF_INET6;
- rtmsg.rtm_table = RT_TABLE_UNSPEC;
- if(rtnl_dump_request(ns, RTM_GETROUTE, &rtmsg, sizeof(rtmsg))) {
- rtnl_sync_reset(ns);
- rtnl_schedule_timeout(ns, rm->now + 1);
- return;
+ switch (ns->sync_state)
+ {
+ case RTNL_SS_OPENING:
+ // Cannot happen here
+ break;
+ case RTNL_SS_LINK:
+ memset (&addrmsg, 0, sizeof (addrmsg));
+ addrmsg.ifa_family = AF_UNSPEC;
+ if (rtnl_dump_request (ns, RTM_GETADDR, &addrmsg, sizeof (addrmsg)))
+ {
+ rtnl_sync_reset (ns);
+ rtnl_schedule_timeout (ns, rm->now + 1);
+ return;
+ }
+ rtnl_schedule_timeout (ns, rm->now + RTNL_DUMP_TIMEOUT);
+ ns->sync_state = RTNL_SS_ADDR;
+ break;
+ case RTNL_SS_ADDR:
+ case RTNL_SS_ROUTE4:
+ memset (&rtmsg, 0, sizeof (rtmsg));
+ rtmsg.rtm_family = (ns->sync_state == RTNL_SS_ADDR) ? AF_INET : AF_INET6;
+ rtmsg.rtm_table = RT_TABLE_UNSPEC;
+ if (rtnl_dump_request (ns, RTM_GETROUTE, &rtmsg, sizeof (rtmsg)))
+ {
+ rtnl_sync_reset (ns);
+ rtnl_schedule_timeout (ns, rm->now + 1);
+ return;
+ }
+ rtnl_schedule_timeout (ns, rm->now + RTNL_DUMP_TIMEOUT);
+ ns->sync_state =
+ (ns->sync_state == RTNL_SS_ADDR) ? RTNL_SS_ROUTE4 : RTNL_SS_ROUTE6;
+ break;
+ case RTNL_SS_ROUTE6:
+ memset (&ndmsg, 0, sizeof (ndmsg));
+ ndmsg.ndm_family = AF_UNSPEC;
+ if (rtnl_dump_request (ns, RTM_GETNEIGH, &ndmsg, sizeof (ndmsg)))
+ {
+ rtnl_sync_reset (ns);
+ rtnl_schedule_timeout (ns, rm->now + 1);
+ return;
+ }
+ rtnl_schedule_timeout (ns, rm->now + RTNL_DUMP_TIMEOUT);
+ ns->sync_state = RTNL_SS_NEIGH;
+ break;
+ case RTNL_SS_NEIGH:
+ ns->state = RTNL_S_READY;
+ ns->sync_state = 0;
+ rtnl_cancel_timeout (ns);
+ break;
}
- rtnl_schedule_timeout(ns, rm->now + RTNL_DUMP_TIMEOUT);
- ns->sync_state = (ns->sync_state == RTNL_SS_ADDR)?RTNL_SS_ROUTE4:RTNL_SS_ROUTE6;
- break;
- case RTNL_SS_ROUTE6:
- memset(&ndmsg, 0, sizeof(ndmsg));
- ndmsg.ndm_family = AF_UNSPEC;
- if(rtnl_dump_request(ns, RTM_GETNEIGH, &ndmsg, sizeof(ndmsg))) {
- rtnl_sync_reset(ns);
- rtnl_schedule_timeout(ns, rm->now + 1);
- return;
- }
- rtnl_schedule_timeout(ns, rm->now + RTNL_DUMP_TIMEOUT);
- ns->sync_state = RTNL_SS_NEIGH;
- break;
- case RTNL_SS_NEIGH:
- ns->state = RTNL_S_READY;
- ns->sync_state = 0;
- rtnl_cancel_timeout(ns);
- break;
- }
}
static void
-rtnl_sync_timeout(rtnl_ns_t *ns)
+rtnl_sync_timeout (rtnl_ns_t *ns)
{
rtnl_main_t *rm = &rtnl_main;
struct ifinfomsg imsg = {};
- switch (ns->sync_state) {
- case RTNL_SS_OPENING:
- if (rtnl_socket_open(ns)) {
- rtnl_schedule_timeout(ns, rm->now + 10);
- return;
- }
- imsg.ifi_family = AF_UNSPEC;
- if (rtnl_dump_request(ns, RTM_GETLINK, &imsg, sizeof(imsg))) {
- rtnl_sync_reset(ns);
- rtnl_schedule_timeout(ns, rm->now + 10);
+ switch (ns->sync_state)
+ {
+ case RTNL_SS_OPENING:
+ if (rtnl_socket_open (ns))
+ {
+ rtnl_schedule_timeout (ns, rm->now + 10);
+ return;
+ }
+ imsg.ifi_family = AF_UNSPEC;
+ if (rtnl_dump_request (ns, RTM_GETLINK, &imsg, sizeof (imsg)))
+ {
+ rtnl_sync_reset (ns);
+ rtnl_schedule_timeout (ns, rm->now + 10);
+ }
+ ns->sync_state = RTNL_SS_LINK;
+ rtnl_schedule_timeout (ns, rm->now + 2);
+ break;
+ case RTNL_SS_LINK:
+ case RTNL_SS_ADDR:
+ case RTNL_SS_ROUTE4:
+ case RTNL_SS_ROUTE6:
+ case RTNL_SS_NEIGH:
+ // Timeout happened while synchronizing
+ rtnl_sync_reset (ns);
+ rtnl_schedule_timeout (ns, rm->now + 1);
+ break;
}
- ns->sync_state = RTNL_SS_LINK;
- rtnl_schedule_timeout(ns, rm->now + 2);
- break;
- case RTNL_SS_LINK:
- case RTNL_SS_ADDR:
- case RTNL_SS_ROUTE4:
- case RTNL_SS_ROUTE6:
- case RTNL_SS_NEIGH:
- //Timeout happened while synchronizing
- rtnl_sync_reset(ns);
- rtnl_schedule_timeout(ns, rm->now + 1);
- break;
- }
}
static int
-rtnl_ns_recv(rtnl_ns_t *ns, struct nlmsghdr *hdr)
+rtnl_ns_recv (rtnl_ns_t *ns, struct nlmsghdr *hdr)
{
rtnl_main_t *rm = &rtnl_main;
int ret, error = 0;
- if (ns->state == RTNL_S_SYNC &&
- ((hdr->nlmsg_flags & RTM_F_NOTIFY) ||
- (hdr->nlmsg_seq != (ns->rtnl_seq)))) {
- clib_warning("Received notification while in sync. Restart synchronization.");
- rtnl_sync_reset(ns);
- rtnl_schedule_timeout(ns, rm->now);
- }
-
- switch (hdr->nlmsg_type) {
- case NLMSG_DONE:
- rtnl_sync_done(ns);
- break;
- case NLMSG_ERROR:
- if((ret = rtnl_rcv_error(ns, hdr, &error)))
- return ret;
- break;
- case RTM_NEWROUTE:
- case RTM_DELROUTE:
- case RTM_NEWLINK:
- case RTM_DELLINK:
- case RTM_NEWADDR:
- case RTM_DELADDR:
- case RTM_NEWNEIGH:
- case RTM_DELNEIGH:
- if (ns->stream.recv_message)
- ns->stream.recv_message(hdr, ns->stream.opaque);
- break;
- default:
- clib_warning("Unknown rtnetlink type %d", hdr->nlmsg_type);
- break;
- }
+ if (ns->state == RTNL_S_SYNC && ((hdr->nlmsg_flags & RTM_F_NOTIFY) ||
+ (hdr->nlmsg_seq != (ns->rtnl_seq))))
+ {
+ clib_warning (
+ "Received notification while in sync. Restart synchronization.");
+ rtnl_sync_reset (ns);
+ rtnl_schedule_timeout (ns, rm->now);
+ }
+
+ switch (hdr->nlmsg_type)
+ {
+ case NLMSG_DONE:
+ rtnl_sync_done (ns);
+ break;
+ case NLMSG_ERROR:
+ if ((ret = rtnl_rcv_error (ns, hdr, &error)))
+ return ret;
+ break;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ if (ns->stream.recv_message)
+ ns->stream.recv_message (hdr, ns->stream.opaque);
+ break;
+ default:
+ clib_warning ("Unknown rtnetlink type %d", hdr->nlmsg_type);
+ break;
+ }
return 0;
}
static void
-rtnl_process_open(rtnl_ns_t *ns)
+rtnl_process_open (rtnl_ns_t *ns)
{
rtnl_main_t *rm = &rtnl_main;
if (ns->state != RTNL_S_INIT)
@@ -438,163 +476,182 @@ rtnl_process_open(rtnl_ns_t *ns)
ns->state = RTNL_S_SYNC;
ns->sync_state = RTNL_SS_OPENING;
- rtnl_schedule_timeout(ns, rm->now);
+ rtnl_schedule_timeout (ns, rm->now);
}
static void
-rtnl_process_close(rtnl_ns_t *ns)
+rtnl_process_close (rtnl_ns_t *ns)
{
rtnl_main_t *rm = &rtnl_main;
if (ns->state == RTNL_S_INIT)
return;
- rtnl_socket_close(ns);
- close(ns->ns_fd);
- pool_put(rm->streams, ns);
+ rtnl_socket_close (ns);
+ close (ns->ns_fd);
+ pool_put (rm->streams, ns);
}
static int
-rtnl_process_read(rtnl_ns_t *ns)
+rtnl_process_read (rtnl_ns_t *ns)
{
uint8_t buff[RTNL_BUFFSIZ];
ssize_t len;
struct nlmsghdr *hdr;
- while(1) {
- if((len = recv(ns->rtnl_socket, buff, RTNL_BUFFSIZ, MSG_DONTWAIT)) < 0) {
- if(errno != EAGAIN) {
- clib_warning("rtnetlink recv error (%d) [%s]: %s", ns->rtnl_socket, ns->stream.name, strerror(errno));
- return -1;
- }
- return 0;
- }
-
- for(hdr = (struct nlmsghdr *) buff;
- len > 0;
- len -= NLMSG_ALIGN(hdr->nlmsg_len),
- hdr = (struct nlmsghdr *) (((uint8_t *) hdr) + NLMSG_ALIGN(hdr->nlmsg_len))) {
- if((sizeof(*hdr) > (size_t)len) || (hdr->nlmsg_len > (size_t)len)) {
- clib_warning("rtnetlink buffer too small (%d Vs %d)", (int) hdr->nlmsg_len, (int) len);
- return -1;
- }
- if (rtnl_ns_recv(ns, hdr))
- return -1;
+ while (1)
+ {
+ if ((len = recv (ns->rtnl_socket, buff, RTNL_BUFFSIZ, MSG_DONTWAIT)) < 0)
+ {
+ if (errno != EAGAIN)
+ {
+ clib_warning ("rtnetlink recv error (%d) [%s]: %s",
+ ns->rtnl_socket, ns->stream.name,
+ strerror (errno));
+ return -1;
+ }
+ return 0;
+ }
+
+ for (hdr = (struct nlmsghdr *) buff; len > 0;
+ len -= NLMSG_ALIGN (hdr->nlmsg_len),
+ hdr = (struct nlmsghdr *) (((uint8_t *) hdr) +
+ NLMSG_ALIGN (hdr->nlmsg_len)))
+ {
+ if ((sizeof (*hdr) > (size_t) len) ||
+ (hdr->nlmsg_len > (size_t) len))
+ {
+ clib_warning ("rtnetlink buffer too small (%d Vs %d)",
+ (int) hdr->nlmsg_len, (int) len);
+ return -1;
+ }
+ if (rtnl_ns_recv (ns, hdr))
+ return -1;
+ }
}
- }
return 0;
}
static void
-rtnl_process_timeout(rtnl_ns_t *ns)
-{
- switch (ns->state) {
- case RTNL_S_SYNC:
- rtnl_sync_timeout(ns);
- break;
- case RTNL_S_INIT:
- case RTNL_S_READY:
- clib_warning("Should not happen");
- break;
- }
+rtnl_process_timeout (rtnl_ns_t *ns)
+{
+ switch (ns->state)
+ {
+ case RTNL_S_SYNC:
+ rtnl_sync_timeout (ns);
+ break;
+ case RTNL_S_INIT:
+ case RTNL_S_READY:
+ clib_warning ("Should not happen");
+ break;
+ }
}
static uword
-rtnl_process (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+rtnl_process (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
rtnl_main_t *rm = &rtnl_main;
uword event_type;
uword *event_data = 0;
- rm->now = vlib_time_now(vm);
+ rm->now = vlib_time_now (vm);
f64 timeout = DBL_MAX;
rtnl_ns_t *ns;
- //Setting up
- while (1) {
- vlib_process_wait_for_event_or_clock(vm, timeout - rm->now);
- event_type = vlib_process_get_events(vm, &event_data);
- rm->now = vlib_time_now(vm);
-
- if (event_type == ~0) { //Clock event or no event
- pool_foreach(ns, rm->streams, {
- if (ns->timeout < rm->now) {
- ns->timeout = DBL_MAX;
- rtnl_process_timeout(ns);
- }
- });
- } else {
- rtnl_ns_t *ns;
- uword *d;
- vec_foreach(d, event_data) {
- ns = &rm->streams[d[0]];
- switch (event_type)
- {
- case RTNL_E_CLOSE:
- rtnl_process_close(ns);
- break;
- case RTNL_E_OPEN:
- rtnl_process_open(ns);
- break;
- case RTNL_E_READ:
- rtnl_process_read(ns);
- break;
- }
- }
+ // Setting up
+ while (1)
+ {
+ vlib_process_wait_for_event_or_clock (vm, timeout - rm->now);
+ event_type = vlib_process_get_events (vm, &event_data);
+ rm->now = vlib_time_now (vm);
+
+ if (event_type == ~0)
+ { // Clock event or no event
+ pool_foreach (ns, rm->streams, {
+ if (ns->timeout < rm->now)
+ {
+ ns->timeout = DBL_MAX;
+ rtnl_process_timeout (ns);
+ }
+ })
+ ;
+ }
+ else
+ {
+ rtnl_ns_t *ns;
+ uword *d;
+ vec_foreach (d, event_data)
+ {
+ ns = &rm->streams[d[0]];
+ switch (event_type)
+ {
+ case RTNL_E_CLOSE:
+ rtnl_process_close (ns);
+ break;
+ case RTNL_E_OPEN:
+ rtnl_process_open (ns);
+ break;
+ case RTNL_E_READ:
+ rtnl_process_read (ns);
+ break;
+ }
+ }
+ }
+
+ vec_reset_length (event_data);
+
+ timeout = DBL_MAX;
+ pool_foreach (ns, rm->streams, {
+ if (ns->timeout < timeout)
+ timeout = ns->timeout;
+ })
+ ;
}
-
- vec_reset_length (event_data);
-
- timeout = DBL_MAX;
- pool_foreach(ns, rm->streams, {
- if (ns->timeout < timeout)
- timeout = ns->timeout;
- });
- }
return frame->n_vectors;
}
-VLIB_REGISTER_NODE(rtnl_process_node, static) = {
+VLIB_REGISTER_NODE (rtnl_process_node, static) = {
.function = rtnl_process,
.name = "rtnl-process",
.type = VLIB_NODE_TYPE_PROCESS,
};
u32
-rtnl_stream_open(rtnl_stream_t *template)
+rtnl_stream_open (rtnl_stream_t *template)
{
- vlib_main_t *vm = vlib_get_main();
+ vlib_main_t *vm = vlib_get_main ();
rtnl_main_t *rm = &rtnl_main;
rtnl_ns_t *ns;
int fd;
- u8 *s = format((u8 *)0, "%U", format_rtnl_nsname2path, template->name);
- vec_add1(s, 0);
-
- if ((fd = open((char *)s, O_RDONLY)) < 0) {
- clib_unix_warning("open stream %s: ", s);
- vec_free(s);
- return ~0;
- }
+ u8 *s = format ((u8 *) 0, "%U", format_rtnl_nsname2path, template->name);
+ vec_add1 (s, 0);
+
+ if ((fd = open ((char *) s, O_RDONLY)) < 0)
+ {
+ clib_unix_warning ("open stream %s: ", s);
+ vec_free (s);
+ return ~0;
+ }
- vec_free(s);
- pool_get(rm->streams, ns);
+ vec_free (s);
+ pool_get (rm->streams, ns);
ns->state = RTNL_S_INIT;
ns->ns_fd = fd;
ns->stream = *template;
- vlib_process_signal_event(vm, rtnl_process_node.index, RTNL_E_OPEN, (uword)(ns - rm->streams));
+ vlib_process_signal_event (vm, rtnl_process_node.index, RTNL_E_OPEN,
+ (uword) (ns - rm->streams));
return ns - rm->streams;
}
void
-rtnl_stream_close(u32 stream_index)
+rtnl_stream_close (u32 stream_index)
{
- vlib_main_t *vm = vlib_get_main();
+ vlib_main_t *vm = vlib_get_main ();
rtnl_main_t *rm = &rtnl_main;
- ASSERT(!pool_is_free_index(rm->streams, stream_index));
- vlib_process_signal_event(vm, rtnl_process_node.index, RTNL_E_CLOSE, stream_index);
+ ASSERT (!pool_is_free_index (rm->streams, stream_index));
+ vlib_process_signal_event (vm, rtnl_process_node.index, RTNL_E_CLOSE,
+ stream_index);
}
clib_error_t *
-rtnl_init (vlib_main_t * vm)
+rtnl_init (vlib_main_t *vm)
{
rtnl_main_t *rm = &rtnl_main;
rm->streams = 0;
diff --git a/extras/router-plugin/devices/rtnetlink/rtnl.h b/extras/router-plugin/devices/rtnetlink/rtnl.h
index 3f96252c1..4c22b912a 100644
--- a/extras/router-plugin/devices/rtnetlink/rtnl.h
+++ b/extras/router-plugin/devices/rtnetlink/rtnl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,7 +21,8 @@
#include <linux/netlink.h>
#include <vppinfra/clib.h>
-typedef enum {
+typedef enum
+{
RTNL_ERR_UNKNOWN,
} rtnl_error_t;
@@ -37,24 +38,27 @@ typedef enum {
* new dump requests are sent.
*/
-typedef struct rtnl_stream_s {
+typedef struct rtnl_stream_s
+{
char name[RTNL_NETNS_NAMELEN + 1];
- void (*recv_message)(struct nlmsghdr *hdr, uword opaque);
- void (*error)(rtnl_error_t err, uword opaque);
+ void (*recv_message) (struct nlmsghdr *hdr, uword opaque);
+ void (*error) (rtnl_error_t err, uword opaque);
uword opaque;
} rtnl_stream_t;
-u32 rtnl_stream_open(rtnl_stream_t *template);
-void rtnl_stream_close(u32 handle);
+u32 rtnl_stream_open (rtnl_stream_t *template);
+void rtnl_stream_close (u32 handle);
/*
* Executes a function in a synchronously executed thread in the
* given namespace.
* Returns 0 on success, and -errno on error.
*/
-int rtnl_exec_in_namespace(u32 handle, void *(*fn)(void *), void *arg, void **ret);
-int rtnl_exec_in_namespace_by_name(char *nsname, void *(*fn)(void *), void *arg, void **ret);
+int rtnl_exec_in_namespace (u32 handle, void *(*fn) (void *), void *arg,
+ void **ret);
+int rtnl_exec_in_namespace_by_name (char *nsname, void *(*fn) (void *),
+ void *arg, void **ret);
-u8 *format_rtnl_nsname2path(u8 *s, va_list *args);
+u8 *format_rtnl_nsname2path (u8 *s, va_list *args);
#endif
diff --git a/extras/router-plugin/devices/rtnetlink/test.c b/extras/router-plugin/devices/rtnetlink/test.c
index 031748dd3..c969f6108 100644
--- a/extras/router-plugin/devices/rtnetlink/test.c
+++ b/extras/router-plugin/devices/rtnetlink/test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,183 +15,191 @@
#include <librtnl/netns.h>
-#include <vnet/plugin/plugin.h>
#include <librtnl/mapper.h>
-#include <vnet/ip/ip.h>
#include <vnet/fib/fib.h>
#include <vnet/fib/ip4_fib.h>
#include <vnet/fib/ip6_fib.h>
+#include <vnet/ip/ip.h>
+#include <vnet/plugin/plugin.h>
u32 handles[10];
static void
-test_notify(void *obj, netns_type_t type, u32 flags, uword opaque) {
+test_notify (void *obj, netns_type_t type, u32 flags, uword opaque)
+{
u32 index = (u32) opaque;
- const char *action = (flags & NETNS_F_ADD)?"add":(flags & NETNS_F_DEL)?"del":"mod";
+ const char *action = (flags & NETNS_F_ADD) ? "add" :
+ (flags & NETNS_F_DEL) ? "del" :
+ "mod";
- switch (type) {
+ switch (type)
+ {
case NETNS_TYPE_ADDR:
- clib_warning("%d: addr %s %U", index, action, format_ns_addr, (ns_addr_t *)obj);
+ clib_warning ("%d: addr %s %U", index, action, format_ns_addr,
+ (ns_addr_t *) obj);
break;
case NETNS_TYPE_ROUTE:
- clib_warning("%d: route %s %U", index, action, format_ns_route, (ns_route_t *)obj);
+ clib_warning ("%d: route %s %U", index, action, format_ns_route,
+ (ns_route_t *) obj);
break;
case NETNS_TYPE_LINK:
- clib_warning("%d:link %s %U", index, action, format_ns_link, (ns_link_t *)obj);
+ clib_warning ("%d:link %s %U", index, action, format_ns_link,
+ (ns_link_t *) obj);
break;
case NETNS_TYPE_NEIGH:
- clib_warning("%d: neigh %s %U", index, action, format_ns_neigh, (ns_neigh_t *)obj);
+ clib_warning ("%d: neigh %s %U", index, action, format_ns_neigh,
+ (ns_neigh_t *) obj);
break;
- }
+ }
}
static clib_error_t *
-test_enable_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+test_enable_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
char *nsname = 0;
u32 index;
- if (!unformat(input, "%s", &nsname)) {
- return clib_error_return(0, "unknown input `%U'",
- format_unformat_error, input);
- }
- if (!unformat(input, "%d", &index)) {
- return clib_error_return(0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- if (!strcmp(nsname, "default"))
+ if (!unformat (input, "%s", &nsname))
+ {
+ return clib_error_return (0, "unknown input `%U'", format_unformat_error,
+ input);
+ }
+ if (!unformat (input, "%d", &index))
+ {
+ return clib_error_return (0, "unknown input `%U'", format_unformat_error,
+ input);
+ }
+
+ if (!strcmp (nsname, "default"))
nsname[0] = 0;
netns_sub_t sub;
sub.notify = test_notify;
sub.opaque = index;
- handles[index] = netns_open(nsname, &sub);
- if (handles[index] == ~0) {
- return clib_error_create("Could not open netns with name %s", nsname);
- }
+ handles[index] = netns_open (nsname, &sub);
+ if (handles[index] == ~0)
+ {
+ return clib_error_create ("Could not open netns with name %s", nsname);
+ }
return 0;
}
static clib_error_t *
-test_disable_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+test_disable_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
u32 index;
- if (!unformat(input, "%d", &index)) {
- return clib_error_return(0, "unknown input `%U'",
- format_unformat_error, input);
- }
+ if (!unformat (input, "%d", &index))
+ {
+ return clib_error_return (0, "unknown input `%U'", format_unformat_error,
+ input);
+ }
- netns_close(handles[index]);
+ netns_close (handles[index]);
return 0;
}
VLIB_CLI_COMMAND (rtnl_enable_command, static) = {
- .path = "test netns enable",
- .short_help = "test netns enable [<ns-name>|default] <index>",
- .function = test_enable_command_fn,
+ .path = "test netns enable",
+ .short_help = "test netns enable [<ns-name>|default] <index>",
+ .function = test_enable_command_fn,
};
VLIB_CLI_COMMAND (rtnl_disable_command, static) = {
- .path = "test netns disable",
- .short_help = "test rtnl disable <index>",
- .function = test_disable_command_fn,
+ .path = "test netns disable",
+ .short_help = "test rtnl disable <index>",
+ .function = test_disable_command_fn,
};
u32 mapper_indexes[10];
static clib_error_t *
-mapper_ns_add_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+mapper_ns_add_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
u32 index;
char *nsname;
u32 table_id;
- if (!unformat(input, "%d", &index))
- return clib_error_return(0, "invalid index `%U'",
- format_unformat_error, input);
- if (!unformat(input, "%s", &nsname))
- return clib_error_return(0, "invalid nsname `%U'",
- format_unformat_error, input);
- if (!unformat(input, "%d", &table_id))
- return clib_error_return(0, "invalid fib index `%U'",
- format_unformat_error, input);
-
- if (!strcmp(nsname, "default"))
+ if (!unformat (input, "%d", &index))
+ return clib_error_return (0, "invalid index `%U'", format_unformat_error,
+ input);
+ if (!unformat (input, "%s", &nsname))
+ return clib_error_return (0, "invalid nsname `%U'", format_unformat_error,
+ input);
+ if (!unformat (input, "%d", &table_id))
+ return clib_error_return (0, "invalid fib index `%U'",
+ format_unformat_error, input);
+
+ if (!strcmp (nsname, "default"))
nsname[0] = 0;
- u32 fib4 = ip4_fib_index_from_table_id(table_id);
- u32 fib6 = ip6_fib_index_from_table_id(table_id);
+ u32 fib4 = ip4_fib_index_from_table_id (table_id);
+ u32 fib6 = ip6_fib_index_from_table_id (table_id);
- if (mapper_add_ns(nsname, fib4, fib6, &mapper_indexes[index]))
- return clib_error_return(0, "Could not add ns %s", nsname);
+ if (mapper_add_ns (nsname, fib4, fib6, &mapper_indexes[index]))
+ return clib_error_return (0, "Could not add ns %s", nsname);
return 0;
}
VLIB_CLI_COMMAND (mapper_ns_add_command, static) = {
- .path = "test mapper ns add",
- .short_help = "test mapper ns add <index> <nsname> <table-id>",
- .function = mapper_ns_add_command_fn,
+ .path = "test mapper ns add",
+ .short_help = "test mapper ns add <index> <nsname> <table-id>",
+ .function = mapper_ns_add_command_fn,
};
static clib_error_t *
-mapper_ns_del_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+mapper_ns_del_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
u32 index;
- if (!unformat(input, "%d", &index))
- return clib_error_return(0, "invalid index `%U'",
- format_unformat_error, input);
+ if (!unformat (input, "%d", &index))
+ return clib_error_return (0, "invalid index `%U'", format_unformat_error,
+ input);
- if (mapper_del_ns(mapper_indexes[index]))
- return clib_error_return(0, "Could not del ns %d", index);
+ if (mapper_del_ns (mapper_indexes[index]))
+ return clib_error_return (0, "Could not del ns %d", index);
return 0;
}
VLIB_CLI_COMMAND (mapper_ns_del_command, static) = {
- .path = "test mapper ns delete",
- .short_help = "test mapper ns delete <index>",
- .function = mapper_ns_del_command_fn,
+ .path = "test mapper ns delete",
+ .short_help = "test mapper ns delete <index>",
+ .function = mapper_ns_del_command_fn,
};
static clib_error_t *
-mapper_iface_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
+mapper_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
u32 nsindex;
u32 ifindex;
u32 sw_if_index;
int del = 0;
- if (!unformat(input, "%d", &nsindex))
- return clib_error_return(0, "invalid nsindex `%U'",
- format_unformat_error, input);
- if (!unformat(input, "%d", &ifindex))
- return clib_error_return(0, "invalid ifindex `%U'",
- format_unformat_error, input);
- if (!unformat(input, "%d", &sw_if_index))
- return clib_error_return(0, "invalid sw_if_index `%U'",
- format_unformat_error, input);
- if (unformat(input, "del"))
+ if (!unformat (input, "%d", &nsindex))
+ return clib_error_return (0, "invalid nsindex `%U'", format_unformat_error,
+ input);
+ if (!unformat (input, "%d", &ifindex))
+ return clib_error_return (0, "invalid ifindex `%U'", format_unformat_error,
+ input);
+ if (!unformat (input, "%d", &sw_if_index))
+ return clib_error_return (0, "invalid sw_if_index `%U'",
+ format_unformat_error, input);
+ if (unformat (input, "del"))
del = 1;
- clib_warning("mapper_add_del %d %d %d %d", mapper_indexes[nsindex], ifindex, sw_if_index, del);
+ clib_warning ("mapper_add_del %d %d %d %d", mapper_indexes[nsindex], ifindex,
+ sw_if_index, del);
- if (mapper_add_del(mapper_indexes[nsindex], ifindex, sw_if_index, del))
- return clib_error_return(0, "Could not add iface");
+ if (mapper_add_del (mapper_indexes[nsindex], ifindex, sw_if_index, del))
+ return clib_error_return (0, "Could not add iface");
return 0;
}
-
VLIB_CLI_COMMAND (mapper_iface_command, static) = {
- .path = "test mapper iface",
- .short_help = "test mapper iface <nsindex> <linux-ifindex> <sw_if_index> [del]",
- .function = mapper_iface_command_fn,
+ .path = "test mapper iface",
+ .short_help =
+ "test mapper iface <nsindex> <linux-ifindex> <sw_if_index> [del]",
+ .function = mapper_iface_command_fn,
};
/* *INDENT-OFF* */
@@ -200,4 +208,3 @@ VLIB_PLUGIN_REGISTER () = {
.description = "netlink",
};
/* *INDENT-ON* */
-
diff --git a/extras/router-plugin/rtinject/tap_inject.c b/extras/router-plugin/rtinject/tap_inject.c
index f41ae86c8..7befb3862 100644
--- a/extras/router-plugin/rtinject/tap_inject.c
+++ b/extras/router-plugin/rtinject/tap_inject.c
@@ -16,10 +16,10 @@
#include "tap_inject.h"
-#include <vnet/mfib/mfib_table.h>
+#include <vnet/fib/fib.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/lookup.h>
-#include <vnet/fib/fib.h>
+#include <vnet/mfib/mfib_table.h>
static tap_inject_main_t tap_inject_main;
extern dpo_type_t tap_inject_dpo_type;
@@ -33,7 +33,7 @@ tap_inject_get_main (void)
void
tap_inject_insert_tap (u32 sw_if_index, u32 tap_fd, u32 tap_if_index)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
vec_validate_init_empty (im->sw_if_index_to_tap_fd, sw_if_index, ~0);
vec_validate_init_empty (im->sw_if_index_to_tap_if_index, sw_if_index, ~0);
@@ -51,7 +51,7 @@ tap_inject_insert_tap (u32 sw_if_index, u32 tap_fd, u32 tap_if_index)
void
tap_inject_delete_tap (u32 sw_if_index)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
u32 tap_fd = im->sw_if_index_to_tap_fd[sw_if_index];
u32 tap_if_index = im->sw_if_index_to_tap_if_index[sw_if_index];
@@ -65,7 +65,7 @@ tap_inject_delete_tap (u32 sw_if_index)
u32
tap_inject_lookup_tap_fd (u32 sw_if_index)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
vec_validate_init_empty (im->sw_if_index_to_tap_fd, sw_if_index, ~0);
return im->sw_if_index_to_tap_fd[sw_if_index];
@@ -74,7 +74,7 @@ tap_inject_lookup_tap_fd (u32 sw_if_index)
u32
tap_inject_lookup_sw_if_index_from_tap_fd (u32 tap_fd)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
vec_validate_init_empty (im->tap_fd_to_sw_if_index, tap_fd, ~0);
return im->tap_fd_to_sw_if_index[tap_fd];
@@ -83,25 +83,24 @@ tap_inject_lookup_sw_if_index_from_tap_fd (u32 tap_fd)
u32
tap_inject_lookup_sw_if_index_from_tap_if_index (u32 tap_if_index)
{
- tap_inject_main_t * im = tap_inject_get_main ();
- uword * sw_if_index;
+ tap_inject_main_t *im = tap_inject_get_main ();
+ uword *sw_if_index;
sw_if_index = hash_get (im->tap_if_index_to_sw_if_index, tap_if_index);
- return sw_if_index ? *(u32 *)sw_if_index : ~0;
+ return sw_if_index ? *(u32 *) sw_if_index : ~0;
}
/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () = {
- // .version = VPP_BUILD_VER, FIXME
- .description = "router",
+ // .version = VPP_BUILD_VER, FIXME
+ .description = "router",
};
/* *INDENT-ON* */
-
static void
tap_inject_disable (void)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
im->flags &= ~TAP_INJECT_F_ENABLED;
@@ -111,8 +110,8 @@ tap_inject_disable (void)
static clib_error_t *
tap_inject_enable (void)
{
- vlib_main_t * vm = vlib_get_main ();
- tap_inject_main_t * im = tap_inject_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
if (tap_inject_is_enabled ())
return 0;
@@ -127,7 +126,8 @@ tap_inject_enable (void)
}
/* Register ARP and ICMP6 as neighbor nodes. */
- ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, im->neighbor_node_index);
+ ethernet_register_input_type (vm, ETHERNET_TYPE_ARP,
+ im->neighbor_node_index);
ip6_register_protocol (IP_PROTOCOL_ICMP6, im->neighbor_node_index);
/* Register remaining protocols. */
@@ -147,26 +147,25 @@ tap_inject_enable (void)
const mfib_prefix_t pfx_224_0_0_0 = {
.fp_len = 24,
.fp_proto = FIB_PROTOCOL_IP4,
- .fp_grp_addr = {
- .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
- },
- .fp_src_addr = {
- .ip4.as_u32 = 0,
- },
+ .fp_grp_addr =
+ {
+ .ip4.as_u32 = clib_host_to_net_u32(0xe0000000),
+ },
+ .fp_src_addr =
+ {
+ .ip4.as_u32 = 0,
+ },
};
- dpo_set(&dpo, tap_inject_dpo_type, DPO_PROTO_IP4, ~0);
+ dpo_set (&dpo, tap_inject_dpo_type, DPO_PROTO_IP4, ~0);
- index_t repi = replicate_create(1, DPO_PROTO_IP4);
- replicate_set_bucket(repi, 0, &dpo);
+ index_t repi = replicate_create (1, DPO_PROTO_IP4);
+ replicate_set_bucket (repi, 0, &dpo);
- mfib_table_entry_special_add(0,
- &pfx_224_0_0_0,
- MFIB_SOURCE_API,
- MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF,
- repi);
+ mfib_table_entry_special_add (0, &pfx_224_0_0_0, MFIB_SOURCE_API,
+ MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF, repi);
- dpo_reset(&dpo);
+ dpo_reset (&dpo);
}
im->flags |= TAP_INJECT_F_ENABLED;
@@ -175,24 +174,24 @@ tap_inject_enable (void)
}
static uword
-tap_inject_iface_isr (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * f)
+tap_inject_iface_isr (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *f)
{
- tap_inject_main_t * im = tap_inject_get_main ();
- vnet_hw_interface_t * hw;
- u32 * hw_if_index;
- clib_error_t * err = 0;
+ tap_inject_main_t *im = tap_inject_get_main ();
+ vnet_hw_interface_t *hw;
+ u32 *hw_if_index;
+ clib_error_t *err = 0;
vec_foreach (hw_if_index, im->interfaces_to_enable)
{
hw = vnet_get_hw_interface (vnet_get_main (), *hw_if_index);
if (hw->hw_class_index == ethernet_hw_interface_class.index)
- {
- err = tap_inject_tap_connect (hw);
- if (err)
- break;
- }
+ {
+ err = tap_inject_tap_connect (hw);
+ if (err)
+ break;
+ }
}
vec_foreach (hw_if_index, im->interfaces_to_disable)
@@ -212,13 +211,12 @@ VLIB_REGISTER_NODE (tap_inject_iface_isr_node, static) = {
.vector_size = sizeof (u32),
};
-
static clib_error_t *
-tap_inject_interface_add_del (struct vnet_main_t * vnet_main, u32 hw_if_index,
- u32 add)
+tap_inject_interface_add_del (struct vnet_main_t *vnet_main, u32 hw_if_index,
+ u32 add)
{
- vlib_main_t * vm = vlib_get_main ();
- tap_inject_main_t * im = tap_inject_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
if (!tap_inject_is_config_enabled ())
return 0;
@@ -237,15 +235,14 @@ tap_inject_interface_add_del (struct vnet_main_t * vnet_main, u32 hw_if_index,
VNET_HW_INTERFACE_ADD_DEL_FUNCTION (tap_inject_interface_add_del);
-
static clib_error_t *
tap_inject_enable_disable_all_interfaces (int enable)
{
- vnet_main_t * vnet_main = vnet_get_main ();
- tap_inject_main_t * im = tap_inject_get_main ();
- vnet_hw_interface_t * interfaces;
- vnet_hw_interface_t * hw;
- u32 ** indices;
+ vnet_main_t *vnet_main = vnet_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
+ vnet_hw_interface_t *interfaces;
+ vnet_hw_interface_t *hw;
+ u32 **indices;
if (enable)
tap_inject_enable ();
@@ -255,7 +252,8 @@ tap_inject_enable_disable_all_interfaces (int enable)
/* Collect all the interface indices. */
interfaces = vnet_main->interface_main.hw_interfaces;
indices = enable ? &im->interfaces_to_enable : &im->interfaces_to_disable;
- pool_foreach (hw, interfaces, vec_add1 (*indices, hw - interfaces));
+ pool_foreach (hw, interfaces, vec_add1 (*indices, hw - interfaces))
+ ;
if (tap_inject_iface_isr (vlib_get_main (), 0, 0))
return clib_error_return (0, "tap-inject interface add del isr failed");
@@ -264,26 +262,26 @@ tap_inject_enable_disable_all_interfaces (int enable)
}
static clib_error_t *
-tap_inject_cli (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
+tap_inject_cli (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
if (cmd->function_arg)
{
- clib_error_t * err;
+ clib_error_t *err;
if (tap_inject_is_config_disabled ())
- return clib_error_return (0,
- "tap-inject is disabled in config, thus cannot be enabled.");
+ return clib_error_return (
+ 0, "tap-inject is disabled in config, thus cannot be enabled.");
/* Enable */
err = tap_inject_enable_disable_all_interfaces (1);
if (err)
- {
- tap_inject_enable_disable_all_interfaces (0);
- return err;
- }
+ {
+ tap_inject_enable_disable_all_interfaces (0);
+ return err;
+ }
im->flags |= TAP_INJECT_F_CONFIG_ENABLE;
}
@@ -311,13 +309,12 @@ VLIB_CLI_COMMAND (tap_inject_disable_cmd, static) = {
.function_arg = 0,
};
-
static clib_error_t *
-show_tap_inject (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
+show_tap_inject (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
{
- vnet_main_t * vnet_main = vnet_get_main ();
- tap_inject_main_t * im = tap_inject_get_main ();
+ vnet_main_t *vnet_main = vnet_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
u32 k, v;
if (tap_inject_is_config_disabled ())
@@ -333,10 +330,9 @@ show_tap_inject (vlib_main_t * vm, unformat_input_t * input,
}
hash_foreach (k, v, im->tap_if_index_to_sw_if_index, {
- vlib_cli_output (vm, "%U -> %U",
- format_vnet_sw_interface_name, vnet_main,
- vnet_get_sw_interface (vnet_main, v),
- format_tap_inject_tap_name, k);
+ vlib_cli_output (vm, "%U -> %U", format_vnet_sw_interface_name, vnet_main,
+ vnet_get_sw_interface (vnet_main, v),
+ format_tap_inject_tap_name, k);
});
return 0;
@@ -348,31 +344,30 @@ VLIB_CLI_COMMAND (show_tap_inject_cmd, static) = {
.function = show_tap_inject,
};
-
static clib_error_t *
-tap_inject_config (vlib_main_t * vm, unformat_input_t * input)
+tap_inject_config (vlib_main_t *vm, unformat_input_t *input)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "enable"))
- im->flags |= TAP_INJECT_F_CONFIG_ENABLE;
+ im->flags |= TAP_INJECT_F_CONFIG_ENABLE;
else if (unformat (input, "disable"))
- im->flags |= TAP_INJECT_F_CONFIG_DISABLE;
+ im->flags |= TAP_INJECT_F_CONFIG_DISABLE;
else if (unformat (input, "netlink-only"))
- im->flags |= TAP_INJECT_F_CONFIG_NETLINK;
+ im->flags |= TAP_INJECT_F_CONFIG_NETLINK;
else
- return clib_error_return (0, "syntax error `%U'",
- format_unformat_error, input);
+ return clib_error_return (0, "syntax error `%U'",
+ format_unformat_error, input);
}
if (tap_inject_is_config_enabled () && tap_inject_is_config_disabled ())
- return clib_error_return (0,
- "tap-inject cannot be both enabled and disabled.");
+ return clib_error_return (
+ 0, "tap-inject cannot be both enabled and disabled.");
return 0;
}
diff --git a/extras/router-plugin/rtinject/tap_inject.h b/extras/router-plugin/rtinject/tap_inject.h
index ec5121a09..6226a0aad 100644
--- a/extras/router-plugin/rtinject/tap_inject.h
+++ b/extras/router-plugin/rtinject/tap_inject.h
@@ -17,14 +17,15 @@
#ifndef _TAP_INJECT_H
#define _TAP_INJECT_H
-#include <vnet/plugin/plugin.h>
#include <vnet/ip/ip.h>
+#include <vnet/plugin/plugin.h>
#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
#endif
-typedef struct {
+typedef struct
+{
/*
* tap-inject can be enabled or disabled in config file or during runtime.
* When disabled in config, it is not possible to enable during runtime.
@@ -36,30 +37,29 @@ typedef struct {
#define TAP_INJECT_F_CONFIG_ENABLE (1U << 0)
#define TAP_INJECT_F_CONFIG_DISABLE (1U << 1)
#define TAP_INJECT_F_CONFIG_NETLINK (1U << 2)
-#define TAP_INJECT_F_ENABLED (1U << 3)
+#define TAP_INJECT_F_ENABLED (1U << 3)
u32 flags;
- u32 * sw_if_index_to_tap_fd;
- u32 * sw_if_index_to_tap_if_index;
- u32 * tap_fd_to_sw_if_index;
- u32 * tap_if_index_to_sw_if_index;
+ u32 *sw_if_index_to_tap_fd;
+ u32 *sw_if_index_to_tap_if_index;
+ u32 *tap_fd_to_sw_if_index;
+ u32 *tap_if_index_to_sw_if_index;
- u32 * interfaces_to_enable;
- u32 * interfaces_to_disable;
+ u32 *interfaces_to_enable;
+ u32 *interfaces_to_disable;
- u32 * rx_file_descriptors;
+ u32 *rx_file_descriptors;
u32 rx_node_index;
u32 tx_node_index;
u32 neighbor_node_index;
- u32 * rx_buffers;
+ u32 *rx_buffers;
} tap_inject_main_t;
-
-tap_inject_main_t * tap_inject_get_main (void);
+tap_inject_main_t *tap_inject_get_main (void);
void tap_inject_insert_tap (u32 sw_if_index, u32 tap_fd, u32 tap_if_index);
void tap_inject_delete_tap (u32 sw_if_index);
@@ -71,7 +71,7 @@ u32 tap_inject_lookup_sw_if_index_from_tap_if_index (u32 tap_if_index);
static inline int
tap_inject_is_enabled (void)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
return !!(im->flags & TAP_INJECT_F_ENABLED);
}
@@ -79,7 +79,7 @@ tap_inject_is_enabled (void)
static inline int
tap_inject_is_config_enabled (void)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
return !!(im->flags & TAP_INJECT_F_CONFIG_ENABLE);
}
@@ -87,22 +87,20 @@ tap_inject_is_config_enabled (void)
static inline int
tap_inject_is_config_disabled (void)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
return !!(im->flags & TAP_INJECT_F_CONFIG_DISABLE);
}
-
/* Netlink */
void tap_inject_enable_netlink (void);
-
/* Tap */
-clib_error_t * tap_inject_tap_connect (vnet_hw_interface_t * hw);
-clib_error_t * tap_inject_tap_disconnect (u32 sw_if_index);
+clib_error_t *tap_inject_tap_connect (vnet_hw_interface_t *hw);
+clib_error_t *tap_inject_tap_disconnect (u32 sw_if_index);
-u8 * format_tap_inject_tap_name (u8 * s, va_list * args);
+u8 *format_tap_inject_tap_name (u8 *s, va_list *args);
#endif /* _TAP_INJECT_H */
diff --git a/extras/router-plugin/rtinject/tap_inject_netlink.c b/extras/router-plugin/rtinject/tap_inject_netlink.c
index a221e8eaa..92ffdc6e5 100644
--- a/extras/router-plugin/rtinject/tap_inject_netlink.c
+++ b/extras/router-plugin/rtinject/tap_inject_netlink.c
@@ -15,25 +15,25 @@
*/
#include "../devices/rtnetlink/netns.h"
+#include <arpa/inet.h>
+#include <linux/mpls.h>
#include <vlibmemory/api.h>
+#include <vnet/ethernet/arp.h>
+#include <vnet/fib/fib.h>
#include <vnet/ip/ip6_neighbor.h>
#include <vnet/ip/lookup.h>
-#include <vnet/fib/fib.h>
-#include <vnet/ethernet/arp.h>
-#include <arpa/inet.h>
-#include <linux/mpls.h>
#include <vnet/mpls/packet.h>
#include "tap_inject.h"
static void
-add_del_addr (ns_addr_t * a, int is_del)
+add_del_addr (ns_addr_t *a, int is_del)
{
- vlib_main_t * vm = vlib_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
u32 sw_if_index;
- sw_if_index = tap_inject_lookup_sw_if_index_from_tap_if_index (
- a->ifaddr.ifa_index);
+ sw_if_index =
+ tap_inject_lookup_sw_if_index_from_tap_if_index (a->ifaddr.ifa_index);
if (sw_if_index == ~0)
return;
@@ -41,37 +41,39 @@ add_del_addr (ns_addr_t * a, int is_del)
if (a->ifaddr.ifa_family == AF_INET)
{
ip4_add_del_interface_address (vm, sw_if_index,
- (ip4_address_t *) a->local, a->ifaddr.ifa_prefixlen, is_del);
+ (ip4_address_t *) a->local,
+ a->ifaddr.ifa_prefixlen, is_del);
}
else if (a->ifaddr.ifa_family == AF_INET6)
{
ip6_add_del_interface_address (vm, sw_if_index,
- (ip6_address_t *) a->addr, a->ifaddr.ifa_prefixlen, is_del);
+ (ip6_address_t *) a->addr,
+ a->ifaddr.ifa_prefixlen, is_del);
}
}
-
-struct set_flags_args {
+struct set_flags_args
+{
u32 index;
u8 flags;
};
static void
-set_flags_cb (struct set_flags_args * a)
+set_flags_cb (struct set_flags_args *a)
{
vnet_sw_interface_set_flags (vnet_get_main (), a->index, a->flags);
}
static void
-add_del_link (ns_link_t * l, int is_del)
+add_del_link (ns_link_t *l, int is_del)
{
struct set_flags_args args = { ~0, 0 };
- vnet_sw_interface_t * sw;
+ vnet_sw_interface_t *sw;
u8 flags = 0;
u32 sw_if_index;
- sw_if_index = tap_inject_lookup_sw_if_index_from_tap_if_index (
- l->ifi.ifi_index);
+ sw_if_index =
+ tap_inject_lookup_sw_if_index_from_tap_if_index (l->ifi.ifi_index);
if (sw_if_index == ~0)
return;
@@ -88,19 +90,18 @@ add_del_link (ns_link_t * l, int is_del)
args.index = sw_if_index;
args.flags = flags;
- vl_api_rpc_call_main_thread (set_flags_cb, (u8 *)&args, sizeof (args));
+ vl_api_rpc_call_main_thread (set_flags_cb, (u8 *) &args, sizeof (args));
}
-
static void
-add_del_neigh (ns_neigh_t * n, int is_del)
+add_del_neigh (ns_neigh_t *n, int is_del)
{
- vnet_main_t * vnet_main = vnet_get_main ();
- vlib_main_t * vm = vlib_get_main ();
+ vnet_main_t *vnet_main = vnet_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
u32 sw_if_index;
- sw_if_index = tap_inject_lookup_sw_if_index_from_tap_if_index (
- n->nd.ndm_ifindex);
+ sw_if_index =
+ tap_inject_lookup_sw_if_index_from_tap_if_index (n->nd.ndm_ifindex);
if (sw_if_index == ~0)
return;
@@ -114,57 +115,54 @@ add_del_neigh (ns_neigh_t * n, int is_del)
clib_memcpy (&a.mac, n->lladdr, ETHER_ADDR_LEN);
clib_memcpy (&a.ip4, n->dst, sizeof (a.ip4));
-
if (n->nd.ndm_state & NUD_REACHABLE)
- {
- vnet_arp_set_ip4_over_ethernet (vnet_main, sw_if_index,
- &a,
- IP_NEIGHBOR_FLAG_NO_FIB_ENTRY);
-
- }
+ {
+ vnet_arp_set_ip4_over_ethernet (vnet_main, sw_if_index, &a,
+ IP_NEIGHBOR_FLAG_NO_FIB_ENTRY);
+ }
else if (n->nd.ndm_state & NUD_FAILED)
- {
- vnet_arp_unset_ip4_over_ethernet (vnet_main, sw_if_index, &a);
- }
+ {
+ vnet_arp_unset_ip4_over_ethernet (vnet_main, sw_if_index, &a);
+ }
}
else if (n->nd.ndm_family == AF_INET6)
{
if (n->nd.ndm_state & NUD_REACHABLE)
- {
-
- mac_address_t * mac1;
- mac1=malloc(sizeof(mac_address_t));
- memcpy (mac1, n->lladdr, ETHER_ADDR_LEN);
- vnet_set_ip6_ethernet_neighbor (vm, sw_if_index,
- (ip6_address_t *) n->dst, (mac_address_t *) mac1,
- IP_NEIGHBOR_FLAG_NONE);
- }
+ {
+
+ mac_address_t *mac1;
+ mac1 = malloc (sizeof (mac_address_t));
+ memcpy (mac1, n->lladdr, ETHER_ADDR_LEN);
+ vnet_set_ip6_ethernet_neighbor (
+ vm, sw_if_index, (ip6_address_t *) n->dst, (mac_address_t *) mac1,
+ IP_NEIGHBOR_FLAG_NONE);
+ }
else
- vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index,
- (ip6_address_t *) n->dst);
+ vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index,
+ (ip6_address_t *) n->dst);
}
}
-
#define TAP_INJECT_HOST_ROUTE_TABLE_MAIN 254
static void
-get_mpls_label_stack(struct mpls_label *addr, u32* l)
+get_mpls_label_stack (struct mpls_label *addr, u32 *l)
{
- u32 entry = ntohl(addr[0].entry);
+ u32 entry = ntohl (addr[0].entry);
u32 label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
- for(int i = 1; label != 0; i++) {
- *l++ = label;
- if(entry & MPLS_LS_S_MASK)
- return;
- entry = ntohl(addr[i].entry);
- label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
- }
+ for (int i = 1; label != 0; i++)
+ {
+ *l++ = label;
+ if (entry & MPLS_LS_S_MASK)
+ return;
+ entry = ntohl (addr[i].entry);
+ label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
+ }
}
static void
-add_del_route (ns_route_t * r, int is_del)
+add_del_route (ns_route_t *r, int is_del)
{
u32 sw_if_index;
@@ -175,101 +173,90 @@ add_del_route (ns_route_t * r, int is_del)
if (r->rtm.rtm_family == AF_INET)
{
- u32 stack[MPLS_STACK_DEPTH] = {0};
+ u32 stack[MPLS_STACK_DEPTH] = { 0 };
fib_prefix_t prefix;
- ip46_address_t nh;
+ ip_address_t nh;
memset (&prefix, 0, sizeof (prefix));
prefix.fp_len = r->rtm.rtm_dst_len;
prefix.fp_proto = FIB_PROTOCOL_IP4;
clib_memcpy (&prefix.fp_addr.ip4, r->dst, sizeof (prefix.fp_addr.ip4));
- get_mpls_label_stack(r->encap, stack);
+ get_mpls_label_stack (r->encap, stack);
memset (&nh, 0, sizeof (nh));
clib_memcpy (&nh.ip4, r->gateway, sizeof (nh.ip4));
- if(*stack == 0)
- fib_table_entry_path_add (0, &prefix, FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE, prefix.fp_proto,
- &nh, sw_if_index, 0,
- 0 /* weight */, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
- else {
- fib_route_path_t *rpaths = NULL, rpath;
- memset(&rpath, 0, sizeof(rpath));
- rpath.frp_weight = 1;
- rpath.frp_proto = DPO_PROTO_IP4;
- clib_memcpy(&rpath.frp_addr.ip4, r->gateway, sizeof(rpath.frp_addr.ip4));
- rpath.frp_sw_if_index = sw_if_index;
- for(int i = 0; i < MPLS_STACK_DEPTH && stack[i] != 0; i++) {
- fib_mpls_label_t fib_label = {stack[i],0,0,0};
- vec_add1(rpath.frp_label_stack, fib_label);
- }
- vec_add1(rpaths, rpath);
- fib_table_entry_path_add2(0,
- &prefix,
- FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE,
- rpaths);
- }
+ if (*stack == 0)
+ fib_table_entry_path_add (
+ 0, &prefix, FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE, prefix.fp_proto,
+ &nh, sw_if_index, 0, 0 /* weight */, NULL, FIB_ROUTE_PATH_FLAG_NONE);
+ else
+ {
+ fib_route_path_t *rpaths = NULL, rpath;
+ memset (&rpath, 0, sizeof (rpath));
+ rpath.frp_weight = 1;
+ rpath.frp_proto = DPO_PROTO_IP4;
+ clib_memcpy (&rpath.frp_addr.ip4, r->gateway,
+ sizeof (rpath.frp_addr.ip4));
+ rpath.frp_sw_if_index = sw_if_index;
+ for (int i = 0; i < MPLS_STACK_DEPTH && stack[i] != 0; i++)
+ {
+ fib_mpls_label_t fib_label = { stack[i], 0, 0, 0 };
+ vec_add1 (rpath.frp_label_stack, fib_label);
+ }
+ vec_add1 (rpaths, rpath);
+ fib_table_entry_path_add2 (0, &prefix, FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_NONE, rpaths);
+ }
}
else if (r->rtm.rtm_family == AF_INET6)
{
fib_prefix_t prefix;
- ip46_address_t nh;
+ ip_address_t nh;
memset (&prefix, 0, sizeof (prefix));
prefix.fp_len = r->rtm.rtm_dst_len;
prefix.fp_proto = FIB_PROTOCOL_IP6;
clib_memcpy (&prefix.fp_addr.ip6, r->dst, sizeof (prefix.fp_addr.ip6));
memset (&nh, 0, sizeof (nh));
clib_memcpy (&nh.ip6, r->gateway, sizeof (nh.ip6));
- fib_table_entry_path_add (0, &prefix, FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE, prefix.fp_proto,
- &nh, sw_if_index, 0,
- 0 /* weight */, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
+ fib_table_entry_path_add (
+ 0, &prefix, FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE, prefix.fp_proto, &nh,
+ sw_if_index, 0, 0 /* weight */, NULL, FIB_ROUTE_PATH_FLAG_NONE);
}
-/* else if (r->rtm.rtm_family == AF_MPLS)
- {
- u32 dst_label;
- get_mpls_label_stack((struct mpls_label*) r->dst, &dst_label);
- struct rtvia *via = (struct rtvia*) r->via;
- fib_prefix_t prefix;
- fib_route_path_t *rpaths = NULL, rpath;
- memset (&prefix, 0, sizeof (prefix));
- prefix.fp_len = 21;
- prefix.fp_label = dst_label;
- prefix.fp_proto = FIB_PROTOCOL_MPLS;
- prefix.fp_payload_proto = DPO_PROTO_IP4;
- memset(&rpath, 0, sizeof(rpath));
- clib_memcpy (&rpath.frp_addr.ip4, via->rtvia_addr, sizeof (rpath.frp_addr.ip4));
- rpath.frp_weight = 1;
- rpath.frp_proto = DPO_PROTO_IP4;
- rpath.frp_fib_index = 0;
- rpath.frp_sw_if_index = sw_if_index;
- vec_add1(rpaths, rpath);
- fib_table_entry_path_add2(0,
- &prefix,
- FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE,
- rpaths);
- }*/
+ /* else if (r->rtm.rtm_family == AF_MPLS)
+ {
+ u32 dst_label;
+ get_mpls_label_stack((struct mpls_label*) r->dst, &dst_label);
+ struct rtvia *via = (struct rtvia*) r->via;
+ fib_prefix_t prefix;
+ fib_route_path_t *rpaths = NULL, rpath;
+ memset (&prefix, 0, sizeof (prefix));
+ prefix.fp_len = 21;
+ prefix.fp_label = dst_label;
+ prefix.fp_proto = FIB_PROTOCOL_MPLS;
+ prefix.fp_payload_proto = DPO_PROTO_IP4;
+ memset(&rpath, 0, sizeof(rpath));
+ clib_memcpy (&rpath.frp_addr.ip4, via->rtvia_addr, sizeof
+ (rpath.frp_addr.ip4)); rpath.frp_weight = 1; rpath.frp_proto =
+ DPO_PROTO_IP4; rpath.frp_fib_index = 0; rpath.frp_sw_if_index =
+ sw_if_index; vec_add1(rpaths, rpath); fib_table_entry_path_add2(0,
+ &prefix, FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE, rpaths);
+ }*/
}
-
static void
-netns_notify_cb (void * obj, netns_type_t type, u32 flags, uword opaque)
+netns_notify_cb (void *obj, netns_type_t type, u32 flags, uword opaque)
{
if (type == NETNS_TYPE_ADDR)
- add_del_addr ((ns_addr_t *)obj, flags & NETNS_F_DEL);
+ add_del_addr ((ns_addr_t *) obj, flags & NETNS_F_DEL);
else if (type == NETNS_TYPE_LINK)
- add_del_link ((ns_link_t *)obj, flags & NETNS_F_DEL);
+ add_del_link ((ns_link_t *) obj, flags & NETNS_F_DEL);
else if (type == NETNS_TYPE_NEIGH)
- add_del_neigh ((ns_neigh_t *)obj, flags & NETNS_F_DEL);
+ add_del_neigh ((ns_neigh_t *) obj, flags & NETNS_F_DEL);
else if (type == NETNS_TYPE_ROUTE)
- add_del_route ((ns_route_t *)obj, flags & NETNS_F_DEL);
+ add_del_route ((ns_route_t *) obj, flags & NETNS_F_DEL);
}
void
diff --git a/extras/router-plugin/rtinject/tap_inject_node.c b/extras/router-plugin/rtinject/tap_inject_node.c
index 73c296451..b888b9223 100644
--- a/extras/router-plugin/rtinject/tap_inject_node.c
+++ b/extras/router-plugin/rtinject/tap_inject_node.c
@@ -15,15 +15,16 @@
*/
#include "tap_inject.h"
-#include <sys/uio.h>
#include <netinet/in.h>
+#include <sys/uio.h>
#include <vnet/ethernet/arp_packet.h>
vlib_node_registration_t tap_inject_rx_node;
vlib_node_registration_t tap_inject_tx_node;
vlib_node_registration_t tap_inject_neighbor_node;
-enum {
+enum
+{
NEXT_NEIGHBOR_ARP,
NEXT_NEIGHBOR_ICMP6,
};
@@ -34,7 +35,7 @@ enum {
dpo_type_t tap_inject_dpo_type;
static inline void
-tap_inject_tap_send_buffer (int fd, vlib_buffer_t * b)
+tap_inject_tap_send_buffer (int fd, vlib_buffer_t *b)
{
struct iovec iov;
ssize_t n_bytes;
@@ -51,10 +52,10 @@ tap_inject_tap_send_buffer (int fd, vlib_buffer_t * b)
}
static uword
-tap_inject_tx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f)
+tap_inject_tx (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
{
- vlib_buffer_t * b;
- u32 * pkts;
+ vlib_buffer_t *b;
+ u32 *pkts;
u32 fd;
u32 i;
@@ -66,7 +67,7 @@ tap_inject_tx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f)
fd = tap_inject_lookup_tap_fd (vnet_buffer (b)->sw_if_index[VLIB_RX]);
if (fd == ~0)
- continue;
+ continue;
/* Re-wind the buffer to the start of the Ethernet header. */
vlib_buffer_advance (b, -b->current_data);
@@ -85,20 +86,19 @@ VLIB_REGISTER_NODE (tap_inject_tx_node) = {
.type = VLIB_NODE_TYPE_INTERNAL,
};
-
static uword
-tap_inject_neighbor (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
+tap_inject_neighbor (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *f)
{
- vlib_buffer_t * b;
- u32 * pkts;
+ vlib_buffer_t *b;
+ u32 *pkts;
u32 fd;
u32 i;
u32 bi;
u32 next_index = node->cached_next_index;
u32 next = ~0;
u32 n_left;
- u32 * to_next;
+ u32 *to_next;
pkts = vlib_frame_vector_args (f);
@@ -109,10 +109,10 @@ tap_inject_neighbor (vlib_main_t * vm,
fd = tap_inject_lookup_tap_fd (vnet_buffer (b)->sw_if_index[VLIB_RX]);
if (fd == ~0)
- {
- vlib_buffer_free (vm, &bi, 1);
- continue;
- }
+ {
+ vlib_buffer_free (vm, &bi, 1);
+ continue;
+ }
/* Re-wind the buffer to the start of the Ethernet header. */
vlib_buffer_advance (b, -b->current_data);
@@ -121,32 +121,32 @@ tap_inject_neighbor (vlib_main_t * vm,
/* Send the buffer to a neighbor node too? */
{
- ethernet_header_t * eth = vlib_buffer_get_current (b);
- u16 ether_type = htons (eth->type);
-
- if (ether_type == ETHERNET_TYPE_ARP)
- {
- ethernet_arp_header_t * arp = (void *)(eth + 1);
-
- if (arp->opcode == ntohs (ETHERNET_ARP_OPCODE_reply))
- next = NEXT_NEIGHBOR_ARP;
- }
- else if (ether_type == ETHERNET_TYPE_IP6)
- {
- ip6_header_t * ip = (void *)(eth + 1);
- icmp46_header_t * icmp = (void *)(ip + 1);
-
- if (ip->protocol == IP_PROTOCOL_ICMP6 &&
- icmp->type == ICMP6_neighbor_advertisement)
- next = NEXT_NEIGHBOR_ICMP6;
- }
+ ethernet_header_t *eth = vlib_buffer_get_current (b);
+ u16 ether_type = htons (eth->type);
+
+ if (ether_type == ETHERNET_TYPE_ARP)
+ {
+ ethernet_arp_header_t *arp = (void *) (eth + 1);
+
+ if (arp->opcode == ntohs (ETHERNET_ARP_OPCODE_reply))
+ next = NEXT_NEIGHBOR_ARP;
+ }
+ else if (ether_type == ETHERNET_TYPE_IP6)
+ {
+ ip6_header_t *ip = (void *) (eth + 1);
+ icmp46_header_t *icmp = (void *) (ip + 1);
+
+ if (ip->protocol == IP_PROTOCOL_ICMP6 &&
+ icmp->type == ICMP6_neighbor_advertisement)
+ next = NEXT_NEIGHBOR_ICMP6;
+ }
}
if (next == ~0)
- {
- vlib_buffer_free (vm, &bi, 1);
- continue;
- }
+ {
+ vlib_buffer_free (vm, &bi, 1);
+ continue;
+ }
/* ARP and ICMP6 expect to start processing after the Ethernet header. */
vlib_buffer_advance (b, sizeof (ethernet_header_t));
@@ -156,39 +156,41 @@ tap_inject_neighbor (vlib_main_t * vm,
*(to_next++) = bi;
--n_left;
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left, bi, next);
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left,
+ bi, next);
vlib_put_next_frame (vm, node, next_index, n_left);
}
return f->n_vectors;
}
-VLIB_REGISTER_NODE (tap_inject_neighbor_node) = {
- .function = tap_inject_neighbor,
- .name = "tap-inject-neighbor",
- .vector_size = sizeof (u32),
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_next_nodes = 2,
- .next_nodes = {
- [NEXT_NEIGHBOR_ARP] = "arp-input",
- [NEXT_NEIGHBOR_ICMP6] = "icmp6-neighbor-solicitation",
- },
+VLIB_REGISTER_NODE(tap_inject_neighbor_node) = {
+ .function = tap_inject_neighbor,
+ .name = "tap-inject-neighbor",
+ .vector_size = sizeof(u32),
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_next_nodes = 2,
+ .next_nodes =
+ {
+ [NEXT_NEIGHBOR_ARP] = "arp-input",
+ [NEXT_NEIGHBOR_ICMP6] = "icmp6-neighbor-solicitation",
+ },
};
-
#define MTU 1500
-#define MTU_BUFFERS ((MTU + vlib_buffer_get_default_data_size(vm) - 1) / vlib_buffer_get_default_data_size(vm))
+#define MTU_BUFFERS \
+ ((MTU + vlib_buffer_get_default_data_size (vm) - 1) / \
+ vlib_buffer_get_default_data_size (vm))
#define NUM_BUFFERS_TO_ALLOC 32
static inline uword
-tap_rx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f, int fd)
+tap_rx (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f, int fd)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
u32 sw_if_index;
struct iovec iov[MTU_BUFFERS];
u32 bi[MTU_BUFFERS];
- vlib_buffer_t * b;
+ vlib_buffer_t *b;
ssize_t n_bytes;
ssize_t n_bytes_left;
u32 i, j;
@@ -202,25 +204,23 @@ tap_rx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f, int fd)
{
u32 len = vec_len (im->rx_buffers);
-
- u8 index = vlib_buffer_pool_get_default_for_numa (vm,0);
- len = vlib_buffer_alloc_from_pool(vm,
- &im->rx_buffers[len], NUM_BUFFERS_TO_ALLOC,
- index);
+ u8 index = vlib_buffer_pool_get_default_for_numa (vm, 0);
+ len = vlib_buffer_alloc_from_pool (vm, &im->rx_buffers[len],
+ NUM_BUFFERS_TO_ALLOC, index);
_vec_len (im->rx_buffers) += len;
if (vec_len (im->rx_buffers) < MTU_BUFFERS)
- {
- clib_warning ("failed to allocate buffers");
- return 0;
- }
+ {
+ clib_warning ("failed to allocate buffers");
+ return 0;
+ }
}
/* Fill buffers from the end of the list to make it easier to resize. */
for (i = 0, j = vec_len (im->rx_buffers) - 1; i < MTU_BUFFERS; ++i, --j)
{
- vlib_buffer_t * b;
+ vlib_buffer_t *b;
bi[i] = im->rx_buffers[j];
@@ -253,7 +253,8 @@ tap_rx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f, int fd)
b->current_length = n_bytes;
/* If necessary, configure any remaining buffers in the chain. */
- for (i = 1; n_bytes_left > 0; ++i, n_bytes_left -= VLIB_BUFFER_DEFAULT_DATA_SIZE)
+ for (i = 1; n_bytes_left > 0;
+ ++i, n_bytes_left -= VLIB_BUFFER_DEFAULT_DATA_SIZE)
{
b = vlib_get_buffer (vm, bi[i - 1]);
b->current_length = VLIB_BUFFER_DEFAULT_DATA_SIZE;
@@ -268,9 +269,9 @@ tap_rx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f, int fd)
/* Get the packet to the output node. */
{
- vnet_hw_interface_t * hw;
- vlib_frame_t * new_frame;
- u32 * to_next;
+ vnet_hw_interface_t *hw;
+ vlib_frame_t *new_frame;
+ u32 *to_next;
hw = vnet_get_hw_interface (vnet_get_main (), sw_if_index);
@@ -286,20 +287,20 @@ tap_rx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f, int fd)
}
static uword
-tap_inject_rx (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f)
+tap_inject_rx (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
{
- tap_inject_main_t * im = tap_inject_get_main ();
- u32 * fd;
+ tap_inject_main_t *im = tap_inject_get_main ();
+ u32 *fd;
uword count = 0;
vec_foreach (fd, im->rx_file_descriptors)
{
if (tap_rx (vm, node, f, *fd) != 1)
- {
- clib_warning ("rx failed");
- count = 0;
- break;
- }
+ {
+ clib_warning ("rx failed");
+ count = 0;
+ break;
+ }
++count;
}
@@ -320,7 +321,7 @@ VLIB_REGISTER_NODE (tap_inject_rx_node) = {
* @brief no-op lock function.
*/
static void
-tap_inject_dpo_lock (dpo_id_t * dpo)
+tap_inject_dpo_lock (dpo_id_t *dpo)
{
}
@@ -328,12 +329,12 @@ tap_inject_dpo_lock (dpo_id_t * dpo)
* @brief no-op unlock function.
*/
static void
-tap_inject_dpo_unlock (dpo_id_t * dpo)
+tap_inject_dpo_unlock (dpo_id_t *dpo)
{
}
u8 *
-format_tap_inject_dpo (u8 * s, va_list * args)
+format_tap_inject_dpo (u8 *s, va_list *args)
{
return (format (s, "tap-inject:[%d]", 0));
}
@@ -355,15 +356,16 @@ const static char *const *const tap_inject_nodes[DPO_PROTO_NUM] = {
};
static clib_error_t *
-tap_inject_init (vlib_main_t * vm)
+tap_inject_init (vlib_main_t *vm)
{
- tap_inject_main_t * im = tap_inject_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
im->rx_node_index = tap_inject_rx_node.index;
im->tx_node_index = tap_inject_tx_node.index;
im->neighbor_node_index = tap_inject_neighbor_node.index;
- tap_inject_dpo_type = dpo_register_new_type (&tap_inject_vft, tap_inject_nodes);
+ tap_inject_dpo_type =
+ dpo_register_new_type (&tap_inject_vft, tap_inject_nodes);
vec_alloc (im->rx_buffers, NUM_BUFFERS_TO_ALLOC);
vec_reset_length (im->rx_buffers);
diff --git a/extras/router-plugin/rtinject/tap_inject_tap.c b/extras/router-plugin/rtinject/tap_inject_tap.c
index a3ec9ffef..44c494347 100644
--- a/extras/router-plugin/rtinject/tap_inject_tap.c
+++ b/extras/router-plugin/rtinject/tap_inject_tap.c
@@ -17,23 +17,23 @@
#include "tap_inject.h"
#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>
#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <vnet/unix/tuntap.h>
+#include <hicn/util/sstrncpy.h>
#include <vlib/unix/unix.h>
-
static clib_error_t *
-tap_inject_tap_read (clib_file_t * f)
+tap_inject_tap_read (clib_file_t *f)
{
- vlib_main_t * vm = vlib_get_main ();
- tap_inject_main_t * im = tap_inject_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ tap_inject_main_t *im = tap_inject_get_main ();
vec_add1 (im->rx_file_descriptors, f->file_descriptor);
@@ -45,16 +45,16 @@ tap_inject_tap_read (clib_file_t * f)
#define TAP_INJECT_TAP_BASE_NAME "vpp"
clib_error_t *
-tap_inject_tap_connect (vnet_hw_interface_t * hw)
+tap_inject_tap_connect (vnet_hw_interface_t *hw)
{
- vnet_main_t * vnet_main = vnet_get_main ();
- vnet_sw_interface_t * sw = vnet_get_sw_interface (vnet_main, hw->hw_if_index);
+ vnet_main_t *vnet_main = vnet_get_main ();
+ vnet_sw_interface_t *sw = vnet_get_sw_interface (vnet_main, hw->hw_if_index);
static const int one = 1;
int fd;
struct ifreq ifr;
clib_file_t template;
u32 tap_fd;
- u8 * name;
+ u8 *name;
memset (&ifr, 0, sizeof (ifr));
memset (&template, 0, sizeof (template));
@@ -64,15 +64,16 @@ tap_inject_tap_connect (vnet_hw_interface_t * hw)
/* Create the tap. */
tap_fd = open ("/dev/net/tun", O_RDWR);
- if ((int)tap_fd < 0)
+ if ((int) tap_fd < 0)
return clib_error_return (0, "failed to open tun device");
name = format (0, TAP_INJECT_TAP_BASE_NAME "%u%c", hw->hw_instance, 0);
- strncpy (ifr.ifr_name, (char *) name, sizeof (ifr.ifr_name) - 1);
+ strcpy_s (ifr.ifr_name, IFNAMSIZ, (char *) name);
+ ifr.ifr_name[IFNAMSIZ - 1] = '\0';
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (ioctl (tap_fd, TUNSETIFF, (void *)&ifr) < 0)
+ if (ioctl (tap_fd, TUNSETIFF, (void *) &ifr) < 0)
{
close (tap_fd);
return clib_error_return (0, "failed to create tap");
@@ -142,9 +143,8 @@ tap_inject_tap_disconnect (u32 sw_if_index)
return 0;
}
-
u8 *
-format_tap_inject_tap_name (u8 * s, va_list * args)
+format_tap_inject_tap_name (u8 *s, va_list *args)
{
int fd;
struct ifreq ifr;
diff --git a/extras/sysrepo/CMakeLists.txt b/extras/sysrepo/CMakeLists.txt
index edf78105a..803b2ae3e 100644
--- a/extras/sysrepo/CMakeLists.txt
+++ b/extras/sysrepo/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# 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:
diff --git a/extras/sysrepo/cmake/Modules/Packaging.cmake b/extras/sysrepo/cmake/Modules/Packaging.cmake
index 2433539c7..d7ef2c79c 100644
--- a/extras/sysrepo/cmake/Modules/Packaging.cmake
+++ b/extras/sysrepo/cmake/Modules/Packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -31,5 +31,3 @@ set(sysrepo_RPM_DEPENDENCIES
"libyang >= 1.0"
CACHE STRING "Dependencies for deb/rpm package."
)
-
-
diff --git a/cmake/Modules/FindUncrustify.cmake b/hicn-light/.clang-format
index f8f6b00b8..2dc5c0c54 100644
--- a/cmake/Modules/FindUncrustify.cmake
+++ b/hicn-light/.clang-format
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -11,11 +11,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Find uncrustify program
-#
-find_program( UNCRUSTIFY_BIN uncrustify
- PATHS
- $ENV{UNCRUSTIFY_HOME}
- )
-
-message( "-- UNCRUSTIFY found in ${UNCRUSTIFY_BIN}" )
+BasedOnStyle: Google
+SortIncludes: false
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index 64b93d997..337e22b7f 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,115 +11,109 @@
# 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(hicn-light)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif()
+##############################################################
+# Libs and Bins names
+##############################################################
+set(LIBHICN_LIGHT hicn-light)
+set(LIBHICN_LIGHT_STATIC ${LIBHICN_LIGHT}.static)
+
+
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+
+
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
+
+##############################################################
+# C Standard
+##############################################################
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
-option(ENABLE_PUNTING "Enable punting on linux systems" ON)
-
-include( CTest )
-include( detectCacheSize )
-if(NOT WIN32)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
-else ()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
-endif ()
+##############################################################
+# Libs and Bins names
+##############################################################
+set(HICN_LIGHT hicn-light CACHE INTERNAL "" FORCE)
+set(HICN_LIGHT_CONTROL ${HICN_LIGHT}-control CACHE INTERNAL "" FORCE)
+set(HICN_LIGHT_SHELL ${HICN_LIGHT}-shell CACHE INTERNAL "" FORCE)
+set(HICN_LIGHT_DAEMON ${HICN_LIGHT}-daemon CACHE INTERNAL "" FORCE)
-if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
- message("############ Detected cross compile for $ENV{CMAKE_SYSTEM_NAME}")
- # Android uses static libs, so we need to link all the dependencies to the executable
- find_package(OpenSSL REQUIRED)
- find_package(LibEvent REQUIRED)
- set(ANDROID_LIBRARIES ${LIBEVENT_LIBRARIES} ${OPENSSL_LIBRARIES})
-endif()
-set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DLIBRTA_DISABLE_VALIDATION -DPARCLibrary_DISABLE_VALIDATION")
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(LibEvent ${LIBEVENT_DEFAULT_VERSION} REQUIRED)
+find_package(Threads REQUIRED)
-include(IosMacros)
-include(WindowsMacros)
-find_package(Libparc REQUIRED)
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ include(CommonSetup)
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
+ find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE)
-set(HICN_LIGHT hicn-light CACHE INTERNAL "" FORCE)
-set(HICN_LIGHT_CONTROL ${HICN_LIGHT}-control CACHE INTERNAL "" FORCE)
-set(HICN_LIGHT_DAEMON ${HICN_LIGHT}-daemon CACHE INTERNAL "" FORCE)
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
-if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(Libhicn REQUIRED)
+ list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE})
+ list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
else()
if (DISABLE_SHARED_LIBRARIES)
- if (WIN32)
- set(HICN_LIBRARIES ${LIBHICN_STATIC})
+ if (WIN32)
+ set(HICN_LIBRARIES ${LIBHICN_STATIC} ${LIBHICNCTRL_STATIC})
else ()
- set(HICN_LIBRARIES ${LIBHICN_STATIC} log)
+ set(HICN_LIBRARIES ${LIBHICN_STATIC} ${LIBHICNCTRL_STATIC} log)
endif ()
list(APPEND DEPENDENCIES
${LIBHICN_STATIC}
+ ${LIBHICNCTRL_STATIC}
)
else ()
- set(HICN_LIBRARIES ${LIBHICN_SHARED})
+ set(HICN_LIBRARIES
+ ${LIBHICN_SHARED}
+ ${LIBHICNCTRL_SHARED}
+ )
list(APPEND DEPENDENCIES
${LIBHICN_SHARED}
+ ${LIBHICNCTRL_SHARED}
)
endif ()
endif()
-include(Packaging)
-
-find_package(Threads REQUIRED)
-
-set(LIBHICN_LIGHT hicn-light)
-set(LIBHICN_LIGHT_STATIC ${LIBHICN_LIGHT}.static)
-
-set(LIBRARIES
- ${LIBPARC_LIBRARIES}
- ${HICN_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${WINDOWS_LIBRARIES}
- ${ANDROID_LIBRARIES}
-)
-
-set(HICN_LIGHT_LIBRARIES_LIST "${LIBPARC_LIBRARIES};${CMAKE_THREAD_LIBS_INIT};${WINDOWS_LIBRARIES}" CACHE INTERNAL "HICN_LIGHT_LIBRARIES_LIST")
-
-
-# Include dirs -- Order does matter!
-list(APPEND HICN_LIGHT_INCLUDE_DIRS
- ${HICN_INCLUDE_DIRS}
- ${LIBPARC_INCLUDE_DIRS}
- ${WINDOWS_INCLUDE_DIRS}
-)
-
-if (UNIX)
- list(APPEND LIBRARIES
- m
- )
-endif()
-
-set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
-
-if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
- set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS} -undefined dynamic_lookup")
- message(STATUS "Set \"-undefined dynamic_lookup\" for shared libraries")
-endif()
+##############################################################
+# Subdirectories
+##############################################################
add_subdirectory(src/hicn)
+
+##############################################################
# Install service file in linux systems
+##############################################################
include(ServiceScript)
install_service_script(
${CMAKE_CURRENT_SOURCE_DIR}/config/hicn-light.service
diff --git a/hicn-light/cmake/Modules/Packaging.cmake b/hicn-light/cmake/packaging.cmake
index 2b9f4a7b9..ccf567e41 100644
--- a/hicn-light/cmake/Modules/Packaging.cmake
+++ b/hicn-light/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -21,7 +21,7 @@ set(${HICN_LIGHT}_DESCRIPTION
)
set(${HICN_LIGHT}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), libparc (>= 1.0)"
+ "lib${LIBHICN} (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
@@ -31,7 +31,7 @@ set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA
)
set(${HICN_LIGHT}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, libparc >= 1.0"
+ "lib${LIBHICN} = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/hicn-light/config/hicn-light.service b/hicn-light/config/hicn-light.service
index f269b2f26..79d5ced93 100644
--- a/hicn-light/config/hicn-light.service
+++ b/hicn-light/config/hicn-light.service
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/hicn-light/config/post b/hicn-light/config/post
index 91f596050..f2f566426 100755
--- a/hicn-light/config/post
+++ b/hicn-light/config/post
@@ -2,4 +2,4 @@
if pidof systemd; then
systemctl enable hicn-light
-fi
+fi \ No newline at end of file
diff --git a/hicn-light/config/postinst b/hicn-light/config/postinst
index dced2a093..f2f566426 100755
--- a/hicn-light/config/postinst
+++ b/hicn-light/config/postinst
@@ -1,3 +1,5 @@
#!/bin/bash
-systemctl enable hicn-light \ No newline at end of file
+if pidof systemd; then
+ systemctl enable hicn-light
+fi \ No newline at end of file
diff --git a/hicn-light/config/prerm b/hicn-light/config/prerm
index 4584c7057..c1d3d55a1 100755
--- a/hicn-light/config/prerm
+++ b/hicn-light/config/prerm
@@ -1,3 +1,5 @@
#!/bin/bash
-systemctl disable hicn-light \ No newline at end of file
+if pidof systemd; then
+ systemctl disable hicn-light
+fi \ No newline at end of file
diff --git a/hicn-light/config/preun b/hicn-light/config/preun
index 4584c7057..c1d3d55a1 100755
--- a/hicn-light/config/preun
+++ b/hicn-light/config/preun
@@ -1,3 +1,5 @@
#!/bin/bash
-systemctl disable hicn-light \ No newline at end of file
+if pidof systemd; then
+ systemctl disable hicn-light
+fi \ No newline at end of file
diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt
index 639bfa179..401ae84eb 100644
--- a/hicn-light/src/hicn/CMakeLists.txt
+++ b/hicn-light/src/hicn/CMakeLists.txt
@@ -1,55 +1,129 @@
-# Define a few configuration variables that we want accessible in the software
+# Copyright (c) 2021-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(BuildMacros)
+##############################################################
+# Libraries to link
+##############################################################
+set(LIBRARIES
+ PUBLIC ${HICN_LIBRARIES}
+ PUBLIC ${LIBHICNCTRL_LIBRARIES}
+ PRIVATE ${LIBEVENT_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+)
+
+if (UNIX)
+ list(APPEND LIBRARIES
+ m
+ )
+endif()
+
+
+##############################################################
+# Configuration file
+##############################################################
configure_file(config.h.in hicn-light/config.h @ONLY)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND ENABLE_PUNTING)
+
+##############################################################
+# Compiler definitions
+##############################################################
+list(APPEND COMPILER_DEFINITIONS
+ PRIVATE -DLIBRTA_DISABLE_VALIDATION
+)
+
+list(APPEND COMPILER_DEFINITIONS
+# "-DWITH_GRO"
+# "-DWITH_GSO"
+# "-DWITH_ZEROCOPY"
+ PRIVATE "-DWITH_POLICY_STATS"
+ PRIVATE "-DWITH_CLI"
+# "-DNDEBUG=1" # disable assertions
+)
+
+if (UNIX AND NOT APPLE)
list(APPEND COMPILER_DEFINITIONS
- "-DPUNTING"
+ "-D_GNU_SOURCE" # batching support through struct mmsghdr
)
endif()
-list(APPEND COMPILER_DEFINITIONS
- "-DWITH_MAPME"
- "-DWITH_POLICY"
+
+##############################################################
+# Compiler options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
)
+##############################################################
+# Sources
+##############################################################
if (NOT DISABLE_EXECUTABLES)
- add_subdirectory(command_line)
+ add_subdirectory(cli)
endif()
+add_subdirectory(base)
add_subdirectory(config)
add_subdirectory(content_store)
add_subdirectory(core)
add_subdirectory(io)
-add_subdirectory(messenger)
add_subdirectory(platforms)
-add_subdirectory(processor)
add_subdirectory(socket)
add_subdirectory(strategies)
add_subdirectory(utils)
+list(APPEND TO_INSTALL_HEADER_FILES
+ ${HEADER_FILES}
+)
+
list(APPEND HEADER_FILES
${CMAKE_CURRENT_BINARY_DIR}/hicn-light/config.h
)
-list(INSERT HICN_LIGHT_INCLUDE_DIRS 0
- ${CMAKE_CURRENT_SOURCE_DIR}/..
- ${CMAKE_CURRENT_BINARY_DIR}/..
+
+##############################################################
+# Includes
+##############################################################
+list(APPEND HICN_LIGHT_INCLUDE_DIRS
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/..>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ ${LIBEVENT_INCLUDE_DIRS}
+ ${WINDOWS_INCLUDE_DIRS}
)
list(APPEND TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_BINARY_DIR}/hicn-light/config.h
)
+
+##############################################################
+# Build type
+##############################################################
+set(LIB_BUILD_TYPE STATIC)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android")
- set(LIB_BUILD_TYPE "NO_DEV")
-else()
- set(LIB_BUILD_TYPE "")
+ list(APPEND LIB_BUILD_TYPE
+ "NO_DEV"
+ )
endif()
+
+##############################################################
+# Build forwarder library
+##############################################################
build_library(${LIBHICN_LIGHT}
- STATIC ${LIB_BUILD_TYPE}
+ ${LIB_BUILD_TYPE}
SOURCES ${SOURCE_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
LINK_LIBRARIES ${LIBRARIES}
@@ -57,6 +131,14 @@ build_library(${LIBHICN_LIGHT}
COMPONENT ${HICN_LIGHT}
INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS}
HEADER_ROOT_DIR hicn
- DEFINITIONS ${COMPILER_DEFINITIONS}
+ DEFINITIONS PUBLIC ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
+
+##############################################################
+# Build tests
+##############################################################
+if (BUILD_TESTS)
+ add_subdirectory(test)
+endif()
diff --git a/hicn-light/src/hicn/messenger/CMakeLists.txt b/hicn-light/src/hicn/base/CMakeLists.txt
index 69a6c32d1..1180ed05b 100644
--- a/hicn-light/src/hicn/messenger/CMakeLists.txt
+++ b/hicn-light/src/hicn/base/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,19 +12,28 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/missiveDeque.h
- ${CMAKE_CURRENT_SOURCE_DIR}/missive.h
- ${CMAKE_CURRENT_SOURCE_DIR}/missiveType.h
- ${CMAKE_CURRENT_SOURCE_DIR}/messenger.h
- ${CMAKE_CURRENT_SOURCE_DIR}/messengerRecipient.h
+ ${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}/messenger.c
- ${CMAKE_CURRENT_SOURCE_DIR}/messengerRecipient.c
- ${CMAKE_CURRENT_SOURCE_DIR}/missive.c
- ${CMAKE_CURRENT_SOURCE_DIR}/missiveDeque.c
+ ${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)
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+
+set(TO_INSTALL_HEADER_FILES
+ ${TO_INSTALL_HEADER_FILES}
+ ${HEADER_FILES}
+ PARENT_SCOPE
+)
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
new file mode 100644
index 000000000..ed3fac2fd
--- /dev/null
+++ b/hicn-light/src/hicn/base/bitmap.h
@@ -0,0 +1,188 @@
+/*
+ * 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, 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] |= (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
new file mode 100644
index 000000000..9f7e3beec
--- /dev/null
+++ b/hicn-light/src/hicn/base/common.h
@@ -0,0 +1,62 @@
+/*
+ * 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
new file mode 100644
index 000000000..3c54feb29
--- /dev/null
+++ b/hicn-light/src/hicn/base/hash.h
@@ -0,0 +1,349 @@
+/*
+ * 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
new file mode 100644
index 000000000..4c62b0260
--- /dev/null
+++ b/hicn-light/src/hicn/base/khash.h
@@ -0,0 +1,748 @@
+/* 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/loop.c b/hicn-light/src/hicn/base/loop.c
new file mode 100644
index 000000000..68970ed3a
--- /dev/null
+++ b/hicn-light/src/hicn/base/loop.c
@@ -0,0 +1,201 @@
+/*
+ * 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 loop.c
+ * @brief Implementation of event loop based on libevent
+ */
+
+#include <assert.h>
+#include <event2/event.h>
+#include <event2/event_struct.h>
+#include <event2/thread.h>
+#include <fcntl.h> // fcntl
+#ifdef WITH_THREAD
+#include <pthread.h>
+#endif /* WITH_THREAD */
+#include <hicn/util/log.h>
+#include <stdlib.h>
+#include <unistd.h> // fcntl
+
+#include "loop.h"
+
+loop_t *MAIN_LOOP = NULL;
+
+/**
+ * \brief Holds all callback parameters
+ */
+typedef struct {
+ void *owner;
+ fd_callback_t callback;
+ void *data;
+} cb_wrapper_args_t;
+
+typedef enum {
+ EVTYPE_TIMER,
+ EVTYPE_FD,
+} event_type_t;
+
+struct loop_s {
+ /* Libevent-based implementation */
+ struct event_base *event_base;
+};
+
+struct event_s {
+ /* Reference to loop */
+ loop_t *loop;
+
+ /* Event type*/
+ event_type_t event_type;
+
+ /* Raw event */
+ struct event raw_event;
+
+ /* Callback on event */
+ cb_wrapper_args_t callback;
+};
+
+loop_t *loop_create() {
+ loop_t *loop = malloc(sizeof(loop_t));
+
+ if (!loop) {
+ ERROR("[loop_create] Failed to allocate memory");
+ goto ERR_MALLOC;
+ }
+
+#ifdef WITH_THREAD
+ evthread_use_pthreads();
+#endif /* WITH_THREAD */
+
+ loop->event_base = event_base_new();
+ if (!loop->event_base) goto ERR_EVENT;
+
+ event_set_log_callback(NULL);
+
+ return loop;
+
+ERR_EVENT:
+ERR_MALLOC:
+ return NULL;
+}
+
+void loop_free(loop_t *loop) {
+ event_base_free(loop->event_base);
+ free(loop);
+}
+
+int _loop_dispatch(loop_t *loop, int flags) {
+ event_base_loop(loop->event_base, flags);
+ return 0;
+}
+
+int loop_dispatch(loop_t *loop) {
+ return _loop_dispatch(loop, EVLOOP_NO_EXIT_ON_EMPTY);
+}
+
+int loop_break(loop_t *loop) { return event_base_loopbreak(loop->event_base); }
+
+int loop_undispatch(loop_t *loop) { return 0; }
+
+void cb_wrapper(evutil_socket_t fd, short what, void *arg) {
+ cb_wrapper_args_t *cb_wrapper_args = arg;
+ cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data);
+}
+
+static inline void _event_create(event_t **event, loop_t *loop,
+ event_type_t type, void *callback_owner,
+ fd_callback_t callback, void *callback_data) {
+ *event = malloc(sizeof(event_t));
+ (*event)->callback = (cb_wrapper_args_t){
+ .owner = callback_owner,
+ .callback = callback,
+ .data = callback_data,
+ };
+ (*event)->event_type = type;
+ (*event)->loop = loop;
+}
+
+int loop_fd_event_create(event_t **event, loop_t *loop, int fd,
+ void *callback_owner, fd_callback_t callback,
+ void *callback_data) {
+ _event_create(event, loop, EVTYPE_FD, callback_owner, callback,
+ callback_data);
+
+ evutil_make_socket_nonblocking(fd);
+ event_assign(&(*event)->raw_event, loop->event_base, fd, EV_READ | EV_PERSIST,
+ cb_wrapper, &(*event)->callback);
+
+ return 0;
+}
+
+int loop_fd_event_register(event_t *event) {
+ assert(event->event_type == EVTYPE_FD);
+
+ if (event_add(&event->raw_event, NULL) < 0) {
+ ERROR("[loop_fd_event_register] event_add");
+ goto ERR_EVENT_ADD;
+ }
+
+ return 0;
+
+ERR_EVENT_ADD:
+ return -1;
+}
+
+int loop_event_unregister(event_t *event) {
+ event_del(&event->raw_event);
+ return 0;
+}
+
+int loop_timer_create(event_t **timer, loop_t *loop, void *callback_owner,
+ fd_callback_t callback, void *callback_data) {
+ _event_create(timer, loop, EVTYPE_TIMER, callback_owner, callback,
+ callback_data);
+
+ evtimer_assign(&(*timer)->raw_event, loop->event_base, cb_wrapper,
+ &(*timer)->callback);
+
+ return 0;
+}
+
+static inline void _ms_to_timeval(unsigned delay_ms, struct timeval *tv) {
+ tv->tv_sec = delay_ms / 1000;
+ tv->tv_usec = (delay_ms % 1000) * 1000;
+}
+
+int loop_timer_register(event_t *timer, unsigned delay_ms) {
+ assert(timer->event_type == EVTYPE_TIMER);
+
+ struct timeval tv;
+ _ms_to_timeval(delay_ms, &tv);
+
+ if (tv.tv_sec == 0 && tv.tv_usec == 0) {
+ event_active(&timer->raw_event, EV_TIMEOUT, 0);
+ } else {
+ event_add(&timer->raw_event, &tv);
+ }
+
+ return 0;
+}
+
+int loop_timer_is_enabled(event_t *timer) {
+ return evtimer_pending(&timer->raw_event, NULL) != 0;
+}
+
+int loop_event_free(event_t *event) {
+ int ret = loop_event_unregister(event);
+ free(event);
+ return ret;
+}
diff --git a/hicn-light/src/hicn/base/loop.h b/hicn-light/src/hicn/base/loop.h
new file mode 100644
index 000000000..f81af333b
--- /dev/null
+++ b/hicn-light/src/hicn/base/loop.h
@@ -0,0 +1,138 @@
+/*
+ * 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 loop.h
+ * \brief Face manager main loop
+ */
+
+#ifndef UTIL_LOOP_H
+#define UTIL_LOOP_H
+
+/* fd & timer callbacks */
+
+typedef int (*fd_callback_t)(void *owner, int fd, void *data);
+
+typedef struct {
+ int fd;
+ void *owner;
+ fd_callback_t callback;
+ void *data;
+} fd_callback_data_t;
+
+/* loop */
+
+typedef struct loop_s loop_t;
+typedef struct event_s event_t;
+
+extern loop_t *MAIN_LOOP;
+
+/**
+ * \brief Creates a main loop
+ * \return Pointer to the newly created loop, or NULL in case of error
+ */
+loop_t *loop_create();
+
+/**
+ * \brief Releases a loop instance and frees all associated memory
+ * \param [in] loop - Pointer to the loop instance to free
+ */
+void loop_free(loop_t *loop);
+
+/**
+ * \brief Runs the loop instance to process events (helper).
+ * \param [in] loop - Pointer to the loop instance
+ * \param [in] flags - Loop mode: EVLOOP_ONCE, EVLOOP_NONBLOCK or
+ * EVLOOP_NO_EXIT_ON_EMPTY \return 0 if successful, -1 otherwise
+ */
+int _loop_dispatch(loop_t *loop, int flags);
+
+/**
+ * \brief Runs the loop instance to process events.
+ * \param [in] loop - Pointer to the loop instance
+ * \return 0 if successful, -1 otherwise
+ */
+int loop_dispatch(loop_t *loop);
+
+/**
+ * \brief Terminates the dispatching of events
+ * \param [in] loop - Pointer to the loop instance
+ */
+int loop_break(loop_t *loop);
+
+int loop_undispatch(loop_t *loop);
+
+/** Create new event associated with given fd.
+ * \param [out] event - Struct representing new fd event
+ * \param [in] loop - Loop running events
+ * \param [in] fd - fd to register
+ * \param [in] callback_owner - Pointer to the owner of the callack (first
+ * parameter of callback function)
+ * \param [in] callback - Callback function
+ * \param [in] callback_data - User data to pass alongside callback invocation
+ * \return 0 in case of success, -1 otherwise
+ */
+int loop_fd_event_create(event_t **event, loop_t *loop, int fd,
+ void *callback_owner, fd_callback_t callback,
+ void *callback_data);
+
+/**
+ * Register event in corresponding event loop.
+ * \param [in] event - Struct representing fd event
+ * \return 0 in case of success, -1 otherwise
+ */
+int loop_fd_event_register(event_t *event);
+
+/**
+ * Unregister event from corresponding event loop.
+ * \param [in] event - Struct representing fd event
+ * \return 0 in case of success, -1 otherwise
+ */
+int loop_event_unregister(event_t *event);
+
+/**
+ * Free event object.
+ * \param [in] event - Struct representing the event
+ * \return 0 in case of success, -1 otherwise
+ */
+int loop_event_free(event_t *event);
+
+/** Create new timer event.
+ * \param [out] event - Struct representing new timer event
+ * \param [in] loop - Loop running events
+ * \param [in] callback_owner - Pointer to the owner of the callack (first
+ * parameter of callback function)
+ * \param [in] callback - Callback function
+ * \param [in] callback_data - User data to pass alongside callback invocation
+ * \return 0 in case of success, -1 otherwise
+ */
+int loop_timer_create(event_t **timer, loop_t *loop, void *callback_owner,
+ fd_callback_t callback, void *callback_data);
+
+/**
+ * Register event in corresponding event loop.
+ * \param [in] timer - Struct representing timer event
+ * \return 0 in case of success, -1 otherwise
+ */
+int loop_timer_register(event_t *timer, unsigned delay_ms);
+
+/**
+ * Check if timer is enabled.
+ * \param [in] timer - Struct representing timer event
+ * \return 1 if enabled, 0 otherwise
+ */
+int loop_timer_is_enabled(event_t *timer);
+
+#endif /* UTIL_LOOP_H */
diff --git a/hicn-light/src/hicn/base/pool.c b/hicn-light/src/hicn/base/pool.c
new file mode 100644
index 000000000..ba2a14c5f
--- /dev/null
+++ b/hicn-light/src/hicn/base/pool.c
@@ -0,0 +1,158 @@
+/*
+ * 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 */
+ uint_fast32_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/pool.h b/hicn-light/src/hicn/base/pool.h
new file mode 100644
index 000000000..b6573195c
--- /dev/null
+++ b/hicn-light/src/hicn/base/pool.h
@@ -0,0 +1,254 @@
+/*
+ * 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.h
+ * \brief Fixed-size pool allocator.
+ *
+ * This memory pool allocates a single block of memory that is used to
+ * efficiently allocate/deallocate fixed-size blocks for high churn data
+ * structures.
+ *
+ * Internally this data structure leverages a vector for managing elements (and
+ * it thus resizeable if needed), as well as a list of free indices (in the
+ * form of another vector) and a bitmap marking free indices also (for fast
+ * iteration).
+ *
+ * The internal API manipulates a pointer to the vector that that is can be
+ * seamlessly resized, and a more convenient user interface is provided through
+ * macros.
+ *
+ * The vector of free indices is managed as a stack where elements indices are
+ * retrieved from and put back to the end of the vector. In the bitmap,
+ * available elements are set to 1, and unset to 0 when in use.
+ *
+ * The pool is not currently resized down when releasing elements.
+ *
+ * It is freely inspired (and simplified) from the VPP infra infrastructure
+ * library.
+ */
+
+#ifndef UTIL_POOL_H
+#define UTIL_POOL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "bitmap.h"
+#include "vector.h"
+
+/* Pool header */
+
+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 */
+} 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))
+
+/******************************************************************************/
+/* Helpers */
+
+/** Local variable naming macro. */
+#define _pool_var(v) _pool_##v
+
+/**
+ * @brief Allocate and initialize a pool data structure (helper).
+ *
+ * @param[in,out] pool_ptr Pointer to the pool data structure.
+ * @param[in] elt_size Size of elements in vector.
+ * @param[in] max_size Maximum size.
+ *
+ * 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);
+
+/**
+ * @brief Free a pool data structure (helper).
+ *
+ * @param[in] pool_ptr Pointer to the pool data structure.
+ */
+void _pool_free(void **pool_ptr);
+
+/**
+ * @brief Resize a pool data structure (helper).
+ *
+ * @param pool_ptr Pointer to the pool data structure.
+ *
+ * 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);
+
+/**
+ * @brief Get a free element from the pool data structure (helper).
+ *
+ * @param[in] pool Pointer to the pool data structure to use.
+ * @param[in,out] elt Pointer to an empty element that will be used to return
+ * the allocated one from the pool.
+ *
+ * NOTES:
+ * - The memory chunk is cleared upon attribution
+ */
+off_t _pool_get(void **pool, void **elt, size_t elt_size);
+
+/**
+ * @brief Put an element back into the pool data structure (helper).
+ *
+ * @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);
+
+/**
+ * @brief Validate a pool element by index (helper).
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in] id The index of the element to validate.
+ *
+ * @return bool A flag indicating whether the index is valid or not.
+ */
+bool _pool_validate_id(void **pool_ptr, off_t id);
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a pool data structure.
+ *
+ * @param[in,out] pool Pointer to the pool data structure.
+ * @param[in] elt_size Size of elements in pool.
+ * @param[in] max_size Maximum size.
+ *
+ * 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);
+
+/**
+ * @brief Free a pool data structure.
+ *
+ * @param[in] pool The pool data structure to free.
+ */
+#define pool_free(pool) _pool_free((void **)&pool);
+
+/**
+ * @brief Get a free element from the pool data structure.
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in,out] elt An empty element that will be used to return the
+ * allocated one from the pool.
+ *
+ * NOTES:
+ * - The memory chunk is cleared upon attribution
+ */
+#define pool_get(pool, elt) \
+ _pool_get((void **)&pool, (void **)&elt, sizeof(*elt))
+
+/**
+ * @brief Put an element back into the pool data structure.
+ *
+ * @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))
+
+/**
+ * @brief Validate a pool element by index.
+ *
+ * @param[in] pool The pool data structure to use.
+ * @param[in] id The index of the element to validate.
+ *
+ * @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_get_free_indices_size(pool) \
+ vector_len(pool_hdr(pool)->free_indices)
+
+/**
+ * @brief Returns the current length of the pool.
+ *
+ * @param[in] pool The pool data structure for which to return the length.
+ *
+ * @return size_t The current length of the pool.
+ *
+ * NOTE:
+ * - 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))
+
+/**
+ * @brief Enumerate elements from a pool.
+ *
+ * @param[in] pool The pool data structure to enumerate.
+ * @param[in, out] i An integer that will be used for enumeration.
+ * @param[in, out] eltp A pointer to the element type that will be used for
+ * enumeration.
+ * @param[in] BODY Block to execute during enumeration.
+ *
+ * Enumeration will iteratively execute BODY with (i, eltp) corresponding
+ * respectively to the index and element found in the pool.
+ *
+ * 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)
+
+/**
+ * @brief Iterate over elements in a pool.
+ *
+ * @param[in] pool The pool data structure to iterate over.
+ * @param[in,out] eltp A pointer to the element type that will be used for
+ * iteration.
+ * @param[in] BODY Block to execute during iteration.
+ *
+ * Iteration will execute BODY with eltp corresponding successively to all
+ * 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_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
+#endif /* WITH_TESTS */
+
+#endif /* UTIL_POOL_H */
diff --git a/hicn-light/src/hicn/base/ring.c b/hicn-light/src/hicn/base/ring.c
new file mode 100644
index 000000000..29727886a
--- /dev/null
+++ b/hicn-light/src/hicn/base/ring.c
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file ring.c
+ * \brief Implementation of ring buffer.
+ */
+
+#include <stdlib.h>
+
+#include "ring.h"
+
+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);
+
+ 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;
+}
+
+void _ring_free(void** ring_ptr) {
+ free(ring_hdr(*ring_ptr));
+ *ring_ptr = NULL;
+}
diff --git a/hicn-light/src/hicn/base/ring.h b/hicn-light/src/hicn/base/ring.h
new file mode 100644
index 000000000..492a8fdac
--- /dev/null
+++ b/hicn-light/src/hicn/base/ring.h
@@ -0,0 +1,201 @@
+/*
+ * 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/base/vector.c b/hicn-light/src/hicn/base/vector.c
new file mode 100644
index 000000000..36d808932
--- /dev/null
+++ b/hicn-light/src/hicn/base/vector.c
@@ -0,0 +1,85 @@
+/*
+ * 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 vector.c
+ * \brief Implementation of resizeable static array
+ */
+
+#include <assert.h>
+#include <stddef.h> // size_t
+#include <stdlib.h> // calloc
+#include <stdio.h>
+
+#include "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);
+
+ if (init_size == 0) init_size = DEFAULT_VECTOR_SIZE;
+
+ *vector_ptr = NULL;
+ _vector_resize(vector_ptr, elt_size, init_size);
+
+ vector_hdr_t* vh = vector_hdr(*vector_ptr);
+ vh->cur_size = 0;
+ vh->max_size = max_size;
+}
+
+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;
+
+ size_t old_size;
+
+ 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);
+
+ /* Don't grow the vector back */
+ 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;
+
+ 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);
+
+ /* Reassign vector pointer */
+ *vector_ptr = (uint8_t*)vh + VECTOR_HDRLEN;
+
+ return 0;
+}
diff --git a/hicn-light/src/hicn/base/vector.h b/hicn-light/src/hicn/base/vector.h
new file mode 100644
index 000000000..0b7a74aeb
--- /dev/null
+++ b/hicn-light/src/hicn/base/vector.h
@@ -0,0 +1,327 @@
+/*
+ * 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 vector.h
+ * \brief Resizeable static array
+ *
+ * A vector is a resizeable area of contiguous memory that contains elements of
+ * fixed size. It is mostly useful to serve as the basis for more advanced data
+ * structures such as memory pools.
+ *
+ * The internal API manipulates a pointer to the vector so that it can be
+ * seamlessly resized, and a more convenient user interface is provided through
+ * macros.
+ *
+ * A vector starts at index 0, and is typed according to the elements it
+ * contains. For that matter, the data structure header precedes the returned
+ * pointer which corresponds to the storage area.
+ *
+ * A vector is by default used as a stack where an end marker is maintained and
+ * new elements are pushed right after this end marker (an indication of
+ * the size of the vector) after ensuring the vector is sufficiently large.
+ *
+ * A user should not store any pointer to vector elements as this might change
+ * during reallocations, but should use indices instead.
+ *
+ * NOTE: a maximum size is currently not implemented.
+ *
+ * It is freely inspired (and simplified) from the VPP infra infrastructure
+ * library.
+ */
+
+#ifndef UTIL_VECTOR_H
+#define UTIL_VECTOR_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "common.h"
+
+/******************************************************************************/
+/* Vector header */
+
+typedef struct {
+ size_t cur_size; /** Vector current size (corresponding to the highest used
+ 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)
+
+/* This header actually prepends the actual content of the vector */
+#define vector_hdr(vector) ((vector_hdr_t *)((uint8_t *)vector - VECTOR_HDRLEN))
+
+/******************************************************************************/
+/* Helpers */
+
+/** Local variable naming macro. */
+#define _vector_var(v) _vector_##v
+
+/**
+ * @brief Allocate and initialize a vector data structure (helper function).
+ *
+ * @param[in,out] vector_ptr Vector to allocate and initialize.
+ * @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).
+ */
+void _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);
+
+/**
+ * @brief Resize a vector data structure.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] pos The position at which the vector should be able to hold an
+ * element.
+ *
+ * @return int Flag indicating whether the vector has been correctly resized.
+ *
+ * NOTE:
+ * - The resize operation does not specify the final size of the vector but
+ * instead ensure that it is large enough to hold an element at the specified
+ * 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);
+
+/**
+ * @brief Ensures a vector is sufficiently large to hold an element at the
+ * given position.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] pos The position to validate.
+ *
+ * @return int Flag indicating whether the vector is available.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a vector element
+ * to eventually make room for it (the vector will eventually be resized).
+ * - 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);
+ return 0;
+}
+
+/**
+ * @brief Push an element at the end of a vector.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] elt The element to insert.
+ *
+ * NOTE:
+ * - This function ensures there is sufficient room for inserting the element,
+ * 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;
+
+ /* 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->cur_size++;
+ return 0;
+}
+
+/**
+ * @brief Remove all the occurrencies of an element from the vector.
+ * The order of the elements is NOT maintained.
+ *
+ * @param[in, out] vector The vector data structure to resize
+ * @param[in] elt_size The size of a vector element
+ * @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) {
+ 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++;
+ }
+ }
+ return num_removed;
+}
+
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a vector data structure.
+ *
+ * @param[in,out] vector Vector to allocate and initialize.
+ * @param[in] init_size Initial vector size.
+ * @param[in] max_size Maximum vector size (nonzero).
+ *
+ * NOTE:
+ * - 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)
+
+/**
+ * @brief Free a vector data structure.
+ *
+ * @param[in] vector The vector data structure to free.
+ */
+#define vector_free(vector) _vector_free((void **)&vector)
+
+/**
+ * @brief Resize a vector data structure.
+ *
+ * @param[in] vector The vector data structure to resize.
+ * @param[in] pos The position at which the vector should be able to hold an
+ * element.
+ *
+ * @return int Flag indicating whether the vector has been correctly resized.
+ *
+ * NOTE:
+ * - The resize operation does not specify the final size of the vector but
+ * instead ensure that it is large enough to hold an element at the specified
+ * position. This allows the caller not to care about doing successive calls to
+ * this API while the vector is growing in size.
+ * - If the new size is smaller than the current size, the content of the
+ * 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)
+
+/**
+ * @brief Ensures a vector is sufficiently large to hold an element at the
+ * given position.
+ *
+ * @param[in] vector The vector for which to validate the position.
+ * @param[in] pos The position to validate.
+ *
+ * NOTE:
+ * - 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);
+
+/**
+ * @brief Push an element at the end of a vector.
+ *
+ * @param[in] vector The vector in which to insert the element.
+ * @param[in] elt The element to insert.
+ *
+ * NOTE:
+ * - This function ensures there is sufficient room for inserting the element,
+ * 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)); \
+ })
+
+/**
+ * @brief Remove all the occurrencies of an element from the vector.
+ * The order of the elements is NOT maintained.
+ *
+ * @param[in, out] vector The vector data structure to resize
+ * @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)); \
+ })
+
+/**
+ * @brief Returns the length of a vector.
+ *
+ * @param[in] vector The vector from which to get the size.
+ *
+ * @see vector_ensure_pos
+ *
+ * NOTE:
+ * - The size of the vector corresponds to the highest accessed index (for
+ * example as specified in the resize operation) and not the currently
+ * allocated size which will typically be bigger to amortize allocations.
+ * - 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
+
+/**
+ * @brief Returns the allocated size of a vector.
+ */
+#define vector_get_alloc_size(vector) vector_hdr(vector)->alloc_size
+
+/**
+ * @brief Iterate over elements in a vector.
+ *
+ * @param[in] pool The vector 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 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); \
+ })
+
+/**
+ * @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; } \
+ } \
+ })
+
+#endif /* UTIL_VECTOR_H */
diff --git a/hicn-light/src/hicn/cli/CMakeLists.txt b/hicn-light/src/hicn/cli/CMakeLists.txt
new file mode 100644
index 000000000..39581e6ad
--- /dev/null
+++ b/hicn-light/src/hicn/cli/CMakeLists.txt
@@ -0,0 +1,93 @@
+# Copyright (c) 2021-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.
+
+
+if (NOT DISABLE_EXECUTABLES)
+##############################################################
+# Force libhicn library to whole archive mode
+##############################################################
+ if (APPLE)
+ set(
+ LIBHICN_LIGHT_WHOLE_ARCHIVE
+ "-Wl,-force_load"
+ "${LIBHICN_LIGHT_STATIC}"
+ )
+ else()
+ set(
+ LIBHICN_LIGHT_WHOLE_ARCHIVE
+ "-Wl,--whole-archive"
+ "${LIBHICN_LIGHT_STATIC}"
+ "-Wl,--no-whole-archive"
+ )
+ endif()
+
+##############################################################
+# Sources
+##############################################################
+ list(APPEND CONTROLLER_SRC
+ color.c
+ hicnc.c
+ )
+
+
+##############################################################
+# Build hicn-light-control
+##############################################################
+ build_executable(${HICN_LIGHT_CONTROL}
+ SOURCES ${CONTROLLER_SRC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_WHOLE_ARCHIVE}
+ DEPENDS ${LIBHICN_LIGHT_STATIC}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ )
+
+
+##############################################################
+# Build hicn-light-shell
+##############################################################
+ list(APPEND SHELL_SRC
+ color.c
+ hicns.c
+ )
+
+ build_executable(${HICN_LIGHT_SHELL}
+ SOURCES ${SHELL_SRC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_WHOLE_ARCHIVE}
+ DEPENDS ${LIBHICN_LIGHT_STATIC}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ )
+
+
+##############################################################
+# Build hicn-light-shell
+##############################################################
+ list(APPEND DAEMON_SRC
+ color.c
+ hicnd.c
+ )
+
+ # hicn-light-daemon does not compile under Android due to bindSocket
+ if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+ build_executable(${HICN_LIGHT_DAEMON}
+ SOURCES ${DAEMON_SRC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_WHOLE_ARCHIVE}
+ DEPENDS ${LIBHICN_LIGHT_STATIC}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ )
+ endif ()
+endif ()
diff --git a/hicn-light/src/hicn/cli/color.c b/hicn-light/src/hicn/cli/color.c
new file mode 100644
index 000000000..aed22e302
--- /dev/null
+++ b/hicn-light/src/hicn/cli/color.c
@@ -0,0 +1,71 @@
+/*
+ * 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 <stdio.h>
+#include "color.h"
+
+#ifndef _WIN32
+
+void vprintfc(color_t color, const char* fmt, va_list ap) {
+ char* color_s;
+ switch (color) {
+#define _(x, y, z) \
+ case COLOR_##x: \
+ color_s = y; \
+ break;
+ foreach_color
+#undef _
+
+ case COLOR_UNDEFINED : case COLOR_N : default : // XXX
+ color_s = "";
+ break;
+ }
+ printf("%s", color_s);
+ vprintf(fmt, ap);
+}
+#else
+void vprintfc(color_t color, const char* fmt, va_list ap) {
+ int color_id;
+ switch (color) {
+#define _(x, y, z) \
+ case COLOR_##x: \
+ color_id = z; \
+ break;
+ foreach_color
+#undef _
+
+ case COLOR_UNDEFINED : case COLOR_N : color_id = 0;
+ break;
+ }
+ HANDLE hConsole = NULL;
+ WORD currentConsoleAttr;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (GetConsoleScreenBufferInfo(hConsole, &csbi))
+ currentConsoleAttr = csbi.wAttributes;
+ if (color_id != 0) SetConsoleTextAttribute(hConsole, color_id);
+ fprintf("%s", color);
+ vfprintf(fmt, ap);
+ SetConsoleTextAttribute(hConsole, currentConsoleAttr);
+}
+#endif
+
+void printfc(color_t color, const char* fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintfc(color, fmt, ap);
+ va_end(ap);
+}
diff --git a/hicn-light/src/hicn/core/connectionState.h b/hicn-light/src/hicn/cli/color.h
index 9daa15c9c..a9b71c047 100644
--- a/hicn-light/src/hicn/core/connectionState.h
+++ b/hicn-light/src/hicn/cli/color.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,25 +13,30 @@
* limitations under the License.
*/
-/**
- * @file connection_state.h
- * @brief Represents the state of a connection
- *
- */
+#ifndef HICNLIGHT_COLOR
+#define HICNLIGHT_COLOR
-#ifndef connection_state_h
-#define connection_state_h
+#include <stdarg.h>
-#define foreach_connection_state \
- _(UNDEFINED) \
- _(DOWN) \
- _(UP) \
- _(N)
+/*
+ * Format : color_name, escape sequence, windows id
+ */
+#define foreach_color \
+ _(RED, "\033[0;31m", 4) \
+ _(WHITE, "\033[0m", 7)
typedef enum {
-#define _(x) CONNECTION_STATE_ ## x,
-foreach_connection_state
+ COLOR_UNDEFINED,
+#define _(x, y, z) COLOR_##x,
+ foreach_color
#undef _
-} connection_state_t;
+ COLOR_N,
+} color_t;
+
+#define IS_VALID_COLOR(color) ((color != COLOR_UNDEFINED) && (color != COLOR_N))
+
+void vprintfc(color_t color, const char* fmt, va_list ap);
+
+void printfc(color_t color, const char* fmt, ...);
-#endif /* connection_state_h */
+#endif /* HICNLIGHT_COLOR */
diff --git a/hicn-light/src/hicn/cli/hicnc.c b/hicn-light/src/hicn/cli/hicnc.c
new file mode 100644
index 000000000..d14093b6b
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicnc.c
@@ -0,0 +1,390 @@
+/*
+ * 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 <limits.h> // LONG_MAX, LONG_MIN
+#include <signal.h>
+#include <hicn/ctrl.h>
+
+#ifndef _WIN32
+#include <getopt.h>
+#endif
+
+#include "color.h"
+#include "../config/parse.h"
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.h>
+
+#define PORT 9695
+
+static struct option longFormOptions[] = {{"help", no_argument, 0, 'h'},
+ {"server", required_argument, 0, 'S'},
+ {"port", required_argument, 0, 'P'},
+ {0, 0, 0, 0}};
+
+static void usage(char *prog) {
+ printf("%s: portable hICN forwarder\n", prog);
+ printf("\n");
+ printf("Usage: %s COMMAND [PARAMETERS]\n", prog);
+ printf("\n");
+ printf(" %s -h This help screen.\n", prog);
+ printf(" %s help Obtain a list of available commands.\n", prog);
+ printf("\n");
+}
+
+static bool stop = false;
+void signal_handler(int sig) {
+ fprintf(stderr, "Received ^C... quitting !\n");
+ stop = true;
+}
+
+int main(int argc, char *const *argv) {
+ log_conf.log_level = LOG_INFO;
+
+ // Handle termination signal
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = signal_handler;
+ sigaction(SIGINT, &sa, NULL);
+
+ /* Parse commandline */
+ char *server_ip = NULL;
+ uint16_t server_port = 0;
+
+ for (;;) {
+ // getopt_long stores the option index here.
+ int optind = 0;
+
+ int c = getopt_long(argc, argv, "hS:P:", longFormOptions, &optind);
+ if (c == -1) break;
+
+ switch (c) {
+ case 'S':
+ server_ip = optarg;
+ break;
+
+ case 'P': {
+ char *endptr;
+ long val = strtol(optarg, &endptr, 10);
+
+ errno = 0; /* To distinguish success/failure after call */
+
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
+ (errno != 0 && val == 0)) {
+ perror("strtol");
+ exit(EXIT_FAILURE);
+ }
+
+ if (endptr == optarg) {
+ fprintf(stderr, "No digits were found.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (*endptr != '\0') {
+ fprintf(stderr, "Spurious characters after number: %s.\n", endptr);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((val < 1) || (val > 65535)) {
+ fprintf(stderr, "Invalid port number: %ld.\n", val);
+ exit(EXIT_FAILURE);
+ }
+
+ server_port = val;
+ break;
+ }
+
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+
+ default:
+ fprintf(stderr, "Invalid argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Parse */
+ char *param = argv[optind];
+ for (; optind < argc - 1; optind++) {
+ char *arg = argv[optind];
+ arg[strlen(arg)] = ' ';
+ }
+
+ if (!param) {
+ usage(argv[0]);
+ goto ERR_PARAM;
+ }
+
+ if (strncmp(param, "help", 4) == 0) {
+ if (help(param) < 0) {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ hc_command_t command = {};
+ if (parse(param, &command) < 0) {
+ fprintf(stderr, "Error parsing command : '%s'\n", param);
+ goto ERR_PARSE;
+ }
+
+ hc_sock_t *s;
+ if (server_ip) {
+ if (server_port == 0) server_port = PORT;
+#define BUFSIZE 255
+ char url[BUFSIZE];
+ snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port);
+ s = hc_sock_create_forwarder_url(HICNLIGHT_NG, url);
+ } else {
+ s = hc_sock_create_forwarder(HICNLIGHT_NG);
+ }
+ if (!s) {
+ fprintf(stderr, "Could not create socket.\n");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(s) < 0) {
+ fprintf(stderr, "Could not establish connection to forwarder.\n");
+ goto ERR_CONNECT;
+ }
+
+ if (!IS_VALID_OBJECT_TYPE(command.object.type) ||
+ !IS_VALID_ACTION(command.action)) {
+ fprintf(stderr, "Unsupported command");
+ goto ERR_PARAM;
+ }
+
+ int rc = UNSUPPORTED_CMD_ERROR;
+ hc_data_t *data = NULL;
+ char buf_listener[MAXSZ_HC_LISTENER];
+ char buf_connection[MAXSZ_HC_CONNECTION];
+ char buf_route[MAXSZ_HC_ROUTE];
+ char buf[MAX_LEN];
+ switch (command.object.type) {
+ case OBJECT_ROUTE:
+ switch (command.action) {
+ case ACTION_CREATE:
+ rc = hc_route_create(s, &command.object.route);
+ break;
+
+ case ACTION_DELETE:
+ rc = hc_route_delete(s, &command.object.route);
+ break;
+
+ case ACTION_LIST:
+ rc = hc_route_list(s, &data);
+ if (rc < 0) break;
+
+ INFO("Routes:");
+ foreach_route(r, data) {
+ if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >=
+ MAXSZ_HC_ROUTE)
+ ERROR("Display error");
+ INFO("%s", buf_route);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_LISTENER:
+ switch (command.action) {
+ case ACTION_CREATE:
+ rc = hc_listener_create(s, &command.object.listener);
+ break;
+
+ case ACTION_DELETE:
+ rc = hc_listener_delete(s, &command.object.listener);
+ break;
+
+ case ACTION_LIST:
+ rc = hc_listener_list(s, &data);
+ if (rc < 0) break;
+
+ INFO("Listeners:");
+ foreach_listener(l, data) {
+ if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER + 17, l) >=
+ MAXSZ_HC_LISTENER)
+ ERROR("Display error");
+ INFO("[%d] %s", l->id, buf_listener);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch (command.action) {
+ case ACTION_CREATE:
+ rc = hc_connection_create(s, &command.object.connection);
+ break;
+
+ case ACTION_DELETE:
+ rc = hc_connection_delete(s, &command.object.connection);
+ break;
+
+ case ACTION_LIST:
+ rc = hc_connection_list(s, &data);
+ if (rc < 0) break;
+
+ INFO("Connections:");
+ foreach_connection(c, data) {
+ if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION,
+ c) >= MAXSZ_HC_CONNECTION)
+ ERROR("Display error");
+ INFO("[%d] %s", c->id, buf_connection);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_CACHE:
+ switch (command.action) {
+ case ACTION_SERVE:
+ rc = hc_cache_set_serve(s, &command.object.cache);
+ break;
+
+ case ACTION_STORE:
+ rc = hc_cache_set_store(s, &command.object.cache);
+ break;
+
+ case ACTION_CLEAR:
+ rc = hc_cache_clear(s, &command.object.cache);
+ break;
+
+ case ACTION_LIST:
+ rc = hc_cache_list(s, &data);
+ if (rc < 0) break;
+
+ hc_cache_snprintf(buf, MAX_LEN, (hc_cache_info_t *)data->buffer);
+ printf("%s\n", buf);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch (command.action) {
+ case ACTION_SET:
+ rc = hc_strategy_set(s, &command.object.strategy);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_MAPME:
+ switch (command.action) {
+ case ACTION_UPDATE:
+ rc = hc_mapme_send_update(s, &command.object.mapme);
+ break;
+ case ACTION_SET:
+ if (command.object.mapme.target == MAPME_TARGET_ENABLE) {
+ rc = hc_mapme_set(s, &command.object.mapme);
+ } else if (command.object.mapme.target == MAPME_TARGET_DISCOVERY) {
+ rc = hc_mapme_set_discovery(s, &command.object.mapme);
+ } else if (command.object.mapme.target == MAPME_TARGET_TIMESCALE) {
+ rc = hc_mapme_set_timescale(s, &command.object.mapme);
+ } else if (command.object.mapme.target == MAPME_TARGET_RETX) {
+ rc = hc_mapme_set_retx(s, &command.object.mapme);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_LOCAL_PREFIX:
+ switch (command.action) {
+ case ACTION_CREATE:
+ rc = hc_strategy_add_local_prefix(s, &command.object.strategy);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case OBJECT_SUBSCRIPTION:
+ // Disable socket recv timeout
+ hc_sock_set_recv_timeout_ms(s, 0);
+
+ rc = hc_subscription_create(s, &command.object.subscription);
+ if (rc < 0) break;
+ INFO("Subscription sent");
+
+ while (!stop) {
+ int rc = hc_sock_callback(s, &data);
+ if (rc < 0 && !stop) ERROR("Notification error");
+
+ if (!stop) {
+ event_type_t event_type = rc;
+ INFO("Notification recevied %s [%d]", event_str(event_type),
+ event_type);
+
+ if (event_type == EVENT_INTERFACE_UPDATE) {
+ hc_event_interface_update_t *event =
+ (hc_event_interface_update_t *)(data->buffer);
+ INFO("Interface update event received: %u", event->interface_type);
+ }
+ }
+ }
+
+ INFO("Unsubscribing...");
+ rc = hc_subscription_delete(s, &command.object.subscription);
+ break;
+
+ default:
+ break;
+ }
+ hc_data_free(data);
+
+ if (rc < -1) {
+ if (rc == INPUT_ERROR) ERROR("Wrong input parameters");
+ if (rc == UNSUPPORTED_CMD_ERROR) ERROR("Unsupported command");
+ goto ERR_CMD;
+ }
+ if (rc < 0) ERROR("Error executing command");
+
+ // Remove the connection created to send the command
+ command.object.connection.id = 0;
+ rc = strcpy_s(command.object.connection.name,
+ sizeof(command.object.connection.name), "SELF");
+ if (rc != EOK || hc_connection_delete(s, &command.object.connection) < 0)
+ fprintf(stderr, "Error removing local connection to forwarder\n");
+
+ exit(EXIT_SUCCESS);
+
+ERR_CMD:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCK:
+ERR_PARSE:
+ERR_PARAM:
+ exit(EXIT_FAILURE);
+}
diff --git a/hicn-light/src/hicn/cli/hicnd.c b/hicn-light/src/hicn/cli/hicnd.c
new file mode 100644
index 000000000..e73517e4c
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicnd.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <hicn/util/log.h>
+
+#include "logo.h"
+#include "../base/loop.h"
+#include "../core/forwarder.h"
+#include "../config/configuration.h" // XXX needed ?
+#include "../config/configuration_file.h"
+
+static void usage(const char *prog) {
+ printf(
+ "Usage: %s [--port port]"
+#ifndef _WIN32
+ " [--daemon]"
+#endif
+ " [--capacity objectStoreSize] [--log level]"
+ "[--log-file filename] [--config file]\n",
+ prog);
+ printf("\n");
+ printf(
+ "hicn-light run as a daemon is the program to launch the forwarder, "
+ "either as a console program\n");
+ printf(
+ "or a background daemon (detatched from console). Once running, use the "
+ "program controller to\n");
+ printf("configure hicn-light.\n");
+ printf("\n");
+ printf(
+ "The configuration file contains configuration lines as per "
+ "controller\n");
+ printf(
+ "If logging level or content store capacity is set in the configuraiton "
+ "file, it overrides the command_line\n");
+ printf(
+ "When a configuration file is specified, no default listeners on 'port' "
+ "are setup. Only 'add listener' lines\n");
+ printf("in the configuration file matter.\n");
+ printf("\n");
+ printf(
+ "If no configuration file is specified, daemon will listen on TCP and "
+ "UDP ports specified by\n");
+ printf(
+ "the --port flag (or default port). It will listen on both IPv4 and "
+ "IPv6 if available.\n");
+ printf("\n");
+ printf("Options:\n");
+ printf("%-30s = tcp port for in-bound connections\n", "--port <tcp_port>");
+#ifndef _WIN32
+ printf("%-30s = start as daemon process\n", "--daemon");
+#endif
+ printf(
+ "%-30s = maximum number of content objects to cache. To disable the "
+ "cache objectStoreSize must be 0.\n",
+ "--capacity <objectStoreSize>");
+ printf("%-30s Default vaule for objectStoreSize is 100000\n", "");
+ printf(
+ "%-30s = sets the log level. Available levels: trace, debug, info, warn, "
+ "error, fatal\n",
+ "--log <level>");
+ printf("%-30s = file to write log messages to (required in daemon mode)\n",
+ "--log-file <output_logfile>");
+ printf("%-30s = configuration filename\n", "--config <config_path>");
+ printf("\n");
+}
+
+#ifndef _WIN32
+static int daemonize(int logfile_fd) {
+ /* Check whether we already are a daemon */
+ if (getppid() == 1) return 0;
+
+ int rc = fork();
+ if (rc < 0) {
+ ERROR("Fork error");
+ goto ERR_FORK;
+ } else if (rc > 0) {
+ /* Parent exits successfully */
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Child daemon detaches */
+ DEBUG("child continuing, pid = %u\n", getpid());
+
+ /* get a new process group independent from old parent */
+ setsid();
+
+ /* close all descriptors (apart from the logfile) */
+#ifdef __ANDROID__
+ for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i) close(i);
+#else
+ for (int i = getdtablesize(); i >= 0; --i) {
+ if (i != logfile_fd) close(i);
+ }
+#endif
+
+ /*
+ * Reset errno because it might be seg to EBADF from the close calls above
+ */
+ errno = 0;
+ /* Redirect stdin and stdout and stderr to /dev/null */
+ const char *devnull = "/dev/null";
+ int nullfile = open(devnull, O_RDWR);
+ if (nullfile < 0) {
+ ERROR("Error opening file '%s': (%d) %s", devnull, errno, strerror(errno));
+ goto ERR_DEVNULL;
+ }
+
+ /* Redirect stdout and stderr to the logfile */
+ rc = dup2(logfile_fd, STDOUT_FILENO);
+ if (rc != STDOUT_FILENO) {
+ ERROR("Error duping fd 1 got %d file: (%d) %s", rc, errno, strerror(errno));
+ goto ERR_DUP1;
+ }
+ rc = dup2(logfile_fd, STDERR_FILENO);
+ if (rc != STDERR_FILENO) {
+ ERROR("Error duping fd 2 got %d file: (%d) %s", rc, errno, strerror(errno));
+ goto ERR_DUP2;
+ }
+
+ /* Forwarder will capture signals */
+ return 0;
+
+ERR_DUP2:
+ERR_DUP1:
+ERR_DEVNULL:
+ERR_FORK:
+ return -1;
+}
+#endif
+
+static void signal_cb(int sig) {
+ switch (sig) {
+ case SIGTERM:
+ case SIGINT:
+ INFO("caught an interrupt signal, exiting cleanly");
+ break;
+#ifndef _WIN32
+ case SIGUSR1:
+ // dump stats
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (loop_break(MAIN_LOOP) < 0) {
+ ERROR("Failed to terminate main loop");
+ _exit(1);
+ }
+}
+
+static void signal_setup() {
+#ifndef _WIN32
+ signal(SIGUSR1, signal_cb);
+
+ /* ignore child */
+ signal(SIGCHLD, SIG_IGN);
+
+ /* ignore tty signals */
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+#endif
+ signal(SIGINT, signal_cb);
+ signal(SIGTERM, signal_cb);
+}
+
+configuration_t *parse_commandline(int argc, const char *argv[]) {
+ if (argc == 2 && strcasecmp(argv[1], "-h") == 0) {
+ usage(argv[0]);
+ exit(EXIT_SUCCESS); // XXX redundant
+ }
+
+ configuration_t *configuration = configuration_create();
+
+ // XXX use getoptlong ????
+ for (int i = 0; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--config") == 0) {
+ const char *fn_config = argv[i + 1];
+ configuration_set_fn_config(configuration, fn_config);
+ i++;
+ } else if (strcmp(argv[i], "--port") == 0) {
+ uint16_t port = atoi(argv[i + 1]);
+ configuration_set_port(configuration, port);
+ i++;
+#ifndef _WIN32
+ } else if (strcmp(argv[i], "--daemon") == 0) {
+ configuration_set_daemon(configuration, true);
+#endif
+ } else if (strcmp(argv[i], "--capacity") == 0 ||
+ strcmp(argv[i], "-c") == 0) {
+ int capacity = atoi(argv[i + 1]);
+ configuration_set_cs_size(configuration, capacity);
+ i++;
+ } else if (strcmp(argv[i], "--log") == 0) {
+ int loglevel = loglevel_from_str(argv[i + 1]);
+ configuration_set_loglevel(configuration, loglevel);
+ i++;
+ } else if (strcmp(argv[i], "--log-file") == 0) {
+ if (configuration_get_logfile(configuration)) {
+ fprintf(stderr, "Cannot specify --log-file more than once\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ const char *logfile = argv[i + 1];
+ configuration_set_logfile(configuration, logfile);
+ i++;
+ } else {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ return configuration;
+}
+
+int main(int argc, const char *argv[]) {
+ signal_setup();
+ logo();
+
+ configuration_t *configuration = parse_commandline(argc, argv);
+ const char *logfile = configuration_get_logfile(configuration);
+ bool daemon = configuration_get_daemon(configuration);
+
+ // set restrictive umask, in case we create any files
+ umask(027);
+
+#ifndef _WIN32
+ if (daemon && (logfile == NULL)) {
+ fprintf(stderr, "Must specify a logfile when running in daemon mode\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* In daemon mode, parent will exit and child will continue */
+ if (daemon && daemonize(configuration_get_logfile_fd(configuration)) < 0) {
+ ERROR("Could not daemonize process");
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ /*
+ * The loop should be created before the forwarder instance as it is needed
+ * for timers
+ */
+ MAIN_LOOP = loop_create();
+
+ forwarder_t *forwarder = forwarder_create(configuration);
+ if (!forwarder) {
+ ERROR(
+ "Forwarder initialization failed. Are you running it with sudo "
+ "privileges?");
+ return -1;
+ }
+
+ forwarder_setup_local_listeners(forwarder,
+ configuration_get_port(configuration));
+
+ /* If specified, process the configuration file */
+ const char *fn_config = configuration_get_fn_config(configuration);
+ if (fn_config) configuration_file_process(forwarder, fn_config);
+ INFO("%s running port %d configuration-port %d", argv[0],
+ configuration_get_port(configuration),
+ configuration_get_configuration_port(configuration));
+
+ /* Main loop */
+ if (loop_dispatch(MAIN_LOOP) < 0) {
+ ERROR("Failed to run main loop");
+ return EXIT_FAILURE;
+ }
+
+ INFO("loop stopped");
+ forwarder_free(forwarder);
+ loop_free(MAIN_LOOP);
+ MAIN_LOOP = NULL;
+
+#ifdef _WIN32
+ WSACleanup(); // XXX why is this needed here ?
+#endif
+
+ configuration_flush_log();
+ return 0;
+}
diff --git a/hicn-light/src/hicn/cli/hicns.c b/hicn-light/src/hicn/cli/hicns.c
new file mode 100644
index 000000000..2f7a360f8
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicns.c
@@ -0,0 +1,206 @@
+/*
+ * 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 <limits.h> // LONG_MAX, LONG_MIN
+#include <hicn/ctrl.h>
+
+#ifndef _WIN32
+#include <getopt.h>
+#endif
+
+#include "logo.h"
+#include "../config/parse.h"
+#include <hicn/util/sstrncpy.h>
+
+#define PORT 9695
+
+static struct option longFormOptions[] = {{"help", no_argument, 0, 'h'},
+ {"server", required_argument, 0, 'S'},
+ {"port", required_argument, 0, 'P'},
+ {0, 0, 0, 0}};
+
+static void usage(char *prog) {
+ printf("%s: interactive shell for hicn-light\n", prog);
+ printf("\n");
+ printf("Usage: %s", prog);
+ printf("\n");
+ printf(" %s -h This help screen.\n", prog);
+ printf("\n");
+}
+
+void prompt(void) {
+ fputs("hicn> ", stdout);
+ fflush(stdout);
+}
+
+int shell(hc_sock_t *s) {
+ char *line = NULL;
+ size_t len = 0;
+ hc_data_t *data = NULL;
+ ssize_t nread;
+
+ hc_data_t *connections;
+
+ prompt();
+ while ((nread = getline(&line, &len, stdin)) != -1) {
+ hc_command_t command = {0};
+
+ char *pos;
+ if ((pos = strchr(line, '\n')) != NULL) {
+ *pos = '\0';
+ } else {
+ fprintf(stderr, "Error while reading command.\n");
+ goto CONTINUE;
+ }
+
+ if (strlen(line) == 0) goto CONTINUE;
+
+ if (strncmp(line, "exit", 4) == 0) break;
+ if (strncmp(line, "quit", 4) == 0) break;
+
+ if (parse(line, &command) < 0) {
+ fprintf(stderr, "Unknown command '%s'\n", line);
+ goto CONTINUE;
+ }
+
+ /* XXX connection list */
+ if (hc_connection_list(s, &connections) < 0) {
+ fprintf(stderr, "Error running command.\n");
+ goto CONTINUE;
+ }
+ // data = command.object.data;
+
+ char buf[MAXSZ_HC_CONNECTION]; // XXX
+ foreach_connection(c, data) {
+ /* XXX connection print */
+ int rc = hc_connection_snprintf(buf, MAXSZ_HC_CONNECTION, c);
+ if (rc < 0) {
+ strcpy_s(buf, sizeof(buf), "(Error)");
+ } else if (rc >= MAXSZ_HC_CONNECTION) {
+ buf[MAXSZ_HC_CONNECTION - 1] = '\0';
+ buf[MAXSZ_HC_CONNECTION - 2] = '.';
+ buf[MAXSZ_HC_CONNECTION - 3] = '.';
+ buf[MAXSZ_HC_CONNECTION - 4] = '.';
+ }
+ printf("%s\n", buf);
+ }
+
+ hc_data_free(data);
+ CONTINUE:
+ prompt();
+ }
+
+ return 0;
+}
+
+int main(int argc, char *const *argv) {
+ logo();
+ printf("Type 'help' for a list of available commands\n");
+ printf("\n");
+ printf("\n");
+
+ /* Parse commandline */
+ char *server_ip = NULL;
+ uint16_t server_port = 0;
+
+ for (;;) {
+ // getopt_long stores the option index here.
+ int optind = 0;
+
+ int c = getopt_long(argc, argv, "hS:P:", longFormOptions, &optind);
+ if (c == -1) break;
+
+ switch (c) {
+ case 'S':
+ server_ip = optarg;
+ break;
+
+ case 'P': {
+ char *endptr;
+ long val = strtol(optarg, &endptr, 10);
+
+ errno = 0; /* To distinguish success/failure after call */
+
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
+ (errno != 0 && val == 0)) {
+ perror("strtol");
+ exit(EXIT_FAILURE);
+ }
+
+ if (endptr == optarg) {
+ fprintf(stderr, "No digits were found.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (*endptr != '\0') {
+ fprintf(stderr, "Spurious characters after number: %s.\n", endptr);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((val < 1) || (val > 65535)) {
+ fprintf(stderr, "Invalid port number: %ld.\n", val);
+ exit(EXIT_FAILURE);
+ }
+
+ server_port = (uint16_t)val;
+ break;
+ }
+
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+
+ default:
+ fprintf(stderr, "Invalid argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (optind != argc) {
+ fprintf(stderr, "Invalid parameters.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ hc_sock_t *s;
+ if (server_ip) {
+ if (server_port == 0) server_port = PORT;
+#define BUFSIZE 255
+ char url[BUFSIZE];
+ snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port);
+ s = hc_sock_create_forwarder_url(HICNLIGHT_NG, url);
+ } else {
+ s = hc_sock_create_forwarder(HICNLIGHT_NG);
+ }
+ if (!s) {
+ fprintf(stderr, "Could not create socket.\n");
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(s) < 0) {
+ fprintf(stderr, "Could not establish connection to forwarder.\n");
+ goto ERR_CONNECT;
+ }
+
+ int rc = shell(s);
+
+ exit((rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS);
+
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCK:
+ exit(EXIT_FAILURE);
+}
diff --git a/hicn-light/src/hicn/cli/logo.h b/hicn-light/src/hicn/cli/logo.h
new file mode 100644
index 000000000..a69097f91
--- /dev/null
+++ b/hicn-light/src/hicn/cli/logo.h
@@ -0,0 +1,37 @@
+/*
+ * 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 HICNLIGHT_LOGO
+#define HICNLIGHT_LOGO
+
+#include "color.h"
+
+static void logo(void) {
+ printfc(COLOR_RED, " ____ ___ _ ");
+ printfc(COLOR_WHITE, " __ _ __ _ __ __\n");
+ printfc(COLOR_RED, " / __// _ \\ (_)___ ");
+ printfc(COLOR_WHITE, " / / (_)____ ___ ____/ /(_)___ _ / / / /_\n");
+ printfc(COLOR_RED, " / _/ / // /_ / // _ \\ ");
+ printfc(COLOR_WHITE, " / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n");
+ printfc(COLOR_RED, "/_/ /____/(_)/_/ \\___/ ");
+ printfc(COLOR_WHITE, "/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n");
+ printfc(
+ COLOR_WHITE,
+ " /___/ "
+ "\n");
+ printf("\n");
+}
+
+#endif /* HICNLIGHT_LOGO */
diff --git a/hicn-light/src/hicn/command_line/CMakeLists.txt b/hicn-light/src/hicn/command_line/CMakeLists.txt
deleted file mode 100644
index 16c23dc5c..000000000
--- a/hicn-light/src/hicn/command_line/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-add_subdirectory(controller)
-add_subdirectory(daemon)
diff --git a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt b/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
deleted file mode 100644
index 4cbd49220..000000000
--- a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-list(APPEND CONTROLLER_SRC
- hicnLightControl_main.c
-)
-
-if (WIN32)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" )
-endif()
-
-if (NOT DISABLE_EXECUTABLES)
- if (${CMAKE_SYSTEM_NAME} MATCHES Android)
- set(LINK_FLAGS "-Wl,--unresolved-symbols=ignore-in-object-files")
- endif()
-
- build_executable(${HICN_LIGHT_CONTROL}
- SOURCES ${CONTROLLER_SRC}
- LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC}
- DEPENDS ${LIBHICN_LIGHT_STATIC}
- COMPONENT ${HICN_LIGHT}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- LINK_FLAGS ${LINK_FLAGS}
- )
-endif ()
diff --git a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
deleted file mode 100644
index e6a97c4e2..000000000
--- a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <hicn/utils/utils.h>
-
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <getopt.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#endif
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <string.h>
-
-#include <parc/security/parc_IdentityFile.h>
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_SafeMemory.h>
-
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-
-#include <errno.h>
-#include <hicn/config/controlRoot.h>
-#include <hicn/config/controlState.h>
-
-#include <hicn/utils/commands.h>
-
-
-
-size_t commandOutputLen = 0; // preserve the number of structs composing
- // payload in case on not interactive call.
-
-// REMINDER: when a new_command is added, the following array has to be updated
-// with the sizeof(new_command). It allows to allocate the buffer for receiving
-// the payload of the DAEMON RESPONSE after the header has beed read. Each
-// command identifier (typedef enum command_id) corresponds to a position in the
-// following array.
-static int payloadLengthController[LAST_COMMAND_VALUE] = {
- sizeof(add_listener_command),
- sizeof(add_connection_command),
- sizeof(list_connections_command), // needed when get response from FWD
- sizeof(add_route_command),
- sizeof(list_routes_command), // needed when get response from FWD
- sizeof(remove_connection_command),
- sizeof(remove_listener_command),
- sizeof(remove_route_command),
- sizeof(cache_store_command),
- sizeof(cache_serve_command),
- 0, // cache clear
- sizeof(set_strategy_command),
- sizeof(set_wldr_command),
- sizeof(add_punting_command),
- sizeof(list_listeners_command), // needed when get response from FWD
- sizeof(mapme_activator_command),
- sizeof(mapme_activator_command),
- sizeof(mapme_timing_command),
- sizeof(mapme_timing_command),
- sizeof(mapme_send_update_command),
- sizeof(connection_set_admin_state_command),
-#ifdef WITH_POLICY
- sizeof(add_policy_command),
- sizeof(list_policies_command),
- sizeof(remove_policy_command),
- sizeof(update_connection_command),
- sizeof(connection_set_priority_command),
- sizeof(connection_set_tags_command),
-#endif
-};
-
-typedef struct controller_main_state {
- ControlState *controlState;
-} ControlMainState;
-
-static void _printRed(const char *output) {
-#ifndef _WIN32
- printf("\033[0;31m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 4);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _printWhite(const char *output) {
-#ifndef _WIN32
- printf("\033[0m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 7);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _displayForwarderLogo(void) {
- _printRed(" ____ ___ _ ");
- _printWhite(" __ _ __ _ __ __\n");
- _printRed(" / __// _ \\ (_)___ ");
- _printWhite(" / / (_)____ ___ ____/ /(_)___ _ / / / /_\n");
- _printRed(" / _/ / // /_ / // _ \\ ");
- _printWhite(" / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n");
- _printRed("/_/ /____/(_)/_/ \\___/ ");
- _printWhite("/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n");
- _printWhite(
- " /___/ "
- "\n");
- printf("\n");
-}
-
-static void _displayUsage(char *programName) {
- printf("Usage: %s -h\n", programName);
- printf(
- "hicn-light is the 1.0 source, which runs on each end system and as a "
- "software source\n");
- printf(
- "on intermediate systems. controller is the program to configure the "
- "source, daemon.\n");
- printf("\n");
- printf("Options:\n");
- printf("-h = This help screen\n");
- printf(
- "commands = configuration line to send to hicn-light (use 'help' "
- "for list)\n");
- printf("\n");
-}
-
-static int _parseArgs(int argc, char *argv[], char **server_ip,
- uint16_t *server_port, PARCList *commandList){
- static struct option longFormOptions[] = {
- {"help", no_argument, 0, 'h'},
- {"server", required_argument, 0, 'S'},
- {"port", required_argument, 0, 'P'},
- {0, 0, 0, 0}};
-
- int c;
-
- while (1) {
- // getopt_long stores the option index here.
- int optionIndex = 0;
-
- c = getopt_long(argc, argv, "hS:P:", longFormOptions, &optionIndex);
-
- // Detect the end of the options.
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'S':
- {
- *server_ip = optarg;
- struct sockaddr_in sa;
- int result = inet_pton(AF_INET, *server_ip, &(sa.sin_addr));
- //inet_pton() returns 1 on success
- if(result != 1){
- return 0;
- }
- break;
- }
- case 'P':
- {
- char * port_str = optarg;
- if(utils_IsNumber(port_str)){
- *server_port = (uint16_t) strtol(port_str, NULL, 10);
- } else {
- return 0;
- }
- break;
- }
- case 'h':
- default:
- return 0;
- }
- }
-
- if (optind < argc) {
- while (optind < argc) {
- parcList_Add(commandList, argv[optind]);
- optind++;
- }
- }
-
- return 1;
-}
-
-struct iovec *_writeAndReadMessage(ControlState *state, struct iovec *msg) {
- parcAssertNotNull(msg, "Parameter msg must be non-null");
- int sockfd = controlState_GetSockfd(state);
-
- // check if request has a payload
- if (((header_control_message *)msg[0].iov_base)->length >
- 0) { // command with payload
- // write header + payload (compatibility issue: two write needed instead of
- // the writev)
-#ifndef _WIN32
- if (write(sockfd, msg[0].iov_base, (unsigned int)msg[0].iov_len) < 0 ||
- write(sockfd, msg[1].iov_base, (unsigned int)msg[1].iov_len) < 0) {
-#else
- if (send(sockfd, msg[0].iov_base, (int)msg[0].iov_len, 0) == SOCKET_ERROR ||
- send(sockfd, msg[1].iov_base, (int)msg[1].iov_len, 0) == SOCKET_ERROR) {
-#endif
- printf("\nError while sending the Message: cannot write on socket \n");
- exit(EXIT_FAILURE);
- }
- parcMemory_Deallocate(&msg[1].iov_base);
- } else { // command without payload, e.g. 'list'
- // write header only
-#ifndef _WIN32
- if (write(sockfd, msg[0].iov_base, msg[0].iov_len) < 0) {
-#else
- int result = send(sockfd, msg[0].iov_base, (int)msg[0].iov_len, 0);
- if (result == SOCKET_ERROR) {
-#endif
- printf("\nError while sending the Message: cannot write on socket \n");
- exit(EXIT_FAILURE);
- }
- }
- parcMemory_Deallocate(&msg[0].iov_base);
-
- // ======= RECEIVE =======
-
- header_control_message *headerResponse =
- (header_control_message *)parcMemory_AllocateAndClear(
- sizeof(header_control_message));
- if (recv(sockfd, (char *)headerResponse, sizeof(header_control_message), 0) <
- 0) {
- printf("\nError in Receiving the Message \n");
- exit(EXIT_FAILURE);
- }
-
- if (headerResponse->messageType < RESPONSE_LIGHT ||
- headerResponse->messageType >= LAST_MSG_TYPE_VALUE) {
- char *checkFinMsg = parcMemory_Reallocate(headerResponse, 32);
-#ifndef _WIN32
- if (recv(sockfd, checkFinMsg, sizeof(checkFinMsg),
- MSG_PEEK | MSG_DONTWAIT) == 0) {
-#else
- if (recv(sockfd, checkFinMsg, sizeof(checkFinMsg), MSG_PEEK) == 0) {
-#endif
- // if recv returns zero, that means the connection has been closed:
- close(sockfd);
- printf("\nConnection terminated by the Daemon. Exiting... \n");
- exit(EXIT_SUCCESS);
- } else {
- printf("\nError: Unrecognized message type received \n");
- exit(EXIT_FAILURE);
- }
- }
-
- void *payloadResponse = NULL;
-
- if ((commandOutputLen = headerResponse->length) > 0) {
- payloadResponse = parcMemory_AllocateAndClear(
- payloadLengthController[headerResponse->commandID] *
- headerResponse->length);
-
- if (recv(sockfd, payloadResponse,
- payloadLengthController[headerResponse->commandID] *
- headerResponse->length,
- 0) < 0) {
- printf("\nError in Receiving the Message \n");
- exit(EXIT_FAILURE);
- }
- }
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = headerResponse;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len = payloadLengthController[headerResponse->commandID] *
- headerResponse->length;
-
- return response;
-}
-
-int main(int argc, char *argv[]) {
- _displayForwarderLogo();
-
-#ifdef _WIN32
- WSADATA wsaData;
- WSAStartup(MAKEWORD(2, 2), &wsaData);
-#endif
-
- if (argc == 2 && strcmp("-h", argv[1]) == 0) {
- _displayUsage(argv[0]);
- exit(EXIT_SUCCESS);
- }
-
- PARCList *commands =
- parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
-
- char *server_ip = SRV_CTRL_IP;
- uint16_t server_port = SRV_CTRL_PORT;
- if (!_parseArgs(argc, argv, &server_ip,
- &server_port, commands)) {
- _displayUsage(argv[0]);
- parcList_Release(&commands);
- exit(EXIT_FAILURE);
- }
-
- ControlMainState mainState;
- mainState.controlState =
- controlState_Create(&mainState, _writeAndReadMessage, true,
- server_ip, server_port);
- if (mainState.controlState == NULL) {
- exit(EXIT_FAILURE);
- }
-
- controlState_RegisterCommand(mainState.controlState,
- controlRoot_HelpCreate(mainState.controlState));
- controlState_RegisterCommand(mainState.controlState,
- controlRoot_Create(mainState.controlState));
-
- if (parcList_Size(commands) > 0) {
- controlState_SetInteractiveFlag(mainState.controlState, false);
- char output[8192];
- controlState_DispatchCommand(mainState.controlState, commands, output, sizeof(output));
- printf("%s", output);
- char **commandOutputMain =
- controlState_GetCommandOutput(mainState.controlState);
- if (commandOutputMain != NULL && commandOutputLen > 0) {
-#if 0
- for (size_t j = 0; j < commandOutputLen; j++) {
- printf("Output %zu: %s \n", j, commandOutputMain[j]);
- }
-#endif
- controlState_ReleaseCommandOutput(mainState.controlState,
- commandOutputMain, commandOutputLen);
- }
- // release
-
- } else {
- controlState_Interactive(mainState.controlState);
- }
-
- parcList_Release(&commands);
-
- controlState_Destroy(&mainState.controlState);
-#ifdef _WIN32
- WSACleanup();
-#endif
- return EXIT_SUCCESS;
-}
diff --git a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
deleted file mode 100644
index ab7039f5e..000000000
--- a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include <hicn/hicn-light/config.h>
-#include <parc/algol/parc_FileOutputStream.h>
-#include <parc/logging/parc_LogLevel.h>
-#include <parc/logging/parc_LogReporterFile.h>
-#include <parc/logging/parc_LogReporterTextStdout.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-
-static void _printRed(const char *output) {
-#ifndef _WIN32
- printf("\033[0;31m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 4);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _printWhite(const char *output) {
-#ifndef _WIN32
- printf("\033[0m%s", output);
-#else
- HANDLE hConsole = NULL;
- WORD currentConsoleAttr;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- if (GetConsoleScreenBufferInfo(hConsole, &csbi))
- currentConsoleAttr = csbi.wAttributes;
- SetConsoleTextAttribute(hConsole, 7);
- printf("%s", output);
- SetConsoleTextAttribute(hConsole, currentConsoleAttr);
-#endif
-}
-
-static void _displayForwarderLogo(void) {
- _printRed(" ____ ___ _ ");
- _printWhite(" __ _ __ _ __ __\n");
- _printRed(" / __// _ \\ (_)___ ");
- _printWhite(" / / (_)____ ___ ____/ /(_)___ _ / / / /_\n");
- _printRed(" / _/ / // /_ / // _ \\ ");
- _printWhite(" / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n");
- _printRed("/_/ /____/(_)/_/ \\___/ ");
- _printWhite("/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n");
- _printWhite(
- " /___/ "
- "\n");
- printf("\n");
-}
-
-static void _usage(int exitCode) {
-#ifndef _WIN32
- printf(
- "Usage: hicn-light-daemon [--port port] [--capacity objectStoreSize] "
- "[--log facility=level] [--log-file filename] [--config file]\n");
-#else
- printf(
- "Usage: hicn-light-daemon.exe [--port port] [--daemon] [--capacity objectStoreSize] "
- "[--log facility=level] [--log-file filename] [--config file]\n");
-#endif
- printf("\n");
- printf(
- "hicn-light run as a daemon is the program to launch the forwarder, "
- "either as a console program\n");
- printf(
- "or a background daemon (detatched from console). Once running, use the "
- "program controller to\n");
- printf("configure hicn-light.\n");
- printf("\n");
- printf(
- "The configuration file contains configuration lines as per "
- "controller\n");
- printf(
- "If logging level or content store capacity is set in the configuraiton "
- "file, it overrides the command_line\n");
- printf(
- "When a configuration file is specified, no default listeners on 'port' "
- "are setup. Only 'add listener' lines\n");
- printf("in the configuration file matter.\n");
- printf("\n");
- printf(
- "If no configuration file is specified, daemon will listen on TCP and "
- "UDP ports specified by\n");
- printf(
- "the --port flag (or default port). It will listen on both IPv4 and "
- "IPv6 if available.\n");
- printf("\n");
- printf("Options:\n");
- printf("--port = tcp port for in-bound connections\n");
-#ifndef _WIN32
- printf("--daemon = start as daemon process\n");
-#endif
- printf("--objectStoreSize = maximum number of content objects to cache\n");
- printf(
- "--log = sets a facility to a given log level. You can have "
- "multiple of these.\n");
- printf(
- " facilities: all, config, core, io, message, "
- "processor\n");
- printf(
- " levels: debug, info, notice, warning, error, "
- "critical, alert, off\n");
- printf(" example: daemon --log io=debug --log core=off\n");
- printf(
- "--log-file = file to write log messages to (required in daemon "
- "mode)\n");
- printf("--config = configuration filename\n");
- printf("\n");
- exit(exitCode);
-}
-
-static void _setLogLevelToLevel(int logLevelArray[LoggerFacility_END],
- LoggerFacility facility,
- const char *levelString) {
- PARCLogLevel level = parcLogLevel_FromString(levelString);
-
- if (level < PARCLogLevel_All) {
- // we have a good facility and level
- logLevelArray[facility] = level;
- } else {
- printf("Invalid log level string %s\n", levelString);
- _usage(EXIT_FAILURE);
- }
-}
-
-/**
- * string: "facility=level"
- * Set the right thing in the logger
- */
-static void _setLogLevel(int logLevelArray[LoggerFacility_END],
- const char *string) {
- char *tofree = parcMemory_StringDuplicate(string, strlen(string));
- char *p = tofree;
-
- char *facilityString = strtok(p, "=");
- if (facilityString) {
- char *levelString = strtok(NULL, "=");
-
- if (strcasecmp(facilityString, "all") == 0) {
- for (LoggerFacility facility = 0; facility < LoggerFacility_END;
- facility++) {
- _setLogLevelToLevel(logLevelArray, facility, levelString);
- }
- } else {
- LoggerFacility facility;
- for (facility = 0; facility < LoggerFacility_END; facility++) {
- if (strcasecmp(facilityString, logger_FacilityString(facility)) == 0) {
- break;
- }
- }
-
- if (facility < LoggerFacility_END) {
- _setLogLevelToLevel(logLevelArray, facility, levelString);
- } else {
- printf("Invalid facility string %s\n", facilityString);
- _usage(EXIT_FAILURE);
- }
- }
- }
-
- parcMemory_Deallocate((void **)&tofree);
-}
-
-#ifndef _WIN32
-static void _daemonize(void) {
- if (getppid() == 1) {
- // already a daemon
- return;
- }
-
- int forkReturn = fork();
- parcTrapUnexpectedStateIf(forkReturn < 0, "Fork error")
-
- if (forkReturn > 0) {
- // parent exits
- exit(EXIT_SUCCESS);
- }
-
- // Child daemon detaches
- printf("child continuing, pid = %u\n", getpid());
-
- // get a new process group independent from old parent
- setsid();
-
- /* close all descriptors */
-#ifdef __ANDROID__
- for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i) {
- close(i);
- }
-#else
- for (int i = getdtablesize(); i >= 0; --i) {
- close(i);
- }
-#endif
- // reset errno because it might be seg to EBADF from the close calls above
- errno = 0;
-
- // Redirect stdin and stdout and stderr to /dev/null
- const char *devnull = "/dev/null";
- int nullfile = open(devnull, O_RDWR);
- parcAssertTrue(nullfile >= 0, "Error opening file '%s': (%d) %s", devnull,
- errno, strerror(errno));
-
- int ret;
- ret = dup(nullfile);
- parcAssertTrue(ret == 1, "Error duping fd 1 got %d file: (%d) %s", ret, errno,
- strerror(errno));
- ret = dup(nullfile);
- parcAssertTrue(ret == 2, "Error duping fd 2, got %d file: (%d) %s", ret,
- errno, strerror(errno));
-
- // forwarder will capture signals
-}
-#endif
-
-static Logger *_createLogfile(const char *logfile) {
-#ifndef _WIN32
- int logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
-#else
- int logfd =
- _open(logfile, _O_WRONLY | _O_APPEND | _O_CREAT, _S_IWRITE | _S_IREAD);
-#endif
- if (logfd < 0) {
- fprintf(stderr, "Error opening %s for writing: (%d) %s\n", logfile, errno,
- strerror(errno));
- exit(EXIT_FAILURE);
- }
-
-#ifndef _WIN32
- chmod(logfile, S_IRWXU);
-#endif
-
- PARCFileOutputStream *fos = parcFileOutputStream_Create(logfd);
- PARCOutputStream *pos = parcFileOutputStream_AsOutputStream(fos);
- PARCLogReporter *reporter = parcLogReporterFile_Create(pos);
-
- Logger *logger = logger_Create(reporter, parcClock_Wallclock());
-
- parcOutputStream_Release(&pos);
- parcLogReporter_Release(&reporter);
-
- return logger;
-}
-
-int main(int argc, const char *argv[]) {
- _displayForwarderLogo();
-#ifndef _WIN32
- bool daemon = false;
-#else
- WSADATA wsaData = {0};
- WSAStartup(MAKEWORD(2, 2), &wsaData);
-#endif
-
- uint16_t port = PORT_NUMBER;
- uint16_t configurationPort = 2001;
- int capacity = -1;
- const char *configFileName = NULL;
-
- char *logfile = NULL;
-
- if (argc == 2 && strcasecmp(argv[1], "-h") == 0) {
- _usage(EXIT_SUCCESS);
- }
-
- int logLevelArray[LoggerFacility_END];
- for (int i = 0; i < LoggerFacility_END; i++) {
- logLevelArray[i] = -1;
- }
-
- for (int i = 0; i < argc; i++) {
- if (argv[i][0] == '-') {
- if (strcmp(argv[i], "--config") == 0) {
- configFileName = argv[i + 1];
- i++;
- } else if (strcmp(argv[i], "--port") == 0) {
- port = atoi(argv[i + 1]);
- i++;
-#ifndef _WIN32
- } else if (strcmp(argv[i], "--daemon") == 0) {
- daemon = true;
-#endif
- } else if (strcmp(argv[i], "--capacity") == 0 ||
- strcmp(argv[i], "-c") == 0) {
- capacity = atoi(argv[i + 1]);
- i++;
- } else if (strcmp(argv[i], "--log") == 0) {
- _setLogLevel(logLevelArray, argv[i + 1]);
- i++;
- } else if (strcmp(argv[i], "--log-file") == 0) {
- if (logfile) {
- // error cannot repeat
- fprintf(stderr, "Cannot specify --log-file more than once\n");
- _usage(EXIT_FAILURE);
- }
-
- logfile = parcMemory_StringDuplicate(argv[i + 1], strlen(argv[i + 1]));
- i++;
- } else {
- _usage(EXIT_FAILURE);
- }
- }
- }
-
- // set restrictive umask, in case we create any files
- umask(027);
-
-#ifndef _WIN32
- if (daemon && (logfile == NULL)) {
- fprintf(stderr, "Must specify a logfile when running in daemon mode\n");
- _usage(EXIT_FAILURE);
- }
-
- if (daemon) {
- // inside this call, parent will EXIT_SUCCESS and child will continue
- _daemonize();
- }
-#endif
-
- Logger *logger = NULL;
- if (logfile) {
- logger = _createLogfile(logfile);
- parcMemory_Deallocate((void **)&logfile);
- } else {
- PARCLogReporter *stdoutReporter = parcLogReporterTextStdout_Create();
- logger = logger_Create(stdoutReporter, parcClock_Wallclock());
- parcLogReporter_Release(&stdoutReporter);
- }
-
- for (int i = 0; i < LoggerFacility_END; i++) {
- if (logLevelArray[i] > -1) {
- logger_SetLogLevel(logger, i, logLevelArray[i]);
- }
- }
-
- // this will update the clock to the tick clock
- Forwarder *forwarder = forwarder_Create(logger);
-
- if (forwarder == NULL) {
- logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Error, "daemon",
- "Forwarder initialization failed. Are you running it with sudo "
- "privileges?");
- logger_Release(&logger);
- return -1;
- }
-
- Configuration *configuration = forwarder_GetConfiguration(forwarder);
-
- if (capacity > -1) {
- configuration_SetObjectStoreSize(configuration, capacity);
- }
-
- forwarder_SetupLocalListeners(forwarder, port);
- if (configFileName) {
- forwarder_SetupFromConfigFile(forwarder, configFileName);
- }
-
- Dispatcher *dispatcher = forwarder_GetDispatcher(forwarder);
-
- logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Alert, "daemon",
- "hicn-light running port %d configuration-port %d", port,
- configurationPort);
-
- dispatcher_Run(dispatcher);
-
- logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Alert, "daemon",
- "hicn-light exiting port %d", port);
-
- forwarder_Destroy(&forwarder);
-
-#ifndef _WIN32
- //sleep(2);
-#else
- //Sleep(2000);
- WSACleanup();
-#endif
-
- logger_Release(&logger);
- return 0;
-}
diff --git a/hicn-light/src/hicn/config.h.in b/hicn-light/src/hicn/config.h.in
index 90ab8e83f..6c2915b7e 100644
--- a/hicn-light/src/hicn/config.h.in
+++ b/hicn-light/src/hicn/config.h.in
@@ -2,7 +2,8 @@
#define LEVEL1_DCACHE_LINESIZE @LEVEL1_DCACHE_LINESIZE@
#ifndef _WIN32
-#define _GNU_SOURCE
+// This is now in CMakeLists.txt
+//#define _GNU_SOURCE
#else
#include <hicn/platforms/windows/win_portability.h>
#endif
diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt
index 104026355..00ee24077 100644
--- a/hicn-light/src/hicn/config/CMakeLists.txt
+++ b/hicn-light/src/hicn/config/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,95 +12,28 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/commandOps.h
- ${CMAKE_CURRENT_SOURCE_DIR}/commandParser.h
- ${CMAKE_CURRENT_SOURCE_DIR}/configuration.h
- ${CMAKE_CURRENT_SOURCE_DIR}/commandReturn.h
- ${CMAKE_CURRENT_SOURCE_DIR}/symbolicNameTable.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlState.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRoot.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddConnection.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAdd.h
- ${CMAKE_CURRENT_SOURCE_DIR}/configurationFile.h
- ${CMAKE_CURRENT_SOURCE_DIR}/configurationListeners.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/command.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/commands.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/parse.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/commandOps.c
- ${CMAKE_CURRENT_SOURCE_DIR}/commandParser.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configurationFile.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configurationListeners.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlState.c
- ${CMAKE_CURRENT_SOURCE_DIR}/symbolicNameTable.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAdd.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddConnection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlList.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRoot.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeRetx.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_connection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_face.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_mapme.c
+ ${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_strategy.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_subscription.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/commands.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/parse.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/config/command.c b/hicn-light/src/hicn/config/command.c
new file mode 100644
index 000000000..bee0d2663
--- /dev/null
+++ b/hicn-light/src/hicn/config/command.c
@@ -0,0 +1,119 @@
+
+/**
+ * @file command.c
+ * @brief Implementation of commands.
+ */
+
+#include <search.h> /* tfind, tdestroy, twalk */
+#include <stdio.h>
+#include <ctype.h>
+#include "command.h"
+#include "parse.h"
+
+/* Commands are registered in the following tree. */
+static void *commands_root = NULL; /**< Tree ordered by name */
+
+#ifdef __linux__
+static void nothing_to_free() {}
+
+__attribute__((destructor)) static void command_clear() {
+ tdestroy(commands_root, nothing_to_free);
+}
+#endif /* __linux__ */
+
+static int _command_compare(const command_parser_t *c1,
+ const command_parser_t *c2) {
+ if (c1->object != c2->object) return c2->object - c1->object;
+ if (c1->action != c2->action) return c2->action - c1->action;
+ if (c1->nparams != c2->nparams) return c2->nparams - c1->nparams;
+ return 0;
+}
+
+#define command_compare (int (*)(const void *, const void *))(_command_compare)
+
+void command_register(const command_parser_t *command) {
+ // Insert the command in the tree if the keys does not exist yet
+ tsearch(command, &commands_root, command_compare);
+}
+
+const command_parser_t *command_search(const hc_action_t action,
+ hc_object_type_t object,
+ unsigned nparams) {
+ command_parser_t **command, search;
+
+ search.action = action;
+ search.object = object;
+ search.nparams = nparams;
+ command = tfind(&search, &commands_root, command_compare);
+
+ return command ? *command : NULL;
+}
+
+static inline void to_lowercase(char *p) {
+ for (; *p; ++p) *p = tolower(*p);
+}
+
+typedef struct {
+ hc_object_type_t object;
+ hc_action_t action;
+} cmd_search_params_t;
+
+static hc_object_type_t prev_obj = OBJECT_UNDEFINED;
+static hc_action_t prev_action = ACTION_UNDEFINED;
+static void traversal_action(const void *nodep, VISIT which,
+ void *cmd_params0) {
+ cmd_search_params_t *cmd_params = cmd_params0;
+
+ // Execute this function during inorder traversal
+ if (which != postorder && which != leaf) return;
+
+ command_parser_t *datap;
+ datap = *(command_parser_t **)nodep;
+ char *obj_str = strdup(object_str(datap->object));
+ to_lowercase(obj_str);
+
+ // List all objects
+ if (cmd_params->object == OBJECT_UNDEFINED &&
+ cmd_params->action == ACTION_UNDEFINED) {
+ if (datap->object == prev_obj) goto FREE_STR;
+ prev_obj = datap->object;
+
+ printf("\thelp %s\n", obj_str);
+ goto FREE_STR;
+ }
+
+ // List actions for specific object
+ if (datap->object != cmd_params->object) goto FREE_STR;
+ if (cmd_params->action == ACTION_UNDEFINED) {
+ if (datap->action == prev_action) goto FREE_STR;
+ prev_action = datap->action;
+
+ printf("\thelp %s %s\n", obj_str, action_to_cmd_action(datap->action));
+ goto FREE_STR;
+ }
+
+ // List commands for specific object and action
+ if (datap->action != cmd_params->action) goto FREE_STR;
+ printf(" %s %s ", action_to_cmd_action(datap->action), obj_str);
+ for (int i = 0; i < datap->nparams; i++)
+ printf("<%s> ", datap->parameters[i].name);
+ printf("\n\n");
+ // List options' details
+ if (datap->nparams == 0) goto FREE_STR;
+ for (int i = 0; i < datap->nparams; i++)
+ printf("%16s: %s\n", datap->parameters[i].name, datap->parameters[i].help);
+ printf("\n");
+
+FREE_STR:
+ free(obj_str);
+}
+
+void command_list(hc_object_type_t object, hc_action_t action) {
+#if defined(__linux__) && !defined(__ANDROID__)
+ cmd_search_params_t cmd_params = {.object = object, .action = action};
+ twalk_r(commands_root, traversal_action, &cmd_params);
+#else
+ fprintf(stderr, "twalk_r() function only available on linux");
+ (void)traversal_action;
+#endif
+}
diff --git a/hicn-light/src/hicn/config/command.h b/hicn-light/src/hicn/config/command.h
new file mode 100644
index 000000000..73d8edb1f
--- /dev/null
+++ b/hicn-light/src/hicn/config/command.h
@@ -0,0 +1,179 @@
+#ifndef HICNLIGHT_CONFIG_COMMAND
+#define HICNLIGHT_CONFIG_COMMAND
+
+/**
+ * @file command.h
+ * @brief Commands.
+ */
+
+#include <stddef.h> // offsetof
+#include <hicn/util/ip_address.h>
+
+#include <hicn/ctrl/api.h>
+
+/* Update sscanf accordingly in parse_cmd.c */
+#define MAX_PARAMETERS 10
+#define MAX_SCANF_PARAM_LEN 100
+
+typedef int (*parser_hook_t)(void *arg);
+
+typedef enum {
+ TYPENAME_UNDEFINED,
+ TYPENAME_INT,
+ TYPENAME_UINT,
+ TYPENAME_STR,
+ TYPENAME_SYMBOLIC_OR_ID,
+ TYPENAME_INTERFACE_NAME,
+ TYPENAME_IP_ADDRESS,
+ TYPENAME_IP_PREFIX,
+ TYPENAME_ON_OFF,
+ TYPENAME_ENUM,
+ TYPENAME_POLICY_STATE,
+} parser_typename_t;
+
+typedef struct {
+ parser_typename_t name;
+ union {
+ struct {
+ size_t max_size;
+ } str;
+ struct {
+ int min;
+ int max;
+ } sint;
+ struct {
+ int min;
+ int max;
+ } uint;
+ struct {
+ int (*from_str)(const char *str);
+ } enum_;
+ struct {
+ policy_tag_t tag;
+ } policy_state;
+ };
+} parser_type_t;
+
+typedef struct {
+ const char *name;
+ const char *help;
+ parser_type_t type;
+ size_t offset;
+ /*
+ * quick hack to let the functions update two or more parameters, like for
+ * IP_ADDRESS or IP_PREFIX types
+ */
+ size_t offset2;
+ size_t offset3;
+} command_parameter_t;
+
+typedef struct {
+ hc_action_t action;
+ hc_object_type_t object;
+ unsigned nparams;
+ command_parameter_t parameters[MAX_PARAMETERS];
+ parser_hook_t post_hook;
+} command_parser_t;
+
+#define TYPE_STRN(N) \
+ (parser_type_t) { \
+ .name = TYPENAME_STR, \
+ .str = { \
+ .max_size = N, \
+ }, \
+ }
+#define TYPE_FMT_STRN(N) "%s"
+
+#define TYPE_INT(MIN, MAX) \
+ (parser_type_t) { \
+ .name = TYPENAME_INT, \
+ .sint = { \
+ .min = (MIN), \
+ .max = (MAX), \
+ }, \
+ }
+#define TYPE_FMT_INT "%d"
+
+#define TYPE_UINT(min, max) \
+ (parser_type_t) { \
+ .name = TYPENAME_UINT, \
+ .uint = { \
+ .min = min, \
+ .max = max, \
+ }, \
+ }
+#define TYPE_FMT_UINT "%u"
+
+#define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN)
+#define TYPE_FMT_SYMBOLIC_OR_ID "%s"
+
+#define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN)
+#define TYPE_FMT_INTERFACE_NAME "%s"
+
+#define TYPE_IP_ADDRESS \
+ (parser_type_t) { .name = TYPENAME_IP_ADDRESS, }
+#define TYPE_FMT_IP_ADDRESS "%s"
+
+#define TYPE_IP_PREFIX \
+ (parser_type_t) { .name = TYPENAME_IP_PREFIX, }
+#define TYPE_FMT_IP_PREFIX "%s"
+
+#define TYPE_ON_OFF \
+ (parser_type_t) { .name = TYPENAME_ON_OFF, }
+#define TYPE_FMT_ON_OFF "%s"
+
+#define TYPE_ENUM(x) \
+ (parser_type_t) { \
+ .name = TYPENAME_ENUM, \
+ .enum_ = { \
+ .from_str = (int (*)(const char *))x##_from_str, \
+ }, \
+ }
+/* We need to allocate room for the intermediate string */
+#define TYPE_FMT_ENUM "%s"
+
+#define TYPE_POLICY_STATE(TAG) \
+ (parser_type_t) { \
+ .name = TYPENAME_POLICY_STATE, \
+ .policy_state = { \
+ .tag = TAG, \
+ }, \
+ }
+/* We need to allocate room for the intermediate string */
+#define TYPE_FMT_POLICY_STATE "%s"
+
+/**
+ * \brief Register a protocol
+ * \param protocol Pointer to a protocol_t structure describing the protocol to
+ * register \return None
+ */
+
+void command_register(const command_parser_t *command);
+
+/**
+ * \brief Search a registered protocol in the library according to its name
+ * \param[in] action The action of the command.
+ * \param[in] object The object of the command.
+ * \param[in] nparams The number of parameters expected in the command.
+ * \return A pointer to the corresponding command if any, NULL othewise
+ */
+const command_parser_t *command_search(hc_action_t action,
+ hc_object_type_t object,
+ unsigned nparams);
+
+/**
+ * @brief List the commands associated with the specified object and/or action.
+ * Use OBJECT_UNDEFINED and ACTION_UNDEFINED to list all the available objects.
+ * Use ACTION_UNDEFINED to list all the actions associated to the specified
+ * object.
+ *
+ * @param object The action of the command
+ * @param action The object of the command
+ */
+void command_list(hc_object_type_t object, hc_action_t action);
+
+#define COMMAND_REGISTER(MOD) \
+ static void __init_##MOD(void) __attribute__((constructor)); \
+ static void __init_##MOD(void) { command_register(&MOD); }
+
+#endif /* HICNLIGHT_CONFIG_COMMAND */
diff --git a/hicn-light/src/hicn/config/commandOps.c b/hicn-light/src/hicn/config/commandOps.c
deleted file mode 100644
index dd8e148d0..000000000
--- a/hicn-light/src/hicn/config/commandOps.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef __ANDROID__
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#else
-#ifndef _WIN32
-extern int errno;
-#endif
-#endif
-#endif
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/commandOps.h>
-#include <hicn/config/commandParser.h>
-
-CommandOps *commandOps_Create(void *closure, const char *command,
- void (*init)(CommandParser *parser,
- CommandOps *ops),
- CommandReturn (*execute)(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size),
- void (*destroyer)(CommandOps **opsPtr)) {
- parcAssertNotNull(command, "Parameter command must be non-null");
- parcAssertNotNull(execute, "Parameter execute must be non-null");
- CommandOps *ops = parcMemory_AllocateAndClear(sizeof(CommandOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(CommandOps));
-
- ops->closure = closure;
- ops->command = parcMemory_StringDuplicate(command, strlen(command) + 1);
- ops->init = init;
- ops->execute = execute;
- ops->destroyer = destroyer;
- return ops;
-}
-
-void commandOps_Destroy(CommandOps **opsPtr) {
- parcAssertNotNull(opsPtr, "Parameter opsPtr must be non-null");
- parcAssertNotNull(*opsPtr,
- "Parameter opsPtr must dereference to non-null pointer");
-
- CommandOps *ops = *opsPtr;
- parcMemory_Deallocate((void **)&(ops->command));
- // DO NOT call ops->destroyer, we are one!
- parcMemory_Deallocate((void **)&ops);
-
- *opsPtr = NULL;
-}
diff --git a/hicn-light/src/hicn/config/commandOps.h b/hicn-light/src/hicn/config/commandOps.h
deleted file mode 100644
index 784b91eb8..000000000
--- a/hicn-light/src/hicn/config/commandOps.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file command_Ops.h
- * @brief The function structure defining a CLI command
- *
- * The function structure that defines a CLI command. Each command will return
- * one of these which defines how to run the command.
- *
- */
-
-#ifndef command_Ops_h
-#define command_Ops_h
-
-#include <parc/algol/parc_List.h>
-
-#include <hicn/config/commandReturn.h>
-
-// forward reference
-struct command_parser;
-
-struct command_ops;
-typedef struct command_ops CommandOps;
-
-/**
- * @typedef CommandOps
- * @abstract Each command implements a CommandOps
- * @constant closure is a user-specified pointer for any state the user needs
- * @constant command The text string of the command, must be the spelled out
- * string, e.g. "help list routes"
- * @constant init A function to call to initialize the command at program
- * startup
- * @constant execute A function to call to execute the command
- * @constant destroyer A function to call to release the command
- * @discussion
- * Typically, the root of the thee has an Init function that then initilizes
- * the rest of the tree. For example:
- *
- * @code
- * const CommandOps control_Root = {
- * .closure = NULL,
- * .command = "", // empty string for root
- * .init = control_Root_Init,
- * .execute = control_Root_Execute
- * .destroyer = NULL
- * };
- * @endcode
- *
- * The control_Root_Init function will then begin adding the subtree under root.
- * For example:
- *
- * @code
- * const CommandOps control_Add = {
- * .closure = NULL,
- * .command = "add",
- * .init = control_Add_Init,
- * .execute = control_Add_Execute,
- * .destroyer = NULL
- * };
- *
- * static void
- * control_Root_Init(ControlState *state, CommandOps *ops)
- * {
- * controlState_RegisterCommand(state, &control_Add);
- * }
- * @endcode
- */
-struct command_ops {
- void *closure;
- char *command;
- void (*init)(struct command_parser *parser, CommandOps *ops);
- CommandReturn (*execute)(struct command_parser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
- void (*destroyer)(CommandOps **opsPtr);
-};
-
-/**
- * A helper function to create the pubically defined CommandOps.
- *
- * Retruns allocated memory of the command
- *
- * @param [in] command The string is copied
- *
- * @retval <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-CommandOps *commandOps_Create(
- void *closure, const char *command,
- void (*init)(struct command_parser *parser, CommandOps *ops),
- CommandReturn (*execute)(struct command_parser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size),
- void (*destroyer)(CommandOps **opsPtr));
-
-/**
- * De-allocates the memory of the CommandOps and the copied command string
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @retval <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void commandOps_Destroy(CommandOps **opsPtr);
-#endif // command_Ops_h
diff --git a/hicn-light/src/hicn/config/commandParser.c b/hicn-light/src/hicn/config/commandParser.c
deleted file mode 100644
index f4652fe39..000000000
--- a/hicn-light/src/hicn/config/commandParser.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Time.h>
-#include <parc/algol/parc_TreeRedBlack.h>
-
-#include <hicn/config/commandParser.h>
-
-#ifndef __ANDROID__
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#else
-#ifndef _WIN32
-extern int errno;
-#endif
-#endif
-#endif
-
-struct command_parser {
- // key = command, value = CommandOps
- PARCTreeRedBlack *commandTree;
- bool debugFlag;
-};
-
-static int _stringCompare(const void *key1, const void *key2) {
- return strcasecmp((const char *)key1, (const char *)key2);
-}
-
-CommandParser *commandParser_Create(void) {
- CommandParser *state = parcMemory_AllocateAndClear(sizeof(CommandParser));
- parcAssertNotNull(state, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(CommandParser));
-
- state->commandTree = parcTreeRedBlack_Create(_stringCompare, // key compare
- NULL, // key free
- NULL, // key copy
- NULL, // value equals
- NULL, // value free
- NULL // value copy
- );
- state->debugFlag = false;
- return state;
-}
-
-void commandParser_Destroy(CommandParser **parserPtr) {
- CommandParser *parser = *parserPtr;
-
- // destroy every element if it has a destroyer
- PARCArrayList *values = parcTreeRedBlack_Values(parser->commandTree);
- if (values) {
- for (int i = 0; i < parcArrayList_Size(values); i++) {
- CommandOps *ops = parcArrayList_Get(values, i);
- parcTreeRedBlack_Remove(parser->commandTree, ops->command);
- if (ops->destroyer) {
- ops->destroyer(&ops);
- }
- }
- parcArrayList_Destroy(&values);
- }
-
- parcTreeRedBlack_Destroy(&parser->commandTree);
-
- parcMemory_Deallocate((void **)&parser);
- *parserPtr = NULL;
-}
-
-void commandParser_SetDebug(CommandParser *state, bool debugFlag) {
- state->debugFlag = debugFlag;
-}
-
-bool commandParser_GetDebug(CommandParser *state) { return state->debugFlag; }
-
-void commandParser_RegisterCommand(CommandParser *state, CommandOps *ops) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(ops->command, "Operation command string must be non-null");
-
- void *exists = parcTreeRedBlack_Get(state->commandTree, ops->command);
- parcAssertNull(exists, "Command '%s' already exists in the tree %p\n",
- ops->command, (void *)exists);
-
- parcTreeRedBlack_Insert(state->commandTree, (void *)ops->command,
- (void *)ops);
-
- // if the command being registered asked for an init function to be called,
- // call it
- if (ops->init != NULL) {
- ops->init(state, ops);
- }
-}
-
-static PARCList *parseStringIntoTokens(const char *originalString) {
- PARCList *list =
- parcList(parcArrayList_Create(parcArrayList_StdlibFreeFunction),
- PARCArrayListAsPARCList);
-
- char *token;
-
- char *tofree =
- parcMemory_StringDuplicate(originalString, strlen(originalString) + 1);
- char *string = tofree;
-
- token = strtok(string, " \t\n");
- while (token != NULL) {
- if (strlen(token) > 0) {
- parcList_Add(list, strdup(token));
- }
- token = strtok(NULL, " \t\n");
- }
-
- parcMemory_Deallocate((void **)&tofree);
-
- return list;
-}
-
-/**
- * Matches the user arguments to available commands, returning the command or
- * NULL if not found
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-static CommandOps *commandParser_MatchCommand(CommandParser *state,
- PARCList *args) {
- // Find the longest matching prefix command.
- // Pretty wildly inefficient
-
- size_t longest_token_count = 0;
- char *longest_command = NULL;
-
- PARCArrayList *commands = parcTreeRedBlack_Keys(state->commandTree);
- for (int i = 0; i < parcArrayList_Size(commands); i++) {
- char *command = parcArrayList_Get(commands, i);
- PARCList *command_tokens = parseStringIntoTokens(command);
-
- // is it a prefix match?
- if (parcList_Size(args) >= parcList_Size(command_tokens)) {
- bool possible_match = true;
- for (int i = 0; i < parcList_Size(command_tokens) && possible_match;
- i++) {
- const char *a = parcList_GetAtIndex(command_tokens, i);
- const char *b = parcList_GetAtIndex(args, i);
- if (strncasecmp(a, b, strlen(a) + 1) != 0) {
- possible_match = false;
- }
- }
-
- if (possible_match &&
- parcList_Size(command_tokens) > longest_token_count) {
- longest_token_count = parcList_Size(command_tokens);
- longest_command = command;
- }
- }
-
- parcList_Release(&command_tokens);
- }
-
- parcArrayList_Destroy(&commands);
-
- if (longest_token_count == 0) {
- return NULL;
- } else {
- CommandOps *ops = parcTreeRedBlack_Get(state->commandTree, longest_command);
- parcAssertNotNull(ops, "Got null operations for command '%s'\n",
- longest_command);
- return ops;
- }
-}
-
-CommandReturn commandParser_DispatchCommand(CommandParser *state,
- PARCList *args,
- char *output,
- size_t output_size) {
- parcAssertNotNull(output, "output buffer is null\n");
- CommandOps *ops = commandParser_MatchCommand(state, args);
-
- if (ops == NULL) {
- snprintf(output, output_size, "Command not found.\n");
- return CommandReturn_Failure;
- } else {
- return ops->execute(state, ops, args, output, output_size);
- }
-}
-
-bool commandParser_ContainsCommand(CommandParser *parser, const char *command) {
- CommandOps *ops = parcTreeRedBlack_Get(parser->commandTree, command);
- return (ops != NULL);
-}
diff --git a/hicn-light/src/hicn/config/commandParser.h b/hicn-light/src/hicn/config/commandParser.h
deleted file mode 100644
index 882d55d26..000000000
--- a/hicn-light/src/hicn/config/commandParser.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file command_Parser.h
- * @brief Creates a dictionary of commands and parses a command_line to match
- * against them
- *
- * A user creates individual CommandParserEntry that map a command_line to a
- * function to execute. The CommandParser then does a longest-matching prefix
- * match of a command_line to the dictionary of commands and executes the
- * appropriate command.
- *
- */
-
-#ifndef command_parser_h
-#define command_parser_h
-
-#include <hicn/config/commandOps.h>
-#include <hicn/config/commandReturn.h>
-
-struct command_parser;
-typedef struct command_parser CommandParser;
-
-/**
- * controlState_Create
- *
- * Creates the global state for the Control program
- *
- * @return non-null A command parser
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-CommandParser *commandParser_Create(void);
-
-/**
- * Destroys the control state, closing all network connections
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void commandParser_Destroy(CommandParser **statePtr);
-
-/**
- * Registers a CommandOps with the system.
- *
- * Each command has its complete command prefix in the "command" field.
- * RegisterCommand will put these command prefixes in to a tree and then match
- * what a user types against the longest-matching prefix in the tree. If
- * there's a match, it will call the "execute" function.
- *
- * When the parser is destroyed, each command's destroyer function will be
- * called.
- *
- * @param [in] state An allocated ControlState
- * @param [in] command The command to register with the system
- *
- * Example:
- * @code
- * static ControlReturn
- * control_Root_Execute(CommandParser *parser, CommandOps *ops, PARCList
- * *args)
- * {
- * printf("Root Command\n");
- * return CommandReturn_Success;
- * }
- *
- * static ControlReturn
- * control_FooBar_Execute(CommandParser *parser, CommandOps *ops, PARCList
- * *args)
- * {
- * printf("Foo Bar Command\n");
- * return CommandReturn_Success;
- * }
- *
- * const CommandOps control_Root = {
- * .closure = NULL,
- * .command = "", // empty string for root
- * .init = NULL,
- * .execute = control_Root_Execute
- * };
- *
- * const CommandOps control_FooBar = {
- * .closure = NULL,
- * .command = "foo bar", // empty string for root
- * .init = NULL,
- * .execute = control_FooBar_Execute
- * };
- *
- * void startup(void)
- * {
- * ControlState *state = controlState_Create("happy", "day");
- * controlState_RegisterCommand(state, control_FooBar);
- * controlState_RegisterCommand(state, control_Root);
- *
- * // this executes "root"
- * controlState_DispatchCommand(state, "foo");
- * controlState_Destroy(&state);
- * }
- * @endcode
- */
-void commandParser_RegisterCommand(CommandParser *state, CommandOps *command);
-
-/**
- * Performs a longest-matching prefix of the args to the command tree
- *
- * The command tree is created with controlState_RegisterCommand.
- *
- * @param [in] state The allocated ControlState
- * @param [in] args Each command_line word parsed to the ordered list
- * @param [in] output The allocated output string, if null, the normal printf is executed
- * @param [in] output_size the size of output array string. It is ignored if the output string is null
- *
- * @return CommandReturn_Success the command was successful
- * @return CommandReturn_Failure the command failed or was not found
- * @return CommandReturn_Exit the command indicates that the interactive mode
- * should exit
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-CommandReturn commandParser_DispatchCommand(CommandParser *state,
- PARCList *args,
- char *output,
- size_t output_size);
-
-/**
- * Sets the Debug mode, which will print out much more information.
- *
- * Prints out much more diagnostic information about what hicn-light controller
- * is doing. yes, you would make a CommandOps to set and unset this :)
- *
- * @param [in] debugFlag true means to print debug info, false means to turn it
- * off
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void commandParser_SetDebug(CommandParser *state, bool debugFlag);
-
-/**
- * Returns the debug state of ControlState
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-bool commandParser_GetDebug(CommandParser *state);
-
-/**
- * Checks if the command is registered
- *
- * Checks if the exact command given is registered. This is not a prefix match.
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return true The command is registered
- * @return false The command is not registered
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-bool commandParser_ContainsCommand(CommandParser *parser, const char *command);
-#endif // command_parser_h
diff --git a/hicn-light/src/hicn/config/commandReturn.h b/hicn-light/src/hicn/config/commandReturn.h
deleted file mode 100644
index 16ee93db1..000000000
--- a/hicn-light/src/hicn/config/commandReturn.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file command_Return.h
- * @brief The return code used by CLI commands
- *
- * This return code is used throughout the command parser and command
- * implementations to indicate success, failure, or if the program should exit.
- *
- */
-
-#ifndef command_return_h
-#define command_return_h
-
-/**
- * @typedef ControlReturn
- * @abstract A command returns one of (SUCCESS, FAILURE, EXIT)
- * @constant SUCCESS means the command succeeded
- * @constant FAILURE indicates failure
- * @constant EXIT means the command indicated that hicn-light controller should
- * exit.
- * @discussion <#Discussion#>
- */
-typedef enum command_return {
- CommandReturn_Success, // command returned success
- CommandReturn_Failure, // command failure
- CommandReturn_Exit // command indicates program should exit
-} CommandReturn;
-
-#endif // command_return_h
diff --git a/hicn-light/src/hicn/config/command_cache.c b/hicn-light/src/hicn/config/command_cache.c
new file mode 100644
index 000000000..073221cf0
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_cache.c
@@ -0,0 +1,54 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+#define serve \
+ { \
+ .name = "serve", \
+ .help = \
+ "Enables/disables replies from local content store. Either the " \
+ "string 'on' or 'off'", \
+ .type = TYPE_ON_OFF, .offset = offsetof(hc_cache_t, serve), \
+ }
+
+#define store \
+ { \
+ .name = "store", \
+ .help = \
+ "enables/disables the storage of incoming data packets in the local " \
+ "content store. Either the string 'on' or 'off'", \
+ .type = TYPE_ON_OFF, .offset = offsetof(hc_cache_t, store), \
+ }
+
+/* Commands */
+
+static const command_parser_t command_cache_set_serve = {
+ .action = ACTION_SERVE,
+ .object = OBJECT_CACHE,
+ .nparams = 1,
+ .parameters = {serve},
+};
+COMMAND_REGISTER(command_cache_set_serve);
+
+static const command_parser_t command_cache_set_store = {
+ .action = ACTION_STORE,
+ .object = OBJECT_CACHE,
+ .nparams = 1,
+ .parameters = {store},
+};
+COMMAND_REGISTER(command_cache_set_store);
+
+static const command_parser_t command_cache_clear = {
+ .action = ACTION_CLEAR,
+ .object = OBJECT_CACHE,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_cache_clear);
+
+static const command_parser_t command_cache_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_CACHE,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_cache_list);
diff --git a/hicn-light/src/hicn/config/command_connection.c b/hicn-light/src/hicn/config/command_connection.c
new file mode 100644
index 000000000..069bf55a6
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_connection.c
@@ -0,0 +1,128 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+#define type_hicn \
+ { \
+ .name = "type", .help = "connection type (hICN)", \
+ .type = TYPE_ENUM(face_type), .offset = offsetof(hc_connection_t, type), \
+ }
+
+#define type_tcp_udp \
+ { \
+ .name = "type", .help = "connection type [tcp | udp]", \
+ .type = TYPE_ENUM(face_type), .offset = offsetof(hc_connection_t, type), \
+ }
+
+#define symbolic \
+ { \
+ .name = "symbolic", \
+ .help = "symbolic name, e.g. 'conn1' (must be unique, start with alpha)", \
+ .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_connection_t, name), \
+ }
+
+#define local_address \
+ { \
+ .name = "local_addr", .help = "local IP address on which to bind.", \
+ .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_connection_t, local_addr), \
+ .offset2 = offsetof(hc_connection_t, family), \
+ }
+
+#define local_port \
+ { \
+ .name = "local_port", .help = "Local port.", \
+ .type = TYPE_INT(1, UINT16_MAX), \
+ .offset = offsetof(hc_connection_t, local_port), \
+ }
+
+#define remote_address \
+ { \
+ .name = "remote_address", \
+ .help = "The IPv4 or IPv6 or hostname of the remote system.", \
+ .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_connection_t, remote_addr), \
+ .offset2 = offsetof(hc_connection_t, family), \
+ }
+
+#define remote_port \
+ { \
+ .name = "remote_port", .help = "Remote port.", \
+ .type = TYPE_INT(1, UINT16_MAX), \
+ .offset = offsetof(hc_connection_t, remote_port), \
+ }
+
+#define interface \
+ { \
+ .name = "interface", .help = "Interface on which to bind", \
+ .type = TYPE_INTERFACE_NAME, \
+ .offset = offsetof(hc_connection_t, interface_name), \
+ }
+
+#define symbolic_or_id \
+ { \
+ .name = "symbolic", .help = "The connection symbolic name or id", \
+ .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_connection_t, name), \
+ }
+
+/* Commands */
+
+int on_connection_create(hc_connection_t* connection) {
+ connection->admin_state = FACE_STATE_UP;
+ return 0;
+}
+
+#if 0
+static command_parser_t command_connection_create4 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 4,
+ .parameters = {type_hicn, symbolic, local_address, remote_address},
+ .post_hook = (parser_hook_t)on_connection_create,
+};
+COMMAND_REGISTER(command_connection_create4);
+
+static const command_parser_t command_connection_create5 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 5,
+ .parameters = {type_hicn, symbolic, local_address, remote_address,
+ interface},
+ .post_hook = (parser_hook_t)on_connection_create,
+};
+COMMAND_REGISTER(command_connection_create5);
+#endif
+
+static const command_parser_t command_connection_create6 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 6,
+ .parameters = {type_tcp_udp, symbolic, remote_address, remote_port,
+ local_address, local_port},
+ .post_hook = (parser_hook_t)on_connection_create,
+};
+COMMAND_REGISTER(command_connection_create6);
+
+static const command_parser_t command_connection_create7 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 7,
+ .parameters = {type_tcp_udp, symbolic, remote_address, remote_port,
+ local_address, local_port, interface},
+ .post_hook = (parser_hook_t)on_connection_create,
+};
+COMMAND_REGISTER(command_connection_create7);
+
+static const command_parser_t command_connection_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_CONNECTION,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_connection_list);
+
+static const command_parser_t command_connection_remove = {
+ .action = ACTION_DELETE,
+ .object = OBJECT_CONNECTION,
+ .nparams = 1,
+ .parameters = {symbolic_or_id},
+};
+COMMAND_REGISTER(command_connection_remove);
diff --git a/hicn-light/src/hicn/config/command_face.c b/hicn-light/src/hicn/config/command_face.c
new file mode 100644
index 000000000..95ec404f0
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_face.c
@@ -0,0 +1,16 @@
+#if 0
+#include "command.h"
+
+/* Parameters */
+
+/* Commands */
+
+// XXX missing add
+
+static const command_parser_t command_face_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_FACE,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_face_list);
+#endif \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/command_listener.c b/hicn-light/src/hicn/config/command_listener.c
new file mode 100644
index 000000000..8ad7c94be
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_listener.c
@@ -0,0 +1,111 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+#define protocol_hicn \
+ { \
+ .name = "protocol", .help = "Protocol [hicn].", \
+ .type = TYPE_ENUM(face_type), .offset = offsetof(hc_listener_t, type), \
+ }
+
+#define protocol_tcp_udp \
+ { \
+ .name = "protocol", .help = "Protocol [tcp | udp]", \
+ .type = TYPE_ENUM(face_type), .offset = offsetof(hc_listener_t, type), \
+ }
+
+#define symbolic \
+ { \
+ .name = "symbolic", \
+ .help = \
+ "User defined name for listener, must start with alpha and be " \
+ "alphanum", \
+ .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_listener_t, name), \
+ }
+
+#define local_address \
+ { \
+ .name = "local_addr", \
+ .help = \
+ "IPv4 or IPv6 address (or prefix protocol = hicn) assigend to the " \
+ "local interface", \
+ .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_listener_t, local_addr), \
+ .offset2 = offsetof(hc_listener_t, family), \
+ }
+
+#define local_port \
+ { \
+ .name = "local_port", .help = "Local port.", \
+ .type = TYPE_INT(1, UINT16_MAX), \
+ .offset = offsetof(hc_listener_t, local_port), \
+ }
+
+#define interface \
+ { \
+ .name = "interface", .help = "Interface on which to bind", \
+ .type = TYPE_INTERFACE_NAME, \
+ .offset = offsetof(hc_listener_t, interface_name), \
+ }
+
+#define symbolic_or_id \
+ { \
+ .name = "symbolic", .help = "The listener symbolic name or id", \
+ .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_listener_t, name), \
+ }
+
+/* Commands */
+
+/* The parse sets the wrong face_type_t for listener, we fix that here */
+int on_listener_create(hc_listener_t* listener) {
+ switch (listener->type) {
+ case FACE_TYPE_UDP:
+ listener->type = FACE_TYPE_UDP_LISTENER;
+ break;
+ case FACE_TYPE_TCP:
+ listener->type = FACE_TYPE_TCP_LISTENER;
+ break;
+ case FACE_TYPE_HICN:
+ listener->type = FACE_TYPE_HICN_LISTENER;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+#if 0
+static const command_parser_t command_listener_create4 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_LISTENER,
+ .nparams = 4,
+ .parameters = {protocol_hicn, symbolic, local_address, interface},
+ .post_hook = (parser_hook_t)on_listener_create,
+};
+COMMAND_REGISTER(command_listener_create4);
+#endif
+
+static const command_parser_t command_listener_create6 = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_LISTENER,
+ .nparams = 5,
+ .parameters = {protocol_tcp_udp, symbolic, local_address, local_port,
+ interface},
+ .post_hook = (parser_hook_t)on_listener_create,
+};
+COMMAND_REGISTER(command_listener_create6);
+
+static const command_parser_t command_listener_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_LISTENER,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_listener_list);
+
+static const command_parser_t command_listener_remove = {
+ .action = ACTION_DELETE,
+ .object = OBJECT_LISTENER,
+ .nparams = 1,
+ .parameters = {symbolic_or_id},
+};
+COMMAND_REGISTER(command_listener_remove);
diff --git a/hicn-light/src/hicn/config/command_mapme.c b/hicn-light/src/hicn/config/command_mapme.c
new file mode 100644
index 000000000..a22e8b340
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_mapme.c
@@ -0,0 +1,59 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+#define target \
+ { \
+ .name = "target", \
+ .help = \
+ "Target for the set action, e.g. enable, discovery, timescale, retx", \
+ .type = TYPE_ENUM(mapme_target), .offset = offsetof(hc_mapme_t, target), \
+ }
+
+#define value \
+ { \
+ .name = "value", \
+ .help = "Value to set for the target, e.g. 'on', 'off', milliseconds", \
+ .type = TYPE_STRN(4), .offset = offsetof(hc_mapme_t, unparsed_arg), \
+ }
+
+#define prefix \
+ { \
+ .name = "prefix", \
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \
+ .type = TYPE_IP_PREFIX, .offset = offsetof(hc_mapme_t, address), \
+ .offset2 = offsetof(hc_mapme_t, len), \
+ .offset3 = offsetof(hc_mapme_t, family), \
+ }
+
+/* Commands */
+
+// Parse the raw string argument into 'timescale' or 'enabled',
+// necessary since the command dispatch is based on the number
+// of arguments and not their type
+int parse_args(hc_mapme_t* mapme) {
+ mapme->timescale = atoi(mapme->unparsed_arg);
+
+ if (strcasecmp(mapme->unparsed_arg, "off") == 0) mapme->enabled = 0;
+ if (strcasecmp(mapme->unparsed_arg, "on") == 0) mapme->enabled = 1;
+
+ return 0;
+}
+
+static const command_parser_t command_mapme_set = {
+ .action = ACTION_SET,
+ .object = OBJECT_MAPME,
+ .nparams = 2,
+ .parameters = {target, value},
+ .post_hook = (parser_hook_t)parse_args,
+};
+COMMAND_REGISTER(command_mapme_set);
+
+static const command_parser_t command_mapme_update = {
+ .action = ACTION_UPDATE,
+ .object = OBJECT_MAPME,
+ .nparams = 1,
+ .parameters = {prefix},
+};
+COMMAND_REGISTER(command_mapme_update); \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/command_policy.c b/hicn-light/src/hicn/config/command_policy.c
new file mode 100644
index 000000000..1e802c3f5
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_policy.c
@@ -0,0 +1,52 @@
+#if 0
+#include <hicn/policy.h>
+
+#include "command.h"
+
+/* Parameters */
+
+#define prefix \
+ { \
+ .name = "prefix", \
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \
+ .type = TYPE_IP_PREFIX, .offset = offsetof(hc_policy_t, remote_addr), \
+ .offset2 = offsetof(hc_policy_t, len), \
+ .offset3 = offsetof(hc_policy_t, family), \
+ }
+
+#define app_name \
+ { \
+ .name = "app_name", \
+ .help = "The application name associated to this policy", \
+ .type = TYPE_STR, .offset = offsetof(hc_policy_t, policy.app_name), \
+ }
+
+/* Commands */
+
+static const command_parser_t command_policy_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_POLICY,
+ .nparams = 2 + POLICY_TAG_N,
+ .parameters = {prefix, app_name,
+#define _(x, y) \
+ { \
+ .name = "flag:" #x, \
+ .help = \
+ "A value among [neutral|require|prefer|avoid|prohibit] with an " \
+ "optional '!' character prefix for disabling changes", \
+ .type = TYPE_POLICY_STATE(POLICY_TAG_##x), \
+ .offset = offsetof(hc_policy_t, policy.tags), \
+ },
+ foreach_policy_tag
+#undef _
+ },
+};
+COMMAND_REGISTER(command_policy_create);
+
+static const command_parser_t command_policy_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_POLICY,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_policy_list);
+#endif \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/command_punting.c b/hicn-light/src/hicn/config/command_punting.c
new file mode 100644
index 000000000..8c7a6dec3
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_punting.c
@@ -0,0 +1,40 @@
+#if 0
+#include "command.h"
+
+/* Parameters */
+
+#define symbolic_or_id \
+ { \
+ .name = "symbolic_or_id", \
+ .help = \
+ "The symbolic name for an egress, or the egress punting id (see " \
+ "'help list puntings')", \
+ .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_punting_t, face_id), \
+ }
+
+#define prefix \
+ { \
+ .name = "prefix", \
+ .help = "Prefix to add as a punting rule. (example 1234::0/64)", \
+ .type = TYPE_IP_PREFIX, .offset = offsetof(hc_punting_t, prefix), \
+ .offset2 = offsetof(hc_punting_t, prefix_len), \
+ .offset3 = offsetof(hc_punting_t, family), \
+ }
+
+/* Commands */
+
+static const command_parser_t command_punting_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_PUNTING,
+ .nparams = 2,
+ .parameters = {symbolic_or_id, prefix},
+};
+COMMAND_REGISTER(command_punting_create);
+
+static const command_parser_t command_punting_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_PUNTING,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_punting_list);
+#endif \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/command_route.c b/hicn-light/src/hicn/config/command_route.c
new file mode 100644
index 000000000..dfbea101f
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_route.c
@@ -0,0 +1,53 @@
+#include <math.h>
+#include "command.h"
+
+/* Parameters */
+
+#define symbolic_or_id \
+ { \
+ .name = "symbolic_or_id", \
+ .help = \
+ "The symbolic name for an egress, or the egress route id (see 'help " \
+ "list routes')", \
+ .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_route_t, name), \
+ }
+
+#define prefix \
+ { \
+ .name = "prefix", \
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \
+ .type = TYPE_IP_PREFIX, .offset = offsetof(hc_route_t, remote_addr), \
+ .offset2 = offsetof(hc_route_t, len), \
+ .offset3 = offsetof(hc_route_t, family), \
+ }
+
+#define cost \
+ { \
+ .name = "cost", .help = "Positive integer representing cost.", \
+ .type = TYPE_INT(1, 255), .offset = offsetof(hc_route_t, cost), \
+ }
+
+/* Commands */
+
+static const command_parser_t command_route_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_ROUTE,
+ .nparams = 3,
+ .parameters = {symbolic_or_id, prefix, cost},
+};
+COMMAND_REGISTER(command_route_create);
+
+static const command_parser_t command_route_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_ROUTE,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_route_list);
+
+static const command_parser_t command_route_remove = {
+ .action = ACTION_DELETE,
+ .object = OBJECT_ROUTE,
+ .nparams = 2,
+ .parameters = {symbolic_or_id, prefix},
+};
+COMMAND_REGISTER(command_route_remove);
diff --git a/hicn-light/src/hicn/config/command_strategy.c b/hicn-light/src/hicn/config/command_strategy.c
new file mode 100644
index 000000000..2341ac830
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_strategy.c
@@ -0,0 +1,47 @@
+#include "command.h"
+
+/* Parameters */
+#define prefix \
+ { \
+ .name = "prefix", \
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \
+ .type = TYPE_IP_PREFIX, .offset = offsetof(hc_strategy_t, address), \
+ .offset2 = offsetof(hc_strategy_t, len), \
+ .offset3 = offsetof(hc_strategy_t, family), \
+ }
+
+#define strategy \
+ { \
+ .name = "strategy", \
+ .help = \
+ "Strategy type (e.g. 'random', 'loadbalancer', 'low_latency', " \
+ "'replication', 'bestpath').", \
+ .type = TYPE_ENUM(strategy_type), .offset = offsetof(hc_strategy_t, type), \
+ }
+
+#define local_prefix \
+ { \
+ .name = "local_prefix", \
+ .help = "The hicn name as IPv4 or IPv6 address (e.g 1234::0/64).", \
+ .type = TYPE_IP_PREFIX, .offset = offsetof(hc_strategy_t, local_address), \
+ .offset2 = offsetof(hc_strategy_t, local_len), \
+ .offset3 = offsetof(hc_strategy_t, local_family), \
+ }
+
+/* Commands */
+
+static const command_parser_t command_strategy_list = {
+ .action = ACTION_SET,
+ .object = OBJECT_STRATEGY,
+ .nparams = 2,
+ .parameters = {prefix, strategy},
+};
+COMMAND_REGISTER(command_strategy_list);
+
+static const command_parser_t local_prefix_add = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_LOCAL_PREFIX,
+ .nparams = 3,
+ .parameters = {prefix, strategy, local_prefix},
+};
+COMMAND_REGISTER(local_prefix_add);
diff --git a/hicn-light/src/hicn/config/command_subscription.c b/hicn-light/src/hicn/config/command_subscription.c
new file mode 100644
index 000000000..89e3dcd98
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_subscription.c
@@ -0,0 +1,23 @@
+#include "command.h"
+
+/* Parameters */
+
+#define topics \
+ { \
+ .name = "topics", \
+ .help = \
+ "Topics to subscribe to, e.g. 6 (110 in binary) means topic 2 (10 in " \
+ "binary, TOPIC_CONNECTION) and topic 4 (100 in binary, " \
+ "TOPIC_LISTENER).", \
+ .type = TYPE_INT(1, 255), .offset = offsetof(hc_subscription_t, topics), \
+ }
+
+/* Commands */
+
+static const command_parser_t command_subscription_create = {
+ .action = ACTION_CREATE,
+ .object = OBJECT_SUBSCRIPTION,
+ .nparams = 1,
+ .parameters = {topics},
+};
+COMMAND_REGISTER(command_subscription_create); \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/commands.c b/hicn-light/src/hicn/config/commands.c
new file mode 100644
index 000000000..e99e0b8f5
--- /dev/null
+++ b/hicn-light/src/hicn/config/commands.c
@@ -0,0 +1,1530 @@
+/*
+ * 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.
+ */
+
+/**
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <hicn/core/connection.h>
+#include <hicn/core/connection_table.h>
+#include <hicn/core/forwarder.h>
+//#include <hicn/core/system.h>
+#ifdef WITH_MAPME
+#include <hicn/core/mapme.h>
+#endif /* WITH_MAPME */
+
+#include <hicn/core/listener.h> //the listener list
+#include <hicn/core/listener_table.h>
+#include <hicn/core/subscription.h>
+#include <hicn/ctrl/hicn-light-ng.h>
+#include <hicn/utils/punting.h>
+#include <hicn/util/log.h>
+#include <hicn/validation.h>
+#include <hicn/face.h>
+
+#include "commands.h"
+#include "configuration.h"
+
+#define ETHERTYPE 0x0801
+#define DEFAULT_COST 1
+#define DEFAULT_PORT 1234
+
+#define make_ack(msg) ((msg_header_t *)msg)->header.message_type = ACK_LIGHT
+#define make_nack(msg) ((msg_header_t *)msg)->header.message_type = NACK_LIGHT
+
+#define msg_malloc_list(msg, COMMAND_ID, N, seq_number) \
+ do { \
+ msg = calloc(1, sizeof((msg)->header) + N * sizeof((msg)->payload)); \
+ (msg)->header.message_type = RESPONSE_LIGHT; \
+ (msg)->header.command_id = (COMMAND_ID); \
+ (msg)->header.length = (uint16_t)(N); \
+ (msg)->header.seq_num = (seq_number); \
+ } while (0);
+
+// conn_id = UINT_MAX when symbolic_name is not found
+static inline unsigned _symbolic_to_conn_id(forwarder_t *forwarder,
+ const char *symbolic_or_connid,
+ bool allow_self,
+ unsigned ingress_id) {
+ unsigned conn_id;
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
+
+ if (allow_self && strcmp(symbolic_or_connid, "SELF") == 0) {
+ conn_id = ingress_id;
+ } else if (is_number(symbolic_or_connid, SYMBOLIC_NAME_LEN)) {
+ // case for conn_id as input
+ // XXX type issue ! XXX No check, see man
+ unsigned id = atoi(symbolic_or_connid);
+ if (id < 0) return CONNECTION_ID_UNDEFINED;
+ conn_id = id;
+
+ if (!connection_table_validate_id(table, conn_id)) {
+ ERROR("ConnID not found, check list connections");
+ conn_id = CONNECTION_ID_UNDEFINED;
+ }
+ } 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);
+ if (connection_id_is_valid(conn_id)) {
+ DEBUG("Resolved symbolic name '%s' to conn_id %u", symbolic_or_connid,
+ conn_id);
+ } else {
+ WARN("Symbolic name '%s' could not be resolved", symbolic_or_connid);
+ }
+ }
+
+ return conn_id;
+}
+
+#define symbolic_to_conn_id(forwarder, symbolic) \
+ _symbolic_to_conn_id(forwarder, symbolic, false, 0)
+
+#define symbolic_to_conn_id_self(forwarder, symbolic, ingress_id) \
+ _symbolic_to_conn_id(forwarder, symbolic, true, ingress_id)
+
+connection_t *getConnectionBySymbolicOrId(forwarder_t *forwarder,
+ const char *symbolic_or_connid) {
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ unsigned conn_id = symbolic_to_conn_id(forwarder, symbolic_or_connid);
+ if (!connection_id_is_valid(conn_id)) return NULL;
+
+ /* conn_id is assumed validated here */
+ return connection_table_at(table, conn_id);
+}
+
+/* Listener */
+
+uint8_t *configuration_on_listener_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: listener add (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_listener_add_t *msg = (msg_listener_add_t *)packet;
+ cmd_listener_add_t *control = &msg->payload;
+
+ switch (control->type) {
+ case FACE_TYPE_UDP_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_HICN_LISTENER:
+ break;
+ default:
+ goto NACK;
+ }
+
+ listener_table_t *table = forwarder_get_listener_table(forwarder);
+ assert(table);
+
+ /* Verify that the listener DOES NOT exist */
+ listener_t *listener = listener_table_get_by_name(table, control->symbolic);
+ if (listener) {
+ ERROR("Listener with name=%s already exists", control->symbolic);
+ goto NACK;
+ }
+
+ address_t address;
+ if (address_from_ip_port(&address, control->family, &control->address,
+ control->port) < 0) {
+ WARN(
+ "Unsupported address type for HICN (ingress id %u): "
+ "must be either IPV4 or IPV6",
+ ingress_id);
+ goto NACK;
+ }
+
+ if (!face_type_is_defined(control->type)) {
+ WARN("[configuration_on_listener_add] Invalid listener type");
+ goto NACK;
+ }
+
+ listener = listener_table_get_by_address(table, control->type, &address);
+ if (listener) {
+ char addr_str[NI_MAXHOST];
+ int port;
+ address_to_string(&address, addr_str, &port);
+ ERROR("Listener for address=%s, type=%s already exists", addr_str,
+ face_type_str(control->type));
+ goto NACK;
+ }
+
+ // NOTE: interface_name is expected NULL for hICN listener
+
+ listener = listener_create(control->type, &address, control->interface_name,
+ control->symbolic, forwarder);
+ if (!listener) goto NACK;
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+unsigned symbolic_to_listener_id(forwarder_t *forwarder,
+ const char *symbolic_or_listener_id) {
+ unsigned listener_id;
+ const listener_table_t *table = forwarder_get_listener_table(forwarder);
+
+ if (is_number(symbolic_or_listener_id, SYMBOLIC_NAME_LEN)) {
+ // XXX type issue ! XXX No check, see man
+ unsigned id = atoi(symbolic_or_listener_id);
+ if (id < 0) return LISTENER_ID_UNDEFINED;
+ listener_id = id;
+
+ if (!listener_table_validate_id(table, listener_id)) {
+ ERROR("Listener ID %d not found", id);
+ listener_id = LISTENER_ID_UNDEFINED;
+ }
+ } 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);
+ if (listener_id_is_valid(listener_id)) {
+ DEBUG("Resolved symbolic name '%s' to conn_id %u",
+ symbolic_or_listener_id, listener_id);
+ } else {
+ WARN("Symbolic name '%s' could not be resolved", symbolic_or_listener_id);
+ }
+ }
+
+ return listener_id;
+}
+
+uint8_t *configuration_on_listener_remove(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: listener remove (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_listener_remove_t *msg = (msg_listener_remove_t *)packet;
+ cmd_listener_remove_t *control = &msg->payload;
+
+ unsigned listener_id =
+ symbolic_to_listener_id(forwarder, control->symbolicOrListenerid);
+ if (!listener_id_is_valid(listener_id)) {
+ ERROR("Invalid listener id=%u", listener_id);
+ goto NACK;
+ }
+
+ listener_table_t *listener_table = forwarder_get_listener_table(forwarder);
+ listener_t *listener = listener_table_get_by_id(listener_table, listener_id);
+ if (!listener) {
+ ERROR("Listener ID not found, check list listeners");
+ goto NACK;
+ }
+
+ // Do not remove listener if it is the one curretly used to send the command
+ connection_table_t *conn_table = forwarder_get_connection_table(forwarder);
+ connection_t *curr_connection =
+ connection_table_get_by_id(conn_table, ingress_id);
+ const address_pair_t *pair = connection_get_pair(curr_connection);
+ if (address_equals(listener_get_address(listener),
+ address_pair_get_local(pair))) {
+ ERROR("Cannot remove current listener");
+ goto NACK;
+ }
+
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *connection;
+ connection_table_foreach(table, connection, {
+ const address_pair_t *pair = connection_get_pair(connection);
+ if (!address_equals(listener_get_address(listener),
+ address_pair_get_local(pair)))
+ continue;
+
+ unsigned conn_id = connection_table_get_connection_id(table, connection);
+ /* Remove connection from the FIB */
+ forwarder_remove_connection_id_from_routes(forwarder, conn_id);
+
+ /* Remove connection */
+ connection_table_remove_by_id(table, conn_id);
+ });
+
+ /* Remove listener */
+ listener_table_remove_by_id(listener_table, listener_id);
+ listener_finalize(listener);
+ WITH_DEBUG(listener_table_print_by_key(listener_table);)
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+// TODO(eloparco): Unused forwarder param
+static inline void fill_listener_command(forwarder_t *forwarder,
+ listener_t *listener,
+ cmd_listener_list_item_t *cmd) {
+ assert(forwarder);
+ assert(listener);
+ assert(cmd);
+
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ const address_t *addr = listener_get_address(listener);
+
+ cmd->id = (uint32_t)listener_get_id(listener);
+ cmd->type = (uint8_t)listener_get_type(listener);
+
+ switch (addr->as_ss.ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)addr;
+ cmd->family = AF_INET;
+ cmd->address.v4.as_inaddr = sin->sin_addr;
+ cmd->port = sin->sin_port;
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)addr;
+ cmd->family = AF_INET6;
+ cmd->address.v6.as_in6addr = sin6->sin6_addr;
+ cmd->port = sin6->sin6_port;
+ break;
+ default:
+ break;
+ }
+
+ const char *name = listener_get_name(listener);
+ snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", name);
+ const char *interface_name = listener_get_interface_name(listener);
+ snprintf(cmd->interface_name, SYMBOLIC_NAME_LEN, "%s", interface_name);
+}
+
+uint8_t *configuration_on_listener_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: listener list (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ listener_table_t *table = forwarder_get_listener_table(forwarder);
+ size_t n = listener_table_len(table);
+ msg_listener_list_t *msg_received = (msg_listener_list_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;
+
+ cmd_listener_list_item_t *payload = &msg->payload;
+ listener_t *listener;
+ listener_table_foreach(table, listener, {
+ fill_listener_command(forwarder, listener, 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;
+}
+
+/* Connection */
+
+uint8_t *configuration_on_connection_add(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: connection add (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_connection_add_t *msg = (msg_connection_add_t *)packet;
+ cmd_connection_add_t *control = &msg->payload;
+
+ switch (control->type) {
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_HICN:
+ break;
+ default:
+ 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;
+ }
+
+ address_pair_t pair;
+ if (address_pair_from_ip_port(&pair, control->family, &control->local_ip,
+ control->local_port, &control->remote_ip,
+ control->remote_port) < 0)
+ goto NACK;
+
+ connection_t *connection = connection_table_get_by_pair(table, &pair);
+#ifdef WITH_MAPME
+ connection_event_t event;
+#endif /* WITH_MAPME */
+
+ if (!connection) {
+ connection =
+ connection_create(control->type, symbolic_name, &pair, forwarder);
+ if (!connection) {
+ ERROR("Failed to create %s connection", face_type_str(control->type));
+ goto NACK;
+ }
+
+#ifdef WITH_MAPME
+ event = CONNECTION_EVENT_CREATE;
+#endif /* WITH_MAPME */
+ } else {
+ WARN("Connection already exists");
+
+#ifdef WITH_MAPME
+ event = CONNECTION_EVENT_UPDATE;
+#endif /* WITH_MAPME */
+ }
+
+#ifdef WITH_POLICY
+ connection_set_tags(connection, control->tags);
+ connection_set_priority(connection, control->priority);
+#endif /* WITH_POLICY */
+
+ connection_set_admin_state(connection, control->admin_state);
+
+#ifdef WITH_MAPME
+ /* Hook: new connection created through the control protocol */
+ forwarder_on_connection_event(forwarder, connection, event);
+#endif /* WITH_MAPME */
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/**
+ * Add an IP-based tunnel.
+ *
+ * The call can fail if the symbolic name is a duplicate. It could also fail if
+ * there's an problem creating the local side of the tunnel (i.e. the local
+ * socket address is not usable).
+ *
+ * @return true Tunnel added
+ * @return false Tunnel not added (an error)
+ */
+
+uint8_t *configuration_on_connection_remove(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: connection remove (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_connection_remove_t *msg = (msg_connection_remove_t *)packet;
+ cmd_connection_remove_t *control = &msg->payload;
+
+ unsigned conn_id = symbolic_to_conn_id_self(
+ forwarder, control->symbolic_or_connid, ingress_id);
+ if (!connection_id_is_valid(conn_id)) {
+ ERROR("Invalid connection id=%u", conn_id);
+ goto NACK;
+ }
+
+ if (strcmp(control->symbolic_or_connid, "SELF") != 0 &&
+ conn_id == ingress_id) {
+ ERROR("Cannot remove current connection");
+ goto NACK;
+ }
+
+ /* Remove connection from the FIB */
+ forwarder_remove_connection_id_from_routes(forwarder, conn_id);
+
+ /* Remove connection */
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *connection = connection_table_get_by_id(table, conn_id);
+ connection_table_remove_by_id(table, conn_id);
+
+ // Don't close the fd for SELF otherwise it won't be possible
+ // to send the reply back
+ if (strcmp(control->symbolic_or_connid, "SELF") != 0)
+ connection_finalize(connection);
+ WITH_DEBUG(connection_table_print_by_pair(table);)
+
+#ifdef WITH_MAPME
+ /* Hook: new connection created through the control protocol */
+ forwarder_on_connection_event(forwarder, NULL, CONNECTION_EVENT_DELETE);
+#endif /* WITH_MAPME */
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+static inline void tolower_str(char *str) {
+ char *p = str;
+ for (; *p; p++) *p = tolower(*p);
+}
+
+// TODO(eloparco): Forwarder param not used
+static inline void fill_connections_command(forwarder_t *forwarder,
+ connection_t *connection,
+ cmd_connection_list_item_t *cmd) {
+ assert(forwarder);
+ assert(connection);
+ assert(cmd);
+
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ const address_pair_t *pair = connection_get_pair(connection);
+
+ cmd->id = connection_get_id(connection),
+ cmd->state = connection_get_state(connection),
+ cmd->admin_state = connection_get_admin_state(connection),
+ cmd->type = connection_get_type(connection),
+#ifdef WITH_POLICY
+ cmd->priority = connection_get_priority(connection),
+ cmd->tags = connection_get_tags(connection),
+#endif /* WITH_POLICY */
+
+ snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", connection_get_name(connection));
+ tolower_str(cmd->name);
+
+ snprintf(cmd->interface_name, SYMBOLIC_NAME_LEN, "%s",
+ connection_get_interface_name(connection));
+
+ switch (pair->local.as_ss.ss_family) {
+ case AF_INET:
+ cmd->family = AF_INET;
+
+ sin = (struct sockaddr_in *)(&pair->local);
+ cmd->local_port = sin->sin_port;
+ cmd->local_addr.v4.as_inaddr = sin->sin_addr;
+
+ sin = (struct sockaddr_in *)(&pair->remote);
+ cmd->remote_port = sin->sin_port;
+ cmd->remote_addr.v4.as_inaddr = sin->sin_addr;
+ break;
+
+ case AF_INET6:
+ cmd->family = AF_INET6;
+
+ sin6 = (struct sockaddr_in6 *)(&pair->local);
+ cmd->local_port = sin6->sin6_port;
+ cmd->local_addr.v6.as_in6addr = sin6->sin6_addr;
+
+ sin6 = (struct sockaddr_in6 *)(&pair->remote);
+ cmd->remote_port = sin6->sin6_port;
+ cmd->remote_addr.v6.as_in6addr = sin6->sin6_addr;
+ break;
+
+ default:
+ break;
+ }
+}
+
+uint8_t *configuration_on_connection_list(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: connection list (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ 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_connection_list_t *msg_received = (msg_connection_list_t *)packet;
+ 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;
+
+ cmd_connection_list_item_t *payload = &msg->payload;
+ connection_t *connection;
+ connection_table_foreach(table, connection, {
+ if (connection->id == ingress_id) continue;
+ fill_connections_command(forwarder, 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;
+}
+
+uint8_t *configuration_on_connection_set_admin_state(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+ msg_connection_set_admin_state_t *msg =
+ (msg_connection_set_admin_state_t *)packet;
+ cmd_connection_set_admin_state_t *control = &msg->payload;
+
+ if ((control->admin_state != FACE_STATE_UP) &&
+ (control->admin_state != FACE_STATE_DOWN))
+ goto NACK;
+
+ connection_t *conn =
+ getConnectionBySymbolicOrId(forwarder, control->symbolic_or_connid);
+ if (!conn) goto NACK;
+
+ connection_set_admin_state(conn, control->admin_state);
+
+#ifdef WITH_MAPME
+ /* Hook: connection event */
+ forwarder_on_connection_event(forwarder, conn,
+ control->admin_state == FACE_STATE_UP
+ ? CONNECTION_EVENT_SET_UP
+ : CONNECTION_EVENT_SET_DOWN);
+#endif /* WITH_MAPME */
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_connection_update(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+#ifdef WITH_POLICY
+ msg_connection_update_t *msg = (msg_connection_update_t *)packet;
+ cmd_connection_update_t *control = &msg->payload;
+
+ connection_t *conn =
+ getConnectionBySymbolicOrId(forwarder, control->symbolic_or_connid);
+ if (!conn) goto NACK;
+
+ connection_set_tags(conn, control->tags);
+ connection_set_admin_state(conn, control->admin_state);
+ if (control->priority > 0) connection_set_priority(conn, control->priority);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_connection_set_priority(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+#ifdef WITH_POLICY
+ msg_connection_set_priority_t *msg = (msg_connection_set_priority_t *)packet;
+ cmd_connection_set_priority_t *control = &msg->payload;
+
+ connection_t *conn =
+ getConnectionBySymbolicOrId(forwarder, control->symbolic_or_connid);
+ if (!conn) goto NACK;
+
+ connection_set_priority(conn, control->priority);
+
+#ifdef WITH_MAPME
+ /* Hook: connection event */
+ forwarder_on_connection_event(forwarder, conn,
+ CONNECTION_EVENT_PRIORITY_CHANGED);
+#endif /* WITH_MAPME */
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_connection_set_tags(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+#ifdef WITH_POLICY
+ msg_connection_set_tags_t *msg = (msg_connection_set_tags_t *)packet;
+ cmd_connection_set_tags_t *control = &msg->payload;
+
+ connection_t *conn =
+ getConnectionBySymbolicOrId(forwarder, control->symbolic_or_connid);
+ if (!conn) goto NACK;
+
+ connection_set_tags(conn, control->tags);
+
+#ifdef WITH_MAPME
+ /* Hook: connection event */
+ forwarder_on_connection_event(forwarder, conn, CONNECTION_EVENT_TAGS_CHANGED);
+#endif /* WITH_MAPME */
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/* Route */
+
+uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ INFO("CMD: route add (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_route_add_t *msg = (msg_route_add_t *)packet;
+ cmd_route_add_t *control = &msg->payload;
+
+ unsigned conn_id = symbolic_to_conn_id_self(
+ forwarder, control->symbolic_or_connid, ingress_id);
+ if (!connection_id_is_valid(conn_id)) goto NACK;
+
+ ip_prefix_t prefix = {.family = control->family,
+ .address = control->address,
+ .len = control->len};
+
+ if (!forwarder_add_or_update_route(forwarder, &prefix, conn_id)) goto NACK;
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_route_remove(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: route remove (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_route_remove_t *msg = (msg_route_remove_t *)packet;
+ cmd_route_remove_t *control = &msg->payload;
+
+ unsigned conn_id =
+ symbolic_to_conn_id(forwarder, control->symbolic_or_connid);
+ if (!connection_id_is_valid(conn_id)) goto NACK;
+
+ ip_prefix_t prefix = {.family = control->family,
+ .address = control->address,
+ .len = control->len};
+
+ if (!forwarder_remove_route(forwarder, &prefix, conn_id)) goto NACK;
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ INFO("CMD: route list (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ msg_route_list_t *msg_received = (msg_route_list_t *)packet;
+ uint8_t command_id = msg_received->header.command_id;
+ uint32_t seq_num = msg_received->header.seq_num;
+ const fib_t *fib = forwarder_get_fib(forwarder);
+ fib_entry_t *entry;
+
+ /*
+ * Two step approach to precompute the number of entries to allocate
+ *
+ * NOTE: we might have routes with no or multiple next hops.
+ */
+ size_t n = 0;
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops));
+ n += nexthops_get_len(nexthops);
+ });
+
+ msg_route_list_reply_t *msg;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_route_list_item_t *payload = &msg->payload;
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops));
+ size_t num_nexthops = nexthops_get_len(nexthops);
+
+ if (num_nexthops == 0) continue;
+
+ NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry));
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ address_t address;
+ nameBitvector_ToAddress(prefix, &address);
+ switch (address_family(&address)) {
+ case AF_INET:
+ payload->family = AF_INET;
+ payload->address.v4.as_inaddr = address4_ip(&address);
+ break;
+ case AF_INET6:
+ payload->family = AF_INET6;
+ payload->address.v6.as_in6addr = address6_ip(&address);
+ break;
+ default:
+ break;
+ }
+ payload->connection_id = nexthop;
+ payload->len = nameBitvector_GetLength(prefix);
+ payload->cost = DEFAULT_COST;
+
+ 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;
+}
+
+/* Cache */
+
+uint8_t *configuration_on_cache_set_store(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: cache set store (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_cache_set_store_t *msg = (msg_cache_set_store_t *)packet;
+ cmd_cache_set_store_t *control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1)) goto NACK;
+ bool value = (bool)control->activate;
+
+ forwarder_cs_set_store(forwarder, value);
+ assert(forwarder_cs_get_store(forwarder) == value);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_cache_set_serve(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: cache set serve (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_cache_set_serve_t *msg = (msg_cache_set_serve_t *)packet;
+ cmd_cache_set_serve_t *control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1)) goto NACK;
+ bool value = (bool)control->activate;
+
+ forwarder_cs_set_serve(forwarder, value);
+ assert(forwarder_cs_get_serve(forwarder) == value);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_cache_clear(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ INFO("CMD: cache clear (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_cache_clear_t *msg = (msg_cache_clear_t *)packet;
+
+ forwarder_cs_clear(forwarder);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_cache_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ INFO("CMD: cache list (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ msg_cache_list_t *msg_received = (msg_cache_list_t *)packet;
+ uint32_t seq_num = msg_received->header.seq_num;
+
+ msg_cache_list_reply_t *msg = malloc(sizeof(*msg));
+ *msg = (msg_cache_list_reply_t){
+ .header = {.message_type = RESPONSE_LIGHT,
+ .length = 1,
+ .seq_num = seq_num},
+ .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)}};
+
+ *reply_size = sizeof(*msg);
+ return (uint8_t *)msg;
+}
+
+/* Strategy */
+
+uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: strategy set (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_strategy_set_t *msg = (msg_strategy_set_t *)packet;
+ cmd_strategy_set_t *control = &msg->payload;
+
+ char prefix_s[MAXSZ_IP_PREFIX];
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len,
+ };
+ int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) goto NACK;
+
+ strategy_type_t strategy = control->type;
+ configuration_t *config = forwarder_get_configuration(forwarder);
+ strategy_type_t existingFwdStrategy =
+ configuration_get_strategy(config, prefix_s);
+ strategy_options_t *options = NULL;
+
+ Name name_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&name_prefix, control->family, control->address,
+ control->len);
+
+ // The strategy is not present in the hash table
+ // or has to be updated or to be restarted
+ if (existingFwdStrategy == STRATEGY_TYPE_UNDEFINED ||
+ strategy != existingFwdStrategy ||
+ (strategy == existingFwdStrategy && strategy == STRATEGY_TYPE_BESTPATH)) {
+ configuration_set_strategy(config, prefix_s, strategy);
+
+ forwarder_set_strategy(forwarder, &name_prefix, strategy, options);
+ } else {
+ WITH_WARN({
+ char *nameString = name_ToString(&name_prefix);
+ WARN("Strategy for prefix %s not updated", nameString);
+ free(nameString);
+ })
+ }
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_strategy_add_local_prefix(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: strategy add local prefix (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_strategy_add_local_prefix_t *msg =
+ (msg_strategy_add_local_prefix_t *)packet;
+ cmd_strategy_add_local_prefix_t *control = &msg->payload;
+
+ char prefix_s[MAXSZ_IP_PREFIX];
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len,
+ };
+ int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) goto NACK;
+
+ strategy_type_t strategy = control->type;
+ configuration_t *config = forwarder_get_configuration(forwarder);
+ strategy_type_t existingFwdStrategy =
+ configuration_get_strategy(config, prefix_s);
+
+ if (strategy != existingFwdStrategy) goto NACK;
+
+ if (strategy != STRATEGY_TYPE_BESTPATH &&
+ strategy != STRATEGY_TYPE_REPLICATION)
+ goto NACK;
+
+ Name name_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&name_prefix, control->family, control->address,
+ control->len);
+
+ strategy_options_t options;
+ Name local_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&local_prefix, control->local_family,
+ control->local_address, control->local_len);
+
+ // for the moment bestpath and replication are the same but we distinguish the
+ // two in case they will diverge in the future
+ if (strategy == STRATEGY_TYPE_BESTPATH) {
+ options.bestpath.local_prefixes = create_local_prefixes();
+ local_prefixes_add_prefix(options.bestpath.local_prefixes, &local_prefix);
+ } else {
+ options.replication.local_prefixes = create_local_prefixes();
+ local_prefixes_add_prefix(options.replication.local_prefixes,
+ &local_prefix);
+ }
+
+ forwarder_add_strategy_options(forwarder, &name_prefix, strategy, &options);
+
+ free_local_prefixes(options.bestpath.local_prefixes);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/* WLDR */
+
+uint8_t *configuration_on_wldr_set(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+ msg_wldr_set_t *msg = (msg_wldr_set_t *)packet;
+ cmd_wldr_set_t *control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1)) goto NACK;
+ bool value = (bool)control->activate;
+
+ unsigned conn_id =
+ symbolic_to_conn_id(forwarder, control->symbolic_or_connid);
+ if (!connection_id_is_valid(conn_id)) goto NACK;
+
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *conn = connection_table_at(table, conn_id);
+
+ if (value) connection_wldr_enable(conn, value);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/* Punting */
+
+uint8_t *configuration_on_punting_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ // #if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
+ msg_punting_add_t *msg = (msg_punting_add_t *)packet;
+
+#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
+ cmd_punting_add_t *control = &msg->payload;
+ if (ip_address_empty(&control->address)) goto NACK;
+
+ /* This is for hICN listeners only */
+ // XXX add check !
+ // comments:
+ // EncapType: I use the Hicn encap since the punting is available only for
+ // Hicn listeners LocalAddress: The only listern for which we need punting
+ // rules is the main one, which has no address
+ // so I create a fake empty address. This need to be consistent
+ // with the address set at creation time
+ address_t fakeaddr;
+ memset(&fakeaddr, 0, sizeof(address_t));
+ fakeaddr = ADDRESS_ANY(control->family, DEFAULT_PORT);
+
+ listener_table_t *table = forwarder_get_listener_table(forwarder);
+ listener_t *listener =
+ listener_table_get_by_address(table, FACE_TYPE_HICN, &fakeaddr);
+ if (!listener) {
+ ERROR("the main listener does not exist");
+ goto NACK;
+ }
+
+ ip_prefix_t prefix = {.family = control->family,
+ .address = control->address,
+ .len = control->len};
+ char prefix_s[MAXSZ_IP_PREFIX];
+ int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) goto NACK;
+
+ if (listener_punt(listener, prefix_s) < 0) {
+ ERROR("error while adding the punting rule");
+ goto NACK;
+ }
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/* MAP-Me */
+
+#ifdef WITH_MAPME
+uint8_t *configuration_on_mapme_enable(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: mapme enable (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_mapme_enable_t *msg = (msg_mapme_enable_t *)packet;
+ cmd_mapme_enable_t *control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1)) goto NACK;
+ bool value = (bool)control->activate;
+
+ INFO("MAP-Me SET enable: %s", value ? "on" : "off");
+ mapme_t *mapme = forwarder_get_mapme(forwarder);
+ if (!mapme) goto NACK;
+ mapme_set_enable(mapme, value);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_mapme_set_discovery(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: mapme discovery (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_mapme_set_discovery_t *msg = (msg_mapme_set_discovery_t *)packet;
+ cmd_mapme_set_discovery_t *control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1)) goto NACK;
+ bool value = (bool)control->activate;
+
+ INFO("MAP-Me SET discovery: %s", value ? "on" : "off");
+ mapme_t *mapme = forwarder_get_mapme(forwarder);
+ if (!mapme) goto NACK;
+ mapme_set_discovery(mapme, value);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_mapme_set_timescale(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: mapme timescale (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_mapme_set_timescale_t *msg = (msg_mapme_set_timescale_t *)packet;
+ cmd_mapme_set_timescale_t *control = &msg->payload;
+
+ INFO("MAP-Me SET timescale: %u", control->timePeriod);
+ mapme_t *mapme = forwarder_get_mapme(forwarder);
+ if (!mapme) goto NACK;
+ mapme_set_timescale(mapme, control->timePeriod);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_mapme_set_retx(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: mapme retransmission (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_mapme_set_retx_t *msg = (msg_mapme_set_retx_t *)packet;
+ cmd_mapme_set_retx_t *control = &msg->payload;
+
+ INFO("MAP-Me SET retx: %u", control->timePeriod);
+ mapme_t *mapme = forwarder_get_mapme(forwarder);
+ if (!mapme) goto NACK;
+ mapme_set_retransmision(mapme, control->timePeriod);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_mapme_send_update(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+ INFO("CMD: mapme send update (ingress=%d)", ingress_id);
+ msg_mapme_send_update_t *msg = (msg_mapme_send_update_t *)packet;
+
+ *reply_size = sizeof(msg_header_t);
+
+ fib_t *fib = forwarder_get_fib(forwarder);
+ if (!fib) goto NACK;
+
+ mapme_t *mapme = forwarder_get_mapme(forwarder);
+
+ /*
+ * The command triggers a mapme update for all prefixes produced on this face
+ * */
+ fib_entry_t *entry;
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ if (nexthop != ingress_id) continue;
+ /* This entry points to the producer face */
+ mapme_set_all_adjacencies(mapme, entry);
+ break;
+ });
+ });
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+#endif /* WITH_MAPME */
+
+/* Policy */
+
+uint8_t *configuration_on_policy_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+#ifdef WITH_POLICY
+ msg_policy_add_t *msg = (msg_policy_add_t *)packet;
+ cmd_policy_add_t *control = &msg->payload;
+
+ ip_prefix_t prefix = {.family = control->family,
+ .address = control->address,
+ .len = control->len};
+
+ if (!forwarder_add_or_update_policy(forwarder, &prefix, &control->policy))
+ goto NACK;
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_policy_remove(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+#ifdef WITH_POLICY
+ msg_policy_remove_t *msg = (msg_policy_remove_t *)packet;
+ cmd_policy_remove_t *control = &msg->payload;
+
+ ip_prefix_t prefix = {.family = control->family,
+ .address = control->address,
+ .len = control->len};
+
+ if (!forwarder_remove_policy(forwarder, &prefix)) goto NACK;
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+ const fib_t *fib = forwarder_get_fib(forwarder);
+ assert(fib);
+ size_t n = fib_get_size(fib);
+
+#ifdef WITH_POLICY
+ msg_policy_list_t *msg_received = (msg_policy_list_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_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_policy_list_item_t *payload = &msg->payload;
+
+ fib_entry_t *entry;
+
+ fib_foreach_entry(fib, entry, {
+ NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry));
+ address_t address;
+ nameBitvector_ToAddress(prefix, &address);
+
+ switch (address_family(&address)) {
+ case AF_INET:
+ payload->family = AF_INET;
+ payload->address.v4.as_inaddr = address4_ip(&address);
+ break;
+
+ case AF_INET6:
+ payload->family = AF_INET6;
+ payload->address.v6.as_in6addr = address6_ip(&address);
+ break;
+
+ default:
+ break;
+ }
+ payload->len = nameBitvector_GetLength(prefix);
+ payload->policy = fib_entry_get_policy(entry);
+
+ payload++;
+ });
+
+ return (uint8_t *)msg;
+#endif /* WITH_POLICY */
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/* Subscription */
+
+uint8_t *configuration_on_subscription_add(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: subscription add (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_subscription_add_t *msg = (msg_subscription_add_t *)packet;
+ cmd_subscription_add_t *control = &msg->payload;
+ hc_topics_t topics = control->topics;
+
+ subscription_table_t *subscriptions = forwarder_get_subscriptions(forwarder);
+ assert(subscriptions);
+
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ ingress_id);
+ if (ret < 0) goto NACK;
+
+ WITH_DEBUG(subscription_table_print(subscriptions);)
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_subscription_remove(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ INFO("CMD: subscription remove (ingress=%d)", ingress_id);
+ assert(forwarder);
+ assert(packet);
+
+ *reply_size = sizeof(msg_header_t);
+ msg_subscription_add_t *msg = (msg_subscription_add_t *)packet;
+ cmd_subscription_add_t *control = &msg->payload;
+ hc_topics_t topics = control->topics;
+
+ subscription_table_t *subscriptions = forwarder_get_subscriptions(forwarder);
+ assert(subscriptions);
+
+ subscription_table_remove_topics_for_connection(subscriptions, topics,
+ ingress_id);
+ WITH_DEBUG(subscription_table_print(subscriptions);)
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet,
+ command_type_t command_type, unsigned ingress_id,
+ size_t *reply_size) {
+ uint8_t *reply = NULL;
+
+ /*
+ * For most commands, the packet will simply be transformed into an ack.
+ * For list commands, a new message will be allocated, and the return value
+ * might eventually be NULL in case of an error. That is why the free the
+ * reply at the end in these circumstances.
+ *
+ * XXX rework this part.
+ */
+ switch (command_type) {
+#define _(l, u) \
+ case COMMAND_TYPE_##u: \
+ reply = configuration_on_##l(forwarder, packet, ingress_id, reply_size); \
+ assert(reply); \
+ break;
+ foreach_command_type
+#undef _
+ case COMMAND_TYPE_UNDEFINED : case COMMAND_TYPE_N
+ : ERROR("Unexpected command type");
+ reply = packet;
+ make_nack(reply);
+ if (reply_size) *reply_size = sizeof(msg_header_t);
+ break;
+ }
+
+ return reply;
+}
+
+ssize_t command_process_msgbuf(forwarder_t *forwarder, msgbuf_t *msgbuf) {
+ assert(forwarder);
+ assert(msgbuf);
+
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ unsigned ingress_id = msgbuf_get_connection_id(msgbuf);
+
+ uint8_t *reply = NULL;
+ size_t reply_size = 0;
+
+ command_type_t command_type = msgbuf_get_command_type(msgbuf);
+
+ reply =
+ command_process(forwarder, packet, command_type, ingress_id, &reply_size);
+ if (connection_id_is_valid(msgbuf->connection_id)) {
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ const connection_t *connection = connection_table_at(table, ingress_id);
+ connection_send_packet(connection, reply, reply_size);
+ }
+
+ switch (msgbuf->command.type) {
+ case COMMAND_TYPE_LISTENER_LIST:
+ case COMMAND_TYPE_CONNECTION_LIST:
+ case COMMAND_TYPE_ROUTE_LIST:
+ case COMMAND_TYPE_POLICY_LIST:
+ /* Free replies that have been allocated (not NACK's) */
+ if (((msg_header_t *)reply)->header.message_type != NACK_LIGHT)
+ free(reply);
+ break;
+ default:
+ break;
+ }
+
+ return msgbuf_get_len(msgbuf);
+}
diff --git a/hicn-light/src/hicn/config/commands.h b/hicn-light/src/hicn/config/commands.h
new file mode 100644
index 000000000..cedf4de01
--- /dev/null
+++ b/hicn-light/src/hicn/config/commands.h
@@ -0,0 +1,152 @@
+/*
+ * 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 commands.h
+ * @brief hicn-light configuration, such as in-band commands or CLI
+ *
+ * Manages all user configuration of the system, such as from the CLI or web
+ * interface It remembers the user commands and will be able to write out a
+ * config file.
+ *
+ */
+
+#ifndef HICNLIGHT_COMMANDS_H
+#define HICNLIGHT_COMMANDS_H
+
+#include "../core/msgbuf.h"
+#include "../core/strategy.h"
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/hicn-light-ng.h>
+
+uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet,
+ command_type_t command_type, unsigned ingress_id,
+ size_t *reply_size);
+
+ssize_t command_process_msgbuf(forwarder_t *forwarder, msgbuf_t *msgbuf);
+
+uint8_t *configuration_on_listener_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_listener_remove(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_listener_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_add(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_remove(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_list(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_set_admin_state(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_update(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_set_priority(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_connection_set_tags(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_route_remove(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_cache_set_store(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_cache_set_serve(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_cache_clear(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_strategy_add_local_prefix(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_wldr_set(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_punting_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+#ifdef WITH_MAPME
+uint8_t *configuration_on_mapme_enable(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_mapme_set_discovery(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_mapme_set_timescale(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_mapme_set_retx(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_mapme_send_update(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+#endif /* WITH_MAPME */
+
+uint8_t *configuration_on_policy_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+uint8_t *configuration_on_policy_remove(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size);
+
+uint8_t *configuration_on_policy_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.c b/hicn-light/src/hicn/config/configuration.c
index e414f05e3..9123ceebf 100644
--- a/hicn-light/src/hicn/config/configuration.c
+++ b/hicn-light/src/hicn/config/configuration.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,1504 +26,169 @@
#include <unistd.h>
#endif
#include <ctype.h>
-#include <parc/assert/parc_Assert.h>
#include <hicn/hicn-light/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_String.h>
-
-#include <hicn/config/configurationListeners.h>
-#include <hicn/config/symbolicNameTable.h>
-
#include <hicn/core/connection.h>
-#include <hicn/core/connectionTable.h>
+#include <hicn/core/connection_table.h>
#include <hicn/core/forwarder.h>
-#include <hicn/core/system.h>
+//#include <hicn/core/system.h>
#ifdef WITH_MAPME
#include <hicn/core/mapme.h>
#endif /* WITH_MAPME */
-#include <hicn/io/streamConnection.h>
-
-#include <hicn/io/hicnTunnel.h>
-#include <hicn/io/tcpTunnel.h>
-#include <hicn/io/udpTunnel.h>
+#include <hicn/core/listener.h> //the listener list
+#include <hicn/core/listener_table.h>
+#include <hicn/ctrl/hicn-light-ng.h>
+#include <hicn/utils/punting.h>
+#include <hicn/util/log.h>
+#include <hicn/face.h>
-#include <parc/algol/parc_Unsigned.h>
-#include <hicn/io/listener.h> //the listener list
-#include <hicn/io/listenerSet.h> // needed to print
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-#include <hicn/utils/address.h>
+#include "configuration.h"
#define ETHERTYPE 0x0801
-
-struct configuration {
- Forwarder *forwarder;
- Logger *logger;
-
- size_t maximumContentObjectStoreSize;
-
- // map from prefix (parcString) to strategy (parcString)
- PARCHashMap *strategy_map;
-
- // translates between a symblic name and a connection id
- SymbolicNameTable *symbolicNameTable;
+#define DEFAULT_COST 1
+#define DEFAULT_PORT 1234
+#define DEFAULT_LOGLEVEL "info"
+#define DEFAULT_CS_CAPACITY 100000
+
+#define msg_malloc_list(msg, N, seq_number) \
+ do { \
+ msg = malloc(sizeof((msg)->header) + N * sizeof((msg)->payload)); \
+ (msg)->header.message_type = RESPONSE_LIGHT; \
+ (msg)->header.length = (uint16_t)(N); \
+ (msg)->header.seq_num = (seq_number); \
+ } while (0);
+
+struct configuration_s {
+ const char *fn_config;
+ uint16_t port;
+ uint16_t configuration_port;
+ size_t cs_capacity;
+ int loglevel;
+ const char *logfile;
+ int logfile_fd;
+ bool daemon;
+ kh_strategy_map_t *strategy_map;
};
-// ========================================================================================
-
-Connection *
-getConnectionBySymbolicOrId(Configuration * config, const char * symbolicOrConnid)
-{
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
- unsigned connid;
- Connection *conn = NULL;
-
- /* Try to resolve an eventual symbolic name as input */
- if (utils_IsNumber(symbolicOrConnid)) {
- connid = (unsigned int)strtold(symbolicOrConnid, NULL);
-
- } else {
- connid = symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid);
- if (connid == UINT32_MAX) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Symbolic name '%s' could not be resolved",
- symbolicOrConnid);
- }
- }
- }
-
- /* Get connection by ID */
- conn = (Connection *)connectionTable_FindById( table, connid);
- if (!conn) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "ConnID not found, check list connections");
- }
- }
-
- return conn;
-}
-
-// ========================================================================================
-
-Configuration *configuration_Create(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter hicn-fwd must be non-null");
- Configuration *config = parcMemory_AllocateAndClear(sizeof(Configuration));
- parcAssertNotNull(config, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Configuration));
- config->forwarder = forwarder;
- config->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- config->maximumContentObjectStoreSize = 100000;
- config->strategy_map = parcHashMap_Create();
- config->symbolicNameTable = symbolicNameTable_Create();
-
- return config;
-}
-
-void configuration_Destroy(Configuration **configPtr) {
- parcAssertNotNull(configPtr, "Parameter must be non-null double poitner");
- parcAssertNotNull(*configPtr,
- "Parameter must dereference to non-null pointer");
-
- Configuration *config = *configPtr;
- logger_Release(&config->logger);
- parcHashMap_Release(&(config->strategy_map));
- symbolicNameTable_Destroy(&config->symbolicNameTable);
- parcMemory_Deallocate((void **)&config);
- *configPtr = NULL;
-}
-
-struct iovec *configuration_ProcessRegisterHicnPrefix(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- add_route_command *control = request[1].iov_base;
-
- bool success = false;
-
- const char *symbolicOrConnid = control->symbolicOrConnid;
-
- if (strcmp(symbolicOrConnid, "SELF") == 0) {
- success = forwarder_AddOrUpdateRoute(config->forwarder, control, ingressId);
- } else if (utils_IsNumber(symbolicOrConnid)) {
- // case for connid as input
- unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL);
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
-
- // check if iconnID present in the fwd table
- if (connectionTable_FindById(table, connid)) {
- success = forwarder_AddOrUpdateRoute(config->forwarder, control, connid);
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "ConnID not found, check list connections");
- // failure
- }
-
- } else {
- // case for symbolic as input: check if symbolic name can be resolved
- unsigned connid =
- symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid);
- // connid = UINT_MAX when symbolicName is not found
- if (connid != UINT32_MAX) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Debug)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug,
- __func__, "Add route resolve name '%s' to connid %u",
- symbolicOrConnid, connid);
- }
-
- success = forwarder_AddOrUpdateRoute(config->forwarder, control, connid);
-
- } else {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Warning,
- __func__,
- "Add route symbolic name '%s' could not be resolved",
- symbolicOrConnid);
- }
- // failure
- }
- }
-
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(add_route_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(add_route_command));
- }
-
- return response;
-}
-
-struct iovec *configuration_ProcessUnregisterHicnPrefix(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- remove_route_command *control = request[1].iov_base;
-
- bool success = false;
-
- const char *symbolicOrConnid = control->symbolicOrConnid;
-
- if (utils_IsNumber(symbolicOrConnid)) {
- // case for connid as input
- unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL);
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
-
- // check if interface index present in the fwd table
- if (connectionTable_FindById(table, connid)) {
- success = forwarder_RemoveRoute(config->forwarder, control, connid);
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "ConnID not found, check list connections");
- // failure
- }
-
- } else {
- // case for symbolic as input: chech if symbolic name can be resolved
- unsigned connid =
- symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid);
- // connid = UINT_MAX when symbolicName is not found
- if (connid != UINT32_MAX) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Debug)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug,
- __func__, "Remove route resolve name '%s' to connid %u",
- symbolicOrConnid, connid);
- }
- success = forwarder_RemoveRoute(config->forwarder, control, connid);
- } else {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Warning,
- __func__,
- "Remove route symbolic name '%s' could not be resolved",
- symbolicOrConnid);
- }
- // failure
- }
- }
-
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(remove_route_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(remove_route_command));
- }
-
- return response;
-}
-
-struct iovec *configuration_ProcessRegistrationList(Configuration *config,
- struct iovec *request) {
- FibEntryList *fibList = forwarder_GetFibEntries(config->forwarder);
-
- size_t payloadSize = fibEntryList_Length(fibList);
- size_t effective_payloadSize = 0;
- size_t pointerLocation = 0;
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* = bytes granularity
- uint8_t *payloadResponse =
- parcMemory_AllocateAndClear(sizeof(list_routes_command) * payloadSize);
-
- for (size_t i = 0; i < fibEntryList_Length(fibList); i++) {
- FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i);
- NameBitvector *prefix = name_GetContentName(fibEntry_GetPrefix(entry));
- const NumberSet *nexthops = fibEntry_GetNexthops(entry);
-
- if (numberSet_Length(nexthops) == 0)
- continue;
-
- if (numberSet_Length(nexthops) > 1) {
- // payload extended, need reallocate, further entries via nexthops
- payloadSize = payloadSize + numberSet_Length(nexthops) - 1;
- payloadResponse = (uint8_t *) parcMemory_Reallocate(
- payloadResponse, sizeof(list_routes_command) * payloadSize);
- }
-
- for (size_t j = 0; j < numberSet_Length(nexthops); j++) {
- list_routes_command *listRouteCommand =
- (list_routes_command *)(payloadResponse +
- (pointerLocation *
- sizeof(list_routes_command)));
-
- Address *addressEntry = nameBitvector_ToAddress(prefix);
- if (addressGetType(addressEntry) == ADDR_INET) {
- addressGetInet(addressEntry, &tmpAddr);
- listRouteCommand->addressType = ADDR_INET;
- listRouteCommand->address.v4.as_inaddr = tmpAddr.sin_addr;
- } else if (addressGetType(addressEntry) == ADDR_INET6) {
- addressGetInet6(addressEntry, &tmpAddr6);
- listRouteCommand->addressType = ADDR_INET6;
- listRouteCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr;
- }
- listRouteCommand->connid = numberSet_GetItem(nexthops, j);
- listRouteCommand->len = nameBitvector_GetLength(prefix);
- listRouteCommand->cost = 1; // cost
-
- pointerLocation++;
- effective_payloadSize++;
- addressDestroy(&addressEntry);
- }
- }
-
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (unsigned)effective_payloadSize;
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len = sizeof(list_routes_command) * effective_payloadSize;
-
- fibEntryList_Destroy(&fibList);
- return response;
-}
-
-static void configuration_SendResponse(Configuration *config, struct iovec *msg,
- unsigned egressId) {
- ConnectionTable *connectionTable =
- forwarder_GetConnectionTable(config->forwarder);
- const Connection *conn = connectionTable_FindById(connectionTable, egressId);
-
- if (conn == NULL) {
- return;
- }
- connection_SendIOVBuffer(conn, msg, 2);
-}
-
-struct iovec *configuration_ProcessCreateTunnel(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- add_connection_command *control = request[1].iov_base;
-
- bool success = false;
-
- Connection *conn;
- const char *symbolicName = control->symbolic;
-
- Address *source = NULL;
- Address *destination = NULL;
-
- if (symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Connection symbolic name already exists");
- goto ERR;
- }
-
- if (control->ipType == ADDR_INET) {
- source =
- addressFromInaddr4Port(&control->localIp.v4.as_u32, &control->localPort);
- destination =
- addressFromInaddr4Port(&control->remoteIp.v4.as_u32, &control->remotePort);
- } else if (control->ipType == ADDR_INET6) {
- source =
- addressFromInaddr6Port(&control->localIp.v6.as_in6addr, &control->localPort);
- destination =
- addressFromInaddr6Port(&control->remoteIp.v6.as_in6addr, &control->remotePort);
- } else {
- printf("Invalid IP type.\n"); // will generate a Nack
- }
-
- AddressPair *pair = addressPair_Create(source, destination);
- conn = (Connection *)connectionTable_FindByAddressPair(
- forwarder_GetConnectionTable(config->forwarder), pair);
-
- addressPair_Release(&pair);
-
- if (!conn) {
- IoOperations *ops = NULL;
- switch (control->connectionType) {
- case TCP_CONN:
- // logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- // __func__,
- // "Unsupported tunnel protocol: TCP");
- ops = tcpTunnel_Create(config->forwarder, source, destination);
- break;
- case UDP_CONN:
- ops = udpTunnel_Create(config->forwarder, source, destination);
- break;
- case GRE_CONN:
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Unsupported tunnel protocol: GRE");
- break;
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- case HICN_CONN:
- ops = hicnTunnel_Create(config->forwarder, source, destination);
- break;
-#endif /* __APPLE__ _WIN32*/
- default:
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Unsupported tunnel protocol: %d",
- control->connectionType);
- break;
- }
-
- if (ops != NULL) {
- Connection *conn = connection_Create(ops);
-#ifdef WITH_POLICY
- connection_SetTags(conn, control->tags);
- connection_SetPriority(conn, control->priority);
-#endif /* WITH_POLICY */
+configuration_t *configuration_create() {
+ configuration_t *config = malloc(sizeof(configuration_t));
+ if (!config) return NULL;
- connection_SetAdminState(conn, control->admin_state);
-
- connectionTable_Add(forwarder_GetConnectionTable(config->forwarder),
- conn);
- symbolicNameTable_Add(config->symbolicNameTable, symbolicName,
- connection_GetConnectionId(conn));
-
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_CREATE);
-#endif /* WITH_MAPME */
-
- success = true;
-
- } else {
- printf("failed, could not create IoOperations");
- }
-
- } else {
-#ifdef WITH_POLICY
- connection_SetTags(conn, control->tags);
- connection_SetPriority(conn, control->priority);
- connection_SetAdminState(conn, control->admin_state);
-
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_UPDATE);
-#endif /* WITH_MAPME */
- if (source)
- addressDestroy(&source);
- if (destination)
- addressDestroy(&destination);
-
- success = true;
+ config->fn_config = NULL;
+ config->port = PORT_NUMBER;
+ config->configuration_port = 2001; // TODO(eloparco): What is this?
+ config->cs_capacity = DEFAULT_CS_CAPACITY;
+ config->logfile = NULL;
+ config->logfile_fd = -1;
+#ifndef _WIN32
+ config->daemon = false;
#else
- printf("failed, symbolic name or connection already exist\n");
-#endif /* WITH_POLICY */
- }
-
- if (source)
- addressDestroy(&source);
- if (destination)
- addressDestroy(&destination);
-
- if (!success)
- goto ERR;
-
- // ACK
- return utils_CreateAck(header, control, sizeof(add_connection_command));
-
-ERR:
- return utils_CreateNack(header, control, sizeof(add_connection_command));
-}
-
-struct iovec *configuration_ProcessRemoveListener(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- remove_listener_command *control = request[1].iov_base;
-
- bool success = false;
-
- const char *symbolicOrListenerid = control->symbolicOrListenerid;
- int listenerId = -1;
- ListenerSet *listenerSet = forwarder_GetListenerSet(config->forwarder);
- if (utils_IsNumber(symbolicOrListenerid)) {
- // case for connid as input
- listenerId = (unsigned)strtold(symbolicOrListenerid, NULL);
- } else {
- listenerId = listenerSet_FindIdByListenerName(listenerSet, symbolicOrListenerid);
- }
-
- if (listenerId >= 0) {
-
- ConnectionTable *connTable = forwarder_GetConnectionTable(config->forwarder);
- ListenerOps *listenerOps = listenerSet_FindById(listenerSet, listenerId);
- if (listenerOps) {
- ConnectionList *connectionList = connectionTable_GetEntries(connTable);
- for (size_t i = 0; i < connectionList_Length(connectionList); i++) {
- Connection *connection = connectionList_Get(connectionList, i);
- const AddressPair *addressPair = connection_GetAddressPair(connection);
- const Address *address = addressPair_GetLocal(addressPair);
- if (addressEquals(listenerOps->getListenAddress(listenerOps),address)) {
- // case for connid as input
- unsigned connid = connection_GetConnectionId(connection);
- // remove connection from the FIB
- forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid);
- // remove connection
- connectionTable_RemoveById(connTable, connid);
- const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid);
- symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection);
- }
- }
- connectionList_Destroy(&connectionList);
- // remove listener
- listenerSet_RemoveById(listenerSet, listenerId);
- success = true;
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "Listener Id not found, check list listeners");
- }
- }
-
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) { // ACK
- response =
- utils_CreateAck(header, control, sizeof(remove_listener_command));
- } else { // NACK
- response =
- utils_CreateNack(header, control, sizeof(remove_connection_command));
- }
-
- return response;
-}
-
-
-/**
- * Add an IP-based tunnel.
- *
- * The call cal fail if the symbolic name is a duplicate. It could also fail if
- * there's an problem creating the local side of the tunnel (i.e. the local
- * socket address is not usable).
- *
- * @return true Tunnel added
- * @return false Tunnel not added (an error)
- */
-
-struct iovec *configuration_ProcessRemoveTunnel(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- remove_connection_command *control = request[1].iov_base;
-
- bool success = false;
-
- const char *symbolicOrConnid = control->symbolicOrConnid;
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
- if (strcmp(symbolicOrConnid, "SELF") == 0) {
- forwarder_RemoveConnectionIdFromRoutes(config->forwarder, ingressId);
- connectionTable_RemoveById(table, ingressId);
-
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
-#endif /* WITH_MAPME */
-
- success = true;
- } else if (utils_IsNumber(symbolicOrConnid)) {
- // case for connid as input
- unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL);
-
- // check if interface index present in the fwd table
- //(it was missing and therefore caused a program crash)
- if (connectionTable_FindById(table, connid)) {
- // remove connection from the FIB
- forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid);
- // remove connection
- connectionTable_RemoveById(table, connid);
- // remove connection from symbolicNameTable
- const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid);
- symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection);
-
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
-#endif /* WITH_MAPME */
-
- success = true;
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "ConnID not found, check list connections");
- // failure
- }
-
- } else {
- // case for symbolic as input
- // chech if symbolic name can be resolved
- unsigned connid =
- symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid);
- // connid = UINT_MAX when symbolicName is not found
- if (connid != UINT32_MAX) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Debug)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug,
- __func__, "Remove connection resolve name '%s' to connid %u",
- symbolicOrConnid, connid);
- }
-
- // remove connection from the FIB
- forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid);
- // remove connection
- connectionTable_RemoveById(table, connid);
- // remove connection from symbolicNameTable since we have symbolic input
- symbolicNameTable_Remove(config->symbolicNameTable, symbolicOrConnid);
-
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
-#endif /* WITH_MAPME */
-
- success = true; // to write
- } else {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__,
- "Remove connection symbolic name '%s' could not be resolved",
- symbolicOrConnid);
- }
- // failure
- }
- }
-
-
-
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) { // ACK
- response =
- utils_CreateAck(header, control, sizeof(remove_connection_command));
- } else { // NACK
- response =
- utils_CreateNack(header, control, sizeof(remove_connection_command));
- }
-
- return response;
-}
-
-void _parc_strlwr(char *string) {
- char *p = string;
- while ((*p = tolower(*p))) {
- p++;
- }
-}
-
-struct iovec *configuration_ProcessConnectionList(Configuration *config,
- struct iovec *request) {
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
- ConnectionList *connList = connectionTable_GetEntries(table);
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* fot bytes granularity
- uint8_t *payloadResponse = parcMemory_AllocateAndClear(
- sizeof(list_connections_command) * connectionList_Length(connList));
-
- for (size_t i = 0; i < connectionList_Length(connList); i++) {
- // Don't release original, it is not stored
- Connection *original = connectionList_Get(connList, i);
-
- const AddressPair *addressPair = connection_GetAddressPair(original);
- Address *localAddress = addressCopy(addressPair_GetLocal(addressPair));
- Address *remoteAddress = addressCopy(addressPair_GetRemote(addressPair));
-
- // Fill payload by shifting and casting at each 'i' step.
- list_connections_command *listConnectionsCommand =
- (list_connections_command *)(payloadResponse +
- (i * sizeof(list_connections_command)));
- // set structure fields
-
- listConnectionsCommand->connid = connection_GetConnectionId(original);
-
- const char *connectionName = symbolicNameTable_GetNameByIndex(config->symbolicNameTable, connection_GetConnectionId(original));
- snprintf(listConnectionsCommand->connectionName, SYMBOLIC_NAME_LEN, "%s", connectionName);
- _parc_strlwr(listConnectionsCommand->connectionName);
-
- snprintf(listConnectionsCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", ioOperations_GetInterfaceName(connection_GetIoOperations(original)));
-
- listConnectionsCommand->state =
- connection_IsUp(original) ? IFACE_UP : IFACE_DOWN;
- listConnectionsCommand->connectionData.admin_state =
- (connection_GetAdminState(original) == CONNECTION_STATE_UP) ? IFACE_UP : IFACE_DOWN;
- listConnectionsCommand->connectionData.connectionType =
- ioOperations_GetConnectionType(connection_GetIoOperations(original));
-
- listConnectionsCommand->connectionData.admin_state = connection_GetAdminState(original);
-
-#ifdef WITH_POLICY
- listConnectionsCommand->connectionData.priority = connection_GetPriority(original);
- listConnectionsCommand->connectionData.tags = connection_GetTags(original);
-#endif /* WITH_POLICY */
-
- if (addressGetType(localAddress) == ADDR_INET &&
- addressGetType(remoteAddress) == ADDR_INET) {
- listConnectionsCommand->connectionData.ipType = ADDR_INET;
-
- // get local port/address
- addressGetInet(localAddress, &tmpAddr);
- listConnectionsCommand->connectionData.localPort = tmpAddr.sin_port;
- listConnectionsCommand->connectionData.localIp.v4.as_inaddr =
- tmpAddr.sin_addr;
- memset(&tmpAddr, 0, sizeof(tmpAddr));
- // get remote port/address
- addressGetInet(remoteAddress, &tmpAddr);
- listConnectionsCommand->connectionData.remotePort = tmpAddr.sin_port;
- listConnectionsCommand->connectionData.remoteIp.v4.as_inaddr =
- tmpAddr.sin_addr;
-
- } else if (addressGetType(localAddress) == ADDR_INET6 &&
- addressGetType(remoteAddress) == ADDR_INET6) {
- listConnectionsCommand->connectionData.ipType = ADDR_INET6;
-
- // get local port/address
- addressGetInet6(localAddress, &tmpAddr6);
- listConnectionsCommand->connectionData.localPort = tmpAddr6.sin6_port;
- listConnectionsCommand->connectionData.localIp.v6.as_in6addr = tmpAddr6.sin6_addr;
- memset(&tmpAddr6, 0, sizeof(tmpAddr6));
- // get remote port/address
- addressGetInet6(remoteAddress, &tmpAddr6);
- listConnectionsCommand->connectionData.remotePort = tmpAddr6.sin6_port;
- listConnectionsCommand->connectionData.remoteIp.v6.as_in6addr = tmpAddr6.sin6_addr;
-
- } // no need further else, control on the addressed already done at the
- // time of insertion in the connection table
- addressDestroy(&localAddress);
- addressDestroy(&remoteAddress);
- }
-
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (uint16_t)connectionList_Length(connList);
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len =
- sizeof(list_connections_command) * connectionList_Length(connList);
-
- connectionList_Destroy(&connList);
- return response;
-}
-
-struct iovec *configuration_ProcessListenersList(Configuration *config,
- struct iovec *request) {
- ListenerSet *listenerList = forwarder_GetListenerSet(config->forwarder);
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* fot bytes granularity
- uint8_t *payloadResponse = parcMemory_AllocateAndClear(
- sizeof(list_listeners_command) * listenerSet_Length(listenerList));
-
- for (size_t i = 0; i < listenerSet_Length(listenerList); i++) {
- ListenerOps *listenerEntry = listenerSet_Get(listenerList, i);
-
- // Fill payload by shifting and casting at each 'i' step.
- list_listeners_command *listListenersCommand =
- (list_listeners_command *)(payloadResponse +
- (i * sizeof(list_listeners_command)));
-
- listListenersCommand->connid =
- (uint32_t)listenerEntry->getInterfaceIndex(listenerEntry);
- listListenersCommand->encapType =
- (uint8_t)listenerEntry->getEncapType(listenerEntry);
- if (addressGetType((const Address *)listenerEntry->getListenAddress(
- listenerEntry)) == ADDR_INET) {
- addressGetInet(
- (const Address *)listenerEntry->getListenAddress(listenerEntry),
- &tmpAddr);
- listListenersCommand->addressType = ADDR_INET;
- listListenersCommand->address.v4.as_inaddr = tmpAddr.sin_addr;
- listListenersCommand->port = tmpAddr.sin_port;
- } else if (addressGetType((const Address *)listenerEntry->getListenAddress(
- listenerEntry)) == ADDR_INET6) {
- addressGetInet6(
- (const Address *)listenerEntry->getListenAddress(listenerEntry),
- &tmpAddr6);
- listListenersCommand->addressType = ADDR_INET6;
- listListenersCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr;
- listListenersCommand->port = tmpAddr6.sin6_port;
- }
-
- const char * listenerName = listenerEntry->getListenerName(listenerEntry);
- snprintf(listListenersCommand->listenerName, SYMBOLIC_NAME_LEN, "%s", listenerName);
- if (listenerEntry->getEncapType(listenerEntry) == ENCAP_TCP ||
- listenerEntry->getEncapType(listenerEntry) == ENCAP_UDP) {
- const char * interfaceName = listenerEntry->getInterfaceName(listenerEntry);
- snprintf(listListenersCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", interfaceName);
- }
- }
-
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (uint16_t)listenerSet_Length(listenerList);
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len =
- sizeof(list_listeners_command) * listenerSet_Length(listenerList);
-
- return response;
-}
-
-struct iovec *configuration_ProcessCacheStore(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- ;
- cache_store_command *control = request[1].iov_base;
- ;
-
- bool success = false;
-
- switch (control->activate) {
- case ACTIVATE_ON:
- forwarder_SetChacheStoreFlag(config->forwarder, true);
- if (forwarder_GetChacheStoreFlag(config->forwarder)) {
- success = true;
- }
- break;
-
- case ACTIVATE_OFF:
- forwarder_SetChacheStoreFlag(config->forwarder, false);
- if (!forwarder_GetChacheStoreFlag(config->forwarder)) {
- success = true;
- }
- break;
-
- default:
- break;
- }
-
- struct iovec *response;
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(cache_store_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(cache_store_command));
- }
-
- return response;
-}
-
-struct iovec *configuration_ProcessCacheServe(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- cache_serve_command *control = request[1].iov_base;
-
- bool success = false;
-
- switch (control->activate) {
- case ACTIVATE_ON:
- forwarder_SetChacheServeFlag(config->forwarder, true);
- if (forwarder_GetChacheServeFlag(config->forwarder)) {
- success = true;
- }
- break;
-
- case ACTIVATE_OFF:
- forwarder_SetChacheServeFlag(config->forwarder, false);
- if (!forwarder_GetChacheServeFlag(config->forwarder)) {
- success = true;
- }
- break;
-
- default:
- break;
- }
-
- struct iovec *response;
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(cache_store_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(cache_store_command));
- }
-
- return response;
-}
-
-struct iovec *configuration_ProcessCacheClear(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
-
- forwarder_ClearCache(config->forwarder);
-
- struct iovec *response = utils_CreateAck(header, NULL, 0);
- return response;
-}
-
-size_t configuration_GetObjectStoreSize(Configuration *config) {
- return config->maximumContentObjectStoreSize;
-}
+ WSADATA wsaData = {0};
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+#endif
+ configuration_set_loglevel(config, loglevel_from_str(DEFAULT_LOGLEVEL));
+ config->strategy_map = kh_init_strategy_map();
-void _configuration_StoreFwdStrategy(Configuration *config, const char *prefix,
- strategy_type strategy) {
- PARCString *prefixStr = parcString_Create(prefix);
- PARCUnsigned *strategyValue = parcUnsigned_Create((unsigned)strategy);
- parcHashMap_Put(config->strategy_map, prefixStr, strategyValue);
- parcUnsigned_Release(&strategyValue);
- parcString_Release(&prefixStr);
+ return config;
}
-struct iovec *configuration_SetWldr(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- set_wldr_command *control = request[1].iov_base;
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
- Connection *conn = NULL;
- bool success = false;
+void configuration_free(configuration_t *config) {
+ assert(config);
- const char *symbolicOrConnid = control->symbolicOrConnid;
+ const char *k_prefix;
+ unsigned _;
+ (void)_;
- if (utils_IsNumber(symbolicOrConnid)) {
- // case for connid as input: check if connID present in the fwd table
- conn = (Connection *)connectionTable_FindById(
- table, (unsigned)strtold(symbolicOrConnid, NULL));
- if (conn) {
- success = true;
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "ConnID not found, check list connections"); // failure
- }
- } else {
- // case for symbolic as input: check if symbolic name can be resolved
- unsigned connid =
- symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid);
- if (connid != UINT32_MAX) {
- conn = (Connection *)connectionTable_FindById(table, connid);
- if (conn) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Debug)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug,
- __func__, "Set wldr resolve name '%s' to connid %u",
- symbolicOrConnid, connid);
- }
- success = true;
- }
- } else {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Symbolic name '%s' could not be resolved",
- symbolicOrConnid);
- } // failure
- }
- }
+ // Free the strategy hashmap
+ kh_foreach(config->strategy_map, k_prefix, _, { free((char *)k_prefix); });
+ kh_destroy_strategy_map(config->strategy_map);
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) {
- switch (control->activate) {
- case ACTIVATE_ON:
- connection_EnableWldr(conn);
- response = utils_CreateAck(header, control, sizeof(set_wldr_command));
- break;
-
- case ACTIVATE_OFF:
- connection_DisableWldr(conn);
- response = utils_CreateAck(header, control, sizeof(set_wldr_command));
- break;
-
- default: // received wrong value
- response = utils_CreateNack(header, control, sizeof(set_wldr_command));
- break;
- }
- } else {
- response = utils_CreateNack(header, control, sizeof(set_wldr_command));
- }
-
- return response;
+ free(config);
}
-strategy_type configuration_GetForwardingStrategy(Configuration *config,
- const char *prefix) {
- PARCString *prefixStr = parcString_Create(prefix);
- const unsigned *val = parcHashMap_Get(config->strategy_map, prefixStr);
- parcString_Release(&prefixStr);
-
- if (val == NULL) {
- return LAST_STRATEGY_VALUE;
- } else {
- return (strategy_type)*val;
- }
+size_t configuration_get_cs_size(const configuration_t *config) {
+ return config->cs_capacity;
}
-struct iovec *configuration_SetForwardingStrategy(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- set_strategy_command *control = request[1].iov_base;
-
- const char *prefix = utils_PrefixLenToString(
- control->addressType, &control->address, &control->len);
- strategy_type strategy = control->strategyType;
- strategy_type existingFwdStrategy =
- configuration_GetForwardingStrategy(config, prefix);
-
- if (existingFwdStrategy == LAST_STRATEGY_VALUE ||
- strategy != existingFwdStrategy) {
- // means such a new strategy is not present in the hash table or has to be
- // updated
- _configuration_StoreFwdStrategy(config, prefix, strategy);
- Name *hicnPrefix = name_CreateFromAddress(control->addressType,
- control->address, control->len);
- Name *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- if(control->related_prefixes != 0){
- for(int i = 0; i < control->related_prefixes; i++){
- related_prefixes[i] = name_CreateFromAddress(
- control->addresses_type[i],
- control->addresses[i], control->lens[i]);
- }
- }
- forwarder_SetStrategy(config->forwarder, hicnPrefix, strategy,
- control->related_prefixes, related_prefixes);
- name_Release(&hicnPrefix);
- if(control->related_prefixes != 0){
- for(int i = 0; i < control->related_prefixes; i++){
- name_Release(&related_prefixes[i]);
- }
- }
- }
-
- free((char *) prefix);
- struct iovec *response =
- utils_CreateAck(header, control, sizeof(set_strategy_command));
-
- return response;
+void configuration_set_cs_size(configuration_t *config, size_t size) {
+ config->cs_capacity = size;
}
-void configuration_SetObjectStoreSize(Configuration *config,
- size_t maximumObjectCount) {
- config->maximumContentObjectStoreSize = maximumObjectCount;
-
- forwarder_SetContentObjectStoreSize(config->forwarder,
- config->maximumContentObjectStoreSize);
+const char *configuration_get_fn_config(const configuration_t *config) {
+ return config->fn_config;
}
-Forwarder *configuration_GetForwarder(const Configuration *config) {
- return config->forwarder;
+void configuration_set_fn_config(configuration_t *config,
+ const char *fn_config) {
+ config->fn_config = fn_config;
}
-Logger *configuration_GetLogger(const Configuration *config) {
- return config->logger;
+void configuration_set_port(configuration_t *config, uint16_t port) {
+ config->port = port;
}
-struct iovec *configuration_MapMeEnable(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- mapme_activator_command *control = request[1].iov_base;
- const char *stateString[2] = {"on", "off"};
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer,
- "The mapme enable setting received is: %s",
- stateString[control->activate]);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+uint16_t configuration_get_port(const configuration_t *config) {
+ return config->port;
}
-struct iovec *configuration_MapMeDiscovery(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- mapme_activator_command *control = request[1].iov_base;
- const char *stateString[2] = {"on", "off"};
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer,
- "The mapme discovery setting received is: %s",
- stateString[control->activate]);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+void configuration_set_configuration_port(configuration_t *config,
+ uint16_t configuration_port) {
+ config->configuration_port = configuration_port;
}
-struct iovec *configuration_MapMeTimescale(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- mapme_timing_command *control = request[1].iov_base;
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer,
- "The mapme timescale value received is: %u",
- control->timePeriod);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
-}
-
-struct iovec *configuration_MapMeRetx(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- mapme_timing_command *control = request[1].iov_base;
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(
- composer, "The mapme retransmission time value received is: %u",
- control->timePeriod);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+uint16_t configuration_get_configuration_port(const configuration_t *config) {
+ return config->configuration_port;
}
-struct iovec * configuration_MapMeSendUpdate(Configuration *config,
- struct iovec *request, unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- mapme_send_update_command *control = request[1].iov_base;
-
- FIB * fib = forwarder_getFib(config->forwarder);
- if (!fib)
- goto ERR;
- Name *prefix = name_CreateFromAddress(control->addressType, control->address,
- control->len);
- if (!prefix)
- goto ERR;
- FibEntry *entry = fib_Contains(fib, prefix);
- name_Release(&prefix);
- if (!entry)
- goto ERR;
-
- const NumberSet * nexthops = fibEntry_GetNexthops(entry);
- unsigned size = (unsigned) numberSet_Length(nexthops);
-
- /* The command is accepted iif triggered by (one of) the producer of this prefix */
- for (unsigned i = 0; i < size; i++) {
- unsigned nhop = numberSet_GetItem(nexthops, i);
- if (nhop == ingressId) {
- MapMe * mapme = forwarder_getMapmeInstance(config->forwarder);
- mapme_send_updates(mapme, entry, nexthops);
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
- }
- }
-
-ERR:
- return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command));
+void configuration_set_loglevel(configuration_t *config, int loglevel) {
+ config->loglevel = loglevel;
+ log_conf.log_level = loglevel;
}
-
-struct iovec *configuration_ConnectionSetAdminState(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- connection_set_admin_state_command *control = request[1].iov_base;
-
- if ((control->admin_state != CONNECTION_STATE_UP) && (control->admin_state != CONNECTION_STATE_DOWN))
- return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command));
-
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command));
-
- connection_SetAdminState(conn, control->admin_state);
-
-#ifdef WITH_MAPME
- /* Hook: connection event */
- forwarder_onConnectionEvent(config->forwarder, conn,
- control->admin_state == CONNECTION_STATE_UP
- ? CONNECTION_EVENT_SET_UP
- : CONNECTION_EVENT_SET_DOWN);
-#endif /* WITH_MAPME */
-
- return utils_CreateAck(header, control, sizeof(connection_set_admin_state_command));
+int configuration_get_loglevel(const configuration_t *config) {
+ return config->loglevel;
}
-#ifdef WITH_POLICY
-
-struct iovec *configuration_ConnectionSetPriority(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- connection_set_priority_command *control = request[1].iov_base;
-
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(connection_set_priority_command));
-
- connection_SetPriority(conn, control->priority);
-
-#ifdef WITH_MAPME
- /* Hook: connection event */
- forwarder_onConnectionEvent(config->forwarder, conn,
- CONNECTION_EVENT_PRIORITY_CHANGED);
-#endif /* WITH_MAPME */
-
- return utils_CreateAck(header, control, sizeof(connection_set_priority_command));
+void configuration_set_logfile(configuration_t *config, const char *logfile) {
+ config->logfile = logfile;
+ log_conf.log_file = fopen(logfile, "w");
+ config->logfile_fd = fileno(log_conf.log_file);
}
-struct iovec *configuration_ConnectionSetTags(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- connection_set_tags_command *control = request[1].iov_base;
-
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(connection_set_tags_command));
-
- connection_SetTags(conn, control->tags);
-
-#ifdef WITH_MAPME
- /* Hook: connection event */
- forwarder_onConnectionEvent(config->forwarder, conn,
- CONNECTION_EVENT_TAGS_CHANGED);
-#endif /* WITH_MAPME */
-
- return utils_CreateAck(header, control, sizeof(connection_set_tags_command));
+const char *configuration_get_logfile(const configuration_t *config) {
+ return config->logfile;
}
-struct iovec *configuration_ProcessPolicyAdd(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- add_policy_command *control = request[1].iov_base;
-
- if (forwarder_AddOrUpdatePolicy(config->forwarder, control)) {
- return utils_CreateAck(header, control, sizeof(add_policy_command));
- } else {
- return utils_CreateNack(header, control, sizeof(add_policy_command));
- }
+int configuration_get_logfile_fd(const configuration_t *config) {
+ return config->logfile_fd;
}
-struct iovec *configuration_ProcessPolicyList(Configuration *config,
- struct iovec *request) {
- FibEntryList *fibList = forwarder_GetFibEntries(config->forwarder);
-
- size_t payloadSize = fibEntryList_Length(fibList);
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* = bytes granularity
- uint8_t *payloadResponse =
- parcMemory_AllocateAndClear(sizeof(list_policies_command) * payloadSize);
-
- for (size_t i = 0; i < fibEntryList_Length(fibList); i++) {
- FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i);
- NameBitvector *prefix = name_GetContentName(fibEntry_GetPrefix(entry));
-
- list_policies_command *listPoliciesCommand =
- (list_policies_command *)(payloadResponse +
- (i * sizeof(list_policies_command)));
-
- Address *addressEntry = nameBitvector_ToAddress(prefix);
- if (addressGetType(addressEntry) == ADDR_INET) {
- addressGetInet(addressEntry, &tmpAddr);
- listPoliciesCommand->addressType = ADDR_INET;
- listPoliciesCommand->address.v4.as_inaddr = tmpAddr.sin_addr;
- } else if (addressGetType(addressEntry) == ADDR_INET6) {
- addressGetInet6(addressEntry, &tmpAddr6);
- listPoliciesCommand->addressType = ADDR_INET6;
- listPoliciesCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr;
- }
- listPoliciesCommand->len = nameBitvector_GetLength(prefix);
- listPoliciesCommand->policy = fibEntry_GetPolicy(entry);
-
- addressDestroy(&addressEntry);
- }
-
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (unsigned)payloadSize;
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len = sizeof(list_policies_command) * payloadSize;
-
- fibEntryList_Destroy(&fibList);
- return response;
+void configuration_set_daemon(configuration_t *config, bool daemon) {
+ config->daemon = daemon;
}
-struct iovec *configuration_ProcessPolicyRemove(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- remove_policy_command *control = request[1].iov_base;
-
- if (forwarder_RemovePolicy(config->forwarder, control))
- return utils_CreateAck(header, control, sizeof(remove_policy_command));
- else
- return utils_CreateNack(header, control, sizeof(remove_policy_command));
+bool configuration_get_daemon(const configuration_t *config) {
+ return config->daemon;
}
-struct iovec *configuration_UpdateConnection(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- update_connection_command *control = request[1].iov_base;
-
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(update_connection_command));
-
- connection_SetTags(conn, control->tags);
- connection_SetAdminState(conn, control->admin_state);
- if (control->priority > 0)
- connection_SetPriority(conn, control->priority);
-
- return utils_CreateAck(header, control, sizeof(update_connection_command));
+void configuration_set_strategy(configuration_t *config, const char *prefix,
+ strategy_type_t strategy_type) {
+ int res;
+ khiter_t k = kh_put_strategy_map(config->strategy_map, strdup(prefix), &res);
+ kh_value(config->strategy_map, k) = strategy_type;
}
-#endif /* WITH_POLICY */
-
-// ===========================
-// Main functions that deal with receiving commands, executing them, and sending
-// ACK/NACK
-
-struct iovec *configuration_DispatchCommand(Configuration *config,
- command_id command,
- struct iovec *control,
- unsigned ingressId) {
- struct iovec *response = NULL;
- switch (command) {
- case ADD_LISTENER:
- response = configurationListeners_Add(config, control, ingressId);
- break;
-
- case ADD_CONNECTION:
- response = configuration_ProcessCreateTunnel(config, control);
- break;
-
- case LIST_CONNECTIONS:
- response = configuration_ProcessConnectionList(config, control);
- break;
-
- case ADD_ROUTE:
- response =
- configuration_ProcessRegisterHicnPrefix(config, control, ingressId);
- break;
-
- case LIST_ROUTES:
- response = configuration_ProcessRegistrationList(config, control);
- break;
-
- case REMOVE_CONNECTION:
- response = configuration_ProcessRemoveTunnel(config, control, ingressId);
- break;
-
- case REMOVE_LISTENER:
- response = configuration_ProcessRemoveListener(config, control, ingressId);
- break;
-
- case REMOVE_ROUTE:
- response = configuration_ProcessUnregisterHicnPrefix(config, control);
- break;
-
- case CACHE_STORE:
- response = configuration_ProcessCacheStore(config, control);
- break;
-
- case CACHE_SERVE:
- response = configuration_ProcessCacheServe(config, control);
- break;
-
- case CACHE_CLEAR:
- response = configuration_ProcessCacheClear(config, control);
- break;
-
- case SET_STRATEGY:
- response = configuration_SetForwardingStrategy(config, control);
- break;
-
- case SET_WLDR:
- response = configuration_SetWldr(config, control);
- break;
-
- case ADD_PUNTING:
- response = configurationListeners_AddPunting(config, control, ingressId);
- break;
- case LIST_LISTENERS:
- response = configuration_ProcessListenersList(config, control);
- break;
-
- case MAPME_ENABLE:
- response = configuration_MapMeEnable(config, control);
- break;
-
- case MAPME_DISCOVERY:
- response = configuration_MapMeDiscovery(config, control);
- break;
-
- case MAPME_TIMESCALE:
- response = configuration_MapMeTimescale(config, control);
- break;
-
- case MAPME_RETX:
- response = configuration_MapMeRetx(config, control);
- break;
-
- case MAPME_SEND_UPDATE:
- response = configuration_MapMeSendUpdate(config, control, ingressId);
- break;
-
- case CONNECTION_SET_ADMIN_STATE:
- response = configuration_ConnectionSetAdminState(config, control);
- break;
-
-#ifdef WITH_POLICY
- case ADD_POLICY:
- response = configuration_ProcessPolicyAdd(config, control);
- break;
-
- case LIST_POLICIES:
- response = configuration_ProcessPolicyList(config, control);
- break;
-
- case REMOVE_POLICY:
- response = configuration_ProcessPolicyRemove(config, control);
- break;
-
- case UPDATE_CONNECTION:
- response = configuration_UpdateConnection(config, control);
- break;
-
- case CONNECTION_SET_PRIORITY:
- response = configuration_ConnectionSetPriority(config, control);
- break;
-
- case CONNECTION_SET_TAGS:
- response = configuration_ConnectionSetTags(config, control);
- break;
-#endif /* WITH_POLICY */
-
- default:
- break;
- }
-
- return response;
+strategy_type_t configuration_get_strategy(const configuration_t *config,
+ const char *prefix) {
+ khiter_t k = kh_get_strategy_map(config->strategy_map, prefix);
+ if (k == kh_end(config->strategy_map)) return STRATEGY_TYPE_UNDEFINED;
+ return kh_val(config->strategy_map, k);
}
-void configuration_ReceiveCommand(Configuration *config, command_id command,
- struct iovec *request, unsigned ingressId) {
- parcAssertNotNull(config, "Parameter config must be non-null");
- parcAssertNotNull(request, "Parameter request must be non-null");
- struct iovec *response =
- configuration_DispatchCommand(config, command, request, ingressId);
- configuration_SendResponse(config, response, ingressId);
-
- /*
- * The message is originally received by a listener, and will be freed in
- * different parts of the code.
- *
- * For the special case of commands, a iovec is created, eg in
- * udpListener::_readCommand, which has to be freed (it is commented in the
- * listener). On the contrary, the original message is freed.
- *
- * From this function, commands are dispatched to different processing
- * functions, which have two general behaviours:
- *
- * - LIST commands:
- * . a payload for the response is allocated
- * . a iovec for the response is allocated with header = request header,
- * payload = newly allocated payload
- *
- * - Other commands:
- * . a ack/nack packet is generated thanks to utils/utils.cc
- * . this allocates a iovec which reuses the header of the request just
- * updating the messageType field inside.
- */
- parcMemory_Deallocate(&request);
-
- switch (command) {
- case LIST_CONNECTIONS:
- case LIST_ROUTES: // case LIST_INTERFACES: case ETC...:
- case LIST_LISTENERS:
- case LIST_POLICIES:
- /* Deallocate payload */
- parcMemory_Deallocate(&response[1].iov_base);
- break;
- default:
- break;
- }
-
- parcMemory_Deallocate(&response);
+void configuration_flush_log() {
+ if (log_conf.log_file) fclose(log_conf.log_file);
}
diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h
index 5090f1413..9861b6c9f 100644
--- a/hicn-light/src/hicn/config/configuration.h
+++ b/hicn-light/src/hicn/config/configuration.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,17 +23,18 @@
*
*/
-#ifndef configuration_h
-#define configuration_h
+#ifndef HICNLIGHT_CONFIGURATION_H
+#define HICNLIGHT_CONFIGURATION_H
-#include <hicn/core/logger.h>
-#include <hicn/utils/commands.h>
+#include "../base/khash.h"
+#include "../core/msgbuf.h"
+#include "../core/strategy.h"
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/hicn-light-ng.h>
-struct configuration;
-typedef struct configuration Configuration;
+KHASH_MAP_INIT_STR(strategy_map, unsigned);
-struct forwarder;
-typedef struct forwarder Forwarder;
+typedef struct configuration_s configuration_t;
/**
* <#One Line Description#>
@@ -49,7 +50,7 @@ typedef struct forwarder Forwarder;
* <#example#>
* @endcode
*/
-Configuration *configuration_Create(Forwarder *forwarder);
+configuration_t *configuration_create();
/**
* <#One Line Description#>
@@ -65,13 +66,7 @@ Configuration *configuration_Create(Forwarder *forwarder);
* <#example#>
* @endcode
*/
-void configuration_Destroy(Configuration **configPtr);
-
-void configuration_SetupAllListeners(Configuration *config, uint16_t port,
- const char *localPath);
-
-void configuration_ReceiveCommand(Configuration *config, command_id command,
- struct iovec *request, unsigned ingressId);
+void configuration_free(configuration_t *config);
/**
* Returns the configured size of the content store
@@ -87,7 +82,7 @@ void configuration_ReceiveCommand(Configuration *config, command_id command,
* <#example#>
* @endcode
*/
-size_t configuration_GetObjectStoreSize(Configuration *config);
+size_t configuration_get_cs_size(const configuration_t *config);
/**
* Sets the size of the content store (in objects, not bytes)
@@ -101,52 +96,42 @@ size_t configuration_GetObjectStoreSize(Configuration *config);
* <#example#>
* @endcode
*/
-void configuration_SetObjectStoreSize(Configuration *config,
- size_t maximumContentObjectCount);
+void configuration_set_cs_size(configuration_t *config, size_t size);
-strategy_type configuration_GetForwardingStrategy(Configuration *config,
- const char *prefix);
+const char *configuration_get_fn_config(const configuration_t *config);
-/**
- * Returns the Forwarder that owns the Configuration
- *
- * Returns the hicn-light Forwarder. Used primarily by associated classes in
- * the configuration group.
- *
- * @param [in] config An allocated Configuration
- *
- * @return non-null The owning Forwarder
- * @return null An error
- *
- * Example:
- * @code
- * {
- * <#example#>
- * }
- * @endcode
- */
-Forwarder *configuration_GetForwarder(const Configuration *config);
+void configuration_set_fn_config(configuration_t *config,
+ const char *fn_config);
-/**
- * Returns the logger used by the Configuration subsystem
- *
- * Returns the logger specified when the Configuration was created.
- *
- * @param [in] config An allocated Configuration
- *
- * @retval non-null The logger
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-Logger *configuration_GetLogger(const Configuration *config);
+void configuration_set_port(configuration_t *config, uint16_t port);
+
+uint16_t configuration_get_port(const configuration_t *config);
+
+void configuration_set_configuration_port(configuration_t *config,
+ uint16_t configuration_port);
+
+uint16_t configuration_get_configuration_port(const configuration_t *config);
+
+void configuration_set_loglevel(configuration_t *config, int loglevel);
+
+int configuration_get_loglevel(const configuration_t *config);
+
+void configuration_set_logfile(configuration_t *config, const char *logfile);
+
+const char *configuration_get_logfile(const configuration_t *config);
+
+int configuration_get_logfile_fd(const configuration_t *config);
+
+void configuration_set_daemon(configuration_t *config, bool daemon);
+
+bool configuration_get_daemon(const configuration_t *config);
+
+void configuration_set_strategy(configuration_t *config, const char *prefix,
+ strategy_type_t strategy_type);
+
+strategy_type_t configuration_get_strategy(const configuration_t *config,
+ const char *prefix);
-struct iovec *configuration_DispatchCommand(Configuration *config,
- command_id command,
- struct iovec *control,
- unsigned ingressId);
+void configuration_flush_log();
-#endif // configuration_h
+#endif // HICNLIGHT_CONFIGURATION_H
diff --git a/hicn-light/src/hicn/config/configurationFile.c b/hicn-light/src/hicn/config/configurationFile.c
deleted file mode 100644
index ebf057fa6..000000000
--- a/hicn-light/src/hicn/config/configurationFile.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/configuration.h>
-#include <hicn/config/configurationFile.h>
-#include <hicn/config/controlRoot.h>
-#include <hicn/config/controlState.h>
-
-struct configuration_file {
- Forwarder *forwarder;
- const char *filename;
- FILE *fh;
-
- size_t linesRead;
-
- // our custom state machine.
- ControlState *controlState;
-};
-
-/*
- * Called by a command to dispatch the correct command
- */
-struct iovec *_writeRead(ControlState *state, struct iovec *msg) {
- ConfigurationFile *configFile =
- (ConfigurationFile *)controlState_GetUserdata(state);
-
- parcAssertNotNull(msg, "Parameter msg must be non-null");
- struct iovec *response = configuration_DispatchCommand(
- forwarder_GetConfiguration(configFile->forwarder),
- ((header_control_message *)msg[0].iov_base)->commandID, msg, 0);
-
- return response;
-}
-
-/**
- * Removes leading whitespace (space + tab).
- *
- * If the string is all whitespace, the return value will point to the
- * terminating '\0'.
- *
- * @param [in] str A null-terminated c-string
- *
- * @retval non-null A pointer in to string of the first non-whitespace
- *
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-static char *_stripLeadingWhitespace(char *str) {
- while (isspace(*str)) {
- str++;
- }
- return str;
-}
-
-/**
- * Removes trailing whitespace
- *
- * Inserts a NULL after the last non-whitespace character, modiyfing the input
- * string.
- *
- * @param [in] str A null-terminated c-string
- *
- * @return non-null A pointer to the input string
- *
- * Example:
- * @code
- * {
- * <#example#>
- * }
- * @endcode
- */
-static char *_stripTrailingWhitespace(char *str) {
- char *p = str + strlen(str) - 1;
- while (p > str && isspace(*p)) {
- p--;
- }
-
- // cap it. If no whitespace, p+1 == str + strlen(str), so will overwrite the
- // current null. If all whitespace p+1 == str+1. For an empty string, p+1 =
- // str.
- *(p + 1) = 0;
-
- // this does not catch the case where the entire string is whitespace
- if (p == str && isspace(*p)) {
- *p = 0;
- }
-
- return str;
-}
-
-/**
- * Removed leading and trailing whitespace
- *
- * Modifies the input string (may add a NULL at the end). Will return
- * a pointer to the first non-whitespace character or the terminating NULL.
- *
- * @param [in] str A null-terminated c-string
- *
- * @return non-null A pointer in to the input string
- *
- * Example:
- * @code
- * {
- * <#example#>
- * }
- * @endcode
- */
-static char *_trim(char *str) {
- return _stripTrailingWhitespace(_stripLeadingWhitespace(str));
-}
-
-/**
- * Parse a string in to a PARCList with one word per element
- *
- * The string passed will be modified by inserting NULLs after each token.
- *
- * @param [in] str A c-string (will be modified)
- *
- * @retval non-null A PARCList where each item is a single word
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-static PARCList *_parseArgs(char *str) {
- PARCList *list =
- parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
-
- const char delimiters[] = " \t";
-
- char *token;
- token = strtok(str, delimiters);
- while (token != NULL) {
- if (strlen(token) > 0) {
- parcList_Add(list, strdup(token));
- }
- token = strtok(NULL, delimiters);
- }
- // while ((token = strsep(&str, delimiters)) != NULL) {
- // parcList_Add(list, token);
- // }
-
- return list;
-}
-
-// =============================================================
-
-static void _destroy(ConfigurationFile **configFilePtr) {
- ConfigurationFile *configFile = *configFilePtr;
- parcMemory_Deallocate((void **)&configFile->filename);
-
- if (configFile->fh != NULL) {
- fclose(configFile->fh);
- }
-
- controlState_Destroy(&configFile->controlState);
-}
-
-parcObject_ExtendPARCObject(ConfigurationFile, _destroy, NULL, NULL, NULL, NULL,
- NULL, NULL);
-
-parcObject_ImplementRelease(configurationFile, ConfigurationFile);
-
-ConfigurationFile *configurationFile_Create(Forwarder *forwarder,
- const char *filename) {
- parcAssertNotNull(forwarder, "Parameter hicn-fwd must be non-null");
- parcAssertNotNull(filename, "Parameter filename must be non-null");
-
- ConfigurationFile *configFile = parcObject_CreateInstance(ConfigurationFile);
-
- if (configFile) {
- configFile->linesRead = 0;
- configFile->forwarder = forwarder;
- configFile->filename =
- parcMemory_StringDuplicate(filename, strlen(filename));
- parcAssertNotNull(configFile->filename, "Could not copy string '%s'",
- filename);
-
- // setup the control state for the command parser: last parameter NULL
- // because
- // writeRead still not implemented from configuration file.
- configFile->controlState =
- controlState_Create(configFile, _writeRead, false,
- SRV_CTRL_IP, SRV_CTRL_PORT);
-
- // we do not register Help commands
- controlState_RegisterCommand(configFile->controlState,
- controlRoot_Create(configFile->controlState));
-
- // open the file and make sure we can read it
- configFile->fh = fopen(configFile->filename, "r");
-
- if (configFile->fh) {
- if (logger_IsLoggable(forwarder_GetLogger(forwarder),
- LoggerFacility_Config, PARCLogLevel_Debug)) {
- logger_Log(forwarder_GetLogger(forwarder), LoggerFacility_Config,
- PARCLogLevel_Debug, __func__, "Open config file %s",
- configFile->filename);
- }
- } else {
- if (logger_IsLoggable(forwarder_GetLogger(forwarder),
- LoggerFacility_Config, PARCLogLevel_Error)) {
- logger_Log(forwarder_GetLogger(forwarder), LoggerFacility_Config,
- PARCLogLevel_Error, __func__,
- "Could not open config file %s: (%d) %s",
- configFile->filename, errno, strerror(errno));
- }
-
- // failure cleanup the object -- this nulls it so final return null be
- // NULL
- configurationFile_Release(&configFile);
- }
- }
- return configFile;
-}
-
-bool configurationFile_Process(ConfigurationFile *configFile) {
- parcAssertNotNull(configFile, "Parameter configFile must be non-null");
-
- // default to a "true" return value and only set to false if we encounter an
- // error.
- bool success = true;
-
-#define BUFFERLEN 2048
- char buffer[BUFFERLEN];
-
- configFile->linesRead = 0;
-
- // always clear errors and fseek to start of file in case we get called
- // multiple times.
- clearerr(configFile->fh);
- rewind(configFile->fh);
-
- while (success && fgets(buffer, BUFFERLEN, configFile->fh) != NULL) {
- configFile->linesRead++;
-
- char *stripedBuffer = _trim(buffer);
- if (strlen(stripedBuffer) > 0) {
- if (stripedBuffer[0] != '#') {
- // not empty and not a comment
-
- // _parseArgs will modify the string
- char *copy =
- parcMemory_StringDuplicate(stripedBuffer, strlen(stripedBuffer));
- PARCList *args = _parseArgs(copy);
- char output[8192];
- CommandReturn result =
- controlState_DispatchCommand(configFile->controlState, args, output, sizeof(output));
-
- // we ignore EXIT from the configuration file
- if (result == CommandReturn_Failure) {
- if (logger_IsLoggable(forwarder_GetLogger(configFile->forwarder),
- LoggerFacility_Config, PARCLogLevel_Error)) {
- logger_Log(forwarder_GetLogger(configFile->forwarder),
- LoggerFacility_Config, PARCLogLevel_Error, __func__,
- "Error on input file %s line %d: %s",
- configFile->filename, configFile->linesRead,
- stripedBuffer);
- }
- success = false;
- }
- for(int i = 0; i < parcList_Size(args); i++){
- free(parcList_GetAtIndex(args, i));
- }
- parcList_Release(&args);
- parcMemory_Deallocate((void **)&copy);
- }
- }
- }
-
- if (ferror(configFile->fh)) {
- if (logger_IsLoggable(forwarder_GetLogger(configFile->forwarder),
- LoggerFacility_Config, PARCLogLevel_Error)) {
- logger_Log(forwarder_GetLogger(configFile->forwarder),
- LoggerFacility_Config, PARCLogLevel_Error, __func__,
- "Error on input file %s line %d: (%d) %s",
- configFile->filename, configFile->linesRead, errno,
- strerror(errno));
- }
- success = false;
- }
-
- return success;
-}
diff --git a/hicn-light/src/hicn/config/configurationFile.h b/hicn-light/src/hicn/config/configurationFile.h
deleted file mode 100644
index b748dfc15..000000000
--- a/hicn-light/src/hicn/config/configurationFile.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file configurationFile.h
- * @brief Accepts a filename and provides a means to read it into Configuration
- *
- * Reads a configuration file and converts the lines in to configuration
- * commands for use in Configuration.
- *
- * Accepts '#' lines as comments. Skips blank and whitespace-only lines.
- *
- */
-
-#ifndef configurationFile_h
-#define configurationFile_h
-
-#include <hicn/core/forwarder.h>
-
-struct configuration_file;
-typedef struct configuration_file ConfigurationFile;
-
-/**
- * Creates a ConfigurationFile to prepare to process the file
- *
- * Prepares the object and opens the file. Makes sure we can read the file.
- * Does not read the file or process any commands from the file.
- *
- * @param [in] hicn-light An allocated Forwarder to configure with the file
- * @param [in] filename The file to use
- *
- * @retval non-null An allocated ConfigurationFile that is readable
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-ConfigurationFile *configurationFile_Create(Forwarder *forwarder,
- const char *filename);
-
-/**
- * Reads the configuration file line-by-line and issues commands to
- * Configuration
- *
- * Reads the file line by line. Skips '#' and blank lines.
- *
- * Will stop on the first error. Lines already processed will not be un-done.
- *
- * @param [in] configFile An allocated ConfigurationFile
- *
- * @retval true The entire files was processed without error.
- * @retval false There was an error in the file.
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-bool configurationFile_Process(ConfigurationFile *configFile);
-
-// void configurationFile_ProcessForwardingStrategies(Configuration * config,
-// ConfigurationFile * configFile);
-
-/**
- * Closes the underlying file and releases memory
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in,out] configFilePtr An allocated ConfigurationFile that will be
- * NULL'd as output
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void configurationFile_Release(ConfigurationFile **configFilePtr);
-
-#endif /* defined(configurationFile_h) */
diff --git a/hicn-light/src/hicn/config/configurationListeners.c b/hicn-light/src/hicn/config/configurationListeners.c
deleted file mode 100644
index 31a0c4776..000000000
--- a/hicn-light/src/hicn/config/configurationListeners.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <unistd.h>
-#endif
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/core/system.h>
-#include <hicn/utils/interfaceSet.h>
-#include <hicn/utils/punting.h>
-
-#include <hicn/config/configurationListeners.h>
-#include <hicn/io/hicnListener.h>
-#include <hicn/io/tcpListener.h>
-#include <hicn/io/udpListener.h>
-
-#include <hicn/utils/address.h>
-#include <hicn/utils/addressList.h>
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static bool _setupHicnListenerOnInet4(Forwarder *forwarder,
- const char *symbolic, Address *address) {
- bool success = false;
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- ListenerOps *ops =
- hicnListener_CreateInet(forwarder, (char *)symbolic, address);
- if (ops != NULL) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
- parcAssertTrue(success, "Failed to add Hicn listener %s to ListenerSet",
- symbolic);
- }
-#endif /* __APPLE__ _WIN32*/
- return success;
-}
-
-static bool _setupHicnListenerOnInet6(Forwarder *forwarder,
- const char *symbolic, Address *address) {
- bool success = false;
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- ListenerOps *ops =
- hicnListener_CreateInet6(forwarder, (char *)symbolic, address);
- if (ops != NULL) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
- parcAssertTrue(success, "Failed to add Hicn listener %s to ListenerSet",
- symbolic);
- }
-#endif /* __APPLE__ _WIN32 */
- return success;
-}
-
-bool configurationListeners_Remove(const Configuration *config) {
- Logger *logger = configuration_GetLogger(config);
- if (logger_IsLoggable(logger, LoggerFacility_Config, PARCLogLevel_Warning)) {
- logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__,
- "Removing a listener not supported: ingress %u control %s");
- }
-
- return false;
-}
-
-bool _AddPuntingInet(const Configuration *config, Punting *punting,
- unsigned ingressId) {
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- struct sockaddr *addr = parcNetwork_SockAddress("0.0.0.0", 1234);
- if (addr == NULL) {
- printf("Error creating address\n");
- return false;
- }
-
- Address *fakeAddr = addressCreateFromInet((struct sockaddr_in *)addr);
-
- ListenerOps *listenerOps = listenerSet_Find(
- forwarder_GetListenerSet(configuration_GetForwarder(config)), ENCAP_HICN,
- fakeAddr);
- addressDestroy(&fakeAddr);
-
- if (listenerOps == NULL) {
- printf("the main listener (IPV4) does not exists\n");
- return false;
- }
-
- struct sockaddr_in puntingAddr;
-
- Address *address = puntingGetAddress(punting);
- if (address == NULL) return false;
-
- bool res = addressGetInet(address, &puntingAddr);
- if (!res) {
- printf("unable to read the punting address\n");
- return false;
- }
-
- char prefix[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &(puntingAddr.sin_addr), prefix, INET_ADDRSTRLEN);
-
- char len[5];
- sprintf(len, "%d", puntingPrefixLen(punting));
-
- char *prefixStr =
- malloc(strlen(prefix) + strlen(len) + 2); //+1 for the zero-terminator
- if (prefixStr == NULL) {
- printf("error while create the prefix string\n");
- return false;
- }
- strcpy(prefixStr, prefix);
- strcat(prefixStr, "/");
- strcat(prefixStr, len);
-
- res = hicnListener_Punting(listenerOps, prefixStr);
- if (!res) {
- printf("error while adding the punting rule\n");
- return false;
- }
-
- return true;
-#else
- return false;
-#endif
-}
-
-bool _AddPuntingInet6(const Configuration *config, Punting *punting,
- unsigned ingressId) {
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- struct sockaddr *addr = parcNetwork_SockAddress("0::0", 1234);
- if (addr == NULL) {
- printf("Error creating address\n");
- return false;
- }
-
- Address *fakeAddr = addressCreateFromInet6((struct sockaddr_in6 *)addr);
-
- // comments:
- // EncapType: I use the Hicn encap since the punting is available only for
- // Hicn listeners LocalAddress: The only listern for which we need punting
- // rules is the main one, which has no address
- // so I create a fake empty address. This need to be consistent
- // with the address set at creation time
-
- ListenerOps *listenerOps = listenerSet_Find(
- forwarder_GetListenerSet(configuration_GetForwarder(config)), ENCAP_HICN,
- fakeAddr);
- addressDestroy(&fakeAddr);
-
- if (listenerOps == NULL) {
- printf("the main listener does not exists\n");
- return false;
- }
-
- struct sockaddr_in6 puntingAddr;
- bool res = addressGetInet6(puntingGetAddress(punting), &puntingAddr);
- if (!res) {
- printf("unable to read the punting address\n");
- return false;
- }
-
- char prefix[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &(puntingAddr.sin6_addr), prefix, INET6_ADDRSTRLEN);
-
- char len[5];
- sprintf(len, "%d", puntingPrefixLen(punting));
-
- char *prefixStr =
- malloc(strlen(prefix) + strlen(len) + 2); //+1 for the zero-terminator
- if (prefixStr == NULL) {
- printf("error while create the prefix string\n");
- return false;
- }
- strcpy(prefixStr, prefix);
- strcat(prefixStr, "/");
- strcat(prefixStr, len);
-
- res = hicnListener_Punting(listenerOps, prefixStr);
- if (!res) {
- printf("error while adding the punting rule\n");
- return false;
- }
-
- return true;
-#else
- return false;
-#endif
-}
-
-//============= LIGHT COMMAN ===============
-
-static bool _addEther(Configuration *config, add_listener_command *control,
- unsigned ingressId) {
- // Not implemented
- return false;
-}
-
-/*
- * Create a new IPV4/TCP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] listenerName The name of the listener
- * @param [in] addr4 The ipv4 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupTcpListenerOnInet(Forwarder *forwarder, char *listenerName, ipv4_addr_t *addr4,
- uint16_t *port, char *interfaceName) {
- parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
-
- bool success = false;
-
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = *port;
- addr.sin_addr.s_addr = *addr4;
-
- ListenerOps *ops = tcpListener_CreateInet(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add TCP listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-
-/*
- * Create a new IPV4/UDP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] listenerName The name of the listener
- * @param [in] addr4 The ipv4 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupUdpListenerOnInet(Forwarder *forwarder, char *listenerName, ipv4_addr_t *addr4,
- uint16_t *port, char *interfaceName) {
- bool success = false;
-
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = *port;
- addr.sin_addr.s_addr = *addr4;
-
- ListenerOps *ops = udpListener_CreateInet(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add UDP listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-
-/*
- * Create a new IPV6/TCP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] addr6 The ipv6 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, char *listenerName,
- ipv6_addr_t *addr6, uint16_t *port, char *interfaceName,
- uint32_t scopeId) {
- bool success = false;
-
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
- addr.sin6_port = *port;
- addr.sin6_addr = *addr6;
- addr.sin6_scope_id = scopeId;
-
- ListenerOps *ops = tcpListener_CreateInet6(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add TCP6 listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-
-/*
- * Create a new IPV6/UDP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] listenerName The name of the listener
- * @param [in] addr6 The ipv6 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder, char *listenerName,
- ipv6_addr_t *addr6, uint16_t *port, char *interfaceName) {
- bool success = false;
-
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
- addr.sin6_port = *port;
- addr.sin6_addr = *addr6;
- addr.sin6_scope_id = 0;
-
- ListenerOps *ops = udpListener_CreateInet6(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add UDP6 listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-/*
- * Create a new HICN listener.
- *
- * @param [in] config The configuration
- * @param [in] control The control command
- * @param [in] port The connection id of the command
- *
- * return true if success, false otherwise
- */
-bool _addHicn(Configuration *config, add_listener_command *control,
- unsigned ingressId) {
- bool success = false;
- const char *symbolic = control->symbolic;
- Address *localAddress = NULL;
-
- switch (control->addressType) {
- case ADDR_INET: {
- localAddress =
- addressFromInaddr4Port(&control->address.v4.as_u32, &control->port);
- success = _setupHicnListenerOnInet4(configuration_GetForwarder(config),
- symbolic, localAddress);
- break;
- }
-
- case ADDR_INET6: {
- localAddress =
- addressFromInaddr6Port(&control->address.v6.as_in6addr, &control->port);
- success = _setupHicnListenerOnInet6(configuration_GetForwarder(config),
- symbolic, localAddress);
- break;
- }
-
- default:
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Warning)) {
- logger_Log(configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Warning, __func__,
- "Unsupported address type for HICN (ingress id %u): "
- "must be either IPV4 or IPV6",
- ingressId);
- }
- break;
- }
-
- if (success == true && localAddress != NULL) {
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Info)) {
- char * str = addressToString(localAddress);
- logger_Log(configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Info, __func__,
- "Setup hicn listener on address %s",
- str);
- parcMemory_Deallocate((void **)&str);
- }
- }
-
- addressDestroy(&localAddress);
-
- return success;
-}
-
-bool _addIP(Configuration *config, add_listener_command *control,
- unsigned ingressId) {
- bool success = false;
- char *symbolic = control->symbolic;
-
- switch (control->addressType) {
- case ADDR_INET: {
-
- if (control->connectionType == UDP_CONN) {
- success =
- _setupUdpListenerOnInet(configuration_GetForwarder(config), symbolic,
- &control->address.v4.as_u32, &control->port, control->interfaceName);
- } else if (control->connectionType == TCP_CONN) {
- success =
- _setupTcpListenerOnInet(configuration_GetForwarder(config), symbolic,
- &control->address.v4.as_u32, &control->port, control->interfaceName);
- }
- break;
- }
-
- case ADDR_INET6: {
- if (control->connectionType == UDP_CONN) {
- success = _setupUdpListenerOnInet6Light(
- configuration_GetForwarder(config), symbolic, &control->address.v6.as_in6addr,
- &control->port, control->interfaceName);
- } else if (control->connectionType == TCP_CONN) {
- success = _setupTcpListenerOnInet6Light(
- configuration_GetForwarder(config), symbolic, &control->address.v6.as_in6addr,
- &control->port, control->interfaceName, 0);
- }
- break;
- }
-
- default:
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Warning)) {
- char *addrStr = utils_CommandAddressToString(
- control->addressType, &control->address, &control->port);
- logger_Log(
- configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Warning, __func__,
- "Unsupported address type for IP encapsulation ingress id %u: %s",
- ingressId, addrStr);
- parcMemory_Deallocate((void **)&addrStr);
- }
- break;
- }
-
- if (success) {
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Info)) {
- char *addrStr = utils_CommandAddressToString(
- control->addressType, &control->address, &control->port);
- logger_Log(configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Info, __func__, "Setup listener on address %s",
- addrStr);
- parcMemory_Deallocate((void **)&addrStr);
- }
- }
-
- return success;
-}
-
-struct iovec *configurationListeners_Add(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- add_listener_command *control = request[1].iov_base;
-
- bool success = false;
-
- ListenerSet *listenerSet = forwarder_GetListenerSet(configuration_GetForwarder(config));
- int listenerId = listenerSet_FindIdByListenerName(listenerSet, control->symbolic);
-
- if (listenerId < 0) {
- if (control->listenerMode == ETHER_MODE) {
- parcTrapNotImplemented("Add Ethernet Listener is not supported");
- success = _addEther(config, control, ingressId);
- // it is a failure
- } else if (control->listenerMode == IP_MODE) {
- success = _addIP(config, control, ingressId);
- } else if (control->listenerMode == HICN_MODE) {
- success = _addHicn(config, control, ingressId);
- } else {
- Logger *logger = configuration_GetLogger(config);
- if (logger_IsLoggable(logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__,
- "Unsupported encapsulation mode (ingress id %u)", ingressId);
- }
- }
- }
-
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(add_listener_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(add_listener_command));
- }
-
- return response;
-}
-
-struct iovec *configurationListeners_AddPunting(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- add_punting_command *control = request[1].iov_base;
-
- const char *symbolicOrConnid = control->symbolicOrConnid;
- uint32_t len = control->len;
- in_port_t port = htons(1234);
- bool success = false;
-
- if (control->addressType == ADDR_INET) {
- Address *address = addressFromInaddr4Port(&control->address.v4.as_u32, &port);
- Punting *punting = puntingCreate(symbolicOrConnid, address, len);
- success = _AddPuntingInet(config, punting, ingressId);
- addressDestroy(&address);
- } else if (control->addressType == ADDR_INET6) {
- Address *address = addressFromInaddr6Port(&control->address.v6.as_in6addr, &port);
- Punting *punting = puntingCreate(symbolicOrConnid, address, len);
- success = _AddPuntingInet6(config, punting, ingressId);
- addressDestroy(&address);
- } else {
- printf("Invalid IP type.\n"); // will generate a Nack
- return utils_CreateNack(header, control, sizeof(add_punting_command));
- }
-
- // generate ACK/NACK
- struct iovec *response;
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(add_punting_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(add_punting_command));
- }
-
- return response;
-}
-
-//=========================== INITIAL LISTENERS ====================
-
-static void _setupListenersOnAddress(Forwarder *forwarder, char *listenerName,
- const Address *address, uint16_t port,
- char *interfaceName) {
- address_type type = addressGetType(address);
- switch (type) {
- case ADDR_INET: {
- struct sockaddr_in tmp;
- addressGetInet(address, &tmp);
- _setupTcpListenerOnInet(forwarder, listenerName, &tmp.sin_addr.s_addr, &port, interfaceName);
- break;
- }
-
- case ADDR_INET6: {
- struct sockaddr_in6 tmp;
- addressGetInet6(address, &tmp);
- _setupTcpListenerOnInet6Light(forwarder, listenerName, &tmp.sin6_addr, &port, interfaceName,
- tmp.sin6_scope_id);
- break;
- }
-
- case ADDR_LINK:
- // not used
- break;
-
- default:
- // dont' know how to handle this, so no listeners
- break;
- }
-}
-
-void configurationListeners_SetupAll(const Configuration *config, uint16_t port,
- const char *localPath) {
- Forwarder *forwarder = configuration_GetForwarder(config);
- InterfaceSet *set = system_Interfaces(forwarder);
-
- size_t interfaceSetLen = interfaceSetLength(set);
- for (size_t i = 0; i < interfaceSetLen; i++) {
- Interface *iface = interfaceSetGetByOrdinalIndex(set, i);
-
- const AddressList *addresses = interfaceGetAddresses(iface);
- size_t addressListLen = addressListLength(addresses);
-
- for (size_t j = 0; j < addressListLen; j++) {
- const Address *address = addressListGetItem(addresses, j);
-
- // Do not start on link address
- char listenerName[SYMBOLIC_NAME_LEN];
-#if defined(__ANDROID__) || defined(_WIN32)
- snprintf(listenerName, SYMBOLIC_NAME_LEN, "local_%zu", i);
-#else
- snprintf(listenerName, SYMBOLIC_NAME_LEN, "local_%ld", i);
-#endif
- if (addressGetType(address) != ADDR_LINK) {
- _setupListenersOnAddress(forwarder, listenerName, address, port,
- (char *)interfaceGetName(iface));
- }
- }
- }
-
- interfaceSetDestroy(&set);
-}
-
-void configurationListeners_SetutpLocalIPv4(const Configuration *config,
- uint16_t port) {
- Forwarder *forwarder = configuration_GetForwarder(config);
- in_addr_t addr = inet_addr("127.0.0.1");
- uint16_t network_byte_order_port = htons(port);
-
- char listenerNameUdp[SYMBOLIC_NAME_LEN] = "lo_udp";
- char listenerNameTcp[SYMBOLIC_NAME_LEN] = "lo_tcp";
- char *loopback_interface = "lo";
- _setupUdpListenerOnInet(forwarder, listenerNameUdp,(ipv4_addr_t *)&(addr),
- &network_byte_order_port, loopback_interface);
- _setupTcpListenerOnInet(forwarder, listenerNameTcp, (ipv4_addr_t *)&(addr),
- &network_byte_order_port, loopback_interface);
-}
diff --git a/hicn-light/src/hicn/config/configurationListeners.h b/hicn-light/src/hicn/config/configurationListeners.h
deleted file mode 100644
index b09ad5167..000000000
--- a/hicn-light/src/hicn/config/configurationListeners.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file configurationListeners.h
- * @brief Configuration routines related to Listeners
- *
- * Adding and removing listeners.
- *
- */
-
-#ifndef configurationListeners_h
-#define configurationListeners_h
-
-#include <hicn/config/configuration.h>
-#include <hicn/core/forwarder.h>
-
-#include <hicn/utils/address.h>
-
-/**
- * Setup udp, tcp, and local listeners
- *
- * Will bind to all available IP protocols on the given port.
- * Does not add Ethernet listeners.
- *
- * @param port is the UPD and TCP port to use
- * @param localPath is the AF_UNIX path to use, if NULL no AF_UNIX listener is
- * setup
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void configurationListeners_SetupAll(const Configuration *config, uint16_t port,
- const char *localPath);
-
-void configurationListeners_SetutpLocalIPv4(const Configuration *config,
- uint16_t port);
-
-bool configurationListeners_Remove(const Configuration *config);
-
-// light functions
-
-/**
- * Add new listener.
- *
- * @param request The request coming from hicnLightControl or the
- * configuration file. The bytes in the request are
- * ordered following the network byte order convention.
- *
- * @param ingressId The connection id of the incoming request.
- */
-struct iovec *configurationListeners_Add(Configuration *config,
- struct iovec *request,
- unsigned ingressId);
-
-struct iovec *configurationListeners_AddPunting(Configuration *config,
- struct iovec *request,
- unsigned ingressId);
-
-#endif /* defined(configurationListeners_h) */
diff --git a/hicn-light/src/hicn/config/configuration_file.c b/hicn-light/src/hicn/config/configuration_file.c
new file mode 100644
index 000000000..2e8e7a6ac
--- /dev/null
+++ b/hicn-light/src/hicn/config/configuration_file.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <hicn/config/configuration_file.h>
+#include <hicn/util/sstrncpy.h>
+
+#include "commands.h"
+#include "parse.h"
+
+#define BUFFERLEN 2048
+
+static char *_trim(char *str) {
+ char *end;
+
+ // Trim leading space
+ while (isspace((unsigned char)*str)) str++;
+
+ if (*str == 0) // All spaces?
+ return str;
+
+ // Trim trailing space
+ end = str + strnlen_s(str, BUFFERLEN) - 1;
+ while (end > str && isspace((unsigned char)*end)) end--;
+
+ // Write new null terminator character
+ end[1] = '\0';
+
+ return str;
+}
+
+bool configuration_file_process(forwarder_t *forwarder, const char *filename) {
+ assert(forwarder);
+ assert(filename);
+
+ int linesRead = 0;
+ FILE *f = fopen(filename, "r");
+ if (!f) {
+ ERROR("Could not open configuration file %s: (%d) %s", filename, errno,
+ strerror(errno));
+ goto ERR_OPEN;
+ }
+ DEBUG("Opening configuration file %s", filename);
+
+ char buffer[BUFFERLEN];
+ bool success = true;
+ // TODO(eloparco): We could use a fake socket since we only need the vft
+ hc_sock_t *s = hc_sock_create_forwarder(HICNLIGHT_NG);
+ if (!s) {
+ ERROR("Could not create socket");
+ goto ERR_SOCK;
+ }
+
+ while (success && fgets(buffer, BUFFERLEN, f) != NULL) {
+ linesRead++;
+
+ char *cmd = _trim(buffer);
+ if (strnlen_s(cmd, BUFFERLEN) <= 0) continue;
+ if (cmd[0] == '#') continue;
+
+ INFO("Processing command: %s", cmd);
+ hc_command_t command = {};
+ if (parse(cmd, &command) < 0) {
+ ERROR("Error parsing command : '%s'", cmd);
+ continue;
+ }
+
+ // TODO(eloparco): Handle all commands
+ hc_result_t *result = NULL;
+ if (command.action == ACTION_CREATE) {
+ if (command.object.type == OBJECT_LISTENER) {
+ result = hc_listener_create_conf(s, &command.object.listener);
+ } else if (command.object.type == OBJECT_CONNECTION) {
+ result = hc_connection_create_conf(s, &command.object.connection);
+ } else if (command.object.type == OBJECT_ROUTE) {
+ result = hc_route_create_conf(s, &command.object.route);
+ } else if (command.object.type == OBJECT_LOCAL_PREFIX) {
+ result = hc_strategy_add_local_prefix_conf(s, &command.object.strategy);
+ }
+ } else if (command.action == ACTION_SET) {
+ if (command.object.type == OBJECT_STRATEGY) {
+ result = hc_strategy_set_conf(s, &command.object.strategy);
+ }
+ }
+ if (result == NULL) {
+ ERROR("Command '%s' not supported", cmd);
+ continue;
+ }
+
+ size_t _unused;
+ hc_msg_t *msg = hc_result_get_msg(s, result);
+ command_type_t cmd_id = hc_result_get_cmd_id(s, result);
+ bool success = hc_result_get_success(s, result);
+ if (success == false) {
+ ERROR("Error serializing command : '%s'", cmd);
+ continue;
+ }
+
+ command_process(forwarder, (uint8_t *)msg, cmd_id, CONNECTION_ID_UNDEFINED,
+ &_unused);
+ hc_result_free(result);
+ }
+ hc_sock_free(s);
+
+ if (ferror(f)) {
+ ERROR("Error on input file %s line %d: (%d) %s", filename, linesRead, errno,
+ strerror(errno));
+ goto ERR_READ;
+ }
+ fclose(f);
+ return true;
+
+ERR_SOCK:
+ hc_sock_free(s);
+ERR_READ:
+ fclose(f);
+ERR_OPEN:
+ return false;
+}
diff --git a/hicn-light/src/hicn/config/configuration_file.h b/hicn-light/src/hicn/config/configuration_file.h
new file mode 100644
index 000000000..4d9535ab7
--- /dev/null
+++ b/hicn-light/src/hicn/config/configuration_file.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file configuration_file.h
+ * @brief Accepts a filename and provides a means to read it into Configuration
+ *
+ * Reads a configuration file and converts the lines in to configuration
+ * commands for use in Configuration.
+ *
+ * Accepts '#' lines as comments. Skips blank and whitespace-only lines.
+ *
+ */
+
+#ifndef configuration_file_h
+#define configuration_file_h
+
+#include <hicn/core/forwarder.h>
+
+/**
+ * Configure hicn-light by reading a configuration file line-by-line and
+ * issueing commands to the forwarder.
+ *
+ * The configuration file is a set of lines, just like used in hicnLightControl.
+ * You need to have "add listener" lines in the file to receive connections. No
+ * default listeners are configured.
+ *
+ * This function reads the file line by line, skipping '#' and blank lines, and
+ * will stop on the first error. Lines already processed will not be un-done.
+ *
+ * @param[in] forwarder An allocated forwarder_t
+ * @param[in] filename The path to the configuration file
+ *
+ * @retval true The entire files was processed without error.
+ * @retval false There was an error in the file.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool configuration_file_process(forwarder_t* forwarder, const char* filename);
+
+#endif /* defined(configuration_file_h) */
diff --git a/hicn-light/src/hicn/config/controlAdd.c b/hicn-light/src/hicn/config/controlAdd.c
deleted file mode 100644
index cac8e7913..000000000
--- a/hicn-light/src/hicn/config/controlAdd.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlAdd.h>
-#include <hicn/config/controlAddConnection.h>
-#include <hicn/config/controlAddListener.h>
-#include <hicn/config/controlAddPunting.h>
-#include <hicn/config/controlAddRoute.h>
-#ifdef WITH_POLICY
-#include <hicn/config/controlAddPolicy.h>
-#endif /* WITH_POLICY */
-
-// ===================================================
-
-static void _controlAdd_Init(CommandParser *parser, CommandOps *ops);
-
-static CommandReturn _controlAdd_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static CommandReturn _controlAdd_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *command_add = "add";
-static const char *help_command_add = "help add";
-
-CommandOps *webControlAdd_Create(ControlState *state) {
- return commandOps_Create(state, command_add, _controlAdd_Init,
- _controlAdd_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlAdd_CreateHelp(ControlState *state) {
- return commandOps_Create(state, help_command_add, NULL,
- _controlAdd_HelpExecute, commandOps_Destroy);
-}
-
-// ===================================================
-
-static CommandReturn _controlAdd_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_add_connection = controlAddConnection_Create(NULL);
- CommandOps *ops_add_route = controlAddRoute_Create(NULL);
- CommandOps *ops_add_punting = controlAddPunting_Create(NULL);
- CommandOps *ops_add_listener = controlAddListener_Create(NULL);
-#ifdef WITH_POLICY
- CommandOps *ops_add_policy = controlAddPolicy_Create(NULL);
-#endif /* WITH_POLICY */
-#ifdef WITH_POLICY
- snprintf(output, output_size, "Available commands:\n %s\n %s\n %s\n %s\n %s\n\n",
- ops_add_connection->command,
- ops_add_route->command,
- ops_add_punting->command,
- ops_add_listener->command,
- ops_add_policy->command);
-#else
- snprintf(output, output_size, "Available commands:\n %s\n %s\n %s\n %s\n\n",
- ops_add_connection->command,
- ops_add_route->command,
- ops_add_punting->command,
- ops_add_listener->command);
-
-#endif /* WITH_POLICY */
-
- commandOps_Destroy(&ops_add_connection);
- commandOps_Destroy(&ops_add_route);
- commandOps_Destroy(&ops_add_punting);
- commandOps_Destroy(&ops_add_listener);
-#ifdef WITH_POLICY
- commandOps_Destroy(&ops_add_policy);
-#endif /* WITH_POLICY */
- return CommandReturn_Success;
-}
-
-static void _controlAdd_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state, controlAddListener_HelpCreate(state));
- controlState_RegisterCommand(state, controlAddListener_Create(state));
- controlState_RegisterCommand(state, controlAddConnection_HelpCreate(state));
- controlState_RegisterCommand(state, controlAddRoute_HelpCreate(state));
- controlState_RegisterCommand(state, controlAddConnection_Create(state));
- controlState_RegisterCommand(state, controlAddRoute_Create(state));
- controlState_RegisterCommand(state, controlAddPunting_Create(state));
- controlState_RegisterCommand(state, controlAddPunting_HelpCreate(state));
-#ifdef WITH_POLICY
- controlState_RegisterCommand(state, controlAddPolicy_HelpCreate(state));
- controlState_RegisterCommand(state, controlAddPolicy_Create(state));
-#endif /* WITH_POLICY */
-}
-
-static CommandReturn _controlAdd_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlAdd_HelpExecute(parser, ops, args, output, output_size);
-}
diff --git a/hicn-light/src/hicn/config/controlAddConnection.c b/hicn-light/src/hicn/config/controlAddConnection.c
deleted file mode 100644
index eed37f3ad..000000000
--- a/hicn-light/src/hicn/config/controlAddConnection.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <parc/assert/parc_Assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/config/controlAddConnection.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-// ===================================================
-
-static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlAddConnection_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddConnection_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-#ifdef __linux__
-static CommandReturn _controlAddConnection_HicnHelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-#endif
-
-static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static CommandReturn _controlAddConnection_TcpHelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *_commandAddConnection = "add connection";
-#ifdef __linux__
-static const char *_commandAddConnectionHicn = "add connection hicn";
-#endif
-static const char *_commandAddConnectionUdp = "add connection udp";
-static const char *_commandAddConnectionTcp = "add connection tcp";
-static const char *_commandAddConnectionHelp = "help add connection";
-#ifdef __linux__
-static const char *_commandAddConnectionHicnHelp = "help add connection hicn";
-#endif
-static const char *_commandAddConnectionUdpHelp = "help add connection udp";
-static const char *_commandAddConnectionTcpHelp = "help add connection tcp";
-
-// ===================================================
-
-CommandOps *controlAddConnection_Create(ControlState *state) {
- return commandOps_Create(state, _commandAddConnection,
- _controlAddConnection_Init,
- _controlAddConnection_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlAddConnection_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionHelp, NULL,
- _controlAddConnection_HelpExecute,
- commandOps_Destroy);
-}
-
-// ===================================================
-
-#ifdef __linux__
-static CommandOps *_controlAddConnection_HicnCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionHicn, NULL,
- _controlAddConnection_HicnExecute,
- commandOps_Destroy);
-}
-#endif
-
-static CommandOps *_controlAddConnection_UdpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionUdp, NULL,
- _controlAddConnection_UdpExecute,
- commandOps_Destroy);
-}
-
-static CommandOps *_controlAddConnection_TcpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionTcp, NULL,
- _controlAddConnection_TcpExecute,
- commandOps_Destroy);
-}
-
-// ===================================================
-#ifdef __linux__
-static CommandOps *_controlAddConnection_HicnHelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionHicnHelp, NULL,
- _controlAddConnection_HicnHelpExecute,
- commandOps_Destroy);
-}
-#endif
-
-static CommandOps *_controlAddConnection_UdpHelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionUdpHelp, NULL,
- _controlAddConnection_UdpHelpExecute,
- commandOps_Destroy);
-}
-
-static CommandOps *_controlAddConnection_TcpHelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddConnectionTcpHelp, NULL,
- _controlAddConnection_TcpHelpExecute,
- commandOps_Destroy);
-}
-
-// ===================================================
-
-static CommandReturn _controlAddConnection_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
-#ifdef __linux__
- snprintf(output, output_size, "Available commands:\n %s\n %s\n %s\n\n",
- _commandAddConnectionHicn,
- _commandAddConnectionUdp,
- _commandAddConnectionTcp);
-#else
- snprintf(output, output_size, "Available commands:\n %s\n %s\n\n",
- _commandAddConnectionUdp,
- _commandAddConnectionTcp);
-#endif
- return CommandReturn_Success;
-}
-
-static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
-#ifdef __linux__
- controlState_RegisterCommand(state,
- _controlAddConnection_HicnHelpCreate(state));
-#endif
- controlState_RegisterCommand(state,
- _controlAddConnection_UdpHelpCreate(state));
- controlState_RegisterCommand(state,
- _controlAddConnection_TcpHelpCreate(state));
-#ifdef __linux__
- controlState_RegisterCommand(state, _controlAddConnection_HicnCreate(state));
-#endif
- controlState_RegisterCommand(state, _controlAddConnection_UdpCreate(state));
- controlState_RegisterCommand(state, _controlAddConnection_TcpCreate(state));
-}
-
-static CommandReturn _controlAddConnection_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlAddConnection_HelpExecute(parser, ops, args, output, output_size);
-}
-
-// ===================================================
-// functions general to all connection types
-
-/**
- * Create a tunnel in the forwarder based on the addresses
- *
- * Caller retains ownership of memory.
- * The symbolic name will be used to refer to this connection. It must be unqiue
- * otherwise the forwarder will reject this commend.
- *
- * @param [in] parser An allocated CommandParser
- * @param [in] ops Allocated CommandOps (needed to extract ControlState)
- * @param [in] localAddress the local IP and port. The port may be the wildcard
- * value.
- * @param [in] remoteAddress The remote IP and port (both must be specified)
- * @param [in] tunnelType The tunneling protocol
- * @param [in] symbolic The symbolic name for the connection (must be unique)
- * @param [in] output Output buffer
- * @param [in] output_size Output buffer size
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * {
- * struct sockaddr_in *anyAddress = parcNetwork_SockInet4AddressAny();
- * struct sockaddr_in *remote =
- * parcNetwork_SockInet4Address("192.168.1.2", 9695);
- *
- * Address *localAddress = addressCreateFromInet(anyAddress);
- * Address *remoteAddress = addressCreateFromInet(remote);
- *
- * control_CreateTunnel(state, localAddress, remoteAddress, IPTUN_TCP,
- * "conn7");
- *
- * addressDestroy(&localAddress);
- * addressDestroy(&remoteAddress);
- * parcMemory_Deallocate((void **)&remote);
- * parcMemory_Deallocate((void **)&anyAddress);
- * }
- * @endcode
- */
-
-static CommandReturn _controlAddConnection_CreateTunnel(CommandParser *parser,
- CommandOps *ops, const char *local_ip,
- const char *local_port,
- const char *remote_ip,
- const char *remote_port,
- connection_type tunnelType,
- const char *symbolic,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
- // a request like this always has an interface index of 0 [FIELD REMOVED]
- // unsigned int interfaceIndex = 0;
-
- // allocate command payload
- add_connection_command *addConnectionCommand =
- parcMemory_AllocateAndClear(sizeof(add_connection_command));
-
- // check and set IP addresses
- if (inet_pton(AF_INET, remote_ip, &addConnectionCommand->remoteIp.v4.as_u32) ==
- 1 &&
- inet_pton(AF_INET, local_ip, &addConnectionCommand->localIp.v4.as_u32) == 1) {
- addConnectionCommand->ipType = ADDR_INET;
-
- } else if (inet_pton(AF_INET6, remote_ip,
- &addConnectionCommand->remoteIp.v6.as_in6addr) == 1 &&
- inet_pton(AF_INET6, local_ip,
- &addConnectionCommand->localIp.v6.as_in6addr) == 1) {
- addConnectionCommand->ipType = ADDR_INET6;
-
- } else {
- snprintf(output, output_size, "Error: local address %s not same type as remote address %s\n",
- local_ip, remote_ip);
- parcMemory_Deallocate(&addConnectionCommand);
- return CommandReturn_Failure;
- }
-
- // Fill remaining payload fields
- addConnectionCommand->connectionType = tunnelType;
- strcpy(addConnectionCommand->symbolic, symbolic);
- addConnectionCommand->remotePort = htons((uint16_t)atoi(remote_port));
- addConnectionCommand->localPort = htons((uint16_t)atoi(local_port));
-
- // send message and receive response
- struct iovec *response =
- utils_SendRequest(state, ADD_CONNECTION, addConnectionCommand,
- sizeof(add_connection_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddConnection_IpHelp(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- const char *protocol,
- char *output,
- size_t output_size) {
- snprintf(output, output_size,
- #ifdef __linux__
- "add connection hicn <symbolic> <remote_ip> <local_ip>\n"
- #endif
- "add connection udp <symbolic> <remote_ip> <port> <local_ip> <port>\n"
- " <symbolic> : symbolic name, e.g. 'conn1' (must be "
- "unique, start with alpha)\n"
- " <remote_ip> : the IPv4 or IPv6 or hostname of the remote system\n"
- " <local_ip> : optional local IP address to bind to\n"
- "\n");
- return CommandReturn_Success;
-}
-
-#ifdef __linux__
-static CommandReturn _controlAddConnection_HicnHelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- _controlAddConnection_IpHelp(parser, ops, args, "hicn", output, output_size);
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- static const int _indexSymbolic = 3;
- static const int _indexRemAddr = 4;
- static const int _indexLocAddr = 5;
-
- if (parcList_Size(args) != 6) {
- _controlAddConnection_HicnHelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- char *symbolic = parcList_GetAtIndex(args, _indexSymbolic);
-
- if (!utils_ValidateSymbolicName(symbolic)) {
- snprintf(output, output_size, "Invalid symbolic name. Must begin with alpha and contain only "
- "alphanum.\n");
- return CommandReturn_Failure;
- }
-
- char *remote_ip = parcList_GetAtIndex(args, _indexRemAddr);
- char *local_ip = parcList_GetAtIndex(args, _indexLocAddr);
- char *port = "1234"; // this is a random port number that will be ignored
-
- return _controlAddConnection_CreateTunnel(
- parser, ops, local_ip, port, remote_ip, port, HICN_CONN, symbolic, output, output_size);
-}
-#endif
-
-static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- _controlAddConnection_IpHelp(parser, ops, args, "udp", output, output_size);
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- static const int _indexSymbolic = 3;
- static const int _indexRemAddr = 4;
- static const int _indexRemPort = 5;
- static const int _indexLocAddr = 6;
- static const int _indexLocPort = 7;
-
- if (parcList_Size(args) != 8) {
- _controlAddConnection_UdpHelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- char *symbolic = parcList_GetAtIndex(args, _indexSymbolic);
- size_t offset = 0;
- if (!utils_ValidateSymbolicName(symbolic)) {
- snprintf(output, output_size,
- "Invalid symbolic name. Must begin with alpha and contain only "
- "alphanum.\n");
- return CommandReturn_Failure;
- }
-
- char *remote_ip = parcList_GetAtIndex(args, _indexRemAddr);
- char *local_ip = parcList_GetAtIndex(args, _indexLocAddr);
-
- char *remote_port = parcList_GetAtIndex(args, _indexRemPort);
- char *local_port = parcList_GetAtIndex(args, _indexLocPort);
-
- return _controlAddConnection_CreateTunnel(parser, ops, local_ip, local_port,
- remote_ip, remote_port, UDP_CONN,
- symbolic,
- output + offset, output_size - offset);
-}
-
-static CommandReturn _controlAddConnection_TcpHelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- _controlAddConnection_IpHelp(parser, ops, args, "tcp", output, output_size);
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- static const int _indexSymbolic = 3;
- static const int _indexRemAddr = 4;
- static const int _indexRemPort = 5;
- static const int _indexLocAddr = 6;
- static const int _indexLocPort = 7;
-
- if (parcList_Size(args) != 8) {
- _controlAddConnection_UdpHelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- char *symbolic = parcList_GetAtIndex(args, _indexSymbolic);
- if (!utils_ValidateSymbolicName(symbolic)) {
- snprintf(output, output_size, "Invalid symbolic name. Must begin with alpha and contain only "
- "alphanum.\n");
- return CommandReturn_Failure;
- }
-
- char *remote_ip = parcList_GetAtIndex(args, _indexRemAddr);
- char *local_ip = parcList_GetAtIndex(args, _indexLocAddr);
-
- char *remote_port = parcList_GetAtIndex(args, _indexRemPort);
- char *local_port = parcList_GetAtIndex(args, _indexLocPort);
-
- return _controlAddConnection_CreateTunnel(parser, ops, local_ip, local_port,
- remote_ip, remote_port, TCP_CONN,
- symbolic,
- output, output_size);
-}
diff --git a/hicn-light/src/hicn/config/controlAddConnection.h b/hicn-light/src/hicn/config/controlAddConnection.h
deleted file mode 100644
index 546388efc..000000000
--- a/hicn-light/src/hicn/config/controlAddConnection.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_AddConnection.h
- * @brief Command-line "add connection" node
- *
- * Implements the "add connection" node of the CLI tree
- *
- *
- */
-
-#ifndef controlAddConnection_h
-#define controlAddConnection_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlAddConnection_Create(ControlState *state);
-CommandOps *controlAddConnection_HelpCreate(ControlState *state);
-#endif // controlAddConnection_h
diff --git a/hicn-light/src/hicn/config/controlAddListener.c b/hicn-light/src/hicn/config/controlAddListener.c
deleted file mode 100644
index df84c4691..000000000
--- a/hicn-light/src/hicn/config/controlAddListener.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/config/controlAddListener.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlAddListener_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddListener_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *command_add_listener = "add listener";
-static const char *command_help_add_listener = "help add listener";
-
-CommandOps *controlAddListener_Create(ControlState *state) {
- return commandOps_Create(state, command_add_listener, NULL,
- _controlAddListener_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlAddListener_HelpCreate(ControlState *state) {
- return commandOps_Create(state, command_help_add_listener, NULL,
- _controlAddListener_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static const int _indexProtocol = 2;
-static const int _indexSymbolic = 3;
-static const int _indexAddress = 4;
-static const int _indexPort = 5;
-static const int _indexInterfaceName = 6;
-
-static CommandReturn _controlAddListener_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size,
- "commands:\n"
-#ifdef __linux__
- " add listener hicn <symbolic> <localAddress> \n"
-#endif
- " add listener udp <symbolic> <localAddress> <port> <interface>\n"
- " add listener tcp <symbolic> <localAddress> <port> <interface>\n"
- "\n"
- " symbolic: User defined name for listener, must start with "
- "alpha and be alphanum\n"
-#ifdef __linux__
- " protocol: hicn | udp\n"
-#else
- " protocol: udp\n"
-#endif
- " localAddress: IPv4 or IPv6 address (or prefix protocol = hicn) "
- "assigend to the local interface\n"
- " port: Udp port\n"
- " interface: interface\n"
- "\n"
- "Notes:\n"
- " The symblic name must be unique or the source will reject it.\n"
-#ifdef __linux__
- " If protocol = hicn: the address 0::0 indicates the main listern, "
- "for which we can set punting rules.\n"
-#endif
- );
- return CommandReturn_Success;
-}
-
-static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops,
- const char *symbolic, const char *addr,
- const char *port, char *interfaceName, listener_mode mode,
- connection_type type,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- // allocate command payload
- add_listener_command *addListenerCommand =
- parcMemory_AllocateAndClear(sizeof(add_listener_command));
-
- // check and set IP address
- if (inet_pton(AF_INET, addr, &addListenerCommand->address.v4.as_u32) == 1) {
- addListenerCommand->addressType = ADDR_INET;
-
- } else if (inet_pton(AF_INET6, addr, &addListenerCommand->address.v6.as_in6addr) == 1) {
- addListenerCommand->addressType = ADDR_INET6;
-
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&addListenerCommand);
- return CommandReturn_Failure;
- }
-
- // Fill remaining payload fields
- size_t name_size = strlen((const char *)interfaceName);
- if(name_size > SYMBOLIC_NAME_LEN){
- //cut the string
- name_size = SYMBOLIC_NAME_LEN;
- }
-
- memcpy(addListenerCommand->interfaceName, interfaceName, name_size);
- addListenerCommand->listenerMode = mode;
- addListenerCommand->connectionType = type;
- addListenerCommand->port = htons((uint16_t)atoi(port));
- strcpy(addListenerCommand->symbolic, symbolic);
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, ADD_LISTENER, addListenerCommand, sizeof(add_listener_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddListener_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 5 && parcList_Size(args) != 7) {
- _controlAddListener_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- CommandReturn result = CommandReturn_Failure;
-
- const char *symbolic = parcList_GetAtIndex(args, _indexSymbolic);
-
- if (!utils_ValidateSymbolicName(symbolic)) {
- snprintf(output, output_size,
- "Error: symbolic name must begin with an alpha and be alphanum "
- "after\n");
- return result;
- }
-
- const char *protocol = parcList_GetAtIndex(args, _indexProtocol);
- const char *host = parcList_GetAtIndex(args, _indexAddress);
- char *interfaceName = parcList_GetAtIndex(args, _indexInterfaceName);
- if ((strcasecmp("hicn", protocol) == 0)) {
- const char *port =
- "1234"; // this is a random port number that will be ignored
-
- // here we discard the prefix len if it exists, since we don't use it in
- // code but we let libhicn to find the right ip address.
- return _CreateListener(parser, ops, symbolic, host, port, "hicn", HICN_MODE,
- HICN_CONN, output, output_size);
- }
- const char *port = parcList_GetAtIndex(args, _indexPort);
-
- if ((strcasecmp("udp", protocol) == 0)) {
- return _CreateListener(parser, ops, symbolic, host, port, interfaceName, IP_MODE,
- UDP_CONN, output, output_size);
- } else if ((strcasecmp("tcp", protocol) == 0)) {
- return _CreateListener(parser, ops, symbolic, host, port, interfaceName, IP_MODE,
- TCP_CONN, output, output_size);
- } else {
- _controlAddListener_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- if (result == CommandReturn_Failure) snprintf(output, output_size, "creation failed\n");
-
- return result;
-}
diff --git a/hicn-light/src/hicn/config/controlAddListener.h b/hicn-light/src/hicn/config/controlAddListener.h
deleted file mode 100644
index 6516d1779..000000000
--- a/hicn-light/src/hicn/config/controlAddListener.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_AddListener.h
- * @brief Add a listener to an interface
- *
- * <#Detailed Description#>
- *
- */
-
-#ifndef Control_AddListener_h
-#define Control_AddListener_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlAddListener_Create(ControlState *state);
-CommandOps *controlAddListener_HelpCreate(ControlState *state);
-#endif // Control_AddListener_h
diff --git a/hicn-light/src/hicn/config/controlAddPolicy.c b/hicn-light/src/hicn/config/controlAddPolicy.c
deleted file mode 100644
index 66439d29c..000000000
--- a/hicn-light/src/hicn/config/controlAddPolicy.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef WITH_POLICY
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/config/controlAddPolicy.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-#include <hicn/utils/token.h>
-
-static CommandReturn _controlAddPolicy_Execute(CommandParser *parser,
- CommandOps *ops, PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddPolicy_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandAddPolicy = "add policy";
-static const char *_commandAddPolicyHelp = "help add policy";
-
-CommandOps *controlAddPolicy_Create(ControlState *state) {
- return commandOps_Create(state, _commandAddPolicy, NULL,
- _controlAddPolicy_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlAddPolicy_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddPolicyHelp, NULL,
- _controlAddPolicy_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlAddPolicy_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- size_t output_offset = snprintf(output, output_size, "commands:\n"
- " add policy <prefix> <app_name>");
-
- #define _(x, y) output_offset += snprintf(output + output_offset, output_size - output_offset, " FLAG:%s", policy_tag_str[POLICY_TAG_ ## x]);
- foreach_policy_tag
- #undef _
-
- output_offset += snprintf(output + output_offset, output_size - output_offset,"\n");
- printf("\n");
- output_offset += snprintf(output + output_offset, output_size - output_offset,
- " prefix: The hicn name as IPv4 or IPv6 address (e.g 1234::0/64)\n"
- " app_name: The application name associated to this policy\n"
- " FLAG:*: A value among [neutral|require|prefer|avoid|prohibit] with an optional '!' character prefix for disabling changes\n"
- "\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddPolicy_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 11) {
- _controlAddPolicy_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *prefixStr = parcList_GetAtIndex(args, 2);
- char *addr = (char *)malloc((strlen(prefixStr) + 1) * sizeof(char));
-
- // separate address and len
- char *slash;
- uint32_t len = 0;
- strcpy(addr, prefixStr);
- slash = strrchr(addr, '/');
- if (slash != NULL) {
- len = atoi(slash + 1);
- *slash = '\0';
- }
-
- // allocate command payload
- add_policy_command *addPolicyCommand =
- parcMemory_AllocateAndClear(sizeof(add_policy_command));
-
- // check and set IP address
- if (inet_pton(AF_INET, addr, &addPolicyCommand->address.v4.as_u32) == 1) {
- if (len > 32) {
- snprintf(output, output_size, "ERROR: exceeded INET mask length, max=32\n");
- parcMemory_Deallocate(&addPolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- addPolicyCommand->addressType = ADDR_INET;
- } else if (inet_pton(AF_INET6, addr, &addPolicyCommand->address.v6.as_in6addr) == 1) {
- if (len > 128) {
- snprintf(output, output_size, "ERROR: exceeded INET6 mask length, max=128\n");
- parcMemory_Deallocate(&addPolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- addPolicyCommand->addressType = ADDR_INET6;
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&addPolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- free(addr);
-
- addPolicyCommand->len = len;
-
- hicn_policy_t policy;
- snprintf((char*)policy.app_name, APP_NAME_LEN, "%s", (char*)parcList_GetAtIndex(args, 3));
- for (int i=4; i < 11; i++) {
- const char *tag = parcList_GetAtIndex(args, i);
- policy_tag_state_t tag_state;
- tag_state.disabled = (tag[0] == '!') ? 1 : 0;
- if (strcmp(&tag[tag_state.disabled], "neutral") == 0) {
- tag_state.state = POLICY_STATE_NEUTRAL;
- } else if (strcmp(&tag[tag_state.disabled], "require") == 0) {
- tag_state.state = POLICY_STATE_REQUIRE;
- } else if (strcmp(&tag[tag_state.disabled], "prefer") == 0) {
- tag_state.state = POLICY_STATE_PREFER;
- } else if (strcmp(&tag[tag_state.disabled], "avoid") == 0) {
- tag_state.state = POLICY_STATE_AVOID;
- } else if (strcmp(&tag[tag_state.disabled], "prohibit") == 0) {
- tag_state.state = POLICY_STATE_PROHIBIT;
- } else {
- snprintf(output, output_size, "ERROR: invalid tag value '%s'\n", tag);
- parcMemory_Deallocate(&addPolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- policy.tags[i-4] = tag_state;
-
- }
-
- addPolicyCommand->policy = policy;
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, ADD_POLICY, addPolicyCommand,
- sizeof(add_policy_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/config/controlAddPunting.c b/hicn-light/src/hicn/config/controlAddPunting.c
deleted file mode 100644
index 41d846d55..000000000
--- a/hicn-light/src/hicn/config/controlAddPunting.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <hicn/utils/punting.h>
-
-#include <hicn/config/controlAddPunting.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlAddPunting_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddPunting_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandAddPunting = "add punting";
-static const char *_commandAddPuntingHelp = "help add punting";
-
-static const int _indexSymbolic = 2;
-static const int _indexPrefix = 3;
-
-CommandOps *controlAddPunting_Create(ControlState *state) {
- return commandOps_Create(state, _commandAddPunting, NULL,
- _controlAddPunting_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlAddPunting_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddPuntingHelp, NULL,
- _controlAddPunting_HelpExecute, commandOps_Destroy);
-}
-
-// =====================================================
-
-static CommandReturn _controlAddPunting_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "add punting <symbolic> <prefix>\n"
- " <symbolic> : listener symbolic name\n"
- " <address> : prefix to add as a punting rule. (example "
- "1234::0/64)\n"
- "\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddPunting_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 4) {
- _controlAddPunting_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *symbolicOrConnid = parcList_GetAtIndex(args, _indexSymbolic);
-
- if (!utils_ValidateSymbolicName(symbolicOrConnid) &&
- !utils_IsNumber(symbolicOrConnid)) {
- snprintf(output, output_size,
- "ERROR: Invalid symbolic or connid:\n"
- "symbolic name must begin with an alpha followed by alphanum;\nconnid "
- "must be an integer\n");
- return CommandReturn_Failure;
- }
-
- const char *prefixStr = parcList_GetAtIndex(args, _indexPrefix);
- char *addr = (char *)malloc((strlen(prefixStr) + 1) * sizeof(char));
-
- // separate address and len
- char *slash;
- uint32_t len = 0;
- strcpy(addr, prefixStr);
- slash = strrchr(addr, '/');
- if (slash != NULL) {
- len = atoi(slash + 1);
- *slash = '\0';
- }
-
- // allocate command payload
- add_punting_command *addPuntingCommand =
- parcMemory_AllocateAndClear(sizeof(add_punting_command));
-
- // check and set IP address
- if (inet_pton(AF_INET, addr, &addPuntingCommand->address.v4.as_u32) == 1) {
- if (len > 32) {
- snprintf(output, output_size, "ERROR: exceeded INET mask length, max=32\n");
- parcMemory_Deallocate(&addPuntingCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- addPuntingCommand->addressType = ADDR_INET;
- } else if (inet_pton(AF_INET6, addr, &addPuntingCommand->address.v6.as_in6addr) == 1) {
- if (len > 128) {
- snprintf(output, output_size, "ERROR: exceeded INET6 mask length, max=128\n");
- parcMemory_Deallocate(&addPuntingCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- addPuntingCommand->addressType = ADDR_INET6;
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&addPuntingCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- free(addr);
-
- // Fill remaining payload fields
- addPuntingCommand->len = len;
- strcpy(addPuntingCommand->symbolicOrConnid, symbolicOrConnid);
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, ADD_PUNTING, addPuntingCommand, sizeof(add_punting_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
-
-// ======================================================================
diff --git a/hicn-light/src/hicn/config/controlAddRoute.c b/hicn-light/src/hicn/config/controlAddRoute.c
deleted file mode 100644
index 78c0173ea..000000000
--- a/hicn-light/src/hicn/config/controlAddRoute.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/config/controlAddRoute.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlAddRoute_Execute(CommandParser *parser,
- CommandOps *ops, PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlAddRoute_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandAddRoute = "add route";
-static const char *_commandAddRouteHelp = "help add route";
-
-CommandOps *controlAddRoute_Create(ControlState *state) {
- return commandOps_Create(state, _commandAddRoute, NULL,
- _controlAddRoute_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlAddRoute_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandAddRouteHelp, NULL,
- _controlAddRoute_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlAddRoute_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "commands:\n"
- " add route <symbolic | connid> <prefix> <cost>\n"
- "\n"
- " symbolic: The symbolic name for an exgress\n"
- " connid: The egress connection id (see 'help list connections')\n"
- " prefix: The hicn name as IPv4 or IPv6 address (e.g 1234::0/64)\n"
- " cost: positive integer representing cost\n"
- "\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlAddRoute_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 5) {
- _controlAddRoute_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *symbolicOrConnid = parcList_GetAtIndex(args, 2);
-
- if (!utils_ValidateSymbolicName(symbolicOrConnid) &&
- !utils_IsNumber(symbolicOrConnid)) {
- snprintf(output, output_size, "ERROR: Invalid symbolic or connid:\nsymbolic name must begin with an "
- "alpha followed by alphanum;\nconnid must be an integer\n");
- return CommandReturn_Failure;
- }
-
- unsigned cost = atoi(parcList_GetAtIndex(args, 4));
-
- if (cost == 0) {
- snprintf(output, output_size, "ERROR: cost must be positive integer, got %u from '%s'\n", cost,
- (char *)parcList_GetAtIndex(args, 4));
- return CommandReturn_Failure;
- }
-
- const char *prefixStr = parcList_GetAtIndex(args, 3);
- char *addr = (char *)malloc((strlen(prefixStr) + 1) * sizeof(char));
-
- // separate address and len
- char *slash;
- uint32_t len = 0;
- strcpy(addr, prefixStr);
- slash = strrchr(addr, '/');
- if (slash != NULL) {
- len = atoi(slash + 1);
- *slash = '\0';
- }
-
- // allocate command payload
- add_route_command *addRouteCommand =
- parcMemory_AllocateAndClear(sizeof(add_route_command));
-
- // check and set IP address
- if (inet_pton(AF_INET, addr, &addRouteCommand->address.v4.as_u32) == 1) {
- if (len > 32) {
- snprintf(output, output_size, "ERROR: exceeded INET mask length, max=32\n");
- parcMemory_Deallocate(&addRouteCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- addRouteCommand->addressType = ADDR_INET;
- } else if (inet_pton(AF_INET6, addr, &addRouteCommand->address.v6.as_in6addr) == 1) {
- if (len > 128) {
- snprintf(output, output_size, "ERROR: exceeded INET6 mask length, max=128\n");
- parcMemory_Deallocate(&addRouteCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- addRouteCommand->addressType = ADDR_INET6;
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&addRouteCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- free(addr);
-
- // Fill remaining payload fields
- addRouteCommand->len = len;
- addRouteCommand->cost = (uint16_t)cost;
- strcpy(addRouteCommand->symbolicOrConnid, symbolicOrConnid);
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, ADD_ROUTE, addRouteCommand,
- sizeof(add_route_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlAddRoute.h b/hicn-light/src/hicn/config/controlAddRoute.h
deleted file mode 100644
index 9588c0f42..000000000
--- a/hicn-light/src/hicn/config/controlAddRoute.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_AddRoute.h
- * @brief Add a static route
- *
- * Implements the "add route" node of the CLI tree
- *
- */
-
-#ifndef Control_AddRoute_h
-#define Control_AddRoute_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlAddRoute_Create(ControlState *state);
-CommandOps *controlAddRoute_HelpCreate(ControlState *state);
-#endif // Control_AddRoute_h
diff --git a/hicn-light/src/hicn/config/controlCache.c b/hicn-light/src/hicn/config/controlCache.c
deleted file mode 100644
index b6010fcfd..000000000
--- a/hicn-light/src/hicn/config/controlCache.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlCache.h>
-#include <hicn/config/controlCacheClear.h>
-#include <hicn/config/controlCacheServe.h>
-#include <hicn/config/controlCacheStore.h>
-
-static void _controlCache_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlCache_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlCache_HelpExecute(CommandParser *parser,
- CommandOps *ops, PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandCache = "cache";
-static const char *_commandCacheHelp = "help cache";
-
-CommandOps *controlCache_Create(ControlState *state) {
- return commandOps_Create(state, _commandCache, _controlCache_Init,
- _controlCache_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlCache_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandCacheHelp, NULL,
- _controlCache_HelpExecute, commandOps_Destroy);
-}
-
-// =====================================================
-
-static CommandReturn _controlCache_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_cache_serve = controlCacheServe_HelpCreate(NULL);
- CommandOps *ops_cache_store = controlCacheStore_HelpCreate(NULL);
- CommandOps *ops_cache_clear = controlCacheClear_HelpCreate(NULL);
-
- snprintf(output, output_size, "Available commands:\n"
- " %s\n %s\n %s\n\n",
- ops_cache_serve->command,
- ops_cache_store->command,
- ops_cache_clear->command);
- commandOps_Destroy(&ops_cache_serve);
- commandOps_Destroy(&ops_cache_store);
- commandOps_Destroy(&ops_cache_clear);
-
- return CommandReturn_Success;
-}
-
-static void _controlCache_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state, controlCacheServe_HelpCreate(state));
- controlState_RegisterCommand(state, controlCacheStore_HelpCreate(state));
- controlState_RegisterCommand(state, controlCacheClear_HelpCreate(state));
- controlState_RegisterCommand(state, controlCacheServe_Create(state));
- controlState_RegisterCommand(state, controlCacheStore_Create(state));
- controlState_RegisterCommand(state, controlCacheClear_Create(state));
-}
-
-static CommandReturn _controlCache_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlCache_HelpExecute(parser, ops, args, output, output_size);
-}
-
-// ======================================================================
diff --git a/hicn-light/src/hicn/config/controlCacheClear.c b/hicn-light/src/hicn/config/controlCacheClear.c
deleted file mode 100644
index afd8f6fc1..000000000
--- a/hicn-light/src/hicn/config/controlCacheClear.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlCacheClear.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlCacheClear_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlCacheClear_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandCacheClear = "cache clear";
-static const char *_commandCacheClearHelp = "help cache clear";
-
-// ====================================================
-
-CommandOps *controlCacheClear_Create(ControlState *state) {
- return commandOps_Create(state, _commandCacheClear, NULL,
- _controlCacheClear_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlCacheClear_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandCacheClearHelp, NULL,
- _controlCacheClear_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlCacheClear_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "cache clear\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlCacheClear_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlCacheClear_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, CACHE_CLEAR, NULL, 0);
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlCacheClear.h b/hicn-light/src/hicn/config/controlCacheClear.h
deleted file mode 100644
index 025758c34..000000000
--- a/hicn-light/src/hicn/config/controlCacheClear.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file controlCacheClear.h
- * @brief Clear the cache
- *
- * Removes all the cached data form the local content store (if available)
- *
- */
-
-#ifndef Control_CacheClear_h
-#define Control_CacheClear_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlCacheClear_Create(ControlState *state);
-CommandOps *controlCacheClear_HelpCreate(ControlState *state);
-#endif // Control_CacheClear_h
diff --git a/hicn-light/src/hicn/config/controlCacheServe.c b/hicn-light/src/hicn/config/controlCacheServe.c
deleted file mode 100644
index a4454037d..000000000
--- a/hicn-light/src/hicn/config/controlCacheServe.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlCacheServe.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlCacheServe_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlCacheServe_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandCacheServe = "cache serve";
-static const char *_commandCacheServeHelp = "help cache serve";
-
-// ====================================================
-
-CommandOps *controlCacheServe_Create(ControlState *state) {
- return commandOps_Create(state, _commandCacheServe, NULL,
- _controlCacheServe_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlCacheServe_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandCacheServeHelp, NULL,
- _controlCacheServe_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlCacheServe_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "cache serve [on|off]\n\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlCacheServe_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 3) {
- _controlCacheServe_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- bool active;
- if (strcmp(parcList_GetAtIndex(args, 2), "on") == 0) {
- active = true;
- } else if (strcmp(parcList_GetAtIndex(args, 2), "off") == 0) {
- active = false;
- } else {
- _controlCacheServe_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- cache_serve_command *cacheServeCommand =
- parcMemory_AllocateAndClear(sizeof(cache_serve_command));
- if (active) {
- cacheServeCommand->activate = ACTIVATE_ON;
- } else {
- cacheServeCommand->activate = ACTIVATE_OFF;
- }
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, CACHE_SERVE, cacheServeCommand, sizeof(cache_serve_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlCacheServe.h b/hicn-light/src/hicn/config/controlCacheServe.h
deleted file mode 100644
index afebc0601..000000000
--- a/hicn-light/src/hicn/config/controlCacheServe.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_CacheServe_h
-#define Control_CacheServe_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlCacheServe_Create(ControlState *state);
-CommandOps *controlCacheServe_HelpCreate(ControlState *state);
-#endif // Control_CacheServe_h
diff --git a/hicn-light/src/hicn/config/controlCacheStore.c b/hicn-light/src/hicn/config/controlCacheStore.c
deleted file mode 100644
index 9f2a18146..000000000
--- a/hicn-light/src/hicn/config/controlCacheStore.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlCacheStore.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlCacheStore_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlCacheStore_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandCacheStore = "cache store";
-static const char *_commandCacheStoreHelp = "help cache store";
-
-// ====================================================
-
-CommandOps *controlCacheStore_Create(ControlState *state) {
- return commandOps_Create(state, _commandCacheStore, NULL,
- _controlCacheStore_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlCacheStore_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandCacheStoreHelp, NULL,
- _controlCacheStore_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlCacheStore_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "cache store [on|off]\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlCacheStore_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 3) {
- _controlCacheStore_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- bool active;
- if (strcmp(parcList_GetAtIndex(args, 2), "on") == 0) {
- active = true;
- } else if (strcmp(parcList_GetAtIndex(args, 2), "off") == 0) {
- active = false;
- } else {
- _controlCacheStore_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- cache_store_command *cacheStoreCommand =
- parcMemory_AllocateAndClear(sizeof(cache_store_command));
- if (active) {
- cacheStoreCommand->activate = ACTIVATE_ON;
- } else {
- cacheStoreCommand->activate = ACTIVATE_OFF;
- }
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, CACHE_STORE, cacheStoreCommand, sizeof(cache_store_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlCacheStore.h b/hicn-light/src/hicn/config/controlCacheStore.h
deleted file mode 100644
index e32bf5663..000000000
--- a/hicn-light/src/hicn/config/controlCacheStore.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_CacheStore_h
-#define Control_CacheStore_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlCacheStore_Create(ControlState *state);
-CommandOps *controlCacheStore_HelpCreate(ControlState *state);
-#endif // Control_CacheStore_h
diff --git a/hicn-light/src/hicn/config/controlList.c b/hicn-light/src/hicn/config/controlList.c
deleted file mode 100644
index 353856c43..000000000
--- a/hicn-light/src/hicn/config/controlList.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlList.h>
-#include <hicn/config/controlListConnections.h>
-//#include <hicn/config/controlListInterfaces.h>
-#include <hicn/config/controlListListeners.h>
-#include <hicn/config/controlListRoutes.h>
-#ifdef WITH_POLICY
-#include <hicn/config/controlListPolicies.h>
-#endif /* WITH_POLICY */
-
-static void _controlList_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlList_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlList_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandList = "list";
-static const char *_commandListHelp = "help list";
-
-CommandOps *controlList_Create(ControlState *state) {
- return commandOps_Create(state, _commandList, _controlList_Init,
- _controlList_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlList_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandListHelp, NULL,
- _controlList_HelpExecute, commandOps_Destroy);
-}
-
-// =====================================================
-
-static CommandReturn _controlList_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_list_connections = controlListConnections_HelpCreate(NULL);
- // CommandOps *ops_list_interfaces = controlListInterfaces_HelpCreate(NULL);
- CommandOps *ops_list_routes = controlListRoutes_HelpCreate(NULL);
- CommandOps *ops_list_listeners = controlListListeners_HelpCreate(NULL);
-#ifdef WITH_POLICY
- CommandOps *ops_list_policies = controlListPolicies_HelpCreate(NULL);
-#endif /* WITH_POLICY */
-
- snprintf(output, output_size, "Available commands:\n"
- " %s\n"
- " %s\n"
- " %s\n"
-#ifdef WITH_POLICY
- " %s\n"
-#endif /* WITH_POLICY */
- "\n",
- ops_list_connections->command,
- ops_list_routes->command,
- ops_list_listeners->command
-#ifdef WITH_POLICY
- , ops_list_policies->command
-#endif /* WITH_POLICY */
- );
-
- commandOps_Destroy(&ops_list_connections);
- // commandOps_Destroy(&ops_list_interfaces);
- commandOps_Destroy(&ops_list_routes);
- commandOps_Destroy(&ops_list_listeners);
-#ifdef WITH_POLICY
- commandOps_Destroy(&ops_list_policies);
-#endif /* WITH_POLICY */
-
- return CommandReturn_Success;
-}
-
-static void _controlList_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state, controlListConnections_HelpCreate(state));
- // controlState_RegisterCommand(state,
- // controlListInterfaces_HelpCreate(state));
- controlState_RegisterCommand(state, controlListListeners_HelpCreate(state));
- controlState_RegisterCommand(state, controlListRoutes_HelpCreate(state));
- controlState_RegisterCommand(state, controlListConnections_Create(state));
- // controlState_RegisterCommand(state, controlListInterfaces_Create(state));
- controlState_RegisterCommand(state, controlListRoutes_Create(state));
- controlState_RegisterCommand(state, controlListListeners_Create(state));
-#ifdef WITH_POLICY
- controlState_RegisterCommand(state, controlListPolicies_HelpCreate(state));
- controlState_RegisterCommand(state, controlListPolicies_Create(state));
-#endif /* WITH_POLICY */
-}
-
-static CommandReturn _controlList_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlList_HelpExecute(parser, ops, args, output, output_size);
-}
-
-// ======================================================================
diff --git a/hicn-light/src/hicn/config/controlList.h b/hicn-light/src/hicn/config/controlList.h
deleted file mode 100644
index d497e5179..000000000
--- a/hicn-light/src/hicn/config/controlList.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_List.h
- * @brief Root node for the "list" commands
- *
- * Implements the "list" node of the CLI tree.
- *
- */
-
-#ifndef controlList_h
-#define controlList_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlList_Create(ControlState *state);
-CommandOps *controlList_HelpCreate(ControlState *state);
-#endif // controlList_h
diff --git a/hicn-light/src/hicn/config/controlListConnections.c b/hicn-light/src/hicn/config/controlListConnections.c
deleted file mode 100644
index 6406ba8c3..000000000
--- a/hicn-light/src/hicn/config/controlListConnections.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlListConnections.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlListConnections_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlListConnections_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandListConnections = "list connections";
-static const char *_commandListConnectionsHelp = "help list connections";
-const char *connTypeString[6] = {"GRE", "TCP", "UDP", "MCAST", "L2", "HICN"};
-const char *stateString[3] = {"UP", "DOWN", "UNKNOWN"};
-
-CommandOps *controlListConnections_Create(ControlState *state) {
- return commandOps_Create(state, _commandListConnections, NULL,
- _controlListConnections_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlListConnections_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandListConnectionsHelp, NULL,
- _controlListConnections_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlListConnections_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
-snprintf(output, output_size, "%s", "list connections: displays a 1-line summary of each connection\n"
- "\n"
- "The columns are:\n"
- " connection id : an integer index for the connection\n"
- " state : UP or DOWN\n"
- " local address : the local network address associated with the "
- "connection\n"
- " remote address: the remote network address associated with the "
- "connection\n"
- " protocol : the network protocol (tcp, udp, gre, mcast, "
- "ether)\n"
- "\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlListConnections_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlListConnections_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-#ifdef WITH_POLICY
- char flags_str[POLICY_TAG_N+1];
- char *s;
-#endif /* WITH_POLICY */
-
- ControlState *state = ops->closure;
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, LIST_CONNECTIONS, NULL, 0);
- if (!response) { // get NULL pointer = FAILURE
- return CommandReturn_Failure;
- }
-
- // Process/Print message
- header_control_message *receivedHeader =
- (header_control_message *)response[0].iov_base;
- uint8_t *receivedPayload = (uint8_t *)response[1].iov_base;
-
- char *sourceString = NULL;
- char *destinationString = NULL;
-
- // Allocate output to pass to the main function if the call is not interactive
- char **commandOutputMain = NULL;
- if (!controlState_IsInteractive(state) && receivedHeader->length > 0) {
- commandOutputMain =
- parcMemory_Allocate(sizeof(char *) * receivedHeader->length);
- for (size_t j = 0; j < receivedHeader->length; j++) {
- commandOutputMain[j] = parcMemory_Allocate(sizeof(char) * 256);
- }
- }
-size_t output_offset = 0;
-
-#ifdef WITH_POLICY
- output_offset = snprintf(output, output_size, "%5s %10s %12s %6s %40s %40s %5s %s %s\n", "id", "name", "admin_state", "state", "source", "destination", "type", "priority", "flags");
-#else
- output_offset = snprintf(output, output_size, "%5s %10s %12s %6s %40s %40s %5s\n", "id", "name", "admin_state", "state", "source", "destination", "type");
-#endif /* WITH_POLICY */
-
- // Process/Print payload
-
- for (int i = 0; i < receivedHeader->length; i++) {
- list_connections_command *listConnectionsCommand =
- (list_connections_command *)(receivedPayload +
- (i * sizeof(list_connections_command)));
-
- sourceString = utils_CommandAddressToString(
- listConnectionsCommand->connectionData.ipType,
- &listConnectionsCommand->connectionData.localIp,
- &listConnectionsCommand->connectionData.localPort);
-
- destinationString = utils_CommandAddressToString(
- listConnectionsCommand->connectionData.ipType,
- &listConnectionsCommand->connectionData.remoteIp,
- &listConnectionsCommand->connectionData.remotePort);
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
-#ifdef WITH_POLICY
-
- s = flags_str;
-#define _(x, y) *s++ = policy_tags_has(listConnectionsCommand->connectionData.tags, POLICY_TAG_ ## x) ? y : '.';
-foreach_policy_tag
-#undef _
- *s = '\0';
-
- parcBufferComposer_Format(
- composer, "%5d %10s %12s %6s %40s %40s %5s [%6d] [%s]", listConnectionsCommand->connid, listConnectionsCommand->connectionName,
- stateString[listConnectionsCommand->connectionData.admin_state],
- stateString[listConnectionsCommand->state], sourceString,
- destinationString,
- connTypeString[listConnectionsCommand->connectionData.connectionType],
- listConnectionsCommand->connectionData.priority,
- flags_str);
-
-#else
- parcBufferComposer_Format(
- composer, "%5d %10s %12s %6s %40s %40s %5s", listConnectionsCommand->connid, listConnectionsCommand->connectionName,
- stateString[listConnectionsCommand->admin_state],
- stateString[listConnectionsCommand->state], sourceString,
- destinationString,
- connTypeString[listConnectionsCommand->connectionData.connectionType]);
-#endif /* WITH_POLICY */
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
-
- if (!controlState_IsInteractive(state)) {
- strcpy(commandOutputMain[i], result);
- }
- output_offset += snprintf(output + output_offset, output_size - output_offset, "%s\n", result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
- }
-
- controlState_SetCommandOutput(state, commandOutputMain);
-
- // DEALLOCATE
- parcMemory_Deallocate((void **)&sourceString);
- parcMemory_Deallocate((void **)&destinationString);
- parcMemory_Deallocate(&receivedHeader); // free response[0].iov_base
- parcMemory_Deallocate(&receivedPayload); // free response[1].iov_base
- parcMemory_Deallocate(&response); // free iovec pointer
-
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlListConnections.h b/hicn-light/src/hicn/config/controlListConnections.h
deleted file mode 100644
index cd5c21cec..000000000
--- a/hicn-light/src/hicn/config/controlListConnections.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_ListConnections.h
- * @brief List the current connections of hicn-light
- *
- * Implements the "list connections" node of the CLI tree
- *
- */
-
-#ifndef Control_ListConnections_h
-#define Control_ListConnections_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlListConnections_Create(ControlState *state);
-CommandOps *controlListConnections_HelpCreate(ControlState *state);
-#endif // Control_ListConnections_h
diff --git a/hicn-light/src/hicn/config/controlListInterfaces.c b/hicn-light/src/hicn/config/controlListInterfaces.c
deleted file mode 100644
index c632a1d21..000000000
--- a/hicn-light/src/hicn/config/controlListInterfaces.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlListInterfaces.h>
-
-static CommandReturn _controlListInterfaces_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlListInterfaces_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandListInterfaces = "list interfaces";
-static const char *_commandListInterfacesHelp = "help list interfaces";
-
-// ====================================================
-
-CommandOps *controlListInterfaces_Create(ControlState *state) {
- return commandOps_Create(state, _commandListInterfaces, NULL,
- _controlListInterfaces_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlListInterfaces_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandListInterfacesHelp, NULL,
- _controlListInterfaces_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlListInterfaces_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "list interfaces\n\n")
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlListInterfaces_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlListInterfaces_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- //========================== NOT IMPLEMENTED
- //===========================
-
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlListInterfaces.h b/hicn-light/src/hicn/config/controlListInterfaces.h
deleted file mode 100644
index f885835ed..000000000
--- a/hicn-light/src/hicn/config/controlListInterfaces.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_ListInterfaces.h
- * @brief List the icn-light interfaces
- *
- * Implements the "list interfaces" and "help list interfaces" nodes of the
- * command tree
- *
- */
-
-#ifndef Control_ListInterfaces_h
-#define Control_ListInterfaces_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlListInterfaces_Create(ControlState *state);
-CommandOps *controlListInterfaces_HelpCreate(ControlState *state);
-#endif // Control_ListInterfaces_h
diff --git a/hicn-light/src/hicn/config/controlListListeners.c b/hicn-light/src/hicn/config/controlListListeners.c
deleted file mode 100644
index c189dfc36..000000000
--- a/hicn-light/src/hicn/config/controlListListeners.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/config/controlListListeners.h>
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlListListeners_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlListListeners_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandListListeners = "list listeners";
-static const char *_commandListListenersHelp = "help list listeners";
-static const char *listenerType[5] = {"TCP", "UDP", "ETHER", "LOCAL", "HICN"};
-
-// ====================================================
-
-CommandOps *controlListListeners_Create(ControlState *state) {
- return commandOps_Create(state, _commandListListeners, NULL,
- _controlListListeners_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlListListeners_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandListListenersHelp, NULL,
- _controlListListeners_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlListListeners_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "list listeners\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlListListeners_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlListListeners_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- ControlState *state = ops->closure;
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, LIST_LISTENERS, NULL, 0);
- if (!response) { // get NULL pointer = FAILURE
- return CommandReturn_Failure;
- }
-
- // Process/Print message
- header_control_message *receivedHeader =
- (header_control_message *)response[0].iov_base;
- uint8_t *receivedPayload = (uint8_t *)response[1].iov_base;
-
- // Allocate output to pass to the main function if the call is not interactive
- char **commandOutputMain = NULL;
- if (!controlState_IsInteractive(state) && receivedHeader->length > 0) {
- commandOutputMain =
- parcMemory_Allocate(sizeof(char *) * receivedHeader->length);
- for (size_t j = 0; j < receivedHeader->length; j++) {
- commandOutputMain[j] = parcMemory_Allocate(sizeof(char) * 128);
- }
- }
-
- char *addrString = NULL;
- size_t output_offset = 0;
- if (receivedHeader->length > 0) {
- output_offset = snprintf(output, output_size, "%6.6s %.*s %50.70s %6s %10s\n", "iface", SYMBOLIC_NAME_LEN, "name", "address", "type", "interface");
-
- } else {
- output_offset = snprintf(output, output_size, " --- No entry in the list \n");
- }
-
- for (int i = 0; i < receivedHeader->length; i++) {
- list_listeners_command *listListenersCommand =
- (list_listeners_command *)(receivedPayload +
- (i * sizeof(list_listeners_command)));
-
- addrString = utils_CommandAddressToString(listListenersCommand->addressType,
- &listListenersCommand->address,
- &listListenersCommand->port);
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
- if (strcmp(listenerType[listListenersCommand->encapType], "UDP") == 0 ||
- strcmp(listenerType[listListenersCommand->encapType], "TCP") == 0) {
- parcBufferComposer_Format(composer, "%6u %.*s %50.70s %6s %10s",
- listListenersCommand->connid,
- SYMBOLIC_NAME_LEN, listListenersCommand->listenerName,
- addrString,
- listenerType[listListenersCommand->encapType],
- listListenersCommand->interfaceName);
- } else {
- parcBufferComposer_Format(composer, "%6u %.*s %50.70s %6s",
- listListenersCommand->connid,
- SYMBOLIC_NAME_LEN, listListenersCommand->listenerName,
- addrString,
- listenerType[listListenersCommand->encapType]);
- }
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
-
- if (!controlState_IsInteractive(state)) {
- strncpy(commandOutputMain[i], result, 128);
- }
- output_offset += snprintf(output + output_offset, output_size - output_offset, "%s\n", result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
- }
-
- controlState_SetCommandOutput(state, commandOutputMain);
-
- // DEALLOCATE
- parcMemory_Deallocate((void **)&addrString);
- parcMemory_Deallocate(&receivedHeader); // free response[0].iov_base
- parcMemory_Deallocate(&receivedPayload); // free response[1].iov_base
- parcMemory_Deallocate(&response); // free iovec pointer
-
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlListListeners.h b/hicn-light/src/hicn/config/controlListListeners.h
deleted file mode 100644
index 11ec07579..000000000
--- a/hicn-light/src/hicn/config/controlListListeners.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_ListListeners.h
- * @brief List the icn-light listeners
- *
- * Implements the "list listeners" and "help list listeners" nodes of the
- * command tree
- *
- */
-
-#ifndef Control_ListListeners_h
-#define Control_ListListeners_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlListListeners_Create(ControlState *state);
-CommandOps *controlListListeners_HelpCreate(ControlState *state);
-#endif // Control_ListListeners_h
diff --git a/hicn-light/src/hicn/config/controlListPolicies.c b/hicn-light/src/hicn/config/controlListPolicies.c
deleted file mode 100644
index 8eae6453b..000000000
--- a/hicn-light/src/hicn/config/controlListPolicies.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef WITH_POLICY
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Time.h>
-
-#include <hicn/config/controlListPolicies.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlListPolicies_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlListPolicies_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandListPolicies = "list policies";
-static const char *_commandListPoliciesHelp = "help list policies";
-
-// ====================================================
-
-CommandOps *controlListPolicies_Create(ControlState *state) {
- return commandOps_Create(state, _commandListPolicies, NULL,
- _controlListPolicies_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlListPolicies_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandListPoliciesHelp, NULL,
- _controlListPolicies_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlListPolicies_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "command: list policies\n\n");
- return CommandReturn_Success;
-}
-
-#define MAX(x,y) (x > y ? x : y)
-#define MAXSZ_COLUMN MAX(MAXSZ_POLICY_TAG, MAXSZ_POLICY_TAG_STATE)
-
-#define MAXSZ_STR_STAT 10
-#define MAXSZ_APP_NAME 25
-
-typedef struct {
- #define _(x, y) char x[MAXSZ_POLICY_TAG_STATE];
- foreach_policy_tag
- #undef _
-} tag_state_str_t;
-
-static CommandReturn _controlListPolicies_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlListPolicies_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- ControlState *state = ops->closure;
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, LIST_POLICIES, NULL, 0);
- if (!response) { // get NULL pointer = FAILURE
- return CommandReturn_Failure;
- }
-
- // Process/Print message
- header_control_message *receivedHeader =
- (header_control_message *)response[0].iov_base;
- uint8_t *receivedPayload = (uint8_t *)response[1].iov_base;
- if (!receivedPayload) {
- snprintf(output, output_size, "No payload!\n");
- return CommandReturn_Failure;
- }
-
- // Allocate output to pass to the main function if the call is not interactive
- char **commandOutputMain = NULL;
- if (!controlState_IsInteractive(state) && receivedHeader->length > 0) {
- commandOutputMain =
- parcMemory_Allocate(sizeof(char *) * receivedHeader->length);
- for (size_t j = 0; j < receivedHeader->length; j++) {
- commandOutputMain[j] = parcMemory_Allocate(sizeof(char) * 128);
- }
- }
-
- char *addrString = NULL;
- in_port_t port = htons(1234); // this is a random port number that is ignored
- size_t output_offset = 0;
- if (receivedHeader->length > 0) {
- output_offset += snprintf(output, output_size, "%*s %*s", MAXSZ_PREFIX, "prefix", MAXSZ_APP_NAME /*APP_NAME_LEN*/, "app_name");
- #define _(x, y) output_offset += snprintf(output + output_offset, output_size - output_offset, " %*s",MAXSZ_COLUMN, policy_tag_str[POLICY_TAG_ ## x]);
- foreach_policy_tag
- #undef _
- output_offset += snprintf(output + output_offset, output_size - output_offset, "\n");
- } else {
- output_offset += snprintf(output, output_size, " --- No entry in the list \n");
- }
-
- tag_state_str_t str;
-
- for (int i = 0; i < receivedHeader->length; i++) {
- list_policies_command *listPoliciesCommand =
- (list_policies_command *)(receivedPayload +
- (i * sizeof(list_policies_command)));
-
-#if 0
- char tag_s[MAXSZ_POLICY_TAG_STATE * POLICY_TAG_N];
-
- policy_tag_state_snprintf((char*)&tag_s[MAXSZ_POLICY_TAG_STATE * POLICY_TAG_ ## x], \
- MAXSZ_POLICY_TAG_STATE, \
- &listPoliciesCommand->policy.tags[POLICY_TAG_ ## x]);
-#endif
-
- #define _(x, y) policy_tag_state_snprintf(str.x, MAXSZ_POLICY_TAG_STATE, &listPoliciesCommand->policy.tags[POLICY_TAG_ ## x]);
- foreach_policy_tag
- #undef _
-
- addrString = utils_CommandAddressToString(
- listPoliciesCommand->addressType, &listPoliciesCommand->address, &port);
-
-#if 0
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
- parcBufferComposer_Format(
- composer, "%*s %*s"
- #define _(x, y) " %*s"
- foreach_policy_tag
- #undef _
- "%s",
- MAXSZ_PREFIX, addrString, APP_NAME_LEN, listPoliciesCommand->policy.app_name,
- #define _(x, y) MAXSZ_COLUMN, str.x,
- foreach_policy_tag
- #undef _
- "");
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
-
- if (!controlState_IsInteractive(state)) {
- strcpy(commandOutputMain[i], result);
- }
-
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-#else
-
- output_offset = snprintf(output + output_offset, output_size - output_offset, "%*s %*s",
- MAXSZ_PREFIX, addrString, MAXSZ_APP_NAME /*APP_NAME_LEN*/, listPoliciesCommand->policy.app_name);
- #define _(x, y) output_offset += snprintf(output + output_offset, output_size - output_offset, " %*s", MAXSZ_COLUMN, str.x);
- foreach_policy_tag
- #undef _
-
- output_offset = snprintf(output + output_offset, output_size - output_offset, "\n");
-
-
- /*printf("%*s %*s"
- #define _(x, y) " %*s"
- foreach_policy_tag
- #undef _
- "%s\n",
- MAXSZ_PREFIX, addrString, MAXSZ_APP_NAME *//*APP_NAME_LEN*//*, listPoliciesCommand->policy.app_name,
- #define _(x, y) MAXSZ_COLUMN, str.x,
- foreach_policy_tag
- #undef _
- "");*/
-
-#endif
- }
-
- output_offset += snprintf(output + output_offset, output_size - output_offset, "\nSTATISTICS\n\n");
- // STATISTICS
- output_offset += snprintf(output + output_offset, output_size - output_offset, "%*s %*s %*s | %*s | %*s | %*s\n",
- MAXSZ_PREFIX, "", MAXSZ_APP_NAME /*APP_NAME_LEN*/, "",
- 3*MAXSZ_STR_STAT+2, "WIRED", 3*MAXSZ_STR_STAT+2, "WIFI", 3*MAXSZ_STR_STAT+2, "CELLULAR", 3*MAXSZ_STR_STAT+2, "ALL");
- output_offset += snprintf(output + output_offset, output_size - output_offset, "%*s %*s %*s %*s %*s | %*s %*s %*s | %*s %*s %*s | %*s %*s %*s\n",
- MAXSZ_PREFIX, "prefix", MAXSZ_APP_NAME /*APP_NAME_LEN*/, "app_name",
- MAXSZ_STR_STAT, "throughput", MAXSZ_STR_STAT, "latency", MAXSZ_STR_STAT, "loss_rate",
- MAXSZ_STR_STAT, "throughput", MAXSZ_STR_STAT, "latency", MAXSZ_STR_STAT, "loss_rate",
- MAXSZ_STR_STAT, "throughput", MAXSZ_STR_STAT, "latency", MAXSZ_STR_STAT, "loss_rate",
- MAXSZ_STR_STAT, "throughput", MAXSZ_STR_STAT, "latency", MAXSZ_STR_STAT, "loss_rate");
- for (int i = 0; i < receivedHeader->length; i++) {
- list_policies_command *listPoliciesCommand =
- (list_policies_command *)(receivedPayload +
- (i * sizeof(list_policies_command)));
- addrString = utils_CommandAddressToString(
- listPoliciesCommand->addressType, &listPoliciesCommand->address, &port);
- output_offset += snprintf(output + output_offset, output_size - output_offset, "%*s %*s %*.2f %*.2f %*.2f | %*.2f %*.2f %*.2f | %*.2f %*.2f %*.2f | %*.2f %*.2f %*.2f\n",
- MAXSZ_PREFIX, addrString, MAXSZ_APP_NAME, listPoliciesCommand->policy.app_name,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wired.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wired.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wired.loss_rate,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wifi.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wifi.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wifi.loss_rate,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.cellular.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.cellular.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.cellular.loss_rate,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.all.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.all.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.all.loss_rate);
- }
-
- controlState_SetCommandOutput(state, commandOutputMain);
-
- // DEALLOCATE
- parcMemory_Deallocate((void **)&addrString);
- parcMemory_Deallocate(&receivedHeader); // free response[0].iov_base
- parcMemory_Deallocate(&receivedPayload); // free response[1].iov_base
- parcMemory_Deallocate(&response); // free iovec pointer
-
- return CommandReturn_Success;
-}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/config/controlListPolicies.h b/hicn-light/src/hicn/config/controlListPolicies.h
deleted file mode 100644
index 7aa0bdd26..000000000
--- a/hicn-light/src/hicn/config/controlListPolicies.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_ListPolicies.h
- * @brief List the icn-light policies
- *
- * Implements the "list policies" and "help list policies" nodes of the command tree
- *
- */
-#ifndef Control_ListPolicies_h
-#define Control_ListPolicies_h
-
-#ifdef WITH_POLICY
-
-#include <hicn/config/controlState.h>
-CommandOps *controlListPolicies_Create(ControlState *state);
-CommandOps *controlListPolicies_HelpCreate(ControlState *state);
-
-#endif /* WITH_POLICY */
-
-#endif // Control_ListPolicies_h
diff --git a/hicn-light/src/hicn/config/controlListRoutes.c b/hicn-light/src/hicn/config/controlListRoutes.c
deleted file mode 100644
index 395251b94..000000000
--- a/hicn-light/src/hicn/config/controlListRoutes.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Time.h>
-
-#include <hicn/config/controlListRoutes.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlListRoutes_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlListRoutes_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandListRoutes = "list routes";
-static const char *_commandListRoutesHelp = "help list routes";
-
-// ====================================================
-
-CommandOps *controlListRoutes_Create(ControlState *state) {
- return commandOps_Create(state, _commandListRoutes, NULL,
- _controlListRoutes_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlListRoutes_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandListRoutesHelp, NULL,
- _controlListRoutes_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlListRoutes_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "command: list routes\n"
- "\n"
- "This command will fetch the prefix routing table. For each route, it "
- "will list:\n"
- " iface: interface\n"
- " protocol: the routing protocol, such as STATIC, CONNECTED, etc.\n"
- " type: LMP or EXACT (longest matching prefix or exact match)\n"
- " cost: The route cost, lower being preferred\n"
- " next: List of next hops by interface id\n"
- " prefix: name prefix\n"
- "\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlListRoutes_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlListRoutes_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- ControlState *state = ops->closure;
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, LIST_ROUTES, NULL, 0);
- if (!response) { // get NULL pointer = FAILURE
- return CommandReturn_Failure;
- }
-
- // Process/Print message
- header_control_message *receivedHeader =
- (header_control_message *)response[0].iov_base;
- uint8_t *receivedPayload = (uint8_t *)response[1].iov_base;
-
- // Allocate output to pass to the main function if the call is not interactive
- char **commandOutputMain = NULL;
- if (!controlState_IsInteractive(state) && receivedHeader->length > 0) {
- commandOutputMain =
- parcMemory_Allocate(sizeof(char *) * receivedHeader->length);
- for (size_t j = 0; j < receivedHeader->length; j++) {
- commandOutputMain[j] = parcMemory_Allocate(sizeof(char) * 128);
- }
- }
-
- char *addrString = NULL;
- in_port_t port = htons(1234); // this is a random port number that is ignored
- size_t output_offset = 0;
- if (receivedHeader->length > 0) {
- output_offset = snprintf(output, output_size, "%6.6s %8.8s %70.70s %s\n", "iface", "cost", "prefix", "len");
- } else {
- output_offset = snprintf(output, output_size, " --- No entry in the list \n");
- }
-
- for (int i = 0; i < receivedHeader->length; i++) {
- list_routes_command *listRoutesCommand =
- (list_routes_command *)(receivedPayload +
- (i * sizeof(list_routes_command)));
-
- addrString = utils_CommandAddressToString(
- listRoutesCommand->addressType, &listRoutesCommand->address, &port);
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
- parcBufferComposer_Format(
- composer, "%6u %8u %70.70s %3d", listRoutesCommand->connid,
- listRoutesCommand->cost, addrString, listRoutesCommand->len);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
-
- if (!controlState_IsInteractive(state)) {
- strcpy(commandOutputMain[i], result);
- }
-
- output_offset += snprintf(output + output_offset, output_size - output_offset, "%s\n", result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
- }
-
- controlState_SetCommandOutput(state, commandOutputMain);
-
- // DEALLOCATE
- parcMemory_Deallocate((void **)&addrString);
- parcMemory_Deallocate(&receivedHeader); // free response[0].iov_base
- parcMemory_Deallocate(&receivedPayload); // free response[1].iov_base
- parcMemory_Deallocate(&response); // free iovec pointer
-
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlListRoutes.h b/hicn-light/src/hicn/config/controlListRoutes.h
deleted file mode 100644
index 341552add..000000000
--- a/hicn-light/src/hicn/config/controlListRoutes.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_ListRoutes.h
- * @brief List the icn-light routes
- *
- * Implements the "list routes" and "help list routes" nodes of the command tree
- *
- */
-#ifndef Control_ListRoutes_h
-#define Control_ListRoutes_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlListRoutes_Create(ControlState *state);
-CommandOps *controlListRoutes_HelpCreate(ControlState *state);
-#endif // Control_ListRoutes_h
diff --git a/hicn-light/src/hicn/config/controlMapMe.c b/hicn-light/src/hicn/config/controlMapMe.c
deleted file mode 100644
index b292ee0f0..000000000
--- a/hicn-light/src/hicn/config/controlMapMe.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/config/controlMapMe.h>
-#include <hicn/config/controlMapMeDiscovery.h>
-#include <hicn/config/controlMapMeEnable.h>
-#include <hicn/config/controlMapMeRetx.h>
-#include <hicn/config/controlMapMeTimescale.h>
-
-static void _controlMapMe_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlMapMe_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlMapMe_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandMapMe = "mapme";
-static const char *_commandMapMeHelp = "help mapme";
-
-CommandOps *controlMapMe_Create(ControlState *state) {
- return commandOps_Create(state, _commandMapMe, _controlMapMe_Init,
- _controlMapMe_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlMapMe_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandMapMeHelp, NULL,
- _controlMapMe_HelpExecute, commandOps_Destroy);
-}
-
-// =====================================================
-
-static CommandReturn _controlMapMe_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_mapme_enable = controlMapMeEnable_HelpCreate(NULL);
- CommandOps *ops_mapme_discovery = controlMapMeDiscovery_HelpCreate(NULL);
- CommandOps *ops_mapme_timescale = controlMapMeTimescale_HelpCreate(NULL);
- CommandOps *ops_mapme_retx = controlMapMeRetx_HelpCreate(NULL);
-
- snprintf(output, output_size, "Available commands:\n"
- " %s\n %s\n %s\n %s\n\n",
- ops_mapme_enable->command,
- ops_mapme_discovery->command,
- ops_mapme_timescale->command,
- ops_mapme_retx->command);
-
- commandOps_Destroy(&ops_mapme_enable);
- commandOps_Destroy(&ops_mapme_discovery);
- commandOps_Destroy(&ops_mapme_timescale);
- commandOps_Destroy(&ops_mapme_retx);
-
- return CommandReturn_Success;
-}
-
-static void _controlMapMe_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state, controlMapMeEnable_HelpCreate(state));
- controlState_RegisterCommand(state, controlMapMeDiscovery_HelpCreate(state));
- controlState_RegisterCommand(state, controlMapMeTimescale_HelpCreate(state));
- controlState_RegisterCommand(state, controlMapMeRetx_HelpCreate(state));
- controlState_RegisterCommand(state, controlMapMeEnable_Create(state));
- controlState_RegisterCommand(state, controlMapMeDiscovery_Create(state));
- controlState_RegisterCommand(state, controlMapMeTimescale_Create(state));
- controlState_RegisterCommand(state, controlMapMeRetx_Create(state));
-}
-
-static CommandReturn _controlMapMe_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlMapMe_HelpExecute(parser, ops, args, output, output_size);
-}
-
-// ======================================================================
diff --git a/hicn-light/src/hicn/config/controlMapMe.h b/hicn-light/src/hicn/config/controlMapMe.h
deleted file mode 100644
index 3edd78989..000000000
--- a/hicn-light/src/hicn/config/controlMapMe.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef controlMapMe_h
-#define controlMapMe_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlMapMe_Create(ControlState *state);
-CommandOps *controlMapMe_HelpCreate(ControlState *state);
-#endif // controlMapMe_h
diff --git a/hicn-light/src/hicn/config/controlMapMeDiscovery.c b/hicn-light/src/hicn/config/controlMapMeDiscovery.c
deleted file mode 100644
index 6ec941141..000000000
--- a/hicn-light/src/hicn/config/controlMapMeDiscovery.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/controlMapMeDiscovery.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlMapMeDiscovery_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlMapMeDiscovery_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandMapMeDiscovery = "mapme discovery";
-static const char *_commandMapMeDiscoveryHelp = "help mapme discovery";
-
-// ====================================================
-
-CommandOps *controlMapMeDiscovery_Create(ControlState *state) {
- return commandOps_Create(state, _commandMapMeDiscovery, NULL,
- _controlMapMeDiscovery_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlMapMeDiscovery_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandMapMeDiscoveryHelp, NULL,
- _controlMapMeDiscovery_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlMapMeDiscovery_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "mapme discovery [on|off]\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlMapMeDiscovery_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 3) {
- _controlMapMeDiscovery_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- bool active;
- if (strcmp(parcList_GetAtIndex(args, 2), "on") == 0) {
- active = true;
- } else if (strcmp(parcList_GetAtIndex(args, 2), "off") == 0) {
- active = false;
- } else {
- _controlMapMeDiscovery_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- mapme_activator_command *mapmeDiscoveryCommand =
- parcMemory_AllocateAndClear(sizeof(mapme_activator_command));
- if (active) {
- mapmeDiscoveryCommand->activate = ACTIVATE_ON;
- } else {
- mapmeDiscoveryCommand->activate = ACTIVATE_OFF;
- }
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response =
- utils_SendRequest(state, MAPME_DISCOVERY, mapmeDiscoveryCommand,
- sizeof(mapme_activator_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlMapMeDiscovery.h b/hicn-light/src/hicn/config/controlMapMeDiscovery.h
deleted file mode 100644
index c2832632a..000000000
--- a/hicn-light/src/hicn/config/controlMapMeDiscovery.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_MapMeDiscovery_h
-#define Control_MapMeDiscovery_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlMapMeDiscovery_Create(ControlState *state);
-CommandOps *controlMapMeDiscovery_HelpCreate(ControlState *state);
-#endif // Control_MapMeDiscovery_h
diff --git a/hicn-light/src/hicn/config/controlMapMeEnable.c b/hicn-light/src/hicn/config/controlMapMeEnable.c
deleted file mode 100644
index 0595cc346..000000000
--- a/hicn-light/src/hicn/config/controlMapMeEnable.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/controlMapMeEnable.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlMapMeEnable_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlMapMeEnable_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandMapMeEnable = "mapme enable";
-static const char *_commandMapMeEnableHelp = "help mapme enable";
-
-// ====================================================
-
-CommandOps *controlMapMeEnable_Create(ControlState *state) {
- return commandOps_Create(state, _commandMapMeEnable, NULL,
- _controlMapMeEnable_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlMapMeEnable_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandMapMeEnableHelp, NULL,
- _controlMapMeEnable_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlMapMeEnable_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "mapme enable [on|off]\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlMapMeEnable_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 3) {
- _controlMapMeEnable_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- bool active;
- if (strcmp(parcList_GetAtIndex(args, 2), "on") == 0) {
- active = true;
- } else if (strcmp(parcList_GetAtIndex(args, 2), "off") == 0) {
- active = false;
- } else {
- _controlMapMeEnable_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- mapme_activator_command *mapmeEnableCommand =
- parcMemory_AllocateAndClear(sizeof(mapme_activator_command));
- if (active) {
- mapmeEnableCommand->activate = ACTIVATE_ON;
- } else {
- mapmeEnableCommand->activate = ACTIVATE_OFF;
- }
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, MAPME_ENABLE, mapmeEnableCommand, sizeof(mapme_activator_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlMapMeEnable.h b/hicn-light/src/hicn/config/controlMapMeEnable.h
deleted file mode 100644
index 0ce4970f3..000000000
--- a/hicn-light/src/hicn/config/controlMapMeEnable.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_MapMeEnable_h
-#define Control_MapMeEnable_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlMapMeEnable_Create(ControlState *state);
-CommandOps *controlMapMeEnable_HelpCreate(ControlState *state);
-#endif // Control_MapMeEnable_h
diff --git a/hicn-light/src/hicn/config/controlMapMeRetx.c b/hicn-light/src/hicn/config/controlMapMeRetx.c
deleted file mode 100644
index 9f37ca6f5..000000000
--- a/hicn-light/src/hicn/config/controlMapMeRetx.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/controlMapMeRetx.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlMapMeRetx_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlMapMeRetx_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandMapMeRetx = "mapme retx";
-static const char *_commandMapMeRetxHelp = "help mapme retx";
-
-// ====================================================
-
-CommandOps *controlMapMeRetx_Create(ControlState *state) {
- return commandOps_Create(state, _commandMapMeRetx, NULL,
- _controlMapMeRetx_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlMapMeRetx_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandMapMeRetxHelp, NULL,
- _controlMapMeRetx_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlMapMeRetx_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "mapme retx <milliseconds>\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlMapMeRetx_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 3) {
- _controlMapMeRetx_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *rtx = parcList_GetAtIndex(args, 2);
- if (!utils_IsNumber(rtx)) {
- snprintf(output, output_size,
- "ERROR: retransmission value (expressed in ms) must be a positive "
- "integer \n");
- return CommandReturn_Failure;
- }
-
- mapme_timing_command *mapmeRetxCommand =
- parcMemory_AllocateAndClear(sizeof(mapme_timing_command));
- mapmeRetxCommand->timePeriod = (unsigned)strtold(rtx, NULL);
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, MAPME_RETX, mapmeRetxCommand, sizeof(mapme_timing_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlMapMeRetx.h b/hicn-light/src/hicn/config/controlMapMeRetx.h
deleted file mode 100644
index 3e3b2de15..000000000
--- a/hicn-light/src/hicn/config/controlMapMeRetx.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_MapMeRetx_h
-#define Control_MapMeRetx_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlMapMeRetx_Create(ControlState *state);
-CommandOps *controlMapMeRetx_HelpCreate(ControlState *state);
-#endif // Control_MapMeRetx_h
diff --git a/hicn-light/src/hicn/config/controlMapMeTimescale.c b/hicn-light/src/hicn/config/controlMapMeTimescale.c
deleted file mode 100644
index 51701aa2f..000000000
--- a/hicn-light/src/hicn/config/controlMapMeTimescale.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/controlMapMeTimescale.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlMapMeTimescale_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlMapMeTimescale_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandMapMeTimescale = "mapme timescale";
-static const char *_commandMapMeTimescaleHelp = "help mapme timescale";
-
-// ====================================================
-
-CommandOps *controlMapMeTimescale_Create(ControlState *state) {
- return commandOps_Create(state, _commandMapMeTimescale, NULL,
- _controlMapMeTimescale_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlMapMeTimescale_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandMapMeTimescaleHelp, NULL,
- _controlMapMeTimescale_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlMapMeTimescale_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "mapme timescale <milliseconds>\n\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlMapMeTimescale_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 3) {
- _controlMapMeTimescale_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *ts = parcList_GetAtIndex(args, 2);
- if (!utils_IsNumber(ts)) {
- snprintf(output, output_size,
- "ERROR: timescale value (expressed in ms) must be a positive integer "
- "\n");
- return CommandReturn_Failure;
- }
-
- mapme_timing_command *mapmeTimescaleCommand =
- parcMemory_AllocateAndClear(sizeof(mapme_timing_command));
- mapmeTimescaleCommand->timePeriod = (unsigned)strtold(ts, NULL);
-
- ControlState *state = ops->closure;
- // send message and receive response
- struct iovec *response =
- utils_SendRequest(state, MAPME_TIMESCALE, mapmeTimescaleCommand,
- sizeof(mapme_timing_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlMapMeTimescale.h b/hicn-light/src/hicn/config/controlMapMeTimescale.h
deleted file mode 100644
index 947d00a5d..000000000
--- a/hicn-light/src/hicn/config/controlMapMeTimescale.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_MapMeTimescale_h
-#define Control_MapMeTimescale_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlMapMeTimescale_Create(ControlState *state);
-CommandOps *controlMapMeTimescale_HelpCreate(ControlState *state);
-#endif // Control_MapMeTimescale_h
diff --git a/hicn-light/src/hicn/config/controlQuit.c b/hicn-light/src/hicn/config/controlQuit.c
deleted file mode 100644
index 621880d13..000000000
--- a/hicn-light/src/hicn/config/controlQuit.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/security/parc_Security.h>
-
-#include <hicn/config/controlQuit.h>
-
-static CommandReturn _controlQuit_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlQuit_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandQuit = "quit";
-static const char *_commandQuitHelp = "help quit";
-
-// ====================================================
-
-CommandOps *controlQuit_Create(ControlState *state) {
- return commandOps_Create(state, _commandQuit, NULL, _controlQuit_Execute,
- commandOps_Destroy);
-}
-
-CommandOps *controlQuit_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandQuitHelp, NULL,
- _controlQuit_HelpExecute, commandOps_Destroy);
-}
-
-// ==============================================
-
-static CommandReturn _controlQuit_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "Exits the interactive control program\n\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlQuit_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "exiting interactive shell\n");
- return CommandReturn_Exit;
-}
diff --git a/hicn-light/src/hicn/config/controlQuit.h b/hicn-light/src/hicn/config/controlQuit.h
deleted file mode 100644
index b45d5e215..000000000
--- a/hicn-light/src/hicn/config/controlQuit.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_Quit.h
- * @brief The quit command
- *
- * Implements the "quit" and "help quit" nodes of the command tree
- *
- */
-#ifndef Control_Quit_h
-#define Control_Quit_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlQuit_Create(ControlState *state);
-CommandOps *controlQuit_HelpCreate(ControlState *state);
-#endif // Control_Quit_h
diff --git a/hicn-light/src/hicn/config/controlRemove.c b/hicn-light/src/hicn/config/controlRemove.c
deleted file mode 100644
index b1a88b5c1..000000000
--- a/hicn-light/src/hicn/config/controlRemove.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlRemove.h>
-#include <hicn/config/controlRemoveListener.h>
-#include <hicn/config/controlRemoveConnection.h>
-#include <hicn/config/controlRemovePunting.h>
-#include <hicn/config/controlRemoveRoute.h>
-#ifdef WITH_POLICY
-#include <hicn/config/controlRemovePolicy.h>
-#endif /* WITH_POLICY */
-
-static void _controlRemove_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlRemove_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRemove_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandRemove = "remove";
-static const char *_commandRemoveHelp = "help remove";
-
-// ====================================================
-
-CommandOps *controlRemove_Create(ControlState *state) {
- return commandOps_Create(state, _commandRemove, _controlRemove_Init,
- _controlRemove_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlRemove_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRemoveHelp, NULL,
- _controlRemove_HelpExecute, commandOps_Destroy);
-}
-
-// ==============================================
-
-static CommandReturn _controlRemove_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_remove_connection = controlRemoveConnection_Create(NULL);
- CommandOps *ops_remove_listener = controlRemoveListener_Create(NULL);
- CommandOps *ops_remove_route = controlRemoveRoute_Create(NULL);
- CommandOps *ops_remove_punting = controlRemovePunting_Create(NULL);
-#ifdef WITH_POLICY
- CommandOps *ops_remove_policy = controlRemovePolicy_Create(NULL);
-#endif /* WITH_POLICY */
-
- snprintf(output, output_size, "Available commands:\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
-#ifdef WITH_POLICY
- " %s\n"
-#endif /* WITH_POLICY */
- "\n",
- ops_remove_connection->command,
- ops_remove_listener->command,
- ops_remove_route->command,
- ops_remove_punting->command
-#ifdef WITH_POLICY
- , ops_remove_policy->command
-#endif /* WITH_POLICY */
- );
-
- commandOps_Destroy(&ops_remove_connection);
- commandOps_Destroy(&ops_remove_listener);
- commandOps_Destroy(&ops_remove_route);
- commandOps_Destroy(&ops_remove_punting);
-#ifdef WITH_POLICY
- commandOps_Destroy(&ops_remove_policy);
-#endif /* WITH_POLICY */
- return CommandReturn_Success;
-}
-
-static void _controlRemove_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state,
- controlRemoveConnection_HelpCreate(state));
- controlState_RegisterCommand(state,
- controlRemoveListener_HelpCreate(state));
- controlState_RegisterCommand(state, controlRemoveRoute_HelpCreate(state));
- controlState_RegisterCommand(state, controlRemoveConnection_Create(state));
- controlState_RegisterCommand(state, controlRemoveListener_Create(state));
- controlState_RegisterCommand(state, controlRemoveRoute_Create(state));
- controlState_RegisterCommand(state, controlRemovePunting_Create(state));
- controlState_RegisterCommand(state, controlRemovePunting_HelpCreate(state));
-#ifdef WITH_POLICY
- controlState_RegisterCommand(state, controlRemovePolicy_HelpCreate(state));
- controlState_RegisterCommand(state, controlRemovePolicy_Create(state));
-#endif /* WITH_POLICY */
-}
-
-static CommandReturn _controlRemove_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlRemove_HelpExecute(parser, ops, args, output, output_size);
-}
diff --git a/hicn-light/src/hicn/config/controlRemove.h b/hicn-light/src/hicn/config/controlRemove.h
deleted file mode 100644
index 863555728..000000000
--- a/hicn-light/src/hicn/config/controlRemove.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_Remove.h
- * @brief Implements the remove node of the CLI tree
- *
- * Implements the "remove" and "help remove" nodes of the command tree
- *
- */
-#ifndef controlRemove_h
-#define controlRemove_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRemove_Create(ControlState *state);
-CommandOps *controlRemove_HelpCreate(ControlState *state);
-#endif // controlRemove_h
diff --git a/hicn-light/src/hicn/config/controlRemoveConnection.c b/hicn-light/src/hicn/config/controlRemoveConnection.c
deleted file mode 100644
index a6cfae1e5..000000000
--- a/hicn-light/src/hicn/config/controlRemoveConnection.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <hicn/utils/address.h>
-
-#include <hicn/config/controlRemoveConnection.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlRemoveConnection_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRemoveConnection_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *_commandRemoveConnection = "remove connection";
-static const char *_commandRemoveConnectionHelp = "help remove connection";
-
-// ====================================================
-
-CommandOps *controlRemoveConnection_Create(ControlState *state) {
- return commandOps_Create(state, _commandRemoveConnection, NULL,
- _controlRemoveConnection_Execute,
- commandOps_Destroy);
-}
-
-CommandOps *controlRemoveConnection_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRemoveConnectionHelp, NULL,
- _controlRemoveConnection_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlRemoveConnection_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "command:\n"
- " remove connection <symbolic|id>\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlRemoveConnection_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 3) {
- _controlRemoveConnection_HelpExecute(parser, ops, args, output, output_size);
- return false;
- }
-
- if ((strcmp(parcList_GetAtIndex(args, 0), "remove") != 0) ||
- (strcmp(parcList_GetAtIndex(args, 1), "connection") != 0)) {
- _controlRemoveConnection_HelpExecute(parser, ops, args, output, output_size);
- return false;
- }
-
- const char *symbolicOrConnid = parcList_GetAtIndex(args, 2);
-
- if (!utils_ValidateSymbolicName(symbolicOrConnid) &&
- !utils_IsNumber(symbolicOrConnid)) {
- snprintf(output, output_size,
- "ERROR: Invalid symbolic or connid:\nsymbolic name must begin with an "
- "alpha followed by alphanum;\nconnid must be an integer\n");
- return CommandReturn_Failure;
- }
-
- // allocate command payload
- remove_connection_command *removeConnectionCommand =
- parcMemory_AllocateAndClear(sizeof(remove_connection_command));
- // fill payload
- strcpy(removeConnectionCommand->symbolicOrConnid, symbolicOrConnid);
-
- // send message and receive response
- struct iovec *response =
- utils_SendRequest(state, REMOVE_CONNECTION, removeConnectionCommand,
- sizeof(remove_connection_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlRemoveConnection.h b/hicn-light/src/hicn/config/controlRemoveConnection.h
deleted file mode 100644
index 51d3a52a8..000000000
--- a/hicn-light/src/hicn/config/controlRemoveConnection.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_RemoveConnection.h
- * @brief Remove a connection from the connection table
- *
- * Implements the "remove connection" and "help remove connection" nodes of the
- * CLI tree
- *
- */
-
-#ifndef Control_RemoveConnection_h
-#define Control_RemoveConnection_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRemoveConnection_Create(ControlState *state);
-CommandOps *controlRemoveConnection_HelpCreate(ControlState *state);
-#endif // Control_RemoveConnection_h
diff --git a/hicn-light/src/hicn/config/controlRemoveListener.c b/hicn-light/src/hicn/config/controlRemoveListener.c
deleted file mode 100644
index 7525316f1..000000000
--- a/hicn-light/src/hicn/config/controlRemoveListener.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <hicn/utils/address.h>
-
-#include <hicn/config/controlRemoveListener.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlRemoveListener_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRemoveListener_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *_commandRemoveListener = "remove listener";
-static const char *_commandRemoveListenerHelp = "help remove listener";
-
-// ====================================================
-
-CommandOps *controlRemoveListener_Create(ControlState *state) {
- return commandOps_Create(state, _commandRemoveListener, NULL,
- _controlRemoveListener_Execute,
- commandOps_Destroy);
-}
-
-CommandOps *controlRemoveListener_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRemoveListenerHelp, NULL,
- _controlRemoveListener_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlRemoveListener_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "command:\n"
- " remove listener <symbolic|id>\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlRemoveListener_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 3) {
- _controlRemoveListener_HelpExecute(parser, ops, args, output, output_size);
- return false;
- }
-
- if ((strcmp(parcList_GetAtIndex(args, 0), "remove") != 0) ||
- (strcmp(parcList_GetAtIndex(args, 1), "listener") != 0)) {
- _controlRemoveListener_HelpExecute(parser, ops, args, output, output_size);
- return false;
- }
-
- const char *listenerId = parcList_GetAtIndex(args, 2);
-
-if (!utils_ValidateSymbolicName(listenerId) &&
- !utils_IsNumber(listenerId)) {
- snprintf(output, output_size,
- "ERROR: Invalid symbolic or listenerId:\nsymbolic name must begin with an "
- "alpha followed by alphanum;\nlistenerId must be an integer\n");
- return CommandReturn_Failure;
- }
-
- // allocate command payload
- remove_listener_command *removeListenerCommand =
- parcMemory_AllocateAndClear(sizeof(remove_listener_command));
- // fill payload
- //removeListenerCommand->listenerId = atoi(listenerId);
- snprintf(removeListenerCommand->symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listenerId);
-
- // send message and receive response
- struct iovec *response =
- utils_SendRequest(state, REMOVE_LISTENER, removeListenerCommand,
- sizeof(remove_listener_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlRemoveListener.h b/hicn-light/src/hicn/config/controlRemoveListener.h
deleted file mode 100644
index 794d1e1a9..000000000
--- a/hicn-light/src/hicn/config/controlRemoveListener.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_RemoveConnection.h
- * @brief Remove a connection from the connection table
- *
- * Implements the "remove connection" and "help remove connection" nodes of the
- * CLI tree
- *
- */
-
-#ifndef Control_RemoveListener_h
-#define Control_RemoveListener_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRemoveListener_Create(ControlState *state);
-CommandOps *controlRemoveListener_HelpCreate(ControlState *state);
-#endif // Control_RemoveListener_h
diff --git a/hicn-light/src/hicn/config/controlRemovePolicy.c b/hicn-light/src/hicn/config/controlRemovePolicy.c
deleted file mode 100644
index 35741396e..000000000
--- a/hicn-light/src/hicn/config/controlRemovePolicy.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef WITH_POLICY
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/assert/parc_Assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <hicn/utils/address.h>
-
-#include <hicn/config/controlRemovePolicy.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlRemovePolicy_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRemovePolicy_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *_commandRemovePolicy = "remove policy";
-static const char *_commandRemovePolicyHelp = "help remove policy";
-
-// ====================================================
-
-CommandOps *controlRemovePolicy_Create(ControlState *state) {
- return commandOps_Create(state, _commandRemovePolicy, NULL,
- _controlRemovePolicy_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlRemovePolicy_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRemovePolicyHelp, NULL,
- _controlRemovePolicy_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlRemovePolicy_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "commands:\n"
- " remove policy <prefix>\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlRemovePolicy_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 3) {
- _controlRemovePolicy_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *prefixStr = parcList_GetAtIndex(args, 2);
- char *addr = (char *)malloc(sizeof(char) * (strlen(prefixStr) + 1));
-
- // separate address and len
- char *slash;
- uint32_t len = 0;
- strcpy(addr, prefixStr);
- slash = strrchr(addr, '/');
- if (slash != NULL) {
- len = atoi(slash + 1);
- *slash = '\0';
- }
-
- // allocate command payload
- remove_policy_command *removePolicyCommand =
- parcMemory_AllocateAndClear(sizeof(remove_policy_command));
-
- // check and set IP address
- if (inet_pton(AF_INET, addr, &removePolicyCommand->address.v4.as_u32) == 1) {
- if (len > 32) {
- snprintf(output, output_size, "ERROR: exceeded INET mask length, max=32\n");
- parcMemory_Deallocate(&removePolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- removePolicyCommand->addressType = ADDR_INET;
- } else if (inet_pton(AF_INET6, addr, &removePolicyCommand->address.v6.as_in6addr) ==
- 1) {
- if (len > 128) {
- snprintf(output, output_size, "ERROR: exceeded INET6 mask length, max=128\n");
- parcMemory_Deallocate(&removePolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- removePolicyCommand->addressType = ADDR_INET6;
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&removePolicyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- free(addr);
- // Fill remaining payload fields
- removePolicyCommand->len = len;
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, REMOVE_POLICY, removePolicyCommand, sizeof(remove_policy_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/config/controlRemovePunting.c b/hicn-light/src/hicn/config/controlRemovePunting.c
deleted file mode 100644
index 84d096b81..000000000
--- a/hicn-light/src/hicn/config/controlRemovePunting.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <hicn/utils/address.h>
-
-#include <hicn/config/controlRemovePunting.h>
-
-static CommandReturn _controlRemovePunting_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRemovePunting_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *_commandRemovePunting = "remove punting";
-static const char *_commandRemovePuntingHelp = "help punting connection";
-
-// ====================================================
-
-CommandOps *controlRemovePunting_Create(ControlState *state) {
- return commandOps_Create(state, _commandRemovePunting, NULL,
- _controlRemovePunting_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlRemovePunting_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRemovePuntingHelp, NULL,
- _controlRemovePunting_HelpExecute,
- commandOps_Destroy);
-}
-
-// ====================================================
-
-// ====================================================
-
-static CommandReturn _controlRemovePunting_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "remove punting <symbolic> <prefix>\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlRemovePunting_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "command not implemented\n");
- return _controlRemovePunting_HelpExecute(parser, ops, args, output, output_size);
-}
-
-// ==================================================
diff --git a/hicn-light/src/hicn/config/controlRemoveRoute.c b/hicn-light/src/hicn/config/controlRemoveRoute.c
deleted file mode 100644
index eb5642d98..000000000
--- a/hicn-light/src/hicn/config/controlRemoveRoute.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/assert/parc_Assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <hicn/utils/address.h>
-
-#include <hicn/config/controlRemoveRoute.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRemoveRoute_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-// ===================================================
-
-static const char *_commandRemoveRoute = "remove route";
-static const char *_commandRemoveRouteHelp = "help remove route";
-
-// ====================================================
-
-CommandOps *controlRemoveRoute_Create(ControlState *state) {
- return commandOps_Create(state, _commandRemoveRoute, NULL,
- _controlRemoveRoute_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlRemoveRoute_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRemoveRouteHelp, NULL,
- _controlRemoveRoute_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlRemoveRoute_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "commands:\n"
- " remove route <symbolic | connid> <prefix>\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 4) {
- _controlRemoveRoute_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *symbolicOrConnid = parcList_GetAtIndex(args, 2);
-
- if (!utils_ValidateSymbolicName(symbolicOrConnid) &&
- !utils_IsNumber(symbolicOrConnid)) {
- snprintf(output, output_size,
- "ERROR: Invalid symbolic or connid:\nsymbolic name must begin with an "
- "alpha followed by alphanum;\nconnid must be an integer\n");
- return CommandReturn_Failure;
- }
-
- const char *prefixStr = parcList_GetAtIndex(args, 3);
- char *addr = (char *)malloc(sizeof(char) * (strlen(prefixStr) + 1));
-
- // separate address and len
- char *slash;
- uint32_t len = 0;
- strcpy(addr, prefixStr);
- slash = strrchr(addr, '/');
- if (slash != NULL) {
- len = atoi(slash + 1);
- *slash = '\0';
- }
-
- // allocate command payload
- remove_route_command *removeRouteCommand =
- parcMemory_AllocateAndClear(sizeof(remove_route_command));
-
- // check and set IP address
- if (inet_pton(AF_INET, addr, &removeRouteCommand->address.v4.as_u32) == 1) {
- if (len > 32) {
- snprintf(output, output_size, "ERROR: exceeded INET mask length, max=32\n");
- parcMemory_Deallocate(&removeRouteCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- removeRouteCommand->addressType = ADDR_INET;
- } else if (inet_pton(AF_INET6, addr, &removeRouteCommand->address.v6.as_in6addr) ==
- 1) {
- if (len > 128) {
- snprintf(output, output_size, "ERROR: exceeded INET6 mask length, max=128\n");
- parcMemory_Deallocate(&removeRouteCommand);
- free(addr);
- return CommandReturn_Failure;
- }
- removeRouteCommand->addressType = ADDR_INET6;
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&removeRouteCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- free(addr);
- // Fill remaining payload fields
- removeRouteCommand->len = len;
- strcpy(removeRouteCommand->symbolicOrConnid, symbolicOrConnid);
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, REMOVE_ROUTE, removeRouteCommand, sizeof(remove_route_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlRemoveRoute.h b/hicn-light/src/hicn/config/controlRemoveRoute.h
deleted file mode 100644
index 5e152b2fd..000000000
--- a/hicn-light/src/hicn/config/controlRemoveRoute.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_RemoveRoute.h
- * @brief Remove a route from the FIB
- *
- * Implements the "remove route" and "help remove route" nodes of the command
- * tree
- *
- */
-
-#ifndef Control_RemoveRoute_h
-#define Control_RemoveRoute_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRemoveRoute_Create(ControlState *state);
-CommandOps *controlRemoveRoute_HelpCreate(ControlState *state);
-#endif // Control_RemoveRoute_h
diff --git a/hicn-light/src/hicn/config/controlRoot.c b/hicn-light/src/hicn/config/controlRoot.c
deleted file mode 100644
index 39a1fa6b5..000000000
--- a/hicn-light/src/hicn/config/controlRoot.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/config/controlAdd.h>
-#include <hicn/config/controlCache.h>
-#include <hicn/config/controlList.h>
-#include <hicn/config/controlMapMe.h>
-#include <hicn/config/controlQuit.h>
-#include <hicn/config/controlRemove.h>
-#include <hicn/config/controlRoot.h>
-#include <hicn/config/controlSet.h>
-#include <hicn/config/controlUnset.h>
-#ifdef WITH_POLICY
-#include <hicn/config/controlUpdate.h>
-#endif /* WITH_POLICY */
-
-static void _controlRoot_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlRoot_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlRoot_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandRoot = "";
-static const char *_commandRootHelp = "help";
-
-// ====================================================
-
-CommandOps *controlRoot_Create(ControlState *state) {
- return commandOps_Create(state, _commandRoot, _controlRoot_Init,
- _controlRoot_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlRoot_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandRootHelp, NULL,
- _controlRoot_HelpExecute, commandOps_Destroy);
-}
-
-// ===================================================
-
-static CommandReturn _controlRoot_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- size_t output_offset = snprintf(output, output_size, "Command-line execution:\n"
- " controller [--server <server-ip>] [--port <server-port>] "
- "command\n"
- "\n"
- "Interactive execution:\n"
- " controller [--server <server-ip>] [--port <server-port>]\n"
- "\n"
- "If the keystore is not specified, the default path is used. Keystore "
- "must exist prior to running program.\n"
- "If the password is not specified, the user will be prompted.\n"
- "\n");
-
- CommandOps *ops_help_add = controlAdd_CreateHelp(NULL);
- CommandOps *ops_help_list = controlList_HelpCreate(NULL);
- CommandOps *ops_help_quit = controlQuit_HelpCreate(NULL);
- CommandOps *ops_help_remove = controlRemove_HelpCreate(NULL);
- CommandOps *ops_help_set = controlSet_HelpCreate(NULL);
- CommandOps *ops_help_unset = controlUnset_HelpCreate(NULL);
- CommandOps *ops_help_cache = controlCache_HelpCreate(NULL);
- CommandOps *ops_help_mapme = controlMapMe_HelpCreate(NULL);
-#ifdef WITH_POLICY
- CommandOps *ops_help_update = controlUpdate_HelpCreate(NULL);
-#endif /* WITH_POLICY */
-
- snprintf(output + output_offset, output_size - output_offset,"Available commands:\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
- " %s\n"
-#ifdef WITH_POLICY
- " %s\n"
-#endif /* WITH_POLICY */
- "\n",
- ops_help_add->command,
- ops_help_list->command,
- ops_help_quit->command,
- ops_help_remove->command,
- ops_help_set->command,
- ops_help_unset->command,
- ops_help_cache->command,
- ops_help_mapme->command
-#ifdef WITH_POLICY
- , ops_help_update->command
-#endif /* WITH_POLICY */
- );
-
- commandOps_Destroy(&ops_help_add);
- commandOps_Destroy(&ops_help_list);
- commandOps_Destroy(&ops_help_quit);
- commandOps_Destroy(&ops_help_remove);
- commandOps_Destroy(&ops_help_set);
- commandOps_Destroy(&ops_help_unset);
- commandOps_Destroy(&ops_help_cache);
- commandOps_Destroy(&ops_help_mapme);
-#ifdef WITH_POLICY
- commandOps_Destroy(&ops_help_update);
-#endif /* WITH_POLICY */
-
- return CommandReturn_Success;
-}
-
-static void _controlRoot_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
-
- controlState_RegisterCommand(state, controlAdd_CreateHelp(state));
- controlState_RegisterCommand(state, controlList_HelpCreate(state));
- controlState_RegisterCommand(state, controlQuit_HelpCreate(state));
- controlState_RegisterCommand(state, controlRemove_HelpCreate(state));
- controlState_RegisterCommand(state, controlSet_HelpCreate(state));
- controlState_RegisterCommand(state, controlUnset_HelpCreate(state));
- controlState_RegisterCommand(state, controlCache_HelpCreate(state));
- controlState_RegisterCommand(state, controlMapMe_HelpCreate(state));
-#ifdef WITH_POLICY
- controlState_RegisterCommand(state, controlUpdate_HelpCreate(state));
-#endif /* WITH_POLICY */
-
- controlState_RegisterCommand(state, webControlAdd_Create(state));
- controlState_RegisterCommand(state, controlList_Create(state));
- controlState_RegisterCommand(state, controlQuit_Create(state));
- controlState_RegisterCommand(state, controlRemove_Create(state));
- controlState_RegisterCommand(state, controlSet_Create(state));
- controlState_RegisterCommand(state, controlUnset_Create(state));
- controlState_RegisterCommand(state, controlCache_Create(state));
- controlState_RegisterCommand(state, controlMapMe_Create(state));
-#ifdef WITH_POLICY
- controlState_RegisterCommand(state, controlUpdate_Create(state));
-#endif /* WITH_POLICY */
-}
-
-static CommandReturn _controlRoot_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return CommandReturn_Success;
-}
-
-// ======================================================================
diff --git a/hicn-light/src/hicn/config/controlRoot.h b/hicn-light/src/hicn/config/controlRoot.h
deleted file mode 100644
index 154b81a80..000000000
--- a/hicn-light/src/hicn/config/controlRoot.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_Root.h
- * @brief Root of the command tree
- *
- * Implements the root of the command tree. This is the one module that
- * needs to be seeded to the control state to build the whole tree.
- *
- */
-
-#ifndef Control_Root_h
-#define Control_Root_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRoot_Create(ControlState *state);
-CommandOps *controlRoot_HelpCreate(ControlState *state);
-#endif // Control_Root_h
diff --git a/hicn-light/src/hicn/config/controlSet.c b/hicn-light/src/hicn/config/controlSet.c
deleted file mode 100644
index 37d56e593..000000000
--- a/hicn-light/src/hicn/config/controlSet.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/security/parc_Security.h>
-
-#include <hicn/config/controlSet.h>
-#include <hicn/config/controlSetDebug.h>
-#include <hicn/config/controlSetStrategy.h>
-#include <hicn/config/controlSetWldr.h>
-
-static void _controlSet_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlSet_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlSet_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandSet = "set";
-static const char *_commandSetHelp = "help set";
-
-// ===========================================================
-
-CommandOps *controlSet_Create(ControlState *state) {
- return commandOps_Create(state, _commandSet, _controlSet_Init,
- _controlSet_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlSet_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandSetHelp, NULL,
- _controlSet_HelpExecute, commandOps_Destroy);
-}
-
-// ===========================================================
-
-static void _controlSet_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state, controlSetDebug_Create(state));
- controlState_RegisterCommand(state, controlSetDebug_HelpCreate(state));
- controlState_RegisterCommand(state, controlSetStrategy_Create(state));
- controlState_RegisterCommand(state, controlSetStrategy_HelpCreate(state));
- controlState_RegisterCommand(state, controlSetWldr_Create(state));
- controlState_RegisterCommand(state, controlSetWldr_HelpCreate(state));
-}
-
-static CommandReturn _controlSet_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_help_set_debug = controlSetDebug_HelpCreate(NULL);
- CommandOps *ops_help_set_strategy = controlSetStrategy_HelpCreate(NULL);
- CommandOps *ops_help_set_wldr = controlSetWldr_HelpCreate(NULL);
-
- snprintf(output, output_size, "Available commands:\n %s\n %s\n %s\n\n",
- ops_help_set_debug->command,
- ops_help_set_strategy->command,
- ops_help_set_wldr->command);
-
- commandOps_Destroy(&ops_help_set_debug);
- commandOps_Destroy(&ops_help_set_strategy);
- commandOps_Destroy(&ops_help_set_wldr);
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlSet_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlSet_HelpExecute(parser, ops, args, output, output_size);
-}
diff --git a/hicn-light/src/hicn/config/controlSet.h b/hicn-light/src/hicn/config/controlSet.h
deleted file mode 100644
index abe2a611d..000000000
--- a/hicn-light/src/hicn/config/controlSet.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_Set.h
- * @brief Implements the set node of the CLI tree
- *
- * Implements the "set" and "help set" nodes of the command tree
- *
- */
-#ifndef Control_Set_h
-#define Control_Set_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlSet_Create(ControlState *state);
-CommandOps *controlSet_HelpCreate(ControlState *state);
-#endif // Control_Set_h
diff --git a/hicn-light/src/hicn/config/controlSetDebug.c b/hicn-light/src/hicn/config/controlSetDebug.c
deleted file mode 100644
index a5dcc89c1..000000000
--- a/hicn-light/src/hicn/config/controlSetDebug.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlSetDebug.h>
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-
-static CommandReturn _controlSetDebug_Execute(CommandParser *parser,
- CommandOps *ops, PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlSetDebug_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandSetDebug = "set debug";
-static const char *_commandSetDebugHelp = "help set debug";
-
-// ====================================================
-
-CommandOps *controlSetDebug_Create(ControlState *state) {
- return commandOps_Create(state, _commandSetDebug, NULL,
- _controlSetDebug_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlSetDebug_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandSetDebugHelp, NULL,
- _controlSetDebug_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlSetDebug_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "set debug: will enable the debug flag for more verbose output\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlSetDebug_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlSetDebug_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- ControlState *state = ops->closure;
- controlState_SetDebug(state, true);
- snprintf(output, output_size, "Debug flag set\n\n");
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlSetDebug.h b/hicn-light/src/hicn/config/controlSetDebug.h
deleted file mode 100644
index fabeb6952..000000000
--- a/hicn-light/src/hicn/config/controlSetDebug.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_SetDebug.h
- * @brief Sets the debug flag for more verbose output
- *
- * Implements the "set debug" and "help set debug" nodes of the command tree
- *
- */
-
-#ifndef Control_SetDebug_h
-#define Control_SetDebug_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlSetDebug_Create(ControlState *state);
-CommandOps *controlSetDebug_HelpCreate(ControlState *state);
-#endif // Control_SetDebug_h
diff --git a/hicn-light/src/hicn/config/controlSetStrategy.c b/hicn-light/src/hicn/config/controlSetStrategy.c
deleted file mode 100644
index fe0ba84a0..000000000
--- a/hicn-light/src/hicn/config/controlSetStrategy.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/config/controlSetDebug.h>
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlSetStrategy_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandSetStrategy = "set strategy";
-static const char *_commandSetStrategyHelp = "help set strategy";
-
-static const char *_commandSetStrategyOptions[LAST_STRATEGY_VALUE] = {
- "loadbalancer",
- "random",
- "low_latency",
-};
-
-// ====================================================
-
-CommandOps *controlSetStrategy_Create(ControlState *state) {
- return commandOps_Create(state, _commandSetStrategy, NULL,
- _controlSetStrategy_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlSetStrategy_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandSetStrategyHelp, NULL,
- _controlSetStrategy_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-strategy_type _validStrategy(const char *strategy) {
- strategy_type validStrategy = LAST_STRATEGY_VALUE;
-
- for (int i = 0; i < LAST_STRATEGY_VALUE; i++) {
- if (strcmp(_commandSetStrategyOptions[i], strategy) == 0) {
- validStrategy = i;
- break;
- }
- }
- return validStrategy;
-}
-
-static void _getAddressAndLen(const char * prefixStr, char *addr, uint32_t *len){
- char *slash;
- strcpy(addr, prefixStr);
- slash = strrchr(addr, '/');
- if (slash != NULL) {
- *len = atoi(slash + 1);
- *slash = '\0';
- }
-}
-
-static bool _checkAndSetIp(set_strategy_command * setStrategyCommand,
- int index,
- char * addr,
- uint32_t len,
- char *output,
- size_t output_size){
- // check and set IP address
- int res;
- if(index == -1)
- res = inet_pton(AF_INET, addr, &setStrategyCommand->address.v4.as_u32);
- else
- res = inet_pton(AF_INET, addr,
- &setStrategyCommand->addresses[index].v4.as_u32);
-
- if(res == 1) {
- if (len == UINT32_MAX) {
- snprintf(output, output_size, "Netmask not specified: set to 32 by default\n");
- len = 32;
- } else if (len > 32) {
- snprintf(output, output_size, "ERROR: exceeded INET mask length, max=32\n");
- return false;
- }
- if(index == -1)
- setStrategyCommand->addressType = ADDR_INET;
- else
- setStrategyCommand->addresses_type[index] = ADDR_INET;
-
- } else {
-
- if(index == -1)
- res = inet_pton(AF_INET6, addr,
- &setStrategyCommand->address.v6.as_in6addr);
- else
- res = inet_pton(AF_INET6, addr,
- &setStrategyCommand->addresses[index].v6.as_in6addr);
-
- if(res == 1) {
- if (len == UINT32_MAX) {
- snprintf(output, output_size, "Netmask not specified: set to 128 by default\n");
- len = 128;
- } else if (len > 128) {
- snprintf(output, output_size, "ERROR: exceeded INET6 mask length, max=128\n");
- return false;
- }
-
- if(index == -1)
- setStrategyCommand->addressType = ADDR_INET6;
- else
- setStrategyCommand->addresses_type[index] = ADDR_INET6;
-
- } else {
- snprintf(output, output_size, "Error: %s is not a valid network address \n", addr);
-
- return false;
- }
- }
- return true;
-}
-
-static CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size,
- "set strategy <prefix> <strategy> "
- "[related_prefix1 related_preifx2 ...]\n"
- "prefix: ipv4/ipv6 address (ex: 1234::/64)\n"
- "strategy: strategy identifier\n"
- "optinal: list of related prefixes (max %u)\n"
- "available strategies:\n"
- " random\n"
- " loadbalancer\n"
- " low_latency\n\n",
- MAX_FWD_STRATEGY_RELATED_PREFIXES);
- return CommandReturn_Success;
-}
-
-
-static CommandReturn _controlSetStrategy_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (output) {
- output[0] = '\0';
- }
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) < 4 ||
- parcList_Size(args) > (4 + MAX_FWD_STRATEGY_RELATED_PREFIXES)) {
- _controlSetStrategy_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- if (((strcmp(parcList_GetAtIndex(args, 0), "set") != 0) ||
- (strcmp(parcList_GetAtIndex(args, 1), "strategy") != 0))) {
- _controlSetStrategy_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *prefixStr = parcList_GetAtIndex(args, 2);
- char *addr = (char *)malloc(sizeof(char) * (strlen(prefixStr) + 1));
- uint32_t len = UINT32_MAX;
- _getAddressAndLen(prefixStr, addr, &len);
-
- // allocate command payload
- set_strategy_command *setStrategyCommand =
- parcMemory_AllocateAndClear(sizeof(set_strategy_command));
-
- bool success = _checkAndSetIp(setStrategyCommand, -1, addr, len, output, output_size);
- if(!success){
- parcMemory_Deallocate(&setStrategyCommand);
- free(addr);
- return CommandReturn_Failure;
- }
-
- const char *strategyStr = parcList_GetAtIndex(args, 3);
- // check valid strategy
- strategy_type strategy;
- if ((strategy = _validStrategy(strategyStr)) == LAST_STRATEGY_VALUE) {
- size_t output_offset = strlen(output);
- output_offset += snprintf(output + output_offset, output_size - output_offset, "Error: invalid strategy \n");
-
- parcMemory_Deallocate(&setStrategyCommand);
- _controlSetStrategy_HelpExecute(parser, ops, args, output + output_offset, output_size - output_offset);
- free(addr);
- return CommandReturn_Failure;
- }
-
- free(addr);
-
- // Fill remaining payload fields
- setStrategyCommand->len = len;
- setStrategyCommand->strategyType = strategy;
- size_t output_offset = strlen(output);
- //check additional prefixes
- if(parcList_Size(args) > 4){
- uint32_t index = 4; //first realted prefix
- uint32_t addr_index = 0;
- setStrategyCommand->related_prefixes = (uint8_t)parcList_Size(args) - 4;
- while(index < parcList_Size(args)){
- const char *str = parcList_GetAtIndex(args, index);
- char *rel_addr = (char *)malloc(sizeof(char) * (strlen(str) + 1));
- uint32_t rel_len = UINT32_MAX;
- _getAddressAndLen(str, rel_addr, &rel_len);
- bool success = _checkAndSetIp(setStrategyCommand, addr_index,
- rel_addr, rel_len, output + output_offset, output_size - output_offset);
- if(!success){
- parcMemory_Deallocate(&setStrategyCommand);
- free(rel_addr);
- return CommandReturn_Failure;
- }
- output_offset = strlen(output);
- setStrategyCommand->lens[addr_index] = rel_len;
- free(rel_addr);
- index++;
- addr_index++;
- }
- }else{
- setStrategyCommand->related_prefixes = 0;
- }
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, SET_STRATEGY, setStrategyCommand, sizeof(set_strategy_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlSetStrategy.h b/hicn-light/src/hicn/config/controlSetStrategy.h
deleted file mode 100644
index 7ad56ccba..000000000
--- a/hicn-light/src/hicn/config/controlSetStrategy.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_SetStrategy_h
-#define Control_SetStrategy_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlSetStrategy_Create(ControlState *state);
-CommandOps *controlSetStrategy_HelpCreate(ControlState *state);
-#endif // Control_SetStrategy_h
diff --git a/hicn-light/src/hicn/config/controlSetWldr.c b/hicn-light/src/hicn/config/controlSetWldr.c
deleted file mode 100644
index 0d4a7eca2..000000000
--- a/hicn-light/src/hicn/config/controlSetWldr.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlSetDebug.h>
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlSetWldr_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlSetWldr_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandSetWldr = "set wldr";
-static const char *_commandSetWldrHelp = "help set wldr";
-
-// ====================================================
-
-CommandOps *controlSetWldr_Create(ControlState *state) {
- return commandOps_Create(state, _commandSetWldr, NULL,
- _controlSetWldr_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlSetWldr_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandSetWldrHelp, NULL,
- _controlSetWldr_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlSetWldr_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "set wldr <on|off> <connection_id>\n\n");
-
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlSetWldr_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- ControlState *state = ops->closure;
-
- if (parcList_Size(args) != 4) {
- _controlSetWldr_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- if (((strcmp(parcList_GetAtIndex(args, 0), "set") != 0) ||
- (strcmp(parcList_GetAtIndex(args, 1), "wldr") != 0))) {
- _controlSetWldr_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- bool active;
- if (strcmp(parcList_GetAtIndex(args, 2), "on") == 0) {
- active = true;
- } else if (strcmp(parcList_GetAtIndex(args, 2), "off") == 0) {
- active = false;
- } else {
- _controlSetWldr_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- // check if valid connid
- const char *symbolicOrConnid = parcList_GetAtIndex(args, 3);
-
- if (!utils_ValidateSymbolicName(symbolicOrConnid) &&
- !utils_IsNumber(symbolicOrConnid)) {
- snprintf(output, output_size,
- "ERROR: Invalid symbolic or connid:\nsymbolic name must begin with an "
- "alpha followed by alphanum;\nconnid must be an integer\n");
- return CommandReturn_Failure;
- }
-
- // allocate command payload
- set_wldr_command *setWldrCommand =
- parcMemory_AllocateAndClear(sizeof(set_wldr_command));
- strcpy(setWldrCommand->symbolicOrConnid, symbolicOrConnid);
- if (active) {
- setWldrCommand->activate = ACTIVATE_ON;
- } else {
- setWldrCommand->activate = ACTIVATE_OFF;
- }
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(state, SET_WLDR, setWldrCommand,
- sizeof(set_wldr_command));
-
- if (!response) { // get NULL pointer
- return CommandReturn_Failure;
- }
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlSetWldr.h b/hicn-light/src/hicn/config/controlSetWldr.h
deleted file mode 100644
index 3c01110e4..000000000
--- a/hicn-light/src/hicn/config/controlSetWldr.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Control_SetWldr_h
-#define Control_SetWldr_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlSetWldr_Create(ControlState *state);
-CommandOps *controlSetWldr_HelpCreate(ControlState *state);
-#endif // Control_SetWldr_h
diff --git a/hicn-light/src/hicn/config/controlState.c b/hicn-light/src/hicn/config/controlState.c
deleted file mode 100644
index acdae9e52..000000000
--- a/hicn-light/src/hicn/config/controlState.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <string.h>
-
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/algol/parc_Time.h>
-#include <parc/algol/parc_TreeRedBlack.h>
-
-#include <hicn/config/commandParser.h>
-#include <hicn/config/controlRoot.h>
-#include <hicn/config/controlState.h>
-
-#include <hicn/utils/commands.h>
-
-struct controller_state {
- CommandParser *parser;
- bool debugFlag;
-
- void *userdata;
- struct iovec *(*writeRead)(ControlState *state, struct iovec *msg);
- int sockfd;
- char **commandOutput;
- bool isInteractive;
-};
-
-int controlState_connectToFwdDeamon(char *server_ip, uint16_t port) {
- int sockfd;
- struct sockaddr_in servaddr;
-
- if ((sockfd = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- printf("\nSocket Creation Failed \n");
- return EXIT_FAILURE;
- }
-
- memset(&servaddr, 0, sizeof(servaddr));
-
- // Filling server information
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(port);
- inet_pton(AF_INET, server_ip, &(servaddr.sin_addr.s_addr));
-
- // Establish connection
- if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
- printf("\nConnection Failed: hicn-light Daemon is not running \n");
- return -1;
- }
-
- return sockfd;
-}
-
-ControlState *controlState_Create(
- void *userdata,
- struct iovec *(*writeRead)(ControlState *state, struct iovec *msg),
- bool openControllerConnetion,
- char *server_ip, uint16_t port) {
- ControlState *state = parcMemory_AllocateAndClear(sizeof(ControlState));
- parcAssertNotNull(state, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ControlState));
- state->parser = commandParser_Create();
-
- state->userdata = userdata;
- state->writeRead = writeRead;
- state->debugFlag = false;
- state->commandOutput = NULL;
- state->isInteractive = true;
-
- if (openControllerConnetion) {
- state->sockfd = controlState_connectToFwdDeamon(server_ip, port);
- if (state->sockfd == -1) {
- return NULL;
- }
- } else {
- state->sockfd = 2; // stderr
- }
-
- return state;
-}
-
-void controlState_Destroy(ControlState **statePtr) {
- parcAssertNotNull(statePtr, "Parameter statePtr must be non-null");
- parcAssertNotNull(*statePtr,
- "Parameter statePtr must dereference t non-null");
- ControlState *state = *statePtr;
- // printf("sockid destroyed: %d\n", state->sockfd);
- // close the connection with the fwd deamon
- shutdown(state->sockfd, 2);
-
- commandParser_Destroy(&state->parser);
- parcMemory_Deallocate((void **)&state);
- *statePtr = NULL;
-}
-
-void controlState_SetDebug(ControlState *state, bool debugFlag) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- state->debugFlag = debugFlag;
- commandParser_SetDebug(state->parser, debugFlag);
-}
-
-bool controlState_GetDebug(ControlState *state) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- return state->debugFlag;
-}
-
-void controlState_RegisterCommand(ControlState *state, CommandOps *ops) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- commandParser_RegisterCommand(state->parser, ops);
-}
-
-struct iovec *controlState_WriteRead(ControlState *state, struct iovec *msg) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- parcAssertNotNull(msg, "Parameter msg must be non-null");
-
- return state->writeRead(state, msg);
-}
-
-static PARCList *_controlState_ParseStringIntoTokens(
- const char *originalString) {
- PARCList *list =
- parcList(parcArrayList_Create(parcArrayList_StdlibFreeFunction),
- PARCArrayListAsPARCList);
-
- char *token;
-
- char *tofree =
- parcMemory_StringDuplicate(originalString, strlen(originalString) + 1);
- char *string = tofree;
-
- token = strtok(string, " \t\n");
- while (token != NULL) {
- if (strlen(token) > 0) {
- parcList_Add(list, strdup(token));
- }
- token = strtok(NULL, " \t\n");
- }
-
- parcMemory_Deallocate((void **)&tofree);
-
- return list;
-}
-
-CommandReturn controlState_DispatchCommand(ControlState *state,
- PARCList *args,
- char *output,
- size_t output_size) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- return commandParser_DispatchCommand(state->parser, args, output, output_size);
-}
-
-int controlState_Interactive(ControlState *state) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- char *line = NULL;
- size_t linecap = 0;
- CommandReturn controlReturn = CommandReturn_Success;
- char output[8192];
- while (controlReturn != CommandReturn_Exit && !feof(stdin)) {
- fputs("> ", stdout);
- fflush(stdout);
- ssize_t failure = getline(&line, &linecap, stdin);
- parcAssertTrue(failure > -1, "Error getline");
-
- PARCList *args = _controlState_ParseStringIntoTokens(line);
-
- controlReturn = controlState_DispatchCommand(state, args, output, sizeof(output));
- printf("%s", output);
- // release and get command
- parcList_Release(&args);
- }
- return 0;
-}
-
-void controlState_SetCommandOutput(ControlState *state, char **commandData) {
- state->commandOutput = commandData;
-}
-
-void controlState_ReleaseCommandOutput(ControlState *state, char **commandData,
- size_t commandLenght) {
- for (size_t i = 0; i < commandLenght; i++) {
- parcMemory_Deallocate(&commandData[i]);
- }
- parcMemory_Deallocate(&commandData);
- state->commandOutput = NULL;
-}
-
-char **controlState_GetCommandOutput(ControlState *state) {
- return state->commandOutput;
-}
-
-// size_t
-// controlState_GetCommandLen(ControlState *state){
-
-// }
-
-void controlState_SetInteractiveFlag(ControlState *state, bool interactive) {
- state->isInteractive = interactive;
-}
-
-bool controlState_IsInteractive(ControlState *state) {
- return state->isInteractive;
-}
-
-int controlState_GetSockfd(ControlState *state) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- return state->sockfd;
-}
-
-void *controlState_GetUserdata(ControlState *state) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- return state->userdata;
-}
-
-bool controlState_isConfigFile(ControlState *state) {
- parcAssertNotNull(state, "Parameter state must be non-null");
- if (state->sockfd != 2) {
- return false;
- } else {
- return true;
- }
-}
diff --git a/hicn-light/src/hicn/config/controlState.h b/hicn-light/src/hicn/config/controlState.h
deleted file mode 100644
index 52b1f6655..000000000
--- a/hicn-light/src/hicn/config/controlState.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file controlState.h
- * @brief A control program for hicn-light using CLI commands
- *
- * Implements the state machine for the control program. It takes a "writeRead"
- * function as part of the constructor. This abstracts out the backend. It
- * could be a Portal from hicnLightControl program down to the forwarder or it
- * could be an internal function within hicn-light.
- *
- */
-
-#ifndef control_h
-#define control_h
-
-#include <parc/algol/parc_List.h>
-#include <hicn/config/commandParser.h>
-
-#include <hicn/utils/commands.h>
-
-#define SRV_CTRL_IP "127.0.0.1"
-#define SRV_CTRL_PORT 9695
-
-struct controller_state;
-typedef struct controller_state ControlState;
-
-/**
- * controlState_Create
- *
- * Creates the global state for the Control program. The user provides the
- * writeRead function for sending and receiving the message wrapping command
- * arguments. For configuration file inside hicn-light, it would make direct
- * calls to Configuration -> Dispatcher.
- *
- * @param [in] userdata A closure passed back to the user when calling
- * writeRead.
- * @param [in] writeRead The function to write then read configuration messages
- * to hicn-light
- *
- * @return non-null The control state
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-
-ControlState *controlState_Create(
- void *userdata,
- struct iovec *(*writeRead)(ControlState *state, struct iovec *msg),
- bool openControllerConnetion,
- char * server_ip, uint16_t port);
-
-/**
- * Destroys the control state, closing all network connections
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void controlState_Destroy(ControlState **statePtr);
-
-/**
- * Registers a CommandOps with the system.
- *
- * Each command has its complete command prefix in the "command" field.
- * RegisterCommand will put these command prefixes in to a tree and then match
- * what a user types against the longest-matching prefix in the tree. If
- * there's a match, it will call the "execute" function.
- *
- * @param [in] state An allocated ControlState
- * @param [in] command The command to register with the system
- *
- * Example:
- * @code
- * static CommandReturn
- * control_Root_Execute(CommandParser *parser, CommandOps *ops, PARCList
- * *args)
- * {
- * printf("Root Command\n");
- * return CommandReturn_Success;
- * }
- *
- * static CommandReturn
- * control_FooBar_Execute(CommandParser *parser, CommandOps *ops, PARCList
- * *args)
- * {
- * printf("Foo Bar Command\n");
- * return CommandReturn_Success;
- * }
- *
- * const CommandOps control_Root = {
- * .command = "", // empty string for root
- * .init = NULL,
- * .execute = control_Root_Execute
- * };
- *
- * const CommandOps control_FooBar = {
- * .command = "foo bar", // empty string for root
- * .init = NULL,
- * .execute = control_FooBar_Execute
- * };
- *
- * void startup(void)
- * {
- * ControlState *state = controlState_Create("happy", "day");
- * controlState_RegisterCommand(state, control_FooBar);
- * controlState_RegisterCommand(state, control_Root);
- *
- * // this executes "root"
- * controlState_DispatchCommand(state, "foo");
- * controlState_Destroy(&state);
- * }
- * @endcode
- */
-void controlState_RegisterCommand(ControlState *state, CommandOps *command);
-
-/**
- * Performs a longest-matching prefix of the args to the command tree
- *
- * The command tree is created with controlState_RegisterCommand.
- *
- * @param [in] state The allocated ControlState
- * @param [in] args Each command_line word parsed to the ordered list
- * @param [in] output Output string
- * @param [in] output_length output string max length
- *
- * @return CommandReturn_Success the command was successful
- * @return CommandReturn_Failure the command failed or was not found
- * @return CommandReturn_Exit the command indicates that the interactive mode
- * should exit
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-CommandReturn controlState_DispatchCommand(ControlState *state,
- PARCList *args,
- char *output,
- size_t output_length);
-
-/**
- * Begin an interactive shell
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-int controlState_Interactive(ControlState *state);
-
-/**
- * Write then Read a command
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-struct iovec *controlState_WriteRead(ControlState *state, struct iovec *msg);
-
-/**
- * Sets the Debug mode, which will print out much more information.
- *
- * Prints out much more diagnostic information about what hicn-light controller
- * is doing. yes, you would make a CommandOps to set and unset this :)
- *
- * @param [in] debugFlag true means to print debug info, false means to turn it
- * off
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void controlState_SetDebug(ControlState *state, bool debugFlag);
-
-/**
- * Returns the debug state of ControlState
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @return <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-bool controlState_GetDebug(ControlState *state);
-#endif // control_h
-
-void controlState_SetCommandOutput(ControlState *state, char **commandData);
-
-void controlState_ReleaseCommandOutput(ControlState *state, char **commandData,
- size_t commandLenght);
-
-char **controlState_GetCommandOutput(ControlState *state);
-
-void controlState_SetInteractiveFlag(ControlState *state, bool interactive);
-
-bool controlState_IsInteractive(ControlState *state);
-
-void *controlState_GetUserdata(ControlState *state);
-
-bool controlState_isConfigFile(ControlState *state);
-
-int controlState_GetSockfd(ControlState *state);
diff --git a/hicn-light/src/hicn/config/controlUnset.c b/hicn-light/src/hicn/config/controlUnset.c
deleted file mode 100644
index e05ba2286..000000000
--- a/hicn-light/src/hicn/config/controlUnset.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/security/parc_Security.h>
-
-#include <hicn/config/controlUnset.h>
-#include <hicn/config/controlUnsetDebug.h>
-
-static void _controlUnset_Init(CommandParser *parser, CommandOps *ops);
-
-static CommandReturn _controlUnset_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlUnset_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandUnset = "unset";
-static const char *_commandUnsetHelp = "help unset";
-
-// ===========================================================
-
-CommandOps *controlUnset_Create(ControlState *state) {
- return commandOps_Create(state, _commandUnset, _controlUnset_Init,
- _controlUnset_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlUnset_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandUnsetHelp, NULL,
- _controlUnset_HelpExecute, commandOps_Destroy);
-}
-
-// ===========================================================
-
-static void _controlUnset_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- controlState_RegisterCommand(state, controlUnsetDebug_Create(state));
- controlState_RegisterCommand(state, controlUnsetDebug_HelpCreate(state));
-}
-
-static CommandReturn _controlUnset_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- CommandOps *ops_help_unset_debug = controlUnsetDebug_HelpCreate(NULL);
- snprintf(output, output_size, "Available commands:\n %s\n\n", ops_help_unset_debug->command);
-
- commandOps_Destroy(&ops_help_unset_debug);
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlUnset_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlUnset_HelpExecute(parser, ops, args, output, output_size);
-}
diff --git a/hicn-light/src/hicn/config/controlUnset.h b/hicn-light/src/hicn/config/controlUnset.h
deleted file mode 100644
index 9d9cb5c44..000000000
--- a/hicn-light/src/hicn/config/controlUnset.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_Unset.h
- * @brief Implements the unset node of the CLI tree
- *
- * Implements the "unset" and "help unset" nodes of the command tree
- *
- */
-#ifndef Control_Unset_h
-#define Control_Unset_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlUnset_Create(ControlState *state);
-CommandOps *controlUnset_HelpCreate(ControlState *state);
-#endif // Control_Unset_h
diff --git a/hicn-light/src/hicn/config/controlUnsetDebug.c b/hicn-light/src/hicn/config/controlUnsetDebug.c
deleted file mode 100644
index ac2a4e028..000000000
--- a/hicn-light/src/hicn/config/controlUnsetDebug.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlUnsetDebug.h>
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-
-static CommandReturn _controlUnsetDebug_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlUnsetDebug_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandUnsetDebug = "unset debug";
-static const char *_commandUnsetDebugHelp = "help unset debug";
-
-// ====================================================
-
-CommandOps *controlUnsetDebug_Create(ControlState *state) {
- return commandOps_Create(state, _commandUnsetDebug, NULL,
- _controlUnsetDebug_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlUnsetDebug_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandUnsetDebugHelp, NULL,
- _controlUnsetDebug_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static CommandReturn _controlUnsetDebug_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- snprintf(output, output_size, "unset debug: will disable the debug flag\n\n");
- return CommandReturn_Success;
-}
-
-static CommandReturn _controlUnsetDebug_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if (parcList_Size(args) != 2) {
- _controlUnsetDebug_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- ControlState *state = ops->closure;
- controlState_SetDebug(state, false);
- snprintf(output, output_size, "Debug flag cleared\n\n");
-
- return CommandReturn_Success;
-}
diff --git a/hicn-light/src/hicn/config/controlUnsetDebug.h b/hicn-light/src/hicn/config/controlUnsetDebug.h
deleted file mode 100644
index c76ba8c98..000000000
--- a/hicn-light/src/hicn/config/controlUnsetDebug.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file control_UnsetDebug.h
- * @brief Unsets the debug flag for more verbose output
- *
- * Implements the "unset debug" and "help unset debug" nodes of the CLI tree
- *
- */
-
-#ifndef Control_UnsetDebug_h
-#define Control_UnsetDebug_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlUnsetDebug_Create(ControlState *state);
-CommandOps *controlUnsetDebug_HelpCreate(ControlState *state);
-#endif // Control_UnsetDebug_h
diff --git a/hicn-light/src/hicn/config/controlUpdate.c b/hicn-light/src/hicn/config/controlUpdate.c
deleted file mode 100644
index 095bbf01e..000000000
--- a/hicn-light/src/hicn/config/controlUpdate.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef WITH_POLICY
-
-#include <hicn/hicn-light/config.h>
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/security/parc_Security.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/config/controlUpdate.h>
-#include <hicn/config/controlUpdateConnection.h>
-
-static void _controlUpdate_Init(CommandParser *parser, CommandOps *ops);
-static CommandReturn _controlUpdate_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlUpdate_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *_commandUpdate = "update";
-static const char *_commandUpdateHelp = "help update";
-
-CommandOps *controlUpdate_Create(ControlState *state) {
- return commandOps_Create(state, _commandUpdate, _controlUpdate_Init,
- _controlUpdate_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlUpdate_HelpCreate(ControlState *state) {
- return commandOps_Create(state, _commandUpdateHelp, NULL,
- _controlUpdate_HelpExecute, commandOps_Destroy);
-}
-
-// =====================================================
-
-static CommandReturn _controlUpdate_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- //CommandOps *ops_update_connections = controlUpdateConnections_HelpCreate(NULL);
- // CommandOps *ops_update_interfaces = controlUpdateInterfaces_HelpCreate(NULL);
- //CommandOps *ops_update_routes = controlUpdateRoutes_HelpCreate(NULL);
- CommandOps *ops_update_listeners = controlUpdateConnection_HelpCreate(NULL);
- snprintf(output, output_size,
- "Available commands:\n %s\n\n",
- ops_update_listeners->command);
-
-
-
- // commandOps_Destroy(&ops_update_connections);
- // commandOps_Destroy(&ops_update_interfaces);
- //commandOps_Destroy(&ops_update_routes);
- commandOps_Destroy(&ops_update_listeners);
-
- return CommandReturn_Success;
-}
-
-static void _controlUpdate_Init(CommandParser *parser, CommandOps *ops) {
- ControlState *state = ops->closure;
- //controlState_RegisterCommand(state, controlUpdateConnections_HelpCreate(state));
- // controlState_RegisterCommand(state,
- // controlUpdateInterfaces_HelpCreate(state));
- controlState_RegisterCommand(state, controlUpdateConnection_HelpCreate(state));
- //controlState_RegisterCommand(state, controlUpdateRoutes_HelpCreate(state));
- //controlState_RegisterCommand(state, controlUpdateConnections_Create(state));
- // controlState_RegisterCommand(state, controlUpdateInterfaces_Create(state));
- //controlState_RegisterCommand(state, controlUpdateRoutes_Create(state));
- controlState_RegisterCommand(state, controlUpdateConnection_Create(state));
-}
-
-static CommandReturn _controlUpdate_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- return _controlUpdate_HelpExecute(parser, ops, args, output, output_size);
-}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/config/controlUpdateConnection.c b/hicn-light/src/hicn/config/controlUpdateConnection.c
deleted file mode 100644
index 70a017d4f..000000000
--- a/hicn-light/src/hicn/config/controlUpdateConnection.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef WITH_POLICY
-
-#include <hicn/hicn-light/config.h>
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/config/controlUpdateConnection.h>
-
-#include <hicn/policy.h>
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static CommandReturn _controlUpdateConnection_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-static CommandReturn _controlUpdateConnection_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size);
-
-static const char *command_update_connection = "update connection";
-static const char *command_help_update_connection = "help update connection";
-
-CommandOps *controlUpdateConnection_Create(ControlState *state) {
- return commandOps_Create(state, command_update_connection, NULL,
- _controlUpdateConnection_Execute, commandOps_Destroy);
-}
-
-CommandOps *controlUpdateConnection_HelpCreate(ControlState *state) {
- return commandOps_Create(state, command_help_update_connection, NULL,
- _controlUpdateConnection_HelpExecute, commandOps_Destroy);
-}
-
-// ====================================================
-
-static const int _indexSymbolic = 2;
-static const int _indexTags = 3;
-
-static CommandReturn _controlUpdateConnection_HelpExecute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
-
- snprintf(output, output_size,
- "commands:\n"
- " update connection <symbolic | id> <tags> \n"
- "\n"
- " symbolic: User defined name for connection, must start with "
- "alpha and be alphanum\n"
- " id: Identifier for the connection\n"
- " tags: A string representing tags\n");
- return CommandReturn_Success;
-}
-
-
-static CommandReturn _controlUpdateConnection_Execute(CommandParser *parser,
- CommandOps *ops,
- PARCList *args,
- char *output,
- size_t output_size) {
- if ((parcList_Size(args) != 3) && (parcList_Size(args) != 4)) {
- _controlUpdateConnection_HelpExecute(parser, ops, args, output, output_size);
- return CommandReturn_Failure;
- }
-
- const char *symbolicOrConnid = parcList_GetAtIndex(args, _indexSymbolic);
-
- if (!utils_ValidateSymbolicName(symbolicOrConnid) &&
- !utils_IsNumber(symbolicOrConnid)) {
- snprintf(output, output_size,
- "ERROR: Invalid symbolic or connid:\nsymbolic name must begin with an "
- "alpha followed by alphanum;\nconnid must be an integer\n");
- return CommandReturn_Failure;
- }
-
- policy_tags_t tags = POLICY_TAGS_EMPTY;
- if (parcList_Size(args) == 4) {
- const char *str_tags = parcList_GetAtIndex(args, _indexTags);
-
- for (unsigned i = 0; str_tags[i] != 0; i++) {
- switch(tolower(str_tags[i])) {
- case 'e':
- policy_tags_add(&tags, POLICY_TAG_WIRED);
- break;
- case 'w':
- policy_tags_add(&tags, POLICY_TAG_WIFI);
- break;
- case 'c':
- policy_tags_add(&tags, POLICY_TAG_CELLULAR);
- break;
- case 'b':
- policy_tags_add(&tags, POLICY_TAG_BEST_EFFORT);
- break;
- case 'r':
- policy_tags_add(&tags, POLICY_TAG_REALTIME);
- break;
- case 'm':
- policy_tags_add(&tags, POLICY_TAG_MULTIPATH);
- break;
- case 't':
- policy_tags_add(&tags, POLICY_TAG_TRUSTED);
- break;
- }
- }
- }
- ControlState *state = ops->closure;
-
- // allocate command payload
- update_connection_command *updateConnectionCommand =
- parcMemory_AllocateAndClear(sizeof(update_connection_command));
- updateConnectionCommand->tags = tags;
- strcpy(updateConnectionCommand->symbolicOrConnid, symbolicOrConnid);
-
- // send message and receive response
- struct iovec *response = utils_SendRequest(
- state, UPDATE_CONNECTION, updateConnectionCommand, sizeof(update_connection_command));
-
- if (!response) // get NULL pointer
- return CommandReturn_Failure;
-
- parcMemory_Deallocate(&response); // free iovec pointer
- return CommandReturn_Success;
-}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/config/parse.c b/hicn-light/src/hicn/config/parse.c
new file mode 100644
index 000000000..ba9c0b348
--- /dev/null
+++ b/hicn-light/src/hicn/config/parse.c
@@ -0,0 +1,402 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+//#include <hicn/ctrl/cli.h>
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.h>
+#include "parse.h"
+
+/*
+ * As there is no portable way to generate a va_list to use with sscanf to
+ * support a variable number of arguments, and no way to use a variable array
+ * initialize in a nested struct, we use a fixed maximum number of parameters
+ *
+ * NOTE: update sscanf accordingly
+ */
+
+#include "command.h"
+
+const char *action_str[] = {
+#define _(x) [ACTION_##x] = #x,
+ foreach_action
+#undef _
+};
+
+#define action_str(x) action_str[x]
+
+hc_action_t action_from_str(const char *action_str) {
+#define _(x) \
+ if (strcasecmp(action_str, #x) == 0) \
+ return ACTION_##x; \
+ else
+ foreach_action
+#undef _
+ if (strcasecmp(action_str, "add") == 0) return ACTION_CREATE;
+ else if (strcasecmp(action_str, "remove") == 0) return ACTION_DELETE;
+ else return ACTION_UNDEFINED;
+}
+
+const char *object_str[] = {
+#define _(x) [OBJECT_##x] = #x,
+ foreach_object
+#undef _
+};
+
+#define object_str(x) object_str[x]
+
+hc_object_type_t object_from_str(const char *object_str) {
+#define _(x) \
+ if (strcasecmp(object_str, #x) == 0) \
+ return OBJECT_##x; \
+ else
+ foreach_object
+#undef _
+ return OBJECT_UNDEFINED;
+}
+
+const char *action_to_cmd_action(hc_action_t action) {
+ switch (action) {
+ case ACTION_CREATE:
+ return "add";
+ case ACTION_UPDATE:
+ return "update";
+ case ACTION_DELETE:
+ return "remove";
+ case ACTION_LIST:
+ return "list";
+ case ACTION_SET:
+ return "set";
+ case ACTION_SERVE:
+ return "serve";
+ case ACTION_STORE:
+ return "store";
+ case ACTION_CLEAR:
+ return "clear";
+ default:
+ return "UNDEFINED";
+ }
+}
+
+const char *parser_type_fmt(const parser_type_t *type) {
+ switch (type->name) {
+ case TYPENAME_INT:
+ return TYPE_FMT_INT;
+ case TYPENAME_UINT:
+ return TYPE_FMT_UINT;
+ case TYPENAME_STR:
+ return TYPE_FMT_STRN(type->str.max_size);
+ case TYPENAME_SYMBOLIC_OR_ID:
+ return TYPE_FMT_SYMBOLIC_OR_ID;
+ case TYPENAME_INTERFACE_NAME:
+ return TYPE_FMT_INTERFACE_NAME;
+ case TYPENAME_IP_ADDRESS:
+ return TYPE_FMT_IP_ADDRESS;
+ case TYPENAME_IP_PREFIX:
+ return TYPE_FMT_IP_PREFIX;
+ case TYPENAME_ON_OFF:
+ return TYPE_FMT_ON_OFF;
+ case TYPENAME_ENUM:
+ return TYPE_FMT_ENUM;
+ case TYPENAME_POLICY_STATE:
+ return TYPE_FMT_POLICY_STATE;
+ case TYPENAME_UNDEFINED:
+ default:
+ return NULL;
+ }
+}
+
+int parser_type_func(const parser_type_t *type, void *src, void *dst,
+ void *dst2, void *dst3) {
+ ip_address_t addr;
+ char *addr_str;
+ char *len_str;
+ int len, tmp, rc;
+
+ switch (type->name) {
+ case TYPENAME_INT:
+ tmp = *(int *)src;
+ if (tmp < type->sint.min || tmp > type->sint.max) {
+ ERROR("Input number (%d) not inside range [%d, %d]", tmp,
+ type->sint.min, type->sint.max);
+ return -1;
+ }
+ *(int *)dst = *(int *)src;
+ break;
+ case TYPENAME_UINT:
+ tmp = *(int *)src;
+ if (tmp < type->uint.min || tmp > type->uint.max) {
+ ERROR("Input number (%d) not inside range [%d, %d]", tmp,
+ type->uint.min, type->uint.max);
+ return -1;
+ }
+ *(unsigned *)dst = *(unsigned *)src;
+ break;
+ case TYPENAME_STR:
+ rc = strcpy_s(dst, type->str.max_size, src);
+ if (rc != EOK) {
+ ERROR("Input string is too long");
+ return -1;
+ }
+ break;
+ case TYPENAME_IP_ADDRESS:
+ rc = ip_address_pton((char *)src, &addr);
+ if (rc < 0) {
+ ERROR("Wrong IP address format");
+ return -1;
+ }
+
+ *(ip_address_t *)dst = addr;
+ *(int *)dst2 = ip_address_get_family((char *)src);
+ break;
+ case TYPENAME_ON_OFF:
+ if (strcmp((char *)src, "off") == 0) {
+ *(unsigned *)dst = 0;
+ } else if (strcmp((char *)src, "on") == 0) {
+ *(unsigned *)dst = 1;
+ } else {
+ ERROR("on/off are the only possible values");
+ return -1;
+ }
+ break;
+ case TYPENAME_IP_PREFIX:
+ addr_str = strtok((char *)src, "/");
+ len_str = strtok(NULL, " ");
+ rc = ip_address_pton((char *)src, &addr);
+ if (rc < 0) {
+ ERROR("Wrong IP address format");
+ return -1;
+ }
+ len = atoi(len_str);
+
+ *(ip_address_t *)dst = addr;
+ *(int *)dst2 = len;
+ *(int *)dst3 = ip_address_get_family(addr_str);
+ break;
+ case TYPENAME_ENUM:
+ /* Enum index from string */
+ assert(type->enum_.from_str);
+ *(int *)dst = type->enum_.from_str((char *)src);
+ break;
+ case TYPENAME_POLICY_STATE: {
+ assert(IS_VALID_POLICY_TAG(type->policy_state.tag));
+ policy_tag_t tag = type->policy_state.tag;
+ /* Format string is "%ms" */
+ const char *str = *(const char **)src;
+ policy_tag_state_t *pts = ((policy_tag_state_t *)dst);
+ pts[tag].disabled = (str[0] == '!') ? 1 : 0;
+ pts[tag].state = policy_state_from_str(str + pts[tag].disabled);
+ break;
+ }
+ case TYPENAME_UNDEFINED:
+ default:
+ ERROR("Unknown format");
+ return -1;
+ }
+ return 0;
+}
+
+int parse_params(const command_parser_t *parser, const char *params_s,
+ hc_command_t *command) {
+ char fmt[1024];
+ int n;
+ size_t size = 0;
+ char *pos = fmt;
+ /* Update MAX_PARAMETERS accordingly in command.h */
+ char sscanf_params[MAX_PARAMETERS][MAX_SCANF_PARAM_LEN];
+
+ unsigned count = 0;
+ for (unsigned i = 0; i < parser->nparams; i++) {
+ const command_parameter_t *p = &parser->parameters[i];
+ const char *_fmt = parser_type_fmt(&p->type);
+ // printf(" _fmt=%s\n", _fmt);
+ if (!_fmt) {
+ WARN("Ignored parameter %s with unknown type formatter", p->name);
+ continue;
+ }
+ n = snprintf(pos, 1024 - size, "%s", _fmt);
+ pos += n;
+
+ *pos = ' ';
+ pos++;
+
+ size += n + 1;
+ count++;
+ }
+ *pos = '\0';
+ DEBUG("parser format: %s", fmt);
+
+ int ret = sscanf(params_s, fmt, sscanf_params[0], sscanf_params[1],
+ sscanf_params[2], sscanf_params[3], sscanf_params[4],
+ sscanf_params[5], sscanf_params[6], sscanf_params[7],
+ sscanf_params[8], sscanf_params[9]);
+ if (ret != parser->nparams) {
+ ERROR("Parsing failed: check for string used where integer was expected");
+ goto ERR;
+ }
+
+ for (unsigned i = 0; i < count; i++) {
+ const command_parameter_t *p = &parser->parameters[i];
+ if (parser_type_func(&p->type, sscanf_params[i],
+ &command->object.as_uint8 + p->offset,
+ &command->object.as_uint8 + p->offset2,
+ &command->object.as_uint8 + p->offset3) < 0) {
+ ERROR("Error during parsing of parameter '%s' value", p->name);
+ goto ERR;
+ }
+ }
+ return 0;
+
+ERR:
+ return -1;
+}
+
+int parse(const char *cmd, hc_command_t *command) {
+ int nparams = 0;
+ char action_s[MAX_SCANF_PARAM_LEN];
+ char object_s[MAX_SCANF_PARAM_LEN];
+ char params_s[MAX_SCANF_PARAM_LEN];
+
+ // if n = 2 later, params_s is uninitialized
+ memset(params_s, 0, MAX_SCANF_PARAM_LEN * sizeof(char));
+
+ errno = 0;
+ int n = sscanf(cmd, "%s %s%[^\n]s", action_s, object_s, params_s);
+ if ((n < 2) || (n > 3)) {
+ if (errno != 0) perror("scanf");
+ return -1;
+ }
+
+ command->action = action_from_str(action_s);
+ command->object.type = object_from_str(object_s);
+
+ if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) {
+ for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++)
+ nparams++;
+ }
+
+ /*
+ * This checks is important even with 0 parameters as it checks whether the
+ * command exists.
+ */
+ const command_parser_t *parser =
+ command_search(command->action, command->object.type, nparams);
+ if (!parser) {
+ ERROR("Could not find parser for command '%s %s'", action_s, object_s);
+ return -1;
+ }
+
+ if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) {
+ if (parse_params(parser, params_s, command) < 0) return -1;
+ }
+
+ if (parser->post_hook) parser->post_hook(&command->object.as_uint8);
+ return 0;
+}
+
+int help(const char *cmd) {
+ int nparams = 1;
+ char action_s[MAX_SCANF_PARAM_LEN];
+ char object_s[MAX_SCANF_PARAM_LEN];
+ char params_s[MAX_SCANF_PARAM_LEN];
+ hc_object_type_t object = OBJECT_UNDEFINED;
+ hc_action_t action = ACTION_UNDEFINED;
+
+ int n = sscanf(cmd, "help %[^\n]s", params_s);
+
+ // No arguments provided to the help command: just list available objects
+ if (n != 1) goto CMD_LIST;
+
+ // Count number of provided parameters
+ for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++) nparams++;
+ if (nparams > 2) {
+ fprintf(stderr, "Error: too many arguments.\n");
+ return -1;
+ }
+
+ // Object specified: list actions available for that object
+ if (nparams == 1) {
+ object = object_from_str(params_s);
+ if (object == OBJECT_UNDEFINED) {
+ fprintf(stderr, "Error: undefined object.\n");
+ return -1;
+ }
+
+ goto CMD_LIST;
+ }
+
+ // Object and action specified: list detailed commands
+ n = sscanf(params_s, "%s %[^\n]s", object_s, action_s);
+ assert(n == 2);
+ object = object_from_str(object_s);
+ action = action_from_str(action_s);
+ if (object == OBJECT_UNDEFINED || action == ACTION_UNDEFINED) {
+ fprintf(stderr, "Error: undefined object and/or action.\n");
+ return -1;
+ }
+
+CMD_LIST:
+ printf("Available commands:\n");
+ command_list(object, action);
+ return 0;
+}
+
+#if 0 // tests
+/* For the tests, we will need to test all non-compliant inputs */
+const char * cmds[] = {
+ "add connection hicn conn1 8.8.8.8 127.0.0.1 eth0",
+ "add connection udp <symbolic> <remote_ip> <port> <local_ip> <port> eth0",
+ "add listener udp lst1 127.0.0.1 9695 eth0",
+ //"add face",
+ "add route 3 b001::/16 1",
+ //"add punting",
+ //"add strategy",
+ "add policy b001::/16 webex require avoid prohibit !prohibit neutral !require prefer",
+ "list connection", // need pluralize
+ "list listener",
+ "list face",
+ "list route",
+ "list punting",
+ "list strategy",
+ "list policy",
+ "remove connection 1",
+ "remove listener 1",
+ //"remove face",
+ "remove route 1 b001::/16",
+ //"remove punting",
+ //"remove policy",
+ "set debug",
+ "unset debug",
+ "set strategy b001::/16 random", // related prefixes (10 max) ?
+ "set strategy b001::/16 load_balancer",
+ "set strategy b001::/16 low_latency",
+ "set strategy b001::/16 replication",
+ "set strategy b001::/16 bestpath",
+ "set wldr <on|off> <connection_id>", // on-off vs unset
+ "cache clear",
+ "cache store on/off", // set/unset
+ "cache serve on/off",
+ "mapme enable on/off",
+ "mapme discovery on/off",
+ "mapme timescale 500ms",
+ "mapme retx 500ms",
+ "update connection conn1 WT",
+};
+
+#define array_size(x) sizeof(x) / sizeof(typeof(x[0]))
+int main()
+{
+ for (unsigned i = 0; i < array_size(cmds); i++) {
+ printf("PARSING [%d] %s\n", i, cmds[i]);
+ if (parse(cmds[i]) < 0) {
+ ERROR("Could not parse command: %s\n", cmds[i]);
+ continue;
+ }
+ }
+ exit(EXIT_SUCCESS);
+
+ERR:
+ exit(EXIT_FAILURE);
+}
+#endif
diff --git a/hicn-light/src/hicn/config/parse.h b/hicn-light/src/hicn/config/parse.h
new file mode 100644
index 000000000..06269208a
--- /dev/null
+++ b/hicn-light/src/hicn/config/parse.h
@@ -0,0 +1,15 @@
+#ifndef HICNLIGHT_PARSE_CMD
+#define HICNLIGHT_PARSE_CMD
+
+#include <hicn/ctrl/api.h>
+
+int parse(const char* cmd, hc_command_t* command);
+int help(const char* cmd);
+
+/**
+ * @brief Convert the action enum to the action name used in the commands (e.g.
+ * from ACTION_CREATE to "add").
+ */
+const char* action_to_cmd_action(hc_action_t action);
+
+#endif /* HICNLIGHT_PARSE_CMD */
diff --git a/hicn-light/src/hicn/config/symbolicNameTable.c b/hicn-light/src/hicn/config/symbolicNameTable.c
deleted file mode 100644
index e5ae81d3e..000000000
--- a/hicn-light/src/hicn/config/symbolicNameTable.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ctype.h>
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/config/symbolicNameTable.h>
-
-struct symblic_name_table {
- PARCHashCodeTable *symbolicNameTable;
- PARCHashCodeTable *indexToNameTable;
-};
-
-// ========================================================================================
-// symbolic name table functions
-
-static bool _symbolicNameEquals(const void *keyA, const void *keyB) {
- return (strcasecmp((const char *)keyA, (const char *)keyB) == 0);
-}
-
-static HashCodeType _symbolicNameHash(const void *keyA) {
- const char *str = (const char *)keyA;
- size_t length = strlen(str);
- return parcHash32_Data(str, length);
-}
-
-static bool _connectionIdEquals(const void *keyA, const void *keyB) {
- unsigned idA = *((unsigned *)keyA);
- unsigned idB = *((unsigned *)keyB);
- return (idA == idB);
-}
-
-static HashCodeType _connectionIdHash(const void *keyA) {
- unsigned idA = *((unsigned *)keyA);
- return parcHash32_Int32(idA);
-}
-
-// ========================================================================================
-
-SymbolicNameTable *symbolicNameTable_Create(void) {
- SymbolicNameTable *table = parcMemory_Allocate(sizeof(SymbolicNameTable));
-
- if (table) {
- // key = char *
- // value = uint32_t *
- table->symbolicNameTable = parcHashCodeTable_Create(
- _symbolicNameEquals, _symbolicNameHash, parcMemory_DeallocateImpl,
- parcMemory_DeallocateImpl);
- table->indexToNameTable = parcHashCodeTable_Create(
- _connectionIdEquals, _connectionIdHash, parcMemory_DeallocateImpl,
- parcMemory_DeallocateImpl);
- }
-
- return table;
-}
-
-void symbolicNameTable_Destroy(SymbolicNameTable **tablePtr) {
- SymbolicNameTable *table = *tablePtr;
- parcHashCodeTable_Destroy(&table->symbolicNameTable);
- parcHashCodeTable_Destroy(&table->indexToNameTable);
- parcMemory_Deallocate((void **)&table);
- *tablePtr = NULL;
-}
-
-static char *_createKey(const char *symbolicName) {
- char *key = parcMemory_StringDuplicate(symbolicName, strlen(symbolicName));
-
- // convert key to upper case
- char *p = key;
-
- // keeps looping until the first null
- while ((*p = toupper(*p))) {
- p++;
- }
- return key;
-}
-
-bool symbolicNameTable_Exists(SymbolicNameTable *table,
- const char *symbolicName) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
-
- char *key = _createKey(symbolicName);
- bool found = (parcHashCodeTable_Get(table->symbolicNameTable, key) != NULL);
- parcMemory_Deallocate((void **)&key);
- return found;
-}
-
-void symbolicNameTable_Remove(SymbolicNameTable *table,
- const char *symbolicName) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
-
- char *key = _createKey(symbolicName);
-
- unsigned id = symbolicNameTable_Get(table, symbolicName);
- uint32_t *value = parcMemory_Allocate(sizeof(uint32_t));
- *value = id;
-
- parcHashCodeTable_Del(table->symbolicNameTable, key);
- parcHashCodeTable_Del(table->indexToNameTable, value);
- parcMemory_Deallocate((void **)&key);
- parcMemory_Deallocate((void **)&value);
-}
-
-bool symbolicNameTable_Add(SymbolicNameTable *table, const char *symbolicName,
- unsigned connid) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
- parcAssertTrue(connid < UINT32_MAX, "Parameter connid must be less than %u",
- UINT32_MAX);
-
- char *key1 = _createKey(symbolicName);
-
- uint32_t *value1 = parcMemory_Allocate(sizeof(uint32_t));
- *value1 = connid;
-
- bool success = parcHashCodeTable_Add(table->symbolicNameTable, key1, value1);
- if (!success)
- goto ERR_NAME;
-
- char *key2 = _createKey(symbolicName);
-
- uint32_t *value2 = parcMemory_Allocate(sizeof(uint32_t));
- *value2 = connid;
-
- success = parcHashCodeTable_Add(table->indexToNameTable, value2, key2);
- if (!success)
- goto ERR_INDEX;
-
- goto END;
-
-ERR_INDEX:
- parcMemory_Deallocate((void **)&key2);
- parcMemory_Deallocate((void **)&value2);
- parcHashCodeTable_Del(table->symbolicNameTable, key1);
-ERR_NAME:
- parcMemory_Deallocate((void **)&key1);
- parcMemory_Deallocate((void **)&value1);
-END:
- return success;
-
-}
-
-unsigned symbolicNameTable_Get(SymbolicNameTable *table,
- const char *symbolicName) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
-
- unsigned connid = UINT32_MAX;
-
- char *key = _createKey(symbolicName);
-
- uint32_t *value = parcHashCodeTable_Get(table->symbolicNameTable, key);
- if (value)
- connid = *value;
-
- parcMemory_Deallocate((void **)&key);
- return connid;
-}
-
-const char *symbolicNameTable_GetNameByIndex(SymbolicNameTable *table,
- unsigned id) {
- parcAssertNotNull(table, "Parameter table must be non-null");
-
- uint32_t *value = parcMemory_Allocate(sizeof(uint32_t));
- *value = id;
-
- const char *name = parcHashCodeTable_Get(table->indexToNameTable, value);
- if (name == NULL) name = "";
-
- parcMemory_Deallocate((void **)&value);
- return name;
-}
diff --git a/hicn-light/src/hicn/config/symbolicNameTable.h b/hicn-light/src/hicn/config/symbolicNameTable.h
deleted file mode 100644
index 69919cf00..000000000
--- a/hicn-light/src/hicn/config/symbolicNameTable.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file symbolicNameTable.h
- * @brief The symbolic name table maps a string name to a connection id
- *
- * When configuring tunnels/connections, the user provides a string name
- * (symbolic name) that they will use to refer to that connection. The symblic
- * name table translates that symbolic name to a connection id.
- *
- */
-
-#ifndef symbolicNameTable_h
-#define symbolicNameTable_h
-
-struct symblic_name_table;
-typedef struct symblic_name_table SymbolicNameTable;
-
-#include <stdbool.h>
-
-/**
- * Creates a symbolic name table
- *
- * Allocates a SymbolicNameTable, which will store the symbolic names
- * in a hash table.
- *
- * @retval non-null An allocated SymbolicNameTable
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-SymbolicNameTable *symbolicNameTable_Create(void);
-
-/**
- * Destroys a name table
- *
- * All keys and data are released.
- *
- * @param [in,out] tablePtr A pointer to a SymbolicNameTable, which will be
- * NULL'd
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void symbolicNameTable_Destroy(SymbolicNameTable **tablePtr);
-
-/**
- * Checks if the name (case insensitive) is in the table
- *
- * Does a case-insensitive match to see if the name is in the table
- *
- * @param [in] table An allocated SymbolicNameTable
- * @param [in] symbolicName The name to check for
- *
- * @retval true The name is in the table
- * @retval false The name is not in the talbe
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-bool symbolicNameTable_Exists(SymbolicNameTable *table,
- const char *symbolicName);
-
-/**
- * Adds a (name, connid) pair to the table.
- *
- * The name is stored case insensitive. The value UINT_MAX is used to indicate
- * a non-existent key, so it should not be stored as a value in the table.
- *
- * @param [in] table An allocated SymbolicNameTable
- * @param [in] symbolicName The name to save (will make a copy)
- * @param [in] connid The connection id to associate with the name
- *
- * @retval true The pair was added
- * @retval false The pair was not added (likely duplicate key)
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-bool symbolicNameTable_Add(SymbolicNameTable *table, const char *symbolicName,
- unsigned connid);
-
-/**
- * Returns the connection id associated with the symbolic name
- *
- * This function will look for the given name (case insensitive) and return the
- * corresponding connid. If the name is not in the table, the function will
- * return UINT_MAX.
- *
- * @param [in] table An allocated SymbolicNameTable
- * @param [in] symbolicName The name to retrieve
- *
- * @retval UINT_MAX symbolicName not found
- * @retval number the corresponding connid.
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-unsigned symbolicNameTable_Get(SymbolicNameTable *table,
- const char *symbolicName);
-
-void symbolicNameTable_Remove(SymbolicNameTable *table,
- const char *symbolicName);
-const char *symbolicNameTable_GetNameByIndex(SymbolicNameTable *table,
- unsigned id);
-
-#endif /* defined(symbolicNameTable_h) */
diff --git a/hicn-light/src/hicn/content_store/CMakeLists.txt b/hicn-light/src/hicn/content_store/CMakeLists.txt
index aaf256118..f7cfc26b6 100644
--- a/hicn-light/src/hicn/content_store/CMakeLists.txt
+++ b/hicn-light/src/hicn/content_store/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,20 +12,12 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreEntry.h
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreInterface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreLRU.h
- ${CMAKE_CURRENT_SOURCE_DIR}/listTimeOrdered.h
- ${CMAKE_CURRENT_SOURCE_DIR}/listLRU.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/lru.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreInterface.c
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreLRU.c
- ${CMAKE_CURRENT_SOURCE_DIR}/listLRU.c
- ${CMAKE_CURRENT_SOURCE_DIR}/listTimeOrdered.c
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreEntry.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lru.c
)
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/hicn-light/src/hicn/content_store/contentStoreEntry.c b/hicn-light/src/hicn/content_store/contentStoreEntry.c
deleted file mode 100644
index 45f98881e..000000000
--- a/hicn-light/src/hicn/content_store/contentStoreEntry.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <hicn/content_store/contentStoreEntry.h>
-
-#include <parc/assert/parc_Assert.h>
-
-const uint64_t contentStoreEntry_MaxExpiryTime = UINT64_MAX;
-
-struct contentstore_entry {
- Message *message;
- ListLruEntry *lruEntry;
- unsigned refcount;
- bool hasExpiryTimeTicks;
- uint64_t expiryTimeTicks;
-};
-
-ContentStoreEntry *contentStoreEntry_Create(Message *contentMessage,
- ListLru *listLRU) {
- parcAssertNotNull(contentMessage, "Parameter objectMessage must be non-null");
-
- ContentStoreEntry *entry =
- parcMemory_AllocateAndClear(sizeof(ContentStoreEntry));
- parcAssertNotNull(entry, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ContentStoreEntry));
- entry->message = message_Acquire(contentMessage);
- entry->refcount = 1;
-
- if (listLRU != NULL) {
- entry->lruEntry = listLRU_NewHeadEntry(listLRU, entry);
- }
-
- entry->hasExpiryTimeTicks = message_HasContentExpiryTime(contentMessage);
-
- if (entry->hasExpiryTimeTicks) {
- entry->expiryTimeTicks = message_GetContentExpiryTimeTicks(contentMessage);
- }
-
- return entry;
-}
-
-ContentStoreEntry *contentStoreEntry_Acquire(
- const ContentStoreEntry *original) {
- parcAssertNotNull(original, "Parameter must be non-null");
- ((ContentStoreEntry *)original)->refcount++;
- return (ContentStoreEntry *)original;
-}
-
-void contentStoreEntry_Release(ContentStoreEntry **entryPtr) {
- parcAssertNotNull(entryPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*entryPtr,
- "Parameter must dereference to non-null pointer");
-
- ContentStoreEntry *entry = *entryPtr;
- parcAssertTrue(entry->refcount > 0, "Illegal state: has refcount of 0");
-
- entry->refcount--;
- if (entry->refcount == 0) {
- if (entry->lruEntry) {
- listLRU_EntryDestroy(&entry->lruEntry);
- }
- message_Release(&entry->message);
- parcMemory_Deallocate((void **)&entry);
- }
- *entryPtr = NULL;
-}
-
-Message *contentStoreEntry_GetMessage(const ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- return storeEntry->message;
-}
-
-bool contentStoreEntry_HasExpiryTimeTicks(const ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- return storeEntry->hasExpiryTimeTicks;
-}
-
-uint64_t contentStoreEntry_GetExpiryTimeTicks(
- const ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- parcAssertTrue(storeEntry->hasExpiryTimeTicks,
- "storeEntry has no ExpiryTimeTicks. Did you call "
- "contentStoreEntry_HasExpiryTimeTicks() first?");
- return storeEntry->expiryTimeTicks;
-}
-
-int contentStoreEntry_CompareExpiryTime(const ContentStoreEntry *value1,
- const ContentStoreEntry *value2) {
- // A signum comparison. negative if key 1 is smaller, 0 if key1 == key2,
- // greater than 0 if key1 is bigger.
-
- ContentStoreEntry *v1 = (ContentStoreEntry *)value1;
- ContentStoreEntry *v2 = (ContentStoreEntry *)value2;
-
- if (v1->expiryTimeTicks < v2->expiryTimeTicks) {
- return -1;
- } else if (v1->expiryTimeTicks > v2->expiryTimeTicks) {
- return +1;
- } else {
- // At this point, the times are the same. Use the address of the message as
- // the decider. This allows us to store multiple messages with the same
- // expiry/cache time.
- if (v1->message < v2->message) {
- return -1;
- } else if (v1->message > v2->message) {
- return +1;
- }
- }
-
- return 0; // The same message has been encountered.
-}
-
-void contentStoreEntry_MoveToHead(ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- parcAssertNotNull(storeEntry->lruEntry,
- "ContentStoreEntry is not attached to an ListLru");
- if (storeEntry->lruEntry) {
- listLRU_EntryMoveToHead(storeEntry->lruEntry);
- }
-}
diff --git a/hicn-light/src/hicn/content_store/contentStoreEntry.h b/hicn-light/src/hicn/content_store/contentStoreEntry.h
deleted file mode 100644
index 4f0fd19c1..000000000
--- a/hicn-light/src/hicn/content_store/contentStoreEntry.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef contentStoreEntry_h
-#define contentStoreEntry_h
-
-#include <hicn/content_store/listLRU.h>
-#include <hicn/core/message.h>
-
-struct contentstore_entry;
-typedef struct contentstore_entry ContentStoreEntry;
-
-/**
- * The max time allowed for an ExpiryTime. Will never be exceeded.
- */
-extern const uint64_t contentStoreEntry_MaxExpiryTime;
-
-/**
- * Creates a new `ContentStoreEntry` instance, acquiring a reference to the
- * supplied `Message`.
- *
- * @param message the message to store
- * @param listLRU the LRU list that this entry will be stored in.
- * @return A newly created `ContentStoreEntry` instance that must eventually be
- * released by calling
- * {@link contentStoreEntry_Release}.
- *
- * @see contentStoreEntry_Release
- */
-ContentStoreEntry *contentStoreEntry_Create(Message *objectMessage,
- ListLru *listLRU);
-
-/**
- * Returns a reference counted copy of the supplied `ContentStoreEntry`.
- *
- * @param original the ContentStoreEntry to return a reference to.
- * @return Reference counted copy, must call
- * <code>contentStoreEntry_Destroy()</code> on it.
- */
-ContentStoreEntry *contentStoreEntry_Acquire(const ContentStoreEntry *original);
-
-/**
- * Releases one reference count and destroys object when reaches zero
- *
- * @param [in,out] entryPtr A pointer to an allocated ContentStoreEntry
- *
- */
-void contentStoreEntry_Release(ContentStoreEntry **entryPtr);
-
-/**
- * Returns a pointer to the contained {@link Message}.
- * The caller must called {@link message_Acquire()} if they want to keep a
- * reference to the returned message.
- *
- * @param storeEntry the ContentStoreEntry from which to retrieve the `Message`
- * pointer.
- * @return the address of the `Message` contained in the storeEntry.
- * @see message_Acquire
- */
-Message *contentStoreEntry_GetMessage(const ContentStoreEntry *storeEntry);
-
-/**
- * Return true if the message stored in this `ContentStoreEntry` has an
- * ExpiryTime.
- *
- * @param storeEntry the ContentStoreEntry containing the message.
- * @return true if the referenced message has an ExpiryTime. False, otherwise.
- */
-bool contentStoreEntry_HasExpiryTimeTicks(const ContentStoreEntry *storeEntry);
-
-/**
- * Return the ExpiryTime stored in this `ContentStoreEntry`.
- *
- * @param storeEntry the ContentStoreEntry from which to retrieve the `Message`
- * pointer.
- * @return the address of the `Message` contained in the storeEntry.
- */
-uint64_t contentStoreEntry_GetExpiryTimeTicks(
- const ContentStoreEntry *storeEntry);
-
-/**
- * A signum function comparing two `ContentStoreEntry` instances, using their
- * ExpiryTime and, if necessary, the addresses of the referenced Message. In
- * other words, if two ContentStoreEntries have the same ExpiryTime, the
- * comparison will then be made on the memory addresses of the Messages
- * referenced by the ContentStoreEntrys. So, the only way two ContentStoreEntrys
- * will compare equally (0) is if they both have the same ExpiryTime and
- * reference the same Message.
- *
- * Used to determine the ordering relationship of two `ContentStoreEntry`
- * instances. This is used by the {@link ListTimeOrdered} to keep a list of
- * ContentStoreEntrys, sorted by ExpiryTime.
- *
- * @param [in] storeEntry1 A pointer to a `ContentStoreEntry` instance.
- * @param [in] storeEntry2 A pointer to a `ContentStoreEntry` instance to be
- * compared to `storeEntry1`.
- *
- * @return 0 if `storeEntry1` and `storeEntry2` are equivalent
- * @return < 0 if `storeEntry1` < `storeEntry2`
- * @return > 0 if `storeEntry1` > `storeEntry2`
- *
- * Example:
- * @code
- * {
- * ContentStoreEntry *entry1 = contentStoreEntry_Create(...);
- * ContentStoreEntry *entry2 = contentStoreEntry_Create(...);
- *
- * int val = contentStoreEntry_CompareExpiryTime(entry1, entry2);
- * if (val < 0) {
- * // entry1 has a lower ExpiryTime, or the same ExpiryTime as entry2
- * and a different message. } else if (val > 0) {
- * // entry2 has a lower ExpiryTime, or the same ExpiryTime as entry1
- * and a different message. } else {
- * // entry1 and entry2 have the same ExpiryTime AND the same message.
- * }
- *
- * contentStoreEntry_Release(&entry1);
- * contentStoreEntry_Release(&entry2);
- *
- * }
- * @endcode
- */
-int contentStoreEntry_CompareExpiryTime(const ContentStoreEntry *storeEntry1,
- const ContentStoreEntry *storeEntry2);
-
-/**
- * Move this entry to the head of the LRU list
- *
- * Moves the entry to the head of the LRU list it was created with
- *
- * @param [in] storeEntry An allocated ContenstoreEntry
- */
-void contentStoreEntry_MoveToHead(ContentStoreEntry *storeEntry);
-#endif // contentStoreEntry_h
diff --git a/hicn-light/src/hicn/content_store/contentStoreInterface.c b/hicn-light/src/hicn/content_store/contentStoreInterface.c
deleted file mode 100644
index 2f5ddb8c2..000000000
--- a/hicn-light/src/hicn/content_store/contentStoreInterface.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/content_store/contentStoreInterface.h>
-
-void contentStoreInterface_Release(ContentStoreInterface **storeImplPtr) {
- (*storeImplPtr)->release(storeImplPtr);
-}
-
-bool contentStoreInterface_PutContent(ContentStoreInterface *storeImpl,
- Message *content,
- uint64_t currentTimeTicks) {
- return storeImpl->putContent(storeImpl, content, currentTimeTicks);
-}
-
-bool contentStoreInterface_RemoveContent(ContentStoreInterface *storeImpl,
- Message *content) {
- return storeImpl->removeContent(storeImpl, content);
-}
-
-Message *contentStoreInterface_MatchInterest(ContentStoreInterface *storeImpl,
- Message *interest,
- uint64_t currentTimeTicks) {
- return storeImpl->matchInterest(storeImpl, interest, currentTimeTicks);
-}
-
-size_t contentStoreInterface_GetObjectCapacity(
- ContentStoreInterface *storeImpl) {
- return storeImpl->getObjectCapacity(storeImpl);
-}
-
-size_t contentStoreInterface_GetObjectCount(ContentStoreInterface *storeImpl) {
- return storeImpl->getObjectCount(storeImpl);
-}
-
-void contentStoreInterface_Log(ContentStoreInterface *storeImpl) {
- storeImpl->log(storeImpl);
-}
-
-void *contentStoreInterface_GetPrivateData(ContentStoreInterface *storeImpl) {
- return storeImpl->_privateData;
-}
diff --git a/hicn-light/src/hicn/content_store/contentStoreInterface.h b/hicn-light/src/hicn/content_store/contentStoreInterface.h
deleted file mode 100644
index b2bc3f919..000000000
--- a/hicn-light/src/hicn/content_store/contentStoreInterface.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef contentStoreInterface_h
-#define contentStoreInterface_h
-
-#include <stdio.h>
-
-#include <hicn/core/message.h>
-
-typedef struct contentstore_config {
- size_t objectCapacity;
-} ContentStoreConfig;
-
-typedef struct contentstore_interface ContentStoreInterface;
-
-struct contentstore_interface {
- /**
- * Place a Message representing a ContentObject into the ContentStore. If
- * necessary to make room, remove expired content or content that has exceeded
- * the Recommended Cache Time.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to place in the store.
- * @param currentTimeTicks - the current time, in hicn-light ticks, since the
- * UTC epoch.
- */
- bool (*putContent)(ContentStoreInterface *storeImpl, Message *content,
- uint64_t currentTimeTicks);
-
- /**
- * The function to call to remove content from the ContentStore.
- * It will Release any references that were created when the content was
- * placed into the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to remove from the store.
- */
- bool (*removeContent)(ContentStoreInterface *storeImpl, Message *content);
-
- /**
- * Given a Message that represents and Interest, try to find a matching
- * ContentObject.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param interest - a pointer to a `Message` representing the Interest to
- * match.
- *
- * @return a pointer to a Message containing the matching ContentObject
- * @return NULL if no matching ContentObject was found
- */
- Message *(*matchInterest)(ContentStoreInterface *storeImpl, Message *interest,
- uint64_t currentTimeTicks);
-
- /**
- * Return the maximum number of ContentObjects that can be stored in this
- * ContentStore. This is a raw count, not based on memory size.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the maximum number of ContentObjects that can be stored
- */
- size_t (*getObjectCapacity)(ContentStoreInterface *storeImpl);
-
- /**
- * Return the number of ContentObjects currently stored in the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the current number of ContentObjects in the ContentStore
- */
- size_t (*getObjectCount)(ContentStoreInterface *storeImpl);
-
- /**
- * Log a ContentStore implementation specific version of store-related
- * information.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
- void (*log)(ContentStoreInterface *storeImpl);
-
- /**
- * Acquire a new reference to the specified ContentStore instance. This
- * reference will eventually need to be released by calling {@link
- * contentStoreInterface_Release}.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
- ContentStoreInterface *(*acquire)(const ContentStoreInterface *storeImpl);
-
- /**
- * Release the ContentStore, which will also Release any references held by
- * it.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
- void (*release)(ContentStoreInterface **storeImpl);
-
- /**
- * A pointer to opaque private data used by the ContentStore instance
- * represented by this instance of ContentStoreInterface.
- */
- void *_privateData;
-};
-
-/**
- * Place a Message representing a ContentObject into the ContentStore. If
- * necessary to make room, remove expired content or content that has exceeded
- * the Recommended Cache Time.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to place in the store.
- *
- * @param currentTimeTicks - the current time, in hicn-light ticks, since the
- * UTC epoch.
- */
-bool contentStoreInterface_PutContent(ContentStoreInterface *storeImpl,
- Message *content,
- uint64_t currentTimeTicks);
-
-/**
- * The function to call to remove content from the ContentStore.
- * It will Release any references that were created when the content was placed
- * into the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to remove from the store.
- */
-bool contentStoreInterface_RemoveContent(ContentStoreInterface *storeImpl,
- Message *content);
-
-/**
- * Given a Message that represents and Interest, try to find a matching
- * ContentObject.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param interest - a pointer to a `Message` representing the Interest to
- * match.
- *
- * @return a pointer to a Message containing the matching ContentObject
- * @return NULL if no matching ContentObject was found
- */
-Message *contentStoreInterface_MatchInterest(ContentStoreInterface *storeImpl,
- Message *interest,
- uint64_t currentTimeTicks);
-
-/**
- * Return the maximum number of ContentObjects that can be stored in this
- * ContentStore. This is a raw count, not based on memory size.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the maximum number of ContentObjects that can be stored
- */
-size_t contentStoreInterface_GetObjectCapacity(
- ContentStoreInterface *storeImpl);
-
-/**
- * Return the number of ContentObjects currently stored in the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the current number of ContentObjects in the ContentStore
- */
-size_t contentStoreInterface_GetObjectCount(ContentStoreInterface *storeImpl);
-
-/**
- * Loga ContentStore implementation specific version of store-related
- * information.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-void contentStoreInterface_Log(ContentStoreInterface *storeImpl);
-
-/**
- * Acquire a new reference to the specified ContentStore instance. This
- * reference will eventually need to be released by calling {@link
- * contentStoreInterface_Release}.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-ContentStoreInterface *contentStoreInterface_Aquire(
- const ContentStoreInterface *storeImpl);
-
-/**
- * Release the ContentStore, which will also Release any references held by it.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-void contentStoreInterface_Release(ContentStoreInterface **storeImplPtr);
-
-/**
- * Return a pointer to the data private to this implementation of the
- * ContentStore interface.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-void *contentStoreInterface_GetPrivateData(ContentStoreInterface *storeImpl);
-#endif // contentStoreInterface_h
diff --git a/hicn-light/src/hicn/content_store/contentStoreLRU.c b/hicn-light/src/hicn/content_store/contentStoreLRU.c
deleted file mode 100644
index 76a2c8659..000000000
--- a/hicn-light/src/hicn/content_store/contentStoreLRU.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <sys/queue.h>
-#endif
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_DisplayIndented.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Object.h>
-
-#include <hicn/core/logger.h>
-
-#include <hicn/content_store/contentStoreLRU.h>
-
-#include <hicn/content_store/contentStoreEntry.h>
-#include <hicn/content_store/contentStoreInterface.h>
-#include <hicn/content_store/listLRU.h>
-#include <hicn/content_store/listTimeOrdered.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/processor/hashTableFunction.h>
-
-typedef struct contentstore_stats {
- uint64_t countExpiryEvictions;
- uint64_t countRCTEvictions;
- uint64_t countLruEvictions;
- uint64_t countAdds;
- uint64_t countHits;
- uint64_t countMisses;
-} _ContentStoreLRUStats;
-
-typedef struct contentstore_lru_data {
- size_t objectCapacity;
- size_t objectCount;
-
- Logger *logger;
-
- // This LRU is just for keeping track of insertion and access order.
- ListLru *lru;
-
- ListTimeOrdered *indexByExpirationTime;
-
- PARCHashCodeTable *storageByName;
-
- _ContentStoreLRUStats stats;
-} _ContentStoreLRU;
-
-static void _destroyIndexes(_ContentStoreLRU *store) {
- if (store->indexByExpirationTime != NULL) {
- listTimeOrdered_Release(&(store->indexByExpirationTime));
- }
-
- if (store->storageByName != NULL) {
- parcHashCodeTable_Destroy(&(store->storageByName));
- }
-
- if (store->lru != NULL) {
- listLRU_Destroy(&(store->lru));
- }
-}
-
-static void _contentStoreInterface_Destroy(
- ContentStoreInterface **storeImplPtr) {
- _ContentStoreLRU *store = contentStoreInterface_GetPrivateData(*storeImplPtr);
-
- parcObject_Release((PARCObject **)&store);
-}
-
-static bool _contentStoreLRU_Destructor(_ContentStoreLRU **storePtr) {
- _ContentStoreLRU *store = *storePtr;
-
- _destroyIndexes(store);
- logger_Release(&store->logger);
-
- return true;
-}
-
-parcObject_Override(_ContentStoreLRU, PARCObject,
- .destructor = (PARCObjectDestructor *)
- _contentStoreLRU_Destructor);
-
-parcObject_ExtendPARCObject(ContentStoreInterface,
- _contentStoreInterface_Destroy, NULL, NULL, NULL,
- NULL, NULL, NULL);
-
-static parcObject_ImplementAcquire(_contentStoreLRU, ContentStoreInterface);
-static parcObject_ImplementRelease(_contentStoreLRU, ContentStoreInterface);
-
-static void _hashTableFunction_ContentStoreEntryDestroyer(void **dataPtr) {
- contentStoreEntry_Release((ContentStoreEntry **)dataPtr);
-}
-
-static bool _contentStoreLRU_Init(_ContentStoreLRU *store,
- ContentStoreConfig *config, Logger *logger) {
- bool result = false;
-
- store->logger = logger_Acquire(logger);
-
- size_t initialSize = config->objectCapacity * 2;
- memset(&store->stats, 0, sizeof(_ContentStoreLRUStats));
-
- store->objectCapacity = config->objectCapacity;
- store->objectCount = 0;
-
- // initial size must be at least 1 or else the data structures break.
- initialSize = (initialSize == 0) ? 1 : initialSize;
-
- store->indexByExpirationTime = listTimeOrdered_Create(
- (TimeOrderList_KeyCompare *)contentStoreEntry_CompareExpiryTime);
-
- store->storageByName = parcHashCodeTable_Create_Size(
- hashTableFunction_MessageNameEquals,
- hashTableFunction_MessageNameHashCode, NULL,
- _hashTableFunction_ContentStoreEntryDestroyer, initialSize);
-
- store->lru = listLRU_Create();
-
- // If any of the index tables couldn't be allocated, we can't continue.
- if ((store->indexByExpirationTime == NULL) ||
- (store->storageByName == NULL) || (store->lru == NULL)) {
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Error)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Error,
- __func__,
- "ContentStoreLRU could not be created. Could not allocate all "
- "index tables.",
- (void *)store, store->objectCapacity);
- }
-
- _destroyIndexes(store);
- result = false;
- } else {
- result = true;
- }
- return result;
-}
-
-/**
- * Remove a ContentStoreEntry from all tables and indices.
- */
-static void _contentStoreLRU_PurgeStoreEntry(_ContentStoreLRU *store,
- ContentStoreEntry *entryToPurge) {
- if (contentStoreEntry_HasExpiryTimeTicks(entryToPurge)) {
- listTimeOrdered_Remove(store->indexByExpirationTime, entryToPurge);
- }
-
- Message *content = contentStoreEntry_GetMessage(entryToPurge);
-
- // This _Del call will call the Release/Destroy on the ContentStoreEntry,
- // which will remove it from the LRU as well.
- parcHashCodeTable_Del(store->storageByName, content);
-
- store->objectCount--;
-}
-
-static bool _contentStoreLRU_RemoveLeastUsed(_ContentStoreLRU *store) {
- bool result = false;
-
- if (store->objectCount > 0) {
- ListLruEntry *lruEntry = listLRU_PopTail(store->lru);
- ContentStoreEntry *storeEntry =
- (ContentStoreEntry *)listLRU_EntryGetData(lruEntry);
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(
- store->logger, LoggerFacility_Processor, PARCLogLevel_Debug, __func__,
- "ContentStore %p evict message %p by LRU (LRU evictions %" PRIu64 ")",
- (void *)store, (void *)contentStoreEntry_GetMessage(storeEntry),
- store->stats.countLruEvictions);
- }
-
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
-
- result = true;
- }
- return result;
-}
-
-static void _evictByStorePolicy(_ContentStoreLRU *store,
- uint64_t currentTimeInTicks) {
- // We need to make room. Here's the plan:
- // 1) Check to see if anything has expired. If so, remove it and we're done.
- // If not, 2) Remove the least recently used item.
-
- ContentStoreEntry *entry =
- listTimeOrdered_GetOldest(store->indexByExpirationTime);
- if (entry && contentStoreEntry_HasExpiryTimeTicks(entry) &&
- (currentTimeInTicks > contentStoreEntry_GetExpiryTimeTicks(entry))) {
- // Found an expired entry. Remove it, and we're done.
-
- store->stats.countExpiryEvictions++;
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStore %p evict message %p by ExpiryTime (ExpiryTime "
- "evictions %" PRIu64 ")",
- (void *)store, (void *)contentStoreEntry_GetMessage(entry),
- store->stats.countExpiryEvictions);
- }
-
- _contentStoreLRU_PurgeStoreEntry(store, entry);
- } else {
- store->stats.countLruEvictions++;
- _contentStoreLRU_RemoveLeastUsed(store);
- }
-}
-
-static bool _contentStoreLRU_PutContent(ContentStoreInterface *storeImpl,
- Message *content,
- uint64_t currentTimeTicks)
-
-{
- bool result = false;
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- parcAssertNotNull(store, "Parameter store must be non-null");
- parcAssertNotNull(content, "Parameter objectMessage must be non-null");
-
- parcAssertTrue(message_GetType(content) == MessagePacketType_ContentObject,
- "Parameter objectMessage must be a Content Object");
-
- if (store->objectCapacity == 0) {
- return false;
- }
-
- ContentStoreEntry *storeEntry = parcHashCodeTable_Get(store->storageByName, content);
- if(storeEntry){
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
- }
-
- uint64_t expiryTimeTicks = contentStoreEntry_MaxExpiryTime;
-
- if (message_HasContentExpiryTime(content)) {
- expiryTimeTicks = message_GetContentExpiryTimeTicks(content);
- }
- // Don't add anything that's already expired or has exceeded RCT.
- if (currentTimeTicks >= expiryTimeTicks) {
- return false;
- }
-
- if (store->objectCount >= store->objectCapacity) {
- // Store is full. Need to make room.
- _evictByStorePolicy(store, currentTimeTicks);
- }
-
- // And now add a new entry to the head of the LRU.
-
- ContentStoreEntry *entry = contentStoreEntry_Create(content, store->lru);
-
- if (entry != NULL) {
- if (parcHashCodeTable_Add(store->storageByName, content, entry)) {
- if (contentStoreEntry_HasExpiryTimeTicks(entry)) {
- listTimeOrdered_Add(store->indexByExpirationTime, entry);
- }
-
- store->objectCount++;
- store->stats.countAdds++;
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStoreLRU %p saved message %p (object count %" PRIu64
- ")",
- (void *)store, (void *)content, store->objectCount);
- }
-
- result = true;
- } else {
- // Free what we just created, but did not add. 'entry' has ownership of
- // 'copy', and so will call _Release() on it
- contentStoreEntry_Release(&entry);
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Warning)) {
- logger_Log(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Warning, __func__,
- "ContentStoreLRU %p failed to add message %p to hash table",
- (void *)store, (void *)content);
- }
- }
- }
-
- return result;
-}
-
-static Message *_contentStoreLRU_MatchInterest(ContentStoreInterface *storeImpl,
- Message *interest,
- uint64_t currentTimeTicks) {
- Message *result = NULL;
-
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
-
- parcAssertNotNull(store, "Parameter store must be non-null");
- parcAssertNotNull(interest, "Parameter interestMessage must be non-null");
- parcAssertTrue(message_GetType(interest) == MessagePacketType_Interest,
- "Parameter interestMessage must be an Interest");
-
- PARCHashCodeTable *table;
- table = store->storageByName;
-
- ContentStoreEntry *storeEntry = parcHashCodeTable_Get(table, interest);
-
- bool foundEntry = false;
-
- if (storeEntry) {
- if (contentStoreEntry_HasExpiryTimeTicks(storeEntry) &&
- contentStoreEntry_GetExpiryTimeTicks(storeEntry) < currentTimeTicks) {
- // the entry is expired, we can remove it
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
- } else {
- foundEntry = true;
- }
- }
-
- if (foundEntry) {
- contentStoreEntry_MoveToHead(storeEntry);
- result = contentStoreEntry_GetMessage(storeEntry);
-
- store->stats.countHits++;
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStoreLRU %p matched interest %p (hits %" PRIu64
- ", misses %" PRIu64 ")",
- (void *)store, (void *)interest, store->stats.countHits,
- store->stats.countMisses);
- }
- } else {
- store->stats.countMisses++;
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStoreLRU %p missed interest %p (hits %" PRIu64
- ", misses %" PRIu64 ")",
- (void *)store, (void *)interest, store->stats.countHits,
- store->stats.countMisses);
- }
- }
-
- return result;
-}
-
-static bool _contentStoreLRU_RemoveContent(ContentStoreInterface *storeImpl,
- Message *content) {
- bool result = false;
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
-
- ContentStoreEntry *storeEntry =
- parcHashCodeTable_Get(store->storageByName, content);
-
- if (storeEntry != NULL) {
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
- result = true;
- }
-
- return result;
-}
-
-static void _contentStoreLRU_Log(ContentStoreInterface *storeImpl) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
-
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_All,
- __func__,
- "ContentStoreLRU @%p {count = %zu, capacity = %zu {"
- "stats = @%p {adds = %" PRIu64 ", hits = %" PRIu64
- ", misses = %" PRIu64 ", LRUEvictons = %" PRIu64
- ", ExpiryEvictions = %" PRIu64 ", RCTEvictions = %" PRIu64 "} }",
- store, store->objectCount, store->objectCapacity, &store->stats,
- store->stats.countAdds, store->stats.countHits,
- store->stats.countMisses, store->stats.countLruEvictions,
- store->stats.countExpiryEvictions, store->stats.countRCTEvictions);
-}
-
-static size_t _contentStoreLRU_GetObjectCapacity(
- ContentStoreInterface *storeImpl) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- return store->objectCapacity;
-}
-
-static size_t _contentStoreLRU_GetObjectCount(
- ContentStoreInterface *storeImpl) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- return store->objectCount;
-}
-
-static size_t _contentStoreLRU_SetObjectCapacity(
- ContentStoreInterface *storeImpl, size_t newCapacity) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- return store->objectCapacity = newCapacity;
-}
-
-ContentStoreInterface *contentStoreLRU_Create(ContentStoreConfig *config,
- Logger *logger) {
- ContentStoreInterface *storeImpl = NULL;
-
- parcAssertNotNull(logger, "ContentStoreLRU requires a non-NULL logger");
-
- storeImpl = parcObject_CreateAndClearInstance(ContentStoreInterface);
-
- if (storeImpl != NULL) {
- storeImpl->_privateData =
- parcObject_CreateAndClearInstance(_ContentStoreLRU);
-
- if (_contentStoreLRU_Init(storeImpl->_privateData, config, logger)) {
- storeImpl->putContent = &_contentStoreLRU_PutContent;
- storeImpl->removeContent = &_contentStoreLRU_RemoveContent;
-
- storeImpl->matchInterest = &_contentStoreLRU_MatchInterest;
-
- storeImpl->getObjectCount = &_contentStoreLRU_GetObjectCount;
- storeImpl->getObjectCapacity = &_contentStoreLRU_GetObjectCapacity;
-
- storeImpl->log = &_contentStoreLRU_Log;
-
- storeImpl->acquire = &_contentStoreLRU_Acquire;
- storeImpl->release = &_contentStoreLRU_Release;
-
- // Initialize from the config passed to us.
- _contentStoreLRU_SetObjectCapacity(storeImpl, config->objectCapacity);
-
- if (logger_IsLoggable(logger, LoggerFacility_Processor,
- PARCLogLevel_Info)) {
- logger_Log(logger, LoggerFacility_Processor, PARCLogLevel_Info,
- __func__, "ContentStoreLRU %p created with capacity %zu",
- (void *)storeImpl,
- contentStoreInterface_GetObjectCapacity(storeImpl));
- }
- }
- } else {
- parcObject_Release((void **)&storeImpl);
- }
-
- return storeImpl;
-}
diff --git a/hicn-light/src/hicn/content_store/contentStoreLRU.h b/hicn-light/src/hicn/content_store/contentStoreLRU.h
deleted file mode 100644
index 94ec4d6b2..000000000
--- a/hicn-light/src/hicn/content_store/contentStoreLRU.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef contentStoreLRU_h
-#define contentStoreLRU_h
-
-#include <hicn/content_store/contentStoreInterface.h>
-#include <hicn/core/logger.h>
-#include <stdio.h>
-
-/**
- * Create and Initialize an instance of contentStoreLRU. A newly allocated
- * {@link ContentStoreInterface} object is initialized and returned. It must
- * eventually be released by calling {@link contentStoreInterface_Release}.
- *
- *
- * @param config An instance of `ContentStoreConfig`, specifying options to be
- * applied by the underlying contentStoreLRU instance.
- * @param logger An instance of a {@link Logger} to use for logging content
- * store events.
- *
- * @return a newly created contentStoreLRU instance.
- *
- */
-ContentStoreInterface *contentStoreLRU_Create(ContentStoreConfig *config,
- Logger *logger);
-#endif // contentStoreLRU_h
diff --git a/hicn-light/src/hicn/content_store/listLRU.c b/hicn-light/src/hicn/content_store/listLRU.c
deleted file mode 100644
index 242af4078..000000000
--- a/hicn-light/src/hicn/content_store/listLRU.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <sys/queue.h>
-#endif
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/content_store/listLRU.h>
-
-struct list_lru_entry {
- void *userData;
-
- // always set to the list
- ListLru *parentList;
-
- // indicates if the Entry is currently in the list
- bool inList;
-
- TAILQ_ENTRY(list_lru_entry) list;
-};
-
-// this defines the TAILQ structure so we can access the tail pointer
-TAILQ_HEAD(lru_s, list_lru_entry);
-
-struct list_lru {
- struct lru_s head;
- size_t itemsInList;
-};
-
-void listLRU_EntryDestroy(ListLruEntry **entryPtr) {
- parcAssertNotNull(entryPtr,
- "Parameter entryPtr must be non-null double pointer");
-
- ListLruEntry *entry = *entryPtr;
- if (entry->inList) {
- TAILQ_REMOVE(&entry->parentList->head, entry, list);
- parcAssertTrue(
- entry->parentList->itemsInList > 0,
- "Invalid state, removed entry from list, but itemsInList is 0");
- entry->parentList->itemsInList--;
- }
-
- parcMemory_Deallocate((void **)&entry);
- *entryPtr = NULL;
-}
-
-void listLRU_EntryMoveToHead(ListLruEntry *entry) {
- parcAssertNotNull(entry, "Parameter entry must be non-null");
-
- TAILQ_REMOVE(&entry->parentList->head, entry, list);
- TAILQ_INSERT_HEAD(&entry->parentList->head, entry, list);
-}
-
-void *listLRU_EntryGetData(ListLruEntry *entry) { return entry->userData; }
-
-ListLru *listLRU_Create() {
- ListLru *list = parcMemory_AllocateAndClear(sizeof(ListLru));
- parcAssertNotNull(list, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListLru));
- list->itemsInList = 0;
- TAILQ_INIT(&list->head);
- return list;
-}
-
-void listLRU_Destroy(ListLru **lruPtr) {
- parcAssertNotNull(lruPtr, "Parameter lruPtr must be non-null double pointer");
-
- ListLru *lru = *lruPtr;
-
- ListLruEntry *entry = TAILQ_FIRST(&lru->head);
- while (entry != NULL) {
- ListLruEntry *next = TAILQ_NEXT(entry, list);
- listLRU_EntryDestroy(&entry);
- entry = next;
- }
-
- parcMemory_Deallocate((void **)&lru);
- *lruPtr = NULL;
-}
-
-ListLruEntry *listLRU_NewHeadEntry(ListLru *lru, void *data) {
- parcAssertNotNull(lru, "Parameter lru must be non-null");
- parcAssertNotNull(data, "Parameter data must be non-null");
-
- ListLruEntry *entry = parcMemory_AllocateAndClear(sizeof(ListLruEntry));
- parcAssertNotNull(entry, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListLruEntry));
- entry->userData = data;
- entry->parentList = lru;
- entry->inList = true;
-
- TAILQ_INSERT_HEAD(&lru->head, entry, list);
- lru->itemsInList++;
-
- return entry;
-}
-
-ListLruEntry *listLRU_PopTail(ListLru *lru) {
- parcAssertNotNull(lru, "Parameter lru must be non-null");
-
- ListLruEntry *entry = TAILQ_LAST(&lru->head, lru_s);
-
- if (entry) {
- parcAssertTrue(
- lru->itemsInList > 0,
- "Invalid state, removed entry from list, but itemsInList is 0");
- lru->itemsInList--;
- TAILQ_REMOVE(&lru->head, entry, list);
- entry->inList = false;
- }
-
- return entry;
-}
-
-size_t listLRU_Length(const ListLru *lru) {
- parcAssertNotNull(lru, "Parameter lru must be non-null");
- return lru->itemsInList;
-}
diff --git a/hicn-light/src/hicn/content_store/listLRU.h b/hicn-light/src/hicn/content_store/listLRU.h
deleted file mode 100644
index 75f698b61..000000000
--- a/hicn-light/src/hicn/content_store/listLRU.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file listLRU.h
- * @brief Maintains an LRU for the content store
- *
- * An LRU list is make up of LRU entries. The entries are bound to the list.
- * The user of the list is reponsible for knowing when there's too many things
- * and wants to remove one. The LRU list will grow without bound otherwise.
- *
- * The LRU list is meant to be used as an auxiliary data structure, not the
- * primary storage of data elements.
- *
- */
-
-#ifndef listLRU_h
-#define listLRU_h
-
-struct list_lru_entry;
-typedef struct list_lru_entry ListLruEntry;
-
-struct list_lru;
-typedef struct list_lru ListLru;
-
-/**
- * @function lruEntry_Destroy
- * @abstract Destroys and element. This will also remove it from the list.
- */
-void listLRU_EntryDestroy(ListLruEntry **entryPtr);
-
-/**
- * @function listLRU_EntryMoveToHead
- * @abstract move an element to head
- */
-void listLRU_EntryMoveToHead(ListLruEntry *entry);
-
-/**
- * @function lruEntry_GetData
- * @abstract Returns the user-supplied opaque data when the entry was created
- */
-void *listLRU_EntryGetData(ListLruEntry *entry);
-
-/**
- * @function listLRU_Create
- * @abstract Creates a new Least-Recently-Used list
- */
-ListLru *listLRU_Create();
-
-/**
- * @function listLRU_Destroy
- * @abstract Destroys a list and frees all the elements in it
- */
-void listLRU_Destroy(ListLru **listPtr);
-
-/**
- * Returns the number of items in the list
- *
- * @param [in] lru An allocated ListLru
- * @retval number The number of items in the LRU list
- */
-size_t listLRU_Length(const ListLru *lru);
-
-/**
- * @function listLRU_NewHeadEntry
- * @abstract Creates a new entry for the list. It is inserted at the head of
- * the list.
- */
-ListLruEntry *listLRU_NewHeadEntry(ListLru *lru, void *data);
-
-/**
- * @function listLRU_PopTail
- * @abstract Removes the tail element from the list and returns it to the user
- * @discussion
- * Pops the tail element. The user should examine its data to destroy their
- * tail object, then call <code>LruEntry_Destroy()</code> to free the
- * LRU entry.
- *
- * @return The tail element, or NULL for an empty list
- */
-ListLruEntry *listLRU_PopTail(ListLru *list);
-#endif // listLRU_h
diff --git a/hicn-light/src/hicn/content_store/listTimeOrdered.c b/hicn-light/src/hicn/content_store/listTimeOrdered.c
deleted file mode 100644
index 690c6e412..000000000
--- a/hicn-light/src/hicn/content_store/listTimeOrdered.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <hicn/content_store/listTimeOrdered.h>
-
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_TreeRedBlack.h>
-
-/**
- * A list of ContentStoreEntrys, kept in sorted order by time. The ordering is
- * calculated by a key compare function (e.g. {@link TimeOrderList_KeyCompare}),
- * passed in.
- *
- * This container does not hold references to the objects that it contains. In
- * other words, it does not Acquire() the Messages that are placed in it. That
- * reference count is managed by the owning ContentStore. This is purely an
- * index, and provides an easy to way index Messages based on a specified time
- * value. Typically, that would be the Expiration Time.
- *
- * It maintains a tree, sorted by the time values passed in to the Add()
- * function. It does not manage capacity, and can grow uncontrollably if the
- * owning ContentStore does not manage it. Items are indexed first by time, then
- * address of the Message (just as a distringuishing attribute). This allows us
- * to store multiple items with the same expiration time.
- */
-
-struct list_timeordered {
- PARCTreeRedBlack *timeOrderedTree;
-};
-
-static void _finalRelease(ListTimeOrdered **listP) {
- ListTimeOrdered *list = *listP;
- parcTreeRedBlack_Destroy(&list->timeOrderedTree);
-}
-
-parcObject_ExtendPARCObject(ListTimeOrdered, _finalRelease, NULL, NULL, NULL,
- NULL, NULL, NULL);
-
-parcObject_ImplementAcquire(listTimeOrdered, ListTimeOrdered);
-
-parcObject_ImplementRelease(listTimeOrdered, ListTimeOrdered);
-
-ListTimeOrdered *listTimeOrdered_Create(
- TimeOrderList_KeyCompare *keyCompareFunction) {
- ListTimeOrdered *result = parcObject_CreateInstance(ListTimeOrdered);
- if (NULL != result) {
- result->timeOrderedTree =
- parcTreeRedBlack_Create(keyCompareFunction, // keyCompare
- NULL, // keyFree
- NULL, // keyCopy
- NULL, // valueEquals
- NULL, // valueFree
- NULL); // valueCopy
- }
- return result;
-}
-
-void listTimeOrdered_Add(ListTimeOrdered *list, ContentStoreEntry *entry) {
- parcTreeRedBlack_Insert(list->timeOrderedTree, entry, entry);
-}
-
-ContentStoreEntry *listTimeOrdered_GetOldest(ListTimeOrdered *list) {
- return parcTreeRedBlack_FirstKey(list->timeOrderedTree);
-}
-
-bool listTimeOrdered_Remove(ListTimeOrdered *list,
- ContentStoreEntry *storeEntry) {
- bool result = false;
-
- ContentStoreEntry *entry = (ContentStoreEntry *)parcTreeRedBlack_Remove(
- list->timeOrderedTree, storeEntry);
- if (entry != NULL) {
- result = true;
- }
- return result;
-}
-
-size_t listTimeOrdered_Length(ListTimeOrdered *list) {
- return (size_t)parcTreeRedBlack_Size(list->timeOrderedTree);
-}
diff --git a/hicn-light/src/hicn/content_store/listTimeOrdered.h b/hicn-light/src/hicn/content_store/listTimeOrdered.h
deleted file mode 100644
index 325e7c0d4..000000000
--- a/hicn-light/src/hicn/content_store/listTimeOrdered.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef listTimeOrdered_h
-#define listTimeOrdered_h
-
-#include <parc/algol/parc_TreeRedBlack.h>
-#include <hicn/content_store/contentStoreEntry.h>
-#include <hicn/core/message.h>
-#include <stdio.h>
-
-struct list_timeordered;
-typedef struct list_timeordered ListTimeOrdered;
-
-/**
- * A signum function that takes two instances of ContentStoreEntrys and
- * returns a value based on their relative values.
- */
-typedef PARCTreeRedBlack_KeyCompare TimeOrderList_KeyCompare;
-
-/**
- * Create a new instance of `ListTimeOrdered` that will maintain the order of
- * its list items using the supplied `keyCompareFunction`.
- *
- * The newly created `ListTimeOrdered` must eventually be released by calling
- * {@link listTimeOrdered_Release}.
- *
- * @param keyCompareFunction the signum comparison function to use to sort
- * stored items.
- * @return a new instance of `TimeOrderList`.
- * @return NULL if the new instance couldn't be created.
- *
- */
-ListTimeOrdered *listTimeOrdered_Create(
- TimeOrderList_KeyCompare *keyCompareFunction);
-
-/**
- * Release a previously acquired reference to the specified instance,
- * decrementing the reference count for the instance.
- *
- * The pointer to the instance is set to NULL as a side-effect of this function.
- *
- * If the invocation causes the last reference to the instance to be released,
- * the instance is deallocated and the instance's implementation will perform
- * additional cleanup and release other privately held references.
- *
- */
-void listTimeOrdered_Release(ListTimeOrdered **listP);
-
-/**
- * Add a {@link ContentStoreEntry} instance to the specified list. Note that a
- * new refernece to the specified `storeEntry` is not acquired.
- *
- * @param list the list instance into which to add the specified storeEntry.
- * @param storeEntry the storeEntry instance to add.
- *
- */
-void listTimeOrdered_Add(ListTimeOrdered *list, ContentStoreEntry *storeEntry);
-
-/**
- * Remove a {@link ContentStoreEntry} instance from the specified list.
- *
- * @param list the list instance from which to remove the specified storeEntry.
- * @param storeEntry the storeEntry instance to remove.
- * @return true if the removal was succesful.
- * @return false if the removal was not succesful.
- *
- */
-bool listTimeOrdered_Remove(ListTimeOrdered *list,
- ContentStoreEntry *storeEntry);
-
-/**
- * Return the oldest {@link ContentStoreEntry} instance in this list. That is,
- * the one with the smallest time value.
- *
- * @param list the list instance from which to retrieve the oldest storeEntry.
- * @param the oldest `ContentStoreEntry` in the list
- * @param NULL if no `ContentStoreEntry` was available.
- *
- */
-ContentStoreEntry *listTimeOrdered_GetOldest(ListTimeOrdered *list);
-
-/**
- * Return the number of items currently stored in the list.
- *
- * @param list the `ListTimeOrdered` instance from which to retrieve the count.
- * @return the number of items in the list.
- *
- */
-size_t listTimeOrdered_Length(ListTimeOrdered *list);
-#endif /* defined(listTimeOrdered_h) */
diff --git a/hicn-light/src/hicn/content_store/lru.c b/hicn-light/src/hicn/content_store/lru.c
new file mode 100644
index 000000000..2f1fb9427
--- /dev/null
+++ b/hicn-light/src/hicn/content_store/lru.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <sys/queue.h>
+#endif
+
+#include <hicn/util/log.h>
+
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+
+#include <hicn/core/packet_cache.h>
+#include "lru.h"
+
+void cs_lru_initialize(cs_t *cs) {
+ /* We start with an empty double-linked list */
+ cs->lru.head = INVALID_ENTRY_ID;
+ cs->lru.tail = INVALID_ENTRY_ID;
+}
+
+void cs_lru_finalize(cs_t *cs) {
+ // Nothing to do
+}
+
+cs_entry_t *_cs_entry_at(pkt_cache_t *pkt_cache, off_t entry_id) {
+ pkt_cache_entry_t *entry = pkt_cache_entry_at(pkt_cache, entry_id);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+ return &entry->u.cs_entry;
+}
+
+/**
+ * Remove a cs_entry_t from all tables and indices.
+ */
+static int cs_lru_remove_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry) {
+ assert(pkt_cache);
+ assert(entry);
+
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ cs_entry_t *cs_entry = &entry->u.cs_entry;
+
+ // If node to be deleted is head node
+ if (cs->lru.head == entry_id) cs->lru.head = cs_entry->lru.next;
+
+ // If node to be deleted is tail node
+ if (cs->lru.tail == entry_id) cs->lru.tail = cs_entry->lru.prev;
+
+ // If node to be deleted is not the last node
+ if (cs_entry->lru.next != INVALID_ENTRY_ID) {
+ cs_entry_t *next_cs_entry = _cs_entry_at(pkt_cache, cs_entry->lru.next);
+ assert(next_cs_entry);
+ next_cs_entry->lru.prev = cs_entry->lru.prev;
+ }
+
+ // If node to be deleted is not the first node
+ if (cs_entry->lru.prev != INVALID_ENTRY_ID) {
+ cs_entry_t *prev_entry = _cs_entry_at(pkt_cache, cs_entry->lru.prev);
+ assert(prev_entry);
+ prev_entry->lru.next = cs_entry->lru.next;
+ }
+
+ cs->stats.lru.countLruDeletions++;
+ return LRU_SUCCESS;
+}
+
+/**
+ * @brief LRU processing related to the insertion of a new entry in the content
+ * store (helper).
+ * @param[in] cs Content store.
+ * @param[in] entry_id Identifier of the entry in the content store entry pool.
+ * @param[in] is_update Boolean value to distinguish update from add operations
+ * since an update involves removing an entry and adding it again
+ *
+ * @return int Error code : 0 if succesful, a negative value otherwise.
+ *
+ * NOTE:
+ * - We insert the new element at the head of the double-linked list.
+ */
+int _cs_lru_add_entry(pkt_cache_t *pkt_cache, off_t entry_id, bool is_update) {
+ assert(pkt_cache);
+
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ cs_entry_t *entry = _cs_entry_at(pkt_cache, entry_id);
+ assert(entry);
+
+ // Add at the front of the LRU doubly linked list
+ if (cs->lru.head != INVALID_ENTRY_ID) {
+ cs_entry_t *head_entry = _cs_entry_at(pkt_cache, cs->lru.head);
+ assert(head_entry->lru.prev == INVALID_ENTRY_ID);
+ head_entry->lru.prev = entry_id;
+
+ entry->lru.next = cs->lru.head;
+ entry->lru.prev = INVALID_ENTRY_ID;
+
+ cs->lru.head = entry_id;
+ } else { /* The list is empty */
+ assert(cs->lru.tail == INVALID_ENTRY_ID);
+
+ entry->lru.next = INVALID_ENTRY_ID;
+ entry->lru.prev = INVALID_ENTRY_ID;
+ cs->lru.head = cs->lru.tail = entry_id;
+ }
+ if (!is_update) cs->stats.lru.countAdds++;
+
+ // Handle LRU eviction
+ if (cs->num_entries > cs->max_size) {
+ DEBUG("LRU eviction");
+ cs->stats.lru.countLruEvictions++;
+
+ // Remove from LRU tail
+ pkt_cache_entry_t *tail = pkt_cache_entry_at(pkt_cache, cs->lru.tail);
+ cs_lru_remove_entry(pkt_cache, tail);
+ return LRU_EVICTION;
+ }
+
+ return LRU_SUCCESS;
+}
+
+/**
+ * @brief LRU processing related to the insertion of a new entry in the content
+ * store.
+ * @param[in] cs Content store.
+ * @param[in] entry_id Identifier of the entry in the content store entry pool.
+ *
+ * @return int Error code : 0 if succesful, a negative value otherwise.
+ *
+ * NOTE:
+ * - We insert the new element at the head of the double-linked list.
+ */
+static int cs_lru_add_entry(pkt_cache_t *pkt_cache, off_t entry_id) {
+ return _cs_lru_add_entry(pkt_cache, entry_id, false);
+}
+
+/**
+ * Move a cs_entry_t to the LRU head.
+ */
+static void cs_lru_update_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry) {
+ assert(pkt_cache);
+ assert(entry);
+
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ cs->stats.lru.countUpdates++;
+
+ // Remove from LRU
+ cs_lru_remove_entry(pkt_cache, entry);
+
+ // Attach at the LRU head
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ _cs_lru_add_entry(pkt_cache, entry_id, true);
+}
+
+DECLARE_CS(lru);
diff --git a/hicn-light/src/hicn/content_store/lru.h b/hicn-light/src/hicn/content_store/lru.h
new file mode 100644
index 000000000..9e78ce327
--- /dev/null
+++ b/hicn-light/src/hicn/content_store/lru.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICNLIGHT_CS_LRU_H
+#define HICNLIGHT_CS_LRU_H
+
+#define LRU_FAILURE 0
+#define LRU_SUCCESS 1
+#define LRU_EVICTION 2
+
+typedef struct {
+ off_t prev;
+ off_t next;
+} cs_entry_lru_state_t;
+
+typedef struct {
+ off_t head;
+ off_t tail;
+} cs_lru_state_t;
+
+/**
+ * @brief Count the number of:
+ * - CS matches
+ * - CS misses
+ * - entries added to CS/LRU (upon receiving a data packet)
+ * - entries updated in the LRU
+ * (because an already-existing CS entry has been updated)
+ * - LRU evictions
+ *
+ * 'countExpiryEvictions' is not collected since an entry is never evicted
+ * because of expiration. An expired CS entry is only detected when
+ * a data packet with the same name is received, causing an update
+ * (NOT an actual eviction).
+ */
+typedef struct {
+ uint64_t countHits;
+ uint64_t countMisses;
+ uint64_t countAdds;
+ uint64_t countUpdates;
+ uint64_t countLruDeletions;
+ uint64_t countLruEvictions;
+} cs_lru_stats_t;
+
+#endif /* HICNLIGHT_CS_LRU_H */
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index 1b13be91f..57ffb780f 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,49 +12,63 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionState.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionTable.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/address.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/address_pair.h
${CMAKE_CURRENT_SOURCE_DIR}/connection.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_vft.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_table.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/content_store.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib.h
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h
- ${CMAKE_CURRENT_SOURCE_DIR}/logger.h
- ${CMAKE_CURRENT_SOURCE_DIR}/dispatcher.h
- ${CMAKE_CURRENT_SOURCE_DIR}/message.h
- ${CMAKE_CURRENT_SOURCE_DIR}/messagePacketType.h
- ${CMAKE_CURRENT_SOURCE_DIR}/numberSet.h
- ${CMAKE_CURRENT_SOURCE_DIR}/streamBuffer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/system.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/pit.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/policy_stats.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_vft.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/subscription.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/system.h
${CMAKE_CURRENT_SOURCE_DIR}/mapme.h
${CMAKE_CURRENT_SOURCE_DIR}/wldr.h
${CMAKE_CURRENT_SOURCE_DIR}/messageHandler.h
${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.h
${CMAKE_CURRENT_SOURCE_DIR}/name.h
)
list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/address.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/address_pair.c
${CMAKE_CURRENT_SOURCE_DIR}/connection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionList.c
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.c
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionTable.c
- ${CMAKE_CURRENT_SOURCE_DIR}/dispatcher.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_table.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_vft.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/content_store.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.c
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.c
- ${CMAKE_CURRENT_SOURCE_DIR}/logger.c
- ${CMAKE_CURRENT_SOURCE_DIR}/message.c
- ${CMAKE_CURRENT_SOURCE_DIR}/numberSet.c
- ${CMAKE_CURRENT_SOURCE_DIR}/streamBuffer.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.c
${CMAKE_CURRENT_SOURCE_DIR}/mapme.c
- ${CMAKE_CURRENT_SOURCE_DIR}/wldr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.c
${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.c
${CMAKE_CURRENT_SOURCE_DIR}/name.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pit.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/policy_stats.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_vft.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/subscription.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/wldr.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
-
-set(TO_INSTALL_HEADER_FILES
- ${TO_INSTALL_HEADER_FILES}
- ${HEADER_FILES}
- PARENT_SCOPE
-)
diff --git a/hicn-light/src/hicn/core/address.c b/hicn-light/src/hicn/core/address.c
new file mode 100644
index 000000000..a4b41c8b5
--- /dev/null
+++ b/hicn-light/src/hicn/core/address.c
@@ -0,0 +1,66 @@
+/*
+ * 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 address.c
+ * \brief Implementation of Address
+ */
+
+#include <hicn/core/address.h>
+#include <hicn/util/sstrncpy.h>
+
+int address_from_ip_port(address_t *address, int family, ip_address_t *addr,
+ uint16_t port) {
+ switch (family) {
+ case AF_INET:
+ *address = ADDRESS4(ntohl(addr->v4.as_inaddr.s_addr), ntohs(port));
+ break;
+ case AF_INET6:
+ *address = ADDRESS6(addr->v6.as_in6addr, ntohs(port));
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+const char *_address_family_str[] = {
+ [AF_INET] = "AF_INET",
+ [AF_INET6] = "AF_INET6",
+};
+
+int address_to_string(const address_t *address, char *addr_str, int *port) {
+ const int SUCCESS = 0;
+ char port_str[NI_MAXSERV];
+ struct sockaddr_storage addr = address->as_ss;
+ socklen_t addr_len = sizeof(addr);
+
+ int result =
+ getnameinfo((struct sockaddr *)&addr, addr_len, addr_str, NI_MAXHOST,
+ port_str, sizeof(port_str), NI_NUMERICHOST | NI_NUMERICSERV);
+
+ if (result != SUCCESS) {
+ strcpy_s(addr_str, NI_MAXHOST, "N/A");
+ if (port != NULL) *port = -1;
+ return result;
+ }
+
+ if (port != NULL) *port = atoi(port_str);
+ return SUCCESS;
+}
+
+address_t _ADDRESS4_LOCALHOST(uint16_t port) {
+ return ADDRESS4_LOCALHOST(port);
+}
diff --git a/hicn-light/src/hicn/core/address.h b/hicn-light/src/hicn/core/address.h
new file mode 100644
index 000000000..7958bd063
--- /dev/null
+++ b/hicn-light/src/hicn/core/address.h
@@ -0,0 +1,141 @@
+/*
+ * 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 address.h
+ * \brief Address
+ */
+
+#ifndef HICNLIGHT_ADDRESS_H
+#define HICNLIGHT_ADDRESS_H
+
+#include <netinet/in.h>
+
+#include <string.h> // memcmp
+#include <hicn/util/ip_address.h>
+#include <netinet/in.h>
+
+typedef union {
+ struct sockaddr_in as_sin;
+ struct sockaddr_in6 as_sin6;
+ struct sockaddr as_sa;
+ struct sockaddr_storage as_ss;
+} address_t;
+
+#define address_equals(a, b) (memcmp(a, b, sizeof(address_t)) == 0)
+
+#define address_family(address) ((address)->as_ss.ss_family)
+
+#define address4(address) ((struct sockaddr_in *)(address))
+#define address6(address) ((struct sockaddr_in6 *)(address))
+#define address_sa(address) ((struct sockaddr *)(address))
+
+#define address4_ip(address) (address4(address)->sin_addr)
+#define address6_ip(address) (address6(address)->sin6_addr)
+#define address6_scope_id(address) (address4_ptr(address)->sin6_scope_id)
+
+#define address_socklen(address) \
+ (((address)->as_ss.ss_family == AF_INET) ? sizeof(struct sockaddr_in) \
+ : sizeof(struct sockaddr_in6))
+
+#define address4_is_local(address) \
+ ((htonl((address4_ip(address)).s_addr) & 0xFF000000) == 0x7F000000)
+
+static inline bool _address6_is_local(struct sockaddr_in6 *sin6) {
+ return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
+}
+
+#define address6_is_local(address) (_address6_is_local(address6(address)))
+
+#define address_is_local(address) \
+ ((address)->as_ss.ss_family == AF_INET) ? address4_is_local(address) \
+ : address6_is_local(address)
+
+int address_from_ip_port(address_t *address, int family, ip_address_t *addr,
+ uint16_t port);
+
+static inline address_t ADDRESS4(in_addr_t in_addr, int port) {
+ address_t address = {
+ .as_sin =
+ {
+ .sin_family = AF_INET,
+ .sin_port = htons(port),
+ .sin_addr = {.s_addr = htonl(in_addr)},
+ },
+ };
+
+ return address;
+}
+
+#define ADDRESS4_LOCALHOST(port) ADDRESS4(INADDR_LOOPBACK, (port))
+
+/**
+ * @brief Helper function to avoid macro expansion in c++ tests. Wrapper around
+ * 'ADDRESS4_LOCALHOST()'.
+ *
+ * @param port
+ * @return address_t
+ */
+address_t _ADDRESS4_LOCALHOST(uint16_t port);
+
+#define ADDRESS4_ANY(port) ADDRESS4(INADDR_ANY, (port))
+
+static inline address_t ADDRESS6(struct in6_addr in_addr, int port) {
+ address_t address = {
+ .as_sin6 =
+ {
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(port),
+ .sin6_addr = in_addr,
+ },
+ };
+
+ return address;
+}
+
+#define ADDRESS6_LOCALHOST(port) ADDRESS6(in6addr_loopback, (port))
+#define ADDRESS6_ANY(port) ADDRESS6((struct in6_addr)IN6ADDR_ANY_INIT, port)
+
+#define ADDRESS_ANY(family, port) \
+ ((family == AF_INET) ? ADDRESS4_ANY(port) : ADDRESS6_ANY(port))
+
+extern const char *_address_family_str[];
+
+#define address_family_str(address) \
+ (_address_family_str[address_family(address)])
+
+#define address4_empty(address) (address4_ip(address).s_addr == 0)
+#define address6_empty(address) \
+ (memcmp(address6_ip(address).s6_addr, &in6addr_any, \
+ sizeof(struct in6_addr)) == 0)
+#define address_empty(address) \
+ (address_family(address) == AF_INET ? address4_empty(address) \
+ : address6_empty(address))
+
+/**
+ * @brief Return the string representation and the port of the IP address
+ * provided.
+ *
+ * @param[in] address Address to obtain the string representation from.
+ * @param[in, out] buffer String to store the string representation of the
+ * address. It contains "N/A" in case of failure (see return value).
+ * @param[in, out] port Integer to store the the port. It contains -1 in case of
+ * failure (see return value). If NULL, it will not be used to store the port.
+ * @return int 0 if success, failure otherwise.
+ */
+
+int address_to_string(const address_t *address, char *buffer, int *port);
+
+#endif /* HICNLIGHT_ADDRESS_H */
diff --git a/hicn-light/src/hicn/core/address_pair.c b/hicn-light/src/hicn/core/address_pair.c
new file mode 100644
index 000000000..facbb8dc4
--- /dev/null
+++ b/hicn-light/src/hicn/core/address_pair.c
@@ -0,0 +1,41 @@
+/*
+ * 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 address_pair.c
+ * \brief Implementation of Address pair
+ */
+
+#include "address_pair.h"
+
+address_pair_t address_pair_factory(address_t local, address_t remote) {
+ address_pair_t pair;
+ memset(&pair, 0, sizeof(address_pair_t));
+
+ pair.local = local;
+ pair.remote = remote;
+ return pair;
+}
+
+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) {
+ memset(pair, 0, sizeof(*pair));
+ if (address_from_ip_port(&pair->local, family, local_addr, local_port) < 0)
+ return -1;
+ if (address_from_ip_port(&pair->remote, family, remote_addr, remote_port) < 0)
+ return -1;
+ return 0;
+}
diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h
new file mode 100644
index 000000000..72b92d6b5
--- /dev/null
+++ b/hicn-light/src/hicn/core/address_pair.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file address_pair.h
+ * \brief Address pair
+ */
+
+#ifndef HICNLIGHT_ADDRESS_PAIR_H
+#define HICNLIGHT_ADDRESS_PAIR_H
+
+#include <hicn/util/ip_address.h>
+
+#include "address.h"
+
+typedef struct {
+ address_t local;
+ address_t remote;
+} address_pair_t;
+
+/**
+ * @brief Create an address pair starting from local and remote addresses.
+ *
+ * @param local The local address to use in the pair
+ * @param remote The remote address to use in the pair
+ * @return address_pair_t The address pair created
+ */
+address_pair_t address_pair_factory(address_t local, address_t remote);
+
+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);
+
+#define address_pair_get_local(pair) (&(pair)->local)
+#define address_pair_get_remote(pair) (&(pair)->remote)
+
+#define address_pair_get_local_family(pair) \
+ (address_family(address_pair_get_local(pair)))
+#define address_pair_get_remote_family(pair) \
+ (address_family(address_pair_get_remote(pair)))
+#define address_pair_get_family(pair) address_pair_get_local_family(pair)
+
+#define address_pair_is_valid(pair) \
+ (address_pair_get_local_family(pair) == address_pair_get_remote_family(pair))
+
+#endif /* HICNLIGHT_ADDRESS_PAIR_H */
diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c
index c2ac71a5f..c8cc1d0b9 100644
--- a/hicn-light/src/hicn/core/connection.c
+++ b/hicn-light/src/hicn/core/connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,347 +13,294 @@
* limitations under the License.
*/
-#include <limits.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
+/**
+ * @file connection.c
+ * @brief Implementation of hICN connections
+ */
-#include <hicn/core/connection.h>
-#include <hicn/core/connectionState.h>
-#include <hicn/core/messageHandler.h>
-#include <hicn/core/ticks.h>
-#include <hicn/core/wldr.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
+#include <assert.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#ifdef WITH_POLICY
-#include <hicn/policy.h>
-#endif /* WITH_POLICY */
+#include <hicn/core/forwarder.h>
+#include <hicn/core/listener.h>
+#include <hicn/util/log.h>
+#include <hicn/core/wldr.h>
-struct connection {
+#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,
+ forwarder_t *forwarder) {
+ assert(face_type_is_valid(type));
+ assert(pair);
+ assert(forwarder);
+
+ face_type_t listener_type;
+ switch (type) {
+ case FACE_TYPE_UDP:
+ listener_type = FACE_TYPE_UDP_LISTENER;
+ break;
+ case FACE_TYPE_TCP:
+ listener_type = FACE_TYPE_TCP_LISTENER;
+ break;
+ default:
+ return NULL;
+ }
- const AddressPair *addressPair;
- IoOperations *ops;
+ listener_table_t *ltable = forwarder_get_listener_table(forwarder);
+ listener_key_t key = listener_key_factory(pair->local, listener_type);
- unsigned refCount;
+ listener_t *listener = listener_table_get_by_key(ltable, &key);
+ if (!listener) {
+ WITH_ERROR({
+ char addr_str[NI_MAXHOST];
+ int port;
+ address_to_string(&pair->local, addr_str, &port);
+ ERROR("Could not find listener to match address %s:%d", addr_str, port);
+ })
- unsigned counter;
+ return NULL;
+ }
- bool wldrAutoStart; // if true, wldr can be set automatically
- // by default this value is set to true.
- // if wldr is activated using a command (config
- // file/hicnLightControl) this value is set to false so
- // that a base station can not disable wldr at the client
- Wldr *wldr;
+ connection_table_t *table =
+ forwarder_get_connection_table(listener->forwarder);
+ unsigned connection_id = listener_create_connection(listener, name, pair);
+ if (!connection_id_is_valid(connection_id)) return NULL;
+ return connection_table_at(table, connection_id);
+}
+/**
+ * @brief Initializes a connection
+ *
+ * @param [out] connection - Allocated connection buffer (eg. from pool) to be
+ * initialized.
+ * @param [in] forwarder - forwarder_t to which the connection is associated.
+ * This parameter needs to be non-NULL for connections receiving packets, such
+ * as TCP connections which are very close to UDP listeners, and unlike
+ * bound UDP connections).
+ * @param [in] fd - A fd specific to the connection, or 0 if the connection
+ * should inherit the fd of the listener.
+ * @return 0 if no error, -1 otherwise
+ */
+int connection_initialize(connection_t *connection, face_type_t type,
+ const char *name, const char *interface_name, int fd,
+ const address_pair_t *pair, bool local,
+ unsigned connection_id, listener_t *listener) {
+ int rc;
+
+ assert(connection);
+ /* Interface name can be NULL eg always for TCP connnections */
+ assert(pair);
+ // assert(address_pair_is_valid(pair)); TODO: local addr in the pair is not
+ // initialized for now
+
+ if (fd == 0) WARN("Connection is not connected");
+
+ *connection = (connection_t){
+ .id = connection_id,
+ .name = strdup(name),
+ .type = type,
+ .interface_name = strdup(interface_name),
+ .pair = *pair,
+ .fd = ((fd != 0) ? fd : listener_get_fd(listener)),
+ .connected = (fd != 0),
+ // .up = true,
+ .local = local,
+ // XXX UDP should start UP, TCP DOWN until remove side answer ?
+ .state = FACE_STATE_UNDEFINED,
+ .admin_state = FACE_STATE_UP,
#ifdef WITH_POLICY
- policy_tags_t tags;
+ .priority = 0,
#endif /* WITH_POLICY */
-};
+ .listener = listener,
+ .closed = false,
-Connection *connection_Create(IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- Connection *conn = parcMemory_AllocateAndClear(sizeof(Connection));
- parcAssertNotNull(conn, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Connection));
- conn->addressPair = ioOperations_GetAddressPair(ops);
- conn->ops = ops;
- conn->refCount = 1;
- conn->wldr = NULL;
+ /* WLDR */
+ .wldr = NULL,
+ .wldr_autostart = true,
+ };
- conn->wldrAutoStart = true;
- conn->counter = 0;
+ connection->data =
+ malloc(connection_vft[get_protocol(connection->type)]->data_size);
+ if (!connection->data) goto ERR_DATA;
- /* By default, a connection will aim at the UP state */
- connection_SetAdminState(conn, CONNECTION_STATE_UP);
+ assert(connection_has_valid_id(connection));
-#ifdef WITH_POLICY
- conn->tags = POLICY_TAGS_EMPTY;
-#endif /* WITH_POLICY */
-
- return conn;
-}
-
-Connection *connection_Acquire(Connection *connection) {
- parcAssertNotNull(connection, "Parameter conn must be non-null");
- connection->refCount++;
- return connection;
-}
-
-void connection_Release(Connection **connectionPtr) {
- parcAssertNotNull(connectionPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*connectionPtr,
- "Parameter must dereference to non-null pointer");
- Connection *conn = *connectionPtr;
-
- parcAssertTrue(
- conn->refCount > 0,
- "Invalid state, connection reference count should be positive, got 0.");
- conn->refCount--;
- if (conn->refCount == 0) {
- // don't destroy addressPair, its part of ops.
- ioOperations_Release(&conn->ops);
- if (conn->wldr != NULL) {
- wldr_Destroy(&(conn->wldr));
- }
- parcMemory_Deallocate((void **)&conn);
+ rc = connection_vft[get_protocol(connection->type)]->initialize(connection);
+ if (rc < 0) {
+ goto ERR_VFT;
}
- *connectionPtr = NULL;
-}
-
-bool connection_Send(const Connection *conn, Message *message) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- if (ioOperations_IsUp(conn->ops)) {
- if (message_GetType(message) == MessagePacketType_ContentObject) {
- uint8_t connectionId = (uint8_t)connection_GetConnectionId(conn);
- message_UpdatePathLabel(message, connectionId);
+ if (connection->connected) {
+ /*
+ * The file descriptor is created by the listener. We assume for now that
+ * all connections get their own fd, and we have to register it.
+ *
+ * TODO the connection has no more read callback, so we call the one from
+ * the listener.
+ */
+ loop_fd_event_create(&connection->event_data, MAIN_LOOP, fd, listener,
+ (fd_callback_t)listener_read_callback, NULL);
+
+ if (!connection->event_data) {
+ goto ERR_REGISTER_FD;
}
- if (conn->wldr != NULL) {
- wldr_SetLabel(conn->wldr, message);
- } else {
- message_ResetWldrLabel(message);
+
+ if (loop_fd_event_register(connection->event_data) < 0) {
+ goto ERR_REGISTER_FD;
}
- return ioOperations_Send(conn->ops, NULL, message);
}
- return false;
-}
-
-bool connection_SendIOVBuffer(const Connection *conn, struct iovec *msg,
- size_t size) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(msg, "Parameter message must be non-null");
-
- return ioOperations_SendIOVBuffer(conn->ops, msg, size);
-}
-
-bool connection_SendBuffer(const Connection *conn, u8 * buffer, size_t length)
-{
- struct iovec iov[1];
- iov[0].iov_base = buffer;
- iov[0].iov_len = length;
- return connection_SendIOVBuffer(conn, iov, 1);
-}
-void connection_Probe(Connection *conn, uint8_t * probe) {
- ioOperations_SendProbe(conn->ops, probe);
-}
-
-void connection_HandleProbe(Connection *conn, uint8_t *probe){
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(probe, "Parameter pkt must be non-null");
-
- if(messageHandler_IsInterest(probe)){
- messageHandler_CreateProbeReply(probe, HF_INET6_TCP);
- ioOperations_SendProbe(conn->ops, probe);
+ return 0;
+
+ERR_REGISTER_FD:
+#ifndef _WIN32
+ close(fd);
+#else
+ closesocket(fd);
+#endif
+ERR_VFT:
+ free(connection->data);
+ERR_DATA:
+ free(connection->interface_name);
+ free(connection->name);
+ return -1;
+}
+
+int connection_finalize(connection_t *connection) {
+ assert(connection);
+ assert(connection_has_valid_type(connection));
+
+ if (connection->connected) {
+ loop_event_unregister(connection->event_data);
+ loop_event_free(connection->event_data);
}
-}
-
-IoOperations *connection_GetIoOperations(const Connection *conn) {
- return conn->ops;
-}
-
-unsigned connection_GetConnectionId(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_GetConnectionId(conn->ops);
-}
-
-const AddressPair *connection_GetAddressPair(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_GetAddressPair(conn->ops);
-}
-
-bool connection_IsUp(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops) return false;
- return ioOperations_IsUp(conn->ops);
-}
-bool connection_IsLocal(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_IsLocal(conn->ops);
-}
+ if (connection->fd != 0) { // Only if connected socket
+#ifndef _WIN32
+ close(connection->fd);
+#else
+ closesocket(connection->fd);
+#endif
+ }
-const void *connection_Class(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_Class(conn->ops);
-}
+ if (connection->wldr) wldr_free(connection->wldr);
-bool connection_ReSend(const Connection *conn, Message *message,
- bool notification) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- bool res = false;
-
- if (connection_IsUp(conn)) {
- // here the wldr header is alreay set: this message is a retransmission or a
- // notification
-
- // we need to recompiute the path lable since we always store a pointer to
- // the same message if this message will be sent again to someonelse, the
- // new path label must be computed starting from the orignal labelorignal
- // label. Notice that we heve the same problem in case of PIT aggregation.
- // That case is handled insied the MessageProcessor. This is specific to
- // WLDR retransmittions. This is done only for data packets
-
- if (message_GetType(message) == MessagePacketType_ContentObject) {
- uint8_t connectionId = (uint8_t)connection_GetConnectionId(conn);
- uint32_t old_path_label = message_GetPathLabel(message);
- message_UpdatePathLabel(message, connectionId);
-
- res = ioOperations_Send(conn->ops, NULL, message);
-
- message_SetPathLabel(message, old_path_label);
- } else {
- res = ioOperations_Send(conn->ops, NULL, message);
- }
- }
+ connection_vft[get_protocol(connection->type)]->finalize(connection);
- if (notification) {
- // the notification is never destroyed
- message_Release(&message);
- }
+ if (connection->data) free(connection->data);
+ connection->data = NULL;
+ if (connection->interface_name) free(connection->interface_name);
+ connection->interface_name = NULL;
+ if (connection->name) free(connection->name);
+ connection->name = NULL;
- return res;
+ return 0;
}
-void connection_AllowWldrAutoStart(Connection *conn, bool allow) {
- conn->wldrAutoStart = allow;
-}
+int connection_send_packet(const connection_t *connection,
+ const uint8_t *packet, size_t size) {
+ assert(connection);
+ assert(face_type_is_valid(connection->type));
+ assert(packet);
-void connection_EnableWldr(Connection *conn) {
- if (!connection_IsLocal(conn)) {
- if (conn->wldr == NULL) {
- printf("----------------- enable wldr\n");
- conn->wldr = wldr_Init();
- }
- }
+ return connection_vft[get_protocol(connection->type)]->send_packet(
+ connection, packet, size);
}
-void connection_DisableWldr(Connection *conn) {
- if (!connection_IsLocal(conn)) {
- if (conn->wldr != NULL) {
- printf("----------------- disable wldr\n");
- wldr_Destroy(&(conn->wldr));
- conn->wldr = NULL;
- }
- }
+bool _connection_send(const connection_t *connection, msgbuf_t *msgbuf,
+ bool queue) {
+ return connection_vft[get_protocol(connection->type)]->send(connection,
+ msgbuf, queue);
}
-bool connection_HasWldr(const Connection *conn) {
- if (conn->wldr == NULL) {
- return false;
- } else {
- return true;
- }
+bool connection_flush(const connection_t *connection) {
+ return connection_vft[get_protocol(connection->type)]->flush(connection);
}
-bool connection_WldrAutoStartAllowed(const Connection *conn) {
- return conn->wldrAutoStart;
-}
+bool connection_send(const connection_t *connection, off_t msgbuf_id,
+ bool queue) {
+ assert(connection);
+ assert(msgbuf_id_is_valid(msgbuf_id));
-void connection_DetectLosses(Connection *conn, Message *message) {
- if (conn->wldr != NULL) wldr_DetectLosses(conn->wldr, conn, message);
-}
+ // if (!connection_is_up(connection))
+ // return false;
-void connection_HandleWldrNotification(Connection *conn, Message *message) {
- if (conn->wldr != NULL)
- wldr_HandleWldrNotification(conn->wldr, conn, message);
-}
+ const listener_t *listener = connection_get_listener(connection);
+ const forwarder_t *forwarder = listener_get_forwarder(listener);
+ const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
-connection_state_t connection_GetState(const Connection *conn)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return CONNECTION_STATE_UNDEFINED;
- return ioOperations_GetState(conn->ops);
-}
+ if (connection->wldr)
+ wldr_set_label(connection->wldr, msgbuf);
+ else
+ msgbuf_reset_wldr_label(msgbuf);
-void connection_SetState(Connection *conn, connection_state_t state)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return;
- ioOperations_SetState(conn->ops, state);
+ return _connection_send(connection, msgbuf, queue);
}
-connection_state_t connection_GetAdminState(const Connection *conn)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return CONNECTION_STATE_UNDEFINED;
- return ioOperations_GetAdminState(conn->ops);
-}
+/*
+ * here the wldr header is alreay set: this message is a retransmission or a
+ * notification
+ *
+ * we need to recompute the path label since we always store a pointer to
+ * the same message if this message will be sent again to someone else, the
+ * new path label must be computed starting from the orignal label. Note
+ * that we heve the same problem in case of PIT aggregation. That case is
+ * 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 notification) {
+ assert(connection);
+ assert(msgbuf);
-void connection_SetAdminState(Connection *conn, connection_state_t admin_state)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return;
- if ((admin_state != CONNECTION_STATE_UP) && (admin_state != CONNECTION_STATE_DOWN))
- return;
- ioOperations_SetAdminState(conn->ops, admin_state);
-}
+ bool ret = false;
-#ifdef WITH_POLICY
-uint32_t connection_GetPriority(const Connection *conn)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return 0;
- return ioOperations_GetPriority(conn->ops);
-}
+ if (!connection_is_up(connection)) return ret;
-void connection_SetPriority(Connection *conn, uint32_t priority)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return;
- ioOperations_SetPriority(conn->ops, priority);
-}
-#endif /* WITH_POLICY */
+ ret = _connection_send(connection, msgbuf, false); /* no queueing */
-const char * connection_GetInterfaceName(const Connection * conn)
-{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return NULL;
- return ioOperations_GetInterfaceName(conn->ops);
+ return ret;
}
-#ifdef WITH_POLICY
+/* WLDR */
-void connection_AddTag(Connection *conn, policy_tag_t tag)
-{
- policy_tags_add(&conn->tags, tag);
+void connection_wldr_allow_autostart(connection_t *connection, bool value) {
+ connection->wldr_autostart = value;
}
-void connection_RemoveTag(Connection *conn, policy_tag_t tag)
-{
- policy_tags_remove(&conn->tags, tag);
+bool connection_wldr_autostart_is_allowed(const connection_t *connection) {
+ return connection->wldr_autostart;
}
-policy_tags_t connection_GetTags(const Connection *conn)
-{
- return conn->tags;
+void connection_wldr_enable(connection_t *connection, bool value) {
+ if (connection_is_local(connection)) return;
+ if (value) {
+ if (connection->wldr) return;
+ connection->wldr = wldr_create();
+ } else {
+ if (!connection->wldr) return;
+ wldr_free(connection->wldr);
+ }
}
-void connection_SetTags(Connection *conn, policy_tags_t tags)
-{
- conn->tags = tags;
+bool connection_has_wldr(const connection_t *connection) {
+ return !!connection->wldr;
}
-void connection_ClearTags(Connection *conn)
-{
- conn->tags = POLICY_TAGS_EMPTY;
+void connection_wldr_detect_losses(const connection_t *connection,
+ const msgbuf_t *msgbuf) {
+ if (!connection->wldr) return;
+ wldr_detect_losses(connection->wldr, connection, msgbuf);
}
-int connection_HasTag(const Connection *conn, policy_tag_t tag)
-{
- return policy_tags_has(conn->tags, tag);
+void connection_wldr_handle_notification(const connection_t *connection,
+ const msgbuf_t *msgbuf) {
+ if (!connection->wldr) return;
+ wldr_handle_notification(connection->wldr, connection, msgbuf);
}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h
index b6513ea1a..05dc1d6e2 100644
--- a/hicn-light/src/hicn/core/connection.h
+++ b/hicn-light/src/hicn/core/connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,19 +15,23 @@
/**
* @file connection.h
- * @brief Wrapper for different types of connections
- *
- * A connection wraps a specific set of {@link IoOperations}. Those operations
- * allow for input and output. Connections get stored in the Connection Table.
- *
+ * @brief hICN connections
*/
-#ifndef connection_h
-#define connection_h
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/connectionState.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/utils/address.h>
+#ifndef HICNLIGHT_CONNECTION_H
+#define HICNLIGHT_CONNECTION_H
+
+#include <hicn/face.h>
+
+#include "address_pair.h"
+#include "listener.h"
+#include "msgbuf.h"
+
+#ifdef WITH_POLICY
+#include <hicn/policy.h>
+#endif /* WITH_POLICY */
+
+#define CONNECTION_ID_UNDEFINED ~0
#ifdef WITH_MAPME
typedef enum {
@@ -42,157 +46,193 @@ typedef enum {
#endif /* WITH_MAPME */
+struct wldr_s;
+
+typedef struct {
+ unsigned id;
+ char* name;
+ char* interface_name;
+ face_type_t type;
+ address_pair_t pair;
+ // bool up;
+ bool local;
+ face_state_t state;
+ face_state_t admin_state;
#ifdef WITH_POLICY
-#include <hicn/policy.h>
+ policy_tags_t tags;
+ uint32_t priority;
#endif /* WITH_POLICY */
-struct connection;
-typedef struct connection Connection;
+ int fd;
+ bool connected; // true if the connection is connected and has its own fd
+ event_t* event_data;
+
+ void* data;
+
+ listener_t* listener;
+ // struct forwarder_s * forwarder; // recv only
+ bool closed;
+
+ /* WLDR */
+
+ bool wldr_autostart;
+ /*
+ * if true, wldr can be set automatically by default this value is set to
+ * true. if wldr is activated using a command (config file/hicnLightControl)
+ * this value is set to false so that a base station can not disable wldr at
+ * the client.
+ */
+ struct wldr_s* wldr;
+
+} connection_t;
+
+#if 1
+#define connection_get_id(C) ((C)->id)
+#define connection_id_is_valid(ID) (ID != CONNECTION_ID_UNDEFINED)
+#define connection_get_name(C) ((C)->name)
+#define connection_get_type(C) ((C)->type)
+#define connection_has_valid_id(C) \
+ (connection_id_is_valid(connection_get_id(C)))
+#define connection_has_valid_type(C) \
+ (face_type_is_valid(connection_get_type(C)))
+#define connection_get_pair(C) (&(C)->pair)
+#define connection_get_local(C) (address_pair_get_local(connection_get_pair(C)))
+#define connection_get_remote(C) \
+ (address_pair_get_remote(connection_get_pair(C)))
+#define connection_get_local(C) (address_pair_get_local(connection_get_pair(C)))
+#define connection_get_remote(C) \
+ (address_pair_get_remote(connection_get_pair(C)))
+#define connection_is_up(C) ((C)->state == FACE_STATE_UP)
+#define connection_is_closed(C) ((C)->closed == true)
+#define connection_is_local(C) ((C)->local)
+#define connection_get_state(C) ((C)->state)
+#define connection_set_state(C, STATE) (C)->state = STATE
+#define connection_get_admin_state(C) ((C)->admin_state)
+#define connection_set_admin_state(C, STATE) (C)->admin_state = STATE
+#define connection_get_interface_name(C) ((C)->interface_name)
-/**
- * Creates a connection object.
- */
-Connection *connection_Create(IoOperations *ops);
+#ifdef WITH_POLICY
+#define connection_get_priority(C) ((C)->priority)
+#define connection_set_priority(C, PRIORITY) (C)->priority = PRIORITY
+#define connection_get_tags(C) ((C)->tags)
+#define connection_set_tags(C, TAGS) (C)->tags = TAGS
+#define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG)
+#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG)
+#define connection_remove_tag(C, TAG) \
+ do { \
+ policy_tags_t _conn_var(tags); \
+ _conn_var(tags) = connection_get_tags(C); \
+ policy_tags_remove(_conn_var(tags), (TAG)); \
+ connection_set_tags((C), _conn_var(tags)); \
+ } while (0)
+#define connection_clear_tags(C) connection_set_tags(C, POLICY_TAGS_EMPTY)
-/**
- * @function connection_Release
- * @abstract Releases a reference count, destroying on last release
- * @discussion
- * Only frees the memory on the final reference count. The pointer will
- * always be NULL'd.
- */
-void connection_Release(Connection **connectionPtr);
+#endif /* WITH_POLICY */
-/**
- * @function connection_Acquire
- * @abstract A reference counted copy.
- * @discussion
- * A shallow copy, they share the same memory.
- */
-Connection *connection_Acquire(Connection *connection);
+#else
-/**
- * @function connection_Send
- * @abstract Sends the message on the connection
- * @return true if message sent, false if connection not up
- */
-bool connection_Send(const Connection *conn, Message *message);
+/* Accessors */
+static inline unsigned connection_get_id(const connection_t* connection);
-/**
- * @function connection_SendIOVBuffer
- * @abstract Sends an IOV buffer
- */
-bool connection_SendIOVBuffer(const Connection *conn, struct iovec *msg,
- size_t size);
+#define connection_id_is_valid(id) (id != CONNECTION_ID_UNDEFINED)
+#define connection_has_valid_id(C) (connection_id_is_valid(connection_get_id(C))
-/**
- * @function connection_SendBuffer
- * @abstract Sends a buffer
- */
-bool connection_SendBuffer(const Connection *conn, u8 * buffer, size_t length);
+static inline char* connection_get_name(const connection_t* connection);
-/**
- * Return the `IoOperations` instance associated with the specified `Connection`
- * instance.
- * @param [in] connection The allocated connection
- * @return a pointer to the IoOperations instance associated by th specified
- * connection.
- */
-IoOperations *connection_GetIoOperations(const Connection *conn);
+static inline face_type_t connection_get_type(const connection_t* connection);
-/**
- * Returns the unique identifier of the connection
- * Calls the underlying IoOperations to fetch the connection id
- * @param [in] connection The allocated connection
- * @return unsigned The unique connection id
- */
-unsigned connection_GetConnectionId(const Connection *conn);
+static inline address_pair_t* connection_get_pair(
+ const connection_t* connection);
-/**
- * Returns the (remote, local) address pair that describes the connection
- * @param [in] connection The allocated connection
- * @return non-null The connection's remote and local address
- * @return null Should never return NULL
- */
-const AddressPair *connection_GetAddressPair(const Connection *conn);
+#define connection_get_local(C) (address_pair_get_local(connection_get_pair(C)))
+#define connection_get_remote(C) (address_pair_remote(connection_get_pair(C)))
-/**
- * Checks if the connection is in the "up" state
- * @param [in] connection The allocated connection
- * @return true The connection is in the "up" state
- * @return false The connection is not in the "up" state
- */
-bool connection_IsUp(const Connection *conn);
+static inline bool connection_is_up(const connection_t* connection);
-/**
- * Checks if the connection is to a Local/Loopback address
- *
- * A local connection is PF_LOCAL (PF_UNIX) and a loopback connection is
- * 127.0.0.0/8 or ::1 for IPv6.
- *
- * @param [in] connection The allocated connection
- *
- * @retval true The connection is local or loopback
- * @retval false The connection is not local or loopback
- */
-bool connection_IsLocal(const Connection *conn);
+static inline bool connection_is_local(const connection_t* connection);
-/**
- * Returns an opaque pointer representing the class of the Io Operations
- *
- * Returns an opaque pointer that an implementation can use to detect if
- * the connection is based on that class.
- *
- * @param [in] conn The Connection to analyze
- *
- * @return non-null An opaque pointer for each concrete implementation
- */
-const void *connection_Class(const Connection *conn);
+static inline face_state_t connection_get_state(const connection_t* connection);
-bool connection_ReSend(const Connection *conn, Message *message,
- bool notification);
+static inline void connection_set_state(connection_t* connection,
+ face_state_t state);
-void connection_Probe(Connection *conn, uint8_t *probe);
+static inline face_state_t connection_get_admin_state(
+ const connection_t* connection);
-void connection_HandleProbe(Connection *conn, uint8_t *message);
+static inline void connection_set_admin_state(connection_t* connection,
+ face_state_t state);
-void connection_AllowWldrAutoStart(Connection *conn, bool allow);
+static inline const char* connection_get_interface_name(
+ const connection_t* connection);
-void connection_EnableWldr(Connection *conn);
+#ifdef WITH_POLICY
-void connection_DisableWldr(Connection *conn);
+static inline uint32_t connection_get_priority(const connection_t* connection);
-bool connection_HasWldr(const Connection *conn);
+static inline void connection_set_priority(connection_t* connection,
+ uint32_t priority);
-bool connection_WldrAutoStartAllowed(const Connection *conn);
+static inline policy_tags_t connection_get_tags(const connection_t* connection);
-void connection_DetectLosses(Connection *conn, Message *message);
+static inline void connection_set_tags(connection_t* connection,
+ policy_tags_t tags);
-void connection_HandleWldrNotification(Connection *conn, Message *message);
+#define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG)
-connection_state_t connection_GetState(const Connection *conn);
+#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG)
-void connection_SetState(Connection *conn, connection_state_t state);
+#define connection_remove_tag(C, TAG) \
+ do { \
+ policy_tags_t _conn_var(tags); \
+ _conn_var(tags) = connection_get_tags(C); \
+ policy_tags_remove(_conn_var(tags), (TAG)); \
+ connection_set_tags((C), _conn_var(tags)); \
+ } while (0)
-connection_state_t connection_GetAdminState(const Connection *conn);
+#define connection_clear_tags(C) connection_set_tags(C, POLICY_TAGS_EMPTY)
-void connection_SetAdminState(Connection *conn, connection_state_t admin_state);
+#endif /* WITH_POLICY */
-#ifdef WITH_POLICY
-uint32_t connection_GetPriority(const Connection *conn);
+#endif
-void connection_SetPriority(Connection *conn, uint32_t priority);
-#endif /* WITH_POLICY */
+connection_t* connection_create(face_type_t type, const char* name,
+ const address_pair_t* pair,
+ struct forwarder_s* forwarder);
-const char * connection_GetInterfaceName(const Connection * conn);
+int connection_initialize(connection_t* connection, face_type_t type,
+ const char* name, const char* interface_name, int fd,
+ const address_pair_t* pair, bool local,
+ unsigned connection_id, listener_t* listener);
-#ifdef WITH_POLICY
-void connection_AddTag(Connection *conn, policy_tag_t tag);
-void connection_RemoveTag(Connection *conn, policy_tag_t tag);
-policy_tags_t connection_GetTags(const Connection *conn);
-void connection_SetTags(Connection *conn, policy_tags_t tags);
-void connection_ClearTags(Connection *conn);
-int connection_HasTag(const Connection *conn, policy_tag_t tag);
-#endif /* WITH_POLICY */
+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_send(const connection_t* connection, off_t msgbuf_id,
+ bool queue);
+
+size_t connection_process_buffer(connection_t* connection,
+ const uint8_t* buffer, size_t size);
+
+/* WLDR */
+
+void connection_wldr_allow_autostart(connection_t* connection, bool value);
+
+bool connection_wldr_autostart_is_allowed(const connection_t* connection);
+
+void connection_wldr_enable(connection_t* connection, bool value);
+
+bool connection_has_wldr(const connection_t* connection);
+
+void connection_wldr_detect_losses(const connection_t* connection,
+ const msgbuf_t* msgbuf);
+
+void connection_wldr_handle_notification(const connection_t* connection,
+ const msgbuf_t* msgbuf);
+
+#define connection_get_listener(connection) (connection->listener)
-#endif // connection_h
+#endif /* HICNLIGHT_CONNECTION_H */
diff --git a/hicn-light/src/hicn/core/connectionList.c b/hicn-light/src/hicn/core/connectionList.c
deleted file mode 100644
index d51a9aad5..000000000
--- a/hicn-light/src/hicn/core/connectionList.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/connectionList.h>
-
-struct connection_list {
- PARCArrayList *listOfConnections;
-};
-
-static void connectionList_ArrayDestroyer(void **voidPtr) {
- Connection **entryPtr = (Connection **)voidPtr;
- connection_Release(entryPtr);
-}
-
-ConnectionList *connectionList_Create() {
- ConnectionList *list = parcMemory_AllocateAndClear(sizeof(ConnectionList));
- parcAssertNotNull(list, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ConnectionList));
- list->listOfConnections = parcArrayList_Create(connectionList_ArrayDestroyer);
- return list;
-}
-
-void connectionList_Destroy(ConnectionList **listPtr) {
- parcAssertNotNull(listPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listPtr, "Parameter must dereference to non-null pointer");
- ConnectionList *list = *listPtr;
- parcArrayList_Destroy(&list->listOfConnections);
- parcMemory_Deallocate((void **)&list);
- *listPtr = NULL;
-}
-
-void connectionList_Append(ConnectionList *list, Connection *entry) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- parcAssertNotNull(entry, "Parameter entry must be non-null");
-
- parcArrayList_Add(list->listOfConnections, connection_Acquire(entry));
-}
-
-size_t connectionList_Length(const ConnectionList *list) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- return parcArrayList_Size(list->listOfConnections);
-}
-
-Connection *connectionList_Get(ConnectionList *list, size_t index) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- Connection *original =
- (Connection *)parcArrayList_Get(list->listOfConnections, index);
- return original;
-}
diff --git a/hicn-light/src/hicn/core/connectionList.h b/hicn-light/src/hicn/core/connectionList.h
deleted file mode 100644
index fbba9f6d8..000000000
--- a/hicn-light/src/hicn/core/connectionList.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file connectionList.h
- * @brief A typesafe list of Connection objects
- *
- * <#Detailed Description#>
- *
- */
-
-#ifndef connectionList_h
-#define connectionList_h
-
-struct connection_list;
-typedef struct connection_list ConnectionList;
-
-#include <hicn/core/connection.h>
-
-/**
- * Creates a lis of Connection
- *
- * @return non-null An allocated list
- * @return null An error
- */
-ConnectionList *connectionList_Create(void);
-
-/**
- * Destroys the list and all objects inside it
- */
-void connectionList_Destroy(ConnectionList **listPtr);
-
-/**
- * @function connectionList_Append
- * @abstract Adds a connection entry to the list.
- * @discussion
- * Acquires a reference to the passed entry and stores it in the list.
- */
-void connectionList_Append(ConnectionList *list, Connection *entry);
-
-/**
- * Returns the number of items on the list
- * @param [in] list The allocated list to check
- * @return number The number of items on the list
- */
-size_t connectionList_Length(const ConnectionList *list);
-
-/**
- * @function connectionList_Get
- * @abstract Returns the connection entry.
- * @discussion
- * Caller must not destroy the returned value. If you will store the
- * entry in your own data structure, you should acquire your own reference.
- * Will assert if you go beyond the end of the list.
- *
- */
-Connection *connectionList_Get(ConnectionList *list, size_t index);
-#endif // connectionList_h
diff --git a/hicn-light/src/hicn/core/connectionManager.c b/hicn-light/src/hicn/core/connectionManager.c
deleted file mode 100644
index 709f0902a..000000000
--- a/hicn-light/src/hicn/core/connectionManager.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * The Connection Manager sets itself up as a listener to the Messenger so it
- * can take action based on system events.
- *
- * The Connection Manager queues and then processes in a later time slice the
- * messages.
- *
- */
-
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/connectionManager.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/messenger/messenger.h>
-#include <hicn/messenger/messengerRecipient.h>
-#include <hicn/messenger/missiveDeque.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct connection_manager {
- Forwarder *forwarder;
- Logger *logger;
-
- MessengerRecipient *messengerRecipient;
-
- // we queue missives as they come in to process in our own
- // event timeslice
- MissiveDeque *missiveQueue;
-
- // for deferred queue processing
- PARCEventTimer *timerEvent;
-};
-
-/**
- * Receives missives from the messenger, queues them, and schedules our
- * execution
- *
- * We defer processing of missives to a later time slice
- */
-static void connectionManager_MessengerCallback(MessengerRecipient *recipient,
- Missive *missive);
-
-/**
- * Event callback
- *
- * This is our main run loop to process our queue of messages. It is scheduled
- * in {@link connectionManager_MessengerCallback} when the queue becomes
- * non-empty.
- *
- * When we are called here, we have exclusive use of the system, so we will not
- * create any message loops
- *
- * @param [in] fd unused, required for compliance with function prototype
- * @param [in] which_event unused, required for compliance with function
- * prototype
- * @param [in] connManagerVoidPtr A void* to ConnectionManager
- *
- */
-static void connectionManager_ProcessQueue(int fd, PARCEventType which_event,
- void *connManagerVoidPtr);
-
-static void connectionManager_ProcessClosedMissive(
- ConnectionManager *connManager, const Missive *missive);
-
-// ========================================================
-// Public API
-
-ConnectionManager *connectionManager_Create(Forwarder *forwarder) {
- ConnectionManager *connManager =
- parcMemory_AllocateAndClear(sizeof(ConnectionManager));
- parcAssertNotNull(connManager,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ConnectionManager));
- connManager->forwarder = forwarder;
- connManager->missiveQueue = missiveDeque_Create();
- connManager->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- Messenger *messenger = forwarder_GetMessenger(connManager->forwarder);
-
- // creates the timer, but does not start it
- PARCEventScheduler *base =
- dispatcher_GetEventScheduler(forwarder_GetDispatcher(forwarder));
- connManager->timerEvent = parcEventTimer_Create(
- base, 0, connectionManager_ProcessQueue, connManager);
-
- connManager->messengerRecipient = messengerRecipient_Create(
- connManager, connectionManager_MessengerCallback);
- messenger_Register(messenger, connManager->messengerRecipient);
- return connManager;
-}
-
-void connectionManager_Destroy(ConnectionManager **managerPtr) {
- parcAssertNotNull(managerPtr, "Double pointer must be non-null");
- parcAssertNotNull(*managerPtr, "Double pointer must dereference to non-null");
-
- ConnectionManager *connManager = *managerPtr;
-
- Messenger *messenger = forwarder_GetMessenger(connManager->forwarder);
- parcEventTimer_Destroy(&(connManager->timerEvent));
- messenger_Unregister(messenger, connManager->messengerRecipient);
- messengerRecipient_Destroy(&connManager->messengerRecipient);
- missiveDeque_Release(&connManager->missiveQueue);
- logger_Release(&connManager->logger);
-
- parcMemory_Deallocate((void **)&connManager);
- *managerPtr = NULL;
-}
-
-// ========================================================
-// Internal Functions
-
-static void connectionManager_MessengerCallback(MessengerRecipient *recipient,
- Missive *missive) {
- ConnectionManager *connManager =
- messengerRecipient_GetRecipientContext(recipient);
-
- // we do not release our reference count, we store it until later
- // We are called with our own reference, so we do not need to acquire the
- // missive here.
- missiveDeque_Append(connManager->missiveQueue, missive);
-
- if (missiveDeque_Size(connManager->missiveQueue) == 1) {
- // When it becomes non-empty, schedule {@link
- // connectionManager_ProcessQueue}
- struct timeval immediateTimeout = {0, 0};
- parcEventTimer_Start(connManager->timerEvent, &immediateTimeout);
- }
-}
-
-static void connectionManager_ProcessQueue(int fd, PARCEventType which_event,
- void *connManagerVoidPtr) {
- ConnectionManager *connManager = (ConnectionManager *)connManagerVoidPtr;
-
- Missive *missive;
- while ((missive = missiveDeque_RemoveFirst(connManager->missiveQueue)) !=
- NULL) {
- switch (missive_GetType(missive)) {
- case MissiveType_ConnectionCreate:
- // hook to signal that a new connection was created
- break;
- case MissiveType_ConnectionUp:
- // hook to signal that a new connection is up
- break;
- case MissiveType_ConnectionDown:
- // hook to signal that a connection is down
- break;
- case MissiveType_ConnectionClosed:
- connectionManager_ProcessClosedMissive(connManager, missive);
- break;
- case MissiveType_ConnectionDestroyed:
- // hook to signal that a connection was destroyed
- break;
- default:
- parcTrapUnexpectedState("Missive %p of unknown type: %d",
- (void *)missive, missive_GetType(missive));
- }
- missive_Release(&missive);
- }
-}
-
-static void connectionManager_ProcessClosedMissive(
- ConnectionManager *connManager, const Missive *missive) {
- logger_Log(connManager->logger, LoggerFacility_Core, PARCLogLevel_Debug,
- __func__, "Processing CLOSED message for connid %u",
- missive_GetConnectionId(missive));
-
- ConnectionTable *table = forwarder_GetConnectionTable(connManager->forwarder);
- const Connection *conn =
- connectionTable_FindById(table, missive_GetConnectionId(missive));
-
- if (conn) {
- // this will destroy the connection if its the last reference count
- connectionTable_Remove(table, conn);
-
- // remove from FIB
- forwarder_RemoveConnectionIdFromRoutes(connManager->forwarder,
- missive_GetConnectionId(missive));
- }
-}
diff --git a/hicn-light/src/hicn/core/connectionManager.h b/hicn-light/src/hicn/core/connectionManager.h
deleted file mode 100644
index 34fee8717..000000000
--- a/hicn-light/src/hicn/core/connectionManager.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file connectionManager.h
- * @brief The connection manager handles connection events, such as going down
- *
- * The connection manager listens to the event notification system. Based on
- * those events, the connection manager will take specific actions. This is
- * expected to be a singleton instantiated by the forwarder.
- *
- */
-
-#ifndef connectionManager_h
-#define connectionManager_h
-
-#include <hicn/core/forwarder.h>
-
-struct connection_manager;
-typedef struct connection_manager ConnectionManager;
-
-ConnectionManager *connectionManager_Create(Forwarder *forwarder);
-
-void connectionManager_Destroy(ConnectionManager **managerPtr);
-#endif // connectionManager_h
diff --git a/hicn-light/src/hicn/core/connectionTable.c b/hicn-light/src/hicn/core/connectionTable.c
deleted file mode 100644
index f8589c12b..000000000
--- a/hicn-light/src/hicn/core/connectionTable.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header ConnectionTable
- * @abstract Records all the current connections and references to them
- * @discussion
- *
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_TreeRedBlack.h>
-#include <hicn/core/connectionTable.h>
-#include <hicn/io/addressPair.h>
-
-struct connection_table {
- // The main storage table that has a Destroy method.
- // The key is an unsigned int pointer. We use an unsigned int pointer
- // because we want to be able to lookup by the id alone, and not have to
- // have the IoOperations everywhere.
- PARCHashCodeTable *storageTableById;
-
- // The key is a AddressPair
- // It does not have a destroy method for the data or key,
- // as they are derived from the storage table.
- PARCHashCodeTable *indexByAddressPair;
-
- // An iterable stucture organized by connection id. The keys and
- // values are the same pointers as in storageTableById, so there
- // are no destructors in the tree.
- // The only reason to keep this tree is so we have an iterable list
- // of connections, which the hash table does not give us.
- PARCTreeRedBlack *listById;
-};
-
-static bool connectionTable_ConnectionIdEquals(const void *keyA,
- const void *keyB) {
- unsigned idA = *((unsigned *)keyA);
- unsigned idB = *((unsigned *)keyB);
- return (idA == idB);
-}
-
-static int connectionTable_ConnectionIdCompare(const void *keyA,
- const void *keyB) {
- unsigned idA = *((unsigned *)keyA);
- unsigned idB = *((unsigned *)keyB);
- if (idA < idB) {
- return -1;
- }
- if (idA > idB) {
- return +1;
- }
- return 0;
-}
-
-static bool connectionTable_AddressPairEquals(const void *keyA,
- const void *keyB) {
- const AddressPair *pairA = (const AddressPair *)keyA;
- const AddressPair *pairB = (const AddressPair *)keyB;
-
- return addressPair_Equals(pairA, pairB);
-}
-
-static HashCodeType connectionTable_ConnectionIdHashCode(const void *keyA) {
- unsigned idA = *((unsigned *)keyA);
- return parcHash32_Int32(idA);
-}
-
-static HashCodeType connectionTable_AddressPairHashCode(const void *keyA) {
- const AddressPair *pairA = (const AddressPair *)keyA;
- return addressPair_HashCode(pairA);
-}
-
-static void connectionTable_ConnectionIdDestroyer(void **dataPtr) {
- unsigned *idA = (unsigned *)*dataPtr;
- parcMemory_Deallocate((void **)&idA);
- *dataPtr = NULL;
-}
-
-static void connectionTable_ConnectionDestroyer(void **dataPtr) {
- connection_Release((Connection **)dataPtr);
-}
-
-ConnectionTable *connectionTable_Create() {
- size_t initialSize = 16384;
-
- ConnectionTable *conntable =
- parcMemory_AllocateAndClear(sizeof(ConnectionTable));
- parcAssertNotNull(conntable, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ConnectionTable));
-
- conntable->storageTableById = parcHashCodeTable_Create_Size(
- connectionTable_ConnectionIdEquals, connectionTable_ConnectionIdHashCode,
- connectionTable_ConnectionIdDestroyer,
- connectionTable_ConnectionDestroyer, initialSize);
-
- // no key or data destroyer, this is an index into storageByid.
- conntable->indexByAddressPair = parcHashCodeTable_Create_Size(
- connectionTable_AddressPairEquals, connectionTable_AddressPairHashCode,
- NULL, NULL, initialSize);
-
- conntable->listById =
- parcTreeRedBlack_Create(connectionTable_ConnectionIdCompare,
- NULL, // key free
- NULL, // key copy
- NULL, // value equals
- NULL, // value free
- NULL); // value copy
-
- return conntable;
-}
-
-void connectionTable_Destroy(ConnectionTable **conntablePtr) {
- parcAssertNotNull(conntablePtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*conntablePtr,
- "Parameter must dereference to non-null pointer");
-
- ConnectionTable *conntable = *conntablePtr;
-
- parcTreeRedBlack_Destroy(&conntable->listById);
- parcHashCodeTable_Destroy(&conntable->indexByAddressPair);
- parcHashCodeTable_Destroy(&conntable->storageTableById);
- parcMemory_Deallocate((void **)&conntable);
- *conntablePtr = NULL;
-}
-
-/**
- * @function connectionTable_Add
- * @abstract Add a connection, takes ownership of memory
- */
-void connectionTable_Add(ConnectionTable *table, Connection *connection) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(connection, "Parameter connection must be non-null");
-
- unsigned *connectionIdKey = parcMemory_Allocate(sizeof(unsigned));
- parcAssertNotNull(connectionIdKey, "parcMemory_Allocate(%zu) returned NULL",
- sizeof(unsigned));
- *connectionIdKey = connection_GetConnectionId(connection);
-
- if (parcHashCodeTable_Add(table->storageTableById, connectionIdKey,
- connection)) {
- parcHashCodeTable_Add(table->indexByAddressPair,
- (void *)connection_GetAddressPair(connection),
- connection);
- parcTreeRedBlack_Insert(table->listById, connectionIdKey, connection);
- } else {
- parcTrapUnexpectedState(
- "Could not add connection id %u -- is it a duplicate?",
- *connectionIdKey);
- }
-}
-
-/**
- * @function connectionTable_Remove
- * @abstract Removes the connection, calling Destroy on our copy
- */
-void connectionTable_Remove(ConnectionTable *table,
- const Connection *connection) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(connection, "Parameter connection must be non-null");
-
- unsigned connid = connection_GetConnectionId(connection);
-
- parcTreeRedBlack_Remove(table->listById, &connid);
- parcHashCodeTable_Del(table->indexByAddressPair,
- connection_GetAddressPair(connection));
- parcHashCodeTable_Del(table->storageTableById, &connid);
-}
-
-void connectionTable_RemoveById(ConnectionTable *table, unsigned id) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- const Connection *connection = connectionTable_FindById(table, id);
- if (connection) {
- connectionTable_Remove(table, connection);
- }
-}
-
-const Connection *connectionTable_FindByAddressPair(ConnectionTable *table,
- const AddressPair *pair) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- return (Connection *)parcHashCodeTable_Get(table->indexByAddressPair, pair);
-}
-
-const Connection *connectionTable_FindById(const ConnectionTable *table,
- unsigned id) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- return (Connection *)parcHashCodeTable_Get(table->storageTableById, &id);
-}
-
-ConnectionList *connectionTable_GetEntries(const ConnectionTable *table) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- ConnectionList *list = connectionList_Create();
-
- PARCArrayList *values = parcTreeRedBlack_Values(table->listById);
- for (size_t i = 0; i < parcArrayList_Size(values); i++) {
- Connection *original = parcArrayList_Get(values, i);
- connectionList_Append(list, original);
- }
- parcArrayList_Destroy(&values);
- return list;
-}
diff --git a/hicn-light/src/hicn/core/connectionTable.h b/hicn-light/src/hicn/core/connectionTable.h
deleted file mode 100644
index 548ef8e6e..000000000
--- a/hicn-light/src/hicn/core/connectionTable.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- */
-
-#ifndef connectionTable_h
-#define connectionTable_h
-
-#include <hicn/core/connection.h>
-#include <hicn/core/connectionList.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
-
-struct connection_table;
-typedef struct connection_table ConnectionTable;
-
-/**
- * Creates an empty connection table
- */
-ConnectionTable *connectionTable_Create(void);
-
-/**
- * Destroys the connection table
- * This will release the reference to all connections stored in the connection
- * table.
- * @param [in,out] conntablePtr Pointer to the allocated connection table, will
- * be NULL'd
- */
-void connectionTable_Destroy(ConnectionTable **conntablePtr);
-
-/**
- * @function connectionTable_Add
- * @abstract Add a connection, takes ownership of memory
- */
-void connectionTable_Add(ConnectionTable *table, Connection *connection);
-
-/**
- * @function connectionTable_Remove
- * @abstract Removes the connection, calling Destroy on our copy
- */
-void connectionTable_Remove(ConnectionTable *table,
- const Connection *connection);
-
-/**
- * Removes a connection from the connection table
- *
- * Looks up a connection by its connection ID and removes it from the connection
- * table. Removing the connection will call connection_Release() on the
- * connection object.
- *
- * @param [in] table The allocated connection table
- * @param [in] id The connection ID
- */
-void connectionTable_RemoveById(ConnectionTable *table, unsigned id);
-
-/**
- * Lookup a connection by the (local, remote) addres pair
- *
- * @param [in] table The allocated connection table
- * @param [in] pair The address pair to match, based on the inner values of the
- * local and remote addresses
- *
- * @retval non-null The matched conneciton
- * @retval null No match found or error
- */
-const Connection *connectionTable_FindByAddressPair(ConnectionTable *table,
- const AddressPair *pair);
-
-/**
- * @function connectionTable_FindById
- * @abstract Find a connection by its numeric id.
- * @return NULL if not found
- */
-const Connection *connectionTable_FindById(const ConnectionTable *table, unsigned id);
-
-/**
- * @function connectionTable_GetEntries
- * @abstract Returns a list of connections. They are reference counted copies
- * from the table.
- * @discussion
- * An allocated list of connections in the table. Each list entry is a
- * reference counted copy of the connection in the table, thus they are "live"
- * objects.
- */
-ConnectionList *connectionTable_GetEntries(const ConnectionTable *table);
-#endif // connectionTable_h
diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c
new file mode 100644
index 000000000..09236ae8e
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_table.c
@@ -0,0 +1,162 @@
+/*
+ * 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 connection_table.c
+ * \brief Implementation of hICN connection table
+ */
+
+#include <hicn/util/log.h>
+
+#include "connection.h"
+#include "connection_table.h"
+
+/* This is only used as a hint for first allocation, as the table is resizeable
+ */
+#define DEFAULT_CONNECTION_TABLE_SIZE 64
+
+connection_table_t *_connection_table_create(size_t init_size,
+ size_t max_size) {
+ if (init_size == 0) init_size = DEFAULT_CONNECTION_TABLE_SIZE;
+
+ connection_table_t *table = malloc(sizeof(connection_table_t));
+ if (!table) return NULL;
+
+ table->max_size = max_size;
+
+ /* Initialize indices */
+ table->id_by_pair = kh_init_ct_pair();
+ table->id_by_name = kh_init_ct_name();
+
+ /*
+ * We start by allocating a reasonably-sized pool, as this will eventually
+ * be resized if needed.
+ */
+ pool_init(table->connections, init_size, 0);
+
+ return table;
+}
+
+void connection_table_free(connection_table_t *table) {
+ const char *k_name;
+ const address_pair_t *k_pair;
+ unsigned v_conn_id;
+
+ connection_t *connection;
+ const char *name;
+ kh_foreach(table->id_by_name, k_name, v_conn_id, {
+ connection = connection_table_get_by_id(table, v_conn_id);
+ name = connection_get_name(connection);
+ INFO("Removing connection %s [%d]", name, connection->fd);
+ connection_finalize(connection);
+ });
+
+ (void)v_conn_id;
+ kh_foreach(table->id_by_name, k_name, v_conn_id, { free((char *)k_name); });
+ kh_foreach(table->id_by_pair, k_pair, v_conn_id,
+ { free((address_pair_t *)k_pair); });
+
+ kh_destroy_ct_pair(table->id_by_pair);
+ kh_destroy_ct_name(table->id_by_name);
+ pool_free(table->connections);
+ free(table);
+}
+
+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);
+ if (k == kh_end(table->id_by_pair)) return NULL;
+ return table->connections + kh_val(table->id_by_pair, k);
+}
+
+off_t connection_table_get_id_by_name(const connection_table_t *table,
+ const char *name) {
+ khiter_t k = kh_get_ct_name(table->id_by_name, name);
+ if (k == kh_end(table->id_by_name)) return CONNECTION_ID_UNDEFINED;
+ return kh_val(table->id_by_name, k);
+}
+
+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);
+ if (!connection_id_is_valid(conn_id)) return NULL;
+ return connection_table_at(table, conn_id);
+}
+
+void connection_table_remove_by_id(connection_table_t *table, off_t id) {
+ connection_t *connection = connection_table_at(table, id);
+ INFO("Removing connection %d (%s)", id, connection_get_name(connection));
+
+ connection_table_deallocate(table, connection);
+}
+
+void connection_table_print_by_pair(const connection_table_t *table) {
+ const address_pair_t *k;
+ unsigned v;
+
+ char local_addr_str[NI_MAXHOST], remote_addr_str[NI_MAXHOST];
+ int local_port, remote_port;
+ connection_t *connection;
+ const char *name;
+
+ INFO("*** Connection table ***");
+ kh_foreach(table->id_by_pair, k, v, {
+ address_to_string(&(k->local), local_addr_str, &local_port);
+ address_to_string(&(k->remote), remote_addr_str, &remote_port);
+ connection = connection_table_get_by_id(table, v);
+ name = connection_get_name(connection);
+ INFO("(%s:%d - %s:%d)\t\t\t(%u, %s)", local_addr_str, local_port,
+ remote_addr_str, remote_port, v, name);
+ })
+}
+
+void connection_table_print_by_name(const connection_table_t *table) {
+ const char *k;
+ unsigned v;
+
+ connection_t *connection;
+ const char *name;
+
+ INFO("*** Connection table ***");
+ kh_foreach(table->id_by_name, k, v, {
+ connection = connection_table_get_by_id(table, v);
+ name = connection_get_name(connection);
+ INFO("(%s)\t\t\t(%u, %s)", k, v, name);
+ })
+}
+
+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;
+
+ /* 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);
+
+ // Return if connection name does not already exist
+ khiter_t k = kh_get_ct_name(table->id_by_name, connection_name);
+ if (k == kh_end(table->id_by_name)) break;
+ }
+
+ return connection_name;
+} \ 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
new file mode 100644
index 000000000..4c03aa642
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_table.h
@@ -0,0 +1,297 @@
+/*
+ * 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 connection_table.h
+ * \brief hICN connection_table
+ *
+ * The connection table is composed of :
+ * - a pool of connections allowing access through their id in constant time;
+ * - a set of indices in the form of hash table for efficient index lookups:
+ * . by name
+ * . by address pair
+ *
+ * For efficient index retrieval, the header will be prepended and the
+ * resulting pointer will directly point to the connection pool.
+ */
+
+#ifndef HICNLIGHT_CONNECTION_TABLE_H
+#define HICNLIGHT_CONNECTION_TABLE_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
+
+/* 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);
+KHASH_MAP_INIT_STR(ct_name, unsigned);
+
+typedef struct {
+ size_t max_size;
+
+ kh_ct_pair_t *id_by_pair;
+ kh_ct_name_t *id_by_name;
+
+ connection_t *connections; // pool
+} connection_table_t;
+
+/**
+ * @brief Allocate a connection from the connection table.
+ *
+ * @param[in] table The connection table from which to allocate a connection.
+ * @param[out] connection The pointer that will hold the allocated connection.
+ * @param[in] pair The address pair associated to the connection (to update
+ * index).
+ * @param[in] name The name associated to the connection (to update index).
+ *
+ * NOTE:
+ * - This function updates all indices from the connection table if the
+ * allocation is successful.
+ * - 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;
+}
+
+/**
+ * @brief Deallocate a connection and return it to the connection table pool.
+ *
+ * @param[in] table The connection table to which the connection is returned.
+ * @param[in] conn The connection that is returned to the pool.
+ *
+ * NOTE:
+ * - 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);
+}
+
+/**
+ * @brief Returns the length of the connection table, the number of active
+ * connections.
+ *
+ * @param[in] table The connection table for which we retrieve the length.
+ *
+ * @return size_t The length of the connection table.
+ *
+ * NOTE:
+ * - The length of the connection table, that is the number of currently active
+ * connections.
+ */
+#define connection_table_len(table) (pool_len(table->connections))
+
+/**
+ * @brief Validate an index in the connection table.
+ *
+ * @param[in] table The connection table in which to validate an index.
+ * @param[in] id The index of the connection to validate.
+ *
+ * @return bool A flag indicating whether the connection index is valid or not.
+ */
+#define connection_table_validate_id(table, id) \
+ pool_validate_id((table)->connections, (id))
+
+/**
+ * @brief Return the connection corresponding to the specified index in the
+ * connection table.
+ *
+ * @param[in] table The connection table for which to retrieve the connection.
+ * @param[in] id The index for which to retrieve the connection.
+ *
+ * @return connection_t * The connection correponding to the specified index in
+ * the connection table.
+ *
+ * @see connection_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is not validated.
+ */
+#define connection_table_at(table, id) ((table)->connections + id)
+
+/**
+ * @brief Return the connection corresponding to the specified and validated
+ * index in the connection table.
+ *
+ * @param[in] table The connection table for which to retrieve the connection.
+ * @param[in] id The index for which to retrieve the connection.
+ *
+ * @return connection_t * The connection correponding to the specified index in
+ * the connection table.
+ *
+ * @see connection_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is validated.
+ */
+#define connection_table_get_by_id(table, id) \
+ connection_table_validate_id(table, id) ? connection_table_at(table, id) \
+ : NULL
+
+/**
+ * @brief Helper function to avoid macro expansion in c++ tests. Wrapper around
+ * 'connection_table_get_by_id'.
+ */
+connection_t *_connection_table_get_by_id(connection_table_t *table, off_t id);
+
+/**
+ * @brief Returns the index of a given connection in the connection table.
+ *
+ * @param[in] table The connection table from which to retrieve the index.
+ * @param[in] conn The connection for which to retrieve the index.
+ *
+ * @return off_t The index of the specified connection in the connection table.
+ */
+#define connection_table_get_connection_id(table, conn) \
+ (conn - table->connections)
+
+#define connection_table_foreach(table, conn, BODY) \
+ pool_foreach(table->connections, (conn), BODY)
+
+#define connection_table_enumerate(table, i, conn, BODY) \
+ pool_enumerate(table->connections, (i), (conn), BODY)
+
+/**
+ * @brief Create a new connection table (extended parameters).
+ *
+ * @param[in] init_size Initially allocated size (hint, 0 = use default value).
+ * @param[in] max_size Maximum size (0 = unlimited).
+ *
+ * @return connection_table_t* The newly created connection table.
+ */
+connection_table_t *_connection_table_create(size_t init_size, size_t max_size);
+
+/**
+ * @brief Create a new connection table (minimal parameters).
+ *
+ * @return connection_table_t* The newly created connection table.
+ */
+#define connection_table_create() _connection_table_create(0, 0)
+
+/**
+ * @brief Free a connection table
+ *
+ * @param[in] table Connection table to free
+ */
+void connection_table_free(connection_table_t *table);
+
+/**
+ * @brief Retrieve a connection from the connection table by address pair.
+ *
+ * @param[in] table The connection table in which to search.
+ * @param[in] pair The address pair to search for.
+ *
+ * @return connection_t * The connection matching the specified address pair, or
+ * NULL if not found.
+ */
+connection_t *connection_table_get_by_pair(const connection_table_t *table,
+ const address_pair_t *pair);
+
+/**
+ * @brief Return a connection index from the connection table by name.
+ *
+ * @param[in] table The connection table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return off_t The index of the connection matching the name, or
+ * CONNECTION_ID_UNDEFINED if not found.
+ */
+off_t connection_table_get_id_by_name(const connection_table_t *table,
+ const char *name);
+
+/**
+ * @brief Return a connection from the connection table by name.
+ *
+ * @param[in] table The connection table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return connection_t * The connection matching the name, or NULL if not
+ * found.
+ */
+connection_t *connection_table_get_by_name(const connection_table_t *table,
+ const char *name);
+
+/**
+ * @brief Remove a connection from the connection table by its index.
+ *
+ * @param[in] table The connection table from which to delete the connection.
+ * @param[in] id The index of the connection to remove.
+ */
+void connection_table_remove_by_id(connection_table_t *table, off_t id);
+
+/**
+ * @brief Print the connection table content.
+ *
+ * @param[in] table The connection table to print.
+ */
+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);
+
+#endif /* HICNLIGHT_CONNECTION_TABLE_H */
diff --git a/hicn-light/src/hicn/core/connection_vft.c b/hicn-light/src/hicn/core/connection_vft.c
new file mode 100644
index 000000000..fe97096d3
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_vft.c
@@ -0,0 +1,37 @@
+/*
+ * 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 connection_vft.c
+ * @brief Implementation of connection VFT
+ */
+
+#include "connection_vft.h"
+
+#ifdef __linux
+extern connection_ops_t connection_hicn;
+#endif
+
+extern connection_ops_t connection_tcp;
+extern connection_ops_t connection_udp;
+
+const connection_ops_t *connection_vft[] = {
+#ifdef __linux
+ [FACE_PROTOCOL_HICN] = &connection_hicn,
+#endif
+
+ [FACE_PROTOCOL_TCP] = &connection_tcp,
+ [FACE_PROTOCOL_UDP] = &connection_udp,
+};
diff --git a/hicn-light/src/hicn/core/connection_vft.h b/hicn-light/src/hicn/core/connection_vft.h
new file mode 100644
index 000000000..e6290cdd4
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_vft.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file connection_vft.h
+ * @brief Connection VFT
+ */
+
+#ifndef HICNLIGHT_CONNECTION_VFT_H
+#define HICNLIGHT_CONNECTION_VFT_H
+
+#include "connection.h"
+
+typedef struct {
+ int (*initialize)(connection_t* connection);
+ 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);
+ int (*send_packet)(const connection_t* connection, const uint8_t* packet,
+ size_t size);
+ // void (*read_callback)(connection_t * connection, int fd, void * data);
+ size_t data_size;
+} connection_ops_t;
+
+#define DECLARE_CONNECTION(NAME) \
+ const connection_ops_t connection_##NAME = { \
+ .initialize = connection_##NAME##_initialize, \
+ .finalize = connection_##NAME##_finalize, \
+ .get_socket = listener_##NAME##_get_socket, \
+ .flush = connection_##NAME##_flush, \
+ .send = connection_##NAME##_send, \
+ .send_packet = connection_##NAME##_send_packet, \
+ .data_size = sizeof(connection_##NAME##_data_t), \
+ };
+
+// .read_callback = connection_ ## NAME ## _read_callback,
+
+extern const connection_ops_t* connection_vft[];
+
+#endif /* HICNLIGHT_CONNECTION_VFT_H */
diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c
new file mode 100644
index 000000000..edbdc5ac1
--- /dev/null
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file content_store.c
+ * \brief Implementation of hICN content_store
+ */
+
+#include "content_store.h"
+#include "packet_cache.h"
+
+extern const cs_ops_t cs_lru;
+
+const cs_ops_t *const cs_vft[] = {
+ [CS_TYPE_LRU] = &cs_lru,
+};
+
+cs_t *_cs_create(cs_type_t type, size_t max_size) {
+ if (!CS_TYPE_VALID(type)) {
+ ERROR("[cs_create] Invalid content store type");
+ return NULL;
+ }
+
+ if (max_size == 0) max_size = DEFAULT_CS_SIZE;
+
+ cs_t *cs = malloc(sizeof(cs_t));
+ if (!cs) return NULL;
+
+ cs->type = type;
+ cs->num_entries = 0;
+ cs->max_size = max_size;
+ cs_vft[type]->initialize(cs);
+ cs->stats.lru = (cs_lru_stats_t){0};
+
+ return cs;
+}
+
+void cs_free(cs_t *cs) {
+ assert(cs);
+
+ cs_vft[cs->type]->finalize(cs);
+ free(cs);
+}
+
+void _cs_clear(cs_t **cs_ptr) {
+ cs_type_t cs_type = (*cs_ptr)->type;
+ size_t max_size = (*cs_ptr)->max_size;
+
+ // Free and recreate the CS
+ cs_free(*cs_ptr);
+ *cs_ptr = _cs_create(cs_type, max_size);
+}
+
+void cs_hit(cs_t *cs) {
+ cs->stats.lru.countHits++;
+ TRACE("ContentStore hit (hits %u, misses %u)", cs->stats.lru.countHits,
+ cs->stats.lru.countMisses);
+}
+
+void cs_miss(cs_t *cs) {
+ cs->stats.lru.countMisses++;
+ TRACE("ContentStore miss (hits %u, misses %u)", cs->stats.lru.countHits,
+ cs->stats.lru.countMisses);
+}
+
+void cs_log(cs_t *cs) {
+ DEBUG(
+ "Content store: size = %u, capacity = %u, hits = %u, misses = %u, adds = "
+ "%u, updates = %u, deletions = %u (with evictions = %u)",
+ cs->num_entries, cs->max_size, cs->stats.lru.countHits,
+ cs->stats.lru.countMisses, cs->stats.lru.countAdds,
+ cs->stats.lru.countUpdates, cs->stats.lru.countLruDeletions,
+ cs->stats.lru.countLruEvictions);
+}
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
new file mode 100644
index 000000000..d47d603be
--- /dev/null
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -0,0 +1,106 @@
+#ifndef HICNLIGHT_CS_H
+#define HICNLIGHT_CS_H
+
+#include "../base/pool.h"
+#include "../content_store/lru.h"
+#include "msgbuf_pool.h"
+
+#define INVALID_ENTRY_ID ~0ul /* off_t */
+#define DEFAULT_CS_SIZE 256 // Fixed CS size
+
+typedef struct {
+ off_t msgbuf_id;
+ struct {
+ off_t prev;
+ off_t next;
+ } lru;
+} cs_entry_t;
+
+#define cs_entry_get_msgbuf_id(entry) ((entry)->msgbuf_id)
+
+typedef enum {
+ CS_TYPE_UNDEFINED,
+ CS_TYPE_LRU,
+ CS_TYPE_N,
+} cs_type_t;
+
+#define CS_TYPE_VALID(type) (type != CS_TYPE_UNDEFINED) && (type != CS_TYPE_N)
+
+typedef struct {
+ /* The maximum allowed expiry time (will never be exceeded). */
+ uint64_t max_expiry_time; // XXX part of lru ?
+} cs_options_t;
+
+typedef struct {
+ cs_type_t type;
+ int num_entries;
+ size_t max_size;
+ cs_lru_state_t lru;
+ union {
+ cs_lru_stats_t lru;
+ } stats;
+} cs_t;
+
+/**
+ * @brief Create a new content store (extended parameters).
+ *
+ * @param[in] type Content store type
+ * @param[in] max_size Maximum size (0 = use default value)
+ *
+ * @return cs_t* - The newly created content store
+ */
+cs_t *_cs_create(cs_type_t type, size_t max_size);
+
+/**
+ * @brief Create a new content store
+ *
+ * @param[in] size Maximum content store size
+ *
+ * @return cs_t* - The newly created content store
+ */
+#define cs_create(size) _cs_create(CS_TYPE_LRU, (size))
+
+/**
+ * @brief Free a content store data structure.
+ *
+ * @param[in] pool_ptr Pointer to the content store to free
+ */
+void cs_free(cs_t *cs);
+
+/**
+ * @brief Clear the content of the content store (helper).
+ *
+ * @param[in, out] cs Pointer to the content store to clear
+ */
+void _cs_clear(cs_t **cs);
+
+/**
+ * @brief Clear the content of the content store.
+ *
+ * @param[in, out] cs Pointer to the content store to clear
+ */
+#define cs_clear(cs) _cs_clear((cs_t **)&cs);
+
+/**
+ * @brief Update content store statistics upon CS hit event.
+ *
+ * @param[in] cs Pointer to the content store to use
+ */
+void cs_hit(cs_t *cs);
+
+/**
+ * @brief Update content store statistics upon CS miss event.
+ *
+ * @param[in] cs Pointer to the content store to use
+ */
+void cs_miss(cs_t *cs);
+
+/**
+ * @brief Log content store statistics, e.g. the CS current and maximum size,
+ * the number of matches, misses, add operations, update operations, evictions.
+ *
+ * @param cs Pointer to the CS data structure to use
+ */
+void cs_log(cs_t *cs);
+
+#endif /* HICNLIGHT_CS_H */
diff --git a/hicn-light/src/hicn/core/dispatcher.c b/hicn-light/src/hicn/core/dispatcher.c
deleted file mode 100644
index 59951e950..000000000
--- a/hicn-light/src/hicn/core/dispatcher.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header dispatcher.c
- * @abstract Event dispatcher for hicn-light. Uses parcEvent
- * @discussion
- * Wraps the functions we use in parcEvent, along with StreamBuffer and
- * Message. The dispatcher is the event loop, so it manages things like signals,
- * timers, and network events.
- */
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <hicn/hicn-light/config.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <parc/algol/parc_EventQueue.h>
-#include <parc/algol/parc_EventTimer.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/core/dispatcher.h>
-
-#include <pthread.h>
-
-#ifndef INPORT_ANY
-#define INPORT_ANY 0
-#endif
-
-struct dispatcher {
- PARCEventScheduler *Base;
- Logger *logger;
-};
-
-// ==========================================
-// Public API
-
-PARCEventScheduler *dispatcher_GetEventScheduler(Dispatcher *dispatcher) {
- return dispatcher->Base;
-}
-
-Dispatcher *dispatcher_Create(Logger *logger) {
- Dispatcher *dispatcher = parcMemory_AllocateAndClear(sizeof(Dispatcher));
- parcAssertNotNull(dispatcher,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Dispatcher));
-
- dispatcher->Base = parcEventScheduler_Create();
- dispatcher->logger = logger_Acquire(logger);
-
- parcAssertNotNull(dispatcher->Base,
- "Got NULL from parcEventScheduler_Create()");
-
- return dispatcher;
-}
-
-void dispatcher_Destroy(Dispatcher **dispatcherPtr) {
- parcAssertNotNull(dispatcherPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*dispatcherPtr,
- "Parameter must dereference to non-null pointer");
- Dispatcher *dispatcher = *dispatcherPtr;
-
- logger_Release(&dispatcher->logger);
- parcEventScheduler_Destroy(&(dispatcher->Base));
- parcMemory_Deallocate((void **)&dispatcher);
- *dispatcherPtr = NULL;
-}
-
-void dispatcher_Stop(Dispatcher *dispatcher) {
- struct timeval delay = {0, 1000};
-
- parcEventScheduler_Stop(dispatcher->Base, &delay);
-}
-
-void dispatcher_Run(Dispatcher *dispatcher) {
- parcAssertNotNull(dispatcher, "Parameter must be non-null");
-
- parcEventScheduler_Start(dispatcher->Base, 0);
-}
-
-void dispatcher_RunDuration(Dispatcher *dispatcher, struct timeval *duration) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(duration, "Parameter duration must be non-null");
-
- parcEventScheduler_Stop(dispatcher->Base, duration);
- parcEventScheduler_Start(dispatcher->Base, 0);
-}
-
-void dispatcher_RunCount(Dispatcher *dispatcher, unsigned count) {
- parcAssertNotNull(dispatcher, "Parameter must be non-null");
-
- for (unsigned i = 0; i < count; i++) {
- parcEventScheduler_Start(dispatcher->Base,
- PARCEventSchedulerDispatchType_LoopOnce);
- }
-}
-
-PARCEventSocket *dispatcher_CreateListener(Dispatcher *dispatcher,
- PARCEventSocket_Callback *callback,
- void *user_data, int backlog,
- const struct sockaddr *sa,
- int socklen) {
- PARCEventSocket *listener = parcEventSocket_Create(
- dispatcher->Base, callback, NULL, user_data, sa, socklen);
- if (listener == NULL) {
- perror("Problem creating listener");
- }
- return listener;
-}
-
-void dispatcher_DestroyListener(Dispatcher *dispatcher,
- PARCEventSocket **listenerPtr) {
- parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listenerPtr,
- "Parameter must dereference to non-null pointer");
- parcEventSocket_Destroy(listenerPtr);
-}
-
-PARCEventQueue *dispatcher_CreateStreamBufferFromSocket(Dispatcher *dispatcher,
- SocketType fd) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- PARCEventQueue *buffer = parcEventQueue_Create(
- dispatcher->Base, fd,
- PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks);
- parcAssertNotNull(buffer,
- "Got null from parcEventBufver_Create for socket %d", fd);
- return buffer;
-}
-
-PARCEventTimer *dispatcher_CreateTimer(Dispatcher *dispatcher, bool isPeriodic,
- PARCEvent_Callback *callback,
- void *userData) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(callback, "Parameter callback must be non-null");
-
- PARCEventType flags = 0;
- if (isPeriodic) {
- flags |= PARCEventType_Persist;
- }
- PARCEventTimer *event =
- parcEventTimer_Create(dispatcher->Base, flags, callback, userData);
- return event;
-}
-
-void dispatcher_StartTimer(Dispatcher *dispatcher, PARCEventTimer *timerEvent,
- struct timeval *delay) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(timerEvent, "Parameter timerEvent must be non-null");
- int failure = parcEventTimer_Start(timerEvent, delay);
- parcAssertFalse(failure < 0, "Error starting timer event %p: (%d) %s",
- (void *)timerEvent, errno, strerror(errno));
-}
-
-void dispatcher_StopTimer(Dispatcher *dispatcher, PARCEventTimer *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEventTimer_Stop(event);
- parcAssertFalse(failure < 0, "Error stopping signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-void dispatcher_DestroyTimerEvent(Dispatcher *dispatcher,
- PARCEventTimer **eventPtr) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(eventPtr,
- "Parameter eventPtr must be non-null double pointer");
- parcAssertNotNull(*eventPtr,
- "Paramter eventPtr must dereference to non-null pointer");
-
- parcEventTimer_Destroy(eventPtr);
- eventPtr = NULL;
-}
-
-PARCEvent *dispatcher_CreateNetworkEvent(Dispatcher *dispatcher,
- bool isPersistent,
- PARCEvent_Callback *callback,
- void *userData, int fd) {
- short flags = PARCEventType_Timeout | PARCEventType_Read;
- if (isPersistent) {
- flags |= PARCEventType_Persist;
- }
-
- PARCEvent *event =
- parcEvent_Create(dispatcher->Base, fd, flags, callback, userData);
- parcAssertNotNull(event, "Got null from parcEvent_Create for socket %d", fd);
- return event;
-}
-
-void dispatcher_DestroyNetworkEvent(Dispatcher *dispatcher,
- PARCEvent **eventPtr) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(eventPtr,
- "Parameter eventPtr must be non-null double pointer");
- parcAssertNotNull(*eventPtr,
- "Paramter eventPtr must dereference to non-null pointer");
-
- parcEvent_Destroy(eventPtr);
- eventPtr = NULL;
-}
-
-void dispatcher_StartNetworkEvent(Dispatcher *dispatcher, PARCEvent *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEvent_Start(event);
- parcAssertFalse(failure < 0, "Error starting signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-void dispatcher_StopNetworkEvent(Dispatcher *dispatcher, PARCEvent *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEvent_Stop(event);
- parcAssertFalse(failure < 0, "Error stopping signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-PARCEventSignal *dispatcher_CreateSignalEvent(
- Dispatcher *dispatcher, PARCEventSignal_Callback *callback, void *userData,
- int signal) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(callback, "Parameter callback must be non-null");
-
- PARCEventSignal *event = parcEventSignal_Create(
- dispatcher->Base, signal, PARCEventType_Signal | PARCEventType_Persist,
- callback, userData);
- parcAssertNotNull(event,
- "Got null event when creating signal catcher for signal %d",
- signal);
-
- return event;
-}
-
-void dispatcher_DestroySignalEvent(Dispatcher *dispatcher,
- PARCEventSignal **eventPtr) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(eventPtr,
- "Parameter eventPtr must be non-null double pointer");
- parcAssertNotNull(*eventPtr,
- "Paramter eventPtr must dereference to non-null pointer");
-
- parcEventSignal_Destroy(eventPtr);
- eventPtr = NULL;
-}
-
-void dispatcher_StartSignalEvent(Dispatcher *dispatcher,
- PARCEventSignal *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEventSignal_Start(event);
- parcAssertFalse(failure < 0, "Error starting signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-void dispatcher_StopSignalEvent(Dispatcher *dispatcher,
- PARCEventSignal *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEventSignal_Stop(event);
- parcAssertFalse(failure < 0, "Error stopping signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-/**
- * Bind to a local address/port then connect to peer.
- */
-static bool dispatcher_StreamBufferBindAndConnect(Dispatcher *dispatcher,
- PARCEventQueue *buffer,
- struct sockaddr *localSock,
- socklen_t localSockLength,
- struct sockaddr *remoteSock,
- socklen_t remoteSockLength) {
- // we need to bind, then connect. Special operation, so we make our
- // own fd then pass it off to the buffer event
-
-#ifndef _WIN32
- int fd = socket(localSock->sa_family, SOCK_STREAM, 0);
- if (fd < 0) {
- perror("socket");
- return -1;
- }
-
- // Set non-blocking flag
- int flags = fcntl(fd, F_GETFL, NULL);
- if (flags < 0) {
- perror("F_GETFL");
- close(fd);
- return -1;
- }
- int failure = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- if (failure) {
- perror("F_SETFL");
- close(fd);
- return -1;
- }
-
- failure = bind(fd, localSock, localSockLength);
- if (failure) {
- perror("bind");
- close(fd);
- return false;
- }
-
- parcEventQueue_SetFileDescriptor(buffer, fd);
-
- failure = parcEventQueue_ConnectSocket(buffer, remoteSock, remoteSockLength);
- if (failure && (errno != EINPROGRESS)) {
- perror("connect");
- close(fd);
- return false;
- }
-#else
- SOCKET fd = socket(localSock->sa_family, SOCK_STREAM, 0);
- if (fd == INVALID_SOCKET) {
- perror("socket");
- return -1;
- }
-
- // Set non-blocking flag
- u_long mode = 1;
- int result = ioctlsocket(fd, FIONBIO, &mode);
- if (result == NO_ERROR) {
- perror("ioctlsocket error");
- closesocket(fd);
- WSACleanup();
- return -1;
- }
-
- int failure = bind(fd, localSock, (int)localSockLength);
- if (failure) {
- perror("bind");
- closesocket(fd);
- WSACleanup();
- return false;
- }
-
- parcEventQueue_SetFileDescriptor(buffer, (int)fd);
-
- failure = parcEventQueue_ConnectSocket(buffer, remoteSock, remoteSockLength);
- if (failure && (errno != EINPROGRESS)) {
- perror("connect");
- closesocket(fd);
- WSACleanup();
- return false;
- }
-#endif
-
- return true;
-}
-
-/**
- * Connect to an INET peer
- * @return NULL on error, otherwise a streambuffer
- */
-static PARCEventQueue *dispatcher_StreamBufferConnect_INET(
- Dispatcher *dispatcher, const Address *localAddress,
- const Address *remoteAddress) {
- struct sockaddr_in localSock, remoteSock;
- addressGetInet(localAddress, &localSock);
- addressGetInet(remoteAddress, &remoteSock);
-
- PARCEventQueue *buffer = parcEventQueue_Create(
- dispatcher->Base, -1, PARCEventQueueOption_CloseOnFree);
- parcAssertNotNull(buffer, "got null buffer from parcEventQueue_Create()");
-
- bool success = dispatcher_StreamBufferBindAndConnect(
- dispatcher, buffer, (struct sockaddr *)&localSock, sizeof(localSock),
- (struct sockaddr *)&remoteSock, sizeof(remoteSock));
- if (!success) {
- parcEventQueue_Destroy(&buffer);
- buffer = NULL;
- }
-
- return buffer;
-}
-
-/**
- * Connect to an INET peer
- * @return NULL on error, otherwise a streambuffer
- */
-static PARCEventQueue *
-// static StreamBuffer *
-dispatcher_StreamBufferConnect_INET6(Dispatcher *dispatcher,
- const Address *localAddress,
- const Address *remoteAddress) {
- struct sockaddr_in6 localSock, remoteSock;
- addressGetInet6(localAddress, &localSock);
- addressGetInet6(remoteAddress, &remoteSock);
-
- PARCEventQueue *buffer = parcEventQueue_Create(
- dispatcher->Base, -1, PARCEventQueueOption_CloseOnFree);
- parcAssertNotNull(buffer, "got null buffer from parcEventQueue_Create()");
-
- bool success = dispatcher_StreamBufferBindAndConnect(
- dispatcher, buffer, (struct sockaddr *)&localSock, sizeof(localSock),
- (struct sockaddr *)&remoteSock, sizeof(remoteSock));
- if (!success) {
- parcEventQueue_Destroy(&buffer);
- buffer = NULL;
- }
-
- return buffer;
-}
-
-PARCEventQueue *dispatcher_StreamBufferConnect(Dispatcher *dispatcher,
- const AddressPair *pair) {
- const Address *localAddress = addressPair_GetLocal(pair);
- const Address *remoteAddress = addressPair_GetRemote(pair);
-
- // they must be of the same address family
- if (addressGetType(localAddress) != addressGetType(remoteAddress)) {
- char message[2048];
- char *localAddressString = addressToString(localAddress);
- char *remoteAddressString = addressToString(remoteAddress);
- snprintf(message, 2048,
- "Remote address not same type as local address, expected %d got "
- "%d\nlocal %s remote %s",
- addressGetType(localAddress), addressGetType(remoteAddress),
- localAddressString, remoteAddressString);
-
- parcMemory_Deallocate((void **)&localAddressString);
- parcMemory_Deallocate((void **)&remoteAddressString);
-
- parcAssertTrue(
- addressGetType(localAddress) == addressGetType(remoteAddress), "%s",
- message);
- }
-
- address_type type = addressGetType(localAddress);
-
- PARCEventQueue *result = NULL;
-
- switch (type) {
- case ADDR_INET:
- return dispatcher_StreamBufferConnect_INET(dispatcher, localAddress,
- remoteAddress);
- break;
- case ADDR_INET6:
- return dispatcher_StreamBufferConnect_INET6(dispatcher, localAddress,
- remoteAddress);
- break;
- default:
- parcTrapIllegalValue(type, "local address unsupported address type: %d",
- type);
- }
- return result;
-}
diff --git a/hicn-light/src/hicn/core/dispatcher.h b/hicn-light/src/hicn/core/dispatcher.h
deleted file mode 100644
index e5c2df336..000000000
--- a/hicn-light/src/hicn/core/dispatcher.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header hicn-light Dispatcher
- * @abstract The dispatcher is the event loop run by Forwarder.
- * @discussion
- * These functions manage listeners, timers, and network events inside
- * the event loop.
- *
- * Curently, it is a thin wrapper around an event so we don't have to
- * expose that implementation detail to other modules.
- *
- */
-
-#ifndef dispatcher_h
-#define dispatcher_h
-
-#ifndef _WIN32
-#include <sys/socket.h>
-#endif
-#include <stdbool.h>
-
-struct dispatcher;
-typedef struct dispatcher Dispatcher;
-
-#include <parc/algol/parc_Event.h>
-#include <parc/algol/parc_EventQueue.h>
-#include <parc/algol/parc_EventScheduler.h>
-#include <parc/algol/parc_EventSignal.h>
-#include <parc/algol/parc_EventSocket.h>
-#include <parc/algol/parc_EventTimer.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/core/logger.h>
-
-PARCEventScheduler *dispatcher_GetEventScheduler(Dispatcher *dispatcher);
-/**
- * Creates an event dispatcher
- *
- * Event dispatcher based on PARCEvent
- *
- * @return non-null Allocated event dispatcher
- * @return null An error
- */
-Dispatcher *dispatcher_Create(Logger *logger);
-
-/**
- * Destroys event dispatcher
- *
- * Caller is responsible for destroying call events before destroying
- * the event dispatcher.
- */
-void dispatcher_Destroy(Dispatcher **dispatcherPtr);
-
-/**
- * @function dispatcher_Stop
- * @abstract Called from a different thread, tells the dispatcher to stop
- * @discussion
- * Called from a user thread or from an interrupt handler.
- * Does not block. Use <code>dispatcher_WaitForStopped()</code> to
- * block until stopped after calling this.
- */
-void dispatcher_Stop(Dispatcher *dispatcher);
-
-/**
- * @function dispatcher_WaitForStopped
- * @abstract Blocks until dispatcher in stopped state
- * @discussion
- * Used after <code>dispatcher_Stop()</code> to wait for stop.
- */
-void dispatcher_WaitForStopped(Dispatcher *dispatcher);
-
-/**
- * @function dispatcher_Run
- * @abstract Runs the forwarder, blocks.
- */
-void dispatcher_Run(Dispatcher *dispatcher);
-
-/**
- * @function dispatcher_RunDuration
- * @abstract Runs forwarder for at most duration, blocks.
- * @discussion
- * Blocks running the forwarder for a duration. May be called
- * iteratively to keep running. Duration is a minimum, actual
- * runtime may be slightly longer.
- */
-void dispatcher_RunDuration(Dispatcher *dispatcher, struct timeval *duration);
-
-/**
- * @header dispatcher_RunCount
- * @abstract Run the event loop for the given count cycles
- * @discussion
- * Runs the event loop for the given number of cycles, blocking
- * until done. May be called sequentially over and over.
- *
- */
-void dispatcher_RunCount(Dispatcher *dispatcher, unsigned count);
-
-typedef int SocketType;
-
-typedef struct evconnlistener Listener;
-
-/**
- * @typedef ListenerCallback
- * @abstract Callback function typedef for a stream listener
- *
- * @constant listener is the object created by <code>forwarder_NewBind()</code>
- * that received the client connection
- * @constant client_socket is the client socket
- * @constant user_data is the user_data passed to
- * <code>forwarder_NewBind()</code>
- * @constant client_addr is the client address
- * @constant socklen is the length of client_addr
- * @discussion <#Discussion#>
- */
-typedef void(ListenerCallback)(Listener *listener, SocketType client_socket,
- struct sockaddr *client_addr, int socklen,
- void *user_data);
-
-/**
- * @header forwarder_NewBind
- * @abstract Allocate a new stream listener
- * @discussion
- * The server socket will be freed when closed and will be reusable.
- *
- * @param forwarder that owns the event loop
- * @param cb is the callback for a new connection
- * @param user_data is opaque user data passed to the callback
- * @param backlog is the listen() depth, may use -1 for a default value
- * @param sa is the socket address to bind to (INET, INET6, LOCAL)
- * @param socklen is the sizeof the actual sockaddr (e.g. sizeof(sockaddr_un))
- */
-PARCEventSocket *dispatcher_CreateListener(Dispatcher *dispatcher,
- PARCEventSocket_Callback *callback,
- void *user_data, int backlog,
- const struct sockaddr *sa,
- int socklen);
-
-void dispatcher_DestroyListener(Dispatcher *dispatcher,
- PARCEventSocket **listenerPtr);
-
-typedef struct event TimerEvent;
-typedef struct event NetworkEvent;
-typedef struct event SignalEvent;
-
-/**
- * @typedef EventCallback
- * @abstract A network event or a timer callback
- * @constant fd The file descriptor associated with the event, may be -1 for
- * timers
- * @constant which_event is a bitmap of the EventType
- * @constant user_data is the user_data passed to
- * <code>Forwarder_CreateEvent()</code>
- */
-typedef void(EventCallback)(SocketType fd, short which_event, void *user_data);
-
-/**
- * @function dispatcher_CreateTimer
- * @abstract Creates a Event for use as a timer.
- * @discussion
- *
- * When created, the timer is idle and you need to call
- * <code>forwarder_StartTimer()</code>
- *
- * @param isPeriodic means the timer will fire repeatidly, otherwise it is a
- * one-shot and needs to be set again with <code>dispatcher_StartTimer()</code>
- */
-PARCEventTimer *dispatcher_CreateTimer(Dispatcher *dispatcher, bool isPeriodic,
- PARCEvent_Callback *callback,
- void *userData);
-
-/**
- * @function dispatcher_StartTimer
- * @abstract Starts the timer with the given delay.
- * @discussion
- * If the timer is periodic, it will keep firing with the given delay
- */
-void dispatcher_StartTimer(Dispatcher *dispatcher, PARCEventTimer *timerEvent,
- struct timeval *delay);
-
-void dispatcher_StopTimer(Dispatcher *dispatcher, PARCEventTimer *timerEvent);
-
-/**
- * @function dispatcher_DestroyTimerEvent
- * @abstract Cancels the timer and frees the event
- */
-void dispatcher_DestroyTimerEvent(Dispatcher *dispatcher,
- PARCEventTimer **eventPtr);
-
-/**
- * @function dispatcher_CreateNetworkEvent
- * @abstract Creates a network event callback on the socket
- * @discussion
- * May be used on any sort of file descriptor or socket. The event is edge
- * triggered and non-reentrent. This means you need to drain the events off the
- * socket, as the callback will not be called again until a new event arrives.
- *
- * When created, the event is idle and you need to call
- * <code>forwarder_StartNetworkEvent()</code>
- *
- * @param isPersistent means the callback will keep firing with new events,
- * otherwise its a one-shot
- * @param fd is the socket to monitor
- */
-PARCEvent *dispatcher_CreateNetworkEvent(Dispatcher *dispatcher,
- bool isPersistent,
- PARCEvent_Callback *callback,
- void *userData, int fd);
-
-void dispatcher_StartNetworkEvent(Dispatcher *dispatcher, PARCEvent *event);
-void dispatcher_StopNetworkEvent(Dispatcher *dispatcher, PARCEvent *event);
-
-void dispatcher_DestroyNetworkEvent(Dispatcher *dispatcher,
- PARCEvent **eventPtr);
-
-/**
- * @function dispatcher_CreateSignalEvent
- * @abstract Creates a signal trap
- * @discussion
- * May be used on catchable signals. The event is edge triggered and
- * non-reentrent. Signal events are persistent.
- *
- * When created, the signal trap is idle and you need to call
- * <code>forwarder_StartSignalEvent()</code>
- *
- * @param signal is the system signal to monitor (e.g. SIGINT).
- * @return <#return#>
- */
-PARCEventSignal *dispatcher_CreateSignalEvent(
- Dispatcher *dispatcher, PARCEventSignal_Callback *callback, void *userData,
- int signal);
-
-void dispatcher_DestroySignalEvent(Dispatcher *dispatcher,
- PARCEventSignal **eventPtr);
-
-void dispatcher_StartSignalEvent(Dispatcher *dispatcher,
- PARCEventSignal *event);
-void dispatcher_StopSignalEvent(Dispatcher *dispatcher, PARCEventSignal *event);
-
-// =============
-// stream buffers
-
-#include <hicn/core/streamBuffer.h>
-#include <hicn/io/addressPair.h>
-
-/**
- * @function dispatcher_CreateStreamBuffer
- * @abstract Creates a high-function buffer around a stream socket
- */
-PARCEventQueue *dispatcher_CreateStreamBufferFromSocket(Dispatcher *dispatcher,
- SocketType fd);
-
-/**
- * @function dispatcher_StreamBufferConnect
- * @abstract Create a TCP tunnel to a remote peer
- * @discussion
- * For TCP, both address pairs need to be the same address family: both INET
- * or both INET6. The remote address must have the complete socket information
- * (address, port). The local socket could be wildcarded or may specify down to
- * the (address, port) pair.
- *
- * If the local address is IPADDR_ANY and the port is 0, then it is a normal
- * call to "connect" that will use whatever local IP address and whatever local
- * port for the connection. If either the address or port is set, the local
- * socket will first be bound (via bind(2)), and then call connect().
- *
- * It is unlikely that the buffer will be connected by the time the function
- * returns. The eventCallback will fire once the remote system accepts the
- * conneciton.
- *
- * @return NULL on error, otherwise a streambuffer.
- */
-PARCEventQueue *dispatcher_StreamBufferConnect(Dispatcher *dispatcher,
- const AddressPair *pair);
-#endif // dispatcher_h
diff --git a/hicn-light/src/hicn/core/fib.c b/hicn-light/src/hicn/core/fib.c
new file mode 100644
index 000000000..d8d3c7cfa
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib.c
@@ -0,0 +1,478 @@
+/*
+ * 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/hicn-light/config.h>
+#include <stdio.h>
+
+#include <hicn/core/fib.h>
+
+typedef struct fib_node_s {
+ struct fib_node_s *left;
+ struct fib_node_s *right;
+ fib_entry_t *entry;
+ bool is_used;
+} fib_node_t;
+
+static fib_node_t *fib_node_create(fib_node_t *left, fib_node_t *right,
+ fib_entry_t *entry, bool is_used) {
+ fib_node_t *node = malloc(sizeof(fib_node_t));
+ if (!node) return NULL;
+
+ *node = (fib_node_t){
+ .left = left,
+ .right = right,
+ .entry = entry,
+ .is_used = is_used,
+ };
+
+ return node;
+}
+
+static void fib_node_free(fib_node_t *node) {
+ if (!node) return;
+
+ fib_node_free(node->right);
+ fib_node_free(node->left);
+
+ fib_entry_free(node->entry);
+ free(node);
+}
+
+/******************************************************************************/
+
+struct fib_s {
+ void *forwarder;
+ fib_node_t *root;
+ unsigned size;
+};
+
+fib_t *fib_create(void *forwarder) {
+ fib_t *fib = malloc(sizeof(fib_t));
+ if (!fib) return NULL;
+
+ fib->forwarder = forwarder;
+ fib->root = NULL;
+ fib->size = 0;
+
+ return fib;
+}
+
+void fib_free(fib_t *fib) {
+ assert(fib);
+
+ fib_node_free(fib->root);
+
+ free(fib);
+}
+
+size_t fib_get_size(const fib_t *fib) {
+ assert(fib);
+ return fib->size;
+}
+
+#define FIB_SET(CURR, NEW_PREFIX, CURR_PREFIX_LEN) \
+ do { \
+ bool bit; \
+ int res = nameBitvector_testBit(NEW_PREFIX, CURR_PREFIX_LEN, &bit); \
+ assert(res >= 0); \
+ (void)res; /* unused */ \
+ CURR = bit ? CURR->right : CURR->left; \
+ } while (0)
+
+#define FIB_INSERT(DST, SRC, PREFIX, PREFIX_LEN) \
+ do { \
+ bool bit; \
+ int res = nameBitvector_testBit(PREFIX, PREFIX_LEN, &bit); \
+ assert(res >= 0); \
+ (void)res; /* unused */ \
+ if (bit) \
+ DST->right = SRC; \
+ else \
+ DST->left = SRC; \
+ } while (0)
+
+void fib_add(fib_t *fib, fib_entry_t *entry) {
+ assert(fib);
+ assert(entry);
+
+ NameBitvector *new_prefix = name_GetContentName(fib_entry_get_prefix(entry));
+ uint32_t new_prefix_len = nameBitvector_GetLength(new_prefix);
+ fib_node_t *curr = fib->root;
+ fib_node_t *last = NULL;
+
+ NameBitvector *curr_name;
+ uint32_t curr_prefix_len;
+ uint32_t match_len;
+
+ while (curr) {
+ curr_name = name_GetContentName(fib_entry_get_prefix(curr->entry));
+
+ match_len = nameBitvector_lpm(new_prefix, curr_name);
+ curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if (curr_prefix_len !=
+ match_len || // the new entry does not match the curr
+ curr_prefix_len >=
+ new_prefix_len) // in this case we cannot procede anymore
+ break;
+
+ last = curr;
+ FIB_SET(curr, new_prefix, curr_prefix_len);
+ }
+
+ // this is the root (empty trie) or an empty child
+ if (!curr) {
+ fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true);
+ if (!last) {
+ fib->root = new_node;
+ } else {
+ uint32_t last_prefix_len = nameBitvector_GetLength(
+ name_GetContentName(fib_entry_get_prefix(last->entry)));
+
+ FIB_INSERT(last, new_node, new_prefix, last_prefix_len);
+ }
+ fib->size++;
+ return;
+ }
+
+ // curr is not null
+
+ // the node already exist
+ // if is not in use we turn it on and we set the rigth fib entry
+ if (curr_prefix_len == match_len && new_prefix_len == match_len) {
+ if (!curr->is_used) {
+ curr->is_used = true;
+ curr->entry = entry;
+ fib->size++;
+ return;
+ } else {
+ // this case should never happen beacuse of the way we add
+ // entries in the fib
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop,
+ { fib_entry_nexthops_add(curr->entry, nexthop); });
+ }
+ }
+
+ // key is prefix of the curr node (so new_prefix_len < curr_prefix_len)
+ if (new_prefix_len == match_len) {
+ fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true);
+ if (!last) {
+ fib->root = new_node;
+ } else {
+ uint32_t last_prefix_len = nameBitvector_GetLength(
+ name_GetContentName(fib_entry_get_prefix(last->entry)));
+ FIB_INSERT(last, new_node, new_prefix, last_prefix_len);
+ }
+ FIB_INSERT(new_node, curr, curr_name, match_len);
+ fib->size++;
+ return;
+ }
+
+ // in the last case we need to add an inner node
+ Name inner_prefix = EMPTY_NAME;
+ name_Copy(fib_entry_get_prefix(entry), &inner_prefix);
+ nameBitvector_clear(name_GetContentName(&inner_prefix), match_len);
+ name_setLen(&inner_prefix, match_len);
+
+ // this is an inner node, we don't want an acctive strategy
+ // like low_latency that sends probes in this node
+ fib_entry_t *inner_entry = fib_entry_create(
+ &inner_prefix, STRATEGY_TYPE_UNDEFINED, NULL, fib->forwarder);
+
+ fib_node_t *inner_node = fib_node_create(NULL, NULL, inner_entry, false);
+ fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true);
+
+ if (!last) {
+ // we need to place the inner_node at the root
+ fib->root = inner_node;
+ } else {
+ uint32_t last_prefix_len = nameBitvector_GetLength(
+ name_GetContentName(fib_entry_get_prefix(last->entry)));
+ NameBitvector *inner_name = name_GetContentName(&inner_prefix);
+ FIB_INSERT(last, inner_node, inner_name, last_prefix_len);
+ }
+
+ bool bit;
+ int res = nameBitvector_testBit(new_prefix, match_len, &bit);
+ assert(res >= 0);
+ (void)res; /* unused */
+ inner_node->left = bit ? curr : new_node;
+ inner_node->right = bit ? new_node : curr;
+ fib->size++;
+}
+
+fib_entry_t *fib_contains(const fib_t *fib, const Name *prefix) {
+ assert(fib);
+ assert(prefix);
+
+ NameBitvector *key_name = name_GetContentName(prefix);
+ uint32_t key_prefix_len = nameBitvector_GetLength(key_name);
+
+ fib_node_t *curr = fib->root;
+
+ while (curr) {
+ NameBitvector *curr_name =
+ name_GetContentName(fib_entry_get_prefix(curr->entry));
+ uint32_t match_len = nameBitvector_lpm(key_name, curr_name);
+ uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if (match_len < curr_prefix_len) {
+ // the current node does not match completelly the key, so
+ // the key is not in the trie
+ // this implies curr_prefix_len > key_prefix_len
+ return NULL;
+ }
+
+ if (curr_prefix_len == key_prefix_len) { //== match_len
+ // this is an exact match
+ if (!curr->is_used) {
+ // the key does not exists
+ return NULL;
+ }
+ // we found the key
+ return curr->entry;
+ }
+
+ FIB_SET(curr, key_name, curr_prefix_len);
+ }
+
+ return NULL;
+}
+
+static void fib_node_remove(fib_t *fib, const Name *prefix) {
+ assert(fib);
+ assert(prefix);
+
+ NameBitvector *key_name = name_GetContentName(prefix);
+ uint32_t key_prefix_len = nameBitvector_GetLength(key_name);
+
+ fib_node_t *curr = fib->root;
+ fib_node_t *parent = NULL;
+ fib_node_t *grandpa = NULL;
+
+ uint32_t match_len;
+ uint32_t curr_prefix_len;
+
+ while (curr) {
+ NameBitvector *curr_name =
+ name_GetContentName(fib_entry_get_prefix(curr->entry));
+ match_len = nameBitvector_lpm(key_name, curr_name);
+ curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if (match_len < curr_prefix_len || curr_prefix_len == key_prefix_len) {
+ break;
+ }
+
+ grandpa = parent;
+ parent = curr;
+
+ FIB_SET(curr, key_name, curr_prefix_len);
+ }
+
+ if (!curr || !curr->is_used || (curr_prefix_len != key_prefix_len)) {
+ // the node does not exists
+ return;
+ }
+
+ // curr has 2 children, leave it there and mark it as inner
+ if (curr->right && curr->left) {
+ curr->is_used = false;
+ fib->size--;
+ return;
+ }
+
+ // curr has no children
+ if (!curr->right && !curr->left) {
+ if (!parent) {
+ // curr is the root and is the only node in the fib
+ fib->root = NULL;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+ if (!grandpa) {
+ // parent is the root
+ if (fib->root->left == curr)
+ fib->root->left = NULL;
+ else
+ fib->root->right = NULL;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+ if (!parent->is_used) {
+ // parent is an inner node
+ // remove curr and inner_node (parent), connect the other child
+ // of the parent to the grandpa
+ fib_node_t *tmp = (parent->right == curr) ? parent->left : parent->right;
+
+ if (grandpa->right == parent)
+ grandpa->right = tmp;
+ else
+ grandpa->left = tmp;
+
+ fib->size--;
+ fib_node_free(curr);
+ fib_node_free(parent);
+ return;
+ }
+ // parent is node not an inner_node
+ // just remove curr the node
+ if (parent->right == curr)
+ parent->right = NULL;
+ else
+ parent->left = NULL;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+
+ // curr has one child
+ if (curr->right || curr->left) {
+ if (!parent) {
+ // curr is the root
+ fib->root = fib->root->right ? fib->root->right : fib->root->left;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+ // attach the child of curr to parent
+ fib_node_t *tmp = curr->right ? curr->right : curr->left;
+
+ if (parent->right == curr)
+ parent->right = tmp;
+ else
+ parent->left = tmp;
+
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+}
+
+void fib_remove(fib_t *fib, const Name *name, unsigned conn_id) {
+ assert(fib);
+ assert(name);
+
+ fib_entry_t *entry = fib_contains(fib, name);
+ if (!entry) return;
+
+ fib_entry_nexthops_remove(entry, conn_id);
+#ifndef WITH_MAPME
+ if (fib_entry_nexthops_len(entry) == 0) fib_node_remove(fib, name);
+#endif /* WITH_MAPME */
+}
+
+static size_t fib_node_remove_connection_id(fib_node_t *node, unsigned conn_id,
+ fib_entry_t **array, size_t pos) {
+ if (!node) return pos;
+ if (node->is_used) {
+ fib_entry_nexthops_remove(node->entry, conn_id);
+#ifndef WITH_MAPME
+ if (fib_entry_nexthops_len(node->entry) == 0) array[pos++] = node->entry;
+#endif /* WITH_MAPME */
+ }
+ pos = fib_node_remove_connection_id(node->right, conn_id, array, pos);
+ pos = fib_node_remove_connection_id(node->left, conn_id, array, pos);
+ return pos;
+}
+
+void fib_remove_connection_id(fib_t *fib, unsigned conn_id) {
+ assert(fib);
+
+ fib_entry_t **array = malloc(sizeof(fib_entry_t *) * fib->size);
+
+ size_t pos = 0;
+ pos = fib_node_remove_connection_id(fib->root, conn_id, array, pos);
+
+ for (int i = 0; i < pos; i++)
+ fib_node_remove(fib, fib_entry_get_prefix(array[i]));
+ free(array);
+}
+
+fib_entry_t *fib_match_message(const fib_t *fib,
+ const msgbuf_t *interest_msgbuf) {
+ assert(fib);
+ assert(interest_msgbuf);
+
+ return fib_match_bitvector(
+ fib, name_GetContentName(msgbuf_get_name(interest_msgbuf)));
+}
+
+fib_entry_t *fib_match_name(const fib_t *fib, const Name *name) {
+ assert(fib);
+ assert(name);
+
+ return fib_match_bitvector(fib, name_GetContentName(name));
+}
+
+fib_entry_t *fib_match_bitvector(const fib_t *fib, const NameBitvector *name) {
+ assert(fib);
+ assert(name);
+
+ uint32_t key_prefix_len = nameBitvector_GetLength(name);
+
+ fib_node_t *curr = fib->root;
+ fib_node_t *candidate = NULL;
+
+ while (curr) {
+ NameBitvector *curr_name =
+ name_GetContentName(fib_entry_get_prefix(curr->entry));
+ uint32_t match_len = nameBitvector_lpm(name, curr_name);
+ uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if (match_len < curr_prefix_len) {
+ // the current node does not match completelly the key, so
+ // return the parent of this node (saved in candidate)
+ break;
+ }
+
+ if (curr->is_used) candidate = curr;
+
+ // if we are here match_len == curr_prefix_len (can't be larger)
+ // so this node is actually a good candidate for a match
+ if (curr_prefix_len == key_prefix_len) {
+ // this an exact match, do not continue
+ break;
+ }
+
+ FIB_SET(curr, name, curr_prefix_len);
+ }
+
+ return candidate ? candidate->entry : NULL;
+}
+
+static size_t fib_node_collect_entries(fib_node_t *node, fib_entry_t **array,
+ size_t pos) {
+ assert(array);
+
+ if (!node) return pos;
+
+ if (node->is_used) array[pos++] = node->entry;
+
+ pos = fib_node_collect_entries(node->right, array, pos);
+ pos = fib_node_collect_entries(node->left, array, pos);
+ return pos;
+}
+
+size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p) {
+ size_t pos = 0;
+ *array_p = malloc(sizeof(fib_entry_t *) * fib->size);
+ if (!*array_p) return pos;
+ pos = fib_node_collect_entries(fib->root, *array_p, pos);
+ return pos;
+}
diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h
new file mode 100644
index 000000000..c0fda960b
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib.h
@@ -0,0 +1,62 @@
+/*
+ * 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 HICNLIGHT_FIB_H
+#define HICNLIGHT_FIB_H
+
+#include "fib_entry.h"
+#include "msgbuf.h"
+#include "name.h"
+
+#define _fib_var(x) _fib_##x
+
+typedef struct fib_s fib_t;
+
+fib_t *fib_create(void *forwarder);
+
+void fib_free(fib_t *fib);
+
+size_t fib_get_size(const fib_t *fib);
+
+void fib_add(fib_t *fib, fib_entry_t *node);
+
+fib_entry_t *fib_contains(const fib_t *fib, const Name *prefix);
+
+void fib_remove(fib_t *fib, const Name *prefix, unsigned conn_id);
+
+void fib_remove_connection_id(fib_t *fib, unsigned conn_id);
+
+fib_entry_t *fib_match_message(const fib_t *fib,
+ const msgbuf_t *interest_msgbuf);
+fib_entry_t *fib_match_name(const fib_t *fib, const Name *name);
+fib_entry_t *fib_match_bitvector(const fib_t *fib, const NameBitvector *name);
+
+size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p);
+
+#define fib_foreach_entry(FIB, ENTRY, BODY) \
+ do { \
+ fib_entry_t **_fib_var(array); \
+ size_t _fib_var(n) = fib_get_entry_array((FIB), &_fib_var(array)); \
+ size_t _fib_var(i); \
+ for (_fib_var(i) = 0; _fib_var(i) < _fib_var(n); _fib_var(i)++) { \
+ ENTRY = _fib_var(array)[_fib_var(i)]; \
+ do { \
+ BODY \
+ } while (0); \
+ } \
+ free(_fib_var(array)); \
+ } while (0)
+
+#endif /* HICNLIGHT_FIB_H */
diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c
new file mode 100644
index 000000000..616f12961
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib_entry.c
@@ -0,0 +1,588 @@
+/*
+ * 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 <stdio.h>
+
+#include <hicn/hicn-light/config.h>
+#include <hicn/core/fib_entry.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/nameBitvector.h>
+
+#ifdef WITH_MAPME
+#include <hicn/core/ticks.h>
+#endif /* WITH_MAPME */
+
+#ifdef WITH_POLICY
+#include <hicn/core/forwarder.h>
+#include <hicn/policy.h>
+
+#ifdef WITH_MAPME
+#include <hicn/core/mapme.h>
+#endif /* WITH_MAPME */
+
+#endif /* WITH_POLICY */
+
+#ifdef WITH_POLICY_STATS
+#include <hicn/core/policy_stats.h>
+#endif /* WITH_POLICY_STATS */
+
+fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type,
+ strategy_options_t *strategy_options,
+ const forwarder_t *forwarder) {
+ assert(name);
+ assert(forwarder);
+
+ fib_entry_t *entry = malloc(sizeof(fib_entry_t));
+ if (!entry) goto ERR_MALLOC;
+
+ memset(entry, 0, sizeof(*entry));
+ name_Copy(name, &entry->name);
+ entry->nexthops = NEXTHOPS_EMPTY;
+
+ fib_entry_add_strategy_options(entry, STRATEGY_TYPE_BESTPATH, NULL);
+ fib_entry_add_strategy_options(entry, STRATEGY_TYPE_REPLICATION, NULL);
+ fib_entry_set_strategy(entry, strategy_type, strategy_options);
+
+#ifdef WITH_MAPME
+ entry->user_data = NULL;
+ entry->user_data_release = NULL;
+#endif /* WITH_MAPME */
+
+ entry->forwarder = forwarder;
+
+#ifdef WITH_POLICY
+ entry->policy = POLICY_EMPTY;
+#endif /* WITH_POLICY */
+
+#ifdef WITH_POLICY_STATS
+ entry->policy_stats = POLICY_STATS_EMPTY;
+ entry->policy_counters = POLICY_COUNTERS_EMPTY;
+#endif /* WITH_POLICY_STATS */
+
+ return entry;
+
+ERR_MALLOC:
+ return NULL;
+}
+
+void fib_entry_free(fib_entry_t *entry) {
+ assert(entry);
+#ifdef WITH_MAPME
+ if (entry->user_data) entry->user_data_release(&entry->user_data);
+#endif /* WITH_MAPME */
+ free(entry);
+}
+
+void fib_entry_add_strategy_options(fib_entry_t *entry,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options) {
+ // for the moment only the best path and replication strategies support
+ // strategy options return for the other strategyes
+ if (strategy_type != STRATEGY_TYPE_BESTPATH &&
+ strategy_type != STRATEGY_TYPE_REPLICATION)
+ return;
+
+ if (!strategy_options) {
+ if (strategy_type == STRATEGY_TYPE_BESTPATH) {
+ entry->strategy.options.bestpath.local_prefixes = NULL;
+ } else {
+ entry->strategy.options.replication.local_prefixes = NULL;
+ }
+ return;
+ }
+
+ local_prefixes_t *new_prefixes;
+ local_prefixes_t *curr_prefixes;
+
+ if (strategy_type == STRATEGY_TYPE_BESTPATH) {
+ new_prefixes = strategy_options->bestpath.local_prefixes;
+ curr_prefixes = entry->strategy.options.bestpath.local_prefixes;
+
+ if (!curr_prefixes) {
+ entry->strategy.options.bestpath.local_prefixes = create_local_prefixes();
+ curr_prefixes = entry->strategy.options.bestpath.local_prefixes;
+ }
+ } else {
+ new_prefixes = strategy_options->replication.local_prefixes;
+ curr_prefixes = entry->strategy.options.replication.local_prefixes;
+
+ if (!curr_prefixes) {
+ entry->strategy.options.replication.local_prefixes =
+ create_local_prefixes();
+ curr_prefixes = entry->strategy.options.replication.local_prefixes;
+ }
+ }
+
+ local_prefixes_add_prefixes(curr_prefixes, new_prefixes);
+}
+
+void fib_entry_set_strategy(fib_entry_t *entry, strategy_type_t strategy_type,
+ strategy_options_t *strategy_options) {
+ // Default strategy if undefined
+ if (!STRATEGY_TYPE_VALID(strategy_type)) strategy_type = STRATEGY_TYPE_RANDOM;
+
+ if (entry->strategy.type == strategy_type) { // startegy alredy set
+ if (strategy_type != STRATEGY_TYPE_BESTPATH) {
+ return; // nothing to do
+ } else {
+ strategy_initialize(&entry->strategy, entry->forwarder);
+ return;
+ }
+ }
+
+ entry->strategy.type = strategy_type;
+ if (strategy_options) entry->strategy.options = *strategy_options;
+
+ strategy_initialize(&entry->strategy, entry->forwarder);
+}
+
+#ifdef WITH_POLICY
+
+nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops,
+ unsigned ingress_id, bool prefer_local) {
+ assert(entry);
+ assert(nexthops);
+
+ nexthops_reset(nexthops);
+
+ // DEBUG("[fib_entry_filter_nexthops] num=%d/%d ingress_id=%d",
+ // nexthops_get_curlen(nexthops), nexthops_get_len(nexthops),
+ // ingress_id);
+
+ /* Filter out ingress, down & administrative down faces */
+ const connection_table_t *table =
+ forwarder_get_connection_table(entry->forwarder);
+ connection_t *conn;
+ unsigned nexthop, i;
+ uint_fast32_t flags;
+
+ hicn_policy_t policy = fib_entry_get_policy(entry);
+
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i, nexthop == ingress_id);
+ nexthops_disable_if(nexthops, i,
+ (connection_get_admin_state(conn) == FACE_STATE_DOWN));
+ nexthops_disable_if(nexthops, i,
+ (connection_get_state(conn) == FACE_STATE_DOWN));
+ });
+
+ // DEBUG("After pruning, num=%d/%d", nexthops_get_curlen(nexthops),
+ // nexthops_get_len(nexthops));
+
+ if (prefer_local) {
+ /* Backup flags and cur_len*/
+ flags = nexthops->flags;
+ size_t cur_len = nexthops_get_curlen(nexthops);
+
+ /* Filter local */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i, (!connection_is_local(conn)));
+ });
+
+ /* Local faces have priority */
+ if (nexthops_get_curlen(nexthops) > 0) return nexthops;
+
+ nexthops->flags = flags;
+ nexthops->cur_elts = cur_len;
+ }
+
+ /* Filter out local */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i, (connection_is_local(conn)));
+
+ /* Policy filtering : next hops */
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_WIRED)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_WIRED)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_WIFI)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_WIFI)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_CELLULAR)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_CELLULAR)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ nexthops_disable_if(
+ nexthops, i,
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ });
+
+ if (nexthops_get_curlen(nexthops) == 0) {
+ DEBUG("After REQUIRE/PROHIBIT pruning, num=%d/%d",
+ nexthops_get_curlen(nexthops), nexthops_get_len(nexthops));
+ return nexthops;
+ }
+
+ /* We have at least one matching next hop, implement heuristic */
+
+ /*
+ * As VPN connections might trigger duplicate uses of one interface, we start
+ * by filtering out interfaces based on trust status.
+ */
+ flags = nexthops->flags;
+
+ if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) ||
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PREFER)) {
+ /* Try to filter out NON TRUSTED faces */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ (!connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ });
+
+ if ((nexthops_get_curlen(nexthops) == 0) &&
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE)) {
+ return nexthops;
+ }
+
+ } else {
+ /* Try to filter out TRUSTED faces */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ (connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ });
+ }
+
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+
+ /* Other preferences */
+ if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_AVOID) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_has_tag(conn, POLICY_TAG_WIRED));
+ });
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_AVOID) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_has_tag(conn, POLICY_TAG_WIFI));
+ });
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_AVOID) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_has_tag(conn, POLICY_TAG_CELLULAR));
+ });
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+ }
+
+ if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PREFER) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ !connection_has_tag(conn, POLICY_TAG_WIRED));
+ });
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PREFER) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ !connection_has_tag(conn, POLICY_TAG_WIFI));
+ });
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PREFER) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ !connection_has_tag(conn, POLICY_TAG_CELLULAR));
+ });
+ if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags;
+ }
+
+ DEBUG("[fib_entry_filter_nexthops] before face priority num=%d/%d",
+ nexthops_get_curlen(nexthops), nexthops_get_len(nexthops));
+
+ /* Priority */
+ uint32_t max_priority = 0;
+ nexthops_foreach(nexthops, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ uint32_t priority = connection_get_priority(conn);
+ if (priority > max_priority) max_priority = priority;
+ });
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_get_priority(conn) < max_priority);
+ });
+
+ DEBUG("[fib_entry_filter_nexthops] result num=%d/%d",
+ nexthops_get_curlen(nexthops), nexthops_get_len(nexthops));
+
+ return nexthops;
+}
+
+/*
+ * Update available next hops following policy update.
+ *
+ * The last nexthop parameter is only used if needed, otherwise the pointer to
+ * fib entry is returned to avoid an useless copy
+ */
+nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *entry,
+ unsigned ingress_id,
+ nexthops_t *new_nexthops) {
+ // DEBUG("[fib_entry_get_available_nexthops]");
+
+ connection_table_t *table = forwarder_get_connection_table(entry->forwarder);
+
+ /*
+ * Give absolute preference to local faces, with no policy, unless
+ * ingress_id == ~0, which means we are searching faces on which to
+ * advertise our prefix
+ */
+ if (ingress_id == ~0) {
+ assert(new_nexthops);
+ /* We create a nexthop structure based on connections */
+ // XXX This should be done close to where it is needed
+ connection_t *connection;
+ 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);
+ nexthops_inc(new_nexthops);
+ });
+
+#ifdef WITH_POLICY
+ return fib_entry_filter_nexthops(entry, new_nexthops, ingress_id, false);
+#else
+ return new_nexthops;
+#endif
+ }
+
+#ifdef WITH_POLICY
+ return fib_entry_filter_nexthops(entry, fib_entry_get_nexthops(entry),
+ ingress_id, true);
+#else
+ return fib_entry_get_nexthops(entry);
+#endif
+}
+
+hicn_policy_t fib_entry_get_policy(const fib_entry_t *entry) {
+ return entry->policy;
+}
+
+void fib_entry_set_policy(fib_entry_t *entry, hicn_policy_t policy) {
+ entry->policy = policy;
+
+#ifdef WITH_MAPME
+ /*
+ * Skip entries that do not correspond to a producer ( / have a locally
+ * served prefix / have no local connection as next hop)
+ */
+ if (!fib_entry_has_local_nexthop(entry)) return;
+ mapme_t *mapme = forwarder_get_mapme(entry->forwarder);
+ mapme_set_all_adjacencies(mapme, entry);
+#endif /* WITH_MAPME */
+}
+
+#endif /* WITH_POLICY */
+
+void fib_entry_nexthops_add(fib_entry_t *entry, unsigned nexthop) {
+ /*
+ * Nexthop is added to both:
+ * - fib_entry: it is added to the nexthops_t struct, in the elts array.
+ * - strategy: only used to eventually initialize internal state, might be
+ * empty like in the random strategy.
+ */
+ off_t id = nexthops_add(&entry->nexthops, nexthop);
+ strategy_add_nexthop(&entry->strategy, &entry->nexthops, id);
+}
+
+void fib_entry_nexthops_remove(fib_entry_t *entry, unsigned nexthop) {
+ off_t id = nexthops_remove(&entry->nexthops, nexthop);
+ strategy_remove_nexthop(&entry->strategy, &entry->nexthops, id);
+}
+
+nexthops_t *fib_entry_get_nexthops_from_strategy(fib_entry_t *entry,
+ const msgbuf_t *msgbuf,
+ bool is_retransmission) {
+ assert(entry);
+ assert(msgbuf);
+
+ // DEBUG("[fib_entry_get_nexthops_from_strategy]");
+
+ const policy_stats_mgr_t *mgr =
+ forwarder_get_policy_stats_mgr(entry->forwarder);
+ assert(mgr);
+
+ /* Filtering */
+ nexthops_t *nexthops = fib_entry_get_available_nexthops(
+ entry, msgbuf_get_connection_id(msgbuf), NULL);
+ if (nexthops_get_curlen(nexthops) == 0) return nexthops;
+
+#ifdef WITH_POLICY_STATS
+ /*
+ * Update statistics about loss rates. We only detect losses upon
+ * retransmissions, and assume for the computation that the candidate set of
+ * output faces is the same as previously (i.e. does not take into account
+ * event such as face up/down, policy update, etc. Otherwise we would need to
+ * know what was the previous choice !
+ */
+ if (is_retransmission)
+ policy_stats_on_retransmission(mgr, &entry->policy_counters, nexthops);
+#endif /* WITH_POLICY_STATS */
+
+ /*
+ * NOTE: We might want to call a forwarding strategy even with no nexthop to
+ * take a fallback decision.
+ */
+ if (nexthops_get_curlen(nexthops) == 0) return nexthops;
+
+#ifdef WITH_POLICY
+
+ /*
+ * Filter out nexthops with lowest strategy priority.
+ * Initializing at 0 allows to disable nexthops with a negative priority
+ */
+ unsigned max_priority = 0;
+ unsigned i;
+ nexthop_t nexthop;
+ nexthops_enumerate(nexthops, i, nexthop, {
+ (void)nexthop;
+ int priority = nexthops->state[i].priority;
+ if (priority > max_priority) max_priority = priority;
+ });
+ nexthops_enumerate(nexthops, i, nexthop, {
+ int priority = nexthops->state[i].priority;
+ nexthops_disable_if(nexthops, i, (priority < max_priority));
+ });
+
+ /*
+ * If multipath is disabled, we don't offer much choice to the forwarding
+ * strategy, but still go through it for accounting purposes.
+ */
+ hicn_policy_t policy = fib_entry_get_policy(entry);
+ if ((policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_PROHIBIT) ||
+ (policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_AVOID)) {
+ DEBUG(
+ "[fib_entry_get_nexthops_from_strategy] select single nexthops due to "
+ "multipath policy");
+ nexthops_select_first(nexthops);
+ }
+
+#endif /* WITH_POLICY */
+
+ // DEBUG("[fib_entry_get_nexthops_from_strategy] calling lookup_nethops "
+ // "on strategy (num=%d)", nexthops_get_len(nexthops));
+ return strategy_lookup_nexthops(&entry->strategy, nexthops, msgbuf);
+}
+
+void fib_entry_on_data(fib_entry_t *entry, nexthops_t *data_nexthops,
+ const msgbuf_t *msgbuf, Ticks pitEntryCreation,
+ Ticks objReception) {
+ assert(entry);
+ assert(data_nexthops);
+ assert(msgbuf);
+
+#ifdef WITH_POLICY_STATS
+ if (pitEntryCreation != 0) { // if pitEntryCreation we no match in the pit
+ // was found
+ const policy_stats_mgr_t *mgr =
+ forwarder_get_policy_stats_mgr(entry->forwarder);
+ Ticks rtt = objReception - pitEntryCreation;
+ policy_stats_on_data(mgr, &entry->policy_stats, &entry->policy_counters,
+ data_nexthops, msgbuf, rtt);
+ }
+#endif /* WITH_POLICY_STATS */
+
+ if (pitEntryCreation != 0 ||
+ (fib_entry_strategy_type(entry) == STRATEGY_TYPE_BESTPATH)) {
+ strategy_on_data(&entry->strategy, &entry->nexthops, data_nexthops, msgbuf,
+ pitEntryCreation, objReception);
+ }
+}
+
+void fib_entry_on_timeout(fib_entry_t *entry,
+ const nexthops_t *timeout_nexthops) {
+ assert(entry);
+ assert(timeout_nexthops);
+
+#ifdef WITH_POLICY_STATS
+ const policy_stats_mgr_t *mgr =
+ forwarder_get_policy_stats_mgr(entry->forwarder);
+ policy_stats_on_timeout(mgr, &entry->policy_counters, timeout_nexthops);
+#endif /* WITH_POLICY_STATS */
+
+ strategy_on_timeout(&entry->strategy, &entry->nexthops, timeout_nexthops);
+}
+
+const Name *fib_entry_get_prefix(const fib_entry_t *entry) {
+ assert(entry);
+ return &(entry->name);
+}
+
+/*
+ * Return true if we have at least one local connection as next hop
+ */
+bool fib_entry_has_local_nexthop(const fib_entry_t *entry) {
+ connection_table_t *table = forwarder_get_connection_table(entry->forwarder);
+
+ unsigned nexthop;
+ nexthops_foreach(fib_entry_get_nexthops(entry), nexthop, {
+ const connection_t *conn = connection_table_at(table, nexthop);
+ /* Ignore non-local connections */
+ if (!connection_is_local(conn)) continue;
+ return true;
+ });
+ return false;
+}
+
+#ifdef WITH_MAPME
+
+void *fib_entry_get_user_data(const fib_entry_t *entry) {
+ assert(entry);
+
+ return entry->user_data;
+}
+
+void fib_entry_set_user_data(fib_entry_t *entry, const void *user_data,
+ void (*user_data_release)(void **)) {
+ assert(entry);
+ assert(user_data);
+ assert(user_data_release);
+
+ entry->user_data = (void *)user_data;
+ entry->user_data_release = user_data_release;
+}
+
+#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h
new file mode 100644
index 000000000..628c4cd4f
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib_entry.h
@@ -0,0 +1,175 @@
+/*
+ * 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 fib_entry.h
+ * @brief A forwarding entry in the FIB table
+ *
+ * A Forwarding Information Base (FIB) entry (fib_entry_t) is a
+ * set of nexthops for a name. It also indicates the forwarding strategy.
+ *
+ * Each nexthop contains the ConnectionId assocaited with it. This could be
+ * something specific like a MAC address or point-to-point tunnel. Or, it
+ * could be something general like a MAC group address or ip multicast overlay.
+ *
+ * See strategy.h for a description of forwarding strategies.
+ * In short, a strategy is the algorithm used to select one or more nexthops
+ * from the set of available nexthops.
+ *
+ * Each nexthop also contains a void* to a forwarding strategy data container.
+ * This allows a strategy to keep proprietary information about each nexthop.
+ *
+ *
+ */
+
+#ifndef fib_entry_h
+#define fib_entry_h
+
+#include "name.h"
+#include "strategy.h"
+#include "msgbuf.h"
+#include "nexthops.h"
+#include "policy_stats.h"
+
+typedef struct {
+ Name name;
+ unsigned refcount;
+ nexthops_t nexthops;
+ strategy_entry_t strategy;
+
+ const void *forwarder;
+
+#ifdef WITH_POLICY
+ hicn_policy_t policy;
+#endif /* WITH_POLICY */
+
+ policy_counters_t policy_counters;
+ policy_stats_t policy_stats;
+
+#ifdef WITH_MAPME
+ /* In case of no multipath, this stores the previous decision taken by policy.
+ * As the list of nexthops is not expected to change, we can simply store the
+ * flags */
+ uint_fast32_t prev_nexthops_flags;
+ void *user_data;
+ void (*user_data_release)(void **user_data);
+#endif /* WITH_MAPME */
+} fib_entry_t;
+
+#define _fib_entry_var(x) _fib_entry_##x
+
+#define fib_entry_strategy_type(fib_entry) ((fib_entry)->strategy.type)
+
+#define fib_entry_get_nexthops(fib_entry) (&(fib_entry)->nexthops)
+#define fib_entry_nexthops_len(fib_entry) \
+ (nexthops_get_len(&(fib_entry)->nexthops))
+#define fib_entry_nexthops_curlen(fib_entry) \
+ (nexthops_curlen(&(fib_entry)->nexthops))
+#define fib_entry_get_nexthop(fib_entry, i) ((fib_entry)->nexthops.elts[i])
+#define fib_entry_foreach_nexthop(fib_entry, nexthop, BODY) \
+ nexthops_foreach(fib_entry->nexthops, BODY)
+
+#define fib_entry_nexthops_changed(fib_entry) \
+ ((fib_entry)->prev_nexthops_flags == fib_entry_get_nexthops(fib_entry)->flags)
+
+#define fib_entry_set_prev_nexthops(fib_entry) \
+ ((fib_entry)->prev_nexthops_flags = fib_entry_get_nexthops(fib_entry)->flags)
+
+struct forwarder_s;
+fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type,
+ strategy_options_t *strategy_options,
+ const struct forwarder_s *table);
+
+void fib_entry_free(fib_entry_t *entry);
+
+void fib_entry_add_strategy_options(fib_entry_t *entry,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options);
+
+void fib_entry_set_strategy(fib_entry_t *fib_entry,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options);
+
+void fib_entry_nexthops_add(fib_entry_t *fib_entry, unsigned nexthop);
+
+void fib_entry_nexthops_remove(fib_entry_t *fib_entry, unsigned nexthop);
+
+size_t fib_entry_NexthopCount(const fib_entry_t *fib_entry);
+
+/**
+ * @function fib_entry_nexthops_get
+ * @abstract Returns the nexthop set of the FIB entry. You must Acquire if it
+ * will be saved.
+ * @discussion
+ * Returns the next hop set for the FIB entry.
+ */
+const nexthops_t *fib_entry_nexthops_get(const fib_entry_t *fib_entry);
+
+const nexthops_t *fib_entry_nexthops_getFromForwardingStrategy(
+ fib_entry_t *fib_entry, const msgbuf_t *interest_msgbuf,
+ bool is_retransmission);
+
+void fib_entry_on_data(fib_entry_t *fib_entry, nexthops_t *nexthops,
+ const msgbuf_t *object_msgbuf, Ticks pit_entry_creation,
+ Ticks data_reception);
+
+#ifdef WITH_POLICY
+hicn_policy_t fib_entry_get_policy(const fib_entry_t *fib_entry);
+void fib_entry_reconsider_policy(fib_entry_t *fib_entry);
+void fib_entry_set_policy(fib_entry_t *fib_entry, hicn_policy_t policy);
+void fib_entry_update_stats(fib_entry_t *fib_entry, uint64_t now);
+#endif /* WITH_POLICY */
+
+nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *fib_entry,
+ unsigned in_connection,
+ nexthops_t *new_nexthops);
+void fib_entry_on_timeout(fib_entry_t *fib_entry, const nexthops_t *egressId);
+nexthops_t *fib_entry_get_nexthops_from_strategy(
+ fib_entry_t *fib_entry, const msgbuf_t *interest_msgbuf,
+ bool is_retransmission);
+
+/**
+ * @function fib_entry_get_prefix
+ * @abstract Returns a copy of the prefix.
+ * @return A reference counted copy that you must destroy
+ */
+const Name *fib_entry_get_prefix(const fib_entry_t *fib_entry);
+
+bool fib_entry_has_local_nexthop(const fib_entry_t *entry);
+
+#ifdef WITH_MAPME
+
+/**
+ * @function fib_entry_get_user_data
+ * @abstract Returns user data associated to the FIB entry.
+ * @param [in] fib_entry - Pointer to the FIB entry.
+ * @return User data as a void pointer
+ */
+void *fib_entry_get_user_data(const fib_entry_t *fib_entry);
+
+/**
+ * @function fib_entry_get_user_data
+ * @abstract Associates user data and release callback to a FIB entry.
+ * @param [in] fib_entry - Pointer to the FIB entry.
+ * @param [in] user_data - Generic pointer to user data
+ * @param [in@ user_data_release - Callback used to release user data upon
+ * change of FIB entry removal.
+ */
+void fib_entry_set_user_data(fib_entry_t *fib_entry, const void *user_data,
+ void (*user_data_release)(void **));
+
+#endif /* WITH_MAPME */
+
+#endif // fib_entry_h
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 94e8cc885..37502f3ac 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,6 +23,15 @@
* the event scheduler
*/
+/* Bypass FIB and send packet one by one */
+//#define BYPASS_FIB 1
+
+/* Send packets one by one : only effective if FIB is not bypassed */
+//#define USE_SEND_PACKET 1
+
+/* Batch sending: only if the previous option is undefined */
+#define USE_QUEUE true
+
#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
@@ -30,8 +39,7 @@
#endif
#include <errno.h>
#include <fcntl.h>
-#include <signal.h>
-#include <hicn/hicn-light/config.h>
+//#include <hicn/hicn-light/config.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -41,90 +49,108 @@
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/logging/parc_LogReporterTextStdout.h>
-
-#include <hicn/core/connectionManager.h>
-#include <hicn/core/connectionTable.h>
-#include <hicn/core/dispatcher.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/messagePacketType.h>
+#include "connection_table.h"
+#include "fib.h"
+#include "forwarder.h"
+#include "listener_table.h"
#ifdef WITH_MAPME
-#include <hicn/core/mapme.h>
+#include "mapme.h"
#endif /* WITH_MAPME */
-#include <hicn/config/configuration.h>
-#include <hicn/config/configurationFile.h>
-#include <hicn/config/configurationListeners.h>
-#include <hicn/processor/messageProcessor.h>
+#include "msgbuf.h"
+#include "msgbuf_pool.h"
+#include "packet_cache.h"
+#include "../config/configuration.h"
+// #include "../config/configuration_file.h"
+#include "../config/commands.h"
+#include "../io/base.h" // MAX_MSG
+
+#ifdef WITH_POLICY_STATS
+#include <hicn/core/policy_stats.h>
+#endif /* WITH_POLICY_STATS */
#include <hicn/core/wldr.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;
-#include <parc/assert/parc_Assert.h>
-
-// the router's clock frequency (we now use the monotonic clock)
-#define HZ 1000
-
-// these will all be a little off because its all integer division
-#define MSEC_PER_TICK (1000 / HZ)
-#define USEC_PER_TICK (1000000 / HZ)
-#define NSEC_PER_TICK ((1000000000ULL) / HZ)
-#define MSEC_TO_TICKS(msec) \
- ((msec < FC_MSEC_PER_TICK) ? 1 : msec / FC_MSEC_PER_TICK)
-#define NSEC_TO_TICKS(nsec) ((nsec < NSEC_PER_TICK) ? 1 : nsec / NSEC_PER_TICK)
-
-struct forwarder {
- Dispatcher *dispatcher;
-
- uint16_t server_port;
+ // used by seed48 and nrand48
+ unsigned short seed[3];
- PARCEventSignal *signal_int;
- PARCEventSignal *signal_term;
-#ifndef _WIN32
- PARCEventSignal *signal_usr1;
-#endif
- PARCEventTimer *keepalive_event;
+ connection_table_t *connection_table;
+ listener_table_t *listener_table;
+ configuration_t *config;
- // will skew the virtual clock forward. In normal operaiton, it is 0.
- Ticks clockOffset;
+ pkt_cache_t *pkt_cache;
+ fib_t *fib;
+ msgbuf_pool_t *msgbuf_pool;
- unsigned nextConnectionid;
- Messenger *messenger;
- ConnectionManager *connectionManager;
- ConnectionTable *connectionTable;
- ListenerSet *listenerSet;
- Configuration *config;
+#ifdef WITH_MAPME
+ mapme_t *mapme;
+#endif /* WITH_MAPME */
- // we'll eventually want to setup a threadpool of these
- MessageProcessor *processor;
+ bool store_in_cs;
+ bool serve_from_cs;
- Logger *logger;
+ forwarder_stats_t stats;
+#ifdef WITH_POLICY_STATS
+ policy_stats_mgr_t policy_stats_mgr;
+#endif /* WITH_POLICY_STATS */
- PARCClock *clock;
+ /*
+ * 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;
-#if !defined(__APPLE__)
- hicn_socket_helper_t
- *hicnSocketHelper; // state required to manage hicn connections
-#endif
- // used by seed48 and nrand48
- unsigned short seed[3];
+ // msgbuf_t msgbuf; /* Storage for msgbuf, which are currently processed 1 by
+ // 1 */
-#ifdef WITH_MAPME
- MapMe *mapme;
-#endif /* WITH_MAPME */
+ subscription_table_t *subscriptions;
};
-// signal traps through the event scheduler
-static void _signal_cb(int, PARCEventType, void *);
-
-// A no-op keepalive to prevent Libevent from exiting the dispatch loop
-static void _keepalive_cb(int, PARCEventType, void *);
-
/**
* Reseed our pseudo-random number generator.
*/
-static void forwarder_Seed(Forwarder *forwarder) {
+static void forwarder_seed(forwarder_t *forwarder) {
#ifndef _WIN32
int fd;
ssize_t res;
@@ -150,452 +176,990 @@ static void forwarder_Seed(Forwarder *forwarder) {
#endif
}
-Logger *forwarder_GetLogger(const Forwarder *forwarder) {
- return forwarder->logger;
-}
+forwarder_t *forwarder_create(configuration_t *configuration) {
+ forwarder_t *forwarder = malloc(sizeof(forwarder_t));
+ if (!forwarder) goto ERR_MALLOC;
-// ============================================================================
-// Setup and destroy section
+ forwarder_seed(forwarder);
+ srand(forwarder->seed[0] ^ forwarder->seed[1] ^ forwarder->seed[2]);
-Forwarder *forwarder_Create(Logger *logger) {
- Forwarder *forwarder = parcMemory_AllocateAndClear(sizeof(Forwarder));
- parcAssertNotNull(forwarder, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Forwarder));
- memset(forwarder, 0, sizeof(Forwarder));
- forwarder_Seed(forwarder);
+ forwarder->config = configuration;
- forwarder->clock = parcClock_Monotonic();
- forwarder->clockOffset = 0;
+ forwarder->listener_table = listener_table_create();
+ if (!forwarder->listener_table) goto ERR_LISTENER_TABLE;
- if (logger) {
- forwarder->logger = logger_Acquire(logger);
- logger_SetClock(forwarder->logger, forwarder->clock);
- } else {
- PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
- forwarder->logger = logger_Create(reporter, forwarder->clock);
- parcLogReporter_Release(&reporter);
- }
+ forwarder->connection_table = connection_table_create();
+ if (!forwarder->connection_table) goto ERR_CONNECTION_TABLE;
- forwarder->nextConnectionid = 1;
- forwarder->dispatcher = dispatcher_Create(forwarder->logger);
- forwarder->messenger = messenger_Create(forwarder->dispatcher);
- forwarder->connectionManager = connectionManager_Create(forwarder);
- forwarder->connectionTable = connectionTable_Create();
- forwarder->listenerSet = listenerSet_Create();
- forwarder->config = configuration_Create(forwarder);
- forwarder->processor = messageProcessor_Create(forwarder);
-
- forwarder->signal_term = dispatcher_CreateSignalEvent(
- forwarder->dispatcher, _signal_cb, forwarder, SIGTERM);
- dispatcher_StartSignalEvent(forwarder->dispatcher, forwarder->signal_term);
-
- forwarder->signal_int = dispatcher_CreateSignalEvent(
- forwarder->dispatcher, _signal_cb, forwarder, SIGINT);
- dispatcher_StartSignalEvent(forwarder->dispatcher, forwarder->signal_int);
-#ifndef _WIN32
- forwarder->signal_usr1 = dispatcher_CreateSignalEvent(
- forwarder->dispatcher, _signal_cb, forwarder, SIGPIPE);
- dispatcher_StartSignalEvent(forwarder->dispatcher, forwarder->signal_usr1);
-#endif
+ forwarder->fib = fib_create(forwarder);
+ if (!forwarder->fib) goto ERR_FIB;
-#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && \
- defined(PUNTING)
- forwarder->hicnSocketHelper = hicn_create();
- if (!forwarder->hicnSocketHelper)
- goto ERR_SOCKET;
-#endif /* __APPLE__ */
+ forwarder->msgbuf_pool = msgbuf_pool_create();
+ if (!forwarder->msgbuf_pool) goto ERR_PACKET_POOL;
-#ifdef WITH_MAPME
- if (!(mapme_create(&forwarder->mapme, forwarder)))
- goto ERR_MAPME;
-#endif /* WITH_MAPME */
+ size_t objectStoreSize = configuration_get_cs_size(configuration);
+ forwarder->pkt_cache = pkt_cache_create(objectStoreSize);
+ if (!forwarder->pkt_cache) goto ERR_PKT_CACHE;
+ forwarder->subscriptions = subscription_table_create();
+ if (!forwarder->subscriptions) goto ERR_SUBSCRIPTION;
- /* ignore child */
-#ifndef _WIN32
- signal(SIGCHLD, SIG_IGN);
-
- /* ignore tty signals */
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
-#endif
+ // the two flags for the cs are set to true by default. If the cs
+ // is active it always work as expected unless the use modifies this
+ // values using controller
+ if (objectStoreSize != 0) {
+ forwarder->store_in_cs = true;
+ forwarder->serve_from_cs = true;
+ }
- // We no longer use this for ticks, but we need to have at least one event
- // schedule to keep Libevent happy.
+#ifdef WITH_MAPME
+ forwarder->mapme = mapme_create(forwarder);
+ if (!forwarder->mapme) goto ERR_MAPME;
+#endif /* WITH_MAPME */
- struct timeval wtnow_timeout;
- timerclear(&wtnow_timeout);
+#ifdef WITH_POLICY_STATS
+ if (policy_stats_mgr_initialize(&forwarder->policy_stats_mgr, forwarder) < 0)
+ goto ERR_MGR;
+#endif /* WITH_POLICY_STATS */
- wtnow_timeout.tv_sec = 0;
- wtnow_timeout.tv_usec = 50000; // 20 Hz keepalive
+ memset(&forwarder->stats, 0, sizeof(forwarder_stats_t));
- PARCEventScheduler *base =
- dispatcher_GetEventScheduler(forwarder->dispatcher);
- forwarder->keepalive_event = parcEventTimer_Create(
- base, PARCEventType_Persist, _keepalive_cb, (void *)forwarder);
- parcEventTimer_Start(forwarder->keepalive_event, &wtnow_timeout);
+ forwarder->num_pending_conn = 0;
return forwarder;
+ERR_MGR:
#ifdef WITH_MAPME
ERR_MAPME:
#endif /* WITH_MAPME */
-#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && \
- defined(PUNTING)
- hicn_free(forwarder->hicnSocketHelper);
-ERR_SOCKET:
-#endif
- listenerSet_Destroy(&(forwarder->listenerSet));
- connectionManager_Destroy(&(forwarder->connectionManager));
- connectionTable_Destroy(&(forwarder->connectionTable));
- messageProcessor_Destroy(&(forwarder->processor));
- configuration_Destroy(&(forwarder->config));
- messenger_Destroy(&(forwarder->messenger));
-
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_int));
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_term));
-#ifndef _WIN32
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_usr1));
-#endif
-
- parcClock_Release(&forwarder->clock);
- logger_Release(&forwarder->logger);
- // do the dispatcher last
- dispatcher_Destroy(&(forwarder->dispatcher));
-
- parcMemory_Deallocate((void **)&forwarder);
+ERR_SUBSCRIPTION:
+ subscription_table_free(forwarder->subscriptions);
+ERR_PKT_CACHE:
+ pkt_cache_free(forwarder->pkt_cache);
+
+ msgbuf_pool_free(forwarder->msgbuf_pool);
+ERR_PACKET_POOL:
+ fib_free(forwarder->fib);
+ERR_FIB:
+ connection_table_free(forwarder->connection_table);
+ERR_CONNECTION_TABLE:
+ listener_table_free(forwarder->listener_table);
+ERR_LISTENER_TABLE:
+ free(forwarder);
+ERR_MALLOC:
return NULL;
}
-void forwarder_Destroy(Forwarder **ptr) {
- parcAssertNotNull(ptr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*ptr, "Parameter must dereference to non-null pointer");
- Forwarder *forwarder = *ptr;
-#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && \
- defined(PUNTING)
- hicn_free(forwarder->hicnSocketHelper);
-#endif
- parcEventTimer_Destroy(&(forwarder->keepalive_event));
+void forwarder_free(forwarder_t *forwarder) {
+ assert(forwarder);
- listenerSet_Destroy(&(forwarder->listenerSet));
- connectionManager_Destroy(&(forwarder->connectionManager));
- connectionTable_Destroy(&(forwarder->connectionTable));
- messageProcessor_Destroy(&(forwarder->processor));
- configuration_Destroy(&(forwarder->config));
-
- // the messenger is used by many of the other pieces, so destroy it last
- messenger_Destroy(&(forwarder->messenger));
+ policy_stats_mgr_finalize(&forwarder->policy_stats_mgr);
#ifdef WITH_MAPME
mapme_free(forwarder->mapme);
#endif /* WITH_MAPME */
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_int));
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_term));
-#ifndef _WIN32
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_usr1));
-#endif
+ pkt_cache_free(forwarder->pkt_cache);
+ msgbuf_pool_free(forwarder->msgbuf_pool);
+ fib_free(forwarder->fib);
+ connection_table_free(forwarder->connection_table);
+ listener_table_free(forwarder->listener_table);
+ subscription_table_free(forwarder->subscriptions);
+ configuration_free(forwarder->config);
+ free(forwarder);
+}
- parcClock_Release(&forwarder->clock);
- logger_Release(&forwarder->logger);
+void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port) {
+ assert(forwarder);
+ listener_setup_local(forwarder, port);
+}
- // do the dispatcher last
- dispatcher_Destroy(&(forwarder->dispatcher));
+configuration_t *forwarder_get_configuration(forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->config;
+}
- parcMemory_Deallocate((void **)&forwarder);
- *ptr = NULL;
+subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder) {
+ return forwarder->subscriptions;
}
-void forwarder_SetupAllListeners(Forwarder *forwarder, uint16_t port,
- const char *localPath) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
+connection_table_t *forwarder_get_connection_table(
+ const forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->connection_table;
+}
- configurationListeners_SetupAll(forwarder->config, port, localPath);
+listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->listener_table;
}
-void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- configurationListeners_SetutpLocalIPv4(forwarder->config, port);
+void forwarder_cs_set_store(forwarder_t *forwarder, bool val) {
+ assert(forwarder);
+ forwarder->store_in_cs = val;
}
-void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename) {
- ConfigurationFile *configFile = configurationFile_Create(forwarder, filename);
- if (configFile) {
- configurationFile_Process(configFile);
- configurationFile_Release(&configFile);
- }
+bool forwarder_cs_get_store(forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->store_in_cs;
}
-Configuration *forwarder_GetConfiguration(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->config;
+void forwarder_cs_set_serve(forwarder_t *forwarder, bool val) {
+ assert(forwarder);
+ forwarder->serve_from_cs = val;
}
-// ============================================================================
+bool forwarder_cs_get_serve(forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->serve_from_cs;
+}
+
+void forwarder_cs_set_size(forwarder_t *forwarder, size_t size) {
+ assert(forwarder);
-unsigned forwarder_GetNextConnectionId(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->nextConnectionid++;
+ if (pkt_cache_set_cs_size(forwarder->pkt_cache, size) < 0) {
+ ERROR(
+ "Unable to resize the CS: provided maximum size (%u) is smaller than "
+ "the number of elements currently stored in the CS (%u). Clear the CS "
+ "and retry.",
+ size, pkt_cache_get_cs_size(forwarder->pkt_cache));
+ }
}
-Messenger *forwarder_GetMessenger(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->messenger;
+size_t forwarder_cs_get_size(forwarder_t *forwarder) {
+ assert(forwarder);
+ return pkt_cache_get_cs_size(forwarder->pkt_cache);
}
-Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->dispatcher;
+size_t forwarder_cs_get_num_stale_entries(forwarder_t *forwarder) {
+ assert(forwarder);
+ return pkt_cache_get_num_cs_stale_entries(forwarder->pkt_cache);
}
-#ifdef WITH_POLICY
-ConnectionTable *forwarder_GetConnectionTable(const Forwarder *forwarder) {
+void forwarder_cs_clear(forwarder_t *forwarder) {
+ assert(forwarder);
+
+ pkt_cache_cs_clear(forwarder->pkt_cache);
+}
+
+/**
+ * @function forwarder_Drop
+ * @abstract Whenever we "drop" a message, increment counters
+ * @discussion
+ * This is a bookkeeping function. It increments the appropriate counters.
+ *
+ * The default action for a message is to destroy it in
+ * <code>forwarder_Receive()</code>, so this function does not need to do
+ * that.
+ *
+ */
+static ssize_t forwarder_drop(forwarder_t *forwarder, off_t msgbuf_id) {
+ forwarder->stats.countDropped++;
+
+ const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ const msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ switch (msgbuf_get_type(msgbuf)) {
+ case MSGBUF_TYPE_INTEREST:
+ forwarder->stats.countInterestsDropped++;
+ break;
+
+ case MSGBUF_TYPE_DATA:
+ forwarder->stats.countObjectsDropped++;
+ break;
+
+ default:
+ forwarder->stats.countOtherDropped++;
+ break;
+ }
+
+ return msgbuf_get_len(msgbuf);
+ // dont destroy message here, its done at end of receive
+}
+
+#ifndef BYPASS_FIB
+/*
+ * If the hoplimit is equal to 0, then we may only forward it to local
+ * applications. Otherwise, we may forward it off the system.
+ *
+ */
+
+static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder,
+ off_t msgbuf_id,
+ unsigned conn_id) {
+ connection_table_t *table = forwarder_get_connection_table(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);
+
+ if (!conn) {
+ forwarder->stats.countDroppedConnectionNotFound++;
+ WARN("forward msgbuf %lu to interface %u not found (count %u)", msgbuf_id,
+ conn_id, forwarder->stats.countDroppedConnectionNotFound);
+ return forwarder_drop(forwarder, msgbuf_id);
+ }
+
+ /* Always queue the packet... */
+ // DEBUG("Queueing packet\n");
+
+#if defined(USE_SEND_PACKET) || !defined(__linux__)
+
+ // Here we need to update the path label of a data packet before send
+ // it. The path label update can be done here because the packet is sent
+ // directly to the socket
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
+ msgbuf_update_pathlabel(msgbuf, connection_get_id(conn));
+
+ bool success = connection_send_packet(conn, msgbuf_get_packet(msgbuf),
+ msgbuf_get_len(msgbuf));
#else
-ConnectionTable *forwarder_GetConnectionTable(Forwarder *forwarder) {
-#endif /* WITH_POLICY */
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->connectionTable;
+
+ // In this case we cannot update the path label even if it is need because
+ // the packet is not copied and only the packet id is enqueued to the ring
+ // buffer associated the output interface. If the path label is updated here
+ // all data packets get delivered to the next hop with the same label that is
+ // associated to the last connection used. For this reason the path label
+ // update must be done before the packet is actually sent inside the different
+ // IO implementations.
+ bool success = connection_send(conn, msgbuf_id, USE_QUEUE);
+
+#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 (!success) {
+ forwarder->stats.countSendFailures++;
+
+ DEBUG("forward msgbuf %llu to interface %u send failure (count %u)",
+ msgbuf_id, conn_id, forwarder->stats.countSendFailures);
+ return forwarder_drop(forwarder, msgbuf_id);
+ }
+
+ switch (msgbuf_get_type(msgbuf)) {
+ case MSGBUF_TYPE_INTEREST:
+ forwarder->stats.countInterestForwarded++;
+ break;
+
+ case MSGBUF_TYPE_DATA:
+ forwarder->stats.countObjectsForwarded++;
+ break;
+
+ default:
+ break;
+ }
+
+ TRACE("forward msgbuf %p to interface %u", msgbuf, conn_id);
+ return msgbuf_get_len(msgbuf);
}
-ListenerSet *forwarder_GetListenerSet(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->listenerSet;
+/**
+ * @function forwarder_forward_to_nexthops
+ * @abstract Try to forward to each nexthop listed in the NumberSet
+ * @discussion
+ * Will not forward to the ingress connection.
+ *
+ * @return The number of nexthops tried
+ */
+static unsigned forwarder_forward_to_nexthops(forwarder_t *forwarder,
+ off_t msgbuf_id,
+ const nexthops_t *nexthops) {
+ // DEBUG("[forwarder_forward_to_nexthops] num=%d/%d",
+ // nexthops_get_curlen(nexthops), nexthops_get_len(nexthops));
+ unsigned forwardedCopies = 0;
+
+ const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ unsigned ingressId = msgbuf_get_connection_id(msgbuf);
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ // DEBUG("[forwarder_forward_to_nexthops] - nexthop = %d");
+ if (nexthop == ingressId) continue;
+
+ forwardedCopies++;
+ // INFO("[forwarder_forward_to_nexthops] - nexthop = %d OK", nexthop);
+ forwarder_forward_via_connection(forwarder, msgbuf_id, nexthop);
+ });
+
+ return forwardedCopies;
}
-void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- messageProcessor_SetCacheStoreFlag(forwarder->processor, val);
+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));
+
+ const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
+
+ fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf);
+ if (!fib_entry) return false;
+
+ // DEBUG("[forwarder] Getting nexthops from strategy");
+ nexthops_t *nexthops = fib_entry_get_nexthops_from_strategy(
+ fib_entry, msgbuf, verdict == PKT_CACHE_VERDICT_RETRANSMIT_INTEREST);
+
+ if (nexthops_get_curlen(nexthops) == 0) {
+ ERROR("Message %p returned an empty next hop set", msgbuf);
+ 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;
+ }
+
+ pit_entry_set_fib_entry(pit_entry, fib_entry);
+
+ // this requires some additional checks. It may happen that some of the output
+ // faces selected by the forwarding strategy are not usable. So far all the
+ // forwarding strategy return only valid faces (or an empty list)
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ // DEBUG("Adding egress to PIT for nexthop %d", nexthop);
+ pit_entry_egress_add(pit_entry, nexthop);
+ });
+
+ if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <= 0) {
+ // this should never happen
+ ERROR("Message %p returned an empty next hop set", msgbuf);
+ return false;
+ }
+
+ return true;
}
-bool forwarder_GetChacheStoreFlag(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return messageProcessor_GetCacheStoreFlag(forwarder->processor);
+#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) {
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, interest_msgbuf_id);
+
+ 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
+ if (verdict == PKT_CACHE_VERDICT_FORWARD_DATA) {
+ assert(forwarder->serve_from_cs == true);
+
+ msgbuf_t *interest_msgbuf = msgbuf_pool_at(msgbuf_pool, interest_msgbuf_id);
+ 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));
+
+ // - Try to forward the interest
+ } else if (!forwarder_forward_via_fib(forwarder, interest_msgbuf_id, verdict,
+ entry)) {
+ 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 msgbuf_get_len(msgbuf);
+}
+
+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;
+
+ switch (verdict) {
+ case PKT_CACHE_VERDICT_FORWARD_INTEREST:
+ DEBUG(
+ "Message will be added to PIT (expiration=%ld), "
+ "if nexthops are available",
+ expiration);
+ break;
+
+ case PKT_CACHE_VERDICT_AGGREGATE_INTEREST:
+ forwarder->stats.countInterestsAggregated++;
+ DEBUG("Message aggregated in PIT (expiration=%ld)", expiration);
+ break;
+
+ case PKT_CACHE_VERDICT_RETRANSMIT_INTEREST:
+ forwarder->stats.countInterestsRetransmitted++;
+ DEBUG("Message retransmitted (expiration=%ld)", expiration);
+ break;
+
+ case PKT_CACHE_VERDICT_FORWARD_DATA:
+ forwarder->stats.countInterestsSatisfiedFromStore++;
+ DEBUG("Message satisfied from content store (expiration=%ld)",
+ expiration);
+ break;
+
+ case PKT_CACHE_VERDICT_INTEREST_EXPIRED_FORWARD_INTEREST:
+ forwarder->stats.countInterestsExpired++;
+ DEBUG("Message replaced expired interest (expiration=%ld)", expiration);
+ break;
+
+ case PKT_CACHE_VERDICT_DATA_EXPIRED_FORWARD_INTEREST:
+ forwarder->stats.countDataExpired++;
+ DEBUG("Message replaced expired data (expiration=%ld)", expiration);
+ break;
+
+ case PKT_CACHE_VERDICT_ERROR:
+ ERROR("Inivalid packet cache content");
+ break;
+
+ default:
+ break;
+ }
}
-void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- messageProcessor_SetCacheServeFlag(forwarder->processor, val);
+/**
+ * @function forwarder_process_interest
+ * @abstract Receive an interest from the network
+ * @discussion
+ * (1) if interest in the PIT, aggregate in PIT
+ * (2) if interest in the ContentStore, reply
+ * (3) if in the FIB, forward
+ * (4) drop
+ *
+ */
+static ssize_t forwarder_process_interest(forwarder_t *forwarder,
+ off_t msgbuf_id) {
+ assert(forwarder);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
+
+ forwarder->stats.countReceived++;
+ forwarder->stats.countInterestsReceived++;
+
+ 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));
+ 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);
+
+ return _forwarder_forward_upon_interest(
+ forwarder, msgbuf_pool, data_msgbuf_id, msgbuf_id, entry, verdict);
}
-bool forwarder_GetChacheServeFlag(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return messageProcessor_GetCacheServeFlag(forwarder->processor);
+static void _forwarder_log_on_data(forwarder_t *forwarder,
+ pkt_cache_verdict_t verdict) {
+ switch (verdict) {
+ case PKT_CACHE_VERDICT_FORWARD_DATA:
+ DEBUG("Message added to CS from PIT");
+ break;
+ case PKT_CACHE_VERDICT_STORE_DATA:
+ DEBUG("Message added to CS (expired or no previous interest pending)");
+ break;
+ case PKT_CACHE_VERDICT_CLEAR_DATA:
+ break;
+ case PKT_CACHE_VERDICT_UPDATE_DATA:
+ DEBUG("Message updated in CS");
+ break;
+ case PKT_CACHE_VERDICT_IGNORE_DATA:
+ DEBUG("Message not stored in CS");
+ break;
+ case PKT_CACHE_VERDICT_ERROR:
+ ERROR("Inivalid packet cache content");
+ break;
+ default:
+ break;
+ }
}
-void forwarder_ReceiveCommand(Forwarder *forwarder, command_id command,
- struct iovec *message, unsigned ingressId) {
- configuration_ReceiveCommand(forwarder->config, command, message, ingressId);
+/**
+ * @function forwarder_process_data
+ * @abstract Process an in-bound content object
+ * @discussion
+ * (1) If it does not match anything in the PIT, drop it
+ * (2) Add to Content Store
+ * (3) Reverse path forward via PIT entries
+ *
+ * @param <#param1#>
+ */
+static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) {
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ WITH_DEBUG({
+ char *nameString = name_ToString(msgbuf_get_name(msgbuf));
+ 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_table_get_by_id(table, msgbuf_get_connection_id(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);
+
+ _forwarder_log_on_data(forwarder, verdict);
+
+ 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++;
+ DEBUG("Message %lu did not match PIT, no reverse path", msgbuf_id);
+
+ // MOVE PROBE HOOK ELSEWHERE
+ // XXX relationship with forwarding strategy... insert hooks
+ // if the packet is a probe we need to analyze it
+ // NOTE : probes are not stored in PIT
+ if (msgbuf_is_probe(msgbuf)) {
+ fib_entry_t *entry = fib_match_message(forwarder->fib, msgbuf);
+ if (entry && fib_entry_strategy_type(entry) == STRATEGY_TYPE_BESTPATH) {
+ nexthops_t probe_nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&probe_nexthops, msgbuf_get_connection_id(msgbuf));
+ fib_entry_on_data(entry, &probe_nexthops, msgbuf, 0, ticks_now());
+ // XXX TODO CONFIRM WE DON'T EXIT HERE ?
+ }
+ }
+ forwarder_drop(forwarder, msgbuf_id);
+ } else {
+ // Reverse path forward via PIT entries
+ forwarder_forward_to_nexthops(forwarder, msgbuf_id, ingressSetUnion);
+ free(ingressSetUnion);
+ }
+
+ return msgbuf_get_len(msgbuf);
}
-void forwarder_Receive(Forwarder *forwarder, Message *message) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
+void forwarder_flush_connections(forwarder_t *forwarder) {
+ // DEBUG("[forwarder_flush_connections]");
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
- // this takes ownership of the message, so we're done here
+ for (unsigned i = 0; i < forwarder->num_pending_conn; i++) {
+ unsigned conn_id = forwarder->pending_conn[i];
+ const 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;
+ // DEBUG("[forwarder_flush_connections] done");
+}
+// XXX move to wldr file, worst case in connection.
+void forwarder_apply_wldr(const forwarder_t *forwarder, const msgbuf_t *msgbuf,
+ connection_t *connection) {
// this are the checks needed to implement WLDR. We set wldr only on the STAs
- // and we let the AP to react according to choise of the client.
+ // and we let the AP to react according to choice of the client.
// if the STA enables wldr using the set command, the AP enable wldr as well
// otherwise, if the STA disable it the AP remove wldr
// WLDR should be enabled only on the STAs using the command line
// TODO
// disable WLDR command line on the AP
- const Connection *conn = connectionTable_FindById(
- forwarder->connectionTable, message_GetIngressConnectionId(message));
-
- if (!conn) {
- /*
- * Drop is a static method in messageProcessor which might or might not need
- * to be called for accounting purposes. This call was initially absent so
- * the behaviour was kept like this, as this situation is unlikely. We need
- * to release memory though, as this is not done in Drop anyways.
- */
- //messageProcessor_Drop(forwarder->processor, message);
- message_Release(&message);
- return;
- }
-
- if (message_HasWldr(message)) {
- if (connection_HasWldr(conn)) {
+ if (msgbuf_has_wldr(msgbuf)) {
+ if (connection_has_wldr(connection)) {
// case 1: WLDR is enabled
- connection_DetectLosses((Connection *)conn, message);
- } else if (!connection_HasWldr(conn) &&
- connection_WldrAutoStartAllowed(conn)) {
+ connection_wldr_detect_losses(connection, msgbuf);
+ } else if (!connection_has_wldr(connection) &&
+ connection_wldr_autostart_is_allowed(connection)) {
// case 2: We are on an AP. We enable WLDR
- connection_EnableWldr((Connection *)conn);
- connection_DetectLosses((Connection *)conn, message);
+ connection_wldr_enable(connection, true);
+ connection_wldr_detect_losses(connection, msgbuf);
}
// case 3: Ignore WLDR
} else {
- if (connection_HasWldr(conn) && connection_WldrAutoStartAllowed(conn)) {
+ if (connection_has_wldr(connection) &&
+ connection_wldr_autostart_is_allowed(connection)) {
// case 1: STA do not use WLDR, we disable it
- connection_DisableWldr((Connection *)conn);
+ connection_wldr_enable(connection, false);
}
}
-
- messageProcessor_Receive(forwarder->processor, message);
}
-Ticks forwarder_GetTicks(const Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return parcClock_GetTime(forwarder->clock) + forwarder->clockOffset;
-}
+bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix,
+ unsigned ingress_id) {
+ assert(forwarder);
+ assert(prefix);
-Ticks forwarder_NanosToTicks(uint64_t nanos) { return NSEC_TO_TICKS(nanos); }
+ configuration_t *config = forwarder_get_configuration(forwarder);
-uint64_t forwarder_TicksToNanos(Ticks ticks) {
- return (1000000000ULL) * ticks / HZ;
-}
+ char prefix_s[MAXSZ_IP_PREFIX];
+ int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) return false;
+
+ DEBUG("Adding prefix=%s for conn_id=%d", prefix_s, ingress_id);
-bool forwarder_AddOrUpdateRoute(Forwarder *forwarder,
- add_route_command *control, unsigned ifidx) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(control, "Parameter route must be non-null");
+ // XXX TODO this should store options too
+ strategy_type_t strategy_type = configuration_get_strategy(config, prefix_s);
- // we only have one message processor
- bool res =
- messageProcessor_AddOrUpdateRoute(forwarder->processor, control, ifidx);
+ Name name_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&name_prefix, prefix->family, prefix->address,
+ prefix->len);
+ fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix);
+ if (!entry) {
+ entry = fib_entry_create(&name_prefix, strategy_type, NULL, forwarder);
+ fib_entry_nexthops_add(entry, ingress_id);
+ fib_add(forwarder->fib, entry);
+
+ } else {
+ fib_entry_nexthops_add(entry, ingress_id);
+ }
- return res;
+ return true;
}
+bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix,
+ unsigned ingress_id) {
+ assert(forwarder);
+ assert(prefix);
-bool forwarder_RemoveRoute(Forwarder *forwarder, remove_route_command *control,
- unsigned ifidx) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(control, "Parameter route must be non-null");
+ Name name_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&name_prefix, prefix->family, prefix->address,
+ prefix->len);
+ fib_remove(forwarder->fib, &name_prefix, ingress_id);
- // we only have one message processor
- return messageProcessor_RemoveRoute(forwarder->processor, control, ifidx);
+ return true;
}
#ifdef WITH_POLICY
-bool forwarder_AddOrUpdatePolicy(Forwarder *forwarder,
- add_policy_command *control) {
- parcAssertNotNull(forwarder, "Parameter forwarder must be non-null");
- parcAssertNotNull(control, "Parameter control must be non-null");
+bool forwarder_add_or_update_policy(forwarder_t *forwarder, ip_prefix_t *prefix,
+ hicn_policy_t *policy) {
+ assert(forwarder);
+ assert(prefix);
+ assert(policy);
- return messageProcessor_AddOrUpdatePolicy(forwarder->processor, control);
+ Name name_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&name_prefix, prefix->family, prefix->address,
+ prefix->len);
+ fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix);
+ if (!entry) return false;
+ fib_entry_set_policy(entry, *policy);
+
+ return true;
}
-bool forwarder_RemovePolicy(Forwarder *forwarder, remove_policy_command *control) {
- parcAssertNotNull(forwarder, "Parameter forwarder must be non-null");
- parcAssertNotNull(control, "Parameter control must be non-null");
+bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix) {
+ assert(forwarder);
+ assert(prefix);
+
+ Name name_prefix = EMPTY_NAME;
+ name_CreateFromAddress(&name_prefix, prefix->family, prefix->address,
+ prefix->len);
+ fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix);
+
+ if (!entry) return false;
+
+ fib_entry_set_policy(entry, POLICY_EMPTY);
- return messageProcessor_RemovePolicy(forwarder->processor, control);
+ return true;
}
#endif /* WITH_POLICY */
-void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder,
- unsigned connectionId) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- messageProcessor_RemoveConnectionIdFromRoutes(forwarder->processor,
- connectionId);
+void forwarder_remove_connection_id_from_routes(forwarder_t *forwarder,
+ unsigned connection_id) {
+ assert(forwarder);
+
+ fib_remove_connection_id(forwarder->fib, connection_id);
}
-void forwarder_SetStrategy(Forwarder *forwarder, Name *prefix,
- strategy_type strategy,
- unsigned related_prefixes_len,
- Name **related_prefixes) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(prefix, "Parameter prefix must be non-null");
+void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options) {
+ assert(forwarder);
+ assert(name_prefix);
+ assert(strategy_options);
+ assert(STRATEGY_TYPE_VALID(strategy_type));
+
+ fib_entry_t *entry = fib_contains(forwarder->fib, name_prefix);
+ if (!entry) return;
- processor_SetStrategy(forwarder->processor, prefix, strategy,
- related_prefixes_len, related_prefixes);
+ fib_entry_add_strategy_options(entry, strategy_type, strategy_options);
}
-FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder) {
- return messageProcessor_GetFibEntries(forwarder->processor);
+void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options) {
+ assert(forwarder);
+ assert(name_prefix);
+ assert(STRATEGY_TYPE_VALID(strategy_type));
+ /* strategy_options might be NULL */
+
+ fib_entry_t *entry = fib_contains(forwarder->fib, name_prefix);
+ if (!entry) {
+ // there is no exact match. so if the forwarding strategy is not in the list
+ // of strategies that can be set by the transport, return
+ if (strategy_type != STRATEGY_TYPE_BESTPATH &&
+ strategy_type != STRATEGY_TYPE_REPLICATION) {
+ return;
+ }
+
+ // here it may be the transprot that wants to set the strategy, but it has
+ // no knowledge of the length of the prefix. so we apply the strategy at the
+ // matching fib entry, which later will be the one that will be used to send
+ // interests with this name
+ entry = fib_match_name(forwarder->fib, name_prefix);
+ if (!entry) {
+ return; // no fib match, return
+ }
+ }
+
+ fib_entry_set_strategy(entry, strategy_type, strategy_options);
}
-void forwarder_SetContentObjectStoreSize(Forwarder *forwarder,
- size_t maximumContentStoreSize) {
- messageProcessor_SetContentObjectStoreSize(forwarder->processor,
- maximumContentStoreSize);
+cs_t *forwarder_get_cs(const forwarder_t *forwarder) {
+ assert(forwarder);
+
+ return pkt_cache_get_cs(forwarder->pkt_cache);
}
-void forwarder_ClearCache(Forwarder *forwarder) {
- messageProcessor_ClearCache(forwarder->processor);
+// =======================================================
+
+fib_t *forwarder_get_fib(forwarder_t *forwarder) { return forwarder->fib; }
+
+msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder) {
+ return forwarder->msgbuf_pool;
}
-PARCClock *forwarder_GetClock(const Forwarder *forwarder) {
- return forwarder->clock;
+#ifdef WITH_MAPME
+void forwarder_on_connection_event(const forwarder_t *forwarder,
+ const connection_t *connection,
+ connection_event_t event) {
+ mapme_on_connection_event(forwarder->mapme, connection, event);
}
-#if !defined(__APPLE__)
-hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder) {
- return forwarder->hicnSocketHelper;
+mapme_t *forwarder_get_mapme(const forwarder_t *forwarder) {
+ return forwarder->mapme;
}
-#endif
-// =======================================================
+#endif /* WITH_MAPME */
-static void _signal_cb(int sig, PARCEventType events, void *user_data) {
- Forwarder *forwarder = (Forwarder *)user_data;
+#ifdef WITH_POLICY_STATS
+const policy_stats_mgr_t *forwarder_get_policy_stats_mgr(
+ const forwarder_t *forwarder) {
+ return &forwarder->policy_stats_mgr;
+}
+#endif /* WITH_POLICY_STATS */
- logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning,
- __func__, "signal %d events %d", sig, events);
+/**
+ * @brief Process a packet by creating the corresponding message buffer and
+ * dispatching it to the forwarder for further processing.
+ * @param[in] forwarder Forwarder instance.
+ *
+ */
+// XXX ??? XXX = process for listener as we are resolving connection id
+//
+
+msgbuf_type_t get_type_from_packet(uint8_t *packet) {
+ if (messageHandler_IsTCP(packet)) {
+ if (messageHandler_IsData(packet)) {
+ return MSGBUF_TYPE_DATA;
+ } else if (messageHandler_IsInterest(packet)) {
+ return MSGBUF_TYPE_INTEREST;
+ } else {
+ return MSGBUF_TYPE_UNDEFINED;
+ }
- switch ((int)sig) {
- case SIGTERM:
- logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning,
- __func__, "Caught an terminate signal; exiting cleanly.");
- dispatcher_Stop(forwarder->dispatcher);
- break;
+ } else if (messageHandler_IsWldrNotification(packet)) {
+ return MSGBUF_TYPE_WLDR_NOTIFICATION;
- case SIGINT:
- logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning,
- __func__, "Caught an interrupt signal; exiting cleanly.");
- dispatcher_Stop(forwarder->dispatcher);
- break;
-#ifndef _WIN32
- case SIGUSR1:
- // dump stats
- break;
-#endif
+ } else if (mapme_match_packet(packet)) {
+ return MSGBUF_TYPE_MAPME;
- default:
- break;
- }
-}
+ } else if (*packet == REQUEST_LIGHT) {
+ return MSGBUF_TYPE_COMMAND;
-static void _keepalive_cb(int fd, PARCEventType what, void *user_data) {
- parcAssertTrue(what & PARCEventType_Timeout, "Got unexpected tick_cb: %d",
- what);
- // function is just a keepalive for hicn-light, does not do anything
+ } else {
+ return MSGBUF_TYPE_UNDEFINED;
+ }
}
-#ifdef WITH_MAPME
-FIB *forwarder_getFib(Forwarder *forwarder) {
- return messageProcessor_getFib(forwarder->processor);
+/**
+ * @brief Finalize (i.e. close fd and free internal data structures)
+ * the current connection ("SELF") when the command is received.
+ * The connection cannot be removed inside the command handling
+ * because it is needed to return the ack back.
+ */
+static void _forwarder_finalize_connection_if_self(connection_t *conn,
+ msgbuf_t *msgbuf) {
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ msg_connection_remove_t *msg = (msg_connection_remove_t *)packet;
+ cmd_connection_remove_t *control = &msg->payload;
+
+ if (strcmp(control->symbolic_or_connid, "SELF") == 0)
+ connection_finalize(conn);
}
-void forwarder_onConnectionEvent(Forwarder *forwarder, const Connection *conn, connection_event_t event) {
-//#ifdef WITH_POLICY
-// messageProcessor_onConnectionEvent(forwarder->processor, conn, event);
-//#else
- mapme_onConnectionEvent(forwarder->mapme, conn, event);
-//#endif /* WITH_POLICY */
-}
+ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
+ off_t msgbuf_id, address_pair_t *pair, Ticks now) {
+ assert(forwarder);
+ /* listener can be NULL */
+ assert(msgbuf_id_is_valid(msgbuf_id));
+ assert(pair);
+
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf);
+
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ size_t size = msgbuf_get_len(msgbuf);
+
+ /* Connection lookup */
+ 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;
+
+ assert((conn_id != CONNECTION_ID_UNDEFINED) || listener);
+
+ msgbuf_type_t type = get_type_from_packet(msgbuf_get_packet(msgbuf));
+
+ msgbuf->type = type;
+ msgbuf->connection_id = conn_id;
+ msgbuf->recv_ts = now;
+
+ switch (type) {
+ case MSGBUF_TYPE_INTEREST:
+ if (!connection_id_is_valid(msgbuf->connection_id)) {
+ char *conn_name = connection_table_get_random_name(table);
+ 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));
+ forwarder_apply_wldr(forwarder, msgbuf, connection);
+ forwarder_process_interest(forwarder, msgbuf_id);
+
+ pkt_cache_log(forwarder->pkt_cache);
+ return size;
+
+ case MSGBUF_TYPE_DATA:
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ return forwarder_drop(forwarder, msgbuf_id);
+ msgbuf_init_pathlabel(msgbuf);
+ name_create_from_data(packet, msgbuf_get_name(msgbuf));
+ forwarder_apply_wldr(forwarder, msgbuf, connection);
+ forwarder_process_data(forwarder, msgbuf_id);
+
+ pkt_cache_log(forwarder->pkt_cache);
+ return size;
+
+ case MSGBUF_TYPE_WLDR_NOTIFICATION:
+ if (!connection_id_is_valid(msgbuf->connection_id))
+ return forwarder_drop(forwarder, msgbuf_id);
+ connection_wldr_handle_notification(connection, msgbuf);
+ return size;
+
+ 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);
+ msgbuf->connection_id =
+ listener_create_connection(listener, conn_name, pair);
+ free(conn_name);
+ }
+ mapme_process(forwarder->mapme, msgbuf);
+ return size;
+
+ 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);
+ 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;
+ msgbuf->command.type = msg->header.command_id;
+ if (!command_type_is_valid(msgbuf->command.type)) {
+ ERROR("Invalid command");
+ return 0;
+ }
+
+ size = command_process_msgbuf(forwarder, msgbuf);
+ if (msgbuf->command.type == COMMAND_TYPE_CONNECTION_REMOVE)
+ _forwarder_finalize_connection_if_self(connection, msgbuf);
+ return size;
-void forwarder_ProcessMapMe(Forwarder *forwarder, const uint8_t *msgBuffer,
- unsigned conn_id) {
- mapme_Process(forwarder->mapme, msgBuffer, conn_id);
+ default:
+ ERROR("Invalid msgbuf type");
+ forwarder_drop(forwarder, msgbuf_id);
+ return 0;
+ }
}
-MapMe *
-forwarder_getMapmeInstance(const Forwarder *forwarder) {
- return forwarder->mapme;
+void forwarder_log(forwarder_t *forwarder) {
+ DEBUG(
+ "Forwarder: received = %u (interest = %u, data = %u), dropped = %u "
+ "(interest = %u, data = %u, other = %u), forwarded = { interests = %u, "
+ "data = %u }, dropped = { connection_not_found = %u, send_failure = %u, "
+ "no_route_in_fib = %u }, interest processing = { aggregated = %u, "
+ "retransmitted = %u, satisfied_from_cs = %u, expired_interests = %u, "
+ "expired_data = %u }, data processing = { "
+ "no_reverse_path = %u }\n",
+ forwarder->stats.countReceived, forwarder->stats.countInterestsReceived,
+ forwarder->stats.countObjectsReceived, forwarder->stats.countDropped,
+ forwarder->stats.countInterestsDropped,
+ forwarder->stats.countObjectsDropped, forwarder->stats.countOtherDropped,
+ forwarder->stats.countInterestForwarded,
+ forwarder->stats.countObjectsForwarded,
+ forwarder->stats.countDroppedConnectionNotFound,
+ forwarder->stats.countSendFailures, forwarder->stats.countDroppedNoRoute,
+ forwarder->stats.countInterestsAggregated,
+ forwarder->stats.countInterestsRetransmitted,
+ forwarder->stats.countInterestsSatisfiedFromStore,
+ forwarder->stats.countInterestsExpired, forwarder->stats.countDataExpired,
+ forwarder->stats.countDroppedNoReversePath);
}
-
-#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h
index d1815b7d4..76c12368a 100644
--- a/hicn-light/src/hicn/core/forwarder.h
+++ b/hicn-light/src/hicn/core/forwarder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,292 +18,212 @@
* only be called within the forwarders thread of execution.
*/
-#ifndef forwarder_h
-#define forwarder_h
+#ifndef HICNLIGHT_FORWARDER_H
+#define HICNLIGHT_FORWARDER_H
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
-#include <stdlib.h>
-
-#include <hicn/core/connectionTable.h>
-#include <hicn/core/dispatcher.h>
-#include <hicn/messenger/messenger.h>
+//#ifndef _WIN32
+//#include <sys/time.h>
+//#endif
+//
-#include <hicn/core/message.h>
+#include <stdlib.h>
+#include <sys/socket.h> // struct mmsghdr
-#include <hicn/config/configuration.h>
+#include "connection.h"
+#include "connection_table.h"
+#include "packet_cache.h"
+#include "listener_table.h"
+#include "msgbuf.h"
+#include "msgbuf_pool.h"
+#include "../config/configuration.h"
+#include "subscription.h"
#ifdef WITH_MAPME
-#include <hicn/processor/fib.h>
+#include "fib.h"
#endif /* WITH_MAPME */
-#include <hicn/core/logger.h>
-#include <hicn/core/ticks.h>
-#include <hicn/io/listenerSet.h>
-
-#include <hicn/processor/fibEntryList.h>
-
-#include <parc/algol/parc_Clock.h>
-
-#if !defined(__APPLE__)
-#include <hicn/socket/api.h>
-#endif
-
#define PORT_NUMBER 9695
#define PORT_NUMBER_AS_STRING "9695"
-#include <hicn/utils/commands.h>
+//#include <hicn/utils/commands.h>
// ==============================================
-struct forwarder;
-typedef struct forwarder Forwarder;
+typedef struct forwarder_s forwarder_t;
/**
- * @function forwarder_Create
- * @abstract Create the forwarder and use the provided logger for diagnostic
+ * @brief Create the forwarder and use the provided logger for diagnostic
* output
* @discussion
* If the logger is null, hicn-light will create a STDOUT logger.
*
* @param logger may be NULL
*/
-Forwarder *forwarder_Create(Logger *logger);
+forwarder_t *forwarder_create(configuration_t *configuration);
/**
- * @function forwarder_Destroy
- * @abstract Destroys the forwarder, stopping all traffic and freeing all memory
+ * @brief Destroys the forwarder, stopping all traffic and freeing all memory
*/
-void forwarder_Destroy(Forwarder **ptr);
+void forwarder_free(forwarder_t *forwarder);
/**
- * @function forwarder_SetupAllListeners
- * @abstract Setup all listeners (tcp, udp, local, ether, ip multicast) on all
- * interfaces
- * @discussion
- * Sets up all listeners on all running interfaces. This provides a quick and
- * easy startup, rather than providing a configuration file or programmatic
- * commands.
- *
- * @param port is used by TCP and UDP listeners, in host byte order
- * @param localPath is the AF_UNIX path to use, if NULL no AF_UNIX listener is
- * setup
- */
-void forwarder_SetupAllListeners(Forwarder *forwarder, uint16_t port,
- const char *localPath);
-/**
- * @function forwarder_SetupAllListeners
- * @abstract Setup one tcp and one udp listener on address 127.0.0.1 and the
+ * @brief Setup one tcp and one udp listener on address 127.0.0.1 and the
* given port
*/
-void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port);
-
-/**
- * Configure hicn-light via a configuration file
- *
- * The configuration file is a set of lines, just like used in hicnLightControl.
- * You need to have "add listener" lines in the file to receive connections. No
- * default listeners are configured.
- *
- * @param [in] forwarder An alloated Forwarder
- * @param [in] filename The path to the configuration file
- */
-void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename);
-
-/**
- * Returns the logger used by this forwarder
- *
- * If you will store the logger, you should acquire a reference to it.
- *
- * @param [in] forwarder An allocated hicn-light forwarder
- *
- * @retval non-null The logger used by hicn-light
- * @retval null An error
- */
-Logger *forwarder_GetLogger(const Forwarder *forwarder);
-
-/**
- * @function forwarder_SetLogLevel
- * @abstract Sets the minimum level to log
- */
-void forwarder_SetLogLevel(Forwarder *forwarder, PARCLogLevel level);
-
-/**
- * @function forwarder_GetNextConnectionId
- * @abstract Get the next identifier for a new connection
- */
-unsigned forwarder_GetNextConnectionId(Forwarder *forwarder);
+void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port);
-Messenger *forwarder_GetMessenger(Forwarder *forwarder);
+configuration_t *forwarder_get_configuration(forwarder_t *forwarder);
-Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder);
+subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder);
/**
* Returns the set of currently active listeners
*
- * @param [in] forwarder An allocated hicn-light forwarder
+ * @param[in] forwarder An allocated hicn-light forwarder
*
* @retval non-null The set of active listeners
* @retval null An error
*/
-ListenerSet *forwarder_GetListenerSet(Forwarder *forwarder);
+listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder);
/**
* Returns the forwrder's connection table
*
- * @param [in] forwarder An allocated hicn-light forwarder
+ * @param[in] forwarder An allocated hicn-light forwarder
*
* @retval non-null The connection tabler
* @retval null An error
*
*/
-#ifdef WITH_POLICY
-ConnectionTable *forwarder_GetConnectionTable(const Forwarder *forwarder);
-#else
-ConnectionTable *forwarder_GetConnectionTable(Forwarder *forwarder);
-#endif /* WITH_POLICY */
+connection_table_t *forwarder_get_connection_table(
+ const forwarder_t *forwarder);
-/**
- * Returns a Tick-based clock
- *
- * Runs at approximately 1 msec per tick (see HZ in forwarder.c).
- * Do not Release this clock. If you save a copy of it, create your own
- * reference to it with parcClock_Acquire().
- *
- * @param [in] forwarder An allocated hicn-light forwarder
- *
- * @retval non-null An allocated hicn-light Clock based on the Tick counter
- * @retval null An error
- */
-PARCClock *forwarder_GetClock(const Forwarder *forwarder);
+void forwarder_cs_set_store(forwarder_t *forwarder, bool val);
-/**
- * Direct call to get the Tick clock
- *
- * Runs at approximately 1 msec per tick (see HZ in forwarder.c)
- *
- * @param [in] forwarder An allocated hicn-light forwarder
- */
-Ticks forwarder_GetTicks(const Forwarder *forwarder);
+bool forwarder_cs_get_store(forwarder_t *forwarder);
+
+void forwarder_cs_set_serve(forwarder_t *forwarder, bool val);
+
+bool forwarder_cs_get_serve(forwarder_t *forwarder);
/**
- * Convert nano seconds to Ticks
+ * Sets the maximum number of content objects in the content store
*
- * Converts nano seconds to Ticks, based on HZ (in forwarder.c)
+ * Implementation dependent - may wipe the cache.
*/
-Ticks forwarder_NanosToTicks(uint64_t nanos);
-
-uint64_t forwarder_TicksToNanos(Ticks ticks);
+void forwarder_cs_set_size(forwarder_t *forwarder, size_t size);
-void forwarder_ReceiveCommand(Forwarder *forwarder, command_id command,
- struct iovec *message, unsigned ingressId);
-
-void forwarder_Receive(Forwarder *forwarder, Message *mesage);
+size_t forwarder_cs_get_size(forwarder_t *forwarder);
+size_t forwarder_cs_get_num_stale_entries(forwarder_t *forwarder);
+void forwarder_cs_clear(forwarder_t *forwarder);
/**
- * @function forwarder_AddOrUpdateRoute
- * @abstract Adds or updates a route on all the message processors
+ * @brief Adds or updates a route on all the message processors
*/
-bool forwarder_AddOrUpdateRoute(Forwarder *forwarder,
- add_route_command *control, unsigned ifidx);
+bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix,
+ unsigned ingress_id);
/**
- * @function forwarder_RemoveRoute
- * @abstract Removes a route from all the message processors
+ * @brief Removes a route from all the message processors
*/
-bool forwarder_RemoveRoute(Forwarder *forwarder, remove_route_command *control,
- unsigned ifidx);
+bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix,
+ unsigned ingress_id);
#ifdef WITH_POLICY
/**
- * @function forwarder_AddOrUpdatePolicy
- * @abstract Adds or updates a policy on the message processor
+ * @brief Adds or updates a policy on the message processor
*/
-bool forwarder_AddOrUpdatePolicy(Forwarder *forwarder, add_policy_command *control);
+bool forwarder_add_or_update_policy(forwarder_t *forwarder, ip_prefix_t *prefix,
+ hicn_policy_t *policy);
/**
- * @function forwarder_RemovePolicy
- * @abstract Removes a policy from the message processor
+ * @brief Removes a policy from the message processor
*/
-bool forwarder_RemovePolicy(Forwarder *forwarder, remove_policy_command *control);
+bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix);
+
#endif /* WITH_POLICY */
/**
* Removes a connection id from all routes
*/
-void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder,
- unsigned connectionId);
+void forwarder_remove_connection_id_from_routes(forwarder_t *forwarder,
+ unsigned connection_id);
-/**
- * @function forwarder_GetConfiguration
- * @abstract The configuration object
- * @discussion
- * The configuration contains all user-issued commands. It does not include
- * dynamic state.
- */
-Configuration *forwarder_GetConfiguration(Forwarder *forwarder);
+void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options);
-FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder);
+void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options);
+
+cs_t *forwarder_get_cs(const forwarder_t *forwarder);
/**
- * Sets the maximum number of content objects in the content store
- *
- * Implementation dependent - may wipe the cache.
+ * @brief Returns the forwarder's FIB.
+ * @param[in] forwarder - Pointer to the forwarder.
+ * @returns Pointer to the hICN FIB.
*/
-void forwarder_SetContentObjectStoreSize(Forwarder *forwarder,
- size_t maximumContentStoreSize);
-
-void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val);
-
-bool forwarder_GetChacheStoreFlag(Forwarder *forwarder);
-
-void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val);
-
-bool forwarder_GetChacheServeFlag(Forwarder *forwarder);
-
-void forwarder_ClearCache(Forwarder *forwarder);
-
-void forwarder_SetStrategy(Forwarder *forwarder, Name *prefix,
- strategy_type strategy, unsigned related_prefixes_len,
- Name **related_prefixes);
-#if !defined(__APPLE__)
-hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder);
-#endif
-#ifdef WITH_MAPME
+fib_t *forwarder_get_fib(forwarder_t *forwarder);
/**
- * @function forwarder_getFib
- * @abstract Returns the hICN forwarder's FIB.
- * @param [in] forwarder - Pointer to the hICN forwarder.
- * @returns Pointer to the hICN FIB.
+ * @brief Return the forwarder packet pool.
+ * @param[in] forwarder The forwarder from which to retrieve the packet
+ * pool.
+ * @return msgbuf_pool_t * The forwarder packet pool.
*/
-FIB *forwarder_getFib(Forwarder *forwarder);
+msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder);
+
+#ifdef WITH_MAPME
/**
- * @function forwarder_onConnectionEvent
- * @abstract Callback fired upon addition of a new connection through the
+ * @brief Callback fired upon addition of a new connection through the
* control protocol.
- * @param [in] forwarder - Pointer to the hICN forwarder.
- * @param [in] conn - Pointer to the newly added connection.
- * @param [in] event - Connection event
+ * @param[in] forwarder - Pointer to the forwarder.
+ * @param[in] conn - Pointer to the newly added connection.
+ * @param[in] event - Connection event
*/
-void forwarder_onConnectionEvent(Forwarder *forwarder, const Connection *conn, connection_event_t event);
+void forwarder_on_connection_event(const forwarder_t *forwarder,
+ const connection_t *connection,
+ connection_event_t event);
/**
- * @function forwarder_ProcessMapMe
- * @abstract Callback fired by an hICN listener upon reception of a MAP-Me
+ * @brief Callback fired by an hICN listener upon reception of a MAP-Me
* message.
- * @param [in] forwarder - Pointer to the hICN forwarder.
- * @param [in] msgBuffer - MAP-Me buffer
- * @param [in] conn_id - Ingress connection id
+ * @param[in] forwarder - Pointer to the forwarder.
+ * @param[in] msgBuffer - MAP-Me buffer
+ * @param[in] conn_id - Ingress connection id
*/
-void forwarder_ProcessMapMe(Forwarder *forwarder, const uint8_t *msgBuffer,
- unsigned conn_id);
+void forwarder_process_mapme(const forwarder_t *forwarder,
+ const uint8_t *packet, unsigned conn_id);
-struct mapme;
-struct mapme * forwarder_getMapmeInstance(const Forwarder *forwarder);
+struct mapme_s *forwarder_get_mapme(const forwarder_t *forwarder);
#endif /* WITH_MAPME */
-#endif // forwarder_h
+#ifdef WITH_POLICY_STATS
+const policy_stats_mgr_t *forwarder_get_policy_stats_mgr(
+ const forwarder_t *forwarder);
+#endif /* WITH_POLICY_STATS */
+
+void forwarder_flush_connections(forwarder_t *forwarder);
+
+/**
+ * @brief Handles a newly received packet from a listener.
+ *
+ * NOTE: the received msgbuf is incomplete and only holds the packet content and
+ * size/
+ */
+ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
+ off_t msgbuf_id, address_pair_t *pair, Ticks now);
+
+/**
+ * @brief Log forwarder statistics, e.g. info about packets processed, packets
+ * dropped, packets forwarded, errors while forwarding, interest and data
+ * processing results.
+ *
+ * @param forwarder Pointer to the forwarder data structure to use
+ */
+void forwarder_log(forwarder_t *forwarder);
+
+#endif // HICNLIGHT_FORWARDER_H
diff --git a/hicn-light/src/hicn/core/listener.c b/hicn-light/src/hicn/core/listener.c
new file mode 100644
index 000000000..ecdfc38f4
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener.c
@@ -0,0 +1,444 @@
+/*
+ * 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 listener.c
+ * @brief Implementation of hICN listeners
+ */
+
+#include <string.h> // strdup
+
+#include <hicn/util/log.h>
+
+#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) {
+ listener_key_t key;
+ memset(&key, 0, sizeof(listener_key_t));
+
+ key.address = address;
+ key.type = type;
+ return key;
+}
+
+listener_t *listener_create(face_type_t type, const address_t *address,
+ const char *interface_name, const char *name,
+ forwarder_t *forwarder) {
+ listener_table_t *table = forwarder_get_listener_table(forwarder);
+
+ 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);
+
+ int ret = listener_initialize(listener, type, name, listener_id, address,
+ interface_name, forwarder);
+ if (ret < 0) {
+ listener_table_remove_by_id(table, listener_id);
+ listener_finalize(listener);
+ return NULL;
+ }
+
+ WITH_INFO({
+ char addr_str[NI_MAXHOST];
+ int port;
+ address_to_string(address, addr_str, &port);
+ INFO("LISTENER CREATE (%s) %p created for address %s:%d",
+ face_type_str(listener->type), listener, addr_str, port);
+ listener_table_print_by_key(table);
+ })
+
+ return listener;
+}
+
+int listener_initialize(listener_t *listener, face_type_t type,
+ const char *name, unsigned listener_id,
+ const address_t *address, const char *interface_name,
+ forwarder_t *forwarder) {
+ int rc;
+
+ assert(listener);
+ assert(forwarder);
+
+ *listener = (listener_t){
+ .id = listener_id,
+ .name = strdup(name),
+ .key = listener_key_factory(*address, type),
+ .interface_name = strdup(interface_name),
+ .family = address->as_ss.ss_family,
+ .fd = 0,
+ .forwarder = forwarder,
+ };
+
+ face_protocol_t face_protocol = get_protocol(listener->type);
+ if (face_protocol == FACE_PROTOCOL_UNKNOWN) goto ERR_VFT;
+
+ listener->data = malloc(listener_vft[face_protocol]->data_size);
+ if (!listener->data) goto ERR_DATA;
+
+ assert(listener_has_valid_type(listener));
+
+ rc = listener_vft[face_protocol]->initialize(listener);
+ if (rc < 0) goto ERR_VFT;
+
+ listener->fd = listener_vft[face_protocol]->get_socket(listener, address,
+ NULL, interface_name);
+ if (listener->fd < 0) {
+ char addr_str[NI_MAXHOST];
+ int port;
+ address_to_string(address, addr_str, &port);
+ ERROR("Error creating listener %s fd: (%d) %s", addr_str, errno,
+ strerror(errno));
+ goto ERR_FD;
+ }
+ assert(listener->fd > 0);
+
+ // XXX data should be pre-allocated here
+
+ loop_fd_event_create(&listener->event_data, MAIN_LOOP, listener->fd, listener,
+ (fd_callback_t)listener_read_callback, NULL);
+
+ if (!listener->event_data) {
+ goto ERR_REGISTER_FD;
+ }
+
+ if (loop_fd_event_register(listener->event_data) < 0) {
+ goto ERR_REGISTER_FD;
+ }
+
+ return 0;
+
+ERR_REGISTER_FD:
+#ifndef _WIN32
+ close(listener->fd);
+#else
+ closesocket(listener->fd);
+#endif
+ERR_FD:
+ERR_VFT:
+ERR_DATA:
+ return -1;
+}
+
+int listener_finalize(listener_t *listener) {
+ assert(listener);
+ assert(listener_has_valid_type(listener));
+
+ if (listener->event_data) {
+ loop_event_unregister(listener->event_data);
+ loop_event_free(listener->event_data);
+ }
+
+ if (listener->fd != -1) {
+#ifndef _WIN32
+ close(listener->fd);
+#else
+ closesocket(listener->fd);
+#endif
+ }
+
+ listener_vft[get_protocol(listener->type)]->finalize(listener);
+
+ if (listener->data) free(listener->data);
+ listener->data = NULL;
+ if (listener->interface_name) free(listener->interface_name);
+ listener->interface_name = NULL;
+ if (listener->name) free(listener->name);
+ listener->name = NULL;
+
+ return 0;
+}
+
+int listener_get_socket(const listener_t *listener, const address_t *local,
+ const address_t *remote, const char *interface_name) {
+ assert(listener);
+ assert(listener_has_valid_type(listener));
+ assert(local);
+ // assert(remote); TODO: can it be null?
+
+ // DEBUG("[listener_get_socket]");
+
+ return listener_vft[get_protocol(listener->type)]->get_socket(
+ listener, local, remote, interface_name);
+}
+
+/*
+ * This is called from the forwarder to dynamially create new connections on the
+ * listener, in that case, name is NULL. It is also called from
+ * connection_create, which is itself called from the configuration part.
+ */
+unsigned listener_create_connection(listener_t *listener,
+ const char *connection_name,
+ const address_pair_t *pair) {
+ assert(listener);
+ assert(listener_has_valid_type(listener));
+ assert(pair);
+
+ connection_table_t *table =
+ forwarder_get_connection_table(listener->forwarder);
+ connection_t *connection =
+ connection_table_allocate(table, pair, connection_name);
+ unsigned connection_id =
+ connection_table_get_connection_id(table, connection);
+
+ /*
+ * We create a connected connection with its own fd, instead of returning
+ * the fd of the listener. This will allow to avoid specifying the
+ * destination address when sending packets, and will increase performance
+ * by avoiding a FIB lookup for each packet.
+ */
+#ifdef USE_CONNECTED_SOCKETS
+ int fd = listener_get_socket(listener, address_pair_get_local(pair),
+ address_pair_get_remote(pair),
+ listener->interface_name);
+#else
+ int fd = 0; // means listener->fd;
+#endif
+ bool local = address_is_local(address_pair_get_local(pair));
+
+ face_type_t connection_type;
+ switch (listener->type) {
+ case FACE_TYPE_UDP_LISTENER:
+ connection_type = FACE_TYPE_UDP;
+ break;
+ case FACE_TYPE_TCP_LISTENER:
+ connection_type = FACE_TYPE_TCP;
+ break;
+ default:
+ connection_table_remove_by_id(table, connection_id);
+ return CONNECTION_ID_UNDEFINED;
+ }
+
+ int rc = connection_initialize(connection, connection_type, connection_name,
+ listener->interface_name, fd, pair, local,
+ connection_id, listener);
+ if (rc < 0) {
+ connection_table_remove_by_id(table, connection_id);
+ connection_finalize(connection);
+ return CONNECTION_ID_UNDEFINED;
+ }
+
+ WITH_INFO({
+ char local_addr_str[NI_MAXHOST];
+ char remote_addr_str[NI_MAXHOST];
+ int local_port;
+ int remote_port;
+ address_to_string(&(pair->local), local_addr_str, &local_port);
+ address_to_string(&(pair->remote), remote_addr_str, &remote_port);
+ INFO("%s connection %p created for address pair %s:%d (local=%s) - %s:%d",
+ face_type_str(connection->type), connection, local_addr_str,
+ local_port, connection_is_local(connection) ? "true" : "false",
+ remote_addr_str, remote_port);
+ connection_table_print_by_pair(table);
+ })
+
+#if 0
+ DEBUG("Notification for new connections");
+ // Generate notification message
+ flag_interface_type_t interface_type =
+ FLAG_INTERFACE_TYPE_WIRED | FLAG_INTERFACE_TYPE_CELLULAR;
+ struct {
+ cmd_header_t header;
+ hc_event_interface_update_t payload;
+ } msg = {.header =
+ {
+ .message_type = NOTIFICATION_LIGHT,
+ .command_id = EVENT_INTERFACE_UPDATE,
+ .length = 0,
+ .seq_num = 0,
+ },
+ .payload = {.interface_type = interface_type}};
+ size_t size = sizeof(msg);
+
+ // Retrieve subscribed connections
+ subscription_table_t *subscriptions =
+ forwarder_get_subscriptions(listener->forwarder);
+ unsigned *subscribed_conn_ids = subscription_table_get_connections_for_topic(
+ subscriptions, TOPIC_CONNECTION);
+
+ // Send notification to subscribed connections
+ for (int i = 0; i < vector_len(subscribed_conn_ids); i++) {
+ DEBUG("Sending notification to connection: %u", subscribed_conn_ids[i]);
+ const connection_t *conn =
+ connection_table_at(table, subscribed_conn_ids[i]);
+ connection_send_packet(conn, (uint8_t *)&msg, size);
+ }
+#endif
+
+ return connection_id;
+}
+
+int listener_punt(const listener_t *listener, const char *prefix_s) {
+ assert(listener);
+ assert(listener_get_type(listener) == FACE_TYPE_HICN);
+ assert(prefix_s);
+
+ return listener_vft[get_protocol(listener->type)]->punt(listener, prefix_s);
+}
+
+ssize_t listener_read_single(listener_t *listener, int fd) {
+ assert(listener);
+
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(listener->forwarder);
+
+ // Preapare the msgbuf
+ msgbuf_t *msgbuf = NULL;
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ if (!msgbuf_id_is_valid(msgbuf_id)) return -1;
+
+ // Prepare the address pair
+ address_pair_t pair;
+ memset(&pair, 0, sizeof(address_pair_t));
+ pair.local = listener->address;
+
+ // Read message and populate the remote address
+ ssize_t n = listener_vft[get_protocol(listener->type)]->read_single(
+ fd, msgbuf, address_pair_get_remote(&pair));
+ if (n <= 0) {
+ msgbuf_pool_put(msgbuf_pool, msgbuf);
+ return -1;
+ }
+
+ msgbuf_pool_acquire(msgbuf);
+
+ // Process received packet
+ size_t processed_bytes = forwarder_receive(listener->forwarder, listener,
+ msgbuf_id, &pair, ticks_now());
+ forwarder_log(listener->forwarder);
+ if (processed_bytes <= 0) ERROR("Unable to handle message");
+
+ /*
+ * The connection on which we went packets might do batching (even without
+ * sendmmsg), and we need to inform the system that we want to proceed to
+ * sending packets.
+ */
+ forwarder_flush_connections(listener->forwarder);
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+ return processed_bytes;
+}
+
+ssize_t listener_read_batch(listener_t *listener, int fd) {
+ assert(listener);
+
+ 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);
+
+ /* Receive messages in the loop as long as we manage to fill the buffers */
+ do {
+ /* Prepare the msgbuf and address pair arrays */
+ msgbuf_t *msgbufs[MAX_MSG];
+ if (msgbuf_pool_getn(msgbuf_pool, msgbufs, MAX_MSG) < 0) {
+ ERROR("Unable to get message buffers");
+ break;
+ }
+
+ address_pair_t pair[MAX_MSG];
+ address_t *address_remote[MAX_MSG];
+ memset(&pair, 0, MAX_MSG * sizeof(address_pair_t));
+
+ off_t msgbuf_ids[MAX_MSG];
+ for (unsigned i = 0; i < MAX_MSG; i++) {
+ // Copy the pointers to the remote addresses
+ address_remote[i] = address_pair_get_remote(&pair[i]);
+
+ // Populate local addresses
+ pair[i].local = listener->address;
+
+ // Do NOT rely on msgbuf pointers since a msgbuf pool rezise event may
+ // make them invalid, use msgbuf ids instead
+ msgbuf_ids[i] = msgbuf_pool_get_id(msgbuf_pool, msgbufs[i]);
+ }
+
+ // Read batch and populate remote addresses
+ num_msg_received = listener_vft[get_protocol(listener->type)]->read_batch(
+ fd, msgbufs, address_remote, MAX_MSG);
+
+ for (int i = 0; i < MAX_MSG; i++) {
+ // Release unused msg buffers
+ if (i >= num_msg_received) {
+ msgbuf_pool_put(msgbuf_pool, msgbufs[i]);
+ continue;
+ }
+
+ msgbuf_pool_acquire(msgbufs[i]);
+ vector_push(acquired_msgbuf_ids, msgbuf_ids[i]);
+ }
+
+ if (num_msg_received < 0) break;
+ TRACE("[listener_read_batch] batch size = %d", num_msg_received);
+
+ for (unsigned i = 0; i < num_msg_received; i++) {
+ size_t processed_bytes = forwarder_receive(
+ forwarder, listener, msgbuf_ids[i], &pair[i], ticks_now());
+ forwarder_log(listener->forwarder);
+
+ total_processed_bytes += processed_bytes;
+ }
+ } while (num_msg_received ==
+ MAX_MSG); /* backpressure based on queue size ? */
+
+ /*
+ * Signal to the forwarder that we reached the end of a batch and we need to
+ * flush connections out
+ */
+ forwarder_flush_connections(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;
+}
+
+/*
+ * This might be called for a connection on the listener too. The listener is
+ * the entity that owns the buffers used for reading.
+ */
+ssize_t listener_read_callback(listener_t *listener, int fd, void *user_data) {
+ // DEBUG("[listener_read_callback]");
+ // XXX make a single callback and arbitrate between read and readbatch
+ assert(listener);
+
+ /*
+ * As the listener callback is shared between the listener and the different
+ * connections created on top of it, the fd might be either of them.
+ */
+ // assert(fd == listener->fd);
+
+ if (listener_vft[get_protocol(listener->type)]->read_batch)
+ return listener_read_batch(listener, fd);
+
+ return listener_read_single(listener, fd);
+}
+
+void listener_setup_local(forwarder_t *forwarder, uint16_t port) {
+ address_t localhost_ipv4_addr = ADDRESS4_LOCALHOST(port);
+ listener_create(FACE_TYPE_UDP_LISTENER, &localhost_ipv4_addr, "lo", "lo_udp4",
+ forwarder);
+
+ address_t localhost_ipv6_addr = ADDRESS6_LOCALHOST(port);
+ listener_create(FACE_TYPE_UDP_LISTENER, &localhost_ipv6_addr, "lo", "lo_udp6",
+ forwarder);
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/listener.h b/hicn-light/src/hicn/core/listener.h
new file mode 100644
index 000000000..346c874c0
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener.h
@@ -0,0 +1,131 @@
+/*
+ * 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 listener.h
+ * @brief hICN listeners
+ */
+
+#ifndef HICNLIGHT_LISTENER_H
+#define HICNLIGHT_LISTENER_H
+
+#include <hicn/face.h>
+
+#include "address_pair.h"
+#include "msgbuf.h"
+#include "../base/loop.h"
+
+#define LISTENER_ID_UNDEFINED ~0
+
+struct forwarder_s;
+
+typedef struct {
+ address_t address;
+ face_type_t type;
+} listener_key_t;
+
+/**
+ * @brief Create a listener key starting from an address and a face type.
+ *
+ * @param address
+ * @param type
+ * @return listener_key_t The listener key created.
+ *
+ * @note The listener key returned is resetted before intializing
+ * the internal fields, to allow a reliable hash generation.
+ */
+listener_key_t listener_key_factory(address_t address, face_type_t type);
+
+/* This structure holds what is in common to all listeners */
+typedef struct {
+ int id;
+ char *name;
+ union {
+ listener_key_t key;
+ struct {
+ address_t address;
+ face_type_t type;
+ };
+ };
+
+ char *interface_name;
+ unsigned family;
+
+ int fd;
+ event_t *event_data;
+
+ void *data; /* Listener specific data */
+ struct forwarder_s *forwarder;
+} listener_t;
+
+#define listener_get_id(L) ((L)->id)
+#define listener_get_name(L) ((L)->name)
+#define listener_get_key(L) (&(L)->key)
+#define listener_get_type(L) ((L)->type)
+#define listener_get_interface_name(L) ((L)->interface_name)
+#define listener_get_address(L) (&(L)->address)
+#define listener_has_valid_type(L) (face_type_is_valid((L)->type))
+#define listener_id_is_valid(ID) (ID != LISTENER_ID_UNDEFINED)
+
+listener_t *listener_create(face_type_t type, const address_t *address,
+ const char *interface_name, const char *symbolic,
+ struct forwarder_s *forwarder);
+
+/**
+ * @brief Helper function used inside 'listener_create' to
+ * setup variables in listener struct.
+ *
+ * @see listener_create
+ */
+int listener_initialize(listener_t *listener, face_type_t type,
+ const char *name, unsigned listener_id,
+ const address_t *address, const char *interface_name,
+ struct forwarder_s *forwarder);
+
+int listener_finalize(listener_t *listener);
+
+int listener_punt(const listener_t *listener, const char *prefix_s);
+
+int listener_get_socket(const listener_t *listener, const address_t *local,
+ const address_t *remote, const char *interface_name);
+
+unsigned listener_create_connection(listener_t *listener, const char *name,
+ const address_pair_t *pair);
+
+void listener_setup_local(struct forwarder_s *forwarder, uint16_t port);
+
+void listener_process_packet(const listener_t *listener, const uint8_t *packet,
+ size_t size);
+
+ssize_t listener_read_single(listener_t *listener, int fd);
+ssize_t listener_read_batch(listener_t *listener, int fd);
+
+/**
+ * @brief Callback helper function for batch reading data from listener fd.
+ *
+ * This function is usually called from the listener read callback to proceed to
+ * actual reading of data from the fd.
+ *
+ * @see listener_read_callback
+ *
+ * NOTE: the function returns size_t as for TCP we might need to know how much
+ * data we can consume from the socket.
+ */
+ssize_t listener_read_callback(listener_t *listener, int fd, void *user_data);
+
+#define listener_get_forwarder(listener) (listener->forwarder)
+#define listener_get_fd(listener) (listener->fd)
+
+#endif /* HICNLIGHT_LISTENER_H */
diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c
new file mode 100644
index 000000000..32b8e9d45
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener_table.c
@@ -0,0 +1,153 @@
+/*
+ * 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 listener_table.c
+ * \brief Implementation of hICN listener table
+ */
+
+#include <hicn/util/log.h>
+
+#include "listener_table.h"
+#include "listener.h"
+
+/* This is only used as a hint for first allocation, as the table is resizeable
+ */
+#define DEFAULT_LISTENER_TABLE_SIZE 64
+
+listener_table_t *_listener_table_create(size_t init_size, size_t max_size) {
+ if (init_size == 0) init_size = DEFAULT_LISTENER_TABLE_SIZE;
+
+ listener_table_t *table = malloc(sizeof(listener_table_t));
+ if (!table) return NULL;
+
+ table->max_size = max_size;
+
+ /* Initialize indices */
+ table->id_by_name = kh_init_lt_name();
+ table->id_by_key = kh_init_lt_key();
+
+ /*
+ * We start by allocating a reasonably-sized pool, as this will eventually
+ * be resized if needed.
+ */
+ pool_init(table->listeners, init_size, 0);
+
+ return table;
+}
+
+void listener_table_free(listener_table_t *table) {
+ const char *k_name;
+ const listener_key_t *k_key;
+ unsigned v;
+
+ listener_t *listener;
+ const char *name;
+ kh_foreach(table->id_by_key, k_key, v, {
+ listener = listener_table_get_by_id(table, v);
+ name = listener_get_name(listener);
+ INFO("Removing listner %s [%d]", name, listener->fd);
+ listener_finalize(listener);
+ });
+
+ (void)v;
+ kh_foreach(table->id_by_name, k_name, v, { free((char *)k_name); });
+ kh_foreach(table->id_by_key, k_key, v, { free((listener_key_t *)k_key); });
+
+ kh_destroy_lt_name(table->id_by_name);
+ kh_destroy_lt_key(table->id_by_key);
+ pool_free(table->listeners);
+ free(table);
+}
+
+listener_t *listener_table_get_by_address(listener_table_t *table,
+ face_type_t type,
+ const address_t *address) {
+ listener_key_t key = listener_key_factory(*address, type);
+ khiter_t k = kh_get_lt_key(table->id_by_key, &key);
+ if (k == kh_end(table->id_by_key)) return NULL;
+ return listener_table_at(table, kh_val(table->id_by_key, k));
+}
+
+listener_t *listener_table_get_by_key(listener_table_t *table,
+ const listener_key_t *key) {
+ khiter_t k = kh_get_lt_key(table->id_by_key, key);
+ if (k == kh_end(table->id_by_key)) return NULL;
+ return listener_table_at(table, kh_val(table->id_by_key, k));
+}
+
+void listener_table_remove_by_id(listener_table_t *table, off_t id) {
+ listener_t *listener = listener_table_at(table, id);
+ INFO("Removing listener %d (%s)", id, listener_get_name(listener));
+
+ listener_table_deallocate(table, listener);
+}
+
+off_t listener_table_get_id_by_name(const listener_table_t *table,
+ const char *name) {
+ khiter_t k = kh_get_lt_name(table->id_by_name, name);
+ if (k == kh_end(table->id_by_name)) return LISTENER_ID_UNDEFINED;
+ return kh_val(table->id_by_name, k);
+}
+
+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);
+ if (!listener_id_is_valid(listener_id)) return NULL;
+ return listener_table_at(table, listener_id);
+}
+
+listener_t *_listener_table_get_by_id(listener_table_t *table, off_t id) {
+ return listener_table_get_by_id(table, id);
+}
+
+void listener_table_print_by_key(const listener_table_t *table) {
+ const listener_key_t *k;
+ unsigned v;
+
+ char addr_str[NI_MAXHOST];
+ int port;
+ listener_t *listener;
+ const char *name;
+
+ INFO("*** Listener table ***");
+ kh_foreach(table->id_by_key, k, v, {
+ address_to_string(&k->address, addr_str, &port);
+ listener = listener_table_get_by_id(table, v);
+ name = listener_get_name(listener);
+ INFO("%s:%d - %s\t\t\t\t(%u, %s)", addr_str, port, face_type_str(k->type),
+ v, name);
+ })
+}
+
+void listener_table_print_by_name(const listener_table_t *table) {
+ const char *k;
+ unsigned v;
+
+ char addr_str[NI_MAXHOST];
+ int port;
+ listener_t *listener;
+ const listener_key_t *key;
+
+ INFO("*** Listener table ***");
+ kh_foreach(table->id_by_name, k, v, {
+ listener = listener_table_get_by_id(table, v);
+ key = listener_get_key(listener);
+ address_to_string(&key->address, addr_str, &port);
+
+ INFO("%s:%d - %s\t\t\t\t(%u, %s)", addr_str, port, face_type_str(key->type),
+ v, k);
+ })
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h
new file mode 100644
index 000000000..5fed638e8
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener_table.h
@@ -0,0 +1,310 @@
+/*
+ * 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 listener_table.h
+ * \brief hICN listener table
+ *
+ * The listener table is composed of:
+ * - a pool of listeners allowing access through their index in constant time;
+ * - a set of indices in the form of hash table for efficient index lookups:
+ * . by name
+ * . by key (listener_type, address)
+ *
+ * For efficient index retrieval, the header will be prepended and the
+ * resulting pointer will directly point to the listener pool.
+ */
+
+#ifndef HICNLIGHT_LISTENER_TABLE_H
+#define HICNLIGHT_LISTENER_TABLE_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
+
+/* 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);
+
+typedef struct {
+ size_t max_size;
+
+ kh_lt_key_t *id_by_key;
+ kh_lt_name_t *id_by_name;
+
+ listener_t *listeners; // pool
+} listener_table_t;
+
+/**
+ * @brief Allocate a listener from the listener table.
+ *
+ * @param[in] table The listener table from which to allocate a listener.
+ * @param[out] listener The pointer that will hold the allocated listener.
+ * @param[in] pair The address pair associated to the listener (to update index)
+ * @param[in] name The name associated to the listener (to update index)
+ *
+ * NOTE:
+ * - This function updates all indices from the listener table if the
+ * allocation is successful.
+ * - 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;
+}
+
+/**
+ * @brief Deallocate a listener and return it to the listener table pool.
+ *
+ * @param[in] table The listener table to which the listener is returned.
+ * @param[in] conn The listener that is returned to the pool.
+ *
+ * NOTE:
+ * - 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);
+}
+
+/**
+ * @brief Returns the length of the listener table, the number of active
+ * listeners.
+ *
+ * @param[in] table The listener table for which we retrieve the length.
+ *
+ * @return size_t The length of the listener table.
+ *
+ * NOTE:
+ * - The length of the listener table, that is the number of currently active
+ * listeners.
+ */
+#define listener_table_len(table) (pool_len(table->listeners))
+
+/**
+ * @brief Validate an index in the listener table.
+ *
+ * @param[in] table The listener table in which to validate an index.
+ * @param[in] id The index of the listener to validate.
+ *
+ * @return bool A flag indicating whether the listener index is valid or not.
+ */
+#define listener_table_validate_id(table, id) \
+ pool_validate_id(table->listeners, id)
+
+/**
+ * @brief Return the listener corresponding to the specified index in the
+ * listener table.
+ *
+ * @param[in] table The listener table for which to retrieve the listener.
+ * @param[in] id The index for which to retrieve the listener.
+ *
+ * @return listener_t * The listener correponding to the specified index in
+ * the listener table.
+ *
+ * @see listener_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is not validated.
+ */
+#define listener_table_at(table, id) ((table)->listeners + id)
+
+/**
+ * @brief Return the listener corresponding to the specified and validated
+ * index in the listener table.
+ *
+ * @param[in] table The listener table for which to retrieve the listener.
+ * @param[in] id The index for which to retrieve the listener.
+ *
+ * @return listener_t * The listener correponding to the specified index in
+ * the listener table.
+ *
+ * @see listener_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is validated.
+ */
+#define listener_table_get_by_id(table, id) \
+ listener_table_validate_id(table, id) ? listener_table_at(table, id) : NULL
+
+/**
+ * @brief Helper function to avoid macro expansion in c++ tests. Wrapper around
+ * 'listener_table_get_by_id'.
+ */
+listener_t *_listener_table_get_by_id(listener_table_t *table, off_t id);
+
+/**
+ * @brief Returns the index of a given listener in the listener table.
+ *
+ * @param[in] table The listener table from which to retrieve the index.
+ * @param[in] conn The listener for which to retrieve the index.
+ *
+ * @return off_t The index of the specified listener in the listener table.
+ */
+#define listener_table_get_listener_id(table, listener) \
+ (listener - table->listeners)
+
+#define listener_table_foreach(table, listener, BODY) \
+ pool_foreach( \
+ table->listeners, listener, do { BODY } while (0))
+
+#define listener_table_enumerate(table, i, conn, BODY) \
+ pool_enumerate(table->listeners, (i), (conn), BODY)
+
+/**
+ * @brief Create a new listener table (extended parameters)
+ *
+ * @param[in] init_size Initially allocated size (hint, 0 = use default value)
+ * @param[in] max_size Maximum size (0 = unlimited)
+ *
+ * @return listener_table_t* - The newly created listener table
+ */
+listener_table_t *_listener_table_create(size_t init_size, size_t max_size);
+
+/**
+ * @brief Create a new listener table (minimal parameters)
+ *
+ * @return listener_table_t* - The newly created listener table
+ */
+#define listener_table_create() _listener_table_create(0, 0)
+
+/**
+ * @brief Free a listener table
+ *
+ * @param[in] table Listener table to free
+ */
+void listener_table_free(listener_table_t *table);
+
+/**
+ * @brief Retrieve a listener from the listener table by address.
+ *
+ * @param[in] table The listener table in which to search.
+ * @param[in] type The face type characterizing the listener to search for.
+ * @param[in] address The address to search for.
+ *
+ * @return listener_t * The listener matching the specified address, or
+ * NULL if not found.
+ */
+listener_t *listener_table_get_by_address(listener_table_t *table,
+ face_type_t type,
+ const address_t *address);
+
+/**
+ * @brief Retrieve a listener from the listener table by listener key (i.e.
+ * address + face type).
+ *
+ * @param[in] table The listener table in which to search.
+ * @param[in] key The listener key characterizing the listener to search for.
+ *
+ * @return listener_t * The listener matching the specified address, or
+ * NULL if not found.
+ */
+listener_t *listener_table_get_by_key(listener_table_t *table,
+ const listener_key_t *key);
+
+/**
+ * @brief Return a listener index from the listener table by name.
+ *
+ * @param[in] table The listener table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return off_t The index of the listener matching the name, or
+ * LISTENER_ID_UNDEFINED if not found.
+ */
+off_t listener_table_get_id_by_name(const listener_table_t *table,
+ const char *name);
+
+/**
+ * @brief Return a listener from the listener table by name.
+ *
+ * @param[in] table The listener table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return listener_t * The listener matching the name, or NULL if not
+ * found.
+ */
+listener_t *listener_table_get_by_name(listener_table_t *table,
+ const char *name);
+
+/**
+ * @brief Remove a listener from the listener table by its index.
+ *
+ * @param[in] table The listener table from which to delete the listener.
+ * @param[in] id The index of the listener to remove.
+ */
+void listener_table_remove_by_id(listener_table_t *table, off_t id);
+
+/**
+ * @brief Print the listener table content.
+ *
+ * @param[in] table The listener table to print.
+ */
+void listener_table_print_by_key(const listener_table_t *table);
+
+void listener_table_print_by_name(const listener_table_t *table);
+
+#endif /* HICNLIGHT_LISTENER_TABLE_H */
diff --git a/hicn-light/src/hicn/core/listener_vft.c b/hicn-light/src/hicn/core/listener_vft.c
new file mode 100644
index 000000000..600c9482f
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener_vft.c
@@ -0,0 +1,36 @@
+/*
+ * 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 listener_vft.c
+ * @brief Implementation of listener VFT
+ */
+
+#include "listener_vft.h"
+
+#ifdef __linux__
+extern listener_ops_t listener_hicn;
+#endif
+extern listener_ops_t listener_tcp;
+extern listener_ops_t listener_udp;
+
+const listener_ops_t* listener_vft[] = {
+#ifdef __linux__
+ [FACE_PROTOCOL_HICN] = &listener_hicn,
+#endif
+
+ [FACE_PROTOCOL_TCP] = &listener_tcp,
+ [FACE_PROTOCOL_UDP] = &listener_udp,
+};
diff --git a/hicn-light/src/hicn/core/listener_vft.h b/hicn-light/src/hicn/core/listener_vft.h
new file mode 100644
index 000000000..97f08778c
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener_vft.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file listener_vft.h
+ * @brief Listener VFT
+ */
+
+#ifndef HICNLIGHT_LISTENER_VFT_H
+#define HICNLIGHT_LISTENER_VFT_H
+
+#include <hicn/core/address_pair.h>
+#include <hicn/core/connection.h>
+#include <hicn/core/listener.h>
+#include <hicn/face.h>
+
+typedef struct {
+ int (*initialize)(listener_t* listener);
+ void (*finalize)(listener_t* listener);
+ int (*punt)(const listener_t* listener, const char* prefix_s);
+ int (*get_socket)(const listener_t* listener, const address_t* local,
+ const address_t* remote, const char* interface_name);
+ int (*send)(const connection_t* connection, const address_t* dummy,
+ msgbuf_t* msgbuf, bool queue);
+ int (*send_packet)(const connection_t* connection, const uint8_t* packet,
+ size_t size);
+ ssize_t (*read_single)(int fd, msgbuf_t* msgbuf, address_t* address);
+ ssize_t (*read_batch)(int fd, msgbuf_t** msgbuf, address_t** address,
+ size_t len);
+ size_t data_size;
+} listener_ops_t;
+
+#define DECLARE_LISTENER(NAME) \
+ const listener_ops_t listener_##NAME = { \
+ .initialize = listener_##NAME##_initialize, \
+ .finalize = listener_##NAME##_finalize, \
+ .punt = listener_##NAME##_punt, \
+ .get_socket = listener_##NAME##_get_socket, \
+ .read_single = listener_##NAME##_read_single, \
+ .read_batch = listener_##NAME##_read_batch, \
+ .data_size = sizeof(listener_##NAME##_data_t), \
+ }
+
+extern const listener_ops_t* listener_vft[];
+
+#endif /* HICNLIGHT_LISTENER_VFT_H */
diff --git a/hicn-light/src/hicn/core/logger.c b/hicn-light/src/hicn/core/logger.c
deleted file mode 100644
index 0b9bb264c..000000000
--- a/hicn-light/src/hicn/core/logger.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-
-#include <parc/logging/parc_Log.h>
-
-#include <hicn/core/forwarder.h>
-#include <hicn/core/logger.h>
-
-struct logger {
- PARCClock *clock;
-
- PARCLogReporter *reporter;
- PARCLog *loggerArray[LoggerFacility_END];
-};
-
-static const struct facility_to_string {
- LoggerFacility facility;
- const char *string;
-} _facilityToString[] = {
- {.facility = LoggerFacility_Config, .string = "Config"},
- {.facility = LoggerFacility_Core, .string = "Core"},
- {.facility = LoggerFacility_IO, .string = "IO"},
- {.facility = LoggerFacility_Message, .string = "Message"},
- {.facility = LoggerFacility_Processor, .string = "Processor"},
- {.facility = LoggerFacility_Strategy, .string = "Strategy"},
- {.facility = 0, .string = NULL}};
-
-const char *logger_FacilityString(LoggerFacility facility) {
- for (int i = 0; _facilityToString[i].string != NULL; i++) {
- if (_facilityToString[i].facility == facility) {
- return _facilityToString[i].string;
- }
- }
- return "Unknown";
-}
-
-static void _allocateLoggers(Logger *logger, PARCLogReporter *reporter) {
- parcTrapUnexpectedStateIf(
- logger->reporter != NULL,
- "Trying to allocate a reporter when the previous one is not null");
- logger->reporter = parcLogReporter_Acquire(reporter);
-
- char hostname[255];
- int gotHostName = gethostname(hostname, 255);
- if (gotHostName < 0) {
- snprintf(hostname, 255, "unknown");
- }
-
- for (int i = 0; i < LoggerFacility_END; i++) {
- logger->loggerArray[i] = parcLog_Create(hostname, logger_FacilityString(i),
- "forwarder", logger->reporter);
- parcLog_SetLevel(logger->loggerArray[i], PARCLogLevel_Error);
- }
-}
-
-static void _releaseLoggers(Logger *logger) {
- for (int i = 0; i < LoggerFacility_END; i++) {
- parcLog_Release(&logger->loggerArray[i]);
- }
- parcLogReporter_Release(&logger->reporter);
-}
-
-static void _destroyer(Logger **loggerPtr) {
- Logger *logger = *loggerPtr;
- _releaseLoggers(logger);
- parcClock_Release(&(*loggerPtr)->clock);
-}
-
-parcObject_ExtendPARCObject(Logger, _destroyer, NULL, NULL, NULL, NULL, NULL,
- NULL);
-
-parcObject_ImplementAcquire(logger, Logger);
-
-parcObject_ImplementRelease(logger, Logger);
-
-Logger *logger_Create(PARCLogReporter *reporter, const PARCClock *clock) {
- parcAssertNotNull(reporter, "Parameter reporter must be non-null");
- parcAssertNotNull(clock, "Parameter clock must be non-null");
-
- Logger *logger = parcObject_CreateAndClearInstance(Logger);
- if (logger) {
- logger->clock = parcClock_Acquire(clock);
- _allocateLoggers(logger, reporter);
- }
-
- return logger;
-}
-
-void logger_SetReporter(Logger *logger, PARCLogReporter *reporter) {
- parcAssertNotNull(logger, "Parameter logger must be non-null");
-
- // save the log level state
- PARCLogLevel savedLevels[LoggerFacility_END];
- for (int i = 0; i < LoggerFacility_END; i++) {
- savedLevels[i] = parcLog_GetLevel(logger->loggerArray[i]);
- }
-
- _releaseLoggers(logger);
-
- _allocateLoggers(logger, reporter);
-
- // restore log level state
- for (int i = 0; i < LoggerFacility_END; i++) {
- parcLog_SetLevel(logger->loggerArray[i], savedLevels[i]);
- }
-}
-
-void logger_SetClock(Logger *logger, PARCClock *clock) {
- parcAssertNotNull(logger, "Parameter logger must be non-null");
- parcClock_Release(&logger->clock);
- logger->clock = parcClock_Acquire(clock);
-}
-
-static void _assertInvariants(const Logger *logger, LoggerFacility facility) {
- parcAssertNotNull(logger, "Parameter logger must be non-null");
- parcTrapOutOfBoundsIf(facility >= LoggerFacility_END, "Invalid facility %d",
- facility);
-}
-
-void logger_SetLogLevel(Logger *logger, LoggerFacility facility,
- PARCLogLevel minimumLevel) {
- _assertInvariants(logger, facility);
- PARCLog *log = logger->loggerArray[facility];
- parcLog_SetLevel(log, minimumLevel);
-}
-
-bool logger_IsLoggable(const Logger *logger, LoggerFacility facility,
- PARCLogLevel level) {
- _assertInvariants(logger, facility);
- PARCLog *log = logger->loggerArray[facility];
- return parcLog_IsLoggable(log, level);
-}
-
-void logger_Log(Logger *logger, LoggerFacility facility, PARCLogLevel level,
- const char *module, const char *format, ...) {
- if (logger_IsLoggable(logger, facility, level)) {
- // this is logged as the messageid
- uint64_t logtime = parcClock_GetTime(logger->clock);
-
- // logger_IsLoggable asserted invariants so we know facility is in bounds
- PARCLog *log = logger->loggerArray[facility];
-
- va_list va;
- va_start(va, format);
-
- parcLog_MessageVaList(log, level, logtime, format, va);
-
- va_end(va);
- }
-}
diff --git a/hicn-light/src/hicn/core/logger.h b/hicn-light/src/hicn/core/logger.h
deleted file mode 100644
index 8ab741f40..000000000
--- a/hicn-light/src/hicn/core/logger.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file logger.h
- * @brief Logger for the hicn-light forwarder
- *
- * A facility based logger to allow selective logging from different parts of
- * hicn-light
- *
- */
-
-#ifndef logger_h
-#define logger_h
-
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
-#include <parc/algol/parc_Buffer.h>
-#include <parc/algol/parc_Clock.h>
-#include <parc/logging/parc_LogLevel.h>
-#include <parc/logging/parc_LogReporter.h>
-#include <stdarg.h>
-
-struct logger;
-typedef struct logger Logger;
-
-/**
- * CONFIG faciilty concerns anything in the /config directory
- * CORE concerns anything in the /core directory
- * IO concerns anything in the /io directory (listeners, connectors, tcp,
- * ethernet, etc.) PROCESSOR concerns FIB, PIT, CS MESSAGE concerns message
- * events, like parsing
- */
-typedef enum {
- LoggerFacility_Config,
- LoggerFacility_Core,
- LoggerFacility_IO,
- LoggerFacility_Processor,
- LoggerFacility_Message,
- LoggerFacility_Strategy,
- LoggerFacility_END // sentinel value
-} LoggerFacility;
-
-/**
- * Returns a string representation of a facility
- *
- * Do not free the returned value.
- *
- * @param [in] facility The facility to change to a string
- *
- * @retval string A string representation of the facility
- */
-const char *logger_FacilityString(LoggerFacility facility);
-
-/**
- * Returns a string representation of a log level
- *
- * Do not free the returned value.
- *
- * @param [in] level The level to change to a string
- *
- * @retval string A string representation of the level
- */
-const char *logger_LevelString(PARCLogLevel level);
-
-/**
- * Create a logger that uses a given writer and clock
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] writer The output writer
- * @param [in] clock The clock to use for log messages
- *
- * @retval non-null An allocated logger
- * @retval null An error
- */
-Logger *logger_Create(PARCLogReporter *reporter, const PARCClock *clock);
-
-/**
- * Release logger
- */
-void logger_Release(Logger **loggerPtr);
-
-/**
- * Acquire logger
- */
-Logger *logger_Acquire(const Logger *logger);
-
-/**
- * Sets the minimum log level for a facility
- *
- * The default log level is ERROR. For a message to be logged, it must be of
- * equal or higher log level.
- *
- * @param [in] logger An allocated logger
- * @param [in] facility The facility to set the log level for
- * @param [in] The minimum level to log
- *
- */
-void logger_SetLogLevel(Logger *logger, LoggerFacility facility,
- PARCLogLevel minimumLevel);
-
-/**
- * Tests if the log level would be logged
- *
- * If the facility would log the given level, returns true. May be used as a
- * guard around expensive logging functions.
- *
- * @param [in] logger An allocated logger
- * @param [in] facility The facility to test
- * @param [in] The level to test
- *
- * @retval true The given facility would log the given level
- * @retval false A message of the given level would not be logged
- *
- */
-bool logger_IsLoggable(const Logger *logger, LoggerFacility facility,
- PARCLogLevel level);
-
-/**
- * Log a message
- *
- * The message will only be logged if it is loggable (logger_IsLoggable returns
- * true).
- *
- * @param [in] logger An allocated Logger
- * @param [in] facility The facility to log under
- * @param [in] level The log level of the message
- * @param [in] module The specific module logging the message
- * @param [in] format The message with varargs
- *
- */
-void logger_Log(Logger *logger, LoggerFacility facility, PARCLogLevel level,
- const char *module, const char *format, ...);
-
-/**
- * Switch the logger to a new reporter
- *
- * Will close the old reporter and re-setup the internal loggers to use the new
- * reporter. All current log level settings are preserved.
- *
- * @param [in] logger An allocated Logger
- * @param [in] reporter An allocated PARCLogReporter
- */
-void logger_SetReporter(Logger *logger, PARCLogReporter *reporter);
-
-/**
- * Set a new clock to use with the logger
- *
- * The logger will start getting the time (logged as the messageid) from the
- * specified clock
- *
- * @param [in] logger An allocated Logger
- * @param [in] clock An allocated PARCClock
- */
-void logger_SetClock(Logger *logger, PARCClock *clock);
-#endif // logger_h
diff --git a/hicn-light/src/hicn/core/mapme.c b/hicn-light/src/hicn/core/mapme.c
index 3a1c9777b..dfb30da5c 100644
--- a/hicn-light/src/hicn/core/mapme.c
+++ b/hicn-light/src/hicn/core/mapme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,98 @@
/**
* @file mapme.c
* @brief MAP-Me : AnchorLess Producer Mobility Management.
+ *
+ * TODO:
+ * - review notification code with to integration of VPP implementation
+ * - reflect changes back in VPP
+ * - implement heuristic for update/notification selection
+ *
+ * MAP-Me hooks in forwarder
+ *
+ * A) Face table changes
+ *
+ * - face added
+ *
+ * * new local/producer face : this is a new prefix that we need to advertise
+ * on existing connections.
+ *
+ * We go over non-local connections an advertise the prefix through an IU
+ * provided that the connection satisfies the policy associated to the FIB
+ * entry. MAP-Me assumes the prefix already exists in the network, and the
+ * IU shall be discarded if the entry does not exist at the next hop. Three
+ * possibilities:
+ * . a bootstrap mechanism
+ * . we allow subprefixes of a prefix that is not empty by duplicating the
+ * FIB entry
+ * . we allow prefix creation in all circumstances : this is problematic
+ * since we might be creating spurious entries in routers for which we
+ * don't expect entries to be created.
+ *
+ * NOTE: because in general we will not allow for FIB entry creation, we
+ * cannot let the forwarder remove FIB entries with no nexthop (for instance
+ * after the producer leaves a point-of-attachment). This might creates
+ * permanent state in router's tables, but we assume it is the role of the
+ * routing plane to take care of routing entries.
+ *
+ * * new non-local face : a new face is available (eg. thanks to the face
+ * manager, after the node has connection to a new WiFi/LTE access point),
+ * and we thus need to advertise all local/producer prefixes onto this
+ * interface.
+ *
+ * For this, we currently scan the FIB for entries that have at least one
+ * local/producer face in nexthops, advertise the prefix on this new
+ * connection provided that it satisfies the associated policy.
+ *
+ * - face removed
+ *
+ * Currently, we take no action when a face is removed. It might however be a
+ * signal that a producer application is no more running at a given node, and
+ * that we can temporarily disable the forwarding towards that path.
+ *
+ * - face up / down
+ *
+ * - face nexthop added
+ *
+ * - face changed priority/tags
+ *
+ * B) Interest and Data forwarder path
+ *
+ * mapme_on_interest
+ *
+ * mapme_on_data
+ *
+ *
+ * EVENTS
+ * NH_SET
+ * NH_ADD
+ * PH_ADD
+ * PH_DEL
+ *
+ * C) Retransmission management
+ *
+ * Data structure
+ *
+ * mapme_on_timeout
+ *
+ *
+ * This allows us to define a convenient API for implementing MAP-Me:
+ *
+ * mapme_on_face_event XXX rename
+ *
+ * mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry)
+ * This function is used to update all the adjacencies. It needs to be called
+ * in case of face add/delete/change (priority/tas) and polocy
+ *
+ * mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ * nexthops_t *nexthops)
+ * This function updates only the nexthops and clear the tfib. It
+ * needs to be called by the forwarding strategy in case of path switch
+ *
+ * mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ * bool inc_iu_seq)
+ * This function is called to propagate the IU and it propagates the IU using
+ * the nexthops in the tfib. It needs to be used for mapme prcessing, IU
+ * forwarding, NATs and in case of timeouts
*/
#ifdef WITH_MAPME
@@ -24,236 +116,184 @@
#include <hicn/core/mapme.h>
#include <stdio.h> // printf
+#include <hicn/base/loop.h>
#include <hicn/core/connection.h>
-#include <hicn/core/connectionList.h>
#include <hicn/core/forwarder.h>
-#include <hicn/core/logger.h>
-#include <hicn/core/message.h>
-#include <hicn/core/messagePacketType.h> // packet types
+#include <hicn/core/msgbuf.h>
#include <hicn/core/ticks.h>
-#include <hicn/processor/fibEntry.h>
-#include <hicn/processor/pitEntry.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Iterator.h>
-#include <parc/algol/parc_Unsigned.h>
-#include <parc/assert/parc_Assert.h>
+#include <hicn/core/fib_entry.h>
+#include <hicn/core/pit.h>
+#include <hicn/base/loop.h>
+#include <hicn/util/log.h>
#define MS2NS(x) x * 1000000
#define T2NS(x) forwarder_TicksToNanos(x)
+//#define MAPME_ALLOW_NONEXISTING_FIB_ENTRY
#define MAPME_DEFAULT_TU 5000 /* ms */
#define MAPME_DEFAULT_RETX 500 /* ms */
-#define MAX_RETX 3
+#define MAPME_DEFAULT_DISCOVERY false
+#define MAPME_DEFAULT_PROTOCOL IPPROTO_IPV6
+#define MAPME_MAX_RETX 3
+#define MTU 1500 // XXX TODO Mutualize this define
-#define NOT_A_NOTIFICATION false
-#define NO_INGRESS 0
+#define DONT_QUEUE false
#define TIMER_NO_REPEAT false
-#define DO_DISCOVERY 1
#define MAPME_INVALID_DICOVERY_SEQ -1
+#define INIT_SEQ 0
-#define LOG_FACILITY LoggerFacility_Core
+#define foreach_mapme_event \
+ _(UNDEFINED) \
+ _(FACE_ADD) \
+ _(FACE_DEL) \
+ _(NH_SET) \
+ _(NH_ADD) \
+ _(PH_ADD) \
+ _(PH_DEL) \
+ _(N)
+
+typedef enum {
+#define _(x) MAPME_EVENT_##x,
+ foreach_mapme_event
+#undef _
+} mapme_event_t;
-#define LOG(mapme, log_level, fmt, ...) \
- do { \
- Logger *logger = forwarder_GetLogger(mapme->forwarder); \
- if (logger_IsLoggable(logger, LOG_FACILITY, log_level)) { \
- logger_Log(logger, LOG_FACILITY, log_level, __func__, fmt, \
- ##__VA_ARGS__); \
- } \
- } while (0)
+/*
+ * We need a retransmission pool holding all necessary information for crafting
+ * special interests, thus including both the DPO and the prefix associated to
+ * it.
+ */
+#define NUM_RETX_ENTRIES 100
+#define NUM_RETX_SLOT 2
-#define WARN(mapme, fmt, ...) \
- LOG(mapme, PARCLogLevel_Warning, fmt, ##__VA_ARGS__)
-#define ERR(mapme, fmt, ...) LOG(mapme, PARCLogLevel_Error, fmt, ##__VA_ARGS__)
-#define INFO(mapme, fmt, ...) LOG(mapme, PARCLogLevel_Info, fmt, ##__VA_ARGS__)
-#define DEBUG(mapme, fmt, ...) \
- LOG(mapme, PARCLogLevel_Debug, fmt, ##__VA_ARGS__)
+typedef struct {
+ hicn_prefix_t prefix;
+ fib_entry_t *entry;
+ uint8_t retx_count; // Number of retransmissions since last tfib addition
+} mapme_retx_t;
/**
* MAP-Me state data structure
*/
-struct mapme {
- uint32_t retx; /* ms */
- uint32_t Tu; /* ms */
- bool removeFibEntries;
+struct mapme_s {
+ /* Options XXX mapme_conf_t ! */
+ uint32_t retx; /* retx timeout (in ms) */
+ uint32_t timescale; /* timescale (in ms) */
+ bool discovery; /* discovery flag */
+ int protocol;
+ bool enabled; /* mapme enabled/disabled */
- Forwarder *forwarder;
+ /*
+ * Retransmissions
+ * Lite calendar queue with NUM_RETX_SLOT slots
+ */
+ event_t *timer;
+ mapme_retx_t retx_array[NUM_RETX_SLOT][NUM_RETX_ENTRIES];
+ uint8_t retx_len[NUM_RETX_SLOT];
+ uint8_t cur;
+ uint8_t idle;
+
+ forwarder_t *forwarder;
};
-static MapMe MapMeDefault = {.retx = MAPME_DEFAULT_RETX,
- .Tu = MAPME_DEFAULT_TU,
- .removeFibEntries = false};
+#define NEXT_SLOT(CUR) (1 - CUR)
+#define CUR mapme->retx_array[mapme->cur]
+#define NXT mapme->retx_array[NEXT_SLOT(mapme->cur)]
+#define CURLEN mapme->retx_len[mapme->cur]
+#define NXTLEN mapme->retx_len[NEXT_SLOT(mapme->cur)]
+
+static mapme_t mapme_default = {
+ .retx = MAPME_DEFAULT_RETX,
+ .timescale = MAPME_DEFAULT_TU,
+ .discovery = MAPME_DEFAULT_DISCOVERY,
+ .protocol = MAPME_DEFAULT_PROTOCOL,
+ .enabled = true,
+ .timer = NULL,
+ // .retx_array = {{ 0 }}, // memset
+ .retx_len = {0},
+ .cur = 0, /* current slot */
+ .idle = 0,
+};
/******************************************************************************/
-bool mapme_create(MapMe **mapme, Forwarder *forwarder) {
- *mapme = malloc(sizeof(MapMe));
- if (!mapme) goto ERR_MALLOC;
+int mapme_on_timeout(void *mapme_arg, int fd, void *data);
- /* Internal state : set default values */
- memcpy(*mapme, &MapMeDefault, sizeof(MapMe));
-
- (*mapme)->forwarder = forwarder;
+mapme_t *mapme_create(void *forwarder) {
+ mapme_t *mapme = malloc(sizeof(mapme_t));
+ if (!mapme) return NULL;
- /* As there is no face table and no related events, we need to install hooks
- * in various places in the forwarder, where both control commands and
- * signalization are processed.
- */
+ /* Internal state : set default values */
+ memcpy(mapme, &mapme_default, sizeof(mapme_t));
+ memset(mapme->retx_array, 0, NUM_RETX_SLOT * NUM_RETX_ENTRIES);
- return true;
+ mapme->forwarder = forwarder;
+ loop_timer_create(&mapme->timer, MAIN_LOOP, mapme, mapme_on_timeout, NULL);
+ if (!mapme->timer) {
+ ERROR("Error allocating mapme timer.");
+ free(mapme);
+ return NULL;
+ }
-ERR_MALLOC:
- return false;
+ return mapme;
}
-void mapme_free(MapMe *mapme)
-{
- free(mapme);
+void mapme_free(mapme_t *mapme) {
+ loop_event_free(mapme->timer);
+ free(mapme);
}
/******************************************************************************
* TFIB
******************************************************************************/
-#define INVALID_SEQ 0
-#define INIT_SEQ 0
-
typedef struct {
+ // XXX We need magic number to know whether the TFIB was initialized or not
+ // ... or merge it inside the real data structure.
+ // NOTE: in VPP we reuse the nexthops in opposite order to gain room
+ // XXX need enough space in user_data !!
uint32_t seq;
- PARCHashMap *nexthops;
+ nexthops_t nexthops; // XXX useless shadow structure
/* Update/Notification heuristic */
- Ticks lastAckedUpdate;
-} MapMeTFIB;
+ Ticks last_acked_update;
+} mapme_tfib_t;
+
+#define TFIB(FIB_ENTRY) ((mapme_tfib_t *)fib_entry_get_user_data(FIB_ENTRY))
+
+static mapme_tfib_t *mapme_tfib_create() {
+ mapme_tfib_t *tfib;
+ tfib = malloc(sizeof(mapme_tfib_t));
+ if (!tfib) return NULL;
-static MapMeTFIB *mapmeTFIB_Create() {
- MapMeTFIB *tfib;
- tfib = malloc(sizeof(MapMeTFIB));
- if (!tfib) goto ERR_MALLOC;
+ // init
tfib->seq = INIT_SEQ;
- tfib->lastAckedUpdate = 0;
- tfib->nexthops = parcHashMap_Create();
- if (!tfib->nexthops) goto ERR_HASHMAP;
+ tfib->last_acked_update = 0;
+ nexthops_set_len(&tfib->nexthops, 0);
return tfib;
-
-ERR_HASHMAP:
- free(tfib);
-ERR_MALLOC:
- return NULL;
}
-static PARCIterator *mapmeTFIB_CreateKeyIterator(const MapMeTFIB *tfib) {
- /*
- * Creating an iterator on an empty HashMap seems to raise an exception
- * due to :
- * parcTrapOutOfMemoryIf(state->listIterator == NULL,
- * "Cannot create parcLinkedList_CreateIterator");
- * in : _parcHashMap_Init
- *
- * All buckets are empty, as they are after creation, and as they should be,
- * but the error is triggered.
- */
- if (parcHashMap_Size(tfib->nexthops) == 0)
- return NULL;
- return parcHashMap_CreateKeyIterator(tfib->nexthops);
+void mapme_release_tfib(mapme_tfib_t **tfibPtr) {
+ mapme_tfib_t *tfib = *tfibPtr;
+ free(tfib);
+ tfibPtr = NULL;
}
-void mapmeTFIB_Release(const MapMe * mapme, MapMeTFIB **tfibPtr);
-
/**
- * @function mapme_CreateTFIB
- * @abstract Associate a new TFIB entry to a FIB entry.
+ * @function mapme_create_tfib
+ * @abstract Associate a new TFIB entry to a FIB entry. If a TFIB already exists
+ * the new one will be used
* @param [in] - Pointer to the FIB entry.
* @return Boolean indicating the success of the operation.
*/
-static void mapme_CreateTFIB(const MapMe * mapme, FibEntry *fibEntry) {
- MapMeTFIB *tfib;
-
- /* Make sure we don't already have an associated TFIB entry */
- tfib = fibEntry_getUserData(fibEntry);
- // assertNull(tfib);
+static void mapme_create_tfib(const mapme_t *mapme, fib_entry_t *entry) {
+ mapme_tfib_t *tfib;
- tfib = mapmeTFIB_Create();
- fibEntry_setUserData(fibEntry, mapme, tfib, (void (*)(const void*, void**))mapmeTFIB_Release);
-}
-
-#define TFIB(fibEntry) ((MapMeTFIB *)fibEntry_getUserData(fibEntry))
-
-static const PARCEventTimer *mapmeTFIB_Get(const MapMeTFIB *tfib,
- unsigned conn_id) {
- const PARCEventTimer *timer;
- const PARCBuffer *buffer;
- PARCUnsigned *cid = parcUnsigned_Create(conn_id);
- buffer = parcHashMap_Get(tfib->nexthops, cid);
- if (!buffer) {
- timer = NULL;
- goto END;
- }
- PARCByteArray *array = parcBuffer_Array(buffer);
- timer = *((PARCEventTimer **)parcByteArray_Array(array));
-END:
- parcUnsigned_Release(&cid);
- return timer;
+ tfib = mapme_tfib_create();
+ fib_entry_set_user_data(entry, tfib, (void (*)(void **))mapme_release_tfib);
}
-static void mapmeTFIB_Put(MapMeTFIB *tfib, unsigned conn_id,
- const PARCEventTimer *timer) {
- /* NOTE: Timers are not objects (the only class not being an object in
- * fact), and as such, we cannot use them as values for the HashMap.
- * Just like for unsigned we needed the PARC wrapper.
- * There is no wrapper for pointers, so we use Arrays, which has an ubly
- * syntax...
- */
- PARCUnsigned *cid = parcUnsigned_Create(conn_id);
- PARCBuffer *buffer = parcBuffer_CreateFromArray(&timer, sizeof(PARCEventTimer *));
- parcHashMap_Put(tfib->nexthops, cid, buffer);
-
- parcUnsigned_Release(&cid);
- parcBuffer_Release(&buffer);
-}
-
-static void mapmeTFIB_Remove(const MapMe * mapme, MapMeTFIB *tfib, unsigned conn_id) {
- PARCUnsigned *cid = parcUnsigned_Create(conn_id);
-
- /* Release timer */
- const PARCBuffer *buffer = parcHashMap_Get(tfib->nexthops, cid);
- if (buffer) {
- PARCByteArray *array = parcBuffer_Array(buffer);
- PARCEventTimer * timer = *((PARCEventTimer **)parcByteArray_Array(array));
- if (timer) {
- parcEventTimer_Stop(timer);
- Dispatcher *dispatcher = forwarder_GetDispatcher(mapme->forwarder);
- dispatcher_DestroyTimerEvent(dispatcher, &timer);
- }
- }
-
- parcHashMap_Remove(tfib->nexthops, cid);
- parcUnsigned_Release(&cid);
-}
-
-void mapmeTFIB_Release(const MapMe * mapme, MapMeTFIB **tfibPtr) {
- MapMeTFIB *tfib = *tfibPtr;
-
- /* Release all TFIB entries, incl. timers */
- PARCIterator *iterator = mapmeTFIB_CreateKeyIterator(tfib);
- if (iterator) {
- /* No iterator is created if the TFIB is empty */
- while (parcIterator_HasNext(iterator)) {
- PARCUnsigned *cid = parcIterator_Next(iterator);
- unsigned conn_id = parcUnsigned_GetUnsigned(cid);
- mapmeTFIB_Remove(mapme, tfib, conn_id);
- }
- parcIterator_Release(&iterator);
- }
-
- parcHashMap_Release(&tfib->nexthops);
- free(tfib);
- *tfibPtr = NULL;
-}
-
-
int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) {
NameBitvector *bv = name_GetContentName(name);
ip_prefix_t ip_prefix;
@@ -263,500 +303,554 @@ int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) {
return hicn_prefix_create_from_ip_prefix(&ip_prefix, prefix);
}
-static Message *mapme_createMessage(const MapMe *mapme, const Name *name,
- mapme_params_t *params) {
- Ticks now = forwarder_GetTicks(mapme->forwarder);
- Logger *logger = forwarder_GetLogger(mapme->forwarder);
-
- INFO(mapme, "[MAP-Me] CreateMessage type=%d seq=%d", params->type,
- params->seq);
-
- hicn_prefix_t prefix;
- int rc = hicn_prefix_from_name(name, &prefix);
- if (rc < 0) {
- ERR(mapme, "[MAP-Me] Failed to create lib's name");
- goto ERR_NAME;
- }
-
-
- size_t size = (params->protocol == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN
- : HICN_MAPME_V4_HDRLEN;
- uint8_t *icmp_pkt = parcMemory_AllocateAndClear(size);
-
- INFO(mapme, "[MAP-Me] Creating MAP-Me packet");
- size_t len = hicn_mapme_create_packet(icmp_pkt, &prefix, params);
- if (len == 0) {
- ERR(mapme, "[MAP-Me] Failed to create mapme packet through lib");
- goto ERR_CREATE;
- }
-
- // hicn_packet_dump(icmp_pkt, MAPME_HDRLEN);
-
- return message_CreateFromByteArray(NO_INGRESS, icmp_pkt,
- MessagePacketType_Interest, now, logger);
-
-ERR_CREATE:
- parcMemory_Deallocate(&icmp_pkt);
-ERR_NAME:
- return NULL;
-}
-
-static Message *mapme_createAckMessage(const MapMe *mapme,
- const uint8_t *msgBuffer,
- const mapme_params_t *params) {
- Ticks now = forwarder_GetTicks(mapme->forwarder);
- Logger *logger = forwarder_GetLogger(mapme->forwarder);
-
- size_t size = (params->protocol == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN
- : HICN_MAPME_V4_HDRLEN;
- uint8_t *icmp_pkt = parcMemory_AllocateAndClear(size);
- memcpy(icmp_pkt, msgBuffer, size);
-
- size_t len = hicn_mapme_create_ack(icmp_pkt, params);
- if (len != size) {
- ERR(mapme, "[MAP-Me] Failed to create mapme ack packet through lib");
- goto ERR;
- }
-
- return message_CreateFromByteArray(
- NO_INGRESS, icmp_pkt, MessagePacketType_ContentObject, now, logger);
-
-ERR:
- parcMemory_Deallocate(&icmp_pkt);
- return NULL;
-}
-
-struct setFacePendingArgs {
- const MapMe *mapme;
- const Name *name;
- FibEntry *fibEntry;
- unsigned conn_id;
- bool send;
- bool is_producer;
- uint32_t num_retx;
-};
-
-static bool mapme_setFacePending(const MapMe *mapme, const Name *name,
- FibEntry *fibEntry, unsigned conn_id,
- bool send, bool is_producer, bool clear_tfib, uint32_t num_retx);
-
-static void mapme_setFacePendingCallback(int fd, PARCEventType which_event,
- void *data) {
- struct setFacePendingArgs *args = (struct setFacePendingArgs *)data;
-
- parcAssertTrue(which_event & PARCEventType_Timeout,
- "Event incorrect, expecting %X set, got %X",
- PARCEventType_Timeout, which_event);
-
- INFO(args->mapme, "Timeout during retransmission. Re-sending");
- mapme_setFacePending(args->mapme, args->name, args->fibEntry, args->conn_id,
- args->send, args->is_producer, false, args->num_retx);
- free(args);
-}
-
/**
* @brief Update/Notification heuristic:
*
* NOTE: IN are currently disabled until the proper placeholder is agreed in the
* interest header.
*/
-static hicn_mapme_type_t mapme_getTypeFromHeuristic(const MapMe *mapme,
- FibEntry *fibEntry) {
+static hicn_mapme_type_t mapme_get_type_from_heuristic(const mapme_t *mapme,
+ fib_entry_t *entry) {
+ if (fib_entry_has_local_nexthop(entry))
+ /* We are a producer for this entry, send update */
+ return UPDATE;
+
#if 0 /* interplay of IU/IN */
- if (TFIB(fibEntry)->lastAckedUpdate == 0) {
+ if (TFIB(fib_entry)->lastAckedUpdate == 0) {
return UPDATE;
} else {
- Ticks interval = now - TFIB(fibEntry)->lastAckedUpdate;
- return (T2NS(interval) > MS2NS(mapme->Tu)) ? UPDATE : NOTIFICATION;
+ Ticks interval = now - TFIB(fib_entry)->lastAckedUpdate;
+ return (T2NS(interval) > MS2NS(mapme->timescale)) ? UPDATE : NOTIFICATION;
}
#else /* Always send IU */
return UPDATE;
#endif
}
-static bool mapme_setFacePending(const MapMe *mapme, const Name *name,
- FibEntry *fibEntry, unsigned conn_id,
- bool send, bool is_producer, bool clear_tfib, uint32_t num_retx) {
- int rc;
+/**
+ *
+ * Here nexthops is not necessarily FIB nexthops as we might advertise given FIB
+ * entries on various other connections.
+ */
+/* NOTE: if the face is pending an we receive an IN, maybe we should not cancel
+ * the timer
+ */
+// XXX Make sure this function is never called for Notifications
+// XXX overall review notification code and integrate it in VPP
+int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry,
+ const nexthops_t *nexthops) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
+ }
- INFO(mapme, "[MAP-Me] SetFacePending connection=%d prefix=XX retx=%d",
- conn_id, num_retx);
+ mapme_tfib_t *tfib = TFIB(entry);
+ if (tfib == NULL) {
+ mapme_create_tfib(mapme, entry);
+ tfib = TFIB(entry);
+ }
- /* NOTE: if the face is pending an we receive an IN, maybe we should not
- * cancel the timer
- */
- Dispatcher *dispatcher = forwarder_GetDispatcher(mapme->forwarder);
- PARCEventTimer *timer;
+ const Name *name = fib_entry_get_prefix(entry);
- /* Safeguard during retransmissions */
- if (!TFIB(fibEntry))
- return true;
+ WITH_DEBUG({
+ char *name_str = name_ToString(name);
+ DEBUG("sending IU/IN for name %s on all nexthops", name_str);
+ free(name_str);
+ })
- /*
- * On the producer side, we have to clear the TFIB everytime we change the list
- * of adjacencies, otherwise retransmissions will occur to preserve them.
- */
- if (clear_tfib) {
- /*
- * It is likely we cannot iterator and remove elements from the hashmap at
- * the same time, so we proceed in two steps
- */
- if (parcHashMap_Size(TFIB(fibEntry)->nexthops) > 0) {
+ mapme_params_t params = {
+ .protocol = mapme->protocol,
+ .type = mapme_get_type_from_heuristic(mapme, entry),
+ .seq = tfib->seq,
+ };
- NumberSet * conns = numberSet_Create();
+ hicn_prefix_t prefix;
+ if (hicn_prefix_from_name(name, &prefix) < 0) {
+ ERROR("Failed to create lib's name");
+ return -1;
+ }
- PARCIterator *it = parcHashMap_CreateKeyIterator(TFIB(fibEntry)->nexthops);
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- unsigned conn_id = parcUnsigned_GetUnsigned(cid);
- numberSet_Add(conns, conn_id);
- }
- parcIterator_Release(&it);
+ uint8_t packet[MTU];
+ size_t size = hicn_mapme_create_packet(packet, &prefix, &params);
+ if (size <= 0) {
+ ERROR("Could not create MAP-Me packet");
+ return -1;
+ }
- for (size_t i = 0; i < numberSet_Length(conns); i++) {
- unsigned conn_id = numberSet_GetItem(conns, i);
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_id);
- }
+ connection_table_t *table = forwarder_get_connection_table(mapme->forwarder);
- numberSet_Release(&conns);
- }
- }
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ INFO("sending mapme packet on connection %d", nexthop);
+ const connection_t *conn = connection_table_get_by_id(table, nexthop);
+ connection_send_packet(conn, packet, size);
+ });
- // NOTE
- // - at producer, send always true, we always send something reliably so we
- // set the timer.
- // - in the network, we always forward an IU, and never an IN
- //if (is_producer || send) {
- if (send) {
- mapme_params_t params = {
- .protocol = IPPROTO_IPV6,
- .type = is_producer ? mapme_getTypeFromHeuristic(mapme, fibEntry) : UPDATE,
- .seq = TFIB(fibEntry)->seq};
- Message *special_interest = mapme_createMessage(mapme, name, &params);
- if (!special_interest) {
- INFO(mapme, "[MAP-Me] Could not create special interest");
- return false;
- }
+ return 0;
+}
- const ConnectionTable *table =
- forwarder_GetConnectionTable(mapme->forwarder);
- const Connection *conn =
- connectionTable_FindById((ConnectionTable *)table, conn_id);
- if (conn) {
- const Name * name = message_GetName(special_interest);
- char * name_str = name_ToString(name);
- INFO(mapme, "[MAP-Me] Sending MAP-Me packet name=%s seq=%d conn=%d",
- name_str, params.seq, conn_id);
- free(name_str);
- connection_ReSend(conn, special_interest, NOT_A_NOTIFICATION);
- } else {
- INFO(mapme, "[MAP-Me] Stopped retransmissions as face went down");
- }
- message_Release(&special_interest);
-
- if (num_retx < MAX_RETX) {
- INFO(mapme, "[MAP-Me] - Scheduling retransmission\n");
- /* Schedule retransmission */
- struct setFacePendingArgs *args =
- malloc(sizeof(struct setFacePendingArgs));
- if (!args)
- goto ERR_MALLOC;
- args->mapme = mapme;
- args->name = name;
- args->fibEntry = fibEntry;
- args->conn_id = conn_id;
- args->send = send;
- args->is_producer = is_producer;
- args->num_retx = num_retx + 1;
-
- timer = dispatcher_CreateTimer(dispatcher, TIMER_NO_REPEAT,
- mapme_setFacePendingCallback, args);
- struct timeval timeout = {mapme->retx / 1000,
- (mapme->retx % 1000) * 1000};
- rc = parcEventTimer_Start(timer, &timeout);
- if (rc < 0) {
- free(args);
- goto ERR_TIMER;
- }
- } else {
- INFO(mapme, "[MAP-Me] Last retransmission.");
- timer = NULL;
- }
- } else {
- INFO(mapme, "[MAP-Me] - not forwarding as send is False");
- timer = NULL;
+/**
+ *
+ * Here nexthops is not necessarily FIB nexthops as we might advertise given FIB
+ * entries on various other connections.
+ */
+void mapme_maybe_send_to_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry,
+ const nexthops_t *nexthops) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return;
}
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_id);
- mapmeTFIB_Put(TFIB(fibEntry), conn_id, timer);
+ /* Detect change */
+ if (!fib_entry_nexthops_changed(fib_entry)) {
+ INFO("No change in nexthops");
+ return;
+ }
+ fib_entry_set_prev_nexthops(fib_entry);
+
+ mapme_send_to_nexthops(mapme, fib_entry, nexthops);
+}
+
+/******************************************************************************
+ * MAPME API
+ ******************************************************************************/
+
+int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
+ }
- return true;
+ /* Apply the policy of the fib_entry over all neighbours */
+ nexthops_t new_nexthops = NEXTHOPS_EMPTY;
+ nexthops_t *nexthops =
+ fib_entry_get_available_nexthops(entry, ~0, &new_nexthops);
-ERR_TIMER:
- dispatcher_DestroyTimerEvent(dispatcher, &timer);
-ERR_MALLOC:
- return false;
+ /* We set force to true to avoid overriding the FIB cache */
+ return mapme_set_adjacencies(mapme, entry, nexthops, true);
}
-/*------------------------------------------------------------------------------
- * Event handling
- *----------------------------------------------------------------------------*/
+int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ nexthops_t *nexthops, bool force) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
+ }
-/*
- * Return true if we have at least one local connection as next hop
- */
-static bool mapme_hasLocalNextHops(const MapMe *mapme,
- const FibEntry *fibEntry) {
- const NumberSet *nexthops = fibEntry_GetNexthops(fibEntry);
- const ConnectionTable *table = forwarder_GetConnectionTable(mapme->forwarder);
-
- for (size_t j = 0; j < fibEntry_NexthopCount(fibEntry); j++) {
- /* Retrieve Nexthop #j */
- unsigned conn_id = numberSet_GetItem(nexthops, j);
- const Connection *conn =
- connectionTable_FindById((ConnectionTable *)table, conn_id);
-
- /* Ignore non-local connections */
- if (!connection_IsLocal(conn)) continue;
- /* We don't need to test against conn_added since we don't
- * expect it to have any entry in the FIB */
+ if (!fib_entry_has_local_nexthop(entry)) return -1;
- return true;
+ /* Advertise prefix on all available next hops (if needed) */
+ mapme_tfib_t *tfib = TFIB(entry);
+ if (tfib == NULL) {
+ mapme_create_tfib(mapme, entry);
+ tfib = TFIB(entry);
}
- return false;
-}
-void
-mapme_send_updates(const MapMe * mapme, FibEntry * fibEntry, const NumberSet * nexthops)
-{
- if (!TFIB(fibEntry)) /* Create TFIB associated to FIB entry */
- mapme_CreateTFIB(mapme, fibEntry);
- TFIB(fibEntry)->seq++;
-
- const Name *name = fibEntry_GetPrefix(fibEntry);
- char *name_str = name_ToString(name);
- bool clear_tfib = true;
-
- INFO(mapme, "[MAP-Me] Candidate next hops changed");
- for (size_t j = 0; j < numberSet_Length(nexthops); j++) {
- unsigned nexthop_id = numberSet_GetItem(nexthops, j);
-
- /* We extract the nexthop type based on tags */
- const char * nexthop_type;
- ConnectionTable * table = forwarder_GetConnectionTable(mapme->forwarder);
- const Connection * conn = connectionTable_FindById(table, nexthop_id);
- if (connection_HasTag(conn, POLICY_TAG_WIRED)) {
- nexthop_type = "WIRED";
- } else if (connection_HasTag(conn, POLICY_TAG_WIFI)) {
- nexthop_type = "WIFI";
- } else if (connection_HasTag(conn, POLICY_TAG_CELLULAR)) {
- nexthop_type = "CELLULAR";
- } else {
- nexthop_type = "UNKNOWN";
- }
+ nexthops_clear(&tfib->nexthops);
+ tfib->seq++;
- INFO(mapme, "[MAP-Me] sending IU/IN for name %s on connection %d - %s (%s)", name_str,
- nexthop_id, connection_GetInterfaceName(conn), nexthop_type);
- mapme_setFacePending(mapme, name, fibEntry, nexthop_id, true, true, clear_tfib, 0);
- clear_tfib = false;
+ if (force) {
+ mapme_send_to_nexthops(mapme, entry, nexthops);
+ return 0;
}
- INFO(mapme, "[MAP-Me] Done sending MAP-Me update");
- free(name_str);
+
+ mapme_maybe_send_to_nexthops(mapme, entry, nexthops);
+ return 0;
}
+int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ bool inc_iu_seq) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
+ }
-void
-mapme_maybe_send_updates(const MapMe * mapme, FibEntry * fibEntry, const NumberSet * nexthops)
-{
- /* Detect change */
- NumberSet * previous_nexthops = fibEntry_GetPreviousNextHops(fibEntry);
- if (numberSet_Equals(nexthops, previous_nexthops)) {
- INFO(mapme, "[MAP-Me] No change in nexthops");
- return;
+ mapme_tfib_t *tfib = TFIB(entry);
+ if (tfib == NULL) {
+ mapme_create_tfib(mapme, entry);
+ tfib = TFIB(entry);
}
- fibEntry_SetPreviousNextHops(fibEntry, nexthops);
- mapme_send_updates(mapme, fibEntry, nexthops);
+ if (inc_iu_seq) tfib->seq++;
+
+ mapme_maybe_send_to_nexthops(mapme, entry, &tfib->nexthops);
+ return 0;
}
-void
-mapme_reconsiderFibEntry(const MapMe *mapme, FibEntry * fibEntry)
-{
- /*
- * Skip entries that do not correspond to a producer ( / have a locally
- * served prefix / have no local connection as next hop)
- */
- if (!mapme_hasLocalNextHops(mapme, fibEntry))
- return;
+int mapme_send_to_nexthop(const mapme_t *mapme, fib_entry_t *entry,
+ unsigned nexthop) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
+ }
- /* Apply the policy of the fibEntry over all neighbours */
- NumberSet * available_nexthops = fibEntry_GetAvailableNextHops(fibEntry, ~0);
+ nexthops_t nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, nexthop);
- /* Advertise prefix on all available next hops (if needed) */
- mapme_send_updates(mapme, fibEntry, available_nexthops);
-
- numberSet_Release(&available_nexthops);
+ return mapme_send_to_nexthops(mapme, entry, &nexthops);
}
/*
* Callback called everytime a new connection is created by the control protocol
*/
-void
-mapme_onConnectionEvent(const MapMe *mapme, const Connection *conn_added, connection_event_t event) {
+void mapme_on_connection_event(const mapme_t *mapme,
+ const connection_t *conn_added,
+ connection_event_t event) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return;
+ }
+
/* Does the priority change impacts the default route selection; if so,
* advertise the prefix on this default route. If there are many default
* routes, either v4 v6, or many connections as next hops on this default
* route, then send to all.
*/
if (conn_added) {
- if (connection_IsLocal(conn_added))
- return;
+ if (connection_is_local(conn_added)) return;
- unsigned conn_added_id = connection_GetConnectionId(conn_added);
- switch(event) {
+ unsigned conn_added_id = connection_get_id(conn_added);
+ switch (event) {
case CONNECTION_EVENT_CREATE:
- INFO(mapme, "[MAP-Me] Connection %d got created", conn_added_id);
- break;
+ INFO("Connection %d got created", conn_added_id);
+ break;
case CONNECTION_EVENT_DELETE:
- INFO(mapme, "[MAP-Me] Connection %d got deleted", conn_added_id);
- break;
+ INFO("Connection %d got deleted", conn_added_id);
+ break;
case CONNECTION_EVENT_UPDATE:
- INFO(mapme, "[MAP-Me] Connection %d got updated", conn_added_id);
- break;
+ INFO("Connection %d got updated", conn_added_id);
+ break;
case CONNECTION_EVENT_SET_UP:
- INFO(mapme, "[MAP-Me] Connection %d went up", conn_added_id);
- break;
+ INFO("Connection %d went up", conn_added_id);
+ break;
case CONNECTION_EVENT_SET_DOWN:
- INFO(mapme, "[MAP-Me] Connection %d went down", conn_added_id);
- break;
+ INFO("Connection %d went down", conn_added_id);
+ break;
case CONNECTION_EVENT_TAGS_CHANGED:
- INFO(mapme, "[MAP-Me] Connection %d changed tags", conn_added_id);
- break;
+ INFO("Connection %d changed tags", conn_added_id);
+ break;
case CONNECTION_EVENT_PRIORITY_CHANGED:
- INFO(mapme, "[MAP-Me] Connection %d changed priority to %d",
- conn_added_id, connection_GetPriority(conn_added));
- break;
+ INFO("Connection %d changed priority to %d", conn_added_id,
+ connection_get_priority(conn_added));
+ break;
}
}
/* We need to send a MapMe update on the newly selected connections for
- * each concerned fibEntry : connection is involved, or no more involved */
- FibEntryList *fiblist = forwarder_GetFibEntries(mapme->forwarder);
-
- /* Iterate a first time on the FIB to get the locally served prefixes */
- for (size_t i = 0; i < fibEntryList_Length(fiblist); i++) {
- FibEntry *fibEntry = (FibEntry *)fibEntryList_Get(fiblist, i);
- mapme_reconsiderFibEntry(mapme, fibEntry);
- }
-
- fibEntryList_Destroy(&fiblist);
-
- INFO(mapme, "[MAP-Me] Done");
+ * each concerned fib_entry : connection is involved, or no more involved */
+ const fib_t *fib = forwarder_get_fib(mapme->forwarder);
+ fib_entry_t *entry;
+ fib_foreach_entry(fib, entry, { mapme_set_all_adjacencies(mapme, entry); });
}
/*------------------------------------------------------------------------------
* Special Interest handling
*----------------------------------------------------------------------------*/
-/**
- * @discussion This function is way too long and should be cut out
- */
-static bool mapme_onSpecialInterest(const MapMe *mapme,
- const uint8_t *msgBuffer,
- unsigned conn_in_id, hicn_prefix_t *prefix,
- mapme_params_t *params) {
- const ConnectionTable *table = forwarder_GetConnectionTable(mapme->forwarder);
- /* The cast is needed since connectionTable_FindById miss the
- * const qualifier for the first parameter */
- const Connection *conn_in =
- connectionTable_FindById((ConnectionTable *)table, conn_in_id);
- seq_t fibSeq, seq = params->seq;
- bool send = (params->type == UPDATE);
- bool rv;
-
- Name *name = name_CreateFromPacket(msgBuffer, MessagePacketType_Interest);
- name_setLen(name, prefix->len);
- char *name_str = name_ToString(name);
- INFO(mapme,
- "[MAP-Me] Ack'ed Special Interest on connection %d - prefix=%s type=XX "
- "seq=%d",
- conn_in_id, name_str, seq);
- free(name_str);
+// XXX this code has not been updated
+#ifdef MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+int mapme_create_fib_entry(const mapme_t *mapme, const Name *name,
+ unsigned ingress_id) {
+ INFO(" - Re-creating FIB entry with next hop on connection %d", ingress_id);
+ /*
+ * This might happen for a node hosting a producer which has moved.
+ * Destroying the face has led to removing all corresponding FIB
+ * entries. In that case, we need to correctly restore the FIB entries.
+ */
+ strategy_type fwdStrategy = LAST_STRATEGY_VALUE;
/*
- * Immediately send an acknowledgement back on the ingress connection
- * We always ack, even duplicates.
+ * It might also be due to the announcement of a more specific prefix. In
+ * that case we need to perform a FIB lookup to find the next hops to which
+ * the message should be propagated.
*/
- Message *ack = mapme_createAckMessage(mapme, msgBuffer, params);
- if (!ack) {
- name_Release(&name);
- return false;
+#ifdef WITH_POLICY
+ entry = fib_entry_Create(name, fwdStrategy, mapme->forwarder);
+#else
+ entry = fib_entry_Create(name, fwdStrategy);
+#endif /* WITH_POLICY */
+ fib_entry_t *lpm = fib_MatchName(fib, name);
+ fib_Add(fib, entry);
+ if (!lpm) {
+ TFIB(entry)->seq = seq;
+ fib_entry_AddNexthop(entry, ingress_id);
+ return true;
}
- rv = connection_ReSend(conn_in, ack, NOT_A_NOTIFICATION);
- message_Release(&ack);
- if (!rv) {
- name_Release(&name);
- return false;
+ /*
+ * We make a clone of the FIB entry (zero'ing the sequence number ?) with
+ * the more specific name, and proceed as usual. Worst case we clone the
+ * default route...
+ */
+ const NumberSet *lpm_nexthops = fib_entry_nexthops_get(lpm);
+ for (size_t i = 0; i < numberSet_Length(lpm_nexthops); i++) {
+ fib_entry_AddNexthop(entry, numberSet_GetItem(lpm_nexthops, i));
}
+ return 0;
+}
+#endif
- /* EPM on FIB */
- /* only the processor has access to the FIB */
- FIB *fib = forwarder_getFib(mapme->forwarder);
+int mapme_on_timeout(void *mapme_arg, int fd, void *data) {
+ mapme_t *mapme = mapme_arg;
+ assert(mapme);
+ assert(!data);
+ /* Timeout occurred, we have to retransmit IUs for all pending
+ * prefixes having entries in TFIB
+ *
+ * timeouts are slotted
+ * | | | |
+ *
+ * ^
+ * +- event occurred
+ * new face, wait for the second next
+ * (having two arrays and swapping cur and next)
+ * retx : put in next
+ */
+ mapme->idle += 1;
- FibEntry *fibEntry = fib_Contains(fib, name);
+ for (uint8_t pos = 0; pos < CURLEN; pos++) {
+ mapme_retx_t *retx = &CUR[pos];
- name_Release(&name);
+ if (!retx->entry) /* deleted entry */
+ continue;
- if (!fibEntry) {
- INFO(mapme, "Ignored update with no FIB entry");
- return 0;
-#if 0
- INFO(mapme,
- "[MAP-Me] - Re-creating FIB entry with next hop on connection %d",
- conn_in_id);
- /*
- * This might happen for a node hosting a producer which has moved.
- * Destroying the face has led to removing all corresponding FIB
- * entries. In that case, we need to correctly restore the FIB entries.
- */
- strategy_type fwdStrategy = LAST_STRATEGY_VALUE;
+ mapme_tfib_t *tfib = TFIB(retx->entry);
+ assert(tfib);
- /*
- * It might also be due to the announcement of a more specific prefix. In
- * that case we need to perform a FIB lookup to find the next hops to which
- * the message should be propagated.
+ /* Re-send interest for all entries */
+ mapme_update_adjacencies(mapme, retx->entry, false);
+
+ retx->retx_count++;
+ /* If we exceed the numver of retransmittion it means that all tfib
+ * entries have seens at least HICN_PARAM_RETX_MAX of retransmission
*/
-#ifdef WITH_POLICY
- fibEntry = fibEntry_Create(name, fwdStrategy, mapme->forwarder);
-#else
- fibEntry = fibEntry_Create(name, fwdStrategy);
-#endif /* WITH_POLICY */
- FibEntry *lpm = fib_MatchName(fib, name);
- mapme_CreateTFIB(mapme, fibEntry);
- fib_Add(fib, fibEntry);
- if (!lpm) {
- TFIB(fibEntry)->seq = seq;
- fibEntry_AddNexthop(fibEntry, conn_in_id);
- return true;
+ if (retx->retx_count < MAPME_MAX_RETX) {
+ /*
+ * We did some retransmissions, so let's reschedule a check in the
+ * next slot
+ */
+ NXT[NXTLEN++] = CUR[pos];
+ mapme->idle = 0;
+ } else {
+ WARN("Maximum retransmissions exceeded");
+ /* If we exceed the numver of retransmission it means that all TFIB
+ * entries have seens at least HICN_PARAM_RTX_MAX retransmissions.
+ * (Deletion might be slightly late).
+ *
+ * XXX document: when adding an entry in TFIB, we might exceed max
+ * retransmissions for previous entries that started retransmitting
+ * beforehand.
+ */
+ nexthops_clear(&tfib->nexthops);
}
+ }
- /*
- * We make a clone of the FIB entry (zero'ing the sequence number ?) with
- * the more specific name, and proceed as usual. Worst case we clone the
- * default route...
- */
- const NumberSet *lpm_nexthops = fibEntry_GetNexthops(lpm);
- for (size_t i = 0; i < numberSet_Length(lpm_nexthops); i++) {
- fibEntry_AddNexthop(fibEntry, numberSet_GetItem(lpm_nexthops, i));
+ /* Reset events in this slot and prepare for next one */
+ CURLEN = 0;
+ mapme->cur = NEXT_SLOT(mapme->cur);
+
+ /* After two empty slots, we disable the timer */
+ if (mapme->idle > 1) {
+ loop_event_unregister(mapme->timer);
+ }
+
+ return 0;
+}
+
+static void mapme_on_event(mapme_t *mapme, mapme_event_t event,
+ fib_entry_t *entry, unsigned ingress_id) {
+ switch (event) {
+#if 0
+ case HICN_MAPME_EVENT_FACE_ADD:
+ {
+ /*
+ * A face has been added:
+ * - In case of a local app face, we need to advertise a new prefix
+ * - For another local face type, we need to advertise local
+ * prefixes and schedule retransmissions
+ */
+ mapme_retx_t *retx_events = event_data;
+ for (uint8_t i = 0; i < vec_len (retx_events); i++) {
+ hicn_mapme_on_face_added(mapme, retx_events[i].dpo);
+ }
+
+ if (mapme->timer_fd == -1)
+ mapme->timer_fd = loop_register_timer(MAIN_LOOP,
+ mapme->retx, mapme, mapme_on_timeout, NULL);
+ mapme->idle = 0;
+ break;
+ }
+ case HICN_MAPME_EVENT_FACE_DEL:
+ if (mapme->timer_fd == -1)
+ mapme->timer_fd = loop_register_timer(MAIN_LOOP,
+ DEFAULT_TIMEOUT, mapme, mapme_on_timeout, NULL);
+ mapme->idle = 0;
+ break;
+#endif
+
+ case MAPME_EVENT_NH_SET:
+ /*
+ * An hICN FIB entry has been modified. All operations so far
+ * have been procedded in the nodes. Here we need to track
+ * retransmissions upon timeout: we mark the FIB entry as pending in
+ * the second-to-next slot
+ */
+
+ /*
+ * XXX Move this in doc
+ *
+ * The FIB entry has a new next hop, and its TFIB section has:
+ * - eventually previous prev hops for which a IU with a
+ * lower seqno has been sent
+ * - the prev hops that have just been added.
+ *
+ * We don't distinguish any and just send an updated IU to all
+ * of them. The retransmission of the latest IU to all
+ * facilitates the matching of ACKs to a single seqno which is
+ * the one stored in the FIB.
+ *
+ * Since we retransmit to all prev hops, we can remove this
+ * (T)FIB entry for the check at the end of the current slot.
+ */
+
+ /* Mark FIB entry as pending for second-to-next slot */
+ /*
+ * Transmit IU for all TFIB entries with latest seqno (we have
+ * at least one for sure!)
+ */
+ mapme_update_adjacencies(mapme, entry, false);
+
+ /* Delete entry_id from retransmissions in the current slot (if present)
+ * ... */
+ /* ... and schedule it for next slot (if not already) */
+ uint8_t j;
+ for (j = 0; j < CURLEN; j++) {
+ if (CUR[j].entry == entry) CUR[j].entry = NULL; /* sufficient */
+ }
+ for (j = 0; j < NXTLEN; j++) {
+ if (NXT[j].entry == entry) break;
+ }
+ if (j == NXTLEN) /* not found */
+ NXT[NXTLEN++] = (mapme_retx_t){
+ .entry = entry,
+ .retx_count = 0,
+ };
+
+ if (!loop_timer_is_enabled(mapme->timer)) {
+ if (loop_timer_register(mapme->timer, mapme->retx) < 0) {
+ ERROR("Error setting mapme timer.");
+ break;
+ }
+ }
+ mapme->idle = 0;
+ break;
+
+ case MAPME_EVENT_NH_ADD:
+ /*
+ * XXX move this in doc
+ *
+ * As per the description of states, this event should add the face
+ * to the list of next hops, and eventually remove it from TFIB.
+ * This corresponds to the multipath case.
+ *
+ * In all cases, we assume the propagation was already done when the first
+ * interest with the same sequence number was received, so we stop here
+ * No change in TFIB = no IU to send
+ *
+ * No change in timers.
+ */
+
+ // XXX useless
+#if 0
+ /* Add ingress face as next hop */
+ idle = 0;
+#endif
+ break;
+
+ case MAPME_EVENT_PH_ADD:
+ /* Back-propagation, interesting even for IN (desync) */
+ mapme_send_to_nexthop(mapme, entry, ingress_id);
+
+ mapme->idle = 0;
+ if (!loop_timer_is_enabled(mapme->timer))
+ loop_timer_register(mapme->timer, mapme->retx);
+ break;
+
+ case MAPME_EVENT_PH_DEL:
+ /* Ack : remove an element from TFIB */
+ break;
+
+ case MAPME_EVENT_FACE_ADD:
+ case MAPME_EVENT_FACE_DEL:
+
+ case MAPME_EVENT_UNDEFINED:
+ case MAPME_EVENT_N:
+ ERROR("Unexpected event");
+ break;
+ }
+}
+
+static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf,
+ unsigned ingress_id, hicn_prefix_t *prefix,
+ mapme_params_t *params) {
+ connection_table_t *table = forwarder_get_connection_table(mapme->forwarder);
+
+ /* The cast is needed since connectionTable_FindById miss the
+ * const qualifier for the first parameter */
+ const connection_t *conn_in = connection_table_get_by_id(table, ingress_id);
+
+ /*
+ * Immediately send an acknowledgement back on the ingress connection
+ * We always ack, even duplicates. Clone mgsbuf to avoid to overwrite the
+ * received message
+ */
+ msgbuf_t *ack;
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(mapme->forwarder);
+ off_t interest_offset = msgbuf_pool_get_id(msgbuf_pool, (msgbuf_t *)msgbuf);
+ msgbuf_pool_clone(msgbuf_pool, &ack, interest_offset);
+
+ uint8_t *ack_packet = msgbuf_get_packet(ack);
+ size_t size = hicn_mapme_create_ack(ack_packet, params);
+ if (connection_send_packet(conn_in, ack_packet, size) < 0) {
+ /* We accept the packet knowing we will get a retransmit */
+ ERROR("Failed to send ACK packet");
+ }
+
+ msgbuf_pool_put(msgbuf_pool, ack);
+
+ /* process received interest */
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ name_create_from_interest(packet, msgbuf_get_name(msgbuf));
+ Name name = EMPTY_NAME;
+ name_Copy(msgbuf_get_name(msgbuf), &name);
+ name_setLen(&name, prefix->len);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(&name);
+ DEBUG("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id,
+ name_str, params->seq);
+ free(name_str);
+ });
+
+ /* EPM on FIB */
+ const fib_t *fib = forwarder_get_fib(mapme->forwarder);
+ fib_entry_t *entry = fib_contains(fib, &name);
+ if (!entry) {
+#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+ if (mapme_create_fib_entry(mapme, &name, ingress_id) < 0) {
+ ERROR("Failed to create FIB entry");
+ return;
}
+#else
+ INFO("Ignored update with no FIB entry");
+ return;
#endif
+ }
- } else if (!TFIB(fibEntry)) {
- /* Create TFIB associated to FIB entry */
- INFO(mapme,
- "[MAP-Me] - Creating TFIB entry with default sequence number");
- mapme_CreateTFIB(mapme, fibEntry);
+ mapme_tfib_t *tfib = TFIB(entry);
+ if (tfib == NULL) {
+ mapme_create_tfib(mapme, entry);
+ tfib = TFIB(entry);
}
/*
@@ -767,102 +861,40 @@ static bool mapme_onSpecialInterest(const MapMe *mapme,
* Detection: we receive a message initially sent by ourselves, ie a message
* for which the prefix has a local next hop in the FIB.
*/
- if (mapme_hasLocalNextHops(mapme, fibEntry)) {
- INFO(mapme, "[MAP-Me] - Received original interest... Update complete");
- return true;
+ // XXX NOT IN VPP ?
+ if (fib_entry_has_local_nexthop(entry)) {
+ INFO("Received original interest... Update complete");
+ return;
}
- fibSeq = TFIB(fibEntry)->seq;
- if (seq > fibSeq) {
- INFO(mapme,
- "[MAP-Me] - Higher sequence number than FIB %d, updating seq and "
- "next hops",
- fibSeq);
- /* This has to be done first to allow processing SpecialInterestAck's */
- TFIB(fibEntry)->seq = seq;
-
- /* Reliably forward the IU on all prevHops */
- INFO(mapme, "[MAP-Me] - (1/3) processing prev hops");
- if (params->type == UPDATE) {
- PARCIterator *iterator = mapmeTFIB_CreateKeyIterator(TFIB(fibEntry));
- if (iterator) {
- /* No iterator is created if the TFIB is empty */
- while (parcIterator_HasNext(iterator)) {
- PARCUnsigned *cid = parcIterator_Next(iterator);
- unsigned conn_id = parcUnsigned_GetUnsigned(cid);
- INFO(mapme, "[MAP-Me] - Re-sending IU to pending connection %d",
- conn_id);
- mapme_setFacePending(mapme, fibEntry_GetPrefix(fibEntry), fibEntry,
- conn_id, false, false, false, 0);
- }
- parcIterator_Release(&iterator);
- }
- }
-
- /* nextHops -> prevHops
- *
- * We add to the list of pendingUpdates the current next hops, and
- * eventually forward them an IU too.
- *
- * Exception: nextHops -> nextHops
- * Because of retransmission issues, it is possible that a second interest
- * (with same of higher sequence number) is receive from a next-hop
- * interface. In that case, the face remains a next hop.
- */
- const NumberSet *nexthops_old = fibEntry_GetNexthops(fibEntry);
-
- /* We make a copy to be able to send IU _after_ updating next hops */
- NumberSet *nexthops = numberSet_Create();
- numberSet_AddSet(nexthops, nexthops_old);
+ mapme_event_t event = MAPME_EVENT_UNDEFINED;
+ if (params->seq > tfib->seq) {
+ INFO(
+ "MAPME IU seq %d > fib_seq %d, updating seq and next hops, new "
+ "nexthop=%d",
+ params->seq, tfib->seq, ingress_id);
+ /* This has to be done first to allow processing ack */
+ // XXX this should even be done before sending ack, as in VPP.
+ tfib->seq = params->seq;
- /* We are considering : * -> nextHops
- *
- * If inFace was a previous hop, we need to cancel the timer and remove
- * the entry. Also, the face should be added to next hops.
+ /*
+ * Move nexthops to TFIB... but ingress_id that lands in nexthops
*
- * Optimization : nextHops -> nextHops
- * - no next hop to add
- * - we know that inFace was not a previous hop since it was a next hop and
- * this forms a partition. No need for a search
- */
-
- INFO(mapme, "[MAP-Me] - (3/3) next hops ~~> prev hops");
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_in_id);
+ * This could might optimized for situations where nothing changes, but
+ * this is very unlikely if not impossible...
+ * */
+ unsigned prevhop;
+ nexthops_foreach(&entry->nexthops, prevhop,
+ { nexthops_add(&tfib->nexthops, prevhop); });
+ nexthops_remove(&tfib->nexthops, ingress_id);
+ nexthops_clear(&entry->nexthops);
+ nexthops_add(&entry->nexthops, ingress_id);
- /* Remove all next hops */
- for (size_t k = 0; k < numberSet_Length(nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(nexthops, k);
- INFO(mapme, "[MAP-Me] - Replaced next hops by connection %d", conn_id);
- fibEntry_RemoveNexthopByConnectionId(fibEntry, conn_id);
- }
- fibEntry_AddNexthop(fibEntry, conn_in_id);
-
- INFO(mapme, "[MAP-Me] - (2/3) processing next hops");
- bool complete = true;
- for (size_t k = 0; k < numberSet_Length(nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(nexthops, k);
- INFO(mapme, " - Next hop connection %d", conn_id);
- if (conn_id == conn_in_id) {
- INFO(mapme, " . Ignored this next hop since equal to ingress face");
- continue;
- }
+ event = MAPME_EVENT_NH_SET;
- INFO(mapme, "[MAP-Me] - Sending IU on current next hop connection %d",
- conn_id);
- mapme_setFacePending(mapme, fibEntry_GetPrefix(fibEntry), fibEntry,
- conn_id, send, false, false, 0);
- complete = false;
- }
+ // XXX tell things are complete if we have no IU to send
- /*
- * The update is completed when the IU could not be sent to any
- * other next hop.
- */
- if (complete) INFO(mapme, "[MAP-Me] - Update completed !");
-
- numberSet_Release(&nexthops);
-
- } else if (seq == fibSeq) {
+ } else if (params->seq == tfib->seq) {
/*
* Multipath, multihoming, multiple producers or duplicate interest
*
@@ -873,142 +905,83 @@ static bool mapme_onSpecialInterest(const MapMe *mapme,
* producer and that we received back our own IU. In that case, we just
* need to Ack and ignore it.
*/
-#if 0
- if (mapme_hasLocalNextHops(mapme, fibEntry)) {
- INFO(mapme, "[MAP-Me] - Received original interest... Update complete");
- return true;
- }
-#endif
+ DEBUG("params.seq %d == fib_seq %d, adding nethop %d", params->seq,
+ tfib->seq, ingress_id);
+
+ /* Move ingress to nexthops (and eventually remove it from TFIB) */
+ nexthops_add(&entry->nexthops, ingress_id);
+ nexthops_remove(&tfib->nexthops, ingress_id);
- INFO(mapme, "[MAP-Me] - Adding multipath next hop on connection %d",
- conn_in_id);
- fibEntry_AddNexthop(fibEntry, conn_in_id);
+ event = MAPME_EVENT_NH_ADD;
- } else { // seq < fibSeq
+ } else { // params->seq < tfib->seq
/*
* Face is propagating outdated information, we can just
* consider it as a prevHops. Send the special interest backwards with
* the new sequence number to reconciliate this outdated part of the
* arborescence.
*/
- INFO(
- mapme,
- "[MAP-Me] - Update interest %d -> %d sent backwards on connection %d",
- seq, fibSeq, conn_in_id);
- mapme_setFacePending(mapme, fibEntry_GetPrefix(fibEntry), fibEntry,
- conn_in_id, send, false, false, 0);
- }
-
- return true;
-}
-
-void mapme_onSpecialInterestAck(const MapMe *mapme, const uint8_t *msgBuffer,
- unsigned conn_in_id, hicn_prefix_t *prefix,
- mapme_params_t *params) {
- INFO(mapme, "[MAP-Me] Receive IU/IN Ack on connection %d", conn_in_id);
+ if (nexthops_contains(&entry->nexthops, ingress_id)) {
+ INFO("Ignored seq %d < fib_seq %d from current nexthop on face %d",
+ params->seq, tfib->seq, ingress_id);
+ return;
+ } else {
+ DEBUG("Received seq %d < fib_seq %d, sending backwards on face %d",
+ params->seq, tfib->seq, ingress_id);
+ nexthops_add(&tfib->nexthops, ingress_id);
+ }
- Name * name =
- name_CreateFromPacket(msgBuffer, MessagePacketType_ContentObject);
- name_setLen((Name*) name, prefix->len);
- char * name_str = name_ToString(name);
- INFO(mapme, "[MAP-Me] Received ack for name prefix=%s seq=%d on conn id=%d",
- name_str, params->seq, conn_in_id);
- free(name_str);
+ event = MAPME_EVENT_PH_ADD;
+ }
- FIB *fib = forwarder_getFib(mapme->forwarder);
- FibEntry *fibEntry = fib_Contains(fib, name);
+ /* Don't trigger events for notification unless we need to send interests
+ * backwards */
+ if ((params->type != UPDATE) && (event != MAPME_EVENT_PH_ADD)) return;
- name_Release(&name);
+ mapme_on_event(mapme, event, entry, ingress_id);
+}
- if (!fibEntry) {
+static void mapme_on_data(mapme_t *mapme, msgbuf_t *msgbuf, unsigned ingress_id,
+ hicn_prefix_t *prefix, mapme_params_t *params) {
+ INFO("Receive IU/IN Ack on connection %d", ingress_id);
+
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ name_create_from_data(packet, msgbuf_get_name(msgbuf));
+ Name name = EMPTY_NAME;
+ name_Copy(msgbuf_get_name(msgbuf), &name);
+ name_setLen(&name, prefix->len);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(&name);
+ DEBUG("Received ack for name prefix=%s seq=%d on conn id=%d", name_str,
+ params->seq, ingress_id);
+ free(name_str);
+ })
+
+ const fib_t *fib = forwarder_get_fib(mapme->forwarder);
+ fib_entry_t *entry = fib_contains(fib, &name);
+ if (!entry) {
+ INFO("Ignored ACK with no corresponding FIB entry");
return;
}
- parcAssertNotNull(fibEntry,
- "No corresponding FIB entry for name contained in IU Ack");
-
- /* Test if the latest pending update has been ack'ed, otherwise just ignore */
- seq_t seq = params->seq;
- if (seq != INVALID_SEQ) {
- seq_t fibSeq = TFIB(fibEntry)->seq;
-
- if (seq < fibSeq) {
-
- /* If we receive an old ack:
- * - either the connection is still a next hop and we have to ignore
- * the ack until we receive a further update with higher seqno
- * - or the connection is no more to be informed and the ack is
- * sufficient and we can remove future retransmissions
- */
-
- INFO(mapme,
- "[MAP-Me] - Ignored special interest Ack with seq=%u, expected %u",
- seq, fibSeq);
- return;
- }
- }
+ mapme_tfib_t *tfib = TFIB(entry);
/*
- * Ignore the Ack if no TFIB is present, or it has no corresponding entry
- * with the ingress face.
- * Note: previously, we were creating the TFIB entry
+ * As we always retransmit IU with the latest seq, we are not interested in
+ * ACKs with inferior seq
*/
- if (!TFIB(fibEntry)) {
- INFO(mapme, "[MAP-Me] - Ignored ACK for prefix with no TFIB entry");
- return;
- }
-
- PARCEventTimer *timer =
- (PARCEventTimer *)mapmeTFIB_Get(TFIB(fibEntry), conn_in_id);
- if (!timer) {
- INFO(mapme,
- "[MAP-Me] - Ignored ACK for prefix not having the Connection in "
- "TFIB entry. Possible duplicate ?");
+ if (params->seq < tfib->seq) {
+ INFO("Ignored ACK with seq %d < %d", params->seq, tfib->seq);
return;
}
- /* Stop timer and remove entry from TFIB */
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_in_id);
-
- INFO(mapme, "[MAP-Me] - Removing TFIB entry for ack on connection %d",
- conn_in_id);
+ nexthops_remove(&tfib->nexthops, ingress_id);
+ mapme_on_event(mapme, MAPME_EVENT_PH_DEL, entry, ingress_id);
/* We need to update the timestamp only for IU Acks, not for IN Acks */
if (params->type == UPDATE_ACK) {
- INFO(mapme, "[MAP-Me] - Updating LastAckedUpdate");
- TFIB(fibEntry)->lastAckedUpdate = forwarder_GetTicks(mapme->forwarder);
- }
-}
-
-/*-----------------------------------------------------------------------------
- * Overloaded functions
- *----------------------------------------------------------------------------*/
-
-/*
- * @abstract returns where to forward a normal interests(nexthops) defined by
- * mapme, it also set the sequnence number properly if needed
- */
-
-/******************************************************************************
- * Public functions (exposed in the .h)
- ******************************************************************************/
-
-/*
- * Returns true iif the message corresponds to a MAP-Me packet
- */
-bool mapme_isMapMe(const uint8_t *packet) {
- hicn_mapme_header_t * mapme = (hicn_mapme_header_t*)packet;
-
- switch(HICN_IP_VERSION(packet)) {
- case 4:
- if (mapme->v4.ip.protocol != IPPROTO_ICMP)
- return false;
- return HICN_IS_MAPME(mapme->v4.icmp_rd.type, mapme->v4.icmp_rd.code);
- case 6:
- if (mapme->v6.ip.nxt != IPPROTO_ICMPV6)
- return false;
- return HICN_IS_MAPME(mapme->v6.icmp_rd.type, mapme->v6.icmp_rd.code);
- default:
- return false;
+ INFO(" - Updating LastAckedUpdate");
+ tfib->last_acked_update = ticks_now();
}
}
@@ -1023,25 +996,68 @@ bool mapme_isMapMe(const uint8_t *packet) {
* MAP-Me (eg. ICMP packets) and return higher level messages that can be
* processed by MAP-Me core.
*/
-void mapme_Process(const MapMe *mapme, const uint8_t *msgBuffer,
- unsigned conn_id) {
+void mapme_process(mapme_t *mapme, msgbuf_t *msgbuf) {
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return;
+ }
+
hicn_prefix_t prefix;
mapme_params_t params;
- hicn_mapme_parse_packet(msgBuffer, &prefix, &params);
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ unsigned conn_id = msgbuf_get_connection_id(msgbuf);
+
+ int rc = hicn_mapme_parse_packet(packet, &prefix, &params);
+ if (rc < 0) return;
+
+ // XXX TYPE STR
+ DEBUG("Received interest type: %d seq: %d len:%d", params.type, params.seq,
+ prefix.len);
+
+ // XXX RENAME TYPES
switch (params.type) {
case UPDATE:
case NOTIFICATION:
- mapme_onSpecialInterest(mapme, msgBuffer, conn_id, &prefix, &params);
+ mapme_on_interest(mapme, msgbuf, conn_id, &prefix, &params);
break;
case UPDATE_ACK:
case NOTIFICATION_ACK:
- mapme_onSpecialInterestAck(mapme, msgBuffer, conn_id, &prefix, &params);
+ mapme_on_data(mapme, msgbuf, conn_id, &prefix, &params);
break;
default:
- ERR(mapme, "[MAP-Me] Unknown message");
+ ERROR("Unknown message");
break;
}
}
+/*
+ * Returns true iif the message corresponds to a MAP-Me packet
+ */
+bool mapme_match_packet(const uint8_t *packet) {
+ hicn_mapme_header_t *mapme = (hicn_mapme_header_t *)packet;
+
+ switch (HICN_IP_VERSION(packet)) {
+ case 4:
+ if (mapme->v4.ip.protocol != IPPROTO_ICMP) return false;
+ return HICN_IS_MAPME(mapme->v4.icmp_rd.type, mapme->v4.icmp_rd.code);
+ case 6:
+ if (mapme->v6.ip.nxt != IPPROTO_ICMPV6) return false;
+ return HICN_IS_MAPME(mapme->v6.icmp_rd.type, mapme->v6.icmp_rd.code);
+ default:
+ return false;
+ }
+}
+
+void mapme_set_enable(mapme_t *mapme, bool enable) { mapme->enabled = enable; }
+void mapme_set_discovery(mapme_t *mapme, bool enable) {
+ mapme->discovery = enable;
+}
+void mapme_set_timescale(mapme_t *mapme, uint32_t time) {
+ mapme->timescale = time;
+}
+void mapme_set_retransmision(mapme_t *mapme, uint32_t time) {
+ mapme->retx = time;
+}
+
#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/core/mapme.h b/hicn-light/src/hicn/core/mapme.h
index 72f8d536a..8c2ca477f 100644
--- a/hicn-light/src/hicn/core/mapme.h
+++ b/hicn-light/src/hicn/core/mapme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,29 +26,30 @@
#include <stdbool.h>
#include <stdint.h>
+#include <hicn/ctrl/hicn-light-ng.h>
#include <hicn/hicn.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/connection.h>
-#include <hicn/utils/commands.h>
-struct mapme;
-typedef struct mapme MapMe;
+#include "connection.h"
+#include "fib_entry.h"
+#include "msgbuf.h"
+
+typedef struct mapme_s mapme_t;
/**
* @function mapme_create
* @abstract Initializes MAP-Me state in the forwarder.
* @return bool - Boolean informing about the success of MAP-Me initialization.
*/
-bool mapme_create(MapMe **mapme, Forwarder *Forwarder);
+mapme_t *mapme_create(void *Forwarder);
/**
* @function mapme_free
* @abstract Free MAP-Me state in the forwarder.
*/
-void mapme_free(MapMe *mapme);
+void mapme_free(mapme_t *mapme);
/**
- * @function messageHandler_isMapMe
+ * @function messageHandler_is_mapme
* @abstract Identifies MAP-Me messages
* @discussion This function can be used by the forwarder to dispatch MAP-Me
* message to the appropriate processing function. Ideally this would be
@@ -56,48 +57,53 @@ void mapme_free(MapMe *mapme);
* @param [in] msgBuffer - The buffer to match
* @return A boolean indicating whether message is a MAP-Me control message.
*/
-bool mapme_isMapMe(const uint8_t *msgBuffer);
+bool mapme_match_packet(const uint8_t *msgBuffer);
/**
- * @function mapme_handleMapMeMessage
+ * @function mapme_handlemapme_tMessage
* @abstract Process a MAP-Me message.
* @param [in] mapme - Pointer to the MAP-Me data structure.
* @param [in] message - MAP-Me buffer
* @param [in] conn_id - Ingress connection id
*/
-void mapme_Process(const MapMe *mapme, const uint8_t *msgBuffer,
- unsigned conn_id);
+void mapme_process(mapme_t *mapme, msgbuf_t *msgbuf);
+/* mapme API */
/**
* @function mapme_send_updates
- * @abstract Trigger (if needed) the update for specified FIB entry and nexthops
+ * @abstract sends an update to all adjacencies. Used for face
+ * add/delete/changes (priority.tag) and policy
* @param [in] mapme - Pointer to the MAP-Me data structure.
- * @param [in] fibEntry - The FIB entry to consider
- * @param [in] nexthops - NumberSet holding the next hops on which to send the
- * update.
+ * @param [in] fib_entry - The FIB entry to consider
*/
-void mapme_send_updates(const MapMe * mapme, FibEntry * fibEntry, const NumberSet * nexthops);
+int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry);
/**
- * @function mapme_send_updates
- * @abstract Trigger the update for specified FIB entry and nexthops, only if needed
+ * @function mapme_set_adjacencies
+ * @abstract sends an update to the specified adjacencies. Used by forwarding
+ * strategies
* @param [in] mapme - Pointer to the MAP-Me data structure.
- * @param [in] fibEntry - The FIB entry to consider
- * @param [in] nexthops - NumberSet holding the next hops on which to send the
- * update.
+ * @param [in] fib_entry - The FIB entry to consider
+ * @param [in] nexthops - next hops on which to send the update.
*/
-void mapme_maybe_send_updates(const MapMe * mapme, FibEntry * fibEntry, const NumberSet * nexthops);
+int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ nexthops_t *nexthops, bool force);
/**
- * @function mapme_reconsiderFibEntry
- * @abstract Process a fib entry for changes that might trigger new updates
+ * @function mapme_update_adjacencies
+ * @abstract sends an update on previuos adjacencies. Used for IU forwarding,
+ * NAT and timeouts
+ * strategies
* @param [in] mapme - Pointer to the MAP-Me data structure.
- * @param [in] fibEntry - The FIB entry to consider
+ * @param [in] fib_entry - The FIB entry to consider
+ * @param [in] inc_iu_seq - if true, the seq number of the tfib/mapme iu will be
+ * increased by one
*/
-void mapme_reconsiderFibEntry(const MapMe *mapme, FibEntry * fibEntry);
+int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ bool inc_iu_seq);
/**
- * @function mapme_onConnectionEvent
+ * @function mapme_on_connection_event
* @abstract Callback following the addition of the face though the control
* protocol.
* @discussion This callback triggers the sending of control packets by MAP-Me.
@@ -105,19 +111,21 @@ void mapme_reconsiderFibEntry(const MapMe *mapme, FibEntry * fibEntry);
* @param [in] conn - The newly added connection.
* @param [in] event - Connection event
*/
-void mapme_onConnectionEvent(const MapMe *mapme, const Connection *conn, connection_event_t event);
+void mapme_on_connection_event(const mapme_t *mapme, const connection_t *conn,
+ connection_event_t event);
/**
- * @function mapme_getNextHops
+ * @function mapme_get_nexthops
* @abstract return the nexthops to forward interests defined by mapme, it
* covers also the case where local discovery mechanisms are trriggered.
*/
-NumberSet *mapme_getNextHops(const MapMe *mapme, FibEntry *fibEntry,
- const Message *interest);
-
-hicn_mapme_type_t mapme_PktType_To_LibHicnPktType(MessagePacketType type);
+// nexthops_t * mapme_get_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry,
+// const msgbuf_t *interest);
-MessagePacketType mapme_LibHicnPktType_To_PktType(hicn_mapme_type_t type);
+void mapme_set_enable(mapme_t *mapme, bool enable);
+void mapme_set_discovery(mapme_t *mapme, bool enable);
+void mapme_set_timescale(mapme_t *mapme, uint32_t time);
+void mapme_set_retransmision(mapme_t *mapme, uint32_t time);
#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/core/message.c b/hicn-light/src/hicn/core/message.c
deleted file mode 100644
index c28938320..000000000
--- a/hicn-light/src/hicn/core/message.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <hicn/core/forwarder.h>
-#include <hicn/core/message.h>
-#include <hicn/core/wldr.h>
-
-#include <hicn/core/messageHandler.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-#include <hicn/core/messagePacketType.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_EventBuffer.h>
-
-struct message {
- Logger *logger;
-
- Ticks receiveTime;
- unsigned ingressConnectionId;
-
- Name *name;
-
- uint8_t *messageHead;
-
- unsigned length;
-
- uint8_t packetType;
-
- unsigned refcount;
-};
-
-Message *message_Acquire(const Message *message) {
- Message *copy = (Message *)message;
- copy->refcount++;
- return copy;
-}
-
-Message *message_CreateFromEventBuffer(PARCEventBuffer *data, size_t dataLength,
- unsigned ingressConnectionId,
- Ticks receiveTime, Logger *logger) {
- // used by applications, we can get only interest or data packets
- Message *message = parcMemory_AllocateAndClear(sizeof(Message));
- parcAssertNotNull(message, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Message));
-
- message->logger = logger_Acquire(logger);
- message->receiveTime = receiveTime;
- message->ingressConnectionId = ingressConnectionId;
- message->length = (unsigned int)dataLength;
-
- message->messageHead = parcMemory_AllocateAndClear(dataLength);
- parcAssertNotNull(message->messageHead,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- dataLength);
-
- // copy the data because *data is destroyed in the connection.
- int res = parcEventBuffer_Read(data, message->messageHead, dataLength);
- if (res == -1) {
- return NULL;
- }
-
- if (messageHandler_IsInterest(message->messageHead)) {
- message->packetType = MessagePacketType_Interest;
- } else if (messageHandler_IsData(message->messageHead)) {
- message->packetType = MessagePacketType_ContentObject;
- } else {
- printf("Got a packet that is not a data nor an interest, drop it!\n");
- return NULL;
- }
- message->name =
- name_CreateFromPacket(message->messageHead, message->packetType);
-
- message->refcount = 1;
-
- return message;
-}
-
-Message *message_CreateFromByteArray(unsigned connid, uint8_t *pckt,
- MessagePacketType type, Ticks receiveTime,
- Logger *logger) {
- Message *message = parcMemory_AllocateAndClear(sizeof(Message));
- parcAssertNotNull(message, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Message));
-
- message->logger = logger_Acquire(logger);
- message->receiveTime = receiveTime;
- message->ingressConnectionId = connid;
- message->messageHead = pckt;
- message->length = messageHandler_GetTotalPacketLength(pckt);
- message->packetType = type;
-
- if (messageHandler_IsWldrNotification(pckt)) {
- message->name = NULL;
- } else {
- message->name =
- name_CreateFromPacket(message->messageHead, message->packetType);
- }
-
- message->refcount = 1;
-
- return message;
-}
-
-void message_Release(Message **messagePtr) {
- parcAssertNotNull(messagePtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*messagePtr,
- "Parameter must dereference to non-null pointer");
-
- Message *message = *messagePtr;
- parcAssertTrue(
- message->refcount > 0,
- "Invalid state: message_Release called on message with 0 references %p",
- (void *)message);
-
- message->refcount--;
- if (message->refcount == 0) {
- if (logger_IsLoggable(message->logger, LoggerFacility_Message,
- PARCLogLevel_Debug)) {
- logger_Log(message->logger, LoggerFacility_Message, PARCLogLevel_Debug,
- __func__, "Message %p destroyed", (void *)message);
- }
-
- logger_Release(&message->logger);
- if (message->name != NULL) name_Release(&message->name);
- parcMemory_Deallocate((void **)&message->messageHead);
- parcMemory_Deallocate((void **)&message);
- }
- *messagePtr = NULL;
-}
-
-bool message_Write(PARCEventQueue *parcEventQueue, const Message *message) {
- parcAssertNotNull(message, "Message parameter must be non-null");
- parcAssertNotNull(parcEventQueue, "Buffer parameter must be non-null");
-
- return parcEventQueue_Write(parcEventQueue, message->messageHead,
- message_Length(message));
-}
-
-size_t message_Length(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return message->length;
-}
-
-bool message_HasWldr(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return messageHandler_HasWldr(message->messageHead);
-}
-
-bool message_IsWldrNotification(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return messageHandler_IsWldrNotification(message->messageHead);
-}
-
-void message_ResetWldrLabel(Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- messageHandler_ResetWldrLabel(message->messageHead);
-}
-
-unsigned message_GetWldrLabel(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return messageHandler_GetWldrLabel(message->messageHead);
-}
-
-unsigned message_GetWldrExpectedLabel(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return messageHandler_GetExpectedWldrLabel(message->messageHead);
-}
-
-unsigned message_GetWldrLastReceived(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return messageHandler_GetWldrLastReceived(message->messageHead);
-}
-
-void message_SetWldrLabel(Message *message, uint16_t label) {
- parcAssertNotNull(message, "Parameter must be non-null");
- messageHandler_SetWldrLabel(message->messageHead, label);
-}
-
-Message *message_CreateWldrNotification(Message *original, uint16_t expected,
- uint16_t lastReceived) {
- parcAssertNotNull(original, "Parameter original must be non-null");
- Message *message = parcMemory_AllocateAndClear(sizeof(Message));
- parcAssertNotNull(message, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Message));
- message->receiveTime = original->receiveTime;
- message->ingressConnectionId = original->ingressConnectionId;
- message->refcount = 1;
- message->logger = logger_Acquire(original->logger);
-
- message->length = (unsigned int)messageHandler_GetICMPPacketSize(
- messageHandler_GetIPPacketType(original->messageHead));
- message->messageHead = parcMemory_AllocateAndClear(message->length);
- parcAssertNotNull(message->messageHead,
- "parcMemory_AllocateAndClear returned NULL");
-
- message->packetType = MessagePacketType_WldrNotification;
- message->name = NULL; // nobody will use the name in a notification packet,
- // so we can simply set it to NULL
-
- // set notification stuff.
- messageHandler_SetWldrNotification(
- message->messageHead, original->messageHead, expected, lastReceived);
- return message;
-}
-
-unsigned message_GetIngressConnectionId(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return message->ingressConnectionId;
-}
-
-void message_SetIngressConnectionId(Message *message, unsigned conn) {
- parcAssertNotNull(message, "Parameter must be non-null");
- message->ingressConnectionId = conn;
-}
-
-Ticks message_GetReceiveTime(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return message->receiveTime;
-}
-
-uint32_t message_GetPathLabel(const Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- return messageHandler_GetPathLabel(message->messageHead);
-}
-
-void message_SetPathLabel(Message *message, uint32_t label) {
- parcAssertNotNull(message, "Parameter must be non-null");
- messageHandler_SetPathLabel(message->messageHead,
- messageHandler_GetPathLabel(message->messageHead), label);
-}
-
-void message_UpdatePathLabel(Message *message, uint8_t outFace) {
- parcAssertNotNull(message, "Parameter must be non-null");
- messageHandler_UpdatePathLabel(message->messageHead, outFace);
-}
-
-void message_ResetPathLabel(Message *message) {
- parcAssertNotNull(message, "Parameter must be non-null");
- messageHandler_ResetPathLabel(message->messageHead);
-}
-
-MessagePacketType message_GetType(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- return message->packetType;
-}
-
-Name *message_GetName(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- return message->name;
-}
-
-bool message_HasInterestLifetime(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- return messageHandler_HasInterestLifetime(message->messageHead);
-}
-
-uint64_t message_GetInterestLifetimeTicks(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- uint64_t lifetime = messageHandler_GetInterestLifetime(message->messageHead);
- return forwarder_NanosToTicks(lifetime * 1000000ULL);
-}
-
-bool message_HasContentExpiryTime(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- return messageHandler_HasContentExpiryTime(message->messageHead);
-}
-
-uint64_t message_GetContentExpiryTimeTicks(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- uint64_t expire = messageHandler_GetContentExpiryTime(message->messageHead);
- if(expire == 0)
- return message->receiveTime;
- return message->receiveTime + forwarder_NanosToTicks(expire * 1000000ULL);
-}
-
-const uint8_t *message_FixedHeader(const Message *message) {
- parcAssertNotNull(message, "Parameter message must be non-null");
- return message->messageHead;
-}
diff --git a/hicn-light/src/hicn/core/message.h b/hicn-light/src/hicn/core/message.h
deleted file mode 100644
index e77dab2b5..000000000
--- a/hicn-light/src/hicn/core/message.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file message.h
- * @brief Message is the unit of forwarding, i.e. the packets being switched
- *
- */
-#ifndef message_h
-#define message_h
-
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/logger.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/core/streamBuffer.h>
-
-#include <hicn/core/name.h>
-
-#include <parc/algol/parc_EventBuffer.h>
-#include <parc/algol/parc_EventQueue.h>
-
-#include <hicn/utils/address.h>
-
-#include <hicn/core/ticks.h>
-
-struct message;
-typedef struct message Message;
-
-/**
- * @function message_CreateFromBuffer
- * @abstract Takes ownership of the input buffer, which comprises one complete
- * message
- */
-
-Message *message_CreateFromEventBuffer(PARCEventBuffer *data, size_t dataLength,
- unsigned ingressConnectionId,
- Ticks receiveTime, Logger *logger);
-
-/**
- * @function message_CreateFromByteArray
- * @abstract create a message from a byte array
- */
-
-Message *message_CreateFromByteArray(unsigned connid, uint8_t *pckt,
- MessagePacketType type, Ticks receiveTime,
- Logger *logger);
-
-/**
- * @function message_Copy
- * @abstract Get a reference counted copy
- */
-
-Message *message_Acquire(const Message *message);
-
-/**
- * Releases the message and frees the memory
- */
-void message_Release(Message **messagePtr);
-
-/**
- * Writes the message to the queue
- */
-
-bool message_Write(PARCEventQueue *parcEventQueue, const Message *message);
-
-/**
- * Returns the total byte length of the message
- */
-size_t message_Length(const Message *message);
-
-bool message_HasWldr(const Message *message);
-
-bool message_IsWldrNotification(const Message *message);
-
-void message_ResetWldrLabel(Message *message);
-
-unsigned message_GetWldrLabel(const Message *message);
-
-unsigned message_GetWldrExpectedLabel(const Message *message);
-
-unsigned message_GetWldrLastReceived(const Message *message);
-
-void message_SetWldrLabel(Message *message, uint16_t label);
-
-Message *message_CreateWldrNotification(Message *original, uint16_t expected,
- uint16_t lastReceived);
-/**
- * Returns the connection id of the packet input
- */
-unsigned message_GetIngressConnectionId(const Message *message);
-
-void message_SetIngressConnectionId(Message *message, unsigned conn);
-
-/**
- * Returns the receive time (in router ticks) of the message
- */
-Ticks message_GetReceiveTime(const Message *message);
-
-/**
- * Returns the PacketType
- */
-MessagePacketType message_GetType(const Message *message);
-
-uint32_t message_GetPathLabel(const Message *message);
-void message_SetPathLabel(Message *message, uint32_t label);
-void message_UpdatePathLabel(Message *message, uint8_t outFace);
-void message_ResetPathLabel(Message *message);
-
-// ===========================================================
-// Accessors used to index and compare messages
-
-/**
- * @function message_GetName
- * @abstract The name in the message
- * @discussion
- * The name of the Interest or Content Object. If the caller will store the
- * name, he should make a reference counted copy.
- * @return The name as stored in the message object.
- */
-
-Name *message_GetName(const Message *message);
-
-/**
- * Determines if the message has an Interest Lifetime parameter
- *
- * @param [in] message An allocated and parsed Message
- *
- * @retval true If an Intrerest Lifetime field exists
- * @retval false If no Interest Lifetime exists
- */
-
-bool message_HasInterestLifetime(const Message *message);
-
-/**
- * Returns the Interest lifetime in hicn-light Ticks
- *
- * the interest expires after now + returned ticks
- *
- * @param [in] message An allocated and parsed Message
- *
- * @retval integer Lifetime in forwarder Ticks
- *
- */
-
-uint64_t message_GetInterestLifetimeTicks(const Message *message);
-
-/**
- * checks if the expiry time is set inside the content object
- */
-bool message_HasContentExpiryTime(const Message *message);
-
-/**
- * returns the moment (in hicn-light ticks) when the content object will expire
- */
-uint64_t message_GetContentExpiryTimeTicks(const Message *message);
-
-/**
- * Returns a pointer to the beginning of the FixedHeader
- *
- * @param [in] message An allocated and parsed Message
- *
- * @return non-null The fixed header memory
- * @return null No fixed header or an error
- */
-
-const uint8_t *message_FixedHeader(const Message *message);
-
-#endif // message_h
diff --git a/hicn-light/src/hicn/core/messageHandler.h b/hicn-light/src/hicn/core/messageHandler.h
index b41c9a7f0..fe26d0579 100644
--- a/hicn-light/src/hicn/core/messageHandler.h
+++ b/hicn-light/src/hicn/core/messageHandler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,16 +13,17 @@
* limitations under the License.
*/
-#ifndef messageHandler
-#define messageHandler
+#ifndef HICNLIGHT_MESSAGE_HANDLER_H
+#define HICNLIGHT_MESSAGE_HANDLER_H
#include <stdlib.h>
#ifndef _WIN32
-#include <unistd.h> // close
-#endif
+#include <unistd.h> // close
+#endif /* _WIN32 */
#include <hicn/hicn.h>
-#include <hicn/core/messagePacketType.h>
+
+//#include <hicn/core/connection_table.h>
#define H(packet) ((hicn_header_t *)packet)
#define H6(packet) (H(packet)->v6.ip)
@@ -49,21 +50,21 @@
#define CONTROL_PORT 9695
#define HTTP_PORT 8080
+#define MIN_PROBE_SUFFIX 0xefffffff
+#define MAX_PROBE_SUFFIX 0xffffffff - 1
+
+// XXX Hardcoded packet format HF_INET6_TCP
+
#define IPV6_DEFAULT_VERSION 6
#define IPV6_DEFAULT_TRAFFIC_CLASS 0
#define IPV6_DEFAULT_FLOW_LABEL 0
-#define expected_lbl wldr_notification_lbl.expected_lbl
-#define received_lbl wldr_notification_lbl.received_lbl
+//#include <hicn/core/forwarder.h>
-#include <hicn/core/forwarder.h>
-
-#ifdef WITH_MAPME
-#include <hicn/core/mapme.h>
-#include <hicn/socket/api.h>
-#endif /* WITH_MAPME */
-
-#define CONNECTION_ID_UNDEFINED -1
+//#ifdef WITH_MAPME
+//#include <hicn/core/mapme.h>
+//#include <hicn/socket/api.h>
+//#endif /* WITH_MAPME */
#define BFD_PORT 3784
@@ -157,6 +158,7 @@ static inline size_t messageHandler_GetIPHeaderLength(unsigned ipVersion) {
return 0;
}
+#if 0
static inline bool messageHandler_IsValidHicnPacket(const uint8_t *message) {
uint8_t version = messageHandler_GetIPPacketType(message);
if (version == IPv6_TYPE || version == IPv4_TYPE) {
@@ -164,6 +166,7 @@ static inline bool messageHandler_IsValidHicnPacket(const uint8_t *message) {
}
return false;
}
+#endif
static inline uint8_t messageHandler_NextHeaderType(const uint8_t *message) {
switch (messageHandler_GetIPPacketType(message)) {
@@ -176,155 +179,6 @@ static inline uint8_t messageHandler_NextHeaderType(const uint8_t *message) {
}
}
-/* Forward declarations */
-static inline void * messageHandler_GetSource(const uint8_t *message);
-static inline void *messageHandler_GetDestination(const uint8_t *message);
-
-static const
-AddressPair *
-_createRecvAddressPairFromPacket(const uint8_t *msgBuffer) {
- Address *packetSrcAddr = NULL; /* This one is in the packet */
- Address *localAddr = NULL; /* This one is to be determined */
-
- if (messageHandler_GetIPPacketType(msgBuffer) == IPv6_TYPE) {
- struct sockaddr_in6 addr_in6;
- addr_in6.sin6_family = AF_INET6;
- addr_in6.sin6_port = htons(1234);
- addr_in6.sin6_flowinfo = 0;
- addr_in6.sin6_scope_id = 0;
- memcpy(&addr_in6.sin6_addr,
- (struct in6_addr *)messageHandler_GetSource(msgBuffer), 16);
- packetSrcAddr = addressCreateFromInet6(&addr_in6);
-
- /* We now determine the local address used to reach the packet src address */
- int sock = (int)socket (AF_INET6, SOCK_DGRAM, 0);
- if (sock < 0)
- goto ERR;
-
- struct sockaddr_in6 remote, local;
- memset(&remote, 0, sizeof(remote));
- remote.sin6_family = AF_INET6;
- remote.sin6_addr = addr_in6.sin6_addr;
- remote.sin6_port = htons(1234);
-
- socklen_t locallen = sizeof(local);
- if (connect(sock, (const struct sockaddr*)&remote, sizeof(remote)) == -1)
- goto ERR;
- if (getsockname(sock, (struct sockaddr*) &local, &locallen) == -1)
- goto ERR;
-
- local.sin6_port = htons(1234);
- localAddr = addressCreateFromInet6(&local);
-
- close(sock);
-
- } else if (messageHandler_GetIPPacketType(msgBuffer) == IPv4_TYPE) {
- struct sockaddr_in addr_in;
- addr_in.sin_family = AF_INET;
- addr_in.sin_port = htons(1234);
- memcpy(&addr_in.sin_addr,
- (struct in_addr *)messageHandler_GetSource(msgBuffer), 4);
- packetSrcAddr = addressCreateFromInet(&addr_in);
-
- /* We now determine the local address used to reach the packet src address */
-
- int sock = (int)socket (AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- perror("Socket error");
- goto ERR;
- }
-
- struct sockaddr_in remote, local;
- memset(&remote, 0, sizeof(remote));
- remote.sin_family = AF_INET;
- remote.sin_addr = addr_in.sin_addr;
- remote.sin_port = htons(1234);
-
- socklen_t locallen = sizeof(local);
- if (connect(sock, (const struct sockaddr*)&remote, sizeof(remote)) == -1)
- goto ERR;
- if (getsockname(sock, (struct sockaddr*) &local, &locallen) == -1)
- goto ERR;
-
- local.sin_port = htons(1234);
- localAddr = addressCreateFromInet(&local);
-
- close(sock);
- }
- /* As this is a receive pair, we swap src and dst */
- return addressPair_Create(localAddr, packetSrcAddr);
-
-ERR:
- perror("Socket error");
- return NULL;
-}
-
-/* Main hook handler */
-
-/**
- * \brief Handle incoming messages
- * \param [in] forwarder - Reference to the Forwarder instance
- * \param [in] packet - Packet buffer
- * \param [in] conn_id - A hint on the connection ID on which the packet
- * was received
- * \return Flag indicating whether the packet matched a hook and was
- * (successfully or not) processed.
- */
-static inline bool messageHandler_handleHooks(Forwarder * forwarder,
- const uint8_t * packet, ListenerOps * listener, int fd, AddressPair * pair)
-{
- bool is_matched = false;
-
- /* BEGIN Match */
-
-#ifdef WITH_MAPME
- bool is_mapme = mapme_isMapMe(packet);
- is_matched |= is_mapme;
-#endif /* WITH_MAPME */
-
- /* ... */
-
- /* END Match */
-
- if (!is_matched)
- return false;
-
- /*
- * Find existing connection or create a new one (we assume all processing
- * requires a valid connection.
- */
-
- if (!pair) {
- /* The hICN listener does not provide any address pair while UDP does */
- const AddressPair * pair = _createRecvAddressPairFromPacket(packet);
- if (!pair)
- return false;
- }
-
- /* Find connection and eventually create it */
- const Connection * conn = connectionTable_FindByAddressPair(
- forwarder_GetConnectionTable(forwarder), pair);
- unsigned conn_id;
- if (conn == NULL) {
- conn_id = listener->createConnection(listener, fd, pair);
- } else {
- conn_id = connection_GetConnectionId(conn);
- }
-
- /* BEGIN Process */
-
-#ifdef WITH_MAPME
- if (mapme_isMapMe(packet))
- forwarder_ProcessMapMe(forwarder, packet, conn_id);
-#endif /* WITH_MAPME */
-
- /* ... */
-
- /* END Process */
- parcMemory_Deallocate((void **)&packet);
- return true;
-}
-
static inline bool messageHandler_IsTCP(const uint8_t *message) {
if (messageHandler_NextHeaderType(message) != IPPROTO_TCP) return false;
return true;
@@ -432,7 +286,8 @@ static inline uint16_t messageHandler_GetExpectedWldrLabel(
return 0;
}
- return ntohs(((_icmp_wldr_header_t *)icmp_ptr)->expected_lbl);
+ return ntohs(
+ ((_icmp_wldr_header_t *)icmp_ptr)->wldr_notification_lbl.expected_lbl);
}
static inline uint16_t messageHandler_GetWldrLastReceived(
@@ -449,7 +304,8 @@ static inline uint16_t messageHandler_GetWldrLastReceived(
return 0;
}
- return ntohs(((_icmp_wldr_header_t *)icmp_ptr)->received_lbl);
+ return ntohs(
+ ((_icmp_wldr_header_t *)icmp_ptr)->wldr_notification_lbl.received_lbl);
}
static inline uint16_t messageHandler_GetWldrLabel(const uint8_t *message) {
@@ -524,6 +380,7 @@ static inline void messageHandler_UpdatePathLabel(uint8_t *message,
uint32_t pl_new_32bit =
(uint32_t)((((pl_old_8bit << 1) | (pl_old_8bit >> 7)) ^ outFace) << 24UL);
+ // XXX path label should be 8 bits now ?
messageHandler_SetPathLabel(message, pl_old_32bit, pl_new_32bit);
}
@@ -531,7 +388,7 @@ static inline void messageHandler_ResetPathLabel(uint8_t *message) {
messageHandler_SetPathLabel(message, messageHandler_GetPathLabel(message), 0);
}
-static inline uint16_t messageHandler_GetInterestLifetime(
+static inline uint32_t messageHandler_GetInterestLifetime(
const uint8_t *message) {
if (!messageHandler_IsTCP(message)) return 0;
@@ -541,6 +398,24 @@ static inline uint16_t messageHandler_GetInterestLifetime(
return lifetime;
}
+static inline bool messageHandler_SetInterestLifetime(uint8_t *message,
+ u32 lifetime) {
+ if (!messageHandler_IsTCP(message)) return false;
+
+ int res = hicn_interest_set_lifetime((hicn_header_t *)message, lifetime);
+ if (res < 0) return false;
+ return true;
+}
+
+static inline bool messageHandler_SetDataExpiryTime(uint8_t *message,
+ u32 lifetime) {
+ if (!messageHandler_IsTCP(message)) return false;
+
+ int res = hicn_data_set_expiry_time((hicn_header_t *)message, lifetime);
+ if (res < 0) return false;
+ return true;
+}
+
static inline bool messageHandler_HasInterestLifetime(const uint8_t *message) {
if (!messageHandler_IsTCP(message)) return false;
@@ -650,7 +525,7 @@ static inline void messageHandler_SetWldrNotification(uint8_t *notification,
case IPv6_TYPE: {
*h = (hicn_header_t){.v6 = {
.ip =
- {
+ (_ipv6_header_t){
.version_class_flow = htonl(
(IPV6_DEFAULT_VERSION << 28) |
(IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
@@ -659,13 +534,17 @@ static inline void messageHandler_SetWldrNotification(uint8_t *notification,
.nxt = IPPROTO_ICMPV6,
.hlim = 5,
},
+ /*
.wldr =
{
.type = ICMP_WLDR_TYPE,
.code = ICMP_WLDR_CODE,
- .expected_lbl = htons(expected),
- .received_lbl = htons(received),
- },
+ .wldr_notification_lbl =
+ {
+ .expected_lbl = htons(expected),
+ .received_lbl = htons(received),
+ },
+ },*/
}};
messageHandler_SetSource_IPv6(
notification,
@@ -682,56 +561,78 @@ static inline void messageHandler_SetWldrNotification(uint8_t *notification,
}
}
-static inline uint8_t * messageHandler_CreateProbePacket(hicn_format_t format,
- uint32_t probe_lifetime){
+static inline void messageHandler_ModifySuffix(uint8_t *packet,
+ uint32_t new_suffix) {
+ hicn_format_t format;
+ hicn_name_t name;
+ hicn_packet_get_format((hicn_header_t *)packet, &format);
+ hicn_interest_get_name(format, (hicn_header_t *)packet, &name);
+ hicn_name_set_seq_number(&name, new_suffix);
+ hicn_interest_set_name(format, (hicn_header_t *)packet, &name);
+}
+
+static inline uint8_t *messageHandler_CreateProbePacket(
+ hicn_format_t format, uint32_t probe_lifetime) {
size_t header_length;
hicn_packet_get_header_length_from_format(format, &header_length);
- uint8_t *pkt = parcMemory_AllocateAndClear(header_length);
+ uint8_t *pkt = (uint8_t *)calloc(header_length, 1);
- hicn_packet_init_header(format, (hicn_header_t *) pkt);
+ hicn_packet_init_header(format, (hicn_header_t *)pkt);
- hicn_packet_set_dst_port(format, (hicn_header_t *) pkt, BFD_PORT);
- hicn_interest_set_lifetime ((hicn_header_t *) pkt, probe_lifetime);
+ hicn_packet_set_dst_port(format, (hicn_header_t *)pkt, BFD_PORT);
+ hicn_interest_set_lifetime((hicn_header_t *)pkt, probe_lifetime);
return pkt;
}
-static inline void messageHandler_CreateProbeReply(uint8_t * probe,
- hicn_format_t format){
-
+static inline void messageHandler_CreateProbeReply(uint8_t *probe,
+ hicn_format_t format) {
hicn_name_t probe_name;
- hicn_interest_get_name (format,
- (const hicn_header_t *) probe, &probe_name);
+ hicn_interest_get_name(format, (const hicn_header_t *)probe, &probe_name);
ip_address_t probe_locator;
- hicn_interest_get_locator (format,
- (const hicn_header_t *) probe, &probe_locator);
+ hicn_interest_get_locator(format, (const hicn_header_t *)probe,
+ &probe_locator);
uint16_t src_prt;
uint16_t dst_prt;
- hicn_packet_get_src_port(format, (const hicn_header_t *) probe, &src_prt);
- hicn_packet_get_dst_port(format, (const hicn_header_t *) probe, &dst_prt);
- hicn_packet_set_src_port(format, (hicn_header_t *) probe, dst_prt);
- hicn_packet_set_dst_port(format, (hicn_header_t *) probe, src_prt);
+ hicn_packet_get_src_port(format, (const hicn_header_t *)probe, &src_prt);
+ hicn_packet_get_dst_port(format, (const hicn_header_t *)probe, &dst_prt);
+ hicn_packet_set_src_port(format, (hicn_header_t *)probe, dst_prt);
+ hicn_packet_set_dst_port(format, (hicn_header_t *)probe, src_prt);
- hicn_data_set_name (format, (hicn_header_t *) probe, &probe_name);
- hicn_data_set_locator (format, (hicn_header_t *) probe, &probe_locator);
- hicn_data_set_expiry_time ((hicn_header_t *) probe, 0);
+ hicn_data_set_name(format, (hicn_header_t *)probe, &probe_name);
+ hicn_data_set_locator(format, (hicn_header_t *)probe, &probe_locator);
+ hicn_data_set_expiry_time((hicn_header_t *)probe, 0);
}
-static inline hicn_name_t * messageHandler_CreateProbeName(const ip_prefix_t *address){
- hicn_name_t * name = parcMemory_AllocateAndClear(sizeof(hicn_name_t));
+static inline hicn_name_t *messageHandler_CreateProbeName(
+ const ip_prefix_t *address) {
+ hicn_name_t *name = (hicn_name_t *)calloc(sizeof(hicn_name_t), 1);
hicn_name_create_from_ip_prefix(address, 0, name);
return name;
}
-static inline void messageHandler_SetProbeName(uint8_t * probe, hicn_format_t format,
- hicn_name_t * name, uint32_t seq){
- hicn_name_set_seq_number (name, seq);
- hicn_interest_set_name(format, (hicn_header_t *) probe, name);
+static inline void messageHandler_SetProbeName(uint8_t *probe,
+ hicn_format_t format,
+ hicn_name_t *name,
+ uint32_t seq) {
+ hicn_name_set_seq_number(name, seq);
+ hicn_interest_set_name(format, (hicn_header_t *)probe, name);
}
-static inline bool messageHandler_IsAProbe(const uint8_t *packet){
+static inline bool messageHandler_IsAProbe(const uint8_t *packet) {
+ hicn_format_t format;
+ hicn_name_t name;
+ uint32_t seq;
+ hicn_packet_get_format((hicn_header_t *)packet, &format);
+ hicn_data_get_name(format, (hicn_header_t *)packet, &name);
+ hicn_name_get_seq_number(&name, &seq);
+ if (seq >= MIN_PROBE_SUFFIX && seq <= MAX_PROBE_SUFFIX) return true;
+ return false;
+
+#if 0
+ // old probe version
uint16_t src_prt;
uint16_t dst_prt;
hicn_packet_get_src_port (HF_INET6_TCP, (const hicn_header_t *) packet, &src_prt);
@@ -753,6 +654,7 @@ static inline bool messageHandler_IsAProbe(const uint8_t *packet){
}
return false;
+#endif
}
-#endif // Metis_metis_MessageHandler
+#endif /* HICNLIGHT_MESSAGE_HANDLER_H */
diff --git a/hicn-light/src/hicn/core/messagePacketType.h b/hicn-light/src/hicn/core/messagePacketType.h
deleted file mode 100644
index dfbb12342..000000000
--- a/hicn-light/src/hicn/core/messagePacketType.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file message_packet_type_h
- * @brief Defines the packet type for a HICN message
- *
- */
-
-#ifndef message_packet_type_h
-#define message_packet_type_h
-
-typedef enum message_type {
- MessagePacketType_Unknown,
- MessagePacketType_Interest,
- MessagePacketType_ContentObject,
- MessagePacketType_WldrNotification
-} MessagePacketType;
-
-#endif // message_packet_type_h
diff --git a/hicn-light/src/hicn/strategies/rnd.h b/hicn-light/src/hicn/core/msgbuf.c
index 78fb34758..299b20f9b 100644
--- a/hicn-light/src/hicn/strategies/rnd.h
+++ b/hicn-light/src/hicn/core/msgbuf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,14 +14,8 @@
*/
/**
- * Forward randomly
+ * \file msgbuf.c
+ * \brief Implementation hICN message buffer
*/
-#ifndef rnd_h
-#define rnd_h
-
-#include <hicn/strategies/strategyImpl.h>
-
-StrategyImpl* strategyRnd_Create();
-
-#endif // rnd_h
+#include "msgbuf.h"
diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h
new file mode 100644
index 000000000..e437f1d09
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file msgbuf.h
+ * \brief hICN message buffer
+ */
+
+#ifndef HICNLIGHT_MSGBUF
+#define HICNLIGHT_MSGBUF
+
+#include "name.h"
+#include "ticks.h"
+#include "messageHandler.h"
+#include <hicn/ctrl/hicn-light-ng.h>
+
+#define MTU 1500
+#define INVALID_MSGBUF_ID ~0ul
+
+#define msgbuf_id_is_valid(msgbuf_id) \
+ ((unsigned long)msgbuf_id != INVALID_MSGBUF_ID)
+
+#define foreach_msg_type \
+ _(UNDEFINED) \
+ _(INTEREST) \
+ _(DATA) \
+ _(WLDR_NOTIFICATION) \
+ _(MAPME) \
+ _(COMMAND) \
+ _(N)
+
+typedef enum {
+#define _(x) MSGBUF_TYPE_##x,
+ foreach_msg_type
+#undef _
+} msgbuf_type_t;
+#undef foreach_msg_type
+
+typedef struct {
+ unsigned length;
+ msgbuf_type_t type;
+ unsigned connection_id;
+ Ticks recv_ts;
+ unsigned refs;
+ unsigned path_label;
+ union {
+ /* Interest or data packet */
+ struct {
+ Name name;
+ } id;
+ /* Command packet */
+ struct {
+ command_type_t type;
+ } command;
+ };
+ uint8_t packet[MTU];
+} msgbuf_t;
+
+#define msgbuf_get_name(M) (&((M)->id.name))
+#define msgbuf_get_connection_id(M) ((M)->connection_id)
+#define msgbuf_get_type(M) ((M)->type)
+#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet))
+#define msgbuf_get_len(M) ((M)->length)
+#define msgbuf_get_packet(M) ((M)->packet)
+#define msgbuf_get_command_type(M) ((M)->command.type)
+
+// XXX TODO EXPLAIN THE CONSTANT
+#define msgbuf_get_lifetime(M) \
+ (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) * 1000000ULL))
+
+// Lifetimes/expiry times in milliseconds
+#define msgbuf_get_interest_lifetime(M) \
+ (messageHandler_GetInterestLifetime((M)->packet))
+#define msgbuf_get_data_expiry_time(M) \
+ (messageHandler_GetContentExpiryTime((M)->packet))
+
+static inline bool msgbuf_set_interest_lifetime(msgbuf_t *msgbuf,
+ u32 lifetime) {
+ return messageHandler_SetInterestLifetime(msgbuf->packet, lifetime);
+}
+static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) {
+ return messageHandler_SetDataExpiryTime(msgbuf->packet, lifetime);
+}
+
+#define msgbuf_is_probe(M) messageHandler_IsAProbe((M)->packet)
+
+/* Path label */
+
+#define msgbuf_init_pathlabel(M) \
+ ((M)->path_label = messageHandler_GetPathLabel((M)->packet))
+#define msgbuf_update_pathlabel(M, outface) \
+ { \
+ messageHandler_SetPathLabel((M)->packet, \
+ messageHandler_GetPathLabel((M)->packet), \
+ (M)->path_label); \
+ messageHandler_UpdatePathLabel((M)->packet, outface); \
+ }
+#define msgbuf_reset_pathlabel(M) \
+ { \
+ (M)->path_label = 0; \
+ messageHandler_ResetPathLabel((M)->packet); \
+ }
+
+/* WLDR */
+
+#define msgbuf_reset_wldr_label(M) (messageHandler_ResetWldrLabel((M)->packet))
+#define msgbuf_get_wldr_label(M) (messageHandler_GetWldrLabel((M)->packet))
+#define msgbuf_get_wldr_expected_label(M) \
+ (messageHandler_GetWldrExpectedLabel((M)->packet))
+#define msgbuf_get_wldr_last_received(M) \
+ (messageHandler_GetWldrLastReceived((M)->packet))
+#define msgbuf_set_wldr_label(M, label) \
+ (messageHandler_GetWldrLabel((M)->packet, label))
+
+#endif /* HICNLIGHT_MSGBUF */
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.c b/hicn-light/src/hicn/core/msgbuf_pool.c
new file mode 100644
index 000000000..fb5d0a07c
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf_pool.c
@@ -0,0 +1,117 @@
+/*
+ * 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 msgbuf_pool.c
+ * @brief Implementation of hICN packet pool.
+ */
+
+#include "../base/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));
+
+ if (init_size == 0) init_size = PACKET_POOL_DEFAULT_INIT_SIZE;
+
+ pool_init(msgbuf_pool->buffers, init_size, 0);
+
+ return msgbuf_pool;
+}
+
+void msgbuf_pool_free(msgbuf_pool_t *msgbuf_pool) {
+ pool_free(msgbuf_pool->buffers);
+ free(msgbuf_pool);
+}
+
+off_t msgbuf_pool_get(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf) {
+ return pool_get(msgbuf_pool->buffers, *msgbuf);
+}
+
+void msgbuf_pool_put(msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf) {
+ pool_put(msgbuf_pool->buffers, msgbuf);
+}
+
+int msgbuf_pool_getn(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf, size_t n) {
+ // CAVEAT: Resize at the beginning otherwise the resize can be
+ // triggered by an intermediate msgbuf_pool_put, making the
+ // buffers previously retrieved invalid
+ uint64_t remaining_pool_space =
+ pool_get_free_indices_size(msgbuf_pool->buffers);
+ while (remaining_pool_space < n) {
+ _pool_resize((void **)&(msgbuf_pool->buffers), sizeof(msgbuf_t));
+
+ remaining_pool_space = pool_get_free_indices_size(msgbuf_pool->buffers);
+ }
+
+ for (unsigned i = 0; i < n; i++) {
+ // If not able to get the msgbuf
+ if (msgbuf_pool_get(msgbuf_pool, &msgbuf[i]) < 0) {
+ // Release all the msgbufs retrieved so far
+ for (unsigned j = 0; j < i; j++) {
+ msgbuf_pool_put(msgbuf_pool, msgbuf[j]);
+ }
+ return -1;
+ }
+ }
+ return 0;
+}
+
+off_t msgbuf_pool_get_id(msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf) {
+ return msgbuf - msgbuf_pool->buffers;
+}
+
+msgbuf_t *msgbuf_pool_at(const msgbuf_pool_t *msgbuf_pool, off_t id) {
+ assert(msgbuf_id_is_valid(id));
+ return msgbuf_pool->buffers + id;
+}
+
+void msgbuf_pool_acquire(msgbuf_t *msgbuf) { msgbuf->refs++; };
+
+void msgbuf_pool_release(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf_ptr) {
+ msgbuf_t *msgbuf = *msgbuf_ptr;
+ assert(msgbuf->refs > 0);
+ msgbuf->refs--;
+
+ if (msgbuf->refs == 0) {
+ WITH_TRACE({
+ off_t msgbuf_id = msgbuf_pool_get_id(msgbuf_pool, msgbuf);
+ if (msgbuf->type != MSGBUF_TYPE_INTEREST &&
+ msgbuf->type != MSGBUF_TYPE_DATA) {
+ TRACE("Msgbuf %d (%p) - put to msgbuf pool", msgbuf_id, msgbuf);
+ } else {
+ char *name_str = name_ToString(msgbuf_get_name(msgbuf));
+ const char *msgbuf_type_str =
+ msgbuf->type == MSGBUF_TYPE_INTEREST ? "interest" : "data";
+ TRACE("Msgbuf %d (%p) - %s (%s) put to msgbuf pool", msgbuf_id, msgbuf,
+ name_str, msgbuf_type_str);
+ free(name_str);
+ }
+ })
+
+ msgbuf_pool_put(msgbuf_pool, msgbuf);
+ *msgbuf_ptr = NULL;
+ }
+};
+
+off_t msgbuf_pool_clone(msgbuf_pool_t *msgbuf_pool, msgbuf_t **new_msgbuf,
+ off_t orginal_msg_id) {
+ msgbuf_t *original_msgbuf = msgbuf_pool_at(msgbuf_pool, orginal_msg_id);
+ off_t offset = pool_get(msgbuf_pool->buffers, *new_msgbuf);
+ memcpy(*new_msgbuf, original_msgbuf, sizeof(msgbuf_t));
+ (*new_msgbuf)->refs = 0;
+ return offset;
+}
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.h b/hicn-light/src/hicn/core/msgbuf_pool.h
new file mode 100644
index 000000000..b8a15fd84
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf_pool.h
@@ -0,0 +1,157 @@
+/*
+ * 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 msgbuf_pool.h
+ * @brief hICN msgbuf pool.
+ *
+ * The msgbuf pool is used to store packet payloads while the packets are in
+ * transit, as well as holding them into the packet cache (PIT, CSS), WLDR,
+ * mapme, etc.
+ *
+ * Control packets might receive a special treatment in that they are eventually
+ * transformed into a ack/nack, but this should not affect any part of this
+ * design.
+ *
+ * Do we need a reference count, or simply a lock ?
+ * What about weak references ?
+ * We need to be sure that a pool element is never referenced ever again after
+ * it is deleted from the pool as its ID might be reaffected.
+ *
+ * It might even be better to store references to msgbuf's as they might hold
+ * additional information of interest about the packet... a bit like a skbuff in
+ * linux. Is this relevant for the packet cache ?
+ */
+
+#ifndef HICNLIGHT_MSGBUF_POOL_H
+#define HICNLIGHT_MSGBUF_POOL_H
+
+#include "msgbuf.h"
+
+#define MTU 1500
+#define PACKET_POOL_DEFAULT_INIT_SIZE 1024
+
+typedef struct {
+ msgbuf_t *buffers;
+} msgbuf_pool_t;
+
+/**
+ * @brief Allocate and initialize a msgbuf pool structure (helper).
+ *
+ * @param[in] init_size Number of buffers that can be stored in msgbuf pool.
+ * @param[in] max_size Maximum size.
+ * @return msgbuf_pool_t* Pointer to the msgbuf pool created.
+ *
+ * @note
+ * - 0 for init size means a default value (of 1024)
+ * - 0 for max_size means no limit
+ */
+msgbuf_pool_t *_msgbuf_pool_create(size_t init_size, size_t max_size);
+
+/**
+ * @brief Allocate and initialize a msgbuf pool data structure.
+ *
+ * @return msgbuf_pool_t* Pointer to the msgbuf pool created.
+ */
+#define msgbuf_pool_create() _msgbuf_pool_create(0, 0)
+
+/**
+ * @brief Free a msgbuf pool data structure.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to free.
+ */
+void msgbuf_pool_free(msgbuf_pool_t *msgbuf_pool);
+
+/**
+ * @brief Get a free msgbuf from the msgbuf pool data structure.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in, out] msgbuf Empty msgbuf that will be used to return the
+ * allocated one from the msgbuf pool.
+ * @return off_t ID of the msgbuf requested.
+ */
+off_t msgbuf_pool_get(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf);
+
+/**
+ * @brief Release a msgbuf previously obtained, making it available to the
+ * msgbuf pool.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in] msgbuf Pointer to the msgbuf to release.
+ */
+void msgbuf_pool_put(msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf);
+
+/**
+ * @brief Get multiple free msgbufs from the msgbuf pool data structure.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in, out] msgbuf Pointer to the first empty msgbuf that will be used to
+ * allocate the msgbufs.
+ * @param[in] n Number of msgbufs requested.
+ * @retval 0 Success.
+ * @retval -1 Error.
+ */
+int msgbuf_pool_getn(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf, size_t n);
+
+/**
+ * @brief Get the ID corresponding to the msgbuf requested.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in] msgbuf Pointer to the msgbuf to retrieve the ID for.
+ * @return off_t ID of the msgbuf requested.
+ */
+off_t msgbuf_pool_get_id(msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf);
+
+/**
+ * @brief Get the msgbuf corresponding to the ID requested.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use.
+ * @param[in] id Index of the msgbuf to retrieve.
+ * @return msgbuf_t* Pointer to the msgbuf corresponding to the ID requested.
+ */
+msgbuf_t *msgbuf_pool_at(const msgbuf_pool_t *msgbuf_pool, off_t id);
+
+/**
+ * @brief Acquire a buffer (by increasing its reference count).
+ *
+ * @param[in] msgbuf Pointer to the msgbuf to acquire
+ */
+void msgbuf_pool_acquire(msgbuf_t *msgbuf);
+
+/**
+ * @brief Release a buffer. The buffer is also put back into the msgbuf
+ * pool if everyone who acquired it has released its possession.
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in, out] msgbuf Pointer that holds the pointer to the msgbuf
+ * to release; the double indirection is used to set the msgbuf pointer
+ * to NULL in case it is put into the msgbuf pool.
+ */
+void msgbuf_pool_release(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf_ptr);
+
+/**
+ * @brief Copy the original msgbuf in new msgbuf taken from the pool. The ref
+ * count on new msgbuf is set to 0
+ *
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in,out] new__msgbuf Pointer that holds the replicatate msgbuf
+ * @param[in] original_msgbuf id. use id instead of the pointer becasue the
+ * pointer may becose invalid if the msgbuf_pool requires a resize
+ * @return off_t ID of the msgbuf requested.
+ */
+off_t msgbuf_pool_clone(msgbuf_pool_t *msgbuf_pool, msgbuf_t **new_msgbuf,
+ off_t orginal_msg_id);
+
+#endif /* HICNLIGHT_MSGBUF_POOL_H */
diff --git a/hicn-light/src/hicn/core/name.c b/hicn-light/src/hicn/core/name.c
index b4a5e8d1b..8886cc929 100644
--- a/hicn-light/src/hicn/core/name.c
+++ b/hicn-light/src/hicn/core/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,201 +13,133 @@
* limitations under the License.
*/
+#include <assert.h>
#include <limits.h>
#include <hicn/hicn-light/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include <parc/algol/parc_BufferComposer.h>
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-
+#include <hicn/common.h> // cumulative_hash32
#include <hicn/core/messageHandler.h>
#include <hicn/core/name.h>
-
-#include <parc/algol/parc_Hash.h>
-
-#include <parc/assert/parc_Assert.h>
+#include <hicn/util/log.h>
+#include <hicn/base/hash.h>
#define IPv6_TYPE 6
#define IPv4_TYPE 4
-// assumption: the IPv6 address is the name, the TCP segment number is the ICN
-// segment
-
-struct name {
- NameBitvector *content_name;
- uint32_t segment;
- uint32_t name_hash;
- // the refcount is shared between all copies
- unsigned *refCountPtr;
-};
-
-// =====================================================
-
-static unsigned _getRefCount(const Name *name) { return *name->refCountPtr; }
-
-static void _incrementRefCount(Name *name) {
- parcAssertTrue(*name->refCountPtr > 0,
- "Illegal State: Trying to increment a 0 refcount!");
- (*name->refCountPtr)++;
-}
-
-static void _decrementRefCount(Name *name) {
- parcAssertTrue(*name->refCountPtr > 0,
- "Illegal State: Trying to decrement a 0 refcount!");
- (*name->refCountPtr)--;
-}
-
static uint32_t _computeHash(Name *name) {
- parcAssertNotNull(name, "Parameter must be non-null pointer");
+ assert(name);
- uint32_t hash1 = nameBitvector_GetHash32(name->content_name);
- return parcHash32_Data_Cumulative((const uint8_t *)&name->segment, 4, hash1);
+ uint32_t hash1 = nameBitvector_GetHash32(&(name->content_name));
+ return hashlittle(&name->segment, sizeof(name->segment), hash1);
}
// ============================================================================
-Name *name_CreateFromPacket(const uint8_t *packet, MessagePacketType type) {
- Name *name = parcMemory_AllocateAndClear(sizeof(Name));
- parcAssertNotNull(name, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Name));
+void name_create_from_interest(const uint8_t *packet, Name *name) {
+ assert(packet);
+ assert(name);
if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) {
- if (type == MessagePacketType_Interest) {
- name->content_name = nameBitvector_CreateFromIn6Addr(
- (struct in6_addr *)messageHandler_GetDestination(packet), 128);
- } else if (type == MessagePacketType_ContentObject) {
- name->content_name = nameBitvector_CreateFromIn6Addr(
- (struct in6_addr *)messageHandler_GetSource(packet), 128);
- } else {
- parcMemory_Deallocate((void **)&name);
- return NULL;
- }
+ nameBitvector_CreateFromIn6Addr(
+ &(name->content_name),
+ (struct in6_addr *)messageHandler_GetDestination(packet), 128);
} else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) {
- if (type == MessagePacketType_Interest) {
- name->content_name = nameBitvector_CreateFromInAddr(
- *((uint32_t *)messageHandler_GetDestination(packet)), 32);
- } else if (type == MessagePacketType_ContentObject) {
- name->content_name = nameBitvector_CreateFromInAddr(
- *((uint32_t *)messageHandler_GetSource(packet)), 32);
- } else {
- parcMemory_Deallocate((void **)&name);
- return NULL;
- }
+ nameBitvector_CreateFromInAddr(
+ &(name->content_name),
+ *((uint32_t *)messageHandler_GetDestination(packet)), 32);
} else {
- printf("Error: unknown message type\n");
- parcMemory_Deallocate((void **)&name);
- return NULL;
+ ERROR("Error: unknown message type\n");
+ return;
}
name->segment = messageHandler_GetSegment(packet);
name->name_hash = _computeHash(name);
-
- name->refCountPtr = parcMemory_Allocate(sizeof(unsigned));
- parcAssertNotNull(name->refCountPtr, "parcMemory_Allocate(%zu) returned NULL",
- sizeof(unsigned));
- *name->refCountPtr = 1;
- return name;
}
-Name *name_CreateFromAddress(address_type addressType, ip_address_t addr,
- uint8_t len) {
- Name *name = parcMemory_AllocateAndClear(sizeof(Name));
- parcAssertNotNull(name, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Name));
- if (addressType == ADDR_INET) {
- name->content_name = nameBitvector_CreateFromInAddr(addr.v4.as_u32, len);
- } else if (addressType == ADDR_INET6) {
- name->content_name = nameBitvector_CreateFromIn6Addr(&addr.v6.as_in6addr, len);
+void name_create_from_data(const uint8_t *packet, Name *name) {
+ assert(packet);
+ assert(name);
+
+ if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) {
+ nameBitvector_CreateFromIn6Addr(
+ &(name->content_name),
+ (struct in6_addr *)messageHandler_GetSource(packet), 128);
+ } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) {
+ nameBitvector_CreateFromInAddr(
+ &(name->content_name), *((uint32_t *)messageHandler_GetSource(packet)),
+ 32);
} else {
- parcTrapNotImplemented("Unkown packet type");
+ printf("Error: unknown message type\n");
+ return;
}
- name->segment = 0;
+ name->segment = messageHandler_GetSegment(packet);
name->name_hash = _computeHash(name);
-
- name->refCountPtr = parcMemory_Allocate(sizeof(unsigned));
- parcAssertNotNull(name->refCountPtr, "parcMemory_Allocate(%zu) returned NULL",
- sizeof(unsigned));
- *name->refCountPtr = 1;
-
- return name;
}
-void name_Release(Name **namePtr) {
- parcAssertNotNull(namePtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*namePtr, "Parameter must dereference to non-null pointer");
-
- Name *name = *namePtr;
- _decrementRefCount(name);
- if (_getRefCount(name) == 0) {
- parcMemory_Deallocate((void **)&(name->refCountPtr));
- nameBitvector_Destroy(&(name->content_name));
+void name_CreateFromAddress(Name *name, int family, ip_address_t addr,
+ uint8_t len) {
+ assert(name);
+
+ switch (family) {
+ case AF_INET:
+ nameBitvector_CreateFromInAddr(&(name->content_name), addr.v4.as_u32,
+ len);
+ break;
+ case AF_INET6:
+ nameBitvector_CreateFromIn6Addr(&(name->content_name),
+ &addr.v6.as_in6addr, len);
+ break;
+ default:
+ return;
}
- parcMemory_Deallocate((void **)&name);
- *namePtr = NULL;
-}
-
-Name *name_Acquire(const Name *original) {
- parcAssertNotNull(original, "Parameter must be non-null");
- Name *copy = parcMemory_AllocateAndClear(sizeof(Name));
- parcAssertNotNull(copy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Name));
- memcpy(copy, original, sizeof(Name));
- _incrementRefCount(copy);
-
- return copy;
+ name->segment = 0;
+ name->name_hash = _computeHash(name);
}
-Name *name_Copy(const Name *original) {
- parcAssertNotNull(original, "Parameter must be non-null");
- Name *copy = parcMemory_AllocateAndClear(sizeof(Name));
- parcAssertNotNull(copy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Name));
+void name_Copy(const Name *original, Name *copy) {
+ assert(original);
+ assert(copy);
- copy->content_name = nameBitvector_Copy(original->content_name);
+ nameBitvector_Copy(&(original->content_name), &(copy->content_name));
copy->segment = original->segment;
copy->name_hash = original->name_hash;
-
- copy->refCountPtr = parcMemory_Allocate(sizeof(unsigned));
- parcAssertNotNull(copy->refCountPtr, "parcMemory_Allocate(%zu) returned NULL",
- sizeof(unsigned));
- *copy->refCountPtr = 1;
-
- return copy;
}
uint32_t name_HashCode(const Name *name) {
- parcAssertNotNull(name, "Parameter must be non-null");
+ assert(name);
return name->name_hash;
}
NameBitvector *name_GetContentName(const Name *name) {
- parcAssertNotNull(name, "Parameter must be non-null");
- return name->content_name;
+ assert(name);
+ return (NameBitvector *)&(name->content_name);
}
-bool name_Equals(const Name *a, const Name *b) {
- parcAssertNotNull(a, "Parameter a must be non-null");
- parcAssertNotNull(b, "Parameter b must be non-null");
+uint32_t name_GetSegment(const Name *name) {
+ assert(name);
+ return name->segment;
+}
- /* BEGIN: Workaround for HICN-400 */
- if ((!a->content_name) || (!b->content_name))
- return false;
- /* END: Workaround for HICN-400 */
+void name_SetSegment(Name *name, uint32_t segment) { name->segment = segment; }
- if ((nameBitvector_Equals(a->content_name, b->content_name) &&
+bool name_Equals(const Name *a, const Name *b) {
+ assert(a);
+ assert(b);
+
+ if ((nameBitvector_Equals(&(a->content_name), &(b->content_name)) &&
a->segment == b->segment))
return true;
return false;
}
int name_Compare(const Name *a, const Name *b) {
- parcAssertNotNull(a, "Parameter a must be non-null");
- parcAssertNotNull(b, "Parameter b must be non-null");
+ assert(a);
+ assert(b);
if (a == NULL && b == NULL) {
return 0;
@@ -219,7 +151,7 @@ int name_Compare(const Name *a, const Name *b) {
return +1;
}
- int res = nameBitvector_Compare(a->content_name, b->content_name);
+ int res = nameBitvector_Compare(&(a->content_name), &(b->content_name));
if (res != 0) {
return res;
@@ -235,30 +167,30 @@ int name_Compare(const Name *a, const Name *b) {
}
char *name_ToString(const Name *name) {
- char *output = malloc(128);
+ char *output = malloc(NI_MAXHOST * 2);
+ address_t address;
+ nameBitvector_ToAddress(name_GetContentName(name), &address);
- Address *packetAddr = nameBitvector_ToAddress(name_GetContentName(name));
+ char addr_str[NI_MAXHOST];
+ int err = address_to_string(&address, addr_str, NULL);
+ _ASSERT(!err);
- char * address_str = addressToString(packetAddr);
- sprintf(output, "name: %s seq: %u", address_str, name->segment);
- parcMemory_Deallocate((void **)&address_str);
-
- addressDestroy(&packetAddr);
+ int chars_written =
+ snprintf(output, NI_MAXHOST * 2, "name=%s|%u", addr_str, name->segment);
+ _ASSERT(chars_written > 0);
return output;
}
void name_setLen(Name *name, uint8_t len) {
- nameBitvector_setLen(name->content_name, len);
+ nameBitvector_setLen(&(name->content_name), len);
name->name_hash = _computeHash(name);
}
#ifdef WITH_POLICY
-uint32_t name_GetSuffix(const Name * name) {
- return name->segment;
-}
+uint32_t name_GetSuffix(const Name *name) { return name->segment; }
-uint8_t name_GetLen(const Name * name) {
- return nameBitvector_GetLength(name->content_name);
+uint8_t name_GetLen(const Name *name) {
+ return nameBitvector_GetLength(&(name->content_name));
}
#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/core/name.h b/hicn-light/src/hicn/core/name.h
index db9438150..23505243b 100644
--- a/hicn-light/src/hicn/core/name.h
+++ b/hicn-light/src/hicn/core/name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,50 +19,52 @@
#include <stdbool.h>
#include <stdlib.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/core/nameBitvector.h>
-#include <hicn/utils/address.h>
+#include "nameBitvector.h"
-#include <hicn/utils/commands.h>
+typedef struct {
+ NameBitvector content_name;
+ uint32_t segment;
+ uint32_t name_hash;
+} Name;
-struct name;
-typedef struct name Name;
+#define EMPTY_NAME \
+ (Name) { .content_name = EMPTY_NAME_BITVECTOR, .segment = 0, .name_hash = 0, }
/**
* Creates a name from packet
*
*/
-Name *name_CreateFromPacket(const uint8_t *memory, MessagePacketType type);
+void name_create_from_interest(const uint8_t *packet, Name *name);
+void name_create_from_data(const uint8_t *packet, Name *name);
/**
- * Releases one reference count, and frees memory after last reference
+ * returns a copy of the name
*/
-void name_Release(Name **namePtr);
+void name_Copy(const Name *original, Name *copy);
/**
- * Acquires a reference to the name so that a reference count increments.
- * Notice however that this * function is used only when a new fib entry is
- * created (mostly configuration time) probably here performance are not
- * critical.
+ * A hash value for use in hash tables
+ *
*/
-Name *name_Acquire(const Name *original);
+uint32_t name_HashCode(const Name *name);
/**
- * returns a copy of the name
+ * Returns the content name without the segment value
+ *
*/
-Name *name_Copy(const Name *original);
+NameBitvector *name_GetContentName(const Name *name);
/**
- * A hash value for use in hash tables
+ * Returns the segment value
*
*/
-uint32_t name_HashCode(const Name *name);
+uint32_t name_GetSegment(const Name *name);
/**
- * Returns the content name without the segment value
+ * Set the sequence number of the name provided
*
*/
-NameBitvector *name_GetContentName(const Name *name);
+void name_SetSegment(Name *name, uint32_t segment);
/**
* Determine if two HicnName instances are equal.
@@ -93,12 +95,12 @@ void name_setLen(Name *name, uint8_t len);
* Creates a name from a Address
*
*/
-Name *name_CreateFromAddress(address_type addressType, ip_address_t addr,
- uint8_t len);
+void name_CreateFromAddress(Name *name, int family, ip_address_t addr,
+ uint8_t len);
#ifdef WITH_POLICY
-uint32_t name_GetSuffix(const Name * name);
-uint8_t name_GetLen(const Name * name);
+uint32_t name_GetSuffix(const Name *name);
+uint8_t name_GetLen(const Name *name);
#endif /* WITH_POLICY */
#endif // name_h
diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c
index 653560750..1314671db 100644
--- a/hicn-light/src/hicn/core/nameBitvector.c
+++ b/hicn-light/src/hicn/core/nameBitvector.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,17 +17,13 @@
#include <stdio.h>
#include <stdlib.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-
#include <hicn/core/messageHandler.h>
#include <hicn/core/nameBitvector.h>
-#include <parc/algol/parc_Hash.h>
-
-#include <hicn/utils/commands.h>
+#include <hicn/base/hash.h>
+#include <hicn/ctrl/hicn-light-ng.h>
-#define NAME_LEN 2
+#define DEFAULT_PORT 1234
const uint64_t BV_SIZE = 64;
const uint64_t WIDTH = 128;
@@ -37,19 +33,12 @@ const uint64_t ONE = 0x1;
// [bits[0] uint64_t ] [bits[1] unit64_t ]
// ^ ^ ^ ^
// 63 0 127 64
-// [1000 0000 ... 0000 1101] [1000 0000 ... 0000 0011] //binary
+// [1000 0000 ... 0000 1011] [1000 0000 ... 0000 0011] //binary
// 1 b 1 c //hex
-struct name_bitvector {
- uint64_t bits[NAME_LEN];
- uint8_t len;
- uint8_t IPversion;
-};
-
-NameBitvector *nameBitvector_CreateFromInAddr(uint32_t addr, uint8_t len) {
- NameBitvector *bitvector = parcMemory_AllocateAndClear(sizeof(NameBitvector));
- parcAssertNotNull(bitvector, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(NameBitvector));
+void nameBitvector_CreateFromInAddr(NameBitvector *bitvector, uint32_t addr,
+ uint8_t len) {
+ assert(bitvector);
bitvector->bits[0] = 0;
bitvector->bits[1] = 0;
@@ -68,17 +57,12 @@ NameBitvector *nameBitvector_CreateFromInAddr(uint32_t addr, uint8_t len) {
bitvector->len = len;
bitvector->IPversion = IPv4_TYPE;
-
- return bitvector;
}
-NameBitvector *nameBitvector_CreateFromIn6Addr(struct in6_addr *addr,
- uint8_t len) {
- parcAssertNotNull(addr, "addr cannot be null");
-
- NameBitvector *bitvector = parcMemory_AllocateAndClear(sizeof(NameBitvector));
- parcAssertNotNull(bitvector, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(NameBitvector));
+void nameBitvector_CreateFromIn6Addr(NameBitvector *bitvector,
+ struct in6_addr *addr, uint8_t len) {
+ assert(addr);
+ assert(bitvector);
bitvector->bits[0] = 0;
bitvector->bits[1] = 0;
@@ -94,69 +78,26 @@ NameBitvector *nameBitvector_CreateFromIn6Addr(struct in6_addr *addr,
bitvector->len = len;
bitvector->IPversion = IPv6_TYPE;
-
- return bitvector;
}
-NameBitvector *nameBitvector_CreateFromAddress(const Address *prefix,
- uint8_t len) {
- parcAssertNotNull(prefix, "prefix cannot be null");
-
- NameBitvector *bitvector = NULL;
- switch (addressGetType(prefix)) {
- case ADDR_INET: {
- struct sockaddr_in addr;
- addressGetInet(prefix, &addr);
- bitvector = nameBitvector_CreateFromInAddr(addr.sin_addr.s_addr, len);
- break;
- }
- case ADDR_INET6: {
- struct sockaddr_in6 addr;
- addressGetInet6(prefix, &addr);
- bitvector = nameBitvector_CreateFromIn6Addr(&addr.sin6_addr, len);
- break;
- }
- default:
- parcTrapNotImplemented("Unkown packet type");
- break;
- }
-
- return bitvector;
-}
-
-NameBitvector *nameBitvector_Copy(const NameBitvector *original) {
- parcAssertNotNull(original, "original cannot be null");
-
- NameBitvector *copy = parcMemory_AllocateAndClear(sizeof(NameBitvector));
- parcAssertNotNull(copy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(NameBitvector));
+void nameBitvector_Copy(const NameBitvector *original, NameBitvector *copy) {
+ assert(original);
+ assert(copy);
copy->bits[0] = original->bits[0];
copy->bits[1] = original->bits[1];
copy->len = original->len;
-
- return copy;
-}
-
-void nameBitvector_Destroy(NameBitvector **bitvectorPtr) {
- parcAssertNotNull(bitvectorPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*bitvectorPtr,
- "Parameter must dereference to non-null pointer");
-
- NameBitvector *bv = *bitvectorPtr;
- parcMemory_Deallocate((void **)&(bv));
- *bitvectorPtr = NULL;
+ copy->IPversion = original->IPversion;
}
uint8_t nameBitvector_GetLength(const NameBitvector *name) { return name->len; }
uint32_t nameBitvector_GetHash32(const NameBitvector *name) {
- return parcHash32_Data_Cumulative((const uint8_t *)name->bits, 16, 0);
+ return hash(&name->bits, 16);
}
bool nameBitvector_Equals(const NameBitvector *a, const NameBitvector *b) {
- if (a->bits[0] == b->bits[0] && a->bits[1] == b->bits[1] && a->len == b->len)
- return true;
+ if (nameBitvector_Compare(a, b) == 0) return true;
return false;
}
@@ -189,14 +130,15 @@ int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b) {
}
int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit) {
- if(pos >= name->len || pos > (WIDTH -1))
- return -1;
+ if (pos >= name->len || pos > (WIDTH - 1)) return -1;
- *bit = (name->bits[pos / BV_SIZE] & (ONE << ((BV_SIZE - 1) - (pos % BV_SIZE))));
+ *bit =
+ (name->bits[pos / BV_SIZE] & (ONE << ((BV_SIZE - 1) - (pos % BV_SIZE))));
return 0;
}
+// TODO XXX use ffs(ll)
uint64_t _diff_bit_log2(uint64_t val) {
// base 2 log of an uint64_t. This is the same as get the position of
// the highest bit set (or most significant bit set, MSB)
@@ -229,8 +171,7 @@ uint64_t _diff_bit_log2(uint64_t val) {
return result;
}
-uint32_t nameBitvector_lpm(const NameBitvector *a,
- const NameBitvector *b) {
+uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b) {
uint32_t limit;
uint32_t prefix_len;
if (a->len < b->len)
@@ -239,32 +180,30 @@ uint32_t nameBitvector_lpm(const NameBitvector *a,
limit = b->len;
uint64_t diff = a->bits[0] ^ b->bits[0];
- if(diff){
+ if (diff) {
prefix_len = (uint32_t)(BV_SIZE - (_diff_bit_log2(diff) + 1));
- //printf("if 1 diff = %lu plen = %d\n", diff, prefix_len);
- }else{
- prefix_len = (uint32_t)BV_SIZE;
+ // printf("if 1 diff = %lu plen = %d\n", diff, prefix_len);
+ } else {
+ prefix_len = BV_SIZE;
diff = a->bits[1] ^ b->bits[1];
- if(diff){
- prefix_len += (uint32_t)(BV_SIZE - (_diff_bit_log2(diff) + 1));
- //printf("if 2 diff = %lu plen = %d\n", diff, prefix_len);
- }else{
- prefix_len += (uint32_t)BV_SIZE;
+ if (diff) {
+ prefix_len += (BV_SIZE - (_diff_bit_log2(diff) + 1));
+ // printf("if 2 diff = %lu plen = %d\n", diff, prefix_len);
+ } else {
+ prefix_len += BV_SIZE;
}
}
- if(prefix_len < limit)
- return prefix_len;
+ if (prefix_len < limit) return prefix_len;
return limit;
}
-void nameBitvector_clear(NameBitvector *a, uint8_t start_from){
- for(uint8_t pos = start_from; pos < WIDTH; pos++)
- a->bits[pos / BV_SIZE] &= ~(ONE << ((BV_SIZE - 1) - (pos % BV_SIZE)));
+void nameBitvector_clear(NameBitvector *a, uint8_t start_from) {
+ for (uint8_t pos = start_from; pos < WIDTH; pos++)
+ a->bits[pos / BV_SIZE] &= ~(ONE << ((BV_SIZE - 1) - (pos % BV_SIZE)));
}
-int nameBitvector_ToIPAddress(const NameBitvector *name,
- ip_prefix_t *prefix) {
+int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix) {
if (name->IPversion == IPv4_TYPE) {
struct in_addr *addr = (struct in_addr *)(&prefix->address.v4.buffer);
prefix->family = AF_INET;
@@ -302,11 +241,11 @@ int nameBitvector_ToIPAddress(const NameBitvector *name,
void nameBitvector_setLen(NameBitvector *name, uint8_t len) { name->len = len; }
-Address *nameBitvector_ToAddress(const NameBitvector *name) {
+void nameBitvector_ToAddress(const NameBitvector *name, address_t *address) {
if (name->IPversion == IPv4_TYPE) {
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(1234);
+ struct sockaddr_in *sin = address4(address);
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(DEFAULT_PORT);
uint32_t tmp_addr = name->bits[0] >> 32ULL;
uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24;
@@ -314,51 +253,44 @@ Address *nameBitvector_ToAddress(const NameBitvector *name) {
uint8_t addr_3 = (tmp_addr & 0x0000ff00) >> 8;
uint8_t addr_4 = (tmp_addr & 0x000000ff);
- addr.sin_addr.s_addr = 0;
- addr.sin_addr.s_addr = (addr.sin_addr.s_addr | addr_4) << 8;
- addr.sin_addr.s_addr = (addr.sin_addr.s_addr | addr_3) << 8;
- addr.sin_addr.s_addr = (addr.sin_addr.s_addr | addr_2) << 8;
- addr.sin_addr.s_addr = (addr.sin_addr.s_addr | addr_1);
-
- Address *packetAddr = addressCreateFromInet(&addr);
-
- return packetAddr;
-
+ sin->sin_addr.s_addr = 0;
+ sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_4) << 8;
+ sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_3) << 8;
+ sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_2) << 8;
+ sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_1);
} else {
- struct sockaddr_in6 addr;
- addr.sin6_family = AF_INET6;
- addr.sin6_port = htons(1234);
- addr.sin6_scope_id = 0;
- addr.sin6_flowinfo = 0;
+ struct sockaddr_in6 *sin6 = address6(address);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = htons(DEFAULT_PORT);
+ sin6->sin6_scope_id = 0;
+ sin6->sin6_flowinfo = 0;
for (int i = 0; i < 8; i++) {
- addr.sin6_addr.s6_addr[i] =
+ sin6->sin6_addr.s6_addr[i] =
(uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF);
}
int x = 0;
for (int i = 8; i < 16; ++i) {
- addr.sin6_addr.s6_addr[i] =
+ sin6->sin6_addr.s6_addr[i] =
(uint8_t)((name->bits[1] >> 8 * (7 - x)) & 0xFF);
x++;
}
-
- Address *packetAddr = addressCreateFromInet6(&addr);
-
- return packetAddr;
}
}
char *nameBitvector_ToString(const NameBitvector *name) {
char *output = malloc(WIDTH);
- Address *packetAddr = nameBitvector_ToAddress(name);
-
- char * str = addressToString(packetAddr);
- sprintf(output, "prefix: %s len: %u", str, name->len);
- parcMemory_Deallocate((void **)&str);
+ address_t address;
+ nameBitvector_ToAddress(name, &address);
- addressDestroy(&packetAddr);
+ // XXX TODO
+#if 0
+ sprintf(output, "prefix: %s len: %u", addressToString(packetAddr), name->len);
+#else
+ snprintf(output, WIDTH, "%s", "ENOIMPL");
+#endif
return output;
}
diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h
index 19944778c..e3cc108ac 100644
--- a/hicn-light/src/hicn/core/nameBitvector.h
+++ b/hicn-light/src/hicn/core/nameBitvector.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,19 +20,25 @@
#include <stdint.h>
#include <stdlib.h>
-#include <hicn/utils/address.h>
+#include "address.h"
-struct name_bitvector;
-typedef struct name_bitvector NameBitvector;
+#define NAME_LEN 2
+typedef struct {
+ uint64_t bits[NAME_LEN];
+ uint8_t len;
+ uint8_t IPversion;
+} NameBitvector;
-NameBitvector *nameBitvector_CreateFromInAddr(uint32_t addr, uint8_t len);
+#define EMPTY_NAME_BITVECTOR \
+ (NameBitvector) { .bits[0] = 0, .bits[1] = 0, .len = 0, .IPversion = 0, }
-NameBitvector *nameBitvector_CreateFromIn6Addr(struct in6_addr *addr,
- uint8_t len);
+void nameBitvector_CreateFromInAddr(NameBitvector *bitvector, uint32_t addr,
+ uint8_t len);
-NameBitvector *nameBitvector_Copy(const NameBitvector *original);
+void nameBitvector_CreateFromIn6Addr(NameBitvector *bitvector,
+ struct in6_addr *addr, uint8_t len);
-void nameBitvector_Destroy(NameBitvector **bitvectorPtr);
+void nameBitvector_Copy(const NameBitvector *original, NameBitvector *copy);
uint8_t nameBitvector_GetLength(const NameBitvector *name);
@@ -51,7 +57,7 @@ void nameBitvector_clear(NameBitvector *a, uint8_t start_from);
int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix);
void nameBitvector_setLen(NameBitvector *name, uint8_t len);
-Address *nameBitvector_ToAddress(const NameBitvector *name);
+void nameBitvector_ToAddress(const NameBitvector *name, address_t *address);
char *nameBitvector_ToString(const NameBitvector *name);
diff --git a/hicn-light/src/hicn/core/nexthops.c b/hicn-light/src/hicn/core/nexthops.c
new file mode 100644
index 000000000..190f09ab0
--- /dev/null
+++ b/hicn-light/src/hicn/core/nexthops.c
@@ -0,0 +1,142 @@
+/*
+ * 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 nexthops.c
+ * \brief Nexthops implementation
+ */
+
+#include "nexthops.h"
+
+int nexthops_disable(nexthops_t *nexthops, off_t offset) {
+ if (offset >= nexthops->num_elts) return -1;
+ nexthops->flags |= (1 << offset);
+ nexthops->cur_elts--;
+ return 0;
+}
+
+void nexthops_reset(nexthops_t *nexthops) {
+ nexthops->flags = 0;
+ nexthops->cur_elts = nexthops->num_elts;
+}
+
+off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop) {
+ off_t id;
+ unsigned i, n;
+ nexthops_enumerate(nexthops, i, n, {
+ if (n == nexthop) return i;
+ });
+ id = nexthops->num_elts++;
+ nexthops->elts[id] = nexthop;
+ nexthops_reset(nexthops);
+ return id;
+}
+
+off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop) {
+ unsigned i, n;
+ nexthops_enumerate(nexthops, i, n, {
+ if (n == nexthop) {
+ nexthops->num_elts--;
+ nexthops->elts[i] = nexthops->elts[nexthops->num_elts];
+ nexthops->state[i] = nexthops->state[nexthops->num_elts];
+ nexthops_reset(nexthops);
+ return i;
+ }
+ });
+ return INVALID_NEXTHOP;
+}
+
+bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop) {
+ unsigned n;
+ nexthops_foreach(nexthops, n, {
+ if (n == nexthop) return true;
+ });
+ return false;
+}
+
+off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop) {
+ unsigned i, n;
+ nexthops_enumerate(nexthops, i, n, {
+ if (n == nexthop) return i;
+ });
+ return INVALID_NEXTHOP;
+}
+
+unsigned nexthops_get_one(nexthops_t *nexthops) {
+ unsigned n;
+ nexthops_foreach(nexthops, n, { return n; });
+ return INVALID_NEXTHOP;
+}
+
+int nexthops_select(nexthops_t *nexthops, off_t i) {
+ if (i >= nexthops->num_elts) return -1;
+ nexthops->flags = ~0; /* all 1, could be limited to num_elts */
+ nexthops->flags &= ~(1 << (i));
+ nexthops->cur_elts = 1;
+ return 0;
+}
+
+#ifdef WITH_POLICY
+
+void nexthops_set_priority(nexthops_t *nexthops, nexthop_t nexthop,
+ int priority) {
+ unsigned i;
+ nexthop_t nh;
+ nexthops_enumerate(nexthops, i, nh, {
+ if (nexthop == nh) nexthops_set_priority_by_id(nexthops, i, priority);
+ });
+}
+
+void nexthops_set_priority_by_id(nexthops_t *nexthops, off_t i, int priority) {
+ nexthops->state[i].priority = priority;
+}
+
+void nexthops_reset_priority(nexthops_t *nexthops, nexthop_t nexthop) {
+ nexthops_set_priority(nexthops, nexthop, DEFAULT_PRIORITY);
+}
+
+void nexthops_reset_priority_by_id(nexthops_t *nexthops, off_t i) {
+ nexthops_set_priority_by_id(nexthops, i, DEFAULT_PRIORITY);
+}
+
+void nexthops_reset_priorities(nexthops_t *nexthops) {
+ unsigned i;
+ nexthop_t nh;
+ nexthops_enumerate(nexthops, i, nh, {
+ (void)nh;
+ nexthops_reset_priority(nexthops, i);
+ });
+}
+
+bool nexthops_equal(nexthops_t *a, nexthops_t *b) {
+ unsigned n;
+ if (nexthops_get_len(a) != nexthops_get_len(b)) return false;
+ nexthops_foreach(a, n, {
+ if (!nexthops_contains(b, n)) return false;
+ });
+ return true;
+}
+
+void nexthops_copy(nexthops_t *src, nexthops_t *dst) {
+ for (unsigned i = 0; i < MAX_NEXTHOPS; i++) {
+ dst->elts[i] = src->elts[i];
+ dst->state[i] = src->state[i];
+ }
+ dst->num_elts = src->num_elts;
+ dst->flags = src->flags;
+ dst->cur_elts = src->cur_elts;
+}
+
+#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/core/nexthops.h b/hicn-light/src/hicn/core/nexthops.h
new file mode 100644
index 000000000..2a7fc0b32
--- /dev/null
+++ b/hicn-light/src/hicn/core/nexthops.h
@@ -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.
+ */
+
+/**
+ * \file nexthops.h
+ * \brief Nexthops
+ *
+ * An implementation of the nexthop data structure for the FIB entry.
+ *
+ * Note that the position of nexthops in this structure can be reordered. This
+ * is not an issue for the strategy state since the state if bound to the
+ * nexthop information, but an external module should not keep any reference to
+ * the offset of the nexthop.
+ */
+
+#ifndef HICNLIGHT_NEXTHOPS_H
+#define HICNLIGHT_NEXTHOPS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <hicn/util/log.h>
+
+#include "connection.h"
+#include "strategy_vft.h"
+
+#define _nexthops_var(x) _nexthops_##x
+
+typedef unsigned nexthop_t;
+#define NEXTHOP(x) ((nexthop_t)x)
+
+#define INVALID_NEXTHOP NEXTHOP(CONNECTION_ID_UNDEFINED)
+
+/*
+ * This allows storage within a single integer
+ * 32 or 64 nexthops should be sufficient
+ * Eventually replace this with a resizeable vector
+ */
+#define MAX_NEXTHOPS (sizeof(uint_fast32_t) * 8)
+
+typedef struct nexthops_s {
+ unsigned elts[MAX_NEXTHOPS];
+ strategy_nexthop_state_t state[MAX_NEXTHOPS];
+ size_t num_elts;
+
+ /*
+ * flags is used during the processing of nexthops by the policy framework,
+ * and its meaning is local to the related functions.
+ * It is a mask where a bit set to 1 in position N indicates that the Nth
+ * elements in the elts array (elts[N]) is disabled.
+ * The number of enabled next hops is reflected in cur_elts, and it is equal
+ * to num_elts if no nexthop is disabled. This could be replaced by an
+ * efficient function counting the number of 1 bits in flags.
+ */
+ uint_fast32_t flags;
+ size_t cur_elts;
+} nexthops_t;
+
+#define NEXTHOPS_EMPTY \
+ (nexthops_t) { \
+ .elts = {0}, .state = {STRATEGY_NEXTHOP_STATE_EMPTY}, .num_elts = 0, \
+ .flags = 0, .cur_elts = 0, \
+ }
+
+#define nexthops_state(NH, i) ((NH)->state[(i)])
+
+#define nexthops_get_len(NH) ((NH)->num_elts)
+
+#define nexthops_set_len(NH, LEN) \
+ do { \
+ (NH)->num_elts = LEN; \
+ (NH)->cur_elts = LEN; \
+ } while (0)
+
+#define nexthops_get_curlen(NH) ((NH)->cur_elts)
+
+#define nexthops_inc(NH) \
+ do { \
+ (NH)->num_elts++; \
+ (NH)->cur_elts++; \
+ } while (0)
+
+int nexthops_disable(nexthops_t *nexthops, off_t offset);
+
+#define nexthops_disable_if(NH, i, condition) \
+ do { \
+ if (condition) { \
+ nexthops_disable((NH), (i)); \
+ } \
+ } while (0)
+
+#define nexthops_is_disabled(NH, i) ((NH)->flags & (1 << (i)))
+
+void nexthops_reset(nexthops_t *nexthops);
+
+#define nexthops_enumerate(NH, i, X, BODY) \
+ do { \
+ for ((i) = 0; (i) < nexthops_get_len(NH); (i)++) { \
+ if (nexthops_is_disabled((NH), (i))) continue; \
+ X = (NH)->elts[(i)]; \
+ do { \
+ BODY \
+ } while (0); \
+ } \
+ } while (0)
+
+#define nexthops_foreach(NH, X, BODY) \
+ do { \
+ unsigned _nexthops_var(i); \
+ nexthops_enumerate((NH), _nexthops_var(i), (X), {BODY}); \
+ } while (0)
+
+off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop);
+
+off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop);
+
+#define nexthops_clear(NH) \
+ do { \
+ nexthops_set_len(NH, 0); \
+ (NH)->flags = 0; \
+ } while (0)
+
+bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop);
+
+off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop);
+
+unsigned nexthops_get_one(nexthops_t *nexthops);
+
+int nexthops_select(nexthops_t *nexthops, off_t i);
+
+/*
+ * This selects the first available element, irrespective of the current state
+ * of flags
+ */
+#define nexthops_select_first(NH) nexthops_select((NH), 0)
+
+#ifdef WITH_POLICY
+
+#define DEFAULT_PRIORITY 0
+#define DISABLED_PRIORITY -1
+
+void nexthops_set_priority(nexthops_t *nexthops, nexthop_t nexthop,
+ int priority);
+
+void nexthops_set_priority_by_id(nexthops_t *nexthops, off_t i, int priority);
+
+void nexthops_reset_priority_by_id(nexthops_t *nexthops, off_t i);
+
+void nexthops_reset_priority(nexthops_t *nexthops, nexthop_t nexthop);
+
+void nexthops_reset_priorities(nexthops_t *nexthops);
+
+/*
+ * returns true if the list of next hops contained in a is the same of b
+ * returns false otherwise
+ */
+bool nexthops_equal(nexthops_t *a, nexthops_t *b);
+
+void nexthops_copy(nexthops_t *src, nexthops_t *dst);
+
+#endif /* WITH_POLICY */
+
+#endif /* HICNLIGHT_NEXTHOPS_H */
diff --git a/hicn-light/src/hicn/core/numberSet.c b/hicn-light/src/hicn/core/numberSet.c
deleted file mode 100644
index 106e13be6..000000000
--- a/hicn-light/src/hicn/core/numberSet.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/numberSet.h>
-#include <stdio.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct number_set {
- Number *arrayOfNumbers;
- size_t length;
- size_t limit;
- unsigned refcount;
-};
-
-static void numberSet_Expand(NumberSet *set);
-
-NumberSet *numberSet_Create() {
- NumberSet *set = parcMemory_AllocateAndClear(sizeof(NumberSet));
- parcAssertNotNull(set, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(NumberSet));
- set->arrayOfNumbers = parcMemory_AllocateAndClear(sizeof(Number) * 16);
- parcAssertNotNull((set->arrayOfNumbers),
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Number) * 16);
- set->length = 0;
- set->limit = 16;
- set->refcount = 1;
- return set;
-}
-
-NumberSet *numberSet_Acquire(const NumberSet *original) {
- parcAssertNotNull(original, "Parameter original must be non-null");
- NumberSet *copy = (NumberSet *)original;
- copy->refcount++;
- return copy;
-}
-
-void numberSet_Release(NumberSet **setPtr) {
- parcAssertNotNull(setPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*setPtr, "Parameter must dereference to non-null pointer");
-
- NumberSet *set = *setPtr;
- parcAssertTrue(
- set->refcount > 0,
- "Invalid state: calling destroy on an object with 0 reference count");
- set->refcount--;
-
- if (set->refcount == 0) {
- parcMemory_Deallocate((void **)&(set->arrayOfNumbers));
- parcMemory_Deallocate((void **)&set);
- *setPtr = NULL;
- }
-}
-
-/**
- * @function numberSet_AddNoChecks
- * @abstract Add a number we know is not already in the set
- * @discussion
- * Used by other functions that already know the number is unique in the set,
- * Does not do the expensive Contains check.
- */
-static void numberSet_AddNoChecks(NumberSet *set, Number number) {
- if (set->length == set->limit) {
- numberSet_Expand(set);
- }
-
- set->arrayOfNumbers[set->length] = number;
- set->length++;
-}
-
-bool numberSet_Add(NumberSet *set, Number number) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- if (numberSet_Contains(set, number)) {
- return false;
- }
-
- numberSet_AddNoChecks(set, number);
- return true;
-}
-
-size_t numberSet_Length(const NumberSet *set) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- return set->length;
-}
-
-Number numberSet_GetItem(const NumberSet *set, size_t ordinalIndex) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- parcAssertTrue(ordinalIndex < set->length,
- "Limit beyond end of set, length %zu got %zu", set->length,
- ordinalIndex);
-
- return set->arrayOfNumbers[ordinalIndex];
-}
-
-bool numberSet_Contains(const NumberSet *set, Number number) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- for (size_t i = 0; i < set->length; i++) {
- if (set->arrayOfNumbers[i] == number) {
- return true;
- }
- }
- return false;
-}
-
-void numberSet_AddSet(NumberSet *destinationSet, const NumberSet *setToAdd) {
- parcAssertNotNull(destinationSet,
- "Parameter destinationSet must be non-null");
- parcAssertNotNull(setToAdd, "Parameter setToAdd must be non-null");
-
- for (size_t i = 0; i < setToAdd->length; i++) {
- numberSet_Add(destinationSet, setToAdd->arrayOfNumbers[i]);
- }
-}
-
-NumberSet *numberSet_Subtract(const NumberSet *minuend,
- const NumberSet *subtrahend) {
- // because the underlying ADT is not sorted, this is pretty ineffient, could
- // be O(n^2).
-
- NumberSet *difference = numberSet_Create();
-
- for (size_t i = 0; i < minuend->length; i++) {
- bool unique = true;
- for (size_t j = 0; j < subtrahend->length && unique; j++) {
- if (minuend->arrayOfNumbers[i] == subtrahend->arrayOfNumbers[j]) {
- unique = false;
- }
- }
-
- if (unique) {
- numberSet_AddNoChecks(difference, minuend->arrayOfNumbers[i]);
- }
- }
- return difference;
-}
-
-bool numberSet_Equals(const NumberSet *a, const NumberSet *b) {
- if (a == NULL && b == NULL) {
- return true;
- }
-
- if (a == NULL || b == NULL) {
- return false;
- }
-
- if (a->length == b->length) {
- for (size_t i = 0; i < a->length; i++) {
- bool found = false;
- for (size_t j = 0; j < b->length && !found; j++) {
- if (a->arrayOfNumbers[i] == b->arrayOfNumbers[j]) {
- found = true;
- }
- }
- if (!found) {
- return false;
- }
- }
- return true;
- }
-
- return false;
-}
-
-void numberSet_Remove(NumberSet *set, Number number) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- for (size_t i = 0; i < set->length; i++) {
- if (set->arrayOfNumbers[i] == number) {
- set->length--;
- if (set->length > 0) {
- // move the last element to the removed element to keep the array
- // packed.
- set->arrayOfNumbers[i] = set->arrayOfNumbers[set->length];
- }
- return;
- }
- }
-}
-
-// =====================================================
-
-static void numberSet_Expand(NumberSet *set) {
- size_t newlimit = set->limit * 2;
- size_t newbytes = newlimit * sizeof(Number);
-
- set->arrayOfNumbers = parcMemory_Reallocate(set->arrayOfNumbers, newbytes);
- set->limit = newlimit;
-}
diff --git a/hicn-light/src/hicn/core/numberSet.h b/hicn-light/src/hicn/core/numberSet.h
deleted file mode 100644
index 91a965d7b..000000000
--- a/hicn-light/src/hicn/core/numberSet.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @brief Stores a set of numbers.
- *
- * Useful for things like the reverse path of a PIT
- * or the forward paths of a FIB. Does not allow duplicates.
- *
- */
-
-#ifndef numberSet_h
-#define numberSet_h
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-struct number_set;
-typedef struct number_set NumberSet;
-
-typedef uint32_t Number;
-
-/**
- * @function numberList_Create
- * @abstract A new list of numbers
- */
-NumberSet *numberSet_Create(void);
-
-/**
- * Obtains a reference counted copy of the original
- * The reference count is increased by one. It must be released with
- * NumberSet_Release().
- * @param [in] original An allocated NumberSet
- * @return non-null The reference counted copy
- */
-NumberSet *numberSet_Acquire(const NumberSet *original);
-
-/**
- * Releases one reference count and destroys the memory after last release
- * The pointer will be NULLed after release regardless if the memory was
- * destroyed.
- * @param [in,out] setPtr A pointer to a NumberSet. Will be NULL'd after
- * release.
- */
-void numberSet_Release(NumberSet **setPtr);
-
-/**
- * @function numberList_Append
- * @abstract Add a number to the end of the list
- * @discussion
- * No check for duplicates is done
- * @return true if added, false if a duplicate
- */
-bool numberSet_Add(NumberSet *set, Number number);
-
-/**
- * @function numberList_Length
- * @abstract The count of numbers in the list
- */
-size_t numberSet_Length(const NumberSet *set);
-
-/**
- * @function numberSet_GetItem
- * @abstract Retrieves an item based on the ordinal index
- * @discussion
- * Will assert if the ordinalIndex is out of bounds.
- */
-Number numberSet_GetItem(const NumberSet *set, size_t ordinalIndex);
-
-/**
- * @function numberSet_Contains
- * @abstract Checks for set membership
- * @return true if the set contains the number, false otherwise
- */
-bool numberSet_Contains(const NumberSet *set, Number number);
-
-/**
- * @function numberSet_AddSet
- * @abstract Adds one set to another set
- * @discussion
- * Adds <code>setToAdd</code> to <code>destinationSet</code>
- * @return true if the set contains the number, false otherwise
- */
-void numberSet_AddSet(NumberSet *destinationSet, const NumberSet *setToAdd);
-
-/**
- * @function numberSet_Subtract
- * @abstract Computes set difference <code>difference = minuend -
- * subtrahend</code>, returns a new number set.
- * @discussion
- * <code>minuend</code> and <code>subtrahend</code> are not modified. A new
- * difference set is created.
- *
- * Returns the elements in <code>minuend</code> that are not in
- * <code>subtrahend</code>.
- *
- * @param minuend The set from which to subtract
- * @param subrahend The set begin removed from minuend
- * @return The set difference. May be empty, but will not be NULL.
- */
-NumberSet *numberSet_Subtract(const NumberSet *minuend,
- const NumberSet *subtrahend);
-
-/**
- * Determine if two NumberSet instances are equal.
- *
- * Two NumberSet instances are equal if, and only if,
- * they are the same size and contain the same elements. Empty sets are
- * equal. NULL equals NULL, but does not equal non-NULL.
- *
- * The following equivalence relations on non-null `NumberSet` instances are
- * maintained:
- *
- * * It is reflexive: for any non-null reference value x, `NumberSet_Equals(x,
- * x)` must return true.
- *
- * * It is symmetric: for any non-null reference values x and y,
- * `numberSet_Equals(x, y)` must return true if and only if
- * `numberSet_Equals(y, x)` returns true.
- *
- * * It is transitive: for any non-null reference values x, y, and z, if
- * `numberSet_Equals(x, y)` returns true and
- * `numberSet_Equals(y, z)` returns true,
- * then `numberSet_Equals(x, z)` must return true.
- *
- * * It is consistent: for any non-null reference values x and y, multiple
- * invocations of `numberSet_Equals(x, y)` consistently return true or
- * consistently return false.
- *
- * * For any non-null reference value x, `numberSet_Equals(x, NULL)` must
- * return false.
- *
- * @param a A pointer to a `NumberSet` instance.
- * @param b A pointer to a `NumberSet` instance.
- * @return true if the two `NumberSet` instances are equal.
- */
-bool numberSet_Equals(const NumberSet *a, const NumberSet *b);
-
-/**
- * @function numberSet_Remove
- * @abstract Removes the number from the set
- */
-void numberSet_Remove(NumberSet *set, Number number);
-#endif // numberSet_h
diff --git a/hicn-light/src/hicn/core/packet_cache.c b/hicn-light/src/hicn/core/packet_cache.c
new file mode 100644
index 000000000..203ad4a63
--- /dev/null
+++ b/hicn-light/src/hicn/core/packet_cache.c
@@ -0,0 +1,547 @@
+/*
+ * 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 packet_cache.c
+ * \brief Implementation of hICN packet cache
+ */
+
+#include "packet_cache.h"
+
+pkt_cache_t *pkt_cache_create(size_t cs_size) {
+ pkt_cache_t *pkt_cache = (pkt_cache_t *)malloc(sizeof(pkt_cache_t));
+
+ pkt_cache->pit = pit_create();
+ if (!pkt_cache->pit) return NULL;
+ pkt_cache->cs = cs_create(cs_size);
+ if (!pkt_cache->cs) return NULL;
+
+ pkt_cache->index_by_name = kh_init(pkt_cache_name);
+ pool_init(pkt_cache->entries, DEFAULT_PKT_CACHE_SIZE, 0);
+
+ 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
+ pool_free(pkt_cache->entries);
+
+ // Free PIT and CS
+ pit_free(pkt_cache->pit);
+ cs_free(pkt_cache->cs);
+
+ free(pkt_cache);
+}
+
+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; }
+
+pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name,
+ msgbuf_pool_t *msgbuf_pool,
+ 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)) {
+ *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;
+ if (entry->has_expire_ts && ticks_now() >= entry->expire_ts) {
+ expired = true;
+ }
+
+ if (entry->entry_type == PKT_CACHE_CS_TYPE) {
+ if (expired)
+ *lookup_result = PKT_CACHE_LU_DATA_EXPIRED;
+ else
+ *lookup_result = PKT_CACHE_LU_DATA_NOT_EXPIRED;
+ } else { // PKT_CACHE_PIT_TYPE
+ if (expired)
+ *lookup_result = PKT_CACHE_LU_INTEREST_EXPIRED;
+ else
+ *lookup_result = PKT_CACHE_LU_INTEREST_NOT_EXPIRED;
+ }
+
+ *entry_id = index;
+ return entry;
+}
+
+void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, bool is_evicted) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+
+ 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);
+
+ // Do not update the LRU cache for evicted entries
+ if (!is_evicted) cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry);
+
+ pkt_cache->cs->num_entries--;
+ pool_put(pkt_cache->entries, entry);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(msgbuf_get_name(msgbuf));
+ DEBUG("Packet %s removed from CS", name_str);
+ free(name_str);
+ })
+
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+}
+
+void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry, const Name *name) {
+ assert(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);
+
+ pool_put(pkt_cache->entries, entry);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(name);
+ DEBUG("Packet %s removed from PIT", name_str);
+ free(name_str);
+ })
+}
+
+void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id) {
+ entry->u.cs_entry =
+ (cs_entry_t){.msgbuf_id = msgbuf_id,
+ .lru = {.prev = INVALID_ENTRY_ID, .next = INVALID_ENTRY_ID}};
+ entry->create_ts = ticks_now();
+ entry->expire_ts = ticks_now() + msgbuf_get_data_expiry_time(msgbuf);
+ entry->has_expire_ts = true;
+ entry->entry_type = PKT_CACHE_CS_TYPE;
+
+ pkt_cache->cs->num_entries++;
+
+ int tail_id = 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)
+ pkt_cache_entry_t *tail = pkt_cache_entry_at(pkt_cache, tail_id);
+ assert(tail->entry_type == PKT_CACHE_CS_TYPE);
+ pkt_cache_cs_remove_entry(pkt_cache, tail, msgbuf_pool, true);
+ }
+
+ // Acquired by CS
+ msgbuf_pool_acquire(msgbuf);
+}
+
+void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *interest_entry,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *data_msgbuf,
+ off_t data_msgbuf_id, off_t entry_id) {
+ assert(pkt_cache);
+ assert(interest_entry);
+ assert(interest_entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ _pkt_cache_add_to_cs(pkt_cache, interest_entry, msgbuf_pool, data_msgbuf,
+ data_msgbuf_id, entry_id);
+}
+
+void _pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf) {
+ entry->u.pit_entry = (pit_entry_t){
+ .ingressIdSet = NEXTHOPS_EMPTY,
+ .egressIdSet = NEXTHOPS_EMPTY,
+ .fib_entry = NULL,
+ };
+ pit_entry_ingress_add(&entry->u.pit_entry, msgbuf_get_connection_id(msgbuf));
+
+ entry->create_ts = ticks_now();
+ entry->expire_ts = ticks_now() + msgbuf_get_interest_lifetime(msgbuf);
+ entry->has_expire_ts = true;
+ entry->entry_type = PKT_CACHE_PIT_TYPE;
+}
+
+void pkt_cache_cs_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, const msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+
+ // Release data associated with expired CS entry
+ off_t cs_entry_msgbuf_id = entry->u.cs_entry.msgbuf_id;
+ msgbuf_t *cs_entry_msgbuf = msgbuf_pool_at(msgbuf_pool, cs_entry_msgbuf_id);
+ msgbuf_pool_release(msgbuf_pool, &cs_entry_msgbuf);
+
+ cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry);
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+ pkt_cache->cs->num_entries--;
+}
+
+void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
+ pkt_cache_entry_t *entry, msgbuf_t *msgbuf,
+ off_t msgbuf_id) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_CS_TYPE);
+
+ // Release previous msgbuf and acquire new one
+ msgbuf_t *prev_msgbuf =
+ msgbuf_pool_at(msgbuf_pool, entry->u.cs_entry.msgbuf_id);
+ msgbuf_pool_release(msgbuf_pool, &prev_msgbuf);
+ msgbuf_pool_acquire(msgbuf);
+
+ entry->u.cs_entry.msgbuf_id = msgbuf_id;
+ entry->create_ts = ticks_now();
+ entry->expire_ts = ticks_now() + msgbuf_get_data_expiry_time(msgbuf);
+ entry->has_expire_ts = true;
+
+ cs_vft[pkt_cache->cs->type]->update_entry(pkt_cache, entry);
+}
+
+pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache,
+ const msgbuf_t *msgbuf) {
+ assert(pkt_cache);
+
+ pkt_cache_entry_t *entry =
+ pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf));
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+ return entry;
+}
+
+pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache,
+ msgbuf_pool_t *msgbuf_pool,
+ msgbuf_t *msgbuf, off_t msgbuf_id) {
+ assert(pkt_cache);
+
+ pkt_cache_entry_t *entry =
+ pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf));
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+
+ return entry;
+}
+
+void pkt_cache_update_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ pit_entry_t *pit_entry = &entry->u.pit_entry;
+ fib_entry_t *fib_entry = pit_entry_get_fib_entry(pit_entry);
+ if (fib_entry)
+ fib_entry_on_timeout(fib_entry, pit_entry_get_egress(pit_entry));
+
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+}
+
+bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ pit_entry_t *pit_entry = &entry->u.pit_entry;
+
+ // Extend entry lifetime
+ Ticks expire_ts = ticks_now() + msgbuf_get_interest_lifetime(msgbuf);
+ if (expire_ts > entry->expire_ts) entry->expire_ts = expire_ts;
+
+ // Check if the reverse path is already present
+ // in the PIT entry (i.e. it is a retransmission)
+ unsigned connection_id = msgbuf_get_connection_id(msgbuf);
+ bool is_aggregated = !pit_entry_ingress_contains(pit_entry, connection_id);
+ if (is_aggregated) pit_entry_ingress_add(pit_entry, connection_id);
+
+ WITH_DEBUG({
+ char *name_str = name_ToString(msgbuf_get_name(msgbuf));
+ if (is_aggregated) {
+ DEBUG("Interest %s already existing (expiry %lu): aggregate", name_str,
+ entry->expire_ts);
+ } else {
+ DEBUG("Interest %s already existing (expiry %lu): retransmit", name_str,
+ entry->expire_ts);
+ }
+ free(name_str);
+ })
+
+ return is_aggregated;
+}
+
+nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache,
+ msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id,
+ bool is_cs_store_enabled,
+ bool is_connection_local, bool *wrong_egress,
+ pkt_cache_verdict_t *verdict) {
+ assert(pkt_cache);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA);
+
+ *wrong_egress = false;
+ 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, true);
+
+ pit_entry_t *pit_entry;
+ fib_entry_t *fib_entry;
+ nexthops_t *nexthops = NULL;
+ nexthops_t *nexthops_copy;
+ switch (lookup_result) {
+ case PKT_CACHE_LU_INTEREST_NOT_EXPIRED:
+ pit_entry = &entry->u.pit_entry;
+ fib_entry = pit_entry_get_fib_entry(pit_entry);
+ if (fib_entry)
+ fib_entry_on_data(fib_entry, pit_entry_get_egress(pit_entry), msgbuf,
+ entry->create_ts, ticks_now());
+
+ // Check if the data is coming from the exepected connection
+ nexthops_t *egressIdSet = pit_entry_get_egress(pit_entry);
+ unsigned egress_connection = msgbuf_get_connection_id(msgbuf);
+ if (!nexthops_contains(egressIdSet, egress_connection)) {
+ *wrong_egress = true;
+ return NULL;
+ }
+
+ // XXX TODO : be sure nexthops are valid b/c pit entry is removed
+ // XXX TODO eventually pass holding structure as parameter
+ nexthops = pit_entry_get_ingress(pit_entry);
+ assert(nexthops);
+
+ nexthops_copy = (nexthops_t *)malloc(sizeof(*nexthops_copy));
+ *nexthops_copy = *nexthops;
+
+ if (is_cs_store_enabled) {
+ pkt_cache_pit_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+ *verdict = PKT_CACHE_VERDICT_FORWARD_DATA;
+ } else {
+ pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf));
+ *verdict = PKT_CACHE_VERDICT_CLEAR_DATA;
+ }
+
+ return nexthops_copy;
+
+ // Data packets are stored in the content store even in the case
+ // where there is no match in the PIT, to allow applications to push
+ // content to the forwarder's CS. This behavior is allowed only for
+ // local faces.
+ case PKT_CACHE_LU_INTEREST_EXPIRED:
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_pit_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+ *verdict = PKT_CACHE_VERDICT_STORE_DATA;
+ } else {
+ pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf));
+ *verdict = PKT_CACHE_VERDICT_CLEAR_DATA;
+ }
+ return NULL;
+
+ case PKT_CACHE_LU_NONE:
+ *verdict = PKT_CACHE_VERDICT_IGNORE_DATA;
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, msgbuf_id);
+ *verdict = PKT_CACHE_VERDICT_STORE_DATA;
+ }
+ return NULL;
+
+ case PKT_CACHE_LU_DATA_EXPIRED:
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, msgbuf, msgbuf_id);
+ *verdict = PKT_CACHE_VERDICT_UPDATE_DATA;
+ } else {
+ pkt_cache_cs_remove_entry(pkt_cache, entry, msgbuf_pool, false);
+ *verdict = PKT_CACHE_VERDICT_CLEAR_DATA;
+ }
+ return NULL;
+
+ case PKT_CACHE_LU_DATA_NOT_EXPIRED:
+ *verdict = PKT_CACHE_VERDICT_IGNORE_DATA;
+ if (is_cs_store_enabled && is_connection_local) {
+ pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, msgbuf, msgbuf_id);
+ *verdict = PKT_CACHE_VERDICT_UPDATE_DATA;
+ }
+ return NULL;
+
+ default:
+ ERROR("Inivalid packet cache content");
+ return NULL;
+ }
+}
+
+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) {
+ assert(pkt_cache);
+ assert(msgbuf_id_is_valid(msgbuf_id));
+
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
+
+ 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);
+ *entry_ptr = entry;
+
+ cs_entry_t *cs_entry = NULL;
+ bool is_cs_miss = true;
+ bool is_aggregated;
+ switch (lookup_result) {
+ case PKT_CACHE_LU_NONE:
+ *verdict = PKT_CACHE_VERDICT_FORWARD_INTEREST;
+ break;
+
+ case PKT_CACHE_LU_DATA_NOT_EXPIRED:
+ if (!is_serve_from_cs_enabled) goto PKT_CACHE_LU_DATA_EXPIRED;
+
+ cs_entry = &entry->u.cs_entry;
+ *data_msgbuf_id = cs_entry->msgbuf_id;
+
+ *verdict = PKT_CACHE_VERDICT_FORWARD_DATA;
+ is_cs_miss = false;
+ break;
+
+ case PKT_CACHE_LU_INTEREST_NOT_EXPIRED:
+ is_aggregated = pkt_cache_try_aggregate_in_pit(pkt_cache, entry, msgbuf);
+
+ *verdict = is_aggregated ? PKT_CACHE_VERDICT_AGGREGATE_INTEREST
+ : PKT_CACHE_VERDICT_RETRANSMIT_INTEREST;
+ break;
+
+ case PKT_CACHE_LU_INTEREST_EXPIRED:
+ pkt_cache_update_pit(pkt_cache, entry, msgbuf);
+
+ *verdict = PKT_CACHE_VERDICT_INTEREST_EXPIRED_FORWARD_INTEREST;
+ break;
+
+ case PKT_CACHE_LU_DATA_EXPIRED:
+ PKT_CACHE_LU_DATA_EXPIRED:
+ pkt_cache_cs_to_pit(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+
+ *verdict = PKT_CACHE_VERDICT_DATA_EXPIRED_FORWARD_INTEREST;
+ break;
+
+ default:
+ *verdict = PKT_CACHE_VERDICT_ERROR;
+ }
+ is_cs_miss ? cs_miss(pkt_cache->cs) : cs_hit(pkt_cache->cs);
+}
+
+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);
+}
+
+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;
+}
+
+size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache) {
+ return pkt_cache->cs->num_entries;
+}
+
+size_t pkt_cache_get_num_cs_stale_entries(pkt_cache_t *pkt_cache) {
+ size_t num_stale_entries = 0;
+ Ticks now = ticks_now();
+ pkt_cache_entry_t *entry;
+
+ pool_foreach(pkt_cache->entries, entry, {
+ if (entry->entry_type == PKT_CACHE_CS_TYPE && entry->has_expire_ts &&
+ now >= entry->expire_ts) {
+ num_stale_entries++;
+ }
+ });
+
+ return num_stale_entries;
+}
+
+int pkt_cache_set_cs_size(pkt_cache_t *pkt_cache, size_t size) {
+ if (pkt_cache->cs->num_entries > size) return -1;
+
+ pkt_cache->cs->max_size = size;
+ return 0;
+}
+
+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;
+ 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);
+
+ cs_log(pkt_cache->cs);
+}
diff --git a/hicn-light/src/hicn/core/packet_cache.h b/hicn-light/src/hicn/core/packet_cache.h
new file mode 100644
index 000000000..ccfc83b97
--- /dev/null
+++ b/hicn-light/src/hicn/core/packet_cache.h
@@ -0,0 +1,445 @@
+/*
+ * 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 packet_cache.h
+ * \brief hICN packet cache
+ *
+ * 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.
+ *
+ * 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
+ * the PIT or CS specific fields.
+ *
+ * Having a single entry that can hold PIT or CS entries allows to reduce
+ * the number of lookups.
+ */
+
+#ifndef HICNLIGHT_PACKET_CACHE_H
+#define HICNLIGHT_PACKET_CACHE_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);
+
+ Name name_key;
+ memset(&name_key, 0, sizeof(Name));
+
+ name_key.content_name = *content_name;
+ name_key.segment = name_GetSegment(name);
+ name_key.name_hash = name_HashCode(name);
+
+ return name_key;
+}
+
+KHASH_INIT(pkt_cache_name, const Name *, unsigned, 1, name_HashCode,
+ name_Equals);
+
+typedef struct {
+ pkt_cache_entry_type_t entry_type;
+
+ Ticks create_ts;
+ Ticks expire_ts;
+ // TODO(eloparco): Is it necessary?
+ // Now it is always set to true
+ bool has_expire_ts;
+
+ union {
+ pit_entry_t pit_entry;
+ cs_entry_t cs_entry;
+ } u;
+} pkt_cache_entry_t;
+
+typedef struct {
+ pit_t *pit;
+ cs_t *cs;
+ pkt_cache_entry_t *entries;
+ kh_pkt_cache_name_t *index_by_name;
+} pkt_cache_t;
+
+/**
+ * @brief Create a new packet cache.
+ *
+ * @return pkt_cache_t* The newly created packet cache
+ */
+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.
+ *
+ * @param[in] pkt_cache Pointer to the msgbuf pool data structure to use.
+ * @param[in, out] entry Empty entry that will be used to return the
+ * 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;
+}
+
+/**
+ * @brief Free a packet cache data structure.
+ *
+ * @param[in] pkt_cache Pointer to packet cache data structure to free.
+ */
+void pkt_cache_free(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Get a reference to the PIT data structure contained in the packet
+ * cache.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to get the
+ * PIT from.
+ */
+pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Get a reference to the CS data structure contained in the packet
+ * cache.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to get the CS
+ * from.
+ */
+cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Return the total packet cache size (i.e. PIT + CS).
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ */
+size_t pkt_cache_get_size(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Return the number of stale entries (i.e. expired) in the CS.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ */
+size_t pkt_cache_get_num_cs_stale_entries(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Change the maximum capacity of the content store (LRU eviction will be
+ * used after reaching the provided size)
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] size Maximum size of the content store
+ * @return int 0 if success, -1 if the provided maximum size is smaller than the
+ * number of elements currently stored in the CS
+ */
+int pkt_cache_set_cs_size(pkt_cache_t *pkt_cache, size_t size);
+
+/**
+ * @brief Return the content store size.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ */
+size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Return the PIT size.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ */
+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) \
+ (entry)->expire_ts = EXPIRY_TIME
+#define pkt_cache_get_entry_id(pkt_cache, entry) (entry - pkt_cache->entries)
+#define pkt_cache_entry_at(pkt_cache, id) (&(pkt_cache)->entries[id])
+#define pkt_cache_at(pkt_cache, i) (pkt_cache->entries + i)
+
+/**
+ * @brief Retrieve from the packet cache the entry associated with the specified
+ * name.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to retrieve
+ * the entry from
+ * @param[in] name Packet name to use for the lookup
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in, out] lookup_result Pointer to store the result of the lookup
+ * @param[in, out] entry_id Pointer to store the entry_id in case of a lookup
+ * match
+ * @param[in] is_serve_from_cs_enabled Boolean to specify if the forwarder is
+ * allowed to serve contents from the CS
+ * @return pkt_cache_entry_t* Entry retrieved, NULL if none found
+ */
+pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name,
+ msgbuf_pool_t *msgbuf_pool,
+ pkt_cache_lookup_t *lookup_result,
+ off_t *entry_id,
+ bool is_serve_from_cs_enabled);
+
+/**
+ * @brief Clear the content of the CS.
+ *
+ * @param pkt_cache Pointer to the packet cache data structure to use
+ */
+void pkt_cache_cs_clear(pkt_cache_t *pkt_cache);
+
+/**
+ * @brief Log packet cache statistics.
+ *
+ * @param pkt_cache Pointer to the packet cache data structure to use
+ */
+void pkt_cache_log(pkt_cache_t *pkt_cache);
+
+// TODO(eloparco): To implement
+void pkt_cache_print(const pkt_cache_t *pkt_cache);
+
+/************** Packet cache entry operations *************/
+
+/**
+ * @brief Remove a content store entry from the packet cache.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] entry Pointer to the content store entry to remove
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in] is_evicted Boolean to specify if the content store entry has
+ * already been evicted from the LRU cache
+ */
+void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, bool is_evicted);
+
+/**
+ * @brief Remove a PIT entry from the packet cache.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] entry Pointer to the PITe entry to remove
+ * @param[in] name Name associated with the PIT entry to remove
+ */
+void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry, const Name *name);
+
+/**
+ * @brief Convert a PIT entry to a CS entry.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in, out] entry Pointer to the PIT entry to replace
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in] msgbuf Pointer to the msgbuf associated with the CS entry to
+ * insert
+ * @param[in] msgbuf_id Msgbuf ID (i.e. ID in the msgbuf pool) associated with
+ * the CS entry to insert
+ * @param[in] entry_id Entry ID (i.e. ID in the packet cache pool of entries)
+ * associated with the PIT entry to replace
+ */
+void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id);
+
+/**
+ * @brief Convert a CS entry to a PIT entry.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in, out] entry Pointer to the CS entry to replace
+ * @param[in] msgbuf Pointer to the msgbuf associated with the PIT entry to
+ * insert
+ * @param[in] msgbuf_id Msgbuf ID (i.e. ID in the msgbuf pool) associated with
+ * the PIT entry to insert
+ * @param[in] entry_id Entry ID (i.e. ID in the packet cache pool of entries)
+ * associated with the CS entry to replace
+ */
+void pkt_cache_cs_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ msgbuf_pool_t *msgbuf_pool, const msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id);
+
+/**
+ * @brief Add PIT entry to the packet cache.
+ *
+ * @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
+ * @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);
+
+/**
+ * @brief Add CS entry to the packet cache.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in] msgbuf Pointer to the msgbuf associated with the CS entry to
+ * insert
+ * @param[in] msgbuf_id Msgbuf ID (i.e. ID in the msgbuf pool) associated with
+ * the CS entry to insert
+ * @return pkt_cache_entry_t* Pointer to the packet cache (CS) entry created
+ */
+pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache,
+ msgbuf_pool_t *msgbuf_pool,
+ msgbuf_t *msgbuf, off_t msgbuf_id);
+
+/**
+ * @brief Update PIT entry in the packet cache in case of an expired PIT entry.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @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
+ */
+void pkt_cache_update_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf);
+
+/**
+ * @brief Update CS entry in the packet cache.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] msgbuf_pool Pointer to the msgbuf pool data structure to use
+ * @param[in, out] entry Pointer to the CS entry to update
+ * @param[in] msgbuf Pointer to the msgbuf associated with the CS entry to
+ * update
+ * @param msgbuf_id Msgbuf ID (i.e. ID in the msgbuf pool) associated with the
+ * CS entry to update
+ */
+void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
+ pkt_cache_entry_t *entry, msgbuf_t *msgbuf,
+ off_t msgbuf_id);
+
+/**
+ * @brief Update PIT entry in the packet cache in case of retransmission or
+ * aggregation.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @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
+ * @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
+ * stored in the PIT entry)
+ */
+bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry,
+ const msgbuf_t *msgbuf);
+
+/************ Handle data/interest packets received *******/
+
+/**
+ * @brief Handle data packet reception.
+ * @details Perform packet cache lookup and execute operations based on it. If:
+ * - INTEREST not expired: Convert PIT entry to CS entry; return the
+ * nexthops (that can be used to forward the data
+ * packet now stored in the CS)
+ * - INTEREST expired: Convert PIT entry to CS entry
+ * - DATA expired/not expired: Update the CS
+ * - No match: Add data packet to CS
+ */
+nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache,
+ msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id,
+ bool is_cs_store_enabled,
+ bool is_connection_local, bool *wrong_egress,
+ pkt_cache_verdict_t *verdict);
+
+/**
+ * @brief Handle interest packet reception.
+ * @details Perform packet cache lookup and execute operations based on it. If:
+ * - No match: Do nothing
+ * - DATA not expired: get data message from CS
+ * - INTEREST not expired: Aggregate or retransmit the interest received;
+ * - INTEREST expired: Update the PIT;
+ * - DATA expired: Convert CS entry to PIT entry;
+ */
+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);
+
+/************** Content Store *****************************/
+
+typedef struct {
+ const char *name;
+ void (*initialize)(cs_t *cs);
+ void (*finalize)(cs_t *cs);
+ int (*add_entry)(pkt_cache_t *pkt_cache, off_t entry_id);
+ void (*update_entry)(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry);
+ int (*remove_entry)(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry);
+} cs_ops_t;
+extern const cs_ops_t *const cs_vft[];
+
+/**
+ * @brief Initialize the virtual function table used for the
+ * CS cache strategy (e.g. LRU).
+ *
+ */
+#define DECLARE_CS(NAME) \
+ const cs_ops_t cs_##NAME = { \
+ .name = #NAME, \
+ .initialize = cs_##NAME##_initialize, \
+ .finalize = cs_##NAME##_finalize, \
+ .add_entry = cs_##NAME##_add_entry, \
+ .update_entry = cs_##NAME##_update_entry, \
+ .remove_entry = cs_##NAME##_remove_entry, \
+ }
+
+#endif /* HICNLIGHT_PACKET_CACHE_H */
diff --git a/hicn-light/src/hicn/core/pit.c b/hicn-light/src/hicn/core/pit.c
new file mode 100644
index 000000000..322e53674
--- /dev/null
+++ b/hicn-light/src/hicn/core/pit.c
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/**
+ * The pending interest table.
+ *
+ * Interest aggregation strategy:
+ * - The first Interest for a name is forwarded
+ * - A second Interest for a name from a different reverse path may be
+ * aggregated
+ * - A second Interest for a name from an existing Interest is forwarded
+ * - The Interest Lifetime is like a subscription time. A reverse path entry is
+ * removed once the lifetime is exceeded.
+ * - Whan an Interest arrives or is aggregated, the Lifetime for that reverse
+ * hop is extended. As a simplification, we only keep a single lifetime not per
+ * reverse hop.
+ *
+ */
+
+#include "pit.h"
+
+Ticks pit_calculate_lifetime(pit_t* pit, const msgbuf_t* msgbuf) {
+ uint64_t lifetime = msgbuf_get_lifetime(msgbuf);
+ if (lifetime == 0) lifetime = NSEC_TO_TICKS(DEFAULT_INTEREST_LIFETIME);
+
+ return ticks_now() + lifetime;
+}
+
+/* This is only used as a hint for first allocation, as the table is resizeable
+ */
+#define DEFAULT_PIT_SIZE 65535
+
+pit_t* _pit_create(size_t init_size, size_t max_size) {
+ pit_t* pit = malloc(sizeof(pit_t));
+ if (!pit) return NULL;
+
+ if (init_size == 0) init_size = DEFAULT_PIT_SIZE;
+
+ pit->max_size = max_size;
+ return pit;
+}
+
+void pit_free(pit_t* pit) {
+ assert(pit);
+ free(pit);
+}
+
+// void pit_print(const pit_t *pit) {
+// const Name *k;
+// unsigned v;
+// pit_entry_t * entry;
+// Ticks expire_ts;
+
+// printf("*** PIT ***\n");
+// kh_foreach(pit->index_by_name, k, v, {
+// char *name_str = name_ToString(k);
+// entry = pit_at(pit, v);
+// expire_ts = pit_entry_get_expire_ts(entry);
+// printf("%s\t\t\texpire=%lu\n", name_str, expire_ts);
+// free(name_str);
+// })
+// }
diff --git a/hicn-light/src/hicn/core/pit.h b/hicn-light/src/hicn/core/pit.h
new file mode 100644
index 000000000..f2e901490
--- /dev/null
+++ b/hicn-light/src/hicn/core/pit.h
@@ -0,0 +1,73 @@
+/*
+ * 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 pit.h
+ * @brief hICN Pending Interest Table (PIT)
+ */
+
+#ifndef HICNLIGHT_PIT_H
+#define HICNLIGHT_PIT_H
+
+#include <hicn/core/fib.h>
+
+typedef struct {
+ nexthops_t ingressIdSet;
+ nexthops_t egressIdSet;
+ fib_entry_t* fib_entry;
+} pit_entry_t;
+
+#define pit_entry_get_ingress(E) (&((E)->ingressIdSet))
+#define pit_entry_get_egress(E) (&((E)->egressIdSet))
+#define pit_entry_get_fib_entry(E) ((E)->fib_entry)
+#define pit_entry_set_fib_entry(E, FIB_ENTRY) ((E)->fib_entry = FIB_ENTRY)
+
+#define pit_entry_ingress_add(E, NH) \
+ nexthops_add(pit_entry_get_ingress(E), (NH))
+
+#define pit_entry_ingress_contains(E, NH) \
+ nexthops_contains(pit_entry_get_ingress(E), (NH))
+
+#define pit_entry_egress_add(E, NH) nexthops_add(pit_entry_get_egress(E), (NH))
+
+typedef struct {
+ // TODO(eloparco): How to handle PIT size?
+ size_t max_size;
+} pit_t;
+
+#define DEFAULT_INTEREST_LIFETIME 4000000000ULL
+
+Ticks pit_calculate_lifetime(pit_t* pit, const msgbuf_t* msgbuf);
+
+/**
+ * @brief Allocate a new PIT data structure (extended parameters)
+ *
+ * @param init_size Initial size (0 = default)
+ * @param max_size Maximum size (0 = unbounded)
+ *
+ * @return pit_t* Newly allocated PIT data structure
+ */
+pit_t* _pit_create(size_t init_size, size_t max_size);
+
+/**
+ * @brief Allocate a new PIT data structure
+ *
+ * @return pit_t* Newly allocated PIT data structure
+ */
+#define pit_create() _pit_create(0, 0)
+
+void pit_free(pit_t* pit);
+
+#endif /* HICNLIGHT_PIT_H */
diff --git a/hicn-light/src/hicn/core/policy_stats.c b/hicn-light/src/hicn/core/policy_stats.c
new file mode 100644
index 000000000..1acbccf69
--- /dev/null
+++ b/hicn-light/src/hicn/core/policy_stats.c
@@ -0,0 +1,189 @@
+#ifdef WITH_POLICY_STATS
+
+// This has to be included first because of _GNU_SOURCE
+#include <hicn/core/forwarder.h>
+
+#include <hicn/core/connection_table.h>
+#include <hicn/base/loop.h>
+#include <hicn/util/log.h>
+#include <hicn/core/ticks.h>
+#include <hicn/policy.h>
+#include <hicn/core/fib.h>
+
+#include "policy_stats.h"
+
+#define ALPHA 0.9
+#define STATS_INTERVAL 1000 /* ms */
+
+static int policy_stats_mgr_tick(void* mgr_arg, int fd, void* data) {
+ policy_stats_mgr_t* mgr = mgr_arg;
+ assert(mgr);
+ assert(!data);
+
+ uint64_t now = ticks_now();
+
+ /* Loop over FIB entries to compute statistics from counters */
+ const fib_t* fib = forwarder_get_fib(mgr->forwarder);
+ fib_entry_t* entry;
+
+ fib_foreach_entry(fib, entry, {
+ policy_stats_update(&entry->policy_stats, &entry->policy_counters, now);
+ });
+
+ return 0;
+}
+
+int policy_stats_mgr_initialize(policy_stats_mgr_t* mgr, void* forwarder) {
+ mgr->forwarder = forwarder;
+
+ loop_timer_create(&mgr->timer, MAIN_LOOP, mgr, policy_stats_mgr_tick, NULL);
+ if (!mgr->timer) {
+ ERROR("Error allocating prefix stats mgr timer.");
+ return -1;
+ }
+
+ if (loop_timer_register(mgr->timer, STATS_INTERVAL) < 0) {
+ ERROR("Error registering prefix stats mgr timer.");
+ return -1;
+ }
+
+ return 0;
+}
+
+void policy_stats_mgr_finalize(policy_stats_mgr_t* mgr) {
+ loop_event_unregister(mgr->timer);
+ loop_event_free(mgr->timer);
+}
+
+void policy_stats_on_retransmission(const policy_stats_mgr_t* mgr,
+ policy_counters_t* counters,
+ const nexthops_t* nexthops) {
+ connection_table_t* table = forwarder_get_connection_table(mgr->forwarder);
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+#ifdef WITH_POLICY
+ const connection_t* conn = connection_table_at(table, nexthop);
+
+ if (connection_has_tag(conn, POLICY_TAG_WIRED))
+ counters->wired.num_losses++;
+ if (connection_has_tag(conn, POLICY_TAG_WIFI)) counters->wifi.num_losses++;
+ if (connection_has_tag(conn, POLICY_TAG_CELLULAR))
+ counters->cellular.num_losses++;
+#endif /* WITH_POLICY */
+ counters->all.num_losses++;
+ });
+}
+
+#define UPDATE_TAG_STATS(TAG, NAME) \
+ do { \
+ if (connection_has_tag(conn, TAG)) { \
+ counters->NAME.num_packets++; \
+ counters->NAME.num_bytes += msg_size; \
+ stats->NAME.latency = \
+ ALPHA * stats->NAME.latency + (1 - ALPHA) * (double)rtt; \
+ counters->NAME.latency_idle = 0; \
+ } \
+ } while (0)
+
+/* Update statistic counters upon Data packet reception */
+void policy_stats_on_data(const policy_stats_mgr_t* mgr, policy_stats_t* stats,
+ policy_counters_t* counters,
+ const nexthops_t* nexthops, const msgbuf_t* msgbuf,
+ Ticks rtt) {
+#ifdef WITH_POLICY
+ forwarder_t* forwarder = mgr->forwarder;
+ connection_table_t* table = forwarder_get_connection_table(forwarder);
+#endif /* WITH_POLICY */
+
+ size_t msg_size = msgbuf_get_len(msgbuf);
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+#ifdef WITH_POLICY
+ const connection_t* conn = connection_table_at(table, nexthop);
+ if (!conn) continue;
+
+ UPDATE_TAG_STATS(POLICY_TAG_WIRED, wired);
+ UPDATE_TAG_STATS(POLICY_TAG_WIFI, wifi);
+ UPDATE_TAG_STATS(POLICY_TAG_CELLULAR, cellular);
+#endif /* WITH_POLICY */
+ });
+
+ stats->all.latency = ALPHA * stats->all.latency + (1 - ALPHA) * (double)rtt;
+ counters->all.latency_idle = 0;
+ counters->all.num_packets++;
+ counters->all.num_bytes += msg_size;
+}
+
+void policy_stats_on_timeout(const policy_stats_mgr_t* mgr,
+ policy_counters_t* counters,
+ const nexthops_t* nexthops) {
+#ifdef WITH_POLICY
+ connection_table_t* table = forwarder_get_connection_table(mgr->forwarder);
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ const connection_t* conn = connection_table_at(table, nexthop);
+ if (!conn) continue;
+ if (connection_has_tag(conn, POLICY_TAG_WIRED))
+ counters->wired.num_losses++;
+ if (connection_has_tag(conn, POLICY_TAG_WIFI)) counters->wifi.num_losses++;
+ if (connection_has_tag(conn, POLICY_TAG_CELLULAR))
+ counters->cellular.num_losses++;
+ });
+#endif /* WITH_POLICY */
+
+ counters->all.num_losses++;
+}
+
+#define UPDATE_TYPE(TYPE) \
+ do { \
+ /* (a) throughput */ \
+ if (counters->TYPE.num_bytes > 0) { \
+ throughput = counters->TYPE.num_bytes / (now - counters->last_update); \
+ throughput = throughput * 8 / 1024; \
+ if (throughput < 0) throughput = 0; \
+ } else { \
+ throughput = 0; \
+ } \
+ stats->TYPE.throughput = \
+ ALPHA * stats->TYPE.throughput + (1 - ALPHA) * throughput; \
+ \
+ /* (b) loss rate */ \
+ if ((counters->TYPE.num_losses > 0) && (counters->TYPE.num_packets > 0)) { \
+ loss_rate = counters->TYPE.num_losses / counters->TYPE.num_packets; \
+ loss_rate *= 100; \
+ } else { \
+ loss_rate = 0; \
+ } \
+ stats->TYPE.loss_rate = \
+ ALPHA * stats->TYPE.loss_rate + (1 - ALPHA) * loss_rate; \
+ \
+ /* (c) latency */ \
+ counters->TYPE.latency_idle++; \
+ if (counters->TYPE.latency_idle > 1) stats->TYPE.latency = 0; \
+ \
+ /* (d) Reset counters */ \
+ counters->TYPE.num_bytes = 0; \
+ counters->TYPE.num_losses = 0; \
+ counters->TYPE.num_packets = 0; \
+ } while (0)
+
+void policy_stats_update(policy_stats_t* stats, policy_counters_t* counters,
+ uint64_t now) {
+ double throughput;
+ double loss_rate;
+
+ if (now == counters->last_update) return;
+
+#ifdef WITH_POLICY
+ UPDATE_TYPE(wired);
+ UPDATE_TYPE(wifi);
+ UPDATE_TYPE(cellular);
+#endif /* WITH_POLICY */
+ UPDATE_TYPE(all);
+
+ counters->last_update = now;
+}
+
+#endif /* WITH_POLICY_STATS */
diff --git a/hicn-light/src/hicn/core/policy_stats.h b/hicn-light/src/hicn/core/policy_stats.h
new file mode 100644
index 000000000..fa12b51cb
--- /dev/null
+++ b/hicn-light/src/hicn/core/policy_stats.h
@@ -0,0 +1,93 @@
+
+#ifndef HICNLIGHT_POLICY_STATS_H
+#define HICNLIGHT_POLICY_STATS_H
+
+#ifdef WITH_POLICY_STATS
+
+#include <hicn/policy.h>
+#include "../base/loop.h"
+
+typedef struct policy_stats_mgr_s {
+ void* forwarder;
+ event_t* timer;
+} policy_stats_mgr_t;
+
+#if 0
+
+/* PER-INTERFACE POLICY STATS */
+
+typedef struct {
+ float throughput;
+ float latency;
+ float loss_rate;
+} interface_stats_t;
+
+/* POLICY STATS */
+
+typedef struct {
+ interface_stats_t wired;
+ interface_stats_t wifi;
+ interface_stats_t cellular;
+ interface_stats_t all;
+} policy_stats_t;
+
+typedef struct {
+ uint32_t num_packets;
+ uint32_t num_bytes;
+ uint32_t num_losses;
+ uint32_t latency_idle;
+} interface_counters_t;
+
+typedef struct {
+ interface_counters_t wired;
+ interface_counters_t wifi;
+ interface_counters_t cellular;
+ interface_counters_t all;
+ uint64_t last_update;
+} policy_counters_t;
+
+#define INTERFACE_STATS_EMPTY \
+ (interface_stats_t) { .throughput = 0, .latency = 0, .loss_rate = 0, }
+
+#define POLICY_STATS_EMPTY \
+ (policy_stats_t) { \
+ .wired = INTERFACE_STATS_EMPTY, .wifi = INTERFACE_STATS_EMPTY, \
+ .cellular = INTERFACE_STATS_EMPTY, .all = INTERFACE_STATS_EMPTY, \
+ }
+
+#define INTERFACE_COUNTERS_EMPTY \
+ (interface_counters_t) { \
+ .num_packets = 0, .num_bytes = 0, .num_losses = 0, .latency_idle = 0, \
+ }
+
+#define POLICY_COUNTERS_EMPTY \
+ (policy_counters_t) { \
+ .wired = INTERFACE_COUNTERS_EMPTY, .wifi = INTERFACE_COUNTERS_EMPTY, \
+ .cellular = INTERFACE_COUNTERS_EMPTY, .all = INTERFACE_COUNTERS_EMPTY, \
+ .last_update = 0, \
+ }
+#endif
+
+int policy_stats_mgr_initialize(policy_stats_mgr_t* mgr, void* forwarder);
+
+void policy_stats_mgr_finalize(policy_stats_mgr_t* mgr);
+
+void policy_stats_on_retransmission(const policy_stats_mgr_t* mgr,
+ policy_counters_t* countrs,
+ const nexthops_t* nexthops);
+
+void policy_stats_on_data(const policy_stats_mgr_t* mgr, policy_stats_t* stats,
+ policy_counters_t* counters,
+ const nexthops_t* nexthops, const msgbuf_t* msgbuf,
+ Ticks rtt);
+
+void policy_stats_on_timeout(const policy_stats_mgr_t* mgr,
+ policy_counters_t* counters,
+ const nexthops_t* nexthops);
+
+void policy_stats_update(policy_stats_t* stats, policy_counters_t* counters,
+ uint64_t now);
+
+#endif /* WITH_POLICY_STATS */
+
+#endif /* HICNLIGHT_POLICY_STATS_H */
diff --git a/hicn-light/src/hicn/core/strategy.c b/hicn-light/src/hicn/core/strategy.c
new file mode 100644
index 000000000..3716cd585
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file strategy.c
+ * \brief Implementation of hICN forwarding strategy
+ */
+
+#include "nexthops.h"
+#include "strategy.h"
+#include "strategy_vft.h"
+
+int strategy_initialize(strategy_entry_t *entry, const void *forwarder) {
+ return strategy_vft[entry->type]->initialize(entry, forwarder);
+}
+
+nexthops_t *strategy_lookup_nexthops(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const msgbuf_t *msgbuf) {
+ return strategy_vft[entry->type]->lookup_nexthops(entry, nexthops, msgbuf);
+}
+
+int strategy_add_nexthop(strategy_entry_t *entry, nexthops_t *nexthops,
+ off_t offset) {
+ return strategy_vft[entry->type]->add_nexthop(entry, nexthops, offset);
+}
+
+int strategy_remove_nexthop(strategy_entry_t *entry, nexthops_t *nexthops,
+ off_t offset) {
+ return strategy_vft[entry->type]->remove_nexthop(entry, nexthops, offset);
+}
+
+int strategy_on_data(strategy_entry_t *entry, nexthops_t *nexthops,
+ const nexthops_t *data_nexthops, const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation, Ticks objReception) {
+ return strategy_vft[entry->type]->on_data(
+ entry, nexthops, data_nexthops, msgbuf, pitEntryCreation, objReception);
+}
+
+int strategy_on_timeout(strategy_entry_t *entry, nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops) {
+ return strategy_vft[entry->type]->on_timeout(entry, nexthops,
+ timeout_nexthops);
+}
diff --git a/hicn-light/src/hicn/core/strategy.h b/hicn-light/src/hicn/core/strategy.h
new file mode 100644
index 000000000..9ce75c51d
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy.h
@@ -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.
+ */
+
+/**
+ * \file strategy.h
+ * \brief hICN forwarding strategy
+ */
+#ifndef HICNLIGHT_STRATEGY_H
+#define HICNLIGHT_STRATEGY_H
+
+/*
+ * Forwarding strategy
+ *
+ * The forwarding strategy decides to elect one or several next hops among those
+ * available in the FIB entry, after an eventual application of the policy. This
+ * means it should be aware of the different flags set in the nexthops_t data
+ * structure by previous forwarding steps, that might have excluded certain
+ * nexthops.
+ *
+ * A strategy is defined by its type and comes with :
+ * - options, initialized at setup and that might eventually be updated (this
+ * is allowed on a per-strategy basis.
+ * - a state (eventually) empty, that is used to inform its decisions, and
+ * might be updated for each interest sent (lookup_nexthops), data received
+ * (on_data) or timeout event (on_timeout).
+ *
+ * All this information (type, options, state) is made available through a
+ * strategy_entry_t which is stored together with nexthops in the FIB entry.
+ *
+ * Per-nexthop strategy informaton is stored in the nexthops table itself. As it
+ * would be difficult and suboptimal to provide a correct strategy-dependent
+ * initialization in the FIB nad nexthops data structures, it is thus the
+ * responsibility of the forwarding strategy to initialize its state and nexthop
+ * related state when appropriate (eg. at initialization, or when a nexthop is
+ * added).
+ */
+
+#include "nexthops.h"
+#include "strategy_vft.h"
+
+typedef struct strategy_entry_s {
+ const void *forwarder;
+ strategy_type_t type;
+ strategy_options_t options;
+ strategy_state_t state;
+} strategy_entry_t;
+
+int strategy_initialize(strategy_entry_t *entry, const void *forwarder);
+
+nexthops_t *strategy_lookup_nexthops(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const msgbuf_t *msgbuf);
+
+int strategy_add_nexthop(strategy_entry_t *entry, nexthops_t *nexthops,
+ off_t offset);
+
+int strategy_remove_nexthop(strategy_entry_t *entry, nexthops_t *nexthops,
+ off_t offset);
+
+int strategy_on_data(strategy_entry_t *entry, nexthops_t *nexthops,
+ const nexthops_t *data_nexthops, const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation, Ticks objReception);
+
+int strategy_on_timeout(strategy_entry_t *entry, nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops);
+
+#endif /* HICNLIGHT_STRATEGY_H */
diff --git a/hicn-light/src/hicn/core/strategy_vft.c b/hicn-light/src/hicn/core/strategy_vft.c
new file mode 100644
index 000000000..dcfda5c78
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy_vft.c
@@ -0,0 +1,37 @@
+/*
+ * 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 strategy_vft.c
+ * \brief Implementation of hICN forwarding strategy VFT
+ */
+
+#include "strategy_vft.h"
+
+extern const strategy_ops_t strategy_load_balancer;
+extern const strategy_ops_t strategy_random;
+extern const strategy_ops_t strategy_replication;
+extern const strategy_ops_t strategy_bestpath;
+extern const strategy_ops_t strategy_low_latency;
+
+const strategy_ops_t *const strategy_vft[] = {
+ [STRATEGY_TYPE_LOADBALANCER] = &strategy_load_balancer,
+ [STRATEGY_TYPE_RANDOM] = &strategy_random,
+ [STRATEGY_TYPE_REPLICATION] = &strategy_replication,
+ [STRATEGY_TYPE_BESTPATH] = &strategy_bestpath,
+#if 0
+ [STRATEGY_TYPE_LOW_LATENCY] = &strategy_low_latency,
+#endif
+};
diff --git a/hicn-light/src/hicn/core/strategy_vft.h b/hicn-light/src/hicn/core/strategy_vft.h
new file mode 100644
index 000000000..0256cba57
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy_vft.h
@@ -0,0 +1,128 @@
+/*
+ * 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 strategy_vft.h
+ * \brief hICN forwarding strategy VFT
+ */
+#ifndef HICNLIGHT_STRATEGY_VFT_H
+#define HICNLIGHT_STRATEGY_VFT_H
+
+#include "msgbuf.h"
+
+#include "../strategies/best_path.h"
+#include "../strategies/load_balancer.h"
+#include "../strategies/low_latency.h"
+#include "../strategies/random.h"
+#include "../strategies/replication.h"
+
+typedef union {
+ strategy_load_balancer_options_t load_balancer;
+ strategy_low_latency_options_t low_latency;
+ strategy_random_options_t random;
+ strategy_replication_options_t replication;
+ strategy_bestpath_options_t bestpath;
+} strategy_options_t;
+
+typedef struct {
+#ifdef WITH_POLICY
+ int priority;
+#endif /* WITH_POLICY */
+ union {
+ strategy_load_balancer_nexthop_state_t load_balancer;
+ strategy_low_latency_nexthop_state_t low_latency;
+ strategy_random_nexthop_state_t random;
+ strategy_replication_nexthop_state_t replication;
+ strategy_bestpath_nexthop_state_t bestpath;
+ };
+} strategy_nexthop_state_t;
+
+#define STRATEGY_NEXTHOP_STATE_EMPTY \
+ { \
+ 0, { \
+ { 0 } \
+ } \
+ }
+
+typedef union {
+ strategy_load_balancer_state_t load_balancer;
+ strategy_low_latency_state_t low_latency;
+ strategy_random_state_t random;
+ strategy_replication_state_t replication;
+ strategy_bestpath_state_t bestpath;
+} strategy_state_t;
+// XXX This has to be merged with nexthops
+// XXX How to avoid errors due to pool id reuse (eg on_data) ?
+
+/**
+ * @typedef strategy_ops_t
+ * @abstract Forwarding strategy implementation
+ * @constant receiveObject is called when we receive an object and have a
+ * measured round trip time. This allows a strategy to update its performance
+ * data.
+ * @constant lookupNexthop Find the set of nexthops to use for the Interest.
+ * May be empty, should not be NULL. Must be destroyed.
+ * @constant addNexthop Add a nexthop to the list of available nexthops with a
+ * routing protocol-specific cost.
+ * @constant destroy cleans up the strategy, freeing all memory and state. A
+ * strategy is reference counted, so the final destruction only happens after
+ * the last reference is released.
+ * @discussion <#Discussion#>
+ */
+
+struct strategy_entry_s;
+struct nexthops_s;
+
+typedef struct {
+ const char *name;
+
+ int (*initialize)(struct strategy_entry_s *entry, const void *forwarder);
+
+ int (*finalize)(struct strategy_entry_s *entry);
+
+ struct nexthops_s *(*lookup_nexthops)(struct strategy_entry_s *entry,
+ struct nexthops_s *nexthops,
+ const msgbuf_t *msgbuf);
+
+ int (*add_nexthop)(struct strategy_entry_s *strategy,
+ struct nexthops_s *nexthops, off_t offset);
+
+ int (*remove_nexthop)(struct strategy_entry_s *entry,
+ struct nexthops_s *nexthops, off_t offset);
+
+ int (*on_data)(struct strategy_entry_s *entry, struct nexthops_s *nexthops,
+ const struct nexthops_s *data_nexthops, const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation, Ticks objReception);
+
+ int (*on_timeout)(struct strategy_entry_s *entry, struct nexthops_s *nexthops,
+ const struct nexthops_s *timeout_nexthops);
+
+} strategy_ops_t;
+
+extern const strategy_ops_t *const strategy_vft[];
+
+#define DECLARE_STRATEGY(NAME) \
+ const strategy_ops_t strategy_##NAME = { \
+ .name = #NAME, \
+ .initialize = strategy_##NAME##_initialize, \
+ .finalize = strategy_##NAME##_finalize, \
+ .add_nexthop = strategy_##NAME##_add_nexthop, \
+ .remove_nexthop = strategy_##NAME##_remove_nexthop, \
+ .lookup_nexthops = strategy_##NAME##_lookup_nexthops, \
+ .on_data = strategy_##NAME##_on_data, \
+ .on_timeout = strategy_##NAME##_on_timeout, \
+ }
+
+#endif /* HICNLIGHT_STRATEGY_VFT_H */
diff --git a/hicn-light/src/hicn/core/streamBuffer.c b/hicn-light/src/hicn/core/streamBuffer.c
index c30139498..401b7c873 100644
--- a/hicn-light/src/hicn/core/streamBuffer.c
+++ b/hicn-light/src/hicn/core/streamBuffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-light/src/hicn/core/streamBuffer.h b/hicn-light/src/hicn/core/streamBuffer.h
index 27e793176..0caa10bea 100644
--- a/hicn-light/src/hicn/core/streamBuffer.h
+++ b/hicn-light/src/hicn/core/streamBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-light/src/hicn/core/subscription.c b/hicn-light/src/hicn/core/subscription.c
new file mode 100644
index 000000000..0c4949f26
--- /dev/null
+++ b/hicn-light/src/hicn/core/subscription.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#include "subscription.h"
+#include <hicn/base/vector.h>
+#include <hicn/util/log.h>
+
+/*----------------------------------------------------------------------------*
+ * Topics and events
+ *----------------------------------------------------------------------------*/
+
+bool topics_contains(hc_topics_t topic_list, hc_topic_t topic) {
+ return ((topic_list) & (topic));
+}
+
+#define topic_is_set(topic_list, topic_index) \
+ ((topic_list) & (1 << (topic_index)))
+
+const char *event_str[] = {
+#define _(x) [EVENT_##x] = #x,
+ foreach_event_type
+#undef _
+};
+
+/*----------------------------------------------------------------------------*
+ * Subscriptions
+ *----------------------------------------------------------------------------*/
+
+struct subscription_table_s {
+ unsigned *table[TOPIC_N];
+};
+
+subscription_table_t *subscription_table_create() {
+ subscription_table_t *subscriptions = malloc(sizeof(subscription_table_t));
+ for (int i = 0; i < NUM_TOPICS; i++)
+ vector_init(subscriptions->table[i], 0, 0);
+
+ return subscriptions;
+}
+
+void subscription_table_free(subscription_table_t *subscriptions) {
+ for (int i = 0; i < NUM_TOPICS; i++) vector_free(subscriptions->table[i]);
+ free(subscriptions);
+}
+
+int subscription_table_add_topics_for_connection(
+ subscription_table_t *subscriptions, hc_topics_t topics,
+ unsigned connection_id) {
+ bool is_subscription_already_present = false;
+ for (int topic_index = 0; topic_index < NUM_TOPICS; topic_index++) {
+ if (topic_is_set(topics, topic_index)) {
+ int num_duplicates = vector_remove_unordered(
+ subscriptions->table[topic_index], connection_id);
+
+ int ret = vector_push(subscriptions->table[topic_index], connection_id);
+ if (ret < 0) {
+ ERROR("Unable to perform subscription for connection %d, topic %s",
+ connection_id, object_str(topic_index));
+ return -1;
+ }
+
+ if (num_duplicates > 0) {
+ DEBUG("Connection %d had already a subscription for topic %s",
+ connection_id, object_str(topic_index));
+ is_subscription_already_present = true;
+ }
+ }
+ }
+ return is_subscription_already_present ? -2 : 0;
+}
+
+int subscription_table_remove_topics_for_connection(
+ subscription_table_t *subscriptions, hc_topics_t topics,
+ unsigned connection_id) {
+ int num_subscriptions_removed = 0;
+ for (int topic_index = 0; topic_index < NUM_TOPICS; topic_index++) {
+ if (topic_is_set(topics, topic_index)) {
+ int num_duplicates = vector_remove_unordered(
+ subscriptions->table[topic_index], connection_id);
+ if (num_duplicates <= 0) {
+ continue;
+ }
+ num_subscriptions_removed++;
+ }
+ }
+ return num_subscriptions_removed;
+}
+
+hc_topics_t subscription_table_get_topics_for_connection(
+ subscription_table_t *subscriptions, unsigned connection_id) {
+ hc_topics_t topics = 0;
+ for (int topic_index = 0; topic_index < NUM_TOPICS; topic_index++) {
+ unsigned *conn_id;
+ bool found = false;
+ vector_foreach(subscriptions->table[topic_index], conn_id, {
+ if (*conn_id == connection_id) {
+ found = true;
+ break;
+ }
+ });
+ if (found) topics |= (1 << topic_index);
+ }
+ return topics;
+}
+
+unsigned *subscription_table_get_connections_for_topic(
+ subscription_table_t *subscriptions, hc_topic_t topic) {
+ int topic_index = object_from_topic(topic);
+ return subscriptions->table[topic_index];
+}
+
+void subscription_table_print(subscription_table_t *subscriptions) {
+ for (int topic_index = OBJECT_UNDEFINED + 1; topic_index < NUM_TOPICS;
+ topic_index++) {
+ printf("topic %s (%lu subscription/s) from connection/s: [ ",
+ object_str(topic_index),
+ (unsigned long)vector_len(subscriptions->table[topic_index]));
+ unsigned *connection_id;
+ vector_foreach(subscriptions->table[topic_index], connection_id,
+ { printf("%d ", *connection_id); });
+ printf("]\n");
+ }
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/subscription.h b/hicn-light/src/hicn/core/subscription.h
new file mode 100644
index 000000000..74ddd9e18
--- /dev/null
+++ b/hicn-light/src/hicn/core/subscription.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#ifndef HICNLIGHT_SUBSCRIPTION_H
+#define HICNLIGHT_SUBSCRIPTION_H
+
+#include <hicn/ctrl/api.h>
+#include <stddef.h>
+
+/*----------------------------------------------------------------------------*
+ * Topics
+ *----------------------------------------------------------------------------*/
+
+bool topics_contains(hc_topics_t topic_list, hc_topic_t topic);
+
+/*----------------------------------------------------------------------------*
+ * Subscriptions
+ *----------------------------------------------------------------------------*/
+
+typedef struct subscription_table_s subscription_table_t;
+
+subscription_table_t *subscription_table_create();
+
+void subscription_table_free(subscription_table_t *subscriptions);
+
+/**
+ * @brief Add topic subscriptions for a connection.
+ *
+ * @param subscriptions The pointer to the subscription table
+ * @param topics Topics the connection wants to subscribe to
+ * @param connection_id Identifier of the connection
+ * @return int 0 for success, -1 for error, -2 if already esisting subscription
+ * for at least one of the topic for
+ */
+int subscription_table_add_topics_for_connection(
+ subscription_table_t *subscriptions, hc_topics_t topics,
+ unsigned connection_id);
+
+/**
+ * @brief Remove topic subscriptions for a connection.
+ *
+ * @param subscriptions The pointer to the subscription table
+ * @param topics Topics the connection wants to unsubscribe to
+ * @param connection_id Identifier of the connection
+ * @return int Number of removed subscriptions
+ */
+int subscription_table_remove_topics_for_connection(
+ subscription_table_t *subscriptions, hc_topics_t topics,
+ unsigned connection_id);
+
+/**
+ * @brief Get the topics a connection has subscribed to.
+ *
+ * @param subscriptions The pointer to the subscription table
+ * @param connection_id Identifier of the connection
+ * @return hc_topics_t
+ */
+hc_topics_t subscription_table_get_topics_for_connection(
+ subscription_table_t *subscriptions, unsigned connection_id);
+
+/**
+ * @brief Get the connections that have a subscription for the specified topic.
+ *
+ * @param subscriptions The pointer to the subscription table
+ * @param topic Topic to retrieve the subscriptions for
+ * @return unsigned* Array containing the connection ids associated with the
+ * specified topic
+ */
+unsigned *subscription_table_get_connections_for_topic(
+ subscription_table_t *subscriptions, hc_topic_t topic);
+
+/**
+ * @brief Print the subscription table containing, for each topic, the list
+ * of connections with a subsctiption.
+ *
+ * @param subscriptions The pointer to the subscription table
+ */
+void subscription_table_print(subscription_table_t *subscriptions);
+
+#endif // HICNLIGHT_SUBSCRIPTION_H \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/system.h b/hicn-light/src/hicn/core/system.h
index be6c3e7cf..860133dd3 100644
--- a/hicn-light/src/hicn/core/system.h
+++ b/hicn-light/src/hicn/core/system.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,13 +25,12 @@
#define system_h
#include <hicn/core/forwarder.h>
-#include <hicn/utils/interfaceSet.h>
/**
* @function system_Interfaces
* @abstract The system network interfaces
*/
-InterfaceSet *system_Interfaces(Forwarder *forwarder);
+InterfaceSet *system_Interfaces(forwarder_t *forwarder);
/**
* Returns the MTU of the named interface
@@ -43,7 +42,7 @@ InterfaceSet *system_Interfaces(Forwarder *forwarder);
* @return positive the MTU the kernel reports
*
*/
-unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName);
+unsigned system_InterfaceMtu(forwarder_t *forwarder, const char *interfaceName);
/**
* Returns the LINK address of the specified interface
@@ -55,6 +54,6 @@ unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName);
* @retval null The interface does not exist
*
*/
-Address *system_GetMacAddressByName(Forwarder *forwarder,
+Address *system_GetMacAddressByName(forwarder_t *forwarder,
const char *interfaceName);
#endif
diff --git a/hicn-light/src/hicn/core/ticks.h b/hicn-light/src/hicn/core/ticks.h
index 8750abde5..0955569df 100644
--- a/hicn-light/src/hicn/core/ticks.h
+++ b/hicn-light/src/hicn/core/ticks.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,7 +25,42 @@
#define __STDC_FORMAT_MACROS
#include <stdint.h>
+#include <time.h>
+
+#include <sys/param.h> // HZ
+
+#ifdef __APPLE__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#define HZ 1000
+#endif
typedef uint64_t Ticks;
+// these will all be a little off because its all integer division
+#define NSEC_PER_TICK ((1000000000ULL) / HZ)
+#define NSEC_TO_TICKS(nsec) ((nsec < NSEC_PER_TICK) ? 1 : nsec / NSEC_PER_TICK)
+
+#define TICKS_TO_NSEC(ticks) ((1000000000ULL) * ticks / HZ)
+
+static inline Ticks ticks_now() {
+#if __linux__
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1e6;
+#elif _WIN32
+ struct timespec ts;
+ _clock_gettime(TIME_UTC, &ts);
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1e6;
+#else
+ clock_serv_t clockService;
+ mach_timespec_t ts;
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clockService);
+ clock_get_time(clockService, &ts);
+ mach_port_deallocate(mach_task_self(), clockService);
+#endif
+
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1e6;
+}
+
#endif // ticks_h
diff --git a/hicn-light/src/hicn/core/wldr.c b/hicn-light/src/hicn/core/wldr.c
index ad3663d0d..aa1dbf4f9 100644
--- a/hicn-light/src/hicn/core/wldr.c
+++ b/hicn-light/src/hicn/core/wldr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,93 +13,100 @@
* limitations under the License.
*/
-#include <parc/assert/parc_Assert.h>
-#include <parc/logging/parc_LogReporterTextStdout.h>
#include <hicn/core/connection.h>
#include <hicn/core/forwarder.h>
#include <hicn/core/wldr.h>
#include <stdint.h>
#include <stdio.h>
-struct wldr_buffer {
- Message *message;
+typedef struct {
+ msgbuf_t *msgbuf;
uint8_t rtx_counter;
-};
-
-typedef struct wldr_buffer WldrBuffer;
+} wldr_buffer_t;
-struct wldr_state {
+struct wldr_s {
uint16_t expected_label;
uint16_t next_label;
- WldrBuffer *buffer[BUFFER_SIZE];
+ wldr_buffer_t *buffer[BUFFER_SIZE];
};
-Wldr *wldr_Init() {
- Wldr *wldr = parcMemory_AllocateAndClear(sizeof(Wldr));
+wldr_t *wldr_create() {
+#if 0
+ wldr_t * wldr = parcMemory_AllocateAndClear(sizeof(Wldr));
parcAssertNotNull(wldr, "parcMemory_AllocateAndClear(%zu) returned NULL",
sizeof(Wldr));
wldr->expected_label = 1;
wldr->next_label = 1;
for (int i = 0; i < BUFFER_SIZE; i++) {
- WldrBuffer *entry = parcMemory_AllocateAndClear(sizeof(WldrBuffer));
+ wldr_buffer_t *entry = parcMemory_AllocateAndClear(sizeof(wldr_buffer_t));
parcAssertNotNull(
entry,
- "WldrBuffer init: parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(WldrBuffer));
- entry->message = NULL;
+ "wldr_buffer_t init: parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(wldr_buffer_t));
+ entry->msgbuf = NULL;
entry->rtx_counter = 0;
wldr->buffer[i] = entry;
}
return wldr;
+#else
+ return NULL;
+#endif
}
-void wldr_ResetState(Wldr *wldr) {
+void wldr_resset_state(wldr_t *wldr) {
+#if 0
wldr->expected_label = 1;
wldr->next_label = 1;
for (int i = 0; i < BUFFER_SIZE; i++) {
- wldr->buffer[i]->message = NULL;
+ wldr->buffer[i]->msgbuf = NULL;
wldr->buffer[i]->rtx_counter = 0;
}
+#endif
}
-void wldr_Destroy(Wldr **wldrPtr) {
- Wldr *wldr = *wldrPtr;
+void wldr_free(wldr_t *wldr) {
+#if 0
+ wldr_t * wldr = *wldrPtr;
for (unsigned i = 0; i < BUFFER_SIZE; i++) {
- if (wldr->buffer[i]->message != NULL) {
- message_Release(&(wldr->buffer[i]->message));
+ if (wldr->buffer[i]->msgbuf != NULL) {
+ message_Release(&(wldr->buffer[i]->msgbuf));
parcMemory_Deallocate((void **)&(wldr->buffer[i]));
}
}
parcMemory_Deallocate((void **)&wldr);
*wldrPtr = NULL;
+#endif
}
-static void _wldr_RetransmitPacket(Wldr *wldr, const Connection *conn,
+#if 0
+static void _wldr_RetransmitPacket(wldr_t * wldr, const connection_t * conn,
uint16_t label) {
- if (wldr->buffer[label % BUFFER_SIZE]->message == NULL) {
+ if (wldr->buffer[label % BUFFER_SIZE]->msgbuf == NULL) {
// the required message for retransmission is not in the buffer
return;
}
if (wldr->buffer[label % BUFFER_SIZE]->rtx_counter < MAX_RTX) {
- Message *msg = wldr->buffer[label % BUFFER_SIZE]->message;
+ msgbuf_t *msg = wldr->buffer[label % BUFFER_SIZE]->msgbuf;
message_SetWldrLabel(msg, wldr->next_label);
- if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->message != NULL) {
- message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message));
+ if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf != NULL) {
+ msgbuf_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf));
}
- wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = msg;
+ wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf = msg;
wldr->buffer[wldr->next_label % BUFFER_SIZE]->rtx_counter =
wldr->buffer[label % BUFFER_SIZE]->rtx_counter + 1;
- message_Acquire(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message);
+ message_Acquire(wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf);
wldr->next_label++;
connection_ReSend(conn, msg, false);
}
}
+#endif
-static void _wldr_SendWldrNotificaiton(Wldr *wldr, const Connection *conn,
- Message *message, uint16_t expected_lbl,
+#if 0
+static void _wldr_SendWldrNotification(wldr_t * wldr, const connection_t * conn,
+ msgbuf_t *msgbuf, uint16_t expected_lbl,
uint16_t received_lbl) {
// here we need to create a new packet that is used to send the wldr
// notification to the prevoius hop. the destionation address of the
@@ -113,38 +120,43 @@ static void _wldr_SendWldrNotificaiton(Wldr *wldr, const Connection *conn,
// this way the notification packet will be dispaced to the right connection
// at the next hop.
- Message *notification =
- message_CreateWldrNotification(message, expected_lbl, received_lbl);
+ msgbuf_t *notification =
+ message_CreateWldrNotification(msgbuf, expected_lbl, received_lbl);
parcAssertNotNull(notification, "Got null from CreateWldrNotification");
connection_ReSend(conn, notification, true);
}
+#endif
-void wldr_SetLabel(Wldr *wldr, Message *message) {
+void wldr_set_label(wldr_t *wldr, msgbuf_t *msgbuf) {
+#if 0
// in this function we send the packet for the first time
// 1) we set the wldr label
- message_SetWldrLabel(message, wldr->next_label);
+ message_SetWldrLabel(msgbuf, wldr->next_label);
// 2) we store the pointer to packet in the buffer
- if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->message != NULL) {
+ if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf != NULL) {
// release an old message if necessary
- message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message));
+ message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf));
}
// we need to acquire the message to avoid that it gets destroyed
- message_Acquire(message);
+ message_Acquire(msgbuf);
- wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = message;
+ wldr->buffer[wldr->next_label % BUFFER_SIZE]->msgbuf = msgbuf;
wldr->buffer[wldr->next_label % BUFFER_SIZE]->rtx_counter = 0;
wldr->next_label++;
if (wldr->next_label ==
0) // we alwasy skip label 0 beacause it means that wldr is not active
wldr->next_label++;
+#endif
}
-void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message) {
- if (message_HasWldr(message)) {
+void wldr_detect_losses(wldr_t *wldr, const connection_t *connection,
+ const msgbuf_t *msgbuf) {
+#if 0
+ if (message_HasWldr(msgbuf)) {
// this is a normal wldr packet
- uint16_t pkt_lbl = (uint16_t)message_GetWldrLabel(message);
+ uint16_t pkt_lbl = (uint16_t)message_GetWldrLabel(msgbuf);
if (pkt_lbl != wldr->expected_label) {
// if the received packet label is 1 and the expected packet label >
// pkt_lbl usually we are in the case where a remote note disconnected for
@@ -153,7 +165,7 @@ void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message) {
// synch the labels
if ((pkt_lbl != 1) || (wldr->expected_label < pkt_lbl)) {
- _wldr_SendWldrNotificaiton(wldr, conn, message, wldr->expected_label,
+ _wldr_SendWldrNotificaiton(wldr, conn, msgbuf, wldr->expected_label,
pkt_lbl);
}
@@ -165,12 +177,14 @@ void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message) {
wldr->expected_label++; // for the next_label we want to skip 0
}
}
+#endif
}
-void wldr_HandleWldrNotification(Wldr *wldr, const Connection *conn,
- Message *message) {
- uint16_t expected_lbl = (uint16_t)message_GetWldrExpectedLabel(message);
- uint16_t received_lbl = (uint16_t)message_GetWldrLastReceived(message);
+void wldr_handle_notification(wldr_t *wldr, const connection_t *connection,
+ const msgbuf_t *msgbuf) {
+#if 0
+ uint16_t expected_lbl = (uint16_t)message_GetWldrExpectedLabel(msgbuf);
+ uint16_t received_lbl = (uint16_t)message_GetWldrLastReceived(msgbuf);
if ((wldr->next_label - expected_lbl) > BUFFER_SIZE) {
// the packets are not in the buffer anymore
return;
@@ -179,4 +193,5 @@ void wldr_HandleWldrNotification(Wldr *wldr, const Connection *conn,
_wldr_RetransmitPacket(wldr, conn, expected_lbl);
expected_lbl++;
}
+#endif
}
diff --git a/hicn-light/src/hicn/core/wldr.h b/hicn-light/src/hicn/core/wldr.h
index e21889f63..7eccf39cd 100644
--- a/hicn-light/src/hicn/core/wldr.h
+++ b/hicn-light/src/hicn/core/wldr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,7 +18,7 @@
#include <hicn/hicn-light/config.h>
#include <hicn/core/connection.h>
-#include <hicn/core/message.h>
+#include <hicn/core/msgbuf.h>
#define BUFFER_SIZE 8192
#define MAX_RTX 3
@@ -34,19 +34,19 @@
// ATTENTION!!! in order to detect a notificaiton the
// source and destination ports must be set to 0
-struct wldr_state;
-typedef struct wldr_state Wldr;
+typedef struct wldr_s wldr_t;
-Wldr *wldr_Init();
+wldr_t *wldr_create();
-void wldr_Destroy(Wldr **wldrPtr);
+void wldr_free(wldr_t *wldr);
-void wldr_ResetState(Wldr *wldr);
+void wldr_reset_state(wldr_t *wldr);
-void wldr_SetLabel(Wldr *wldr, Message *message);
+void wldr_set_label(wldr_t *wldr, msgbuf_t *msgbuf);
-void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message);
+void wldr_detect_losses(wldr_t *wldr, const connection_t *connection,
+ const msgbuf_t *msgbuf);
-void wldr_HandleWldrNotification(Wldr *wldr, const Connection *conn,
- Message *message);
+void wldr_handle_notification(wldr_t *wldr, const connection_t *connection,
+ const msgbuf_t *msgbuf);
#endif // wldr_h
diff --git a/hicn-light/src/hicn/io/CMakeLists.txt b/hicn-light/src/hicn/io/CMakeLists.txt
index cc4f7371f..68a5baec5 100644
--- a/hicn-light/src/hicn/io/CMakeLists.txt
+++ b/hicn-light/src/hicn/io/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,46 +12,22 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/addressPair.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ioOperations.h
- ${CMAKE_CURRENT_SOURCE_DIR}/listener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/listenerSet.h
- ${CMAKE_CURRENT_SOURCE_DIR}/tcpListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicnListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udpTunnel.h
- ${CMAKE_CURRENT_SOURCE_DIR}/tcpTunnel.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udpConnection.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udpListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/streamConnection.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicnTunnel.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicnConnection.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/addressPair.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ioOperations.c
- ${CMAKE_CURRENT_SOURCE_DIR}/listenerSet.c
- ${CMAKE_CURRENT_SOURCE_DIR}/streamConnection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/tcpListener.c
- ${CMAKE_CURRENT_SOURCE_DIR}/tcpTunnel.c
- ${CMAKE_CURRENT_SOURCE_DIR}/udpConnection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/udpListener.c
- ${CMAKE_CURRENT_SOURCE_DIR}/udpTunnel.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/base.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tcp.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp.c
)
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- list(APPEND SOURCE_FILES
- io/hicnTunnel.c
- io/hicnConnection.c
- io/hicnListener.c
- )
-endif()
-
-set(TO_INSTALL_HEADER_FILES
- ${TO_INSTALL_HEADER_FILES}
- ${HEADER_FILES}
- PARENT_SCOPE
-)
+#if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+# list(APPEND SOURCE_FILES
+# io/hicnTunnel.c
+# io/hicnConnection.c
+# io/hicnListener.c
+# )
+#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/hicn-light/src/hicn/io/addressPair.c b/hicn-light/src/hicn/io/addressPair.c
deleted file mode 100644
index f9451f900..000000000
--- a/hicn-light/src/hicn/io/addressPair.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/io/addressPair.h>
-
-struct address_pair {
- Address *local;
- Address *remote;
-};
-
-static void _addressPair_Destroy(AddressPair **addressPairPtr) {
- AddressPair *pair = *addressPairPtr;
-
- addressDestroy(&pair->local);
- addressDestroy(&pair->remote);
-}
-
-parcObject_ExtendPARCObject(AddressPair, _addressPair_Destroy, NULL,
- addressPair_ToString, addressPair_Equals, NULL,
- addressPair_HashCode, NULL);
-
-parcObject_ImplementAcquire(addressPair, AddressPair);
-
-parcObject_ImplementRelease(addressPair, AddressPair);
-
-AddressPair *addressPair_Create(const Address *local, const Address *remote) {
- parcAssertNotNull(local, "Parameter local must be non-null");
- parcAssertNotNull(remote, "Parameter remote must be non-null");
-
- AddressPair *pair = parcObject_CreateInstance(AddressPair);
- parcAssertNotNull(pair, "Got null from parcObject_Create()");
-
- pair->local = addressCopy(local);
- pair->remote = addressCopy(remote);
-
- return pair;
-}
-
-bool addressPair_Equals(const AddressPair *a, const AddressPair *b) {
- if (a == b) {
- return true;
- }
- if (a == NULL || b == NULL) {
- return false;
- }
-
- if (addressEquals(a->local, b->local)) {
- if (addressEquals(a->remote, b->remote)) {
- return true;
- }
- }
-
- return false;
-}
-
-bool addressPair_EqualsAddresses(const AddressPair *a, const Address *local,
- const Address *remote) {
- if (a == NULL || local == NULL || remote == NULL) {
- return false;
- }
-
- if (addressEquals(a->local, local)) {
- if (addressEquals(a->remote, remote)) {
- return true;
- }
- }
-
- return false;
-}
-
-char *addressPair_ToString(const AddressPair *pair) {
- parcAssertNotNull(pair, "Parameter pair must be non-null");
-
- char *local = addressToString(pair->local);
- char *remote = addressToString(pair->remote);
-
- char *output;
- int failure = asprintf(&output, "{ .local=%s, .remote=%s }", local, remote);
- parcAssertTrue(failure > -1, "Error on asprintf");
-
- parcMemory_Deallocate((void **)&local);
- parcMemory_Deallocate((void **)&remote);
-
- return output;
-}
-
-const Address *addressPair_GetLocal(const AddressPair *pair) {
- parcAssertNotNull(pair, "Parameter pair must be non-null");
- return pair->local;
-}
-
-const Address *addressPair_GetRemote(const AddressPair *pair) {
- parcAssertNotNull(pair, "Parameter pair must be non-null");
- return pair->remote;
-}
-
-/**
- * @function addressPair_HashCode
- * @abstract Hash useful for tables. Consistent with Equals.
- * @discussion
- * Returns a non-cryptographic hash that is consistent with equals. That is,
- * if a == b, then hash(a) == hash(b).
- *
- */
-PARCHashCode addressPair_HashCode(const AddressPair *pair) {
- PARCHashCode hashpair[2];
- hashpair[0] = addressHashCode(pair->local);
- hashpair[1] = addressHashCode(pair->remote);
- return parcHashCode_Hash((const uint8_t *)hashpair, sizeof(hashpair));
-}
diff --git a/hicn-light/src/hicn/io/addressPair.h b/hicn-light/src/hicn/io/addressPair.h
deleted file mode 100644
index f1b72e0dc..000000000
--- a/hicn-light/src/hicn/io/addressPair.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Used to identify a connection between a specific local address and
- * a specific remote address.
- */
-
-#ifndef address_Pair_h
-#define address_Pair_h
-
-#include <hicn/utils/address.h>
-
-struct address_pair;
-typedef struct address_pair AddressPair;
-
-/**
- * @function addressPair_Create
- * @abstract Creates and address pair. There is no restriction on the address
- * types.
- * @discussion
- * Creates an ordered pair of addresses, where the first is considered the
- * "local" address and the second is the "remote" address. Those designations
- * are purely a convention used to name them, and does not imply any specifici
- * types of operations.
- *
- * The two addresses may be of any address types (e.g. IPv4, IPv6, Local,
- * Ethernet). However, some functions that use an AddressPair may require that
- * the local and remote addresses be the same type.
- *
- */
-AddressPair *addressPair_Create(const Address *local, const Address *remote);
-
-/**
- * Returns a reference counted copy of the address pair
- *
- * Increments the reference count and returns the same address pair
- *
- * @param [in] addressPair An allocated address pair
- *
- * @retval non-null A reference counted copy
- * @retval null An error
- */
-AddressPair *addressPair_Acquire(const AddressPair *addressPair);
-
-/**
- * Releases a reference count to the object
- *
- * Decrements the reference count and destroys the object when it reaches 0.
- */
-void addressPair_Release(AddressPair **pairPtr);
-
-/**
- * Determine if two AddressPair instances are equal.
- *
- * Two AddressPair instances are equal if, and only if, the local and remote
- * addresses are identical. Equality is determined by addressEquals(a->local,
- * b->local) and Adress_Equals(a->remote, b->remote).
- *
- * The following equivalence relations on non-null `AddressPair` instances are
- * maintained:
- *
- * * It is reflexive: for any non-null reference value x,
- * `AddressPair_Equals(x, x)` must return true.
- *
- * * It is symmetric: for any non-null reference values x and y,
- * `addressPair_Equals(x, y)` must return true if and only if
- * `addressPair_Equals(y, x)` returns true.
- *
- * * It is transitive: for any non-null reference values x, y, and z, if
- * `addressPair_Equals(x, y)` returns true and
- * `addressPair_Equals(y, z)` returns true,
- * then `addressPair_Equals(x, z)` must return true.
- *
- * * It is consistent: for any non-null reference values x and y, multiple
- * invocations of `addressPair_Equals(x, y)` consistently return true or
- * consistently return false.
- *
- * * For any non-null reference value x, `addressPair_Equals(x, NULL)` must
- * return false.
- *
- * @param a A pointer to a `AddressPair` instance.
- * @param b A pointer to a `AddressPair` instance.
- * @return true if the two `AddressPair` instances are equal.
- */
-bool addressPair_Equals(const AddressPair *a, const AddressPair *b);
-
-/**
- * @function addressPair_EqualsAddresses
- * @abstract As AddressEquals, but "b" is broken out
- * @discussion
- * Equality is determined by addressEquals(a->local, local) and
- * Adress_Equals(a->remote, remote).
- */
-bool addressPair_EqualsAddresses(const AddressPair *a, const Address *local,
- const Address *remote);
-
-const Address *addressPair_GetLocal(const AddressPair *pair);
-
-const Address *addressPair_GetRemote(const AddressPair *pair);
-
-/**
- * @function addressPair_HashCode
- * @abstract Hash useful for tables. Consistent with Equals.
- * @discussion
- * Returns a non-cryptographic hash that is consistent with equals. That is,
- * if a == b, then hash(a) == hash(b).
- */
-PARCHashCode addressPair_HashCode(const AddressPair *pair);
-
-/**
- * @function addressPair_ToString
- * @abstract Human readable string representation. Caller must use free(3).
- */
-char *addressPair_ToString(const AddressPair *pair);
-#endif // address_Pair_h
diff --git a/hicn-light/src/hicn/io/base.c b/hicn-light/src/hicn/io/base.c
new file mode 100644
index 000000000..71d10021e
--- /dev/null
+++ b/hicn-light/src/hicn/io/base.c
@@ -0,0 +1,139 @@
+/*
+ * 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 base.c
+ * #brief Implementation of base IO functions.
+ */
+
+#include <hicn/util/log.h>
+
+#include "base.h"
+
+/**
+ * @brief Helper function for listener to read a single packet on a socket
+ */
+ssize_t io_read_single_fd(int fd, msgbuf_t *msgbuf, address_t *address) {
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ size_t size = msgbuf_get_len(msgbuf);
+
+ for (;;) {
+ ssize_t n = read(fd, packet, size);
+ if (n == 0) return n;
+ if (n < 0) {
+ if (errno == EINTR) continue; // XXX was break;
+
+ /* ICMP unreachable due to closing the remote end of a connection */
+ if (errno == ECONNREFUSED) continue;
+
+ ERROR("read failed %d: (%d) %s", fd, errno, strerror(errno));
+ return -1;
+ }
+
+ msgbuf->length = n;
+ *address = ADDRESS_ANY(AF_UNSPEC, 0); // XXX placeholder, see hicn.c
+ }
+
+ return 1;
+}
+
+ssize_t io_read_single_socket(int fd, msgbuf_t *msgbuf, address_t *address) {
+ struct sockaddr_storage *sa = &address->as_ss;
+ socklen_t sa_len = sizeof(sa);
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+
+ ssize_t n = recvfrom(fd, packet, MTU, 0, (struct sockaddr *)sa, &sa_len);
+ msgbuf->length = n;
+
+ return n;
+}
+
+#ifdef __linux__
+ssize_t io_read_batch_socket(int fd, msgbuf_t **msgbuf, address_t **address,
+ size_t batch_size) {
+ struct mmsghdr msghdr[batch_size];
+ struct iovec iovecs[batch_size];
+ struct sockaddr_storage addrs[batch_size];
+
+ /* Prepare the mmghdr struct for recvmmsg */
+ for (unsigned i = 0; i < MAX_MSG; i++) {
+ struct mmsghdr *msg = &msghdr[i];
+ *msg = (struct mmsghdr){
+ .msg_hdr =
+ {
+ .msg_iov = &iovecs[i],
+ .msg_iovlen = 1,
+ .msg_name = &addrs[i],
+ .msg_namelen = sizeof(struct sockaddr_storage),
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ },
+ };
+
+ iovecs[i] = (struct iovec){
+ .iov_base = msgbuf_get_packet(msgbuf[i]),
+ .iov_len = MTU,
+ };
+ }
+
+ int n;
+ for (;;) {
+ n = recvmmsg(fd, msghdr, batch_size, /* flags */ 0,
+ /* timeout */ NULL);
+ if (n == 0) return 0;
+ if (n < 0) {
+ if (errno == EINTR) continue; // XXX was break;
+
+ /* ICMP unreachable due to closing the remote end of a connection */
+ if (errno == ECONNREFUSED) break;
+ if (errno == EAGAIN) return n; // Nothing to read
+
+ ERROR("read failed %d: (%d) %s", fd, errno, strerror(errno));
+ return (ssize_t)n;
+ }
+
+ /*
+ * Assign size to msgbuf, and put the source address into the array
+ * received in parameters, which corresponds to the remote parts of the
+ * connection (local part is setup in the listener itself, eg.
+ * listener_read_batch).
+ */
+ for (int i = 0; i < n; i++) {
+ 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;
+ }
+
+ return n;
+}
+#endif /* __linux__ */
diff --git a/hicn-light/src/hicn/io/base.h b/hicn-light/src/hicn/io/base.h
new file mode 100644
index 000000000..3463c6760
--- /dev/null
+++ b/hicn-light/src/hicn/io/base.h
@@ -0,0 +1,37 @@
+/*
+ * 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 base.h
+ * #brief Base IO functions.
+ */
+
+#ifndef HICNLIGHT_IO_BASE
+#define HICNLIGHT_IO_BASE
+
+#include "../core/address_pair.h"
+#include "../core/msgbuf.h"
+
+#define MAX_MSG 128 // 64 //16 //32
+#define USE_CONNECTED_SOCKETS 1
+
+ssize_t io_read_single_fd(int fd, msgbuf_t* msgbuf, address_t* address);
+
+ssize_t io_read_single_socket(int fd, msgbuf_t* msgbuf, address_t* address);
+
+ssize_t io_read_batch_socket(int fd, msgbuf_t** msgbuf, address_t** address,
+ size_t n);
+
+#endif /* HICNLIGHT_IO_BASE */
diff --git a/hicn-light/src/hicn/io/hicn.c b/hicn-light/src/hicn/io/hicn.c
new file mode 100644
index 000000000..8b4ad2e00
--- /dev/null
+++ b/hicn-light/src/hicn/io/hicn.c
@@ -0,0 +1,450 @@
+/*
+ * 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 hicn.c
+ * @brief Implementation of hicn face
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <hicn/hicn-light/config.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <hicn/util/log.h>
+
+#include "base.h"
+#include "../core/listener.h"
+#include "../core/listener_vft.h"
+#include "../core/connection.h"
+#include "../core/connection_vft.h"
+#include "../core/connection_table.h"
+#include "../core/forwarder.h"
+#include "../core/mapme.h"
+#include "../socket/api.h"
+
+#ifdef __linux__
+#include "../socket/error.h"
+
+#define IPv6 6
+#define IPv4 4
+#define MTU_SIZE 1500 // bytes
+#define MAX_HICN_RETRY 5
+#define DEFAULT_PORT 1234
+
+// XXX #if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) &&
+// defined(PUNTING)
+
+// XXX the socket helper should be moved here as we can have a single hicn
+// listener
+
+#if 0
+static
+const
+address_pair_t *
+_createRecvAddressPairFromPacket(const uint8_t *msgBuffer) {
+ address_t * packetSrcAddr = NULL; /* This one is in the packet */
+ address_t * localAddr = NULL; /* This one is to be determined */
+
+ if (messageHandler_GetIPPacketType(msgBuffer) == IPv6_TYPE) {
+ struct sockaddr_in6 addr_in6;
+ addr_in6.sin6_family = AF_INET6;
+ addr_in6.sin6_port = htons(DEFAULT_PORT);
+ addr_in6.sin6_flowinfo = 0;
+ addr_in6.sin6_scope_id = 0;
+ memcpy(&addr_in6.sin6_addr,
+ (struct in6_addr *)messageHandler_GetSource(msgBuffer), 16);
+ packetSrcAddr = addressCreateFromInet6(&addr_in6);
+
+ /* We now determine the local address used to reach the packet src address */
+#ifndef _WIN32
+ int sock = socket (AF_INET6, SOCK_DGRAM, 0);
+#else
+ int sock = (int)socket (AF_INET6, SOCK_DGRAM, 0);
+#endif /* _WIN32 */
+ if (sock < 0)
+ goto ERR;
+
+ struct sockaddr_in6 remote, local;
+ memset(&remote, 0, sizeof(remote));
+ remote.sin6_family = AF_INET6;
+ remote.sin6_addr = addr_in6.sin6_addr;
+ remote.sin6_port = htons(DEFAULT_PORT);
+
+ socklen_t locallen = sizeof(local);
+ if (connect(sock, (const struct sockaddr*)&remote, sizeof(remote)) == -1)
+ goto ERR;
+ if (getsockname(sock, (struct sockaddr*) &local, &locallen) == -1)
+ goto ERR;
+
+ local.sin6_port = htons(DEFAULT_PORT);
+ localAddr = addressCreateFromInet6(&local);
+
+ close(sock);
+
+ } else if (messageHandler_GetIPPacketType(msgBuffer) == IPv4_TYPE) {
+ struct sockaddr_in addr_in;
+ addr_in.sin_family = AF_INET;
+ addr_in.sin_port = htons(DEFAULT_PORT);
+ memcpy(&addr_in.sin_addr,
+ (struct in_addr *)messageHandler_GetSource(msgBuffer), 4);
+ packetSrcAddr = addressCreateFromInet(&addr_in);
+
+ /* We now determine the local address used to reach the packet src address */
+
+#ifndef _WIN32
+ int sock = socket (AF_INET, SOCK_DGRAM, 0);
+#else
+ int sock = (int)socket (AF_INET, SOCK_DGRAM, 0);
+#endif /* _WIN32 */
+ if (sock < 0) {
+ perror("Socket error");
+ goto ERR;
+ }
+
+ struct sockaddr_in remote, local;
+ memset(&remote, 0, sizeof(remote));
+ remote.sin_family = AF_INET;
+ remote.sin_addr = addr_in.sin_addr;
+ remote.sin_port = htons(DEFAULT_PORT);
+
+ socklen_t locallen = sizeof(local);
+ if (connect(sock, (const struct sockaddr*)&remote, sizeof(remote)) == -1)
+ goto ERR;
+ if (getsockname(sock, (struct sockaddr*) &local, &locallen) == -1)
+ goto ERR;
+
+ local.sin_port = htons(DEFAULT_PORT);
+ localAddr = addressCreateFromInet(&local);
+
+ close(sock);
+ }
+ /* As this is a receive pair, we swap src and dst */
+ return addressPair_Create(localAddr, packetSrcAddr);
+
+ERR:
+ perror("Socket error");
+ return NULL;
+}
+
+static
+bool _isEmptyAddressIPv6(address_t * address) {
+ struct sockaddr_in6 *addr6 =
+ parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6));
+ parcAssertNotNull(addr6, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(addr6));
+
+ addressGetInet6(address, addr6);
+
+ bool res = true;
+ for (int i = 0; i < 16; ++i) {
+ if (addr6->sin6_addr.s6_addr[i] != 0) {
+ res = false;
+ }
+ }
+
+ parcMemory_Deallocate((void **)&addr6);
+
+ return res;
+}
+
+}
+
+static
+const Connection *
+_lookupConnection(ListenerOps * listener, const address_pair_t *pair)
+{
+ HicnListener * hicn = (HicnListener*)listener->context;
+ const connection_table_t * table = forwarder_GetConnectionTable(hicn->forwarder);
+ const address_t * packetSourceAddress = address_pair_local(pair);
+
+ if (hicn->connection_id != -1)
+ return connection_table_get_by_id(table, hicn->connection_id);
+
+ if (!packetSourceAddress)
+ return NULL;
+
+ // in this first check we try to retrieve the standard connection
+ // generated by the hicn-light
+ const address_pair_t new_pair = {
+ .local = hicn->localAddress,
+ .remote = *packetSourceAddress,
+ };
+ return *connection_table_lookup(table, &new_pair);
+}
+
+
+// XXX TODO : rely on libhicn
+int
+_createAddressFromPacket(const uint8_t *packet, address_t * address)
+{
+ if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) {
+ struct sockaddr_in6 * sin6 = address6(address);
+ *sin6 = (struct sockaddr_in6) {
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(DEFAULT_PORT),
+ .sin6_flowinfo = 0,
+ .sin6_scope_id = 0,
+ };
+ memcpy(&sin6->sin6_addr,
+ (struct in6_addr *)messageHandler_GetSource(packet), 16);
+ return 0;
+ } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) {
+ struct sockaddr_in * sin = address4(address);
+ *sin = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_port = htons(DEFAULT_PORT),
+ };
+ memcpy(&sin->sin_addr,
+ (struct in_addr *)messageHandler_GetSource(packet), 4);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+#endif
+
+/******************************************************************************
+ * Listener
+ ******************************************************************************/
+
+typedef struct {
+ // address_t localAddress; // this is the local address or 0::0 in case of
+ // the
+ // main listener this is the address used inside
+ // forwarder to identify the listener. Notice that this
+ // address is the same as the fisical interfaces on
+ // which we create the TUN. it is NOT the TUN address
+ // which is given by libhicn after the bind operation
+ // However the user alway uses this address since is
+ // the only one available at configuration time
+
+ // XXX why do we need the id of the associated connection ?
+ int connection_id; // this is used only if the listener is used to receive
+ // data packets we assume that 1 connection is associated
+ // to one listener in this case so we set the
+ // connection_id we the connection is create. if this id
+ // is not set and a data packet is received, the packet is
+ // dropped
+
+ hicn_socket_t *hicn_socket;
+ hicn_socket_helper_t *hicn_socket_helper;
+
+} listener_hicn_data_t;
+
+#define listener_hicn_read_callback listener_read_callback
+
+bool listener_hicn_bind(listener_t *listener, const address_t *address) {
+ assert(listener);
+ assert(address);
+
+ listener_hicn_data_t *data = listener->data;
+ assert(data);
+
+ char *address_str = malloc(/* max */ INET6_ADDRSTRLEN);
+ inet_ntop(address_family(address), address, address_str,
+ /* max */ INET6_ADDRSTRLEN);
+ int rc = hicn_bind(data->hicn_socket_helper, listener->fd, address_str);
+ if (rc < 0) {
+ ERROR("hicn_bind failed %d %s", rc, hicn_socket_strerror(rc));
+ free(address_str);
+ return false;
+ }
+
+ free(address_str);
+ return true;
+}
+
+static int listener_hicn_initialize(listener_t *listener) {
+ assert(listener);
+
+ listener_hicn_data_t *data = listener->data;
+ assert(data);
+
+ /* This is the id of the connection associated to this listener (unique in
+ * the case of hICN */
+ data->connection_id = -1;
+
+ data->hicn_socket_helper = hicn_create();
+ if (!data->hicn_socket) goto ERR_HELPER;
+
+ if (address_empty(&listener->address)) {
+ listener->fd = hicn_socket(data->hicn_socket_helper, listener->name, NULL);
+ } else {
+ char *local_addr = malloc(/* max */ INET6_ADDRSTRLEN);
+ inet_ntop(address_family(&listener->address), &listener->address,
+ local_addr, /* max */ INET6_ADDRSTRLEN);
+ listener->fd =
+ hicn_socket(data->hicn_socket_helper, listener->name, local_addr);
+ free(local_addr);
+ }
+
+ if (listener->fd < 0) {
+ ERROR("HicnListener %s: error creating hICN listener", listener->name);
+ goto ERR_FD;
+ }
+
+ // Set non-blocking flag
+ int flags = fcntl(listener->fd, F_GETFL, NULL);
+ if (flags != -1) {
+ ERROR("fcntl failed to obtain file descriptor flags (%d)", errno);
+ goto ERR_FLAGS;
+ }
+
+ if (fcntl(listener->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ ERROR("fcntl failed to set file descriptor flags (%d)", errno);
+ goto ERR_FLAGS;
+ }
+
+ return 0;
+
+ERR_FLAGS:
+ close(listener->fd);
+ERR_FD:
+ hicn_free(data->hicn_socket_helper);
+ERR_HELPER:
+ return -1;
+}
+
+static void listener_hicn_finalize(listener_t *listener) {
+ assert(listener);
+ assert(listener_get_type(listener) == FACE_TYPE_HICN);
+
+ listener_hicn_data_t *data = listener->data;
+ assert(data);
+
+ // TODO destroy hicn_socket
+ // TODO free(data) (like in other classes)
+
+ hicn_free(data->hicn_socket_helper);
+ // XXX
+ // hicn_socket_free(data->hicn_socket);
+
+ return;
+}
+
+static int listener_hicn_punt(const listener_t *listener,
+ const char *prefix_s) {
+ assert(listener);
+ assert(listener_get_type(listener) == FACE_TYPE_HICN);
+ assert(prefix_s);
+
+ listener_hicn_data_t *data = listener->data;
+ assert(data);
+
+ int rc;
+ for (int retry = 0; retry < MAX_HICN_RETRY; retry++) {
+ if ((rc = hicn_listen(data->hicn_socket_helper, listener->fd, prefix_s)) >=
+ 0)
+ return 0;
+ sleep(1);
+ }
+ ERROR("hicn_listen failed %d %s", rc, hicn_socket_strerror(rc));
+ return -1;
+}
+
+static int listener_hicn_get_socket(const listener_t *listener,
+ const address_t *local,
+ const address_t *remote,
+ const char *interface_name) {
+ assert(listener);
+ assert(listener_get_type(listener) == FACE_TYPE_HICN);
+ assert(local);
+ assert(remote);
+
+ /* ... */
+
+ return -1;
+}
+
+#define listener_hicn_read_single io_read_single_fd
+#define listener_hicn_read_batch NULL
+
+DECLARE_LISTENER(hicn);
+
+/******************************************************************************
+ * Connection
+ ******************************************************************************/
+
+typedef struct {
+ /* ... */
+} connection_hicn_data_t;
+
+static int connection_hicn_initialize(connection_t *connection) {
+ assert(connection);
+ assert(connection_get_type(connection) == FACE_TYPE_HICN);
+
+ /* ... */
+
+ return 0;
+}
+
+static void connection_hicn_finalize(connection_t *connection) {
+ /* ... */
+
+ return;
+}
+
+static bool connection_hicn_flush(const connection_t *connection) {
+ return false;
+}
+
+static bool connection_hicn_send(const connection_t *connection,
+ msgbuf_t *msgbuf, bool queue) {
+ assert(connection);
+ /* msgbuf can be NULL */
+
+ // connection_hicn_data_t * data = connection->data;
+ // assert(data);
+
+ /* ... */
+
+ return false;
+}
+
+// static
+// int
+// connection_hicn_sendv(const connection_t * connection, struct iovec * iov,
+// size_t size)
+//{
+//
+// assert(connetion);
+// assert(iov);
+//
+//// connection_hicn_data_t * data = connection->data;
+//// assert(data);
+//
+// /* ... */
+//
+// return 0;
+//}
+//
+static int connection_hicn_send_packet(const connection_t *connection,
+ const uint8_t *packet, size_t size) {
+ assert(connection);
+ assert(packet);
+
+ /* ... */
+
+ return 0;
+}
+
+DECLARE_CONNECTION(hicn);
+
+#endif
diff --git a/hicn-light/src/hicn/io/hicnConnection.c b/hicn-light/src/hicn/io/hicnConnection.c
deleted file mode 100644
index 646cea990..000000000
--- a/hicn-light/src/hicn/io/hicnConnection.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Embodies the reader/writer for a Hicn connection
- *
- * NB The Send() function may overflow the output buffer
- *
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include <hicn/core/message.h>
-#include <hicn/io/hicnConnection.h>
-
-#include <hicn/core/messageHandler.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/forwarder.h>
-
-typedef struct hicn_state {
- Forwarder *forwarder;
- char * interfaceName;
- Logger *logger;
-
- // the hicn listener socket we receive packets on
- int hicnListenerSocket;
-
- AddressPair *addressPair;
-
- // We need to access this all the time, so grab it out
- // of the addressPair;
- struct sockaddr *peerAddress;
- socklen_t peerAddressLength;
-
- struct sockaddr *localAddress;
- socklen_t localAddressLength;
-
- bool isLocal;
- bool isUp;
- unsigned id;
-
- unsigned delay;
-
- /* This information would better be stored in the connection data structure
- * but it is currently not reachable from within the implementation. */
- connection_state_t state;
- connection_state_t admin_state;
-#ifdef WITH_POLICY
- uint32_t priority;
-#endif /* WITH_POLICY */
-} _HicnState;
-
-// Prototypes
-static bool _send(IoOperations *ops, const Address *nexthop, Message *message);
-static bool _sendIOVBuffer(IoOperations *ops, struct iovec *message,
- size_t size);
-static const Address *_getRemoteAddress(const IoOperations *ops);
-static const AddressPair *_getAddressPair(const IoOperations *ops);
-static unsigned _getConnectionId(const IoOperations *ops);
-static bool _isUp(const IoOperations *ops);
-static bool _isLocal(const IoOperations *ops);
-static void _destroy(IoOperations **opsPtr);
-static list_connections_type _getConnectionType(const IoOperations *ops);
-static void _sendProbe(IoOperations *ops, uint8_t *message);
-static connection_state_t _getState(const IoOperations *ops);
-static void _setState(IoOperations *ops, connection_state_t state);
-static connection_state_t _getAdminState(const IoOperations *ops);
-static void _setAdminState(IoOperations *ops, connection_state_t admin_state);
-#ifdef WITH_POLICY
-static uint32_t _getPriority(const IoOperations *ops);
-static void _setPriority(IoOperations *ops, uint32_t priority);
-#endif /* WITH_POLICY */
-static const char * _getInterfaceName(const IoOperations *ops);
-
-/*
- * This assigns a unique pointer to the void * which we use
- * as a GUID for this class.
- */
-static const void *_ioOperationsGuid = __FILE__;
-
-/*
- * Return our GUID
- */
-static const void *_streamConnection_Class(const IoOperations *ops) {
- return _ioOperationsGuid;
-}
-
-static IoOperations _template = {
- .closure = NULL,
- .send = &_send,
- .sendIOVBuffer = &_sendIOVBuffer,
- .getRemoteAddress = &_getRemoteAddress,
- .getAddressPair = &_getAddressPair,
- .getConnectionId = &_getConnectionId,
- .isUp = &_isUp,
- .isLocal = &_isLocal,
- .destroy = &_destroy,
- .class = &_streamConnection_Class,
- .getConnectionType = &_getConnectionType,
- .sendProbe = &_sendProbe,
- .getState = &_getState,
- .setState = &_setState,
- .getAdminState = &_getAdminState,
- .setAdminState = &_setAdminState,
-#ifdef WITH_POLICY
- .getPriority = &_getPriority,
- .setPriority = &_setPriority,
-#endif /* WITH_POLICY */
- .getInterfaceName = &_getInterfaceName,
-};
-
-// =================================================================
-
-static void _setConnectionState(_HicnState *Hicn, bool isUp);
-static bool _saveSockaddr(_HicnState *hicnConnState, const AddressPair *pair);
-
-IoOperations *hicnConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
- const AddressPair *pair, bool isLocal) {
- IoOperations *io_ops = NULL;
-
- _HicnState *hicnConnState = parcMemory_AllocateAndClear(sizeof(_HicnState));
- parcAssertNotNull(hicnConnState,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(_HicnState));
-
- hicnConnState->forwarder = forwarder;
- hicnConnState->interfaceName = strdup(interfaceName);
- hicnConnState->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- bool saved = _saveSockaddr(hicnConnState, pair);
- if (saved) {
- hicnConnState->hicnListenerSocket = fd;
- hicnConnState->id = forwarder_GetNextConnectionId(forwarder);
- hicnConnState->addressPair = addressPair_Acquire(pair);
- hicnConnState->isLocal = isLocal;
-
- // allocate a connection
- io_ops = parcMemory_AllocateAndClear(sizeof(IoOperations));
- parcAssertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(IoOperations));
- memcpy(io_ops, &_template, sizeof(IoOperations));
- io_ops->closure = hicnConnState;
-
- _setConnectionState(hicnConnState, true);
-
-#ifdef WITH_POLICY
- hicnConnState->priority = 0;
-#endif /* WITH_POLICY */
-
- if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Info)) {
- char *str = addressPair_ToString(hicnConnState->addressPair);
- logger_Log(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Info,
- __func__,
- "HicnConnection %p created for address %s (isLocal %d)",
- (void *)hicnConnState, str, hicnConnState->isLocal);
- free(str);
- }
-
- messenger_Send(
- forwarder_GetMessenger(forwarder),
- missive_Create(MissiveType_ConnectionCreate, hicnConnState->id));
- messenger_Send(forwarder_GetMessenger(forwarder),
- missive_Create(MissiveType_ConnectionUp, hicnConnState->id));
- } else {
- // _saveSockaddr will already log an error, no need for extra log message
- // here
- logger_Release(&hicnConnState->logger);
- free(hicnConnState->interfaceName);
- parcMemory_Deallocate((void **)&hicnConnState);
- }
-
- return io_ops;
-}
-
-// =================================================================
-// I/O Operations implementation
-
-static void _destroy(IoOperations **opsPtr) {
- parcAssertNotNull(opsPtr, "Parameter opsPtr must be non-null double pointer");
- parcAssertNotNull(*opsPtr,
- "Parameter opsPtr must dereference to non-null pointer");
-
- IoOperations *ops = *opsPtr;
- parcAssertNotNull(ioOperations_GetClosure(ops),
- "ops->context must not be null");
-
- _HicnState *hicnConnState = (_HicnState *)ioOperations_GetClosure(ops);
- addressPair_Release(&hicnConnState->addressPair);
- parcMemory_Deallocate((void **)&(hicnConnState->peerAddress));
- parcMemory_Deallocate((void **)&(hicnConnState->localAddress));
-
- messenger_Send(
- forwarder_GetMessenger(hicnConnState->forwarder),
- missive_Create(MissiveType_ConnectionDestroyed, hicnConnState->id));
-
- if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Info)) {
- logger_Log(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Info,
- __func__, "HicnConnection %p destroyed", (void *)hicnConnState);
- }
-
- // do not close hicListenerSocket, the listener will close
- // that when its done
- // should I say something to libhicn?
-
- logger_Release(&hicnConnState->logger);
- free(hicnConnState->interfaceName);
- parcMemory_Deallocate((void **)&hicnConnState);
- parcMemory_Deallocate((void **)&ops);
-
- *opsPtr = NULL;
-}
-
-static bool _isUp(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->isUp;
-}
-
-static bool _isLocal(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->isLocal;
-}
-
-static const Address *_getRemoteAddress(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return addressPair_GetRemote(hicnConnState->addressPair);
-}
-
-static const AddressPair *_getAddressPair(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->addressPair;
-}
-
-static unsigned _getConnectionId(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->id;
-}
-
-/**
- * @function hicnConnection_Send
- * @abstract Non-destructive send of the message.
- * @discussion
- * sends a message to the peer.
- *
- * @param dummy is ignored. .
- */
-static bool _send(IoOperations *ops, const Address *dummy, Message *message) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- _HicnState *hicnConnState = (_HicnState *)ioOperations_GetClosure(ops);
-
- // NAT for HICN
- if (message_GetType(message) == MessagePacketType_ContentObject) {
- // this is a data packet. We need to put the remote address in the
- // destination field
-
- if (messageHandler_GetIPPacketType(message_FixedHeader(message)) ==
- IPv6_TYPE) {
- messageHandler_SetDestination_IPv6(
- (uint8_t *)message_FixedHeader(message),
- &((struct sockaddr_in6 *)hicnConnState->peerAddress)->sin6_addr);
- } else {
- messageHandler_SetDestination_IPv4(
- (uint8_t *)message_FixedHeader(message),
- &(((struct sockaddr_in *)hicnConnState->peerAddress)
- ->sin_addr.s_addr));
- }
- } else if (message_GetType(message) == MessagePacketType_Interest) {
- // this si an interest packet. We need to put the local address in the
- // source field
- if (messageHandler_GetIPPacketType(message_FixedHeader(message)) ==
- IPv6_TYPE) {
- messageHandler_SetSource_IPv6(
- (uint8_t *)message_FixedHeader(message),
- &((struct sockaddr_in6 *)hicnConnState->localAddress)->sin6_addr);
- } else {
- messageHandler_SetSource_IPv4(
- (uint8_t *)message_FixedHeader(message),
- &(((struct sockaddr_in *)hicnConnState->localAddress)
- ->sin_addr.s_addr));
- }
- } else if (message_GetType(message) == MessagePacketType_WldrNotification) {
- // here we don't need to do anything for now
- } else {
- // unkown packet
- if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Debug,
- __func__, "connid %u can't parse the message",
- hicnConnState->id);
- }
- return false;
- }
-
- ssize_t writeLength =
- write(hicnConnState->hicnListenerSocket, message_FixedHeader(message),
- message_Length(message));
-
- if (writeLength < 0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- return false;
- } else {
- // this print is for debugging
- printf("Incorrect write length %zd, expected %zd: (%d) %s\n", writeLength,
- message_Length(message), errno, strerror(errno));
- return false;
- }
- }
-
- return true;
-}
-
-static bool _sendIOVBuffer(IoOperations *ops, struct iovec *message,
- size_t size) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
-
- _HicnState *hicnConnState = (_HicnState *)ioOperations_GetClosure(ops);
-
-
- ssize_t n = writev(hicnConnState->hicnListenerSocket, message, size);
- if (n < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- size_t length = 0;
- for (int i = 0; i < size; i++)
- length += message[i].iov_len;
- logger_Log(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Error,
- __func__, "Incorrect write length %zd, expected %zd: (%d) %s\n",
- n, length, errno, strerror(errno));
- }
- }
- return false;
- }
- return true;
-}
-
-static list_connections_type _getConnectionType(const IoOperations *ops) {
- return CONN_HICN;
-}
-
-static void _sendProbe(IoOperations *ops, uint8_t *message) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
-
- _HicnState *hicnConnState = (_HicnState *)ioOperations_GetClosure(ops);
-
- if(messageHandler_IsInterest(message)){//
- // this is an interest packet. We need to put the local address in the
- // source field
- if (messageHandler_GetIPPacketType(message) == IPv6_TYPE) {
- messageHandler_SetSource_IPv6(message,
- &((struct sockaddr_in6 *)hicnConnState->localAddress)->sin6_addr);
- } else {
- messageHandler_SetSource_IPv4(message,
- &(((struct sockaddr_in *)hicnConnState->localAddress)
- ->sin_addr.s_addr));
- }
- }//if is a data packet the packet is already set (see
- //messageHandler_CreateProbeReply)
-
- ssize_t writeLength = write(hicnConnState->hicnListenerSocket, message,
- messageHandler_GetTotalPacketLength(message));
-
- if (writeLength < 0) {
- return;
- }
-}
-
-// =================================================================
-// Internal API
-
-static bool _saveSockaddr(_HicnState *hicnConnState, const AddressPair *pair) {
- bool success = false;
- const Address *remoteAddress = addressPair_GetRemote(pair);
- const Address *localAddress = addressPair_GetLocal(pair);
- switch (addressGetType(remoteAddress)) { // local must be of the same type
-
- case ADDR_INET: {
- size_t bytes = sizeof(struct sockaddr_in);
- hicnConnState->peerAddress = parcMemory_Allocate(bytes);
- parcAssertNotNull(hicnConnState->peerAddress,
- "parcMemory_Allocate(%zu) returned NULL", bytes);
-
- addressGetInet(remoteAddress,
- (struct sockaddr_in *)hicnConnState->peerAddress);
- hicnConnState->peerAddressLength = (socklen_t)bytes;
-
- hicnConnState->localAddress = parcMemory_Allocate(bytes);
- parcAssertNotNull(hicnConnState->localAddress,
- "parcMemory_Allocate(%zu) returned NULL", bytes);
-
- addressGetInet(localAddress,
- (struct sockaddr_in *)hicnConnState->localAddress);
- hicnConnState->localAddressLength = (socklen_t)bytes;
- success = true;
- break;
- }
-
- case ADDR_INET6: {
- size_t bytes = sizeof(struct sockaddr_in6);
- hicnConnState->peerAddress = parcMemory_Allocate(bytes);
- parcAssertNotNull(hicnConnState->peerAddress,
- "parcMemory_Allocate(%zu) returned NULL", bytes);
-
- addressGetInet6(remoteAddress,
- (struct sockaddr_in6 *)hicnConnState->peerAddress);
- hicnConnState->peerAddressLength = (socklen_t)bytes;
-
- hicnConnState->localAddress = parcMemory_Allocate(bytes);
- parcAssertNotNull(hicnConnState->localAddress,
- "parcMemory_Allocate(%zu) returned NULL", bytes);
-
- addressGetInet6(localAddress,
- (struct sockaddr_in6 *)hicnConnState->localAddress);
- hicnConnState->localAddressLength = (socklen_t)bytes;
- success = true;
- break;
- }
-
- default:
- if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- char *str = addressToString(remoteAddress);
- logger_Log(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Error,
- __func__, "Remote address is not INET or INET6: %s", str);
- parcMemory_Deallocate((void **)&str);
- }
- break;
- }
- return success;
-}
-
-static void _setConnectionState(_HicnState *hicnConnState, bool isUp) {
- parcAssertNotNull(hicnConnState, "Parameter HICN must be non-null");
-
- Messenger *messenger = forwarder_GetMessenger(hicnConnState->forwarder);
-
- bool oldStateIsUp = hicnConnState->isUp;
- hicnConnState->isUp = isUp;
-
- if (oldStateIsUp && !isUp) {
- // bring connection DOWN
- Missive *missive =
- missive_Create(MissiveType_ConnectionDown, hicnConnState->id);
- messenger_Send(messenger, missive);
- return;
- }
-
- if (!oldStateIsUp && isUp) {
- // bring connection UP
- Missive *missive =
- missive_Create(MissiveType_ConnectionUp, hicnConnState->id);
- messenger_Send(messenger, missive);
- return;
- }
-}
-
-static connection_state_t _getState(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->state;
-}
-
-static void _setState(IoOperations *ops, connection_state_t state) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _HicnState *hicnConnState =
- (_HicnState *)ioOperations_GetClosure(ops);
- hicnConnState->state = state;
-}
-
-static connection_state_t _getAdminState(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->admin_state;
-}
-
-static void _setAdminState(IoOperations *ops, connection_state_t admin_state) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _HicnState *hicnConnState =
- (_HicnState *)ioOperations_GetClosure(ops);
- hicnConnState->admin_state = admin_state;
-}
-
-#ifdef WITH_POLICY
-static uint32_t _getPriority(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _HicnState *hicnConnState =
- (const _HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->priority;
-}
-
-static void _setPriority(IoOperations *ops, uint32_t priority) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _HicnState *hicnConnState =
- (_HicnState *)ioOperations_GetClosure(ops);
- hicnConnState->priority = priority;
-}
-#endif /* WITH_POLICY
-*/
-static const char * _getInterfaceName(const IoOperations *ops)
-{
- parcAssertNotNull(ops, "Parameter must be non-null");
- _HicnState *hicnConnState =
- (_HicnState *)ioOperations_GetClosure(ops);
- return hicnConnState->interfaceName;
-}
diff --git a/hicn-light/src/hicn/io/hicnConnection.h b/hicn-light/src/hicn/io/hicnConnection.h
deleted file mode 100644
index fec18e1bd..000000000
--- a/hicn-light/src/hicn/io/hicnConnection.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file hicnConnection.h
- * @brief Represents a Hicn connection for the connection table
- *
- * <#Detailed Description#>
- *
- */
-
-#ifndef hicnConnection_h
-#define hicnConnection_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/utils/address.h>
-
-/**
- * Creates a Hicn connection that can send to the remote address
- *
- * The address pair must both be same type (i.e. INET or INET6).
- *
- * @param [in] an allocated hicn-light Forwarder (saves reference)
- * @param [in] fd The socket to use
- * @param [in] pair An allocated address pair for the connection (saves
- * reference)
- * @param [in] isLocal determines if the remote address is on the current system
- *
- * @retval non-null An allocated Io operations
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-IoOperations *hicnConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
- const AddressPair *pair, bool isLocal);
-#endif // hicnConnection_h
diff --git a/hicn-light/src/hicn/io/hicnListener.c b/hicn-light/src/hicn/io/hicnListener.c
deleted file mode 100644
index 8647a4d54..000000000
--- a/hicn-light/src/hicn/io/hicnListener.c
+++ /dev/null
@@ -1,673 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <unistd.h>
-
-#include <hicn/io/hicnConnection.h>
-#include <hicn/io/hicnListener.h>
-
-#include <hicn/core/connection.h>
-#include <hicn/core/connectionTable.h>
-#include <hicn/core/forwarder.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/mapme.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/io/listener.h>
-#include <hicn/socket/api.h>
-
-#define IPv6 6
-#define IPv4 4
-#define MTU_SIZE 1500 // bytes
-#define MAX_HICN_RETRY 5
-
-struct hicn_listener {
-
- char *listenerName;
-
- Forwarder *forwarder;
- Logger *logger;
-
- PARCEvent *hicn_event;
- int hicn_fd; // this is the file descriptor got from hicn library
-
- Address
- *localAddress; // this is the local address or 0::0 in case of the
- // main listener this is the address used inside
- // forwarder to identify the listener. Notice that this
- // address is the same as the fisical interfaces on
- // which we create the TUN. it is NOT the TUN address
- // which is given by libhicn after the bind operation
- // However the user alway uses this address since is
- // the only one available at configuration time
-
- unsigned inetFamily;
-
- int connection_id; // this is used only if the listener is used to receive
- // data packets we assume that 1 connection is associated
- // to one listener in this case so we set the
- // connection_id we the connection is create. if this id
- // is not set and a data packet is received, the packet is
- // dropped
-
- unsigned conn_id;
-};
-
-static void _destroy(ListenerOps **listenerOpsPtr);
-static const char *_getListenerName(const ListenerOps *ops);
-static const char *_getInterfaceName(const ListenerOps *ops);
-static unsigned _getInterfaceIndex(const ListenerOps *ops);
-static const Address *_getListenAddress(const ListenerOps *ops);
-static EncapType _getEncapType(const ListenerOps *ops);
-static int _getSocket(const ListenerOps *ops);
-static unsigned _createNewConnection(ListenerOps *listener, int fd, const AddressPair *pair);
-static const Connection * _lookupConnection(ListenerOps * listener, const AddressPair *pair);
-static Message *_readMessage(ListenerOps * listener, int fd, uint8_t *msgBuffer);
-static void _hicnListener_readcb(int fd, PARCEventType what, void *listener_void);
-static Address *_createAddressFromPacket(uint8_t *msgBuffer);
-static void _handleWldrNotification(ListenerOps *listener, uint8_t *msgBuffer);
-static void _readFrameToDiscard(HicnListener *hicn, int fd);
-
-static ListenerOps _hicnTemplate = {
- .context = NULL,
- .destroy = &_destroy,
- .getInterfaceIndex = &_getInterfaceIndex,
- .getListenAddress = &_getListenAddress,
- .getEncapType = &_getEncapType,
- .getSocket = &_getSocket,
- .getInterfaceName = &_getInterfaceName,
- .getListenerName = &_getListenerName,
- .createConnection = &_createNewConnection,
- .lookupConnection = &_lookupConnection,
-};
-
-static bool _isEmptyAddressIPv6(Address *address) {
- struct sockaddr_in6 *addr6 =
- parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6));
- parcAssertNotNull(addr6, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(addr6));
-
- addressGetInet6(address, addr6);
-
- bool res = true;
- for (int i = 0; i < 16; ++i) {
- if (addr6->sin6_addr.s6_addr[i] != 0) {
- res = false;
- }
- }
-
- parcMemory_Deallocate((void **)&addr6);
-
- return res;
-}
-
-static Message *_readMessage(ListenerOps * listener, int fd, uint8_t *msgBuffer) {
- HicnListener * hicn = (HicnListener*)listener->context;
- Message *message = NULL;
-
- ssize_t readLength = read(fd, msgBuffer, MTU_SIZE);
-
- if (readLength < 0) {
- printf("read failed %d: (%d) %s\n", fd, errno, strerror(errno));
- return message;
- }
-
- size_t packetLength = messageHandler_GetTotalPacketLength(msgBuffer);
-
- if (readLength != packetLength) {
- parcMemory_Deallocate((void **)&msgBuffer);
- return message;
- }
-
- if (messageHandler_IsTCP(msgBuffer)) {
- MessagePacketType pktType;
- unsigned connid = 0;
- if (messageHandler_IsData(msgBuffer)) {
- pktType = MessagePacketType_ContentObject;
- if (hicn->connection_id == -1) {
- parcMemory_Deallocate((void **)&msgBuffer);
- return message;
- } else {
- connid = hicn->connection_id;
- }
- } else if (messageHandler_IsInterest(msgBuffer)) {
- // notice that the connections for the interest (the one that we create at
- // run time) uses as a local address 0::0, so the main tun
- pktType = MessagePacketType_Interest;
- Address *packetAddr = _createAddressFromPacket(msgBuffer);
-
- AddressPair *pair_find = addressPair_Create(packetAddr, /* dummy */ hicn->localAddress);
- const Connection *conn = _lookupConnection(listener, pair_find);
- addressPair_Release(&pair_find);
- if (conn == NULL) {
- AddressPair *pair = addressPair_Create(hicn->localAddress, packetAddr);
- connid = _createNewConnection(listener, fd, pair);
- addressPair_Release(&pair);
- } else {
- connid = connection_GetConnectionId(conn);
- }
- addressDestroy(&packetAddr);
- } else {
- printf("Got a packet that is not a data nor an interest, drop it!\n");
- parcMemory_Deallocate((void **)&msgBuffer);
- return message;
- }
-
- message = message_CreateFromByteArray(connid, msgBuffer, pktType,
- forwarder_GetTicks(hicn->forwarder),
- forwarder_GetLogger(hicn->forwarder));
- if (message == NULL) {
- parcMemory_Deallocate((void **)&msgBuffer);
- }
- } else if (messageHandler_IsWldrNotification(msgBuffer)) {
- _handleWldrNotification(listener, msgBuffer);
- } else {
- messageHandler_handleHooks(hicn->forwarder, msgBuffer, listener, fd, NULL);
- parcMemory_Deallocate((void **)&msgBuffer);
- }
-
- return message;
-}
-
-static void _receivePacket(ListenerOps * listener, int fd) {
- HicnListener * hicn = (HicnListener*)listener->context;
- Message *msg = NULL;
- uint8_t *msgBuffer = parcMemory_AllocateAndClear(MTU_SIZE);
- msg = _readMessage(listener, fd, msgBuffer);
-
- if (msg) {
- forwarder_Receive(hicn->forwarder, msg);
- }
-}
-
-static void _hicnListener_readcb(int fd, PARCEventType what, void *listener_void) {
- ListenerOps * listener = (ListenerOps *)listener_void;
- HicnListener *hicn = (HicnListener *)listener->context;
-
- if (hicn->inetFamily == IPv4 || hicn->inetFamily == IPv6) {
- if (what & PARCEventType_Read) {
- _receivePacket(listener, fd);
- }
- } else {
- _readFrameToDiscard(hicn, fd);
- }
-}
-
-static bool _isEmptyAddressIPv4(Address *address) {
- bool res = false;
-
- char * str = addressToString(address);
- if (strcmp("inet4://0.0.0.0:1234", str) == 0) res = true;
- parcMemory_Deallocate((void**)&str);
-
- return res;
-}
-
-ListenerOps *hicnListener_CreateInet(Forwarder *forwarder, char *symbolic,
- Address *address) {
- HicnListener *hicn = parcMemory_AllocateAndClear(sizeof(HicnListener));
- parcAssertNotNull(hicn, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(HicnListener));
-
- hicn->forwarder = forwarder;
- hicn->listenerName = parcMemory_StringDuplicate(symbolic, strlen(symbolic));
- hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- hicn->conn_id = forwarder_GetNextConnectionId(forwarder);
- hicn->inetFamily = IPv4;
-
- hicn->connection_id = -1;
-
- hicn_socket_helper_t *hicnSocketHelper =
- forwarder_GetHicnSocketHelper(forwarder);
-
- if (_isEmptyAddressIPv4(address)) {
- hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, NULL);
- } else {
- struct sockaddr_in *tmpAddr =
- parcMemory_AllocateAndClear(sizeof(struct sockaddr_in));
- parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(tmpAddr));
- addressGetInet(address, tmpAddr);
- char *local_addr = parcMemory_AllocateAndClear(INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &(tmpAddr->sin_addr), local_addr, INET_ADDRSTRLEN);
- parcMemory_Deallocate((void **)&tmpAddr);
-
- hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, local_addr);
-
- parcMemory_Deallocate((void **)&local_addr);
- }
-
- if (hicn->hicn_fd < 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(
- hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "HicnListener %s: error while creating an hicn listener in lib_hicn",
- symbolic);
- }
- logger_Release(&hicn->logger);
- addressDestroy(&hicn->localAddress);
- parcMemory_Deallocate((void **)&hicn->listenerName);
- parcMemory_Deallocate((void **)&hicn);
- return NULL;
- }
-
- // Set non-blocking flag
- int flags = fcntl(hicn->hicn_fd, F_GETFL, NULL);
- parcAssertTrue(flags != -1,
- "fcntl failed to obtain file descriptor flags (%d)", errno);
- int failure = fcntl(hicn->hicn_fd, F_SETFL, flags | O_NONBLOCK);
- parcAssertFalse(failure, "fcntl failed to set file descriptor flags (%d)",
- errno);
-
- ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerOps));
-
- memcpy(ops, &_hicnTemplate, sizeof(ListenerOps));
- ops->context = hicn;
-
- hicn->hicn_event = dispatcher_CreateNetworkEvent(
- forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb,
- (void *)ops, hicn->hicn_fd);
- dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder),
- hicn->hicn_event);
-
-
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "HicnListener %s created", symbolic);
- }
-
- return ops;
- return NULL;
-}
-
-ListenerOps *hicnListener_CreateInet6(Forwarder *forwarder, char *symbolic,
- Address *address) {
- HicnListener *hicn = parcMemory_AllocateAndClear(sizeof(HicnListener));
- parcAssertNotNull(hicn, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(HicnListener));
-
- hicn->forwarder = forwarder;
- hicn->listenerName = parcMemory_StringDuplicate(symbolic, strlen(symbolic));
- hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- hicn->conn_id = forwarder_GetNextConnectionId(forwarder);
- hicn->localAddress = addressCopy(address);
-
- hicn->inetFamily = IPv6;
-
- hicn->connection_id = -1;
-
- // the call to libhicn is the same both for the main and the normal listeners
- // in both cases we need to set only the identifier. In the case of normal
- // listener (listener for data packet) we let the library select the right ip
- // address we just need to set the right type of packet
-
- hicn_socket_helper_t *hicnSocketHelper =
- forwarder_GetHicnSocketHelper(forwarder);
-
- if (_isEmptyAddressIPv6(address)) {
- // create main listener
- hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, NULL);
- } else {
- // create listener for the connetion
- struct sockaddr_in6 *tmpAddr =
- parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6));
-
- parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(tmpAddr));
- addressGetInet6(address, tmpAddr);
-
- char *local_addr = parcMemory_AllocateAndClear(INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6, &(tmpAddr->sin6_addr), local_addr, INET6_ADDRSTRLEN);
-
- parcMemory_Deallocate((void **)&tmpAddr);
-
- hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, local_addr);
-
- parcMemory_Deallocate((void **)&local_addr);
- }
-
- if (hicn->hicn_fd < 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(
- hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "HicnListener %s: error while creating an hicn listener in lib_hicn",
- symbolic);
- }
- logger_Release(&hicn->logger);
- addressDestroy(&hicn->localAddress);
- parcMemory_Deallocate((void **)&hicn->listenerName);
- parcMemory_Deallocate((void **)&hicn);
- return NULL;
- }
-
- // Set non-blocking flag
- int flags = fcntl(hicn->hicn_fd, F_GETFL, NULL);
- parcAssertTrue(flags != -1,
- "fcntl failed to obtain file descriptor flags (%d)", errno);
- int failure = fcntl(hicn->hicn_fd, F_SETFL, flags | O_NONBLOCK);
- parcAssertFalse(failure, "fcntl failed to set file descriptor flags (%d)",
- errno);
-
- ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerOps));
-
- memcpy(ops, &_hicnTemplate, sizeof(ListenerOps));
- ops->context = hicn;
-
- hicn->hicn_event = dispatcher_CreateNetworkEvent(
- forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb,
- (void *)ops, hicn->hicn_fd);
- dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder),
- hicn->hicn_event);
-
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "HicnListener %s created", symbolic);
- }
-
- return ops;
-}
-
-bool _hicnListener_BindInet6(ListenerOps *ops, const Address *remoteAddress) {
- HicnListener *hicn = (HicnListener *)ops->context;
- hicn_socket_helper_t *hicnSocketHelper =
- forwarder_GetHicnSocketHelper(hicn->forwarder);
-
- struct sockaddr_in6 *tmpAddr =
- parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6));
- parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(tmpAddr));
- addressGetInet6(remoteAddress, tmpAddr);
- char *remote_addr = parcMemory_AllocateAndClear(INET6_ADDRSTRLEN);
- inet_ntop(AF_INET6, &(tmpAddr->sin6_addr), remote_addr, INET6_ADDRSTRLEN);
- parcMemory_Deallocate((void **)&tmpAddr);
-
- int res = hicn_bind(hicnSocketHelper, hicn->hicn_fd, remote_addr);
-
- bool result = false;
- if (res < 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "hicn_bind failed %d %s", res, hicn_socket_strerror(res));
- }
- } else {
- result = true;
- }
-
- parcMemory_Deallocate((void **)&remote_addr);
-
- return result;
-}
-
-bool _hicnListener_BindInet(ListenerOps *ops, const Address *remoteAddress) {
- HicnListener *hicn = (HicnListener *)ops->context;
- hicn_socket_helper_t *hicnSocketHelper =
- forwarder_GetHicnSocketHelper(hicn->forwarder);
-
- struct sockaddr_in *tmpAddr =
- parcMemory_AllocateAndClear(sizeof(struct sockaddr_in));
- parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(tmpAddr));
- addressGetInet(remoteAddress, tmpAddr);
- char *remote_addr = parcMemory_AllocateAndClear(INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &(tmpAddr->sin_addr), remote_addr, INET_ADDRSTRLEN);
- parcMemory_Deallocate((void **)&tmpAddr);
-
- int res = hicn_bind(hicnSocketHelper, hicn->hicn_fd, remote_addr);
- bool result = false;
-
- if (res < 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "hicn_bind failed %d %s", res, hicn_socket_strerror(res));
- }
- } else {
- result = true;
- }
-
- parcMemory_Deallocate((void **)&remote_addr);
-
- return result;
-}
-
-bool hicnListener_Bind(ListenerOps *ops, const Address *remoteAddress) {
- if (addressGetType(remoteAddress) == ADDR_INET) {
- return _hicnListener_BindInet(ops, remoteAddress);
- } else if (addressGetType(remoteAddress) == ADDR_INET6) {
- return _hicnListener_BindInet6(ops, remoteAddress);
- } else {
- printf("Bind failed: Invalid address\n");
- return false;
- }
-}
-
-bool hicnListener_Punting(ListenerOps *ops, const char *prefix) {
- HicnListener *hicn = (HicnListener *)ops->context;
- hicn_socket_helper_t *hicnSocketHelper =
- forwarder_GetHicnSocketHelper(hicn->forwarder);
-
- int res = hicn_listen(hicnSocketHelper, hicn->hicn_fd, prefix);
- int retry = 0;
-
- while (res < 0 && retry < MAX_HICN_RETRY) {
- sleep(1);
- res = hicn_listen(hicnSocketHelper, hicn->hicn_fd, prefix);
- retry++;
- }
-
- if (res < 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "hicn_listen failed %d %s", res, hicn_socket_strerror(res));
- }
- return false;
- }
-
- return true;
-}
-
-bool hicnListener_SetConnectionId(ListenerOps *ops, unsigned connId) {
- HicnListener *hicn = (HicnListener *)ops->context;
- if (hicn) {
- hicn->connection_id = connId;
- return true;
- }
- return false;
-}
-
-static void _hicnListener_Destroy(HicnListener **listenerPtr) {
- parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listenerPtr,
- "Parameter must derefernce to non-null pointer");
-
- HicnListener *hicn = *listenerPtr;
-
- dispatcher_DestroyNetworkEvent(forwarder_GetDispatcher(hicn->forwarder),
- &hicn->hicn_event);
- logger_Release(&hicn->logger);
- addressDestroy(&hicn->localAddress);
- parcMemory_Deallocate((void **)&hicn);
- *listenerPtr = NULL;
-}
-
-static void _destroy(ListenerOps **listenerOpsPtr) {
- ListenerOps *ops = *listenerOpsPtr;
- HicnListener *hicn = (HicnListener *)ops->context;
- _hicnListener_Destroy(&hicn);
- parcMemory_Deallocate((void **)&ops);
- *listenerOpsPtr = NULL;
-}
-
-static const char *_getListenerName(const ListenerOps *ops) {
- HicnListener *hicn = (HicnListener *)ops->context;
- return hicn->listenerName;
-}
-
-static const char *_getInterfaceName(const ListenerOps *ops) {
- const char *interfaceName = "";
- return interfaceName;
-}
-
-static unsigned _getInterfaceIndex(const ListenerOps *ops) {
- HicnListener *hicn = (HicnListener *)ops->context;
- return hicn->conn_id;
-}
-
-static const Address *_getListenAddress(const ListenerOps *ops) {
- HicnListener *hicn = (HicnListener *)ops->context;
- return hicn->localAddress;
-}
-
-static EncapType _getEncapType(const ListenerOps *ops) { return ENCAP_HICN; }
-
-static int _getSocket(const ListenerOps *ops) {
- HicnListener *hicn = (HicnListener *)ops->context;
- return hicn->hicn_fd;
-}
-
-// ===============================
-
-static void _readFrameToDiscard(HicnListener *hicn, int fd) {
- // we need to discard the frame. Read 1 byte. This will clear it off the
- // stack.
- uint8_t buffer;
- int nread = read(fd, &buffer, 1);
-
- if (nread > 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "Discarded frame from fd %d", fd);
- }
- } else if (nread < 0) {
- if (logger_IsLoggable(hicn->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Error trying to discard frame from fd %d: (%d) %s", fd, errno,
- strerror(errno));
- }
- }
-}
-
-static unsigned _createNewConnection(ListenerOps * listener, int fd,
- const AddressPair *pair) {
- HicnListener * hicn = (HicnListener *)listener->context;
- bool isLocal = false;
-
- // udpConnection_Create takes ownership of the pair
- IoOperations *ops = hicnConnection_Create(hicn->forwarder, listener->getInterfaceName(listener), fd, pair, isLocal);
- Connection *conn = connection_Create(ops);
-
- connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), conn);
- unsigned connid = ioOperations_GetConnectionId(ops);
-
- return connid;
-}
-
-static const Connection * _lookupConnection(ListenerOps * listener,
- const AddressPair *pair) {
- HicnListener * hicn = (HicnListener*)listener->context;
- const Address * packetSourceAddress = addressPair_GetLocal(pair);
-
- const Connection *conn = NULL;
- if (hicn->connection_id != -1) {
- conn = connectionTable_FindById(
- forwarder_GetConnectionTable(hicn->forwarder), hicn->connection_id);
- } else {
- if (packetSourceAddress != NULL) {
- // in this first check we try to retrieve the standard connection
- // generated by the hicn-light
- AddressPair *pair =
- addressPair_Create(hicn->localAddress, packetSourceAddress);
- conn = connectionTable_FindByAddressPair(
- forwarder_GetConnectionTable(hicn->forwarder), pair);
- addressPair_Release(&pair);
- }
- }
-
- return conn;
-}
-
-static Address *_createAddressFromPacket(uint8_t *msgBuffer) {
- Address *packetAddr = NULL;
- if (messageHandler_GetIPPacketType(msgBuffer) == IPv6_TYPE) {
- struct sockaddr_in6 addr_in6;
- addr_in6.sin6_family = AF_INET6;
- addr_in6.sin6_port = htons(1234);
- addr_in6.sin6_flowinfo = 0;
- addr_in6.sin6_scope_id = 0;
- memcpy(&addr_in6.sin6_addr,
- (struct in6_addr *)messageHandler_GetSource(msgBuffer), 16);
- packetAddr = addressCreateFromInet6(&addr_in6);
- } else if (messageHandler_GetIPPacketType(msgBuffer) == IPv4_TYPE) {
- struct sockaddr_in addr_in;
- addr_in.sin_family = AF_INET;
- addr_in.sin_port = htons(1234);
- memcpy(&addr_in.sin_addr,
- (struct in_addr *)messageHandler_GetSource(msgBuffer), 4);
- packetAddr = addressCreateFromInet(&addr_in);
- }
- return packetAddr;
-}
-
-static void _handleWldrNotification(ListenerOps *listener, uint8_t *msgBuffer) {
- HicnListener * hicn = (HicnListener *)listener->context;
-
- Address *packetAddr = _createAddressFromPacket(msgBuffer);
-
- if (packetAddr == NULL) {
- parcMemory_Deallocate((void **)&msgBuffer);
- return;
- }
-
- AddressPair * pair = addressPair_Create(packetAddr, /* dummy */ hicn->localAddress);
-
- const Connection *conn = _lookupConnection(listener, pair);
-
- addressPair_Release(&pair);
- addressDestroy(&packetAddr);
-
- if (conn == NULL) {
- parcMemory_Deallocate((void **)&msgBuffer);
- return;
- }
-
- Message *message = message_CreateFromByteArray(
- connection_GetConnectionId(conn), msgBuffer,
- MessagePacketType_WldrNotification, forwarder_GetTicks(hicn->forwarder),
- forwarder_GetLogger(hicn->forwarder));
-
- connection_HandleWldrNotification((Connection *)conn, message);
-
- message_Release(&message);
-}
diff --git a/hicn-light/src/hicn/io/hicnListener.h b/hicn-light/src/hicn/io/hicnListener.h
deleted file mode 100644
index faf6ad6b8..000000000
--- a/hicn-light/src/hicn/io/hicnListener.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file hicnListener.h
- * @brief Listens for in coming Hicn connections
- *
- *
- */
-
-#ifndef hicnListener_h
-#define hicnListener_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/core/messageHandler.h>
-#include <hicn/io/listener.h>
-#include <stdlib.h>
-
-struct hicn_listener;
-typedef struct hicn_listener HicnListener;
-
-ListenerOps *hicnListener_CreateInet(Forwarder *forwarder, char *symbolic,
- Address *address);
-ListenerOps *hicnListener_CreateInet6(Forwarder *forwarder, char *symbolic,
- Address *address);
-bool hicnListener_Punting(ListenerOps *ops, const char *prefix);
-bool hicnListener_Bind(ListenerOps *ops, const Address *remoteAddress);
-bool hicnListener_SetConnectionId(ListenerOps *ops, unsigned connId);
-// const Address *hicnListener_GetTunAddress(const ListenerOps *ops);
-#endif // hicnListener_h
diff --git a/hicn-light/src/hicn/io/hicnTunnel.c b/hicn-light/src/hicn/io/hicnTunnel.c
deleted file mode 100644
index fd5acc680..000000000
--- a/hicn-light/src/hicn/io/hicnTunnel.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/io/hicnConnection.h>
-#include <hicn/io/hicnListener.h>
-#include <hicn/io/hicnTunnel.h>
-
-IoOperations *hicnTunnel_CreateOnListener(Forwarder *forwarder,
- ListenerOps *localListener,
- const Address *remoteAddress) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(localListener, "Parameter localListener must be non-null");
- parcAssertNotNull(remoteAddress, "Parameter remoteAddress must be non-null");
-
- Logger *logger = forwarder_GetLogger(forwarder);
-
- IoOperations *ops = NULL;
- if (localListener->getEncapType(localListener) == ENCAP_HICN) {
- const Address *localAddress =
- localListener->getListenAddress(localListener);
- address_type localType = addressGetType(localAddress);
- address_type remoteType = addressGetType(remoteAddress);
-
- if (localType == remoteType) {
- bool res = hicnListener_Bind(localListener, remoteAddress);
- if (res == false) {
- if (logger_IsLoggable(logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- logger_Log(logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Unable to bind local listener to remote node");
- }
- return ops;
- }
-
- // localAddress = hicnListener_GetTunAddress(localListener); //This is the
- // true local address
-
- AddressPair *pair = addressPair_Create(localAddress, remoteAddress);
- bool isLocal = false;
- int fd = localListener->getSocket(localListener);
- ops = hicnConnection_Create(forwarder, localListener->getInterfaceName(localListener), fd, pair, isLocal);
-
- addressPair_Release(&pair);
- } else {
- if (logger_IsLoggable(logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- logger_Log(logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Local listener of type %s and remote type %s, cannot "
- "establish tunnel",
- addressTypeToString(localType),
- addressTypeToString(remoteType));
- }
- }
- } else {
- if (logger_IsLoggable(logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- logger_Log(logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Local listener %p is not type UDP, cannot establish tunnel",
- (void *)localListener);
- }
- }
-
- return ops;
-}
-
-IoOperations *hicnTunnel_Create(Forwarder *forwarder,
- const Address *localAddress,
- const Address *remoteAddress) {
- ListenerSet *set = forwarder_GetListenerSet(forwarder);
- ListenerOps *listener = listenerSet_Find(set, ENCAP_HICN, localAddress);
- IoOperations *ops = NULL;
- if (listener) {
- ops = hicnTunnel_CreateOnListener(forwarder, listener, remoteAddress);
- } else {
- if (logger_IsLoggable(forwarder_GetLogger(forwarder), LoggerFacility_IO,
- PARCLogLevel_Error)) {
- char *str = addressToString(localAddress);
- logger_Log(forwarder_GetLogger(forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "Could not find listener to match address %s", str);
- parcMemory_Deallocate((void **)&str);
- }
- }
-
- if (ops) {
- hicnListener_SetConnectionId(listener, ops->getConnectionId(ops));
- }
-
- return ops;
-}
diff --git a/hicn-light/src/hicn/io/hicnTunnel.h b/hicn-light/src/hicn/io/hicnTunnel.h
deleted file mode 100644
index 1fe0b413c..000000000
--- a/hicn-light/src/hicn/io/hicnTunnel.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file hicnTunnel.h
- * @brief Establish a tunnel to a remote system
- *
- * Creates a "hicn tunnel" to a remote system. There must already be a local
- * HICN listener for the local side of the connection.
- *
- */
-
-#ifndef hicnTunnel_h
-#define hicnTunnel_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/io/listener.h>
-#include <hicn/utils/address.h>
-
-/**
- * Establishes a connection to a remote system over HICN
- *
- * The remoteAddress must be of the same type (i.e. v4 or v6) as the
- * localAddress. There must be an existing HICN listener on the local address.
- * If either of these are not true, will return NULL.
- *
- * The connection will go in the table immediately, and will be in the "up"
- * state.
- *
- * @param [in] an allocated hicn-light Forwarder
- * @param [in] localAddress The local IP address and port to use for the
- * connection
- * @param [in] remote Address the remote IP address for the connection, must
- * include a destination port.
- *
- * @retval non-null An allocated Io Operations structure for the connection
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-IoOperations *hicnTunnel_Create(Forwarder *forwarder,
- const Address *localAddress,
- const Address *remoteAddress);
-
-IoOperations *hicnTunnel_CreateOnListener(Forwarder *forwarder,
- ListenerOps *localListener,
- const Address *remoteAddress);
-
-#endif // hicnTunnel_h
diff --git a/hicn-light/src/hicn/io/ioOperations.c b/hicn-light/src/hicn/io/ioOperations.c
deleted file mode 100644
index 0087b320a..000000000
--- a/hicn-light/src/hicn/io/ioOperations.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <hicn/io/ioOperations.h>
-#include <stdio.h>
-
-void *ioOperations_GetClosure(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- return ops->closure;
-}
-
-bool ioOperations_Send(IoOperations *ops, const Address *nexthop,
- Message *message) {
- return ops->send(ops, nexthop, message);
-}
-
-bool ioOperations_SendIOVBuffer(IoOperations *ops, struct iovec *message,
- size_t size) {
- return ops->sendIOVBuffer(ops, message, size);
-}
-
-const Address *ioOperations_GetRemoteAddress(const IoOperations *ops) {
- return ops->getRemoteAddress(ops);
-}
-
-const AddressPair *ioOperations_GetAddressPair(const IoOperations *ops) {
- return ops->getAddressPair(ops);
-}
-
-
-
-bool ioOperations_IsUp(const IoOperations *ops) { return ops->isUp(ops); }
-
-bool ioOperations_IsLocal(const IoOperations *ops) { return ops->isLocal(ops); }
-
-unsigned ioOperations_GetConnectionId(const IoOperations *ops) {
- return ops->getConnectionId(ops);
-}
-
-void ioOperations_Release(IoOperations **opsPtr) {
- IoOperations *ops = *opsPtr;
- ops->destroy(opsPtr);
-}
-
-const void *ioOperations_Class(const IoOperations *ops) {
- return ops->class(ops);
-}
-
-list_connections_type ioOperations_GetConnectionType(const IoOperations *ops) {
- return ops->getConnectionType(ops);
-}
-
-void ioOperations_SendProbe(IoOperations *ops, uint8_t *message) {
- ops->sendProbe(ops, message);
-}
-
-
-connection_state_t ioOperations_GetState(const IoOperations *ops) {
- return ops->getState(ops);
-}
-
-void ioOperations_SetState(IoOperations *ops, connection_state_t state) {
- ops->setState(ops, state);
-}
-
-connection_state_t ioOperations_GetAdminState(const IoOperations *ops) {
- return ops->getAdminState(ops);
-}
-
-void ioOperations_SetAdminState(IoOperations *ops, connection_state_t admin_state) {
- ops->setAdminState(ops, admin_state);
-}
-
-#ifdef WITH_POLICY
-uint32_t ioOperations_GetPriority(const IoOperations *ops) {
- return ops->getPriority(ops);
-}
-
-void ioOperations_SetPriority(IoOperations *ops, uint32_t priority) {
- ops->setPriority(ops, priority);
-}
-#endif /* WITH_POLICY */
-
-const char * ioOperations_GetInterfaceName(const IoOperations *ops) {
- return ops->getInterfaceName(ops);
-}
diff --git a/hicn-light/src/hicn/io/ioOperations.h b/hicn-light/src/hicn/io/ioOperations.h
deleted file mode 100644
index 5d9befac3..000000000
--- a/hicn-light/src/hicn/io/ioOperations.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Defines the interface all connections use to communicate with the forwarder.
- */
-
-/**
- * I/O is built around a callback structure. The connection table contains an
- * operations structure built around function pointers. These allow the
- * connection table to be agnostic about underlying connections.
- */
-
-#ifndef io_h
-#define io_h
-
-#include <hicn/core/connectionState.h>
-#include <hicn/core/message.h>
-#include <hicn/core/ticks.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/utils/address.h>
-
-// packet types for probing
-#define PACKET_TYPE_PROBE_REQUEST 5
-#define PACKET_TYPE_PROBE_REPLY 6
-
-struct io_ops;
-typedef struct io_ops IoOperations;
-
-/**
- * @typedef IoOperations
- * @abstract The IO Operations structure abstracts an connection's properties
- * and send() method
- * @constant context Implementation specific opaque data, passed back on each
- * call
- * @constant send function pointer to send a message, does not destroy the
- * message
- * @constant getRemoteAddress function pointer to return the "to" address
- * associated with the connection. Some connections might not have a specific
- * peer, such as multicast, where its the group address.
- * @constant isUp test if the connection is up, ready to send a message.
- * @constant isLocal test if the connection is local to the host.
- * @constant getConnectionId returns the hicn-light id for the connection.
- * @constant destroy releases a refernce count on the connection and possibly
- * destroys the connection.
- * @constant class A unique identifier for each class that instantiates
- * IoOperations.
- * @constant getConnectionType Returns the type of connection (TCP, UDP, L2,
- * etc.) of the underlying connection.
- * @constant getState Returns the current state of the connection (redundant
- * with isUp for added for completeness of the API).
- * @constant setState Allows to mark the current state of a connection.
- * @constant getAdminState Returns the administrative state of a connection (as
- * requested by the user, which might occasionally differ from the current
- * state).
- * @constant setAdminState Allows to set the administrative state of a
- * connection.
- * @constant getInterfaceName Returns the interface name associated to a
- * connection.
- * @discussion <#Discussion#>
- */
-struct io_ops {
- void *closure;
- bool (*send)(IoOperations *ops, const Address *nexthop, Message *message);
- bool (*sendIOVBuffer)(IoOperations *ops, struct iovec *message, size_t
- size);
- const Address *(*getRemoteAddress)(const IoOperations *ops);
- const AddressPair *(*getAddressPair)(const IoOperations *ops);
- bool (*isUp)(const IoOperations *ops);
- bool (*isLocal)(const IoOperations *ops);
- unsigned (*getConnectionId)(const IoOperations *ops);
- void (*destroy)(IoOperations **opsPtr);
- const void *(*class)(const IoOperations *ops);
- list_connections_type (*getConnectionType)(const IoOperations *ops);
- void (*sendProbe)(IoOperations *ops, uint8_t *message);
- connection_state_t (*getState)(const IoOperations *ops);
- void (*setState)(IoOperations *ops, connection_state_t state);
- connection_state_t (*getAdminState)(const IoOperations *ops);
- void (*setAdminState)(IoOperations *ops, connection_state_t admin_state);
-#ifdef WITH_POLICY
- uint32_t (*getPriority)(const IoOperations *ops);
- void (*setPriority)(IoOperations *ops, uint32_t priority);
-#endif /* WITH_POLICY */
- const char * (*getInterfaceName)(const IoOperations *ops);
-};
-
-/**
- * Returns the closure of the interface
- *
- * The creator of the closure sets this parameter to store its state.
- *
- * @param [in] ops A concrete instance of the interface
- *
- * @return The value set by the concrete instance of the interface.
- *
- * Example:
- * @clode
- * {
-
- * }
- * @endcode
- */
-void *ioOperations_GetClosure(const IoOperations *ops);
-
-/**
- * Release all memory related to the interface and implementation
- *
- * This function must release all referenced memory in the concrete
- * implementation and memory related to the IoOperations. It should NULL the
- * input parameter.
- *
- * @param [in,out] opsPtr Pointer to interface. Will be NULLed.
- *
- * Example:
- * @code
- *
- * static void
- * _etherConnection_InternalRelease(_EtherState *etherConnState)
- * {
- * // release internal state of _EtherState
- * }
- *
- * static void
- * _etherConnection_Release(IoOperations **opsPtr)
- * {
- * IoOperations *ops = *opsPtr;
- *
- * _EtherState *etherConnState = (_EtherState *)
- * ioOperations_GetClosure(ops);
- * _etherConnection_InternalRelease(etherConnState);
- *
- * parcMemory_Deallocate((void **) &ops);
- * }
- *
- * IoOperations *
- * etherConnection_Create(Forwarder *forwarder, GenericEther *ether,
- * AddressPair *pair)
- * {
- * size_t allocationSize = sizeof(_EtherState) + sizeof(IoOperations);
- * IoOperations *ops = parcMemory_AllocateAndClear(allocationSize);
- * if (ops) {
- * // fill in other interface functions
- * ops->destroy = &_etherConnection_Release;
- * ops->closure = (uint8_t *) ops + sizeof(IoOperations);
- *
- * _EtherState *etherConnState = ioOperations_GetClosure(ops);
- * // fill in Ethernet state
- * }
- * return ops;
- * }
- * @endcode
- */
-void ioOperations_Release(IoOperations **opsPtr);
-
-/**
- * Sends the specified Message out this connection
- *
- * The the implementation of send may queue the message, it must acquire a
- * reference to it.
- *
- * @param [in] ops The connection implementation.
- * @param [in] nexthop On multiple access networks, this parameter might be
- * used, usually NULL.
- * @param [in] message The message to send. If the message will be queued, it
- * will be acquired.
- *
- * @return true The message was sent or queued
- * @retrun false An error occured and the message will not be sent or queued
- *
- * Example:
- * @code
- * {
- * if (ioOperations_IsUp(conn->ops)) {
- * return ioOperations_Send(conn->ops, NULL, message);
- * }
- * }
- * @endcode
- */
-bool ioOperations_Send(IoOperations *ops, const Address *nexthop,
- Message *message);
-
-bool ioOperations_SendIOVBuffer(IoOperations *ops, struct iovec *message,
- size_t size);
-
-/**
- * A connection is made up of a local and a remote address. This function
- * returns the remote address.
- *
- * Represents the destination endpoint of the communication.
- *
- * @param [in] ops The connection implementation.
- *
- * @return non-null The remote address
- * @return null The connection does not have a remote address
- *
- * Example:
- * @code
- * {
- * Address *local = addressCreateFromLink((uint8_t []) { 0x01, 0x02, 0x03,
- * 0x04, 0x05, 0x06 }, 6); Address *remote = addressCreateFromLink((uint8_t [])
- * { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, 6); AddressPair *pair =
- * addressPair_Create(local, remote); IoOperations *ops =
- * etherConnection_Create(forwarder, ether, pair);
- *
- * const Address *test = ioOperations_GetRemoteAddress(ops);
- * parcAssertTrue(addressEquals(test, remote), "Wrong remote address");
- * ioOperations_Release(&ops);
- * addressPair_Release(&pair);
- * addressDestroy(&local);
- * addressDestroy(&remote);
- * }
- * @endcode
- */
-const Address *ioOperations_GetRemoteAddress(const IoOperations *ops);
-
-/**
- * A connection is made up of a local and a remote address. This function
- * returns the address pair.
- *
- * Represents the destination endpoint of the communication.
- *
- * @param [in] ops The connection implementation.
- *
- * @return non-null The address pair
- * @return null An error.
- *
- * Example:
- * @code
- * {
- * Address *local = addressCreateFromLink((uint8_t []) { 0x01, 0x02, 0x03,
- * 0x04, 0x05, 0x06 }, 6); Address *remote = addressCreateFromLink((uint8_t [])
- * { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, 6); AddressPair *pair =
- * addressPair_Create(local, remote); IoOperations *ops =
- * etherConnection_Create(forwarder, ether, pair);
- *
- * const AddressPair *test = ioOperations_GetAddressPair(ops);
- * parcAssertTrue(addressPair(test, pair), "Wrong address pair");
- * ioOperations_Release(&ops);
- * addressPair_Release(&pair);
- * addressDestroy(&local);
- * addressDestroy(&remote);
- * }
- * @endcode
- */
-const AddressPair *ioOperations_GetAddressPair(const IoOperations *ops);
-
-/**
- * Returns true if the underlying connection is in operation
- *
- * An UP connection is able to send and receive packets. If a subsystem needs to
- * take actions when a connection goes UP or DOWN, it should subscribe as a
- * Missive listener.
- *
- * @param [in] ops The connection implementation.
- *
- * @return true The connection is UP
- * @return false The connection is not UP
- *
- * Example:
- * @code
- * {
- * if (ioOperations_IsUp(conn->ops)) {
- * return ioOperations_Send(conn->ops, NULL, message);
- * }
- * }
- * @endcode
- */
-bool ioOperations_IsUp(const IoOperations *ops);
-
-/**
- * If the remote address is local to this system, returns true
- *
- * Will return true if an INET or INET6 connection is on localhost. Will return
- * true for AF_UNIX. An Ethernet connection is not local.
- *
- * @param [in] ops The connection implementation.
- *
- * @return true The remote address is local to the system
- * @return false The remote address is not local
- *
- * Example:
- * @code
- * {
- * // Is the ingress connection remote? If so check for non-zero and
- * decrement if (!ioOperations(ingressConnectionOps) { uint8_t hoplimit =
- * message_GetHopLimit(interestMessage); if (hoplimit == 0) {
- * // error
- * } else {
- * hoplimit--;
- * }
- * // take actions on hoplimit
- * }
- * }
- * @endcode
- */
-bool ioOperations_IsLocal(const IoOperations *ops);
-
-/**
- * Returns the connection ID represented by this IoOperations in the
- * ConnectionTable.
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] ops The connection implementation.
- *
- * @return number The connection ID in the connection table.
- *
- * Example:
- * @code
- * {
- * unsigned id = ioOperations_GetConnectionId(ingressIoOps);
- * const Connection *conn =
- * connectionTable_FindById(forwarder->connectionTable, id);
- * }
- * @endcode
- */
-unsigned ioOperations_GetConnectionId(const IoOperations *ops);
-
-/**
- * A pointer that represents the class of the connection
- *
- * Each concrete implementation has a class pointer that is unique to the
- * implementation (not instance). Each implementation is free to choose how to
- * determine the value, so long as it is unique on the system. This is a
- * system-local value.
- *
- * @param [in] ops The connection implementation.
- *
- * @return non-null A pointer value unique to the implementation (not instance).
- *
- * Example:
- * @code
- * bool
- * etherConnection_IsInstanceOf(const Connection *conn)
- * {
- * bool result = false;
- * if (conn != NULL) {
- * IoOperations *ops = connection_GetIoOperations(conn);
- * const void *class = ioOperations_Class(ops);
- * result = (class == _etherConnection_Class(ops));
- * }
- * return result;
- * }
- * @endcode
- */
-const void *ioOperations_Class(const IoOperations *ops);
-
-/**
- * Returns the transport type of the connection (TCP, UDP, L2, etc.).
- *
- * TCP and AF_UNIX are both stream connections and will both return
- * "Connection_TCP". Ethernet will return "Connection_L2".
- *
- * @param [in] ops The connection implementation.
- *
- * @return Connection_TCP A TCP4, TCP6, or AF_UNIX connection
- * @return Connection_UDP A UDP4 or UDP6 connection
- * @return Connection_L2 An Ethernet connection
- *
- * Example:
- * @code
- * {
- * ConnectionType type =
- * ioOperations_GetConnectionType(connection_GetIoOperations(connection));
- * Connection *Conn =
- * Connection_Create(connection_GetConnectionId(connection), localAddress,
- * remoteAddress, type);
- * }
- * @endcode
- */
-list_connections_type ioOperations_GetConnectionType(const IoOperations *ops);
-
-void ioOperations_SendProbe(IoOperations *ops, uint8_t *message);
-
-
-/**
- * Returns the current state of the connection
- *
- * @param [in] ops The connection implementation.
- *
- * @return Connection state (connection_state_t).
- */
-connection_state_t ioOperations_GetState(const IoOperations *ops);
-
-/**
- * Sets the current state of the connection
- *
- * @param [in] ops The connection implementation.
- * @param [in] state New state to set (connection_state_t).
- */
-void ioOperations_SetState(IoOperations *ops, connection_state_t state);
-
-/**
- * Returns the administrative state of the connection
- *
- * @param [in] ops The connection implementation.
- *
- * @return Connection state (connection_state_t).
- */
-connection_state_t ioOperations_GetAdminState(const IoOperations *ops);
-
-/**
- * Sets the administrative state of the connection
- *
- * @param [in] ops The connection implementation.
- * @param [in] state New state to set (connection_state_t).
- */
-void ioOperations_SetAdminState(IoOperations *ops, connection_state_t admin_state);
-
-#ifdef WITH_POLICY
-/**
- * Returns the priority of the connection
- *
- * @param [in] ops The connection implementation.
- *
- * @return Connection state (uint32_t).
- */
-uint32_t ioOperations_GetPriority(const IoOperations *ops);
-
-/**
- * Sets the priority of the connection
- *
- * @param [in] ops The connection implementation.
- * @param [in] state New state to set (uint32_t).
- */
-void ioOperations_SetPriority(IoOperations *ops, uint32_t priority);
-#endif /* WITH_POLICY */
-
-/**
- * Sets the interface name associated to the connection.
- *
- * @param [in] ops The connection implementation.
- * @return the name associated to the connection (const char *)
- */
-const char * ioOperations_GetInterfaceName(const IoOperations *ops);
-
-#endif // io_h
diff --git a/hicn-light/src/hicn/io/listener.h b/hicn-light/src/hicn/io/listener.h
deleted file mode 100644
index 1b473be59..000000000
--- a/hicn-light/src/hicn/io/listener.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file listener.h
- * @brief Provides the function abstraction of all Listeners.
- *
- * A listener accepts in coming packets. A Stream listener will accept the
- * connection then pass it off to the {@link StreamConnection} class. A
- * datagram listener will have to have its own way to multiplex packets.
- *
- */
-
-#ifndef listener_h
-#define listener_h
-
-#include <hicn/utils/address.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/core/connection.h>
-
-struct listener_ops;
-typedef struct listener_ops ListenerOps;
-
-typedef enum {
- ENCAP_TCP, /**< TCP encapsulation type */
- ENCAP_UDP, /**< UDP encapsulation type */
- ENCAP_ETHER, /**< Ethernet encapsulation type */
- ENCAP_LOCAL, /**< A connection to a local protocol stack */
- ENCAP_HICN
-} EncapType;
-
-struct listener_ops {
- /**
- * A user-defined parameter
- */
- void *context;
-
- /**
- * Called to destroy the Listener.
- *
- * @param [in] listenerOpsPtr Double pointer to this structure
- */
- void (*destroy)(ListenerOps **listenerOpsPtr);
-
- /**
- * Returns the listener name of the listener.
- *
- * @param [in] ops Pointer to this structure
- *
- * @return the listener name of the listener
- */
- const char *(*getListenerName)(const ListenerOps *ops);
-
- /**
- * Returns the interface index of the listener.
- *
- * @param [in] ops Pointer to this structure
- *
- * @return the interface index of the listener
- */
- unsigned (*getInterfaceIndex)(const ListenerOps *ops);
-
- /**
- * Returns the address pair that defines the listener (local, remote)
- *
- * @param [in] ops Pointer to this structure
- *
- * @return the (local, remote) pair of addresses
- */
- const Address *(*getListenAddress)(const ListenerOps *ops);
-
- /**
- * Returns the encapsulation type of the listener (e.g. TCP, UDP, HICN)
- *
- * @param [in] ops Pointer to this structure
- *
- * @return the listener encapsulation type
- */
- EncapType (*getEncapType)(const ListenerOps *ops);
-
- /**
- * Returns the interface name of the listener.
- *
- * @param [in] ops Pointer to this structure
- *
- * @return the interface name of the listener
- */
- const char *(*getInterfaceName)(const ListenerOps *ops);
-
- /**
- * Returns the underlying socket associated with the listener
- *
- * Not all listeners are capable of returning a useful socket. In those
- * cases, this function pointer is NULL.
- *
- * TCP does not support this operation (function is NULL). UDP returns its
- * local socket.
- *
- * The caller should never close this socket, the listener will do that when
- * its destroy method is called.
- *
- * @param [in] ops Pointer to this structure
- *
- * @retval integer The socket descriptor
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
- int (*getSocket)(const ListenerOps *ops);
-
- unsigned (*createConnection)(ListenerOps *listener, int fd, const AddressPair *pair);
- const Connection * (*lookupConnection)(ListenerOps * listener, const AddressPair *pair);
-};
-#endif // listener_h
diff --git a/hicn-light/src/hicn/io/listenerSet.c b/hicn-light/src/hicn/io/listenerSet.c
deleted file mode 100644
index d69632287..000000000
--- a/hicn-light/src/hicn/io/listenerSet.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/io/listenerSet.h>
-
-struct listener_set {
- PARCArrayList *listOfListeners;
-};
-
-static void listenerSet_DestroyListenerOps(void **opsPtr) {
- ListenerOps *ops = *((ListenerOps **)opsPtr);
- ops->destroy(&ops);
-}
-
-ListenerSet *listenerSet_Create() {
- ListenerSet *set = parcMemory_AllocateAndClear(sizeof(ListenerSet));
- parcAssertNotNull(set, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerSet));
- set->listOfListeners = parcArrayList_Create(listenerSet_DestroyListenerOps);
-
- return set;
-}
-
-void listenerSet_Destroy(ListenerSet **setPtr) {
- parcAssertNotNull(setPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*setPtr, "Parameter must dereference to non-null pointer");
-
- ListenerSet *set = *setPtr;
- parcArrayList_Destroy(&set->listOfListeners);
- parcMemory_Deallocate((void **)&set);
- *setPtr = NULL;
-}
-
-/**
- * @function listenerSet_Add
- * @abstract Adds the listener to the set
- * @discussion
- * Unique set based on pair (EncapType, localAddress)
- *
- * @param <#param1#>
- * @return <#return#>
- */
-bool listenerSet_Add(ListenerSet *set, ListenerOps *ops) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- parcAssertNotNull(ops, "Parameter ops must be non-null");
-
- int opsEncap = ops->getEncapType(ops);
- const Address *opsAddress = ops->getListenAddress(ops);
-
- // make sure its not in the set
- size_t length = parcArrayList_Size(set->listOfListeners);
- for (size_t i = 0; i < length; i++) {
- ListenerOps *entry = parcArrayList_Get(set->listOfListeners, i);
-
- int entryEncap = entry->getEncapType(entry);
- const Address *entryAddress = entry->getListenAddress(entry);
-
- if (opsEncap == entryEncap && addressEquals(opsAddress, entryAddress)) {
- // duplicate
- return false;
- }
- }
-
- parcArrayList_Add(set->listOfListeners, ops);
- return true;
-}
-
-size_t listenerSet_Length(const ListenerSet *set) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- return parcArrayList_Size(set->listOfListeners);
-}
-
-/**
- * Returns the listener at the given index
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- * @param [in] index The index position (0 <= index < listenerSet_Count)
- *
- * @retval non-null The listener at index
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-ListenerOps *listenerSet_Get(const ListenerSet *set, size_t index) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- return parcArrayList_Get(set->listOfListeners, index);
-}
-
-ListenerOps *listenerSet_Find(const ListenerSet *set, EncapType encapType,
- const Address *localAddress) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- parcAssertNotNull(localAddress, "Parameter localAddress must be non-null");
-
- ListenerOps *match = NULL;
-
- for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners) && !match;
- i++) {
- ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i);
- parcAssertNotNull(ops, "Got null listener ops at index %zu", i);
-
- if (ops->getEncapType(ops) == encapType) {
- if (addressEquals(localAddress, ops->getListenAddress(ops))) {
- match = ops;
- }
- }
- }
-
- return match;
-}
-
-ListenerOps *listenerSet_FindById(const ListenerSet *set, unsigned id) {
- parcAssertNotNull(set, "Parameter set must be non-null");
-
- ListenerOps *match = NULL;
-
- for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners) && !match;
- i++) {
- ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i);
- parcAssertNotNull(ops, "Got null listener ops at index %zu", i);
- if (ops->getInterfaceIndex(ops) == id) {
- match = ops;
- }
- }
-
- return match;
-}
-
-int listenerSet_FindIdByListenerName(const ListenerSet *set, const char *listenerName ) {
- parcAssertNotNull(set, "Parameter set must be non-null");
- parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
-
- ListenerOps *match = NULL;
- int index = -1;
- for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners) && !match;
- i++) {
- ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i);
- parcAssertNotNull(ops, "Got null listener ops at index %zu", i);
- if (ops->getListenerName(ops) && strcmp(ops->getListenerName(ops), listenerName) == 0) {
- index = ops->getInterfaceIndex(ops);
- break;
- }
- }
-
- return index;
-}
-
-void listenerSet_RemoveById(const ListenerSet *set, unsigned id) {
- parcAssertNotNull(set, "Parameter set must be non-null");
-
- for (size_t i = 0; i < parcArrayList_Size(set->listOfListeners);
- i++) {
- ListenerOps *ops = parcArrayList_Get(set->listOfListeners, i);
- parcAssertNotNull(ops, "Got null listener ops at index %zu", i);
- if (ops->getInterfaceIndex(ops) == id) {
- parcArrayList_RemoveAndDestroyAtIndex(set->listOfListeners, i);
- break;
- }
- }
-}
diff --git a/hicn-light/src/hicn/io/listenerSet.h b/hicn-light/src/hicn/io/listenerSet.h
deleted file mode 100644
index 5779d2af4..000000000
--- a/hicn-light/src/hicn/io/listenerSet.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file listenerSet.h
- * @brief A listener set is unique on (EncapType, localAddress)
- *
- * Keeps track of all the running listeners. The set is unique on the
- * encapsulation type and the local address. For example, with TCP
- * encapsulation and local address 127.0.0.1 or Ethernet encapsulation and MAC
- * address 00:11:22:33:44:55.
- *
- * NOTE: This does not allow multiple EtherType on the same interface because
- * the Address for a LINK address does not include an EtherType.
- *
- */
-
-#ifndef listenerSet_h
-#define listenerSet_h
-
-#include <hicn/io/listener.h>
-
-struct listener_set;
-typedef struct listener_set ListenerSet;
-
-/**
- * <#One Line Description#>
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @retval <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-ListenerSet *listenerSet_Create(void);
-
-/**
- * <#One Line Description#>
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [<#in out in,out#>] <#name#> <#description#>
- *
- * @retval <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void listenerSet_Destroy(ListenerSet **setPtr);
-
-/**
- * @function listenerSet_Add
- * @abstract Adds the listener to the set
- * @discussion
- * Unique set based on pair (EncapType, localAddress).
- * Takes ownership of the ops memory if added.
- *
- * @param <#param1#>
- * @return true if added, false if not
- */
-bool listenerSet_Add(ListenerSet *set, ListenerOps *ops);
-
-/**
- * The number of listeners in the set
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- *
- * @retval <#value#> <#explanation#>
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-size_t listenerSet_Length(const ListenerSet *set);
-size_t listenerSet_Length(const ListenerSet *set);
-
-/**
- * Returns the listener at the given index
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- * @param [in] index The index position (0 <= index < listenerSet_Lenght)
- *
- * @retval non-null The listener at index
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-ListenerOps *listenerSet_Get(const ListenerSet *set, size_t index);
-
-/**
- * Looks up a listener by its key (EncapType, LocalAddress)
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- * @param [in] encapType the listener type
- * @param [in] localAddress The local bind address (e.g. MAC address or TCP
- * socket)
- *
- * @retval non-null The listener matching the query
- * @retval null Does not exist
- *
- * Example:
- * @code
- *
- * @endcode
- */
-ListenerOps *listenerSet_Find(const ListenerSet *set, EncapType encapType,
- const Address *localAddress);
-
-/**
- * Looks up a listener by its id
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- * @param [in] id of the listener
- *
- * @retval non-null The listener matching the query
- * @retval null Does not exist
- *
- * Example:
- * @code
- *
- * @endcode
- */
-ListenerOps *listenerSet_FindById(const ListenerSet *set, unsigned id);
-
-/**
- * Looks up a listener by its id
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- * @param [in] name of the listener
- *
- * @retval greater or equal to 0 The listener matching the query
- * @retval -1 Does not exist
- *
- * Example:
- * @code
- *
- * @endcode
- */
-int listenerSet_FindIdByListenerName(const ListenerSet *set, const char *listenerName);
-
-/**
- * Remove up a listener by its id
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] set An allocated listener set
- * @param [in] id of the listener
- *
- * Example:
- * @code
- *
- * @endcode
- */
-void listenerSet_RemoveById(const ListenerSet *set, unsigned id);
-#endif
diff --git a/hicn-light/src/hicn/io/streamConnection.c b/hicn-light/src/hicn/io/streamConnection.c
deleted file mode 100644
index 53ffa74c3..000000000
--- a/hicn-light/src/hicn/io/streamConnection.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Common activity for STREAM based listeners.
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/message.h>
-#include <hicn/io/streamConnection.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/messageHandler.h>
-
-#include <hicn/utils/commands.h>
-
-#include <hicn/hicn.h>
-// 128 KB output queue
-#define OUTPUT_QUEUE_BYTES (128 * 1024)
-
-static void _conn_readcb(PARCEventQueue *bufferEventVector, PARCEventType type,
- void *ioOpsVoid);
-
-static void _conn_eventcb(PARCEventQueue *bufferEventVector,
- PARCEventQueueEventType events, void *ioOpsVoid);
-
-typedef struct stream_state {
- Forwarder *forwarder;
- char * interfaceName;
- Logger *logger;
-
- int fd;
-
- AddressPair *addressPair;
- PARCEventQueue *bufferEventVector;
-
- bool isLocal;
- bool isUp;
- bool isClosed;
- unsigned id;
-
- size_t nextMessageLength;
-
- /* This information would better be stored in the connection data structure
- * but it is currently not reachable from within the implementation. */
- connection_state_t state;
- connection_state_t admin_state;
-#ifdef WITH_POLICY
- uint32_t priority;
-#endif /* WITH_POLICY */
-} _StreamState;
-
-// Prototypes
-static bool _streamConnection_Send(IoOperations *ops, const Address *nexthop,
- Message *message);
-static bool _streamConnection_SendIOVBuffer(IoOperations *ops, struct
- iovec *msg, size_t size);
-static const Address *_streamConnection_GetRemoteAddress(
- const IoOperations *ops);
-static const AddressPair *_streamConnection_GetAddressPair(
- const IoOperations *ops);
-static unsigned _streamConnection_GetConnectionId(const IoOperations *ops);
-static bool _streamConnection_IsUp(const IoOperations *ops);
-static bool _streamConnection_IsLocal(const IoOperations *ops);
-static void _streamConnection_DestroyOperations(IoOperations **opsPtr);
-
-static void _setConnectionState(_StreamState *stream, bool isUp);
-static list_connections_type _streamConnection_GetConnectionType(
- const IoOperations *ops);
-static void _sendProbe(IoOperations *ops, uint8_t *message);
-static connection_state_t _streamConnection_getState(const IoOperations *ops);
-static void _streamConnection_setState(IoOperations *ops, connection_state_t state);
-static connection_state_t _streamConnection_getAdminState(const IoOperations *ops);
-static void _streamConnection_setAdminState(IoOperations *ops, connection_state_t admin_state);
-#ifdef WITH_POLICY
-static uint32_t _streamConnection_getPriority(const IoOperations *ops);
-static void _streamConnection_setPriority(IoOperations *ops, uint32_t priority);
-#endif /* WITH_POLICY */
-static const char * _streamConnection_getInterfaceName(const IoOperations *ops);
-
-/*
- * This assigns a unique pointer to the void * which we use
- * as a GUID for this class.
- */
-static const void *_ioOperationsGuid = __FILE__;
-
-/*
- * Return our GUID
- */
-static const void *_streamConnection_Class(const IoOperations *ops) {
- return _ioOperationsGuid;
-}
-
-static IoOperations _template = {
- .closure = NULL,
- .send = &_streamConnection_Send,
- .sendIOVBuffer = &_streamConnection_SendIOVBuffer,
- .getRemoteAddress = &_streamConnection_GetRemoteAddress,
- .getAddressPair = &_streamConnection_GetAddressPair,
- .getConnectionId = &_streamConnection_GetConnectionId,
- .isUp = &_streamConnection_IsUp,
- .isLocal = &_streamConnection_IsLocal,
- .destroy = &_streamConnection_DestroyOperations,
- .class = &_streamConnection_Class,
- .getConnectionType = &_streamConnection_GetConnectionType,
- .sendProbe = &_sendProbe,
- .getState = &_streamConnection_getState,
- .setState = &_streamConnection_setState,
- .getAdminState = &_streamConnection_getAdminState,
- .setAdminState = &_streamConnection_setAdminState,
-#ifdef WITH_POLICY
- .getPriority = &_streamConnection_getPriority,
- .setPriority = &_streamConnection_setPriority,
-#endif /* WITH_POLICY */
- .getInterfaceName = &_streamConnection_getInterfaceName,
-};
-
-IoOperations *streamConnection_AcceptConnection(Forwarder *forwarder, int fd,
- AddressPair *pair,
- bool isLocal) {
- _StreamState *stream = parcMemory_AllocateAndClear(sizeof(_StreamState));
- parcAssertNotNull(stream, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(_StreamState));
-
- Dispatcher *dispatcher = forwarder_GetDispatcher(forwarder);
- PARCEventScheduler *eventBase = dispatcher_GetEventScheduler(dispatcher);
- stream->bufferEventVector = parcEventQueue_Create(
- eventBase, fd,
- PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks);
-
- stream->forwarder = forwarder;
- stream->interfaceName = NULL;
- stream->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- stream->fd = fd;
- stream->id = forwarder_GetNextConnectionId(forwarder);
- stream->addressPair = pair;
- stream->isClosed = false;
-
-#ifdef WITH_POLICY
- stream->priority = 0;
-#endif /* WITH_POLICY */
-
- // allocate a connection
- IoOperations *io_ops = parcMemory_AllocateAndClear(sizeof(IoOperations));
- parcAssertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(IoOperations));
- memcpy(io_ops, &_template, sizeof(IoOperations));
- io_ops->closure = stream;
- stream->isLocal = isLocal;
-
- parcEventQueue_SetCallbacks(stream->bufferEventVector, _conn_readcb, NULL,
- _conn_eventcb, (void *)io_ops);
- parcEventQueue_Enable(stream->bufferEventVector, PARCEventType_Read);
-
- messenger_Send(forwarder_GetMessenger(stream->forwarder),
- missive_Create(MissiveType_ConnectionCreate, stream->id));
-
- // As we are acceting a connection, we begin in the UP state
- _setConnectionState(stream, true);
-
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- char *pair_str = addressPair_ToString(pair);
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "StreamConnection %p accept for address pair %s", (void *)stream,
- pair_str);
- free(pair_str);
- }
-
- return io_ops;
-}
-
-IoOperations *streamConnection_OpenConnection(Forwarder *forwarder,
- AddressPair *pair, bool isLocal) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(pair, "Parameter pair must be non-null");
-
- // if there's an error on the bind or connect, will return NULL
- PARCEventQueue *bufferEventVector =
- dispatcher_StreamBufferConnect(forwarder_GetDispatcher(forwarder), pair);
- if (bufferEventVector == NULL) {
- // error opening connection
- return NULL;
- }
-
- _StreamState *stream = parcMemory_AllocateAndClear(sizeof(_StreamState));
- parcAssertNotNull(stream, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(_StreamState));
-
- stream->forwarder = forwarder;
- stream->interfaceName = NULL;
- stream->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- stream->fd = parcEventQueue_GetFileDescriptor(bufferEventVector);
- stream->bufferEventVector = bufferEventVector;
- stream->id = forwarder_GetNextConnectionId(forwarder);
- stream->addressPair = pair;
- stream->isClosed = false;
-
- // allocate a connection
- IoOperations *io_ops = parcMemory_AllocateAndClear(sizeof(IoOperations));
- parcAssertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(IoOperations));
- memcpy(io_ops, &_template, sizeof(IoOperations));
- io_ops->closure = stream;
- stream->isLocal = isLocal;
-
- parcEventQueue_SetCallbacks(stream->bufferEventVector, _conn_readcb, NULL,
- _conn_eventcb, (void *)io_ops);
- parcEventQueue_Enable(stream->bufferEventVector, PARCEventType_Read);
-
- // we start in DOWN state, until remote side answers
- messenger_Send(forwarder_GetMessenger(stream->forwarder),
- missive_Create(MissiveType_ConnectionCreate, stream->id));
- _setConnectionState(stream, false);
-
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO, PARCLogLevel_Info)) {
- char *pair_str = addressPair_ToString(pair);
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Info, __func__,
- "StreamConnection %p connect for address pair %s",
- (void *)stream, pair_str);
- free(pair_str);
- }
-
- return io_ops;
-}
-
-static void _streamConnection_DestroyOperations(IoOperations **opsPtr) {
- parcAssertNotNull(opsPtr, "Parameter opsPtr must be non-null double pointer");
- parcAssertNotNull(*opsPtr,
- "Parameter opsPtr must dereference to non-null pointer");
-
- IoOperations *ops = *opsPtr;
- parcAssertNotNull(ioOperations_GetClosure(ops),
- "ops->context must not be null");
-
- _StreamState *stream = (_StreamState *)ioOperations_GetClosure(ops);
-
- parcEventQueue_Destroy(&stream->bufferEventVector);
-
- addressPair_Release(&stream->addressPair);
-
- if (!stream->isClosed) {
- stream->isClosed = true;
- messenger_Send(forwarder_GetMessenger(stream->forwarder),
- missive_Create(MissiveType_ConnectionClosed, stream->id));
- }
-
- messenger_Send(forwarder_GetMessenger(stream->forwarder),
- missive_Create(MissiveType_ConnectionDestroyed, stream->id));
-
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO, PARCLogLevel_Info)) {
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Info, __func__,
- "StreamConnection %p destroyed", (void *)stream);
- }
-
- logger_Release(&stream->logger);
- parcMemory_Deallocate((void **)&stream);
- parcMemory_Deallocate((void **)&ops);
-
- *opsPtr = NULL;
-}
-
-static bool _streamConnection_IsUp(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->isUp;
-}
-
-static bool _streamConnection_IsLocal(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->isLocal;
-}
-
-static const Address *_streamConnection_GetRemoteAddress(
- const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return addressPair_GetRemote(stream->addressPair);
-}
-
-static const AddressPair *_streamConnection_GetAddressPair(
- const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->addressPair;
-}
-
-static unsigned _streamConnection_GetConnectionId(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->id;
-}
-
-bool _streamConnection_SendIOVBuffer(IoOperations *ops,
- struct iovec * message, size_t size) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
-
- _StreamState *conn = (_StreamState *)ioOperations_GetClosure(ops);
-
- if (!conn->isUp) {
- if (logger_IsLoggable(conn->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- logger_Log(
- conn->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "connid %u tried to send to down connection (isUp %d isClosed %d)",
- conn->id, conn->isUp, conn->isClosed);
- }
- return false;
- }
-
- PARCEventBuffer *buffer =
- parcEventBuffer_GetQueueBufferOutput(conn->bufferEventVector);
- size_t buffer_backlog = parcEventBuffer_GetLength(buffer);
- parcEventBuffer_Destroy(&buffer);
-
- if (buffer_backlog >= OUTPUT_QUEUE_BYTES) {
- if (logger_IsLoggable(conn->logger, LoggerFacility_IO,
- PARCLogLevel_Warning)) {
- logger_Log(conn->logger, LoggerFacility_IO, PARCLogLevel_Warning,
- __func__,
- "connid %u Writing to buffer backlog %zu bytes DROP MESSAGE",
- conn->id, buffer_backlog);
- }
- return false;
- }
-
- if (logger_IsLoggable(conn->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- size_t length = 0;
- for (int i = 0; i < size; i++)
- length += message[i].iov_len;
-
- logger_Log( conn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "connid %u Writing %zu bytes to buffer with backlog %zu bytes",
- conn->id, length, buffer_backlog);
- }
-
- /* Write directly into the parcEventQueue without passing through message */
- for (int i = 0; i < size; i++) {
- if (parcEventQueue_Write(conn->bufferEventVector, message[i].iov_base,
- message[i].iov_len) != 0)
- return false;
- }
-
- return true;
-}
-
-/**
- * @function streamConnection_Send
- * @abstract Non-destructive send of the message.
- * @discussion
- * Send uses message_CopyToStreamBuffer, which is a non-destructive write.
- * The send may fail if there's no buffer space in the output queue.
- *
- * @param dummy is ignored. A stream has only one peer.
- * @return <#return#>
- */
-static bool _streamConnection_Send(IoOperations *ops, const Address *dummy,
- Message *message) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- _StreamState *stream = (_StreamState *)ioOperations_GetClosure(ops);
-
- bool success = false;
- if (stream->isUp) {
- PARCEventBuffer *buffer =
- parcEventBuffer_GetQueueBufferOutput(stream->bufferEventVector);
- size_t buffer_backlog = parcEventBuffer_GetLength(buffer);
- parcEventBuffer_Destroy(&buffer);
-
- if (buffer_backlog < OUTPUT_QUEUE_BYTES) {
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Debug)) {
- logger_Log(
- stream->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "connid %u Writing %zu bytes to buffer with backlog %zu bytes",
- stream->id, message_Length(message), buffer_backlog);
- }
-
- int failure = message_Write(stream->bufferEventVector, message);
- if (failure == 0) {
- success = true;
- }
- } else {
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Warning)) {
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Warning,
- __func__,
- "connid %u Writing to buffer backlog %zu bytes DROP MESSAGE",
- stream->id, buffer_backlog);
- }
- }
- } else {
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- logger_Log(
- stream->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "connid %u tried to send to down connection (isUp %d isClosed %d)",
- stream->id, stream->isUp, stream->isClosed);
- }
- }
-
- return success;
-}
-
-list_connections_type _streamConnection_GetConnectionType(
- const IoOperations *ops) {
- return CONN_TCP;
-}
-
-static void _sendProbe(IoOperations *ops, uint8_t *message) {
- // we don't need to implemet this here, it is a local connection
-}
-
-// =================================================================
-// the actual I/O functions
-
-int _isACommand(PARCEventBuffer *input) {
- size_t bytesAvailable = parcEventBuffer_GetLength(input);
- parcAssertTrue(bytesAvailable >= sizeof(header_control_message),
- "Called with too short an input: %zu", bytesAvailable);
-
- uint8_t *msg = parcEventBuffer_Pullup(input, bytesAvailable);
- // read first byte of the header
-
- // first byte: must be a REQUEST_LIGHT
- if (msg[0] != REQUEST_LIGHT) {
- return LAST_COMMAND_VALUE;
- }
-
- // second byte: must be a command_id
- if (msg[1] < 0 || msg[1] >= LAST_COMMAND_VALUE) {
- return LAST_COMMAND_VALUE;
- }
-
- return msg[1];
-}
-
-PARCEventBuffer *_tryReadControlMessage(_StreamState *stream,
- PARCEventBuffer *input,
- command_id command,
- struct iovec **request) {
- size_t bytesAvailable = parcEventBuffer_GetLength(input);
-
- if (stream->nextMessageLength == 0) {
- stream->nextMessageLength =
- sizeof(header_control_message) +
- payloadLengthDaemon(command); // consider the whole packet.
- }
-
- if (bytesAvailable >= stream->nextMessageLength) {
- PARCEventBuffer *message = parcEventBuffer_Create();
- int bytesRead = parcEventBuffer_ReadIntoBuffer(input, message,
- stream->nextMessageLength);
- parcAssertTrue(bytesRead == stream->nextMessageLength,
- "Partial read, expected %zu got %d",
- stream->nextMessageLength, bytesRead);
-
- uint8_t *control =
- parcEventBuffer_Pullup(message, stream->nextMessageLength);
- if (!(*request = (struct iovec *)parcMemory_AllocateAndClear(
- sizeof(struct iovec) * 2))) {
- return NULL;
- }
- (*request)[0].iov_base = control; // header
- (*request)[0].iov_len = sizeof(header_control_message);
- if (payloadLengthDaemon(command) > 0) {
- (*request)[1].iov_base =
- control + sizeof(header_control_message); // payload
- } else {
- (*request)[1].iov_base = NULL;
- }
- (*request)[1].iov_len = payloadLengthDaemon(command);
- // now reset message length for next packet
-
- stream->nextMessageLength = 0;
-
- return message;
- }
-
- return NULL;
-}
-
-static bool _isAnHicnPacket(PARCEventBuffer *input) {
- size_t bytesAvailable = parcEventBuffer_GetLength(input);
- parcAssertTrue(bytesAvailable >= sizeof(header_control_message),
- "Called with too short an input: %zu", bytesAvailable);
-
- uint8_t *fh = parcEventBuffer_Pullup(input, sizeof(header_control_message));
- return messageHandler_IsValidHicnPacket(fh);
-}
-
-static Message *_readMessage(_StreamState *stream, Ticks time,
- PARCEventBuffer *input) {
- Message *message = message_CreateFromEventBuffer(
- input, stream->nextMessageLength, stream->id, time, stream->logger);
-
- return message;
-}
-
-static void _startNewMessage(_StreamState *stream, PARCEventBuffer *input,
- size_t inputBytesAvailable) {
- parcAssertTrue(stream->nextMessageLength == 0,
- "Invalid state, nextMessageLength not zero: %zu",
- stream->nextMessageLength);
- parcAssertTrue(inputBytesAvailable >= sizeof(header_control_message),
- "read_length not a whole fixed header!: %zd",
- inputBytesAvailable);
-
- // this linearizes the first messageHandler_GetIPv6HeaderLength() bytes of the
- // input buffer's iovecs and returns a pointer to it.
- uint8_t *fh = parcEventBuffer_Pullup(input, sizeof(header_control_message));
-
- // Calculate the total message size based on the fixed header
- stream->nextMessageLength = messageHandler_GetTotalPacketLength(fh);
-}
-
-static Message *_tryReadMessage(PARCEventBuffer *input, _StreamState *stream) {
- size_t bytesAvailable = parcEventBuffer_GetLength(input);
- parcAssertTrue(bytesAvailable >= sizeof(header_control_message),
- "Called with too short an input: %zu", bytesAvailable);
-
- if (stream->nextMessageLength == 0) {
- _startNewMessage(stream, input, bytesAvailable);
- }
-
- // This is not an ELSE statement. We can both start a new message then
- // check if there's enough bytes to read the whole thing.
-
- if (bytesAvailable >= stream->nextMessageLength) {
- Message *message =
- _readMessage(stream, forwarder_GetTicks(stream->forwarder), input);
-
- // now reset message length for next packet
- stream->nextMessageLength = 0;
-
- return message;
- }
-
- return NULL;
-}
-
-/**
- * @function conn_readcb
- * @abstract Event callback for reads
- * @discussion
- * Will read messages off the input. Continues reading as long as we
- * can get a header to determine the next message length or as long as we
- * can read a complete message.
- *
- * This function manipulates the read low water mark. (1) read a fixed header
- * plus complete message, then set the low water mark to FIXED_HEADER_LEN. (2)
- * read a fixed header, but not a complete message, then set low water mark to
- * the total mesage length. Using the low water mark like this means the buffer
- * event will only trigger on meaningful byte boundaries when we can get actual
- * work done.
- *
- * @param <#param1#>
- * @return <#return#>
- */
-static void _conn_readcb(PARCEventQueue *event, PARCEventType type,
- void *ioOpsVoid) {
- command_id command;
- IoOperations *ops = (IoOperations *)ioOpsVoid;
- _StreamState *stream = (_StreamState *)ioOperations_GetClosure(ops);
-
- PARCEventBuffer *input = parcEventBuffer_GetQueueBufferInput(event);
-
- // drain the input buffer
-
- // notice that we always try to read at least 8 bytes
- // (sizeof(header_control_message)). This is enough to read the length of all
- // kind of packets
- while (parcEventBuffer_GetLength(input) >= sizeof(header_control_message) &&
- parcEventBuffer_GetLength(input) >= stream->nextMessageLength) {
-
- if ((command = _isACommand(input)) != LAST_COMMAND_VALUE) {
- struct iovec *rx;
- // Get message from the stream and set the stream->nextMessageLength
- PARCEventBuffer *message =
- _tryReadControlMessage(stream, input, command, &rx);
- // If received correctly the whole message, send to dispatcher
- if (message) {
- forwarder_ReceiveCommand(stream->forwarder, command, rx, stream->id);
- //parcMemory_Deallocate((void **)&rx);
- parcEventBuffer_Destroy(&message);
- }
-
- } else if (_isAnHicnPacket(input)) {
- // this is an Hicn packet (here we should distinguish between IPv4 and
- // IPv6 tryReadMessage may set nextMessageLength
- Message *message = _tryReadMessage(input, stream);
-
- if (message) {
- forwarder_Receive(stream->forwarder, message);
- }
-
- } else {
- parcAssertTrue(false,
- "(Local stream connection) malformed packet received");
- }
- }
-
- if (stream->nextMessageLength == 0) {
- // we don't have the next header, so set it to the header length
- streamBuffer_SetWatermark(event, true, false,
- sizeof(header_control_message), 0);
- } else {
- // set it to the packet length
- streamBuffer_SetWatermark(event, true, false, stream->nextMessageLength, 0);
- }
- parcEventBuffer_Destroy(&input);
-}
-
-static void _setConnectionState(_StreamState *stream, bool isUp) {
- parcAssertNotNull(stream, "Parameter stream must be non-null");
-
- Messenger *messenger = forwarder_GetMessenger(stream->forwarder);
-
- bool oldStateIsUp = stream->isUp;
- stream->isUp = isUp;
-
- if (oldStateIsUp && !isUp) {
- // bring connection DOWN
- Missive *missive = missive_Create(MissiveType_ConnectionDown, stream->id);
- messenger_Send(messenger, missive);
- return;
- }
-
- if (!oldStateIsUp && isUp) {
- // bring connection UP
- Missive *missive = missive_Create(MissiveType_ConnectionUp, stream->id);
- messenger_Send(messenger, missive);
- return;
- }
-}
-
-static void _conn_eventcb(PARCEventQueue *event, PARCEventQueueEventType events,
- void *ioOpsVoid) {
- IoOperations *ops = (IoOperations *)ioOpsVoid;
- _StreamState *stream = (_StreamState *)ioOperations_GetClosure(ops);
-
- if (events & PARCEventQueueEventType_Connected) {
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Info)) {
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Info, __func__,
- "Connection %u is connected", stream->id);
- }
-
- // if the stream was closed, do not transition to an UP state
- if (!stream->isClosed) {
- _setConnectionState(stream, true);
- }
- } else if (events & PARCEventQueueEventType_EOF) {
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Info)) {
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Info, __func__,
- "connid %u closed.", stream->id);
- }
-
- parcEventQueue_Disable(stream->bufferEventVector, PARCEventType_Read);
-
- _setConnectionState(stream, false);
-
- if (!stream->isClosed) {
- stream->isClosed = true;
- // this will cause the connection manager to destroy the connection later
- messenger_Send(forwarder_GetMessenger(stream->forwarder),
- missive_Create(MissiveType_ConnectionClosed, stream->id));
- }
- } else if (events & PARCEventQueueEventType_Error) {
- if (logger_IsLoggable(stream->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- logger_Log(stream->logger, LoggerFacility_IO, PARCLogLevel_Error,
- __func__, "Got an error on the connection %u: %s", stream->id,
- strerror(errno));
- }
-
- parcEventQueue_Disable(stream->bufferEventVector,
- PARCEventType_Read | PARCEventType_Write);
-
- _setConnectionState(stream, false);
-
- if (!stream->isClosed) {
- stream->isClosed = true;
- // this will cause the connection manager to destroy the connection later
- messenger_Send(forwarder_GetMessenger(stream->forwarder),
- missive_Create(MissiveType_ConnectionClosed, stream->id));
- }
- }
- /* None of the other events can happen here, since we haven't enabled
- * timeouts */
-}
-
-static connection_state_t _streamConnection_getState(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->state;
-}
-
-static void _streamConnection_setState(IoOperations *ops, connection_state_t state) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _StreamState *stream =
- (_StreamState *)ioOperations_GetClosure(ops);
- stream->state = state;
-}
-
-static connection_state_t _streamConnection_getAdminState(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->admin_state;
-}
-
-static void _streamConnection_setAdminState(IoOperations *ops, connection_state_t admin_state) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _StreamState *stream =
- (_StreamState *)ioOperations_GetClosure(ops);
- stream->admin_state = admin_state;
-}
-
-#ifdef WITH_POLICY
-static uint32_t _streamConnection_getPriority(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _StreamState *stream =
- (const _StreamState *)ioOperations_GetClosure(ops);
- return stream->priority;
-}
-
-static void _streamConnection_setPriority(IoOperations *ops, uint32_t priority) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _StreamState *stream =
- (_StreamState *)ioOperations_GetClosure(ops);
- stream->priority = priority;
-}
-#endif /* WITH_POLICY */
-
-static const char * _streamConnection_getInterfaceName(const IoOperations *ops)
-{
- parcAssertNotNull(ops, "Parameter must be non-null");
- _StreamState *stream =
- (_StreamState *)ioOperations_GetClosure(ops);
- return stream->interfaceName;
-}
diff --git a/hicn-light/src/hicn/io/streamConnection.h b/hicn-light/src/hicn/io/streamConnection.h
deleted file mode 100644
index f483d0b82..000000000
--- a/hicn-light/src/hicn/io/streamConnection.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Methods common to TCP and PF_LOCAL stream-based listeners
- */
-
-#ifndef streamConnection_h
-#define streamConnection_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/core/messagePacketType.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/utils/address.h>
-
-/**
- * @function streamConnection_AcceptConnection
- * @abstract Receive a connection from a remote peer
- * @discussion
- * We are the "server side" of the stream connection, so we need to accept the
- * client connection and setup state for her.
- *
- * @param <#param1#>
- * @return <#return#>
- */
-IoOperations *streamConnection_AcceptConnection(Forwarder *forwarder, int fd,
- AddressPair *pair,
- bool isLocal);
-
-/**
- * @function streamConnection_OpenConnection
- * @abstract Initiate a connection to a remote peer
- * @discussion
- * We are the "client side" of the stream connection. We'll create state for
- * the peer, but it will be in the "down" state until the connection
- * establishes.
- *
- * For TCP, both address pairs need to be the same address family: both INET
- * or both INET6. The remote address must have the complete socket information
- * (address, port). The local socket could be wildcarded or may specify down to
- * the (address, port) pair.
- *
- * If the local address is IPADDR_ANY and the port is 0, then it is a normal
- * call to "connect" that will use whatever local IP address and whatever local
- * port for the connection. If either the address or port is set, the local
- * socket will first be bound (via bind(2)), and then call connect().
- *
- * AF_UNIX is not yet supported
- *
- * If there's an error binding to the specified address or connecting to the
- * remote address, will return NULL.
- *
- * @param pair (takes ownership of this) is the complete socket pair of
- * (address, port) for each end, if INET or INET6.
- * @return NULL on error, otherwise the connections IO operations.
- */
-IoOperations *streamConnection_OpenConnection(Forwarder *forwarder,
- AddressPair *pair, bool isLocal);
-
-bool streamState_SendIOVBuffer(IoOperations *ops, struct iovec *response,
- size_t size);
-
-#endif // streamConnection_h
diff --git a/hicn-light/src/hicn/io/tcp.c b/hicn-light/src/hicn/io/tcp.c
new file mode 100644
index 000000000..69ad32d16
--- /dev/null
+++ b/hicn-light/src/hicn/io/tcp.c
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+/**
+ * Common activity for STREAM based listeners.
+ */
+
+#include <errno.h>
+#ifndef _WIN32
+#include <unistd.h> // fcntl
+#endif /* _WIN32 */
+#include <fcntl.h> // fcntl
+#include <hicn/hicn-light/config.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <hicn/hicn.h>
+#include <hicn/util/log.h>
+
+#include "base.h"
+#include "../core/connection.h"
+#include "../core/connection_vft.h"
+#include "../core/listener.h"
+#include "../core/listener_vft.h"
+#include "../core/msgbuf.h"
+#include "../core/forwarder.h"
+#include "../core/messageHandler.h"
+
+// 128 KB output queue
+#define OUTPUT_QUEUE_BYTES (128 * 1024)
+
+#define TCP_RECV_BUFLEN 8192
+//#define MTU 1500
+
+/******************************************************************************
+ * Listener
+ ******************************************************************************/
+
+typedef struct {
+ void *_;
+} listener_tcp_data_t;
+
+static int listener_tcp_initialize(listener_t *listener) {
+ ERROR("[listener_tcp_initialize] Not implemented");
+
+ return 0;
+}
+
+static void listener_tcp_finalize(listener_t *listener) {
+ ERROR("[listener_tcp_finalize] Not implemented");
+}
+
+static int listener_tcp_punt(const listener_t *listener, const char *prefix_s) {
+ ERROR("[listener_tcp_punt] Not implemented");
+ return -1;
+}
+
+static int listener_tcp_get_socket(const listener_t *listener,
+ const address_t *local,
+ const address_t *remote,
+ const char *interface_name) {
+ ERROR("[listener_tcp_get_socket] Not implemented");
+ return -1;
+}
+
+#define listener_tcp_read_single io_read_single_socket
+#define listener_tcp_read_batch NULL
+
+DECLARE_LISTENER(tcp);
+
+/******************************************************************************
+ * Connection
+ ******************************************************************************/
+
+typedef struct {
+ /* Partial receive buffer */
+ u8 buf[TCP_RECV_BUFLEN];
+ size_t roff; /**< Read offset */
+ size_t woff; /**< Write offset */
+
+ // XXX this should be initialized with the header length, and tells what we
+ // expect to receive next...
+ size_t next_len;
+ struct bufferevent *bufferevent;
+} connection_tcp_data_t;
+
+// XXX This seems more a listener code !
+// XXX we must have accept to the connection table to spawn new ones !!
+// XXX equivalent to initialize
+int connection_tcp_accept(connection_t *connection, listener_t *listener,
+ int fd, address_pair_t *pair, bool local,
+ unsigned connection_id) {
+ assert(connection);
+ assert(listener);
+
+ *connection = (connection_t){
+ .id = connection_id,
+ .interface_name = NULL,
+ .type = FACE_TYPE_TCP,
+ .pair = *pair,
+ .fd = fd,
+ .local = local,
+ // As we are accepting a connection, we begin in the UP state
+ .state = FACE_STATE_UP,
+ .admin_state = FACE_STATE_UP,
+#ifdef WITH_POLICY
+ .priority = 0,
+#endif /* WITH_POLICY */
+
+ .listener = listener,
+ .closed = false,
+ };
+
+ WITH_INFO({
+ char addr_str[NI_MAXHOST];
+ int port;
+ address_to_string(&(pair->local), addr_str, &port);
+ INFO("%s connection %p created for address %s:%d (local=%s)",
+ face_type_str(connection->type), connection, addr_str, port,
+ connection_is_local(connection) ? "true" : "false");
+ })
+
+ return 0;
+}
+
+int make_socket(address_pair_t *pair) {
+#ifndef _WIN32
+ int fd = socket(address_family(&pair->local), SOCK_STREAM, 0);
+ if (fd < 0) {
+ perror("socket");
+ goto ERR_SOCKET;
+ }
+#else
+ SOCKET fd = socket(address_family(&pair->local), SOCK_STREAM, 0);
+ if (fd == INVALID_SOCKET) {
+ perror("socket");
+ goto ERR_SOCKET;
+ }
+#endif /* _WIN32 */
+
+ /* Set non-blocking flag */
+#ifndef _WIN32
+ int flags = fcntl(fd, F_GETFL, NULL);
+ if (flags == -1) {
+ perror("F_GETFL");
+ goto ERR;
+ }
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
+ perror("F_SETFL");
+ goto ERR;
+ }
+#else
+ if (ioctlsocket(fd, FIONBIO, &(u_long){1}) != NO_ERROR) {
+ perror("ioctlsocket");
+ goto ERR;
+ }
+#endif /* _WIN32 */
+
+ if (bind(fd, address_sa(&pair->local), address_socklen(&pair->local)) == -1) {
+ perror("bind");
+ goto ERR;
+ }
+
+ if (connect(fd, address_sa(&pair->remote), address_socklen(&pair->remote)) <
+ 0) {
+ perror("connect");
+ goto ERR;
+ }
+
+ return 0;
+
+ERR:
+#ifndef _WIN32
+ close(fd);
+#else
+ closesocket(fd);
+#endif
+
+ERR_SOCKET:
+ return -1;
+}
+
+static int connection_tcp_initialize(connection_t *connection) {
+ assert(connection);
+ assert(connection->type == FACE_TYPE_TCP);
+
+ connection_tcp_data_t *data = connection->data;
+ assert(data);
+
+ data->roff = 0;
+ data->woff = 0;
+
+ connection->fd = make_socket(connection_get_pair(connection));
+ if (connection->fd < 0) {
+ ERROR("Error creating TCP socket");
+ return -1;
+ }
+
+ WITH_INFO({
+ char local_addr_str[NI_MAXHOST];
+ char remote_addr_str[NI_MAXHOST];
+ int local_port;
+ int remote_port;
+ address_to_string(&(connection->pair.local), local_addr_str, &local_port);
+ address_to_string(&(connection->pair.remote), remote_addr_str,
+ &remote_port);
+ INFO("%s connection %p connect for address pair %s:%d (local=%s) - %s:%d",
+ face_type_str(connection->type), connection, local_addr_str,
+ local_port, connection_is_local(connection) ? "true" : "false",
+ remote_addr_str, remote_port);
+ })
+
+ return 0;
+}
+
+// XXX a part needs to be handled in the connection.c
+static void connection_tcp_finalize(connection_t *connection) {
+ if (!connection->closed) {
+ connection->closed = true;
+ // XXX need to delete the connection like previously in the connection
+ // manager
+ }
+
+ INFO("%s connection %p destroyed", face_type_str(connection->type),
+ connection);
+ // XXX need to release the "connection"
+}
+
+#if 0
+static
+bool
+connection_tcp_sendv(connnection_t * connection, struct iovec * iov,
+ size_t size)
+{
+ assert(connection);
+ assert(iov);
+
+ if (!connection_is_up(connection)) {
+ ERROR("Connection #%u tried to send to down connection (up=%d closed=%d)",
+ connection_get_id(connection),
+ connection_get_up(connection) ? "true" : "false",
+ connection_get_closed(connection) ? "true" : "false");
+ return false;
+ }
+
+ PARCEventBuffer *buffer =
+ parcEventBuffer_GetQueueBufferOutput(connection->events);
+ size_t buffer_backlog = parcEventBuffer_GetLength(buffer);
+ parcEventBuffer_Destroy(&buffer);
+
+ if (buffer_backlog >= OUTPUT_QUEUE_BYTES) {
+ WARN("Connection #%u Writing to buffer backlog %zu bytes DROP MESSAGE",
+ connection_get_id(connection), buffer_backlog);
+ return false;
+ }
+
+#if 0
+ /* DEBUG */
+ size_t length = 0;
+ for (int i = 0; i < size; i++)
+ length += message[i].iov_len;
+ DEBUG("Connection #%u writing %zu bytes to buffer with backlog %zu bytes",
+ connection_get_id(connection), length, buffer_backlog);
+#endif
+
+ /* Write directly into the parcEventQueue without passing through message */
+ for (int i = 0; i < size; i++) {
+ if (parcEventQueue_Write(conn->events, iov[i].iov_base,
+ iov[i].iov_len) != 0)
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+static bool connection_tcp_flush(const connection_t *connection) {
+ return true;
+}
+
+/**
+ * @function streamConnection_Send
+ * @abstract Non-destructive send of the message.
+ * @discussion
+ * Send uses message_CopyToStreamBuffer, which is a non-destructive write.
+ * The send may fail if there's no buffer space in the output queue.
+ *
+ * @param dummy is ignored. A stream has only one peer.
+ * @return <#return#>
+ */
+// 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) {
+ assert(connection);
+ assert(msgbuf);
+
+ if (!connection_is_up(connection)) {
+ ERROR("Connection #%u tried to send to down connection (up=%d closed=%d)",
+ connection_get_id(connection),
+ connection_is_up(connection) ? "true" : "false",
+ connection_is_closed(connection) ? "true" : "false");
+ return false;
+ }
+
+ // XXX TODO write to fd
+#if 0
+ PARCEventBuffer *buffer =
+ parcEventBuffer_GetQueueBufferOutput(connection->events);
+ size_t buffer_backlog = parcEventBuffer_GetLength(buffer);
+ parcEventBuffer_Destroy(&buffer);
+
+ if (buffer_backlog >= OUTPUT_QUEUE_BYTES) {
+ WARN("Connection #%u Writing to buffer backlog %zu bytes DROP MESSAGE",
+ connection_get_id(connection), buffer_backlog);
+ return false;
+ }
+
+ DEBUG("Connection #%u Writing %zu bytes to buffer with backlog %zu bytes",
+ connection_get_id(connection), msgbuf_len(message), buffer_backlog);
+
+ return (parcEventQueue_Write(connection->events, msgbuf_packet(message),
+ msgbuf_len(message)) == 0);
+#endif
+ return true;
+}
+
+static int connection_tcp_send_packet(const connection_t *connection,
+ const uint8_t *packet, size_t size) {
+ /* Not implemented for local connections */
+ // XXX shall we set the pointer to NULL and add a check ?
+
+ ERROR("[connection_tcp_send_packet] Not implemented");
+
+ return -1;
+}
+
+// =================================================================
+// the actual I/O functions
+
+// not needed anymore ?
+#if 0
+// XXX this is called iif there is sufficient data to read, otherwise it raises
+// an assertion error. This was a problem before I guess
+static
+int
+connection_tcp_read_message(connection_t * connection, msgbuf_t * msgbuf)
+{
+ assert(connection);
+ assert(msgbuf);
+
+ connection_tcp_data_t * data = connection->data;
+ assert(data);
+
+ size_t n = evbuffer_get_length(data->evbuffer);
+ // XXX this check was wrong
+ // parcAssertTrue(n >= sizeof(cmd_header_t),
+ "Called with too short an input: %zu", n);
+
+ // XXX WTF
+ if (stream->next_len == 0) {
+ // this linearizes the first messageHandler_GetIPv6HeaderLength() bytes of the
+ // input buffer's iovecs and returns a pointer to it.
+ uint8_t *fh = parcEventBuffer_Pullup(data->evbuffer, sizeof(cmd_header_t));
+
+ // Calculate the total message size based on the fixed header
+ stream->next_len = messageHandler_GetTotalPacketLength(fh);
+ }
+ // This is not an ELSE statement. We can both start a new message then
+ // check if there's enough bytes to read the whole thing.
+
+ if (n < stream->next_len)
+ return -1;
+
+ uint8_t packet_type;
+ if (messageHandler_IsInterest(packet)) {
+ packet_type = MESSAGE_TYPE_INTEREST;
+ } else if (messageHandler_IsData(packet)) {
+ packet_type = MESSAGE_TYPE_DATA;
+ } else {
+ ERROR("Dropped packet that is not interest nor data");
+ goto ERR;
+ }
+
+ if (evbuffer_remove(data->evbuffer, data->packet, data->next_len) < 0)
+ return -1;
+
+ msgbuf_from_packet(msgbuf, data->packet, packet_type, stream->id,
+ ticks_now());
+
+ // now reset message length for next packet
+ data->next_len = 0;
+ return 0;
+
+ERR:
+ evbuffer_drain(data->evbuffer, data->next_len);
+ return -1;
+}
+#endif
+
+/**
+ * @function conn_readcb
+ * @abstract Event callback for reads
+ * @discussion
+ * Will read messages off the input. Continues reading as long as we
+ * can get a header to determine the next message length or as long as we
+ * can read a complete message.
+ *
+ * This function manipulates the read low water mark. (1) read a fixed header
+ * plus complete message, then set the low water mark to FIXED_HEADER_LEN. (2)
+ * read a fixed header, but not a complete message, then set low water mark to
+ * the total mesage length. Using the low water mark like this means the buffer
+ * event will only trigger on meaningful byte boundaries when we can get actual
+ * work done.
+ *
+ * @param <#param1#>
+ * @return <#return#>
+ */
+#if 0
+static
+void
+connection_tcp_read_callback(connection_t * connection, int fd, void * user_data)
+{
+ assert(connection);
+ /* user_data can be NULL */
+
+ connection_tcp_data_t * data = connection->data;
+ assert(TCP_RECV_BUFLEN - data->woff > MTU);
+
+ /* No batching here as code is not expected to receive much throughput */
+ for (;;) {
+ ssize_t n = recv(connection->fd, data->buf + data->woff,
+ TCP_RECV_BUFLEN - data->woff, 0);
+ if (n == 0) /* EOF */
+ return; // XXX close connection
+ if (n < 0) {
+ if (errno == EWOULDBLOCK)
+ break;
+ perror("recv");
+ return; // XXX close connection
+ }
+ data->woff += n;
+
+ /* Process */
+ uint8_t * packet = data->buf + data->roff;
+ size_t size = data->woff - data->roff; /* > 0 */
+
+ ssize_t used = listener_read_callback(NULL, fd,
+ address_pair_get_local(&connection->pair), packet, size);
+ if (used < 0)
+ return; // XXX close connection ?
+ if (used == 0)
+ break; /* We would have received more if there was still packets to be read */
+ data->roff += used;
+ assert(data->roff <= data->woff);
+
+ if (data->roff == data->woff) {
+ /* Reset state whenever possible to avoid memcpy's */
+ data->roff = 0;
+ data->woff = 0;
+ return;
+ }
+ }
+
+ /* Make sure there is enough remaining space in the buffer */
+ if (TCP_RECV_BUFLEN - data->woff < MTU) {
+ /*
+ * There should be no overlap provided a sufficiently large BUFLEN, but
+ * who knows.
+ */
+ memmove(data->buf, data->buf + data->roff, data->woff - data->roff);
+ data->woff -= data->roff;
+ data->roff = 0;
+ }
+
+ return;
+}
+#endif
+
+#if 0
+static
+void
+connection_tcp_callback(connection_t * connection, int fd, void * user_data)
+{
+ if (events & PARCEventQueueEventType_Connected) {
+ INFO("Connection %u is connected", stream->id);
+
+ // if the stream was closed, do not transition to an UP state
+ if (!stream->isClosed) {
+ _setConnectionState(stream, true);
+ }
+ } else if (events & PARCEventQueueEventType_EOF) {
+ INFO("connid %u closed.", stream->id);
+
+ parcEventQueue_Disable(stream->events, PARCEventType_Read);
+
+ _setConnectionState(stream, false);
+
+ if (!stream->isClosed) {
+ stream->isClosed = true;
+ // XXX TODO destroy the connection
+ }
+ } else if (events & PARCEventQueueEventType_Error) {
+ ERROR("Got an error on the connection %u: %s", stream->id,
+ strerror(errno));
+
+ parcEventQueue_Disable(stream->events,
+ PARCEventType_Read | PARCEventType_Write);
+
+ _setConnectionState(stream, false);
+
+ if (!stream->isClosed) {
+ stream->isClosed = true;
+ // XXX TODO destroy the connection
+ }
+ }
+ /* None of the other events can happen here, since we haven't enabled
+ * timeouts */
+}
+#endif
+
+DECLARE_CONNECTION(tcp)
diff --git a/hicn-light/src/hicn/io/tcpListener.c b/hicn-light/src/hicn/io/tcpListener.c
deleted file mode 100644
index e2b80c215..000000000
--- a/hicn-light/src/hicn/io/tcpListener.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <hicn/core/connectionTable.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/io/listener.h>
-#include <hicn/io/streamConnection.h>
-#include <hicn/io/tcpListener.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/assert/parc_Assert.h>
-
-typedef struct tcp_listener {
- char *listenerName;
- Forwarder *forwarder;
- Logger *logger;
-
- PARCEventSocket *listener;
-
- Address *localAddress;
-
- unsigned id;
- char *interfaceName;
-
- // is the localAddress as 127.0.0.0 address?
- bool isLocalAddressLocal;
-} _TcpListener;
-
-static void _tcpListener_Destroy(_TcpListener **listenerPtr);
-
-static void _tcpListener_OpsDestroy(ListenerOps **listenerOpsPtr);
-
-static const char *_tcpListener_ListenerName(const ListenerOps *ops);
-
-static unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops);
-
-static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops);
-
-static const char *_tcpListener_InterfaceName(const ListenerOps *ops);
-
-static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops);
-
-static ListenerOps _tcpTemplate = {
- .context = NULL,
- .destroy = &_tcpListener_OpsDestroy,
- .getListenerName = &_tcpListener_ListenerName,
- .getInterfaceIndex = &_tcpListener_OpsGetInterfaceIndex,
- .getListenAddress = &_tcpListener_OpsGetListenAddress,
- .getEncapType = &_tcpListener_OpsGetEncapType,
- .getInterfaceName = &_tcpListener_InterfaceName,
- .getSocket = NULL};
-
-// STREAM daemon listener callback
-static void _tcpListener_Listen(int, struct sockaddr *, int socklen,
- void *tcpVoid);
-
-ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in6 sin6, char *interfaceName) {
-
- _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener));
- parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(_TcpListener));
-
- tcp->forwarder = forwarder;
- tcp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
- tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- tcp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
-
- tcp->listener = dispatcher_CreateListener(
- forwarder_GetDispatcher(forwarder), _tcpListener_Listen, (void *)tcp, -1,
- (struct sockaddr *)&sin6, sizeof(sin6));
-
- if (tcp->listener == NULL) {
- logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "dispatcher_CreateListener failed to create listener (%d) %s",
- errno, strerror(errno));
- logger_Release(&tcp->logger);
- parcMemory_Deallocate((void **)&tcp);
- return NULL;
- }
-
- tcp->localAddress = addressCreateFromInet6(&sin6);
- tcp->id = forwarder_GetNextConnectionId(forwarder);
- tcp->isLocalAddressLocal =
- parcNetwork_IsSocketLocal((struct sockaddr *)&sin6);
-
- ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerOps));
-
- memcpy(ops, &_tcpTemplate, sizeof(ListenerOps));
- ops->context = tcp;
-
- if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- char *str = addressToString(tcp->localAddress);
- logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "TcpListener %p created for address %s (isLocal %d)",
- (void *)tcp, str, tcp->isLocalAddressLocal);
- parcMemory_Deallocate((void **)&str);
- }
-
- return ops;
-}
-
-ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in sin, char *interfaceName) {
- _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener));
- parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(_TcpListener));
-
- tcp->forwarder = forwarder;
- tcp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
- tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- tcp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
-
- tcp->listener = dispatcher_CreateListener(
- forwarder_GetDispatcher(forwarder), _tcpListener_Listen, (void *)tcp, -1,
- (struct sockaddr *)&sin, sizeof(sin));
-
- if (tcp->listener == NULL) {
- logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "dispatcher_CreateListener failed to create listener (%d) %s",
- errno, strerror(errno));
-
- logger_Release(&tcp->logger);
- parcMemory_Deallocate((void **)&tcp);
- return NULL;
- }
-
- tcp->localAddress = addressCreateFromInet(&sin);
- tcp->id = forwarder_GetNextConnectionId(forwarder);
- tcp->isLocalAddressLocal = parcNetwork_IsSocketLocal((struct sockaddr *)&sin);
-
- ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerOps));
-
- memcpy(ops, &_tcpTemplate, sizeof(ListenerOps));
- ops->context = tcp;
-
- if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- char *str = addressToString(tcp->localAddress);
- logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "TcpListener %p created for address %s (isLocal %d)",
- (void *)tcp, str, tcp->isLocalAddressLocal);
- parcMemory_Deallocate((void **)&str);
- }
-
- return ops;
-}
-
-static void _tcpListener_Destroy(_TcpListener **listenerPtr) {
- parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listenerPtr,
- "Parameter must derefernce to non-null pointer");
- _TcpListener *tcp = *listenerPtr;
-
- if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- char *str = addressToString(tcp->localAddress);
- logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "TcpListener %p destroyed", (void *)tcp);
- parcMemory_Deallocate((void **)&str);
- }
-
- parcMemory_Deallocate((void **)&tcp->listenerName);
- parcMemory_Deallocate((void **)&tcp->interfaceName);
- logger_Release(&tcp->logger);
- dispatcher_DestroyListener(forwarder_GetDispatcher(tcp->forwarder),
- &tcp->listener);
- addressDestroy(&tcp->localAddress);
- parcMemory_Deallocate((void **)&tcp);
- *listenerPtr = NULL;
-}
-
-// ==================================================
-
-static const char *_tcpListener_ListenerName(const ListenerOps *ops) {
- _TcpListener *tcp = (_TcpListener *)ops->context;
- return tcp->listenerName;
-}
-
-static const char *_tcpListener_InterfaceName(const ListenerOps *ops) {
- _TcpListener *tcp = (_TcpListener *)ops->context;
- return tcp->interfaceName;
-}
-
-static void _tcpListener_Listen(int fd, struct sockaddr *sa, int socklen,
- void *tcpVoid) {
- _TcpListener *tcp = (_TcpListener *)tcpVoid;
-
- Address *remote;
-
- switch (sa->sa_family) {
- case AF_INET:
- remote = addressCreateFromInet((struct sockaddr_in *)sa);
- break;
-
- case AF_INET6:
- remote = addressCreateFromInet6((struct sockaddr_in6 *)sa);
- break;
-
- default:
- parcTrapIllegalValue(sa, "Expected INET or INET6, got %d", sa->sa_family);
- abort();
- }
-
- AddressPair *pair = addressPair_Create(tcp->localAddress, remote);
-
- IoOperations *ops = streamConnection_AcceptConnection(
- tcp->forwarder, fd, pair, tcp->isLocalAddressLocal);
- Connection *conn = connection_Create(ops);
-
- connectionTable_Add(forwarder_GetConnectionTable(tcp->forwarder), conn);
-
- if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "TcpListener %p listen started", (void *)tcp);
- }
-
- addressDestroy(&remote);
-}
-
-static void _tcpListener_OpsDestroy(ListenerOps **listenerOpsPtr) {
- ListenerOps *ops = *listenerOpsPtr;
- _TcpListener *tcp = (_TcpListener *)ops->context;
- _tcpListener_Destroy(&tcp);
- parcMemory_Deallocate((void **)&ops);
- *listenerOpsPtr = NULL;
-}
-
-static unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops) {
- _TcpListener *tcp = (_TcpListener *)ops->context;
- return tcp->id;
-}
-
-static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops) {
- _TcpListener *tcp = (_TcpListener *)ops->context;
- return tcp->localAddress;
-}
-
-static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops) {
- return ENCAP_TCP;
-}
diff --git a/hicn-light/src/hicn/io/tcpListener.h b/hicn-light/src/hicn/io/tcpListener.h
deleted file mode 100644
index a841738e5..000000000
--- a/hicn-light/src/hicn/io/tcpListener.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file tcpListener.h
- * @brief Listens for in coming TCP connections
- *
- * This is the "server socket" of hicn-light for TCP connections. The actual
- * I/O is handled by {@link StreamConnection}.
- *
- */
-
-#ifndef tcpListener_h
-#define tcpListener_h
-
-#ifndef _WIN32
-#include <netinet/in.h>
-#endif
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/listener.h>
-#include <stdlib.h>
-
-ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in6 sin6, char *interfaceName);
-ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in sin, char *interfaceName);
-#endif // tcpListener_h
diff --git a/hicn-light/src/hicn/io/tcpTunnel.c b/hicn-light/src/hicn/io/tcpTunnel.c
deleted file mode 100644
index 7a04a4222..000000000
--- a/hicn-light/src/hicn/io/tcpTunnel.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/io/streamConnection.h>
-#include <hicn/io/tcpListener.h>
-#include <hicn/io/tcpTunnel.h>
-
-IoOperations *tcpTunnel_Create(Forwarder *forwarder,
- const Address *localAddress,
- const Address *remoteAddress) {
- IoOperations *ops = NULL;
-
- address_type localType = addressGetType(localAddress);
- address_type remoteType = addressGetType(remoteAddress);
-
- if (localType == remoteType) {
- AddressPair *pair = addressPair_Create(localAddress, remoteAddress);
- bool isLocal = false;
-
- ops = streamConnection_OpenConnection(forwarder, pair, isLocal);
- }
-
- return ops;
-}
diff --git a/hicn-light/src/hicn/io/tcpTunnel.h b/hicn-light/src/hicn/io/tcpTunnel.h
deleted file mode 100644
index d1d2a8524..000000000
--- a/hicn-light/src/hicn/io/tcpTunnel.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file tcpTunnel.h
- * @brief Establish a tunnel to a remote system
- *
- */
-
-#ifndef tcpTunnel_h
-#define tcpTunnel_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/io/listener.h>
-#include <hicn/utils/address.h>
-
-/**
- */
-// IoOperations *tcpTunnel_CreateOnListener(Forwarder *forwarder,
-// ListenerOps *localListener,
-// const Address *remoteAddress);
-
-/**
- */
-IoOperations *tcpTunnel_Create(Forwarder *forwarder,
- const Address *localAddress,
- const Address *remoteAddress);
-
-#endif // tcpTunnel_h
diff --git a/hicn-light/src/hicn/io/udp.c b/hicn-light/src/hicn/io/udp.c
new file mode 100644
index 000000000..3301e2178
--- /dev/null
+++ b/hicn-light/src/hicn/io/udp.c
@@ -0,0 +1,566 @@
+/*
+ * 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 udp.c
+ * #brief Implementation of the UDP face
+ *
+ * Old comment:
+ * - The Send() function may overflow the output buffer
+ *
+ */
+
+/* This has to be included early as other modules are including socket.h */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <sys/uio.h>
+#include <unistd.h>
+#endif
+#include <sys/socket.h>
+
+#ifdef WITH_GSO
+#include <netinet/if_ether.h> // ETH_DATA_LEN
+#include <linux/ipv6.h> // struct ipv6hdr
+#include <netinet/udp.h> // struct udphdr, SOL_UDP
+//#include <linux/udp.h> // UDP_GRO
+#define UDP_GRO 104
+#endif /* WITH_GSO */
+
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.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"
+#include "../core/forwarder.h"
+#include "../core/listener.h"
+#include "../core/listener_vft.h"
+#include "../core/messageHandler.h"
+#include "../core/msgbuf.h"
+//#include "../hicn-light/config.h"
+
+// Batching based on recvmmsg is also generic
+// the difference is the handling of packet as in tcp we need to go through the
+// ring buffer first to do the framing, while in UDP this is already done
+//
+// each module should have a function to process a packet, then call a callback
+// in the forwarder again
+
+#define BATCH_SOCKET_BUFFER 512 * 1024 /* 256k */
+
+/******************************************************************************
+ * Listener
+ ******************************************************************************/
+
+typedef struct {
+ uint16_t port; // in address ?
+} listener_udp_data_t;
+
+#ifdef __ANDROID__
+extern int bindSocket(int sock, const char *interface_name);
+#endif
+
+#if 0
+#include <arpa/inet.h>
+char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) {
+ switch (sa->sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen);
+ break;
+
+ case AF_INET6:
+ inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen);
+ break;
+
+ default:
+ strncpy(s, "Unknown AF", maxlen);
+ return NULL;
+ }
+
+ return s;
+}
+#endif
+
+/* socket options */
+int socket_set_options(int fd) {
+#ifndef _WIN32
+ // Set non-blocking flag
+ int flags = fcntl(fd, F_GETFL, NULL);
+ if (flags < 0) {
+ perror("fcntl");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ perror("fcntl");
+ return -1;
+ }
+#else
+ // Set non-blocking flag
+ int result = ioctlsocket(fd, FIONBIO, &(int){1});
+ if (result != NO_ERROR) {
+ perror("ioctlsocket");
+ return -1;
+ }
+#endif
+
+ // don't hang onto address after listener has closed
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+
+#ifdef WITH_GSO
+ int gso_size = ETH_DATA_LEN - sizeof(struct ipv6hdr) - sizeof(struct udphdr);
+ if (setsockopt(fd, SOL_UDP, UDP_SEGMENT, &gso_size, sizeof(gso_size)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+#endif /* WITH_GSO */
+
+#ifdef WITH_GRO
+ if (setsockopt(fd, IPPROTO_UDP, UDP_GRO, &(int){1}, sizeof(int)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+#endif /* WITH_GRO */
+
+#ifdef WITH_ZEROCOPY
+ if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &(int){1}, sizeof(int))) {
+ perror("setsockopt");
+ return -1;
+ }
+#endif /* WITH_ZEROCOPY */
+
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &(int){BATCH_SOCKET_BUFFER},
+ sizeof(int)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &(int){BATCH_SOCKET_BUFFER},
+ sizeof(int)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+ return 0;
+}
+
+#ifdef __linux__
+/* bind to device */
+int socket_bind_to_device(int fd, const char *interface_name) {
+ if (strncmp("lo", interface_name, 2) == 0) return 0;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, interface_name,
+ strnlen_s(interface_name, IFNAMSIZ)) < 0) {
+ perror("setsockopt");
+ goto ERR_BIND_TO_DEVICE;
+ }
+
+ return 0;
+
+ERR_BIND_TO_DEVICE:
+#ifdef __ANDROID__
+ if (bindSocket(fd, interface_name) < 0) return -1;
+ return 0;
+#else
+ return -1;
+#endif /* __ANDROID__ */
+}
+#endif /* __linux__ */
+
+static int listener_udp_initialize(listener_t *listener) {
+ assert(listener);
+
+#if 0
+ listener_udp_data_t * data = listener->data;
+ assert(data);
+#endif
+ return 0;
+}
+
+static void listener_udp_finalize(listener_t *listener) {
+ assert(listener);
+ assert(listener->type == FACE_TYPE_UDP_LISTENER);
+
+ return;
+}
+
+static int listener_udp_punt(const listener_t *listener, const char *prefix_s) {
+ return -1;
+}
+
+static int listener_udp_get_socket(const listener_t *listener,
+ const address_t *local,
+ const address_t *remote,
+ const char *interface_name) {
+ int fd = socket(address_family(local), SOCK_DGRAM, 0);
+ if (fd < 0) goto ERR_SOCKET;
+
+ if (socket_set_options(fd) < 0) {
+ goto ERR;
+ }
+
+ if (bind(fd, address_sa(local), address_socklen(local)) < 0) {
+ perror("bind");
+ goto ERR;
+ }
+
+#ifdef __linux__
+ if (socket_bind_to_device(fd, interface_name) < 0) {
+ goto ERR;
+ }
+#endif /* __linux__ */
+
+ // DEBUG("UDP remote ?");
+ if (remote) {
+ // DEBUG("UDP connected socket ");
+ if (connect(fd, address_sa(remote), address_socklen(remote)) < 0) {
+ perror("connect");
+ goto ERR;
+ }
+ }
+
+ return fd;
+
+ERR:
+#ifndef _WIN32
+ close(fd);
+#else
+ closesocket(fd);
+#endif
+ERR_SOCKET:
+ return -1;
+}
+
+#define listener_udp_read_single io_read_single_socket
+
+#ifdef __linux__
+#define listener_udp_read_batch io_read_batch_socket
+#else
+#define listener_udp_read_batch NULL
+#endif /* __linux__ */
+
+DECLARE_LISTENER(udp);
+
+/******************************************************************************
+ * Connection
+ ******************************************************************************/
+
+#define RING_LEN 5 * MAX_MSG
+
+typedef struct {
+ /*
+ * Ring buffer
+ *
+ * This is sized to more than a batch to cope with transient failures of
+ * sendmmsg.
+ */
+ off_t *ring;
+
+#ifdef __linux__
+ struct mmsghdr msghdr[MAX_MSG];
+ struct iovec iovecs[MAX_MSG];
+#endif /* __linux__ */
+} connection_udp_data_t;
+
+static int connection_udp_initialize(connection_t *connection) {
+ assert(connection);
+ assert(connection->type == FACE_TYPE_UDP);
+ assert(connection->interface_name);
+
+#ifdef __linux__
+ connection_udp_data_t *data = connection->data;
+ assert(data);
+
+ ring_init(data->ring, RING_LEN);
+
+ void *name = NULL;
+ int namelen = 0;
+
+ /*
+ * If the connection does not use a connected socket, we need to set the
+ * different destination addresses
+ */
+ if (!connection->connected) {
+ const address_t *remote = connection_get_remote(connection);
+ name = address_sa(remote);
+ namelen = address_socklen(remote);
+ }
+
+ memset(data->msghdr, 0, MAX_MSG * sizeof(struct mmsghdr));
+ for (unsigned i = 0; i < MAX_MSG; i++) {
+ struct mmsghdr *msg = &data->msghdr[i];
+ *msg = (struct mmsghdr){
+ .msg_hdr =
+ {
+ .msg_iov = &data->iovecs[i],
+ .msg_iovlen = 1,
+ .msg_name = name,
+ .msg_namelen = namelen,
+#if 0
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0,
+#endif
+ },
+ };
+ }
+#endif /* __linux__ */
+
+ return 0;
+}
+
+static void connection_udp_finalize(connection_t *connection) {
+ assert(connection);
+ assert(connection->type == FACE_TYPE_UDP);
+
+ connection_udp_data_t *data = connection->data;
+ assert(data);
+
+ ring_free(data->ring);
+}
+
+static bool connection_udp_flush(const connection_t *connection) {
+#ifdef __linux__
+ int retry = 0;
+ off_t msgbuf_id = 0;
+ unsigned cpt;
+ size_t i;
+ int n;
+
+ assert(connection);
+ forwarder_t *forwarder = listener_get_forwarder(connection->listener);
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ connection_udp_data_t *data = connection->data;
+ assert(data);
+
+ TRACE("[connection_udp_send] Flushing connection queue");
+
+ /* Flush operation */
+#ifdef WITH_ZEROCOPY
+ int flags = MSG_ZEROCOPY;
+#else
+ int flags = 0;
+#endif /* WITH_ZEROCOPY */
+
+SEND:
+ /* Consume up to MSG_MSG packets in ring buffer */
+ cpt = 0;
+
+ ring_enumerate_n(data->ring, i, &msgbuf_id, MAX_MSG, {
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+
+ // update path label
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
+ msgbuf_update_pathlabel(msgbuf, connection_get_id(connection));
+
+ data->iovecs[i].iov_base = msgbuf_get_packet(msgbuf);
+ data->iovecs[i].iov_len = msgbuf_get_len(msgbuf);
+ cpt++;
+ });
+
+SENDMMSG:
+ n = sendmmsg(connection->fd, data->msghdr, cpt, flags);
+ if (n == -1) {
+ /* man(2)sendmmsg / BUGS
+ *
+ * If an error occurs after at least one message has been sent, the call
+ * succeeds, and returns the number of messages sent. The error code is
+ * lost. The caller can retry the transmission, starting at the first
+ * failed message, but there is no guarantee that, if an error is
+ * returned, it will be the same as the one that was lost on the previous
+ * call.
+ */
+ WARN("sendmmsg failed %s", strerror(errno));
+ if (retry < 1) {
+ retry++;
+ goto SENDMMSG;
+ }
+ return false;
+ }
+
+ ring_advance(data->ring, n);
+
+ if (n < cpt) {
+ WARN("Unknown error after sending n=%d packets...", n);
+ if (retry < 1) {
+ retry++;
+ goto SEND;
+ }
+ }
+
+ if (ring_get_size(data->ring) > 0) {
+ retry = 0;
+ goto SEND;
+ }
+#endif /* __linux__ */
+ return true;
+}
+
+/**
+ * @function metisUdpConnection_Send
+ * @abstract Non-destructive send of the message.
+ * @discussion
+ * sends a message to the peer.
+ *
+ * @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) {
+ assert(connection);
+ assert(msgbuf);
+
+#ifdef __linux__
+ connection_udp_data_t *data = connection->data;
+ assert(data);
+
+ forwarder_t *forwarder = listener_get_forwarder(connection->listener);
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+
+ /* Queue packet ? */
+ if (queue) {
+ off_t msgbuf_id;
+ if (ring_is_full(data->ring)) connection_udp_flush(connection);
+
+ msgbuf_id = msgbuf_pool_get_id(msgbuf_pool, msgbuf);
+ ring_add(data->ring, &msgbuf_id);
+
+ } else {
+#endif /* __linux__ */
+ /* Send one */
+ // update the path label befor send the packet
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
+ msgbuf_update_pathlabel(msgbuf, connection_get_id(connection));
+
+ ssize_t writeLength = write(connection->fd, msgbuf_get_packet(msgbuf),
+ msgbuf_get_len(msgbuf));
+
+ if (writeLength < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ return false;
+ } else {
+ // this print is for debugging
+ printf("Incorrect write length %zd, expected %u: (%d) %s\n",
+ writeLength, msgbuf_get_len(msgbuf), errno, strerror(errno));
+ return false;
+ }
+ }
+#ifdef __linux__
+ }
+#endif /* __linux__ */
+
+ return true;
+}
+
+#if 0
+static
+bool
+connection_udp_sendv(const connection_t * connection, struct iovec * iov,
+ size_t size)
+{
+
+ assert(connetion);
+ assert(iov);
+
+ connection_udp_data_t * data = connection->data;
+ assert(data);
+
+#ifndef _WIN32
+ // Perform connect before to establish association between this peer and
+ // the remote peer. This is required to use writev.
+ // Connection association can be changed at any time.
+
+ if (writev(connection->fd, iov, (int)size) < 0)
+ return false;
+#else
+ WSABUF *buf = (WSABUF *) malloc(size * sizeof(WSABUF));
+
+ DWORD bytes_sent = 0;
+
+ for (int i = 0; i < size; i++) {
+ buf[i].buf = iov[i].iov_base;
+ buf[i].len = (ULONG)iov[i].iov_len;
+ }
+
+ int rc = WSASendTo(udp->fd, buf, size, &bytes_sent, 0,
+ (SOCKADDR *)address_sa(address_pair_remote(&udp->pair)),
+ address_socklen(address_pair_remote(&udp->pair)), NULL, NULL);
+ free(dataBuf);
+ if (rc == SOCKET_ERROR)
+ return false;
+#endif
+
+ return true;
+}
+#endif
+
+static int connection_udp_send_packet(const connection_t *connection,
+ const uint8_t *packet, size_t size) {
+ assert(connection);
+ assert(packet);
+
+ // XXX: in case of two connections this functions may have wrong behaviour. We
+ // noticed that the packet is sent by the forwarder on the right socket (fd)
+ // but from tcpdump we see that the packet goes on the other connection. In
+ // other cases the packet is sent twice, first on the wrong socket and later
+ // on the right one, even if we log a single send from the forwarder. The
+ // same behaviour was observed with the write executed in the function
+ // connection_udp_send with the queue flag set to false. A workaround that
+ // seems to solve the problem is to use connection_udp_send with queue = true
+ // and force the flush of the connection if needed.
+
+ // TODO: commented otherwise unable to do tests locally
+ // if(connection_is_local(connection))
+ // return -1;
+
+#ifdef USE_CONNECTED_SOCKETS
+ ssize_t n = send(connection->fd, packet, size, 0);
+ if (n < 0) {
+ perror("sendto");
+ return -1;
+ }
+#else
+ const address_t *remote = connection_get_remote(connection);
+ ssize_t n = sendto(connection->fd, packet, size, 0, address_sa(remote),
+ address_socklen(remote));
+ if (n < 0) return -1;
+#endif
+
+ return 0;
+}
+
+#define connection_udp_read_single \
+ listener_read_batch_socket listener_single_socket
+
+#ifdef __linux__
+#define connection_udp_read_batch listener_read_batch_socket
+#else
+#define connection_udp_read_batch NULL
+#endif /* __linux__ */
+
+DECLARE_CONNECTION(udp);
diff --git a/hicn-light/src/hicn/io/udpConnection.c b/hicn-light/src/hicn/io/udpConnection.c
deleted file mode 100644
index 2747b7ef4..000000000
--- a/hicn-light/src/hicn/io/udpConnection.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Embodies the reader/writer for a UDP connection
- *
- * NB The Send() function may overflow the output buffer
- *
- */
-
-#ifndef _WIN32
-#include <sys/uio.h>
-#endif
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <hicn/core/messageHandler.h>
-#include <hicn/io/udpConnection.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/message.h>
-
-typedef struct udp_state {
- Forwarder *forwarder;
- char * interfaceName;
- Logger *logger;
-
- // the udp listener socket we receive packets on
- int udpListenerSocket;
-
- AddressPair *addressPair;
-
- // We need to access this all the time, so grab it out
- // of the addressPair;
- struct sockaddr *peerAddress;
- socklen_t peerAddressLength;
-
- bool isLocal;
- bool isUp;
- unsigned id;
-
- unsigned delay;
-
- /* This information would better be stored in the connection data structure
- * but it is currently not reachable from within the implementation. */
- connection_state_t state;
- connection_state_t admin_state;
-#ifdef WITH_POLICY
- uint32_t priority;
-#endif /* WITH_POLICY */
-} _UdpState;
-
-// Prototypes
-static bool _send(IoOperations *ops, const Address *nexthop, Message *message);
-static bool _sendIOVBuffer(IoOperations *ops, struct iovec *message,
- size_t size);
-static const Address *_getRemoteAddress(const IoOperations *ops);
-static const AddressPair *_getAddressPair(const IoOperations *ops);
-static unsigned _getConnectionId(const IoOperations *ops);
-static bool _isUp(const IoOperations *ops);
-static bool _isLocal(const IoOperations *ops);
-static void _destroy(IoOperations **opsPtr);
-static list_connections_type _getConnectionType(const IoOperations *ops);
-static void _sendProbe(IoOperations *ops, uint8_t *message);
-static connection_state_t _getState(const IoOperations *ops);
-static void _setState(IoOperations *ops, connection_state_t state);
-static connection_state_t _getAdminState(const IoOperations *ops);
-static void _setAdminState(IoOperations *ops, connection_state_t admin_state);
-#ifdef WITH_POLICY
-static uint32_t _getPriority(const IoOperations *ops);
-static void _setPriority(IoOperations *ops, uint32_t priority);
-#endif /* WITH_POLICY */
-static const char * _getInterfaceName(const IoOperations *ops);
-
-/*
- * This assigns a unique pointer to the void * which we use
- * as a GUID for this class.
- */
-static const void *_IoOperationsGuid = __FILE__;
-
-/*
- * Return our GUID
- */
-static const void *_streamConnection_Class(const IoOperations *ops) {
- return _IoOperationsGuid;
-}
-
-static IoOperations _template = {
- .closure = NULL,
- .send = &_send,
- .sendIOVBuffer = &_sendIOVBuffer,
- .getRemoteAddress = &_getRemoteAddress,
- .getAddressPair = &_getAddressPair,
- .getConnectionId = &_getConnectionId,
- .isUp = &_isUp,
- .isLocal = &_isLocal,
- .destroy = &_destroy,
- .class = &_streamConnection_Class,
- .getConnectionType = &_getConnectionType,
- .sendProbe = &_sendProbe,
- .getState = &_getState,
- .setState = &_setState,
- .getAdminState = &_getAdminState,
- .setAdminState = &_setAdminState,
-#ifdef WITH_POLICY
- .getPriority = &_getPriority,
- .setPriority = &_setPriority,
-#endif /* WITH_POLICY */
- .getInterfaceName = &_getInterfaceName,
-};
-
-// =================================================================
-
-static void _setConnectionState(_UdpState *Udp, bool isUp);
-static bool _saveSockaddr(_UdpState *udpConnState, const AddressPair *pair);
-
-IoOperations *udpConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
- const AddressPair *pair, bool isLocal) {
- IoOperations *io_ops = NULL;
-
- _UdpState *udpConnState = parcMemory_AllocateAndClear(sizeof(_UdpState));
- parcAssertNotNull(udpConnState,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(_UdpState));
-
- udpConnState->forwarder = forwarder;
- udpConnState->interfaceName = strdup(interfaceName);
- udpConnState->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- bool saved = _saveSockaddr(udpConnState, pair);
- if (saved) {
- udpConnState->udpListenerSocket = fd;
- udpConnState->id = forwarder_GetNextConnectionId(forwarder);
- udpConnState->addressPair = addressPair_Acquire(pair);
- udpConnState->isLocal = isLocal;
-
- // allocate a connection
- io_ops = parcMemory_AllocateAndClear(sizeof(IoOperations));
- parcAssertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(IoOperations));
- memcpy(io_ops, &_template, sizeof(IoOperations));
- io_ops->closure = udpConnState;
-
- _setConnectionState(udpConnState, true);
-
-#ifdef WITH_POLICY
- udpConnState->priority = 0;
-#endif /* WITH_POLICY */
-
- if (logger_IsLoggable(udpConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Info)) {
- char *str = addressPair_ToString(udpConnState->addressPair);
- logger_Log(udpConnState->logger, LoggerFacility_IO, PARCLogLevel_Info,
- __func__,
- "UdpConnection %p created for address %s (isLocal %d)",
- (void *)udpConnState, str, udpConnState->isLocal);
- free(str);
- }
-
- messenger_Send(
- forwarder_GetMessenger(forwarder),
- missive_Create(MissiveType_ConnectionCreate, udpConnState->id));
- messenger_Send(forwarder_GetMessenger(forwarder),
- missive_Create(MissiveType_ConnectionUp, udpConnState->id));
- } else {
- // _saveSockaddr will already log an error, no need for extra log message
- // here
- logger_Release(&udpConnState->logger);
-
- free(udpConnState->interfaceName);
- parcMemory_Deallocate((void **)&udpConnState);
- }
-
- return io_ops;
-}
-
-// =================================================================
-// I/O Operations implementation
-
-static void _destroy(IoOperations **opsPtr) {
- parcAssertNotNull(opsPtr, "Parameter opsPtr must be non-null double pointer");
- parcAssertNotNull(*opsPtr,
- "Parameter opsPtr must dereference to non-null pointer");
-
- IoOperations *ops = *opsPtr;
- parcAssertNotNull(ioOperations_GetClosure(ops),
- "ops->context must not be null");
-
- _UdpState *udpConnState = (_UdpState *)ioOperations_GetClosure(ops);
- addressPair_Release(&udpConnState->addressPair);
- parcMemory_Deallocate((void **)&(udpConnState->peerAddress));
-
- messenger_Send(
- forwarder_GetMessenger(udpConnState->forwarder),
- missive_Create(MissiveType_ConnectionDestroyed, udpConnState->id));
-
- if (logger_IsLoggable(udpConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Info)) {
- logger_Log(udpConnState->logger, LoggerFacility_IO, PARCLogLevel_Info,
- __func__, "UdpConnection %p destroyed", (void *)udpConnState);
- }
-
- // do not close udp->udpListenerSocket, the listener will close
- // that when its done
-
- logger_Release(&udpConnState->logger);
- free(udpConnState->interfaceName);
- parcMemory_Deallocate((void **)&udpConnState);
- parcMemory_Deallocate((void **)&ops);
-
- *opsPtr = NULL;
-}
-
-static bool _isUp(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->isUp;
-}
-
-static bool _isLocal(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->isLocal;
-}
-
-static const Address *_getRemoteAddress(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return addressPair_GetRemote(udpConnState->addressPair);
-}
-
-static const AddressPair *_getAddressPair(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->addressPair;
-}
-
-static unsigned _getConnectionId(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->id;
-}
-
-/**
- * @function metisUdpConnection_Send
- * @abstract Non-destructive send of the message.
- * @discussion
- * sends a message to the peer.
- *
- * @param dummy is ignored. A udp connection has only one peer.
- * @return <#return#>
- */
-static bool _send(IoOperations *ops, const Address *dummy, Message *message) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- _UdpState *udpConnState = (_UdpState *)ioOperations_GetClosure(ops);
-
- // NAT for HICN
- // in this particular connection we don't need natting beacause we send the
- // packet to the next hop using upd connection
-
- ssize_t writeLength =
- sendto(udpConnState->udpListenerSocket, message_FixedHeader(message),
- (int)message_Length(message), 0, udpConnState->peerAddress,
- udpConnState->peerAddressLength);
-
- if (writeLength < 0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- return false;
- } else {
- // this print is for debugging
- printf("Incorrect write length %zd, expected %zd: (%d) %s\n", writeLength,
- message_Length(message), errno, strerror(errno));
- return false;
- }
- }
-
- return true;
-}
-
-static bool _sendIOVBuffer(IoOperations *ops, struct iovec *message,
- size_t size) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- _UdpState *udpConnState = (_UdpState *)ioOperations_GetClosure(ops);
-
-#ifndef _WIN32
- // Perform connect before to establish association between this peer and
- // the remote peer. This is required to use writev.
- // Connection association can be changed at any time.
- connect(udpConnState->udpListenerSocket,
- udpConnState->peerAddress,
- udpConnState->peerAddressLength);
-
- ssize_t writeLength = writev(udpConnState->udpListenerSocket, message, (int)size);
-
- struct sockaddr any_address = {0};
- any_address.sa_family = AF_UNSPEC;
- connect(udpConnState->udpListenerSocket,
- &any_address, (socklen_t)sizeof(any_address));
-
- if (writeLength < 0) {
- return false;
- }
-#else
-
- WSABUF *dataBuf = (WSABUF *) malloc(size * sizeof (dataBuf));
- DWORD BytesSent = 0;
-
- for (int i = 0; i < size; i++) {
- dataBuf[i].buf = message[i].iov_base;
- dataBuf[i].len = (ULONG)message[i].iov_len;
- }
-
- int rc = WSASendTo(udpConnState->udpListenerSocket, dataBuf, (DWORD)size,
- &BytesSent, 0, (SOCKADDR *)udpConnState->peerAddress,
- udpConnState->peerAddressLength, NULL, NULL);
- free(dataBuf);
- if (rc == SOCKET_ERROR) {
- return false;
- }
-#endif
- return true;
-}
-
-static list_connections_type _getConnectionType(const IoOperations *ops) {
- return CONN_UDP;
-}
-
-static void _sendProbe(IoOperations *ops, uint8_t *message) {
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
- _UdpState *udpConnState = (_UdpState *)ioOperations_GetClosure(ops);
-
- if(udpConnState->isLocal)
- return;
-
- ssize_t writeLength =
- sendto(udpConnState->udpListenerSocket, message,
- messageHandler_GetTotalPacketLength(message), 0, udpConnState->peerAddress,
- udpConnState->peerAddressLength);
-
- if (writeLength < 0) {
- return;
- }
-}
-
-// =================================================================
-// Internal API
-
-static bool _saveSockaddr(_UdpState *udpConnState, const AddressPair *pair) {
- bool success = false;
- const Address *remoteAddress = addressPair_GetRemote(pair);
-
- switch (addressGetType(remoteAddress)) {
- case ADDR_INET: {
- size_t bytes = sizeof(struct sockaddr_in);
- udpConnState->peerAddress = parcMemory_Allocate(bytes);
- parcAssertNotNull(udpConnState->peerAddress,
- "parcMemory_Allocate(%zu) returned NULL", bytes);
-
- addressGetInet(remoteAddress,
- (struct sockaddr_in *)udpConnState->peerAddress);
- udpConnState->peerAddressLength = (socklen_t)bytes;
-
- success = true;
- break;
- }
-
- case ADDR_INET6: {
- size_t bytes = sizeof(struct sockaddr_in6);
- udpConnState->peerAddress = parcMemory_Allocate(bytes);
- parcAssertNotNull(udpConnState->peerAddress,
- "parcMemory_Allocate(%zu) returned NULL", bytes);
-
- addressGetInet6(remoteAddress,
- (struct sockaddr_in6 *)udpConnState->peerAddress);
- udpConnState->peerAddressLength = (socklen_t)bytes;
-
- success = true;
- break;
- }
-
- default:
- if (logger_IsLoggable(udpConnState->logger, LoggerFacility_IO,
- PARCLogLevel_Error)) {
- char *str = addressToString(remoteAddress);
- logger_Log(udpConnState->logger, LoggerFacility_IO, PARCLogLevel_Error,
- __func__, "Remote address is not INET or INET6: %s", str);
- parcMemory_Deallocate((void **)&str);
- }
- break;
- }
- return success;
-}
-
-static void _setConnectionState(_UdpState *udpConnState, bool isUp) {
- parcAssertNotNull(udpConnState, "Parameter Udp must be non-null");
-
- Messenger *messenger = forwarder_GetMessenger(udpConnState->forwarder);
-
- bool oldStateIsUp = udpConnState->isUp;
- udpConnState->isUp = isUp;
-
- if (oldStateIsUp && !isUp) {
- // bring connection DOWN
- Missive *missive =
- missive_Create(MissiveType_ConnectionDown, udpConnState->id);
- messenger_Send(messenger, missive);
- return;
- }
-
- if (!oldStateIsUp && isUp) {
- // bring connection UP
- Missive *missive =
- missive_Create(MissiveType_ConnectionUp, udpConnState->id);
- messenger_Send(messenger, missive);
- return;
- }
-}
-
-static connection_state_t _getState(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->state;
-}
-
-static void _setState(IoOperations *ops, connection_state_t state) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _UdpState *udpConnState =
- (_UdpState *)ioOperations_GetClosure(ops);
- udpConnState->state = state;
-}
-
-static connection_state_t _getAdminState(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->admin_state;
-}
-
-static void _setAdminState(IoOperations *ops, connection_state_t admin_state) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _UdpState *udpConnState =
- (_UdpState *)ioOperations_GetClosure(ops);
- udpConnState->admin_state = admin_state;
-}
-
-#ifdef WITH_POLICY
-static uint32_t _getPriority(const IoOperations *ops) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- const _UdpState *udpConnState =
- (const _UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->priority;
-}
-
-static void _setPriority(IoOperations *ops, uint32_t priority) {
- parcAssertNotNull(ops, "Parameter must be non-null");
- _UdpState *udpConnState =
- (_UdpState *)ioOperations_GetClosure(ops);
- udpConnState->priority = priority;
-}
-#endif /* WITH_POLICY */
-
-static const char * _getInterfaceName(const IoOperations *ops)
-{
- parcAssertNotNull(ops, "Parameter must be non-null");
- _UdpState *udpConnState =
- (_UdpState *)ioOperations_GetClosure(ops);
- return udpConnState->interfaceName;
-}
diff --git a/hicn-light/src/hicn/io/udpConnection.h b/hicn-light/src/hicn/io/udpConnection.h
deleted file mode 100644
index 9fbc5348b..000000000
--- a/hicn-light/src/hicn/io/udpConnection.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file udpConnection.h
- * @brief Represents a UDP connection (socket) for the connection table
- *
- * <#Detailed Description#>
- *
- */
-
-#ifndef udpConnection_h
-#define udpConnection_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/utils/address.h>
-
-/**
- * Creates a UDP connection that can send to the remote address
- *
- * The address pair must both be same type (i.e. INET or INET6).
- *
- * @param [in] metis An allocated MetisForwarder (saves reference)
- * @param [in] fd The socket to use
- * @param [in] pair An allocated address pair for the connection (saves
- * reference)
- * @param [in] isLocal determines if the remote address is on the current system
- *
- * @retval non-null An allocated Io operations
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-IoOperations *udpConnection_Create(Forwarder *forwarder, const char * interfaceName, int fd,
- const AddressPair *pair, bool isLocal);
-#endif // udpConnection_h
diff --git a/hicn-light/src/hicn/io/udpListener.c b/hicn-light/src/hicn/io/udpListener.c
deleted file mode 100644
index 3b318c500..000000000
--- a/hicn-light/src/hicn/io/udpListener.c
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <hicn/core/messageHandler.h>
-
-#include <hicn/io/udpConnection.h>
-#include <hicn/io/udpListener.h>
-
-#include <parc/algol/parc_Network.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/connection.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/messagePacketType.h>
-
-#define IPv4 4
-#define IPv6 6
-
-struct udp_listener {
- char *listenerName;
- Forwarder *forwarder;
- Logger *logger;
-
- PARCEvent *udp_event;
- SocketType udp_socket;
- uint16_t port;
-
- unsigned id;
- char *interfaceName;
- Address *localAddress;
-};
-
-static void _destroy(ListenerOps **listenerOpsPtr);
-static const char *_getListenerName(const ListenerOps *ops);
-static unsigned _getInterfaceIndex(const ListenerOps *ops);
-static const Address *_getListenAddress(const ListenerOps *ops);
-static EncapType _getEncapType(const ListenerOps *ops);
-static const char *_getInterfaceName(const ListenerOps *ops);
-static int _getSocket(const ListenerOps *ops);
-static unsigned _createNewConnection(ListenerOps *listener, int fd, const AddressPair *pair);
-static const Connection * _lookupConnection(ListenerOps * listener, const AddressPair *pair);
-
-static ListenerOps udpTemplate = {
- .context = NULL,
- .destroy = &_destroy,
- .getInterfaceIndex = &_getInterfaceIndex,
- .getListenAddress = &_getListenAddress,
- .getEncapType = &_getEncapType,
- .getSocket = &_getSocket,
- .getListenerName = &_getListenerName,
- .createConnection = &_createNewConnection,
- .lookupConnection = &_lookupConnection,
- .getInterfaceName = &_getInterfaceName,
-};
-
-
-static void _readcb(int fd, PARCEventType what, void * listener_void);
-
-#ifdef __ANDROID__
-extern int bindSocket(int sock, const char* ifname);
-#endif
-
-ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in6 sin6, const char *interfaceName) {
- ListenerOps *ops = NULL;
-
- UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener));
- parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(UdpListener));
- udp->forwarder = forwarder;
- udp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
- udp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
- udp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- udp->localAddress = addressCreateFromInet6(&sin6);
- udp->id = forwarder_GetNextConnectionId(forwarder);
-
- udp->udp_socket = (SocketType)socket(AF_INET6, SOCK_DGRAM, 0);
- parcAssertFalse(udp->udp_socket < 0, "Error opening UDP socket: (%d) %s",
- errno, strerror(errno));
-
- int failure = 0;
-#ifndef _WIN32
- // Set non-blocking flag
- int flags = fcntl(udp->udp_socket, F_GETFL, NULL);
- parcAssertTrue(flags != -1,
- "fcntl failed to obtain file descriptor flags (%d)", errno);
- failure = fcntl(udp->udp_socket, F_SETFL, flags | O_NONBLOCK);
- parcAssertFalse(failure, "fcntl failed to set file descriptor flags (%d)",
- errno);
-#else
- // Set non-blocking flag
- u_long mode = 1;
- int result = ioctlsocket(udp->udp_socket, FIONBIO, &mode);
- if (result != NO_ERROR) {
- parcAssertTrue(result != NO_ERROR,
- "ioctlsocket failed to set file descriptor");
- }
-#endif
-
- int one = 1;
- // don't hang onto address after listener has closed
- failure = setsockopt(udp->udp_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
- (socklen_t)sizeof(one));
- parcAssertFalse(failure, "failed to set REUSEADDR on socket(%d)", errno);
-
- failure = bind(udp->udp_socket, (struct sockaddr *)&sin6, sizeof(sin6));
-
- if (failure == 0) {
-#ifdef __linux__
- if (strncmp("lo", interfaceName, 2) != 0) {
- int ret = setsockopt(udp->udp_socket, SOL_SOCKET, SO_BINDTODEVICE,
- interfaceName, strlen(interfaceName) + 1);
- if (ret < 0) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "setsockopt(%d, SO_BINDTODEVICE, %s) failed (%d) %s",
- udp->udp_socket, interfaceName, errno, strerror(errno));
-#ifdef __ANDROID__
- ret = bindSocket(udp->udp_socket, interfaceName);
- if (ret < 0) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "bindSocket(%d, %s) failed", udp->udp_socket, interfaceName);
- close(udp->udp_socket);
- addressDestroy(&udp->localAddress);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- return NULL;
- } else {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "bindSocket(%d, %s) success", udp->udp_socket, interfaceName);
- }
-#else
- close(udp->udp_socket);
- addressDestroy(&udp->localAddress);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- return NULL;
-#endif
- }
- }
-#endif
-
- ops = parcMemory_AllocateAndClear(sizeof(ListenerOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerOps));
- memcpy(ops, &udpTemplate, sizeof(ListenerOps));
- ops->context = udp;
-
- udp->udp_event =
- dispatcher_CreateNetworkEvent(forwarder_GetDispatcher(forwarder), true,
- _readcb, (void*)ops, udp->udp_socket);
- dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder),
- udp->udp_event);
-
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- char *str = addressToString(udp->localAddress);
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "UdpListener %p created for address %s", (void *)udp, str);
- parcMemory_Deallocate((void **)&str);
- }
- } else {
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- int myerrno = errno;
- char *str = addressToString(udp->localAddress);
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Error binding UDP socket to address %s: (%d) %s", str,
- myerrno, strerror(myerrno));
- parcMemory_Deallocate((void **)&str);
- }
- parcMemory_Deallocate((void **)&udp->listenerName);
- parcMemory_Deallocate((void **)&udp->interfaceName);
-#ifndef _WIN32
- close(udp->udp_socket);
-#else
- closesocket(udp->udp_socket);
-#endif
- addressDestroy(&udp->localAddress);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- }
-
- return ops;
-}
-
-ListenerOps *udpListener_CreateInet(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in sin, const char *interfaceName) {
- ListenerOps *ops = NULL;
-
- UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener));
- parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(UdpListener));
- udp->forwarder = forwarder;
- udp->listenerName = parcMemory_StringDuplicate(listenerName, strlen(listenerName));
- udp->interfaceName = parcMemory_StringDuplicate(interfaceName, strlen(interfaceName));
- udp->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- udp->localAddress = addressCreateFromInet(&sin);
- udp->id = forwarder_GetNextConnectionId(forwarder);
-
- udp->udp_socket = (SocketType)socket(AF_INET, SOCK_DGRAM, 0);
- parcAssertFalse(udp->udp_socket < 0, "Error opening UDP socket: (%d) %s",
- errno, strerror(errno));
-
- int failure = 0;
-#ifndef _WIN32
- // Set non-blocking flag
- int flags = fcntl(udp->udp_socket, F_GETFL, NULL);
- parcAssertTrue(flags != -1,
- "fcntl failed to obtain file descriptor flags (%d)", errno);
- failure = fcntl(udp->udp_socket, F_SETFL, flags | O_NONBLOCK);
- parcAssertFalse(failure, "fcntl failed to set file descriptor flags (%d)",
- errno);
-#else
- u_long mode = 1;
- int result = ioctlsocket(udp->udp_socket, FIONBIO, &mode);
- if (result != NO_ERROR) {
- parcAssertTrue(result != NO_ERROR,
- "ioctlsocket failed to set file descriptor");
- }
-#endif
-
- int one = 1;
- // don't hang onto address after listener has closed
- failure = setsockopt(udp->udp_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
- (socklen_t)sizeof(one));
- parcAssertFalse(failure, "failed to set REUSEADDR on socket(%d)", errno);
-
- failure = bind(udp->udp_socket, (struct sockaddr *)&sin, sizeof(sin));
- if (failure == 0) {
-#ifdef __linux__
- if (strncmp("lo", interfaceName, 2) != 0) {
- int ret = setsockopt(udp->udp_socket, SOL_SOCKET, SO_BINDTODEVICE,
- interfaceName, strlen(interfaceName) + 1);
- if (ret < 0) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "setsockopt(%d, SO_BINDTODEVICE, %s) failed (%d) %s",
- udp->udp_socket, interfaceName, errno, strerror(errno));
-#ifdef __ANDROID__
- ret = bindSocket(udp->udp_socket, interfaceName);
- if (ret < 0) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "bindSocket(%d, %s) failed", udp->udp_socket, interfaceName);
- close(udp->udp_socket);
- addressDestroy(&udp->localAddress);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- return NULL;
- } else {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "bindSocket(%d, %s) success", udp->udp_socket, interfaceName);
- }
-#else
- close(udp->udp_socket);
- addressDestroy(&udp->localAddress);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- return NULL;
-#endif
- }
- }
-#endif
- ops = parcMemory_AllocateAndClear(sizeof(ListenerOps));
- parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListenerOps));
- memcpy(ops, &udpTemplate, sizeof(ListenerOps));
- ops->context = udp;
-
- udp->udp_event =
- dispatcher_CreateNetworkEvent(forwarder_GetDispatcher(forwarder), true,
- _readcb, (void *)ops, udp->udp_socket);
- dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder),
- udp->udp_event);
-
-
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- char *str = addressToString(udp->localAddress);
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "UdpListener %p created for address %s", (void *)udp, str);
- parcMemory_Deallocate((void **)&str);
- }
- } else {
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- int myerrno = errno;
- char *str = addressToString(udp->localAddress);
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Error binding UDP socket to address %s: (%d) %s", str,
- myerrno, strerror(myerrno));
- parcMemory_Deallocate((void **)&str);
- }
- parcMemory_Deallocate((void **)&udp->listenerName);
- parcMemory_Deallocate((void **)&udp->interfaceName);
-#ifndef _WIN32
- close(udp->udp_socket);
-#else
- closesocket(udp->udp_socket);
-#endif
- addressDestroy(&udp->localAddress);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- }
-
- return ops;
-}
-
-static void udpListener_Destroy(UdpListener **listenerPtr) {
- parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listenerPtr,
- "Parameter must derefernce to non-null pointer");
-
- UdpListener *udp = *listenerPtr;
-
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "UdpListener %p destroyed", (void *)udp);
- }
-
- parcMemory_Deallocate((void **)&udp->listenerName);
- parcMemory_Deallocate((void **)&udp->interfaceName);
-#ifndef _WIN32
- close(udp->udp_socket);
-#else
- closesocket(udp->udp_socket);
-#endif
-
- addressDestroy(&udp->localAddress);
- dispatcher_DestroyNetworkEvent(forwarder_GetDispatcher(udp->forwarder),
- &udp->udp_event);
- logger_Release(&udp->logger);
- parcMemory_Deallocate((void **)&udp);
- *listenerPtr = NULL;
-}
-
-static const char *_getListenerName(const ListenerOps *ops) {
- UdpListener *udp = (UdpListener *)ops->context;
- return udp->listenerName;
-}
-
-static const char *_getInterfaceName(const ListenerOps *ops) {
- UdpListener *udp = (UdpListener *)ops->context;
- return udp->interfaceName;
-}
-
-static void _destroy(ListenerOps **listenerOpsPtr) {
- ListenerOps *ops = *listenerOpsPtr;
- UdpListener *udp = (UdpListener *)ops->context;
- udpListener_Destroy(&udp);
- parcMemory_Deallocate((void **)&ops);
- *listenerOpsPtr = NULL;
-}
-
-static unsigned _getInterfaceIndex(const ListenerOps *ops) {
- UdpListener *udp = (UdpListener *)ops->context;
- return udp->id;
-}
-
-static const Address *_getListenAddress(const ListenerOps *ops) {
- UdpListener *udp = (UdpListener *)ops->context;
- return udp->localAddress;
-}
-
-static EncapType _getEncapType(const ListenerOps *ops) { return ENCAP_UDP; }
-
-static int _getSocket(const ListenerOps *ops) {
- UdpListener *udp = (UdpListener *)ops->context;
- return (int)udp->udp_socket;
-}
-
-// =====================================================================
-
-/**
- * @function _constructAddressPair
- * @abstract Creates the address pair that uniquely identifies the connection
- * @discussion
- * The peerIpAddress must be of AF_INET or AF_INET6 family.
- *
- * @param <#param1#>
- * @return Allocated MetisAddressPair, must be destroyed
- */
-static AddressPair *_constructAddressPair(UdpListener *udp,
- struct sockaddr *peerIpAddress,
- socklen_t peerIpAddressLength) {
- Address *remoteAddress;
-
- switch (peerIpAddress->sa_family) {
- case AF_INET:
- remoteAddress =
- addressCreateFromInet((struct sockaddr_in *)peerIpAddress);
- break;
-
- case AF_INET6:
- remoteAddress =
- addressCreateFromInet6((struct sockaddr_in6 *)peerIpAddress);
- break;
-
- default:
- parcTrapIllegalValue(peerIpAddress,
- "Peer address unrecognized family for IP: %d",
- peerIpAddress->sa_family);
- }
-
- AddressPair *pair = addressPair_Create(udp->localAddress, remoteAddress);
- addressDestroy(&remoteAddress);
-
- return pair;
-}
-
-static const Connection * _lookupConnection(ListenerOps * listener,
- const AddressPair *pair) {
- UdpListener * udp = (UdpListener *)listener->context;
- ConnectionTable *connTable = forwarder_GetConnectionTable(udp->forwarder);
- return connectionTable_FindByAddressPair(connTable, pair);
-
-}
-
-/**
- * @function _createNewConnection
- * @abstract Creates a new Metis connection for the peer
- * @discussion
- * PRECONDITION: you know there's not an existing connection with the address
- * pair
- *
- * Creates a new connection and adds it to the connection table.
- *
- * @param <#param1#>
- * @return The connection id for the new connection
- */
-
-static unsigned _createNewConnection(ListenerOps * listener, int fd,
- const AddressPair *pair) {
- UdpListener * udp = (UdpListener *)listener->context;
-
- //check it the connection is local
- bool isLocal = false;
- const Address *localAddress = addressPair_GetLocal(pair);
- if(addressGetType(localAddress) == ADDR_INET){
- struct sockaddr_in tmpAddr;
- addressGetInet(localAddress, &tmpAddr);
- if(parcNetwork_IsSocketLocal((struct sockaddr *)&tmpAddr))
- isLocal = true;
- }else{
- struct sockaddr_in6 tmpAddr6;
- addressGetInet6(localAddress, &tmpAddr6);
- if(parcNetwork_IsSocketLocal((struct sockaddr *)&tmpAddr6))
- isLocal = true;
- }
-
- // metisUdpConnection_Create takes ownership of the pair
- IoOperations *ops = udpConnection_Create(udp->forwarder, udp->interfaceName, fd, pair, isLocal);
- Connection *conn = connection_Create(ops);
- // connection_AllowWldrAutoStart(conn);
-
- connectionTable_Add(forwarder_GetConnectionTable(udp->forwarder), conn);
- unsigned connid = ioOperations_GetConnectionId(ops);
-
- return connid;
-}
-
-static void _handleWldrNotification(UdpListener *udp, unsigned connId,
- uint8_t *msgBuffer) {
- const Connection *conn = connectionTable_FindById(
- forwarder_GetConnectionTable(udp->forwarder), connId);
- if (conn == NULL) {
- parcMemory_Deallocate((void **)&msgBuffer);
- return;
- }
-
- Message *message = message_CreateFromByteArray(
- connId, msgBuffer, MessagePacketType_WldrNotification,
- forwarder_GetTicks(udp->forwarder), forwarder_GetLogger(udp->forwarder));
-
- connection_HandleWldrNotification((Connection *)conn, message);
-
- message_Release(&message);
-}
-
-static Message *_readMessage(ListenerOps * listener, int fd,
- AddressPair *pair, uint8_t * packet, bool * processed) {
- UdpListener * udp = (UdpListener *)listener->context;
-
- Message *message = NULL;
-
- unsigned connid;
- bool foundConnection;
-
- const Connection *conn = _lookupConnection(listener, pair);
- if (conn) {
- connid = connection_GetConnectionId(conn);
- foundConnection = true;
- } else {
- connid = 0;
- foundConnection = false;
- }
-
- if (messageHandler_IsTCP(packet)) {
- *processed = true;
- MessagePacketType pktType;
-
- if (messageHandler_IsData(packet)) {
- pktType = MessagePacketType_ContentObject;
- if (!foundConnection) {
- parcMemory_Deallocate((void **)&packet);
- return message;
- }
- } else if (messageHandler_IsInterest(packet)) {
- pktType = MessagePacketType_Interest;
- if (!foundConnection) {
- connid = _createNewConnection(listener, fd, pair);
- }
- } else {
- printf("Got a packet that is not a data nor an interest, drop it!\n");
- parcMemory_Deallocate((void **)&packet);
- return message;
- }
-
- message = message_CreateFromByteArray(
- connid, packet, pktType, forwarder_GetTicks(udp->forwarder),
- forwarder_GetLogger(udp->forwarder));
-
- if (message == NULL) {
- parcMemory_Deallocate((void **)&packet);
- }
- } else if (messageHandler_IsWldrNotification(packet)) {
- *processed = true;
- _handleWldrNotification(udp, connid, packet);
- } else {
-
- *processed = messageHandler_handleHooks(udp->forwarder, packet, listener, fd, pair);
- }
-
- return message;
-}
-
-static void _readCommand(ListenerOps * listener, int fd,
- AddressPair *pair, uint8_t * command) {
- UdpListener * udp = (UdpListener *)listener->context;
-
- if (*command != REQUEST_LIGHT){
- printf("the message received is not a command, drop\n");
- parcMemory_Deallocate((void **) &command);
- return;
- }
-
- command_id id = *(command + 1);
-
- if (id >= LAST_COMMAND_VALUE){
- printf("the message received is not a valid command, drop\n");
- parcMemory_Deallocate((void **) &command);
- return;
- }
-
- unsigned connid;
-
- const Connection *conn = _lookupConnection(listener, pair);
- if (conn) {
- connid = connection_GetConnectionId(conn);
- } else {
- connid = _createNewConnection(listener, fd, pair);
- }
-
- struct iovec *request;
- if (!(request = (struct iovec *) parcMemory_AllocateAndClear(
- sizeof(struct iovec) * 2))) {
- return;
- }
-
- request[0].iov_base = command;
- request[0].iov_len = sizeof(header_control_message);
- request[1].iov_base = command + sizeof(header_control_message);
- request[1].iov_len = payloadLengthDaemon(id);
-
- forwarder_ReceiveCommand(udp->forwarder, id, request, connid);
- parcMemory_Deallocate((void **) &command);
- //parcMemory_Deallocate((void **) &request);
-}
-
-
-static bool _receivePacket(ListenerOps * listener, int fd,
- AddressPair *pair,
- uint8_t * packet) {
- UdpListener * udp = (UdpListener *)listener->context;
- bool processed = false;
- Message *message = _readMessage(listener, fd, pair,
- packet, &processed);
- if (message) {
- forwarder_Receive(udp->forwarder, message);
- }
- return processed;
-}
-
-static void _readcb(int fd, PARCEventType what, void * listener_void) {
- ListenerOps * listener = (ListenerOps *)listener_void;
- UdpListener * udp = (UdpListener *)listener->context;
-
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "%s socket %d what %s%s%s%s data %p", __func__, fd,
- (what & PARCEventType_Timeout) ? " timeout" : "",
- (what & PARCEventType_Read) ? " read" : "",
- (what & PARCEventType_Write) ? " write" : "",
- (what & PARCEventType_Signal) ? " signal" : "", udp);
- }
-
- if (what & PARCEventType_Read) {
- struct sockaddr_storage peerIpAddress;
- socklen_t peerIpAddressLength = sizeof(peerIpAddress);
-
- //packet it deallocated by _receivePacket or _readCommand
- uint8_t * packet = parcMemory_AllocateAndClear(1500); //max MTU
- ssize_t readLength = recvfrom(fd, packet, 1500, 0,
- (struct sockaddr *)&peerIpAddress, &peerIpAddressLength);
-
-#ifdef __APPLE__
- peerIpAddress.ss_len = 0x00;
-#endif
-
- if(readLength < 0) {
- printf("unable to read the message\n");
- parcMemory_Deallocate(packet);
- return;
- }
-
- AddressPair *pair = _constructAddressPair(
- udp, (struct sockaddr *)&peerIpAddress, peerIpAddressLength);
-
- bool done = _receivePacket(listener, fd, pair, packet);
- if(!done){
- _readCommand(listener, fd, pair, packet);
- }
-
- addressPair_Release(&pair);
- }
-}
diff --git a/hicn-light/src/hicn/io/udpListener.h b/hicn-light/src/hicn/io/udpListener.h
deleted file mode 100644
index 62c09e4db..000000000
--- a/hicn-light/src/hicn/io/udpListener.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef udpListener_h
-#define udpListener_h
-
-#ifndef _WIN32
-#include <netinet/in.h>
-#endif
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/listener.h>
-#include <stdlib.h>
-
-struct udp_listener;
-typedef struct udp_listener UdpListener;
-
-ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in6 sin6, const char *if_bind);
-ListenerOps *udpListener_CreateInet(Forwarder *forwarder, char *listenerName,
- struct sockaddr_in sin, const char *if_bind);
-// void udpListener_SetPacketType(ListenerOps *ops, MessagePacketType type);
-#endif // udpListener_h
diff --git a/hicn-light/src/hicn/io/udpTunnel.c b/hicn-light/src/hicn/io/udpTunnel.c
deleted file mode 100644
index 9f5249e3c..000000000
--- a/hicn-light/src/hicn/io/udpTunnel.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/algol/parc_Network.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/io/udpConnection.h>
-#include <hicn/io/udpListener.h>
-#include <hicn/io/udpTunnel.h>
-
-IoOperations *udpTunnel_CreateOnListener(Forwarder *forwarder,
- ListenerOps *localListener,
- const Address *remoteAddress) {
- parcAssertNotNull(forwarder, "Parameter metis must be non-null");
- parcAssertNotNull(localListener, "Parameter localListener must be non-null");
- parcAssertNotNull(remoteAddress, "Parameter remoteAddress must be non-null");
-
- Logger *logger = forwarder_GetLogger(forwarder);
-
- IoOperations *ops = NULL;
- if (localListener->getEncapType(localListener) == ENCAP_UDP) {
- const Address *localAddress =
- localListener->getListenAddress(localListener);
- address_type localType = addressGetType(localAddress);
- address_type remoteType = addressGetType(remoteAddress);
-
- if (localType == remoteType) {
- AddressPair *pair = addressPair_Create(localAddress, remoteAddress);
-
- //check it the connection is local
- bool isLocal = false;
- if(localType == ADDR_INET){
- struct sockaddr_in tmpAddr;
- addressGetInet(localAddress, &tmpAddr);
- if(parcNetwork_IsSocketLocal((struct sockaddr *)&tmpAddr))
- isLocal = true;
- }else{
- struct sockaddr_in6 tmpAddr6;
- addressGetInet6(localAddress, &tmpAddr6);
- if(parcNetwork_IsSocketLocal((struct sockaddr *)&tmpAddr6))
- isLocal = true;
- }
- int fd = localListener->getSocket(localListener);
- // udpListener_SetPacketType(localListener,
- // MessagePacketType_ContentObject);
- ops = udpConnection_Create(forwarder, localListener->getInterfaceName(localListener), fd, pair, isLocal);
-
- addressPair_Release(&pair);
- } else {
- if (logger_IsLoggable(logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- logger_Log(logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Local listener of type %s and remote type %s, cannot "
- "establish tunnel",
- addressTypeToString(localType),
- addressTypeToString(remoteType));
- }
- }
- } else {
- if (logger_IsLoggable(logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- logger_Log(logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Local listener %p is not type UDP, cannot establish tunnel",
- (void *)localListener);
- }
- }
-
- return ops;
-}
-
-IoOperations *udpTunnel_Create(Forwarder *forwarder,
- const Address *localAddress,
- const Address *remoteAddress) {
- ListenerSet *set = forwarder_GetListenerSet(forwarder);
- ListenerOps *listener = listenerSet_Find(set, ENCAP_UDP, localAddress);
- IoOperations *ops = NULL;
- if (listener) {
- ops = udpTunnel_CreateOnListener(forwarder, listener, remoteAddress);
- } else {
- if (logger_IsLoggable(forwarder_GetLogger(forwarder), LoggerFacility_IO,
- PARCLogLevel_Error)) {
- char *str = addressToString(localAddress);
- logger_Log(forwarder_GetLogger(forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "Could not find listener to match address %s", str);
- parcMemory_Deallocate((void **)&str);
- }
- }
- return ops;
-}
diff --git a/hicn-light/src/hicn/io/udpTunnel.h b/hicn-light/src/hicn/io/udpTunnel.h
deleted file mode 100644
index dacfdbb01..000000000
--- a/hicn-light/src/hicn/io/udpTunnel.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file udpTunnel.h
- * @brief Establish a tunnel to a remote system
- *
- */
-
-#ifndef udpTunnel_h
-#define udpTunnel_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/io/listener.h>
-#include <hicn/utils/address.h>
-
-/**
- */
-IoOperations *udpTunnel_CreateOnListener(Forwarder *forwarder,
- ListenerOps *localListener,
- const Address *remoteAddress);
-
-/**
- */
-IoOperations *udpTunnel_Create(Forwarder *forwarder,
- const Address *localAddress,
- const Address *remoteAddress);
-
-#endif // udpTunnel_h
diff --git a/hicn-light/src/hicn/messenger/messenger.c b/hicn-light/src/hicn/messenger/messenger.c
deleted file mode 100644
index 45437539d..000000000
--- a/hicn-light/src/hicn/messenger/messenger.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- *
- * The messenger is contructued with a reference to the forwarder's dispatcher
- * so it can schedule future events. When someone calls messenger_Send(...), it
- * will put the message on a queue. If the queue was empty, it will scheudle
- * itself to be run. By running the queue in a future dispatcher slice, it
- * guarantees that there will be no re-entrant behavior between callers and
- * message listeners.
- *
- * A recipient will receive a reference counted copy of the missive, so it must
- * call
- * {@link missive_Release} on it.
- *
- */
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Event.h>
-#include <parc/algol/parc_EventScheduler.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/messenger/messenger.h>
-#include <hicn/messenger/missiveDeque.h>
-
-struct messenger {
- PARCArrayList *callbacklist;
- Dispatcher *dispatcher;
- MissiveDeque *eventQueue;
-
- PARCEventTimer *timerEvent;
-};
-
-static void messenger_Dequeue(int fd, PARCEventType which_event,
- void *messengerVoidPtr);
-
-// =========================================
-// Public API
-
-Messenger *messenger_Create(Dispatcher *dispatcher) {
- Messenger *messenger = parcMemory_AllocateAndClear(sizeof(Messenger));
- parcAssertNotNull(messenger, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Messenger));
-
- // NULL destroyer because we're storing structures owned by the caller
- messenger->dispatcher = dispatcher;
- messenger->callbacklist = parcArrayList_Create(NULL);
- messenger->eventQueue = missiveDeque_Create();
-
- // creates the timer, but does not start it
- messenger->timerEvent =
- dispatcher_CreateTimer(dispatcher, false, messenger_Dequeue, messenger);
-
- return messenger;
-}
-
-void messenger_Destroy(Messenger **messengerPtr) {
- parcAssertNotNull(messengerPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*messengerPtr,
- "Parameter must dereference to non-null pointer");
-
- Messenger *messenger = *messengerPtr;
- parcArrayList_Destroy(&messenger->callbacklist);
- missiveDeque_Release(&messenger->eventQueue);
- dispatcher_DestroyTimerEvent(messenger->dispatcher, &messenger->timerEvent);
- parcMemory_Deallocate((void **)&messenger);
- *messengerPtr = NULL;
-}
-
-void messenger_Send(Messenger *messenger, Missive *missive) {
- parcAssertNotNull(messenger, "Parameter messenger must be non-null");
- parcAssertNotNull(missive, "Parameter event must be non-null");
-
- missiveDeque_Append(messenger->eventQueue, missive);
- if (missiveDeque_Size(messenger->eventQueue) == 1) {
- // We need to scheudle ourself when an event is added to an empty queue
-
- // precondition: timer should not be running.
- struct timeval immediateTimeout = {0, 0};
- dispatcher_StartTimer(messenger->dispatcher, messenger->timerEvent,
- &immediateTimeout);
- }
-}
-
-static void removeRecipient(Messenger *messenger,
- const MessengerRecipient *recipient) {
- // don't increment i in the loop
- for (size_t i = 0; i < parcArrayList_Size(messenger->callbacklist);) {
- const void *p = parcArrayList_Get(messenger->callbacklist, i);
- if (p == recipient) {
- // removing will compact the list, so next element will also be at i.
- parcArrayList_RemoveAndDestroyAtIndex(messenger->callbacklist, i);
- } else {
- i++;
- }
- }
-}
-
-/**
- * @function eventMessenger_Register
- * @abstract Receive all event messages
- */
-void messenger_Register(Messenger *messenger,
- const MessengerRecipient *recipient) {
- parcAssertNotNull(messenger, "Parameter messenger must be non-null");
- parcAssertNotNull(recipient, "Parameter recipient must be non-null");
-
- // do not allow duplicates
- removeRecipient(messenger, recipient);
-
- parcArrayList_Add(messenger->callbacklist, recipient);
-}
-
-/**
- * @function eventMessenger_Unregister
- * @abstract Stop receiving event messages
- */
-void messenger_Unregister(Messenger *messenger,
- const MessengerRecipient *recipient) {
- parcAssertNotNull(messenger, "Parameter messenger must be non-null");
- parcAssertNotNull(recipient, "Parameter recipient must be non-null");
-
- removeRecipient(messenger, recipient);
-}
-
-/**
- * Called by event scheduler to give us a slice in which to dequeue events
- *
- * Called inside an event callback, so we now have exclusive access to the
- * system. Dequeues all pending events and calls all the listeners for each one.
- *
- * @param [in] fd unused, required for compliance with function prototype
- * @param [in] which_event unused, required for compliance with function
- * prototype
- * @param [in] messengerVoidPtr A void* to Messenger
- */
-static void messenger_Dequeue(int fd, PARCEventType which_event,
- void *messengerVoidPtr) {
- Messenger *messenger = (Messenger *)messengerVoidPtr;
- parcAssertNotNull(messenger, "Called with null messenger pointer");
-
- Missive *missive;
- while ((missive = missiveDeque_RemoveFirst(messenger->eventQueue)) != NULL) {
- for (size_t i = 0; i < parcArrayList_Size(messenger->callbacklist); i++) {
- MessengerRecipient *recipient =
- parcArrayList_Get(messenger->callbacklist, i);
- parcAssertTrue(recipient, "Recipient is null at index %zu", i);
-
- messengerRecipient_Deliver(recipient, missive_Acquire(missive));
- }
-
- // now let go of our reference to the missive
- missive_Release(&missive);
- }
-}
diff --git a/hicn-light/src/hicn/messenger/messenger.h b/hicn-light/src/hicn/messenger/messenger.h
deleted file mode 100644
index 79d65cda6..000000000
--- a/hicn-light/src/hicn/messenger/messenger.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * The EventMessenger is the system that messages events between
- * producers and consumers.
- *
- * Events are delivered in a deferred event cycle to avoid event callbacks
- * firing when the event generator is still running.
- */
-
-#ifndef messenger_h
-#define messenger_h
-
-#include <hicn/core/dispatcher.h>
-#include <hicn/messenger/messengerRecipient.h>
-#include <hicn/messenger/missive.h>
-
-struct messenger;
-typedef struct messenger Messenger;
-
-/**
- * @function eventmessenger_Create
- * @abstract Creates an event notification system
- * @discussion
- * Typically there's only one of these managed by forwarder.
- *
- * @param dispatcher is the event dispatcher to use to schedule events.
- */
-Messenger *messenger_Create(Dispatcher *dispatcher);
-
-/**
- * @function eventMessenger_Destroy
- * @abstract Destroys the messenger system, no notification is sent
- */
-void messenger_Destroy(Messenger **messengerPtr);
-
-/**
- * @function eventMessenger_Send
- * @abstract Send an event message, takes ownership of the event memory
- */
-void messenger_Send(Messenger *messenger, Missive *missive);
-
-/**
- * @function eventMessenger_Register
- * @abstract Receive all event messages
- */
-void messenger_Register(Messenger *messenger,
- const MessengerRecipient *recipient);
-
-/**
- * @function eventMessenger_Unregister
- * @abstract Stop receiving event messages
- */
-void messenger_Unregister(Messenger *messenger,
- const MessengerRecipient *recipient);
-#endif // messenger_h
diff --git a/hicn-light/src/hicn/messenger/messengerRecipient.c b/hicn-light/src/hicn/messenger/messengerRecipient.c
deleted file mode 100644
index 17407030a..000000000
--- a/hicn-light/src/hicn/messenger/messengerRecipient.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/messenger/messenger.h>
-#include <hicn/messenger/messengerRecipient.h>
-
-struct messenger_recipient {
- void *context;
- MessengerRecipientCallback *notify;
-};
-
-MessengerRecipient *messengerRecipient_Create(
- void *recipientContext, MessengerRecipientCallback *recipientCallback) {
- parcAssertNotNull(recipientCallback,
- "Parameter recipientCallback must be non-null");
-
- MessengerRecipient *recipient =
- parcMemory_AllocateAndClear(sizeof(MessengerRecipient));
- parcAssertNotNull(recipient, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(MessengerRecipient));
- recipient->context = recipientContext;
- recipient->notify = recipientCallback;
- return recipient;
-}
-
-void messengerRecipient_Destroy(MessengerRecipient **recipientPtr) {
- parcAssertNotNull(recipientPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*recipientPtr,
- "Parameter must dereference to non-null pointer");
-
- parcMemory_Deallocate((void **)recipientPtr);
- *recipientPtr = NULL;
-}
-
-void *messengerRecipient_GetRecipientContext(MessengerRecipient *recipient) {
- parcAssertNotNull(recipient, "Parameter must be non-null");
-
- return recipient->context;
-}
-
-void messengerRecipient_Deliver(MessengerRecipient *recipient,
- Missive *missive) {
- parcAssertNotNull(recipient, "Parameter must be non-null");
- recipient->notify(recipient, missive);
-}
diff --git a/hicn-light/src/hicn/messenger/messengerRecipient.h b/hicn-light/src/hicn/messenger/messengerRecipient.h
deleted file mode 100644
index cb5705b3a..000000000
--- a/hicn-light/src/hicn/messenger/messengerRecipient.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file messengerRecipient.h
- * @brief A recipient represents the entity that will recieve a Missive from the
- * Messenger.
- *
- * A recipient is identified by the pair (contenxt, callback). The context is
- * the recipients context, such as it's object pointer. The callback is the
- * function the recipient uses to receive a Missive.
- *
- * If the receiver is going to do a lot of work or potentially send other
- * missives, the receiver should queue the received notifications and process
- * them in its own slice.
- *
- * A recipient will receive a reference counted copy of the missive, so it must
- * call
- * {@link missive_Release} on it.
- *
- *
- */
-
-#ifndef messengerRecipient_h
-#define messengerRecipient_h
-
-#include <hicn/messenger/missive.h>
-
-struct messenger_recipient;
-typedef struct messenger_recipient MessengerRecipient;
-
-/**
- * @typedef MessengerRecipientCallback
- * @abstract A recipient implements a callback to receive Missives.
- * @constant recipient The recipient to recieve the missive
- * @constant missive The missive, recipient must call {@link missive_Release} on
- * it
- */
-typedef void(MessengerRecipientCallback)(MessengerRecipient *recipient,
- Missive *missive);
-
-/**
- * Creates a Recipient, which represents a reciever of missives.
- *
- * Creates a Recipient that can be registerd with the Messenger using {@link
- * messenger_Register}.
- *
- * @param [in] recipientContext This pointer will be passed back to the
- * recipient with each missive, may be NULL
- * @param [in] recipientCallback The function that receives the missive, must be
- * non-NULL.
- *
- * @return non-null A recipient object
- */
-MessengerRecipient *messengerRecipient_Create(
- void *recipientContext, MessengerRecipientCallback *recipientCallback);
-
-/**
- * Destroys a recipient. You should unregister it first.
- *
- * Destroying a recipient does not unregister it, so be sure to call
- * {@link messenger_Unregister} first.
- *
- * @param [in,out] recipientPtr Double pointer to the recipient to destroy, will
- * be NULL'd.
- */
-void messengerRecipient_Destroy(MessengerRecipient **recipientPtr);
-
-/**
- * Returns the recipient context passed on Create
- *
- * @param [in] recipient The recipient object
- *
- * @return pointer The context pointer used to create the object, maybe NULL
- */
-void *messengerRecipient_GetRecipientContext(MessengerRecipient *recipient);
-
-/**
- * Delivers a Missive to the recipient
- *
- * Passes the missive to the recipients callback.
- *
- * A recipient will receive a reference counted copy of the missive, so it must
- * call
- * {@link missive_Release} on it.
- *
- * @param [in] recipient The receiver
- * @param [in] missive The message to send
- */
-void messengerRecipient_Deliver(MessengerRecipient *recipient,
- Missive *missive);
-#endif // messengerRecipient_h
diff --git a/hicn-light/src/hicn/messenger/missive.c b/hicn-light/src/hicn/messenger/missive.c
deleted file mode 100644
index 5162e683d..000000000
--- a/hicn-light/src/hicn/messenger/missive.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/messenger/missive.h>
-
-struct missive {
- MissiveType missiveType;
- unsigned connectionid;
-};
-
-parcObject_Override(Missive, PARCObject, .isLockable = false);
-
-Missive *missive_Create(MissiveType missiveType, unsigned connectionid) {
- Missive *missive = parcObject_CreateInstance(Missive);
- missive->missiveType = missiveType;
- missive->connectionid = connectionid;
- return missive;
-}
-
-Missive *missive_Acquire(const Missive *missive) {
- return parcObject_Acquire(missive);
-}
-
-void missive_Release(Missive **missivePtr) {
- parcObject_Release((void **)missivePtr);
-}
-
-MissiveType missive_GetType(const Missive *missive) {
- parcAssertNotNull(missive, "Parameter missive must be non-null");
- return missive->missiveType;
-}
-
-unsigned missive_GetConnectionId(const Missive *missive) {
- parcAssertNotNull(missive, "Parameter missive must be non-null");
- return missive->connectionid;
-}
diff --git a/hicn-light/src/hicn/messenger/missive.h b/hicn-light/src/hicn/messenger/missive.h
deleted file mode 100644
index fdeddce83..000000000
--- a/hicn-light/src/hicn/messenger/missive.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file missive.h
- * @brief A Missive is a status message sent over a broadcast channel inside
- * hicn-light
- *
- * Recipients use {@link messenger_Register} to receive missives. They are
- * broadcast to all recipients.
- *
- */
-#ifndef missive_h
-#define missive_h
-
-#include <hicn/messenger/missiveType.h>
-
-struct missive;
-typedef struct missive Missive;
-
-/**
- * Creates a Missive and sets the reference count to 1
- *
- * A Missive may be sent to listeners of the Messenger to inform them of events
- * on a connection id.
- *
- * @param [in] MissiveType The event type
- * @param [in] connectionid The relevant conneciton id
- *
- * @return non-null A message
- * @retrun null An error
- */
-Missive *missive_Create(MissiveType missiveType, unsigned connectionid);
-
-/**
- * Acquire a reference counted copy
- *
- * Increases the reference count by 1 and returns the original object.
- *
- * @param [in] missive An allocated missive
- *
- * @return non-null The original missive with increased reference count
- */
-Missive *missive_Acquire(const Missive *missive);
-
-/**
- * Releases a reference counted copy.
- *
- * If it is the last reference, the missive is freed.
- *
- * @param [in,out] missivePtr Double pointer to a missive, will be nulled.
- */
-void missive_Release(Missive **missivePtr);
-
-/**
- * Returns the type of the missive
- *
- * Returns the type of event the missive represents
- *
- * @param [in] missive An allocated missive
- *
- * @return MissiveType The event type
- */
-MissiveType missive_GetType(const Missive *missive);
-
-/**
- * Returns the connection ID of the missive
- *
- * An event is usually associated with a connection id (i.e. the I/O channel
- * that originaged the event).
- *
- * @param [in] missive An allocated missive
- *
- * @return number The relevant connection id.
- */
-unsigned missive_GetConnectionId(const Missive *missive);
-#endif // missive_h
diff --git a/hicn-light/src/hicn/messenger/missiveDeque.c b/hicn-light/src/hicn/messenger/missiveDeque.c
deleted file mode 100644
index ab94a4f18..000000000
--- a/hicn-light/src/hicn/messenger/missiveDeque.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * A type-safe wrapper for Missives around a {@link PARCDeque}. We only
- * implement the subset of functions used.
- *
- */
-
-#include <parc/algol/parc_Deque.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/messenger/missive.h>
-#include <hicn/messenger/missiveDeque.h>
-
-struct missive_deque {
- PARCDeque *queue;
-};
-
-MissiveDeque *missiveDeque_Create(void) {
- MissiveDeque *missiveDeque =
- parcMemory_AllocateAndClear(sizeof(MissiveDeque));
- parcAssertNotNull(missiveDeque,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(MissiveDeque));
- missiveDeque->queue = parcDeque_Create();
- return missiveDeque;
-}
-
-void missiveDeque_Release(MissiveDeque **dequePtr) {
- parcAssertNotNull(dequePtr, "Double pointer must be non-null");
- parcAssertNotNull(*dequePtr, "Double pointer must dereference to non-null");
- MissiveDeque *missiveDeque = *dequePtr;
-
- // flush the queue
- while (!parcDeque_IsEmpty(missiveDeque->queue)) {
- Missive *missive = missiveDeque_RemoveFirst(missiveDeque);
- missive_Release(&missive);
- }
-
- parcDeque_Release(&missiveDeque->queue);
- parcMemory_Deallocate((void **)&missiveDeque);
- *dequePtr = NULL;
-}
-
-MissiveDeque *missiveDeque_Append(MissiveDeque *deque, Missive *missive) {
- parcAssertNotNull(deque, "Parameter deque must be non-null");
- parcAssertNotNull(missive, "Parameter missive must be non-null");
-
- parcDeque_Append(deque->queue, missive);
- return deque;
-}
-
-Missive *missiveDeque_RemoveFirst(MissiveDeque *deque) {
- parcAssertNotNull(deque, "Parameter deque must be non-null");
- return (Missive *)parcDeque_RemoveFirst(deque->queue);
-}
-
-size_t missiveDeque_Size(const MissiveDeque *deque) {
- parcAssertNotNull(deque, "Parameter deque must be non-null");
- return parcDeque_Size(deque->queue);
-}
diff --git a/hicn-light/src/hicn/messenger/missiveDeque.h b/hicn-light/src/hicn/messenger/missiveDeque.h
deleted file mode 100644
index c6f955ce0..000000000
--- a/hicn-light/src/hicn/messenger/missiveDeque.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file missiveDeque
- * @brief Double ended queue of Missives
- *
- * Used to queue Missives. This is a type-safe wrapper around {@link PARCDeque}
- *
- */
-
-#ifndef missiveDeque_h
-#define missiveDeque_h
-
-struct missive_deque;
-
-typedef struct missive_deque MissiveDeque;
-
-/**
- * Create a `PARCDeque` instance with the default element equals function.
- *
- * The queue is created with no elements.
- *
- * The default element equals function is used by the `parcDeque_Equals`
- * function and simply compares the values using the `==` operator. Users that
- * need more sophisticated comparisons of the elements need to supply their own
- * function via the `parcDeque_CreateCustom` function.
- *
- * @return non-NULL A pointer to a PARCDeque instance.
- */
-MissiveDeque *missiveDeque_Create(void);
-
-void missiveDeque_Release(MissiveDeque **dequePtr);
-
-/**
- * Appends the missive to the queue, taking ownership of the memory
- */
-MissiveDeque *missiveDeque_Append(MissiveDeque *deque, Missive *missive);
-
-Missive *missiveDeque_RemoveFirst(MissiveDeque *deque);
-
-size_t missiveDeque_Size(const MissiveDeque *deque);
-#endif // missiveDeque_h
diff --git a/hicn-light/src/hicn/messenger/missiveType.h b/hicn-light/src/hicn/messenger/missiveType.h
deleted file mode 100644
index b0d9c7704..000000000
--- a/hicn-light/src/hicn/messenger/missiveType.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file missiveType
- * @brief Defines what a Missive represents
- *
- * Currently, missives only carry information about the state of a connection
- * (created, up, down, closed, destroyed).
- *
- */
-
-#ifndef missiveType_h
-#define missiveType_h
-
-/**
- * @typedef Represents the state of a connection
- * @abstract CREATE is the initial state. UP & DOWN are recurrent states.
- * CLOSED is transient. DESTROYED is the terminal state.
- * @constant MissiveType_ConnectionCreate Connection created (new)
- * @constant MissiveType_ConnectionUp Connection is active and passing
- * data
- * @constant MissiveType_ConnectionDown Connection is inactive and cannot
- * pass data
- * @constant MissiveType_ConnectionClosed Connection closed and will be
- * destroyed
- * @constant MissiveType_ConnectionDestroyed Connection destroyed
- * @discussion State transitions:
- * initial -> CREATE
- * CREATE -> (UP | DOWN)
- * UP -> (DOWN | DESTROYED)
- * DOWN -> (UP | CLOSED | DESTROYED)
- * CLOSED -> DESTROYED
- * DESTROYED -> terminal
- */
-typedef enum {
- MissiveType_ConnectionCreate,
- MissiveType_ConnectionUp,
- MissiveType_ConnectionDown,
- MissiveType_ConnectionClosed,
- MissiveType_ConnectionDestroyed
-} MissiveType;
-#endif // missiveType_h
diff --git a/hicn-light/src/hicn/platforms/CMakeLists.txt b/hicn-light/src/hicn/platforms/CMakeLists.txt
index 4073e0558..14237c976 100644
--- a/hicn-light/src/hicn/platforms/CMakeLists.txt
+++ b/hicn-light/src/hicn/platforms/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
diff --git a/hicn-light/src/hicn/platforms/README.txt b/hicn-light/src/hicn/platforms/README.txt
index a1293944c..18c63a5f9 100644
--- a/hicn-light/src/hicn/platforms/README.txt
+++ b/hicn-light/src/hicn/platforms/README.txt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,4 +14,3 @@
*/
Operating system dependent modules.
-
diff --git a/hicn-light/src/hicn/platforms/android/system.c b/hicn-light/src/hicn/platforms/android/system.c
index ba91748a0..80ca864ea 100644
--- a/hicn-light/src/hicn/platforms/android/system.c
+++ b/hicn-light/src/hicn/platforms/android/system.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#if 0
#include <errno.h>
#include <hicn/hicn-light/config.h>
#include <stdio.h>
@@ -181,3 +182,4 @@ unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) {
return mtu;
}
+#endif \ No newline at end of file
diff --git a/hicn-light/src/hicn/platforms/darwin/system.c b/hicn-light/src/hicn/platforms/darwin/system.c
index d817248a8..b80fa9b69 100644
--- a/hicn-light/src/hicn/platforms/darwin/system.c
+++ b/hicn-light/src/hicn/platforms/darwin/system.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,6 +13,8 @@
* limitations under the License.
*/
+#if 0
+
#include <errno.h>
#include <ifaddrs.h>
#include <hicn/hicn-light/config.h>
@@ -144,3 +146,5 @@ unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) {
}
return mtu;
}
+
+#endif
diff --git a/hicn-light/src/hicn/platforms/linux/system.c b/hicn-light/src/hicn/platforms/linux/system.c
index 3bf23cf57..4c14271a7 100644
--- a/hicn-light/src/hicn/platforms/linux/system.c
+++ b/hicn-light/src/hicn/platforms/linux/system.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,6 +13,8 @@
* limitations under the License.
*/
+#if 0
+
#include <errno.h>
#include <ifaddrs.h>
#include <hicn/hicn-light/config.h>
@@ -37,8 +39,6 @@
#include <parc/assert/parc_Assert.h>
-#include <hicn/utils/addressList.h>
-
/**
* Returns the MTU for a named interface
*
@@ -66,11 +66,9 @@ static int getMtu(const char *ifname) {
return ifr.ifr_mtu;
}
-InterfaceSet *system_Interfaces(Forwarder *forwarder) {
+InterfaceSet *system_Interfaces(forwarder_t * forwarder) {
InterfaceSet *set = interfaceSetCreate();
- Logger *logger = forwarder_GetLogger(forwarder);
-
// this is the dynamically allocated head of the list
struct ifaddrs *ifaddr;
int failure = getifaddrs(&ifaddr);
@@ -93,60 +91,18 @@ InterfaceSet *system_Interfaces(Forwarder *forwarder) {
interfaceSetAdd(set, iface);
}
- int family = next->ifa_addr->sa_family;
- switch (family) {
- case AF_INET: {
- Address *address =
- addressCreateFromInet((struct sockaddr_in *)next->ifa_addr);
- interfaceAddAddress(iface, address);
- break;
- }
-
- case AF_INET6: {
- Address *address =
- addressCreateFromInet6((struct sockaddr_in6 *)next->ifa_addr);
- interfaceAddAddress(iface, address);
- break;
- }
-
- case AF_PACKET: {
- struct sockaddr_ll *addr_ll = (struct sockaddr_ll *)next->ifa_addr;
-
- if (logger_IsLoggable(logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "sockaddr_ll family %d proto %d ifindex %d hatype %d "
- "pkttype %d halen %d",
- addr_ll->sll_family, addr_ll->sll_protocol,
- addr_ll->sll_ifindex, addr_ll->sll_hatype,
- addr_ll->sll_pkttype, addr_ll->sll_halen);
- }
-
- switch (addr_ll->sll_hatype) {
- // list of the ARP hatypes we can extract a MAC address from
- case ARPHRD_ETHER:
- // fallthrough
- case ARPHRD_IEEE802: {
- Address *address = addressCreateFromLink(
- (uint8_t *)addr_ll->sll_addr, addr_ll->sll_halen);
- interfaceAddAddress(iface, address);
- break;
- }
- default:
- break;
- }
-
- break;
- }
- }
+ address_t * address = (address_t *)next->ifa_addr;
+ interfaceAddAddress(iface, address);
}
freeifaddrs(ifaddr);
return set;
}
-Address *system_GetMacAddressByName(Forwarder *forwarder,
+#if 0
+address_t *system_GetMacAddressByName(Forwarder *forwarder,
const char *interfaceName) {
- Address *linkAddress = NULL;
+ address_t *linkAddress = NULL;
InterfaceSet *interfaceSet = system_Interfaces(forwarder);
Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName);
@@ -156,7 +112,7 @@ Address *system_GetMacAddressByName(Forwarder *forwarder,
size_t length = addressListLength(addressList);
for (size_t i = 0; i < length && !linkAddress; i++) {
- const Address *a = addressListGetItem(addressList, i);
+ const address_t *a = addressListGetItem(addressList, i);
if (addressGetType(a) == ADDR_LINK) {
linkAddress = addressCopy(a);
}
@@ -167,6 +123,7 @@ Address *system_GetMacAddressByName(Forwarder *forwarder,
return linkAddress;
}
+#endif
unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) {
unsigned mtu = 0;
@@ -182,3 +139,5 @@ unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) {
return mtu;
}
+
+#endif
diff --git a/hicn-light/src/hicn/platforms/windows/system.c b/hicn-light/src/hicn/platforms/windows/system.c
index 55d89f63a..6bd36a372 100644
--- a/hicn-light/src/hicn/platforms/windows/system.c
+++ b/hicn-light/src/hicn/platforms/windows/system.c
@@ -1,223 +1,223 @@
-/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <string.h>
-
-#define WORKING_BUFFER_SIZE 15000
-#define MAX_TRIES 3
-
-#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
-#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
-
-#include <hicn/core/forwarder.h>
-#include <hicn/utils/interfaceSet.h>
-
-#include <hicn/utils/addressList.h>
-
-/**
- * Returns the MTU for a named interface
- *
- * On linux, we get the MTU by opening a socket and reading SIOCGIFMTU
- *
- * @param [in] ifname Interface name (e.g. "eth0")
- *
- * @retval number The MTU in bytes
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-static int getMtu(const char *ifname) {
- PIP_ADAPTER_ADDRESSES pAddresses = NULL;
- PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
- ULONG outBufLen = 0;
- ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
- ULONG family = AF_UNSPEC;
-
- DWORD dwSize = 0;
- DWORD dwRetVal = 0;
- ULONG Iterations = 0;
- do {
- pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
- if (pAddresses == NULL) {
- printf("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
- exit(1);
- }
-
- dwRetVal =
- GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
-
- if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
- FREE(pAddresses);
- pAddresses = NULL;
- } else {
- break;
- }
-
- Iterations++;
-
- } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
-
- if (dwRetVal == NO_ERROR) {
- pCurrAddresses = pAddresses;
- while (pCurrAddresses) {
- if (strcmp(pCurrAddresses->AdapterName, ifname)) {
- int mtu = pCurrAddresses->Mtu;
- if (pAddresses) {
- FREE(pAddresses);
- }
- return mtu;
- }
- pCurrAddresses = pCurrAddresses->Next;
- }
- }
-
- if (pAddresses) {
- FREE(pAddresses);
- }
- return -1;
-}
-
-InterfaceSet *system_Interfaces(Forwarder *forwarder) {
- InterfaceSet *set = interfaceSetCreate();
-
- Logger *logger = forwarder_GetLogger(forwarder);
-
- DWORD dwSize = 0;
- DWORD dwRetVal = 0;
- unsigned int i = 0;
- // Set the flags to pass to GetAdaptersAddresses
- ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
-
- // default to unspecified address family (both)
- ULONG family = AF_UNSPEC;
-
- LPVOID lpMsgBuf = NULL;
-
- PIP_ADAPTER_ADDRESSES pAddresses = NULL;
- ULONG outBufLen = 0;
- ULONG Iterations = 0;
-
- PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
- PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
- PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
- PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
- IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
- IP_ADAPTER_PREFIX *pPrefix = NULL;
-
- outBufLen = WORKING_BUFFER_SIZE;
-
- do {
- pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
- parcAssertNotNull(
- pAddresses,
- "Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
- dwRetVal =
- GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
-
- if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
- FREE(pAddresses);
- pAddresses = NULL;
- } else {
- break;
- }
-
- Iterations++;
-
- } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
- if (dwRetVal == NO_ERROR) {
- // If successful, output some information from the data we received
- pCurrAddresses = pAddresses;
- while (pCurrAddresses) {
- if (pCurrAddresses->OperStatus == IfOperStatusUp) {
- Interface *iface =
- interfaceSetGetByName(set, pCurrAddresses->AdapterName);
- if (iface == NULL) {
- pMulticast = pCurrAddresses->FirstMulticastAddress;
- if (pMulticast) {
- for (i = 0; pMulticast != NULL; i++) pMulticast = pMulticast->Next;
- }
-
- iface = interfaceCreate(
- pCurrAddresses->AdapterName,
- forwarder_GetNextConnectionId(forwarder),
- pCurrAddresses->IfType == IF_TYPE_SOFTWARE_LOOPBACK, i > 0,
- pCurrAddresses->Mtu);
-
- interfaceSetAdd(set, iface);
- for (pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != NULL;
- pUnicast = pUnicast->Next) {
- int family = pUnicast->Address.lpSockaddr->sa_family;
-
- switch (family) {
- case AF_INET: {
- char *ip = inet_ntoa(
- ((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))
- ->sin_addr);
- Address *address = addressCreateFromInet(
- (struct sockaddr_in *)(pUnicast->Address.lpSockaddr));
- interfaceAddAddress(iface, address);
- break;
- }
-
- case AF_INET6: {
- char str[INET6_ADDRSTRLEN];
- inet_ntop(
- AF_INET6,
- &((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))
- ->sin6_addr,
- str, INET6_ADDRSTRLEN);
- Address *address = addressCreateFromInet6(
- (struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr));
- interfaceAddAddress(iface, address);
- break;
- }
-
- default:
- break;
- }
- }
- }
- }
- pCurrAddresses = pCurrAddresses->Next;
- }
- }
-
- if (pAddresses) {
- FREE(pAddresses);
- }
- return set;
-}
-
-Address *system_GetMacAddressByName(Forwarder *forwarder,
- const char *interfaceName) {
- return NULL;
-}
-
-unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) {
- unsigned mtu = 0;
-
- return mtu;
-}
+/*
+ * 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 <parc/assert/parc_Assert.h>
+#include <hicn/hicn-light/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <string.h>
+
+#define WORKING_BUFFER_SIZE 15000
+#define MAX_TRIES 3
+
+#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
+#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
+
+#include <hicn/core/forwarder.h>
+#include <hicn/utils/interfaceSet.h>
+
+#include <hicn/utils/addressList.h>
+
+/**
+ * Returns the MTU for a named interface
+ *
+ * On linux, we get the MTU by opening a socket and reading SIOCGIFMTU
+ *
+ * @param [in] ifname Interface name (e.g. "eth0")
+ *
+ * @retval number The MTU in bytes
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static int getMtu(const char *ifname) {
+ PIP_ADAPTER_ADDRESSES pAddresses = NULL;
+ PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
+ ULONG outBufLen = 0;
+ ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
+ ULONG family = AF_UNSPEC;
+
+ DWORD dwSize = 0;
+ DWORD dwRetVal = 0;
+ ULONG Iterations = 0;
+ do {
+ pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
+ if (pAddresses == NULL) {
+ printf("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
+ exit(1);
+ }
+
+ dwRetVal =
+ GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
+
+ if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
+ FREE(pAddresses);
+ pAddresses = NULL;
+ } else {
+ break;
+ }
+
+ Iterations++;
+
+ } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
+
+ if (dwRetVal == NO_ERROR) {
+ pCurrAddresses = pAddresses;
+ while (pCurrAddresses) {
+ if (strcmp(pCurrAddresses->AdapterName, ifname)) {
+ int mtu = pCurrAddresses->Mtu;
+ if (pAddresses) {
+ FREE(pAddresses);
+ }
+ return mtu;
+ }
+ pCurrAddresses = pCurrAddresses->Next;
+ }
+ }
+
+ if (pAddresses) {
+ FREE(pAddresses);
+ }
+ return -1;
+}
+
+InterfaceSet *system_Interfaces(Forwarder *forwarder) {
+ InterfaceSet *set = interfaceSetCreate();
+
+ Logger *logger = forwarder_GetLogger(forwarder);
+
+ DWORD dwSize = 0;
+ DWORD dwRetVal = 0;
+ unsigned int i = 0;
+ // Set the flags to pass to GetAdaptersAddresses
+ ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
+
+ // default to unspecified address family (both)
+ ULONG family = AF_UNSPEC;
+
+ LPVOID lpMsgBuf = NULL;
+
+ PIP_ADAPTER_ADDRESSES pAddresses = NULL;
+ ULONG outBufLen = 0;
+ ULONG Iterations = 0;
+
+ PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
+ PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
+ PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
+ PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
+ IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
+ IP_ADAPTER_PREFIX *pPrefix = NULL;
+
+ outBufLen = WORKING_BUFFER_SIZE;
+
+ do {
+ pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
+ parcAssertNotNull(
+ pAddresses,
+ "Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
+ dwRetVal =
+ GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
+
+ if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
+ FREE(pAddresses);
+ pAddresses = NULL;
+ } else {
+ break;
+ }
+
+ Iterations++;
+
+ } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
+ if (dwRetVal == NO_ERROR) {
+ // If successful, output some information from the data we received
+ pCurrAddresses = pAddresses;
+ while (pCurrAddresses) {
+ if (pCurrAddresses->OperStatus == IfOperStatusUp) {
+ Interface *iface =
+ interfaceSetGetByName(set, pCurrAddresses->AdapterName);
+ if (iface == NULL) {
+ pMulticast = pCurrAddresses->FirstMulticastAddress;
+ if (pMulticast) {
+ for (i = 0; pMulticast != NULL; i++) pMulticast = pMulticast->Next;
+ }
+
+ iface = interfaceCreate(
+ pCurrAddresses->AdapterName,
+ forwarder_GetNextConnectionId(forwarder),
+ pCurrAddresses->IfType == IF_TYPE_SOFTWARE_LOOPBACK, i > 0,
+ pCurrAddresses->Mtu);
+
+ interfaceSetAdd(set, iface);
+ for (pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != NULL;
+ pUnicast = pUnicast->Next) {
+ int family = pUnicast->Address.lpSockaddr->sa_family;
+
+ switch (family) {
+ case AF_INET: {
+ char *ip = inet_ntoa(
+ ((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))
+ ->sin_addr);
+ Address *address = addressCreateFromInet(
+ (struct sockaddr_in *)(pUnicast->Address.lpSockaddr));
+ interfaceAddAddress(iface, address);
+ break;
+ }
+
+ case AF_INET6: {
+ char str[INET6_ADDRSTRLEN];
+ inet_ntop(
+ AF_INET6,
+ &((struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr))
+ ->sin6_addr,
+ str, INET6_ADDRSTRLEN);
+ Address *address = addressCreateFromInet6(
+ (struct sockaddr_in6 *)(pUnicast->Address.lpSockaddr));
+ interfaceAddAddress(iface, address);
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ pCurrAddresses = pCurrAddresses->Next;
+ }
+ }
+
+ if (pAddresses) {
+ FREE(pAddresses);
+ }
+ return set;
+}
+
+Address *system_GetMacAddressByName(Forwarder *forwarder,
+ const char *interfaceName) {
+ return NULL;
+}
+
+unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) {
+ unsigned mtu = 0;
+
+ return mtu;
+}
diff --git a/hicn-light/src/hicn/platforms/windows/win_portability.c b/hicn-light/src/hicn/platforms/windows/win_portability.c
index 3138640dd..e063cec24 100644
--- a/hicn-light/src/hicn/platforms/windows/win_portability.c
+++ b/hicn-light/src/hicn/platforms/windows/win_portability.c
@@ -1,50 +1,54 @@
-/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/platforms/windows/win_portability.h>
-
-int getline(char **lineptr, size_t *n, FILE *stream) {
- static char line[256];
- char *ptr;
- unsigned int len;
-
- if (lineptr == NULL || n == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (ferror(stream)) return -1;
-
- if (feof(stream)) return -1;
-
- fgets(line, 256, stream);
-
- ptr = strchr(line, '\n');
- if (ptr) *ptr = '\0';
-
- len = (unsigned int)strlen(line);
-
- if ((len + 1) < 256) {
- ptr = (char *)realloc(*lineptr, 256);
- if (ptr == NULL) return (-1);
- *lineptr = ptr;
- *n = 256;
- }
-
- strcpy(*lineptr, line);
- return (len);
+/*
+ * 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/platforms/windows/win_portability.h>
+#include <hicn/util/sstrncpy.h>
+
+int getline(char **lineptr, size_t *n, FILE *stream) {
+ static char line[256];
+ char *ptr;
+ unsigned int len;
+ int rc;
+
+ if (lineptr == NULL || n == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (ferror(stream)) return -1;
+
+ if (feof(stream)) return -1;
+
+ fgets(line, 256, stream);
+
+ ptr = strchr(line, '\n');
+ if (ptr) *ptr = '\0';
+
+ len = (unsigned int)strlen(line);
+
+ if ((len + 1) < 256) {
+ ptr = (char *)realloc(*lineptr, 256);
+ if (ptr == NULL) return (-1);
+ *lineptr = ptr;
+ *n = 256;
+ }
+
+ rc = strcpy_s(*lineptr, 256, line);
+ if (rc != EOK) return -1;
+
+ return (len);
} \ No newline at end of file
diff --git a/hicn-light/src/hicn/platforms/windows/win_portability.h b/hicn-light/src/hicn/platforms/windows/win_portability.h
index 5c25f4bb2..f42bf9d53 100644
--- a/hicn-light/src/hicn/platforms/windows/win_portability.h
+++ b/hicn-light/src/hicn/platforms/windows/win_portability.h
@@ -1,45 +1,45 @@
-/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-#include <parc/windows/parc_Utils.h>
-#include <afunix.h>
-#include <io.h>
-#include <iphlpapi.h>
-#include <process.h>
-#include <stdio.h>
-#pragma comment(lib, "IPHLPAPI.lib")
-
-#ifndef in_port_t
-#define in_port_t uint16_t
-#endif
-
-#ifndef in_addr_t
-#define in_addr_t uint32_t
-#endif
-
-#ifndef strncasecmp
-#define strncasecmp _strnicmp
-#endif
-
-#ifndef strcasecmp
-#define strcasecmp _stricmp
-#endif
-
-#define HAVE_STRUCT_TIMESPEC
-
-#ifndef getline
-int getline(char **lineptr, size_t *n, FILE *stream);
+/*
+ * 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 <parc/windows/parc_Utils.h>
+#include <afunix.h>
+#include <io.h>
+#include <iphlpapi.h>
+#include <process.h>
+#include <stdio.h>
+#pragma comment(lib, "IPHLPAPI.lib")
+
+#ifndef in_port_t
+#define in_port_t uint16_t
+#endif
+
+#ifndef in_addr_t
+#define in_addr_t uint32_t
+#endif
+
+#ifndef strncasecmp
+#define strncasecmp _strnicmp
+#endif
+
+#ifndef strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+#define HAVE_STRUCT_TIMESPEC
+
+#ifndef getline
+int getline(char **lineptr, size_t *n, FILE *stream);
#endif \ No newline at end of file
diff --git a/hicn-light/src/hicn/processor/CMakeLists.txt b/hicn-light/src/hicn/processor/CMakeLists.txt
deleted file mode 100644
index 17c3b1f88..000000000
--- a/hicn-light/src/hicn/processor/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/fibEntry.h
- ${CMAKE_CURRENT_SOURCE_DIR}/fibEntryList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/messageProcessor.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hashTableFunction.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pit.h
- ${CMAKE_CURRENT_SOURCE_DIR}/fib.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pitEntry.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pitVerdict.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pitStandard.h
-)
-
-list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hashTableFunction.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fib.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fibEntry.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fibEntryList.c
- ${CMAKE_CURRENT_SOURCE_DIR}/messageProcessor.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pit.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pitEntry.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pitStandard.c
-)
-
-set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/processor/fib.c b/hicn-light/src/hicn/processor/fib.c
deleted file mode 100644
index de0d1e2ef..000000000
--- a/hicn-light/src/hicn/processor/fib.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/core/forwarder.h>
-#include <hicn/processor/fib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct node;
-typedef struct node FibNode;
-
-struct node {
- FibNode *left;
- FibNode *right;
- FibEntry *entry;
- bool is_used;
-};
-
-struct fib {
- Forwarder *forwarder;
- FibNode *root;
- unsigned size;
-};
-
-// =====================================================
-// Public API
-
-FibNode *_createNode(FibNode *left, FibNode *right, FibEntry *entry,
- bool is_used) {
- FibNode *n = parcMemory_AllocateAndClear(sizeof(FibNode));
- parcAssertNotNull(n, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(FibNode));
-
- n->left = left;
- n->right = right;
- n->entry = entry;
- n->is_used = is_used;
-
- return n;
-}
-
-FIB *fib_Create(Forwarder *forwarder) {
- FIB *hicnFib = parcMemory_AllocateAndClear(sizeof(FIB));
- parcAssertNotNull(hicnFib, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(FIB));
-
- hicnFib->forwarder = forwarder;
- hicnFib->root = NULL;
- hicnFib->size = 0;
-
- return hicnFib;
-}
-
-void _destroyNode(FibNode *n) {
- fibEntry_Release(&n->entry);
- parcMemory_Deallocate((void **)&n);
- n = NULL;
-}
-
-void _destroyFib(FibNode *n) {
- if(n != NULL){
- _destroyFib(n->right);
- _destroyFib(n->left);
- _destroyNode(n);
- }
-}
-
-void fib_Destroy(FIB **fibPtr) {
- parcAssertNotNull(fibPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*fibPtr, "Parameter must dereference to non-null pointer");
-
- FIB *fib = *fibPtr;
- _destroyFib(fib->root);
-
- parcMemory_Deallocate((void **)&fib);
- *fibPtr = NULL;
-}
-
-void fib_Add(FIB *fib, FibEntry *entry) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(entry, "Parameter must be non-null");
-
- NameBitvector *new_prefix = name_GetContentName(fibEntry_GetPrefix(entry));
- uint32_t new_prefix_len = nameBitvector_GetLength(new_prefix);
- FibNode * curr = fib->root;
- FibNode * last = NULL;
-
- NameBitvector *curr_name;
- uint32_t curr_prefix_len;
- uint32_t match_len;
-
- while(curr != NULL){
- curr_name = name_GetContentName(fibEntry_GetPrefix(curr->entry));
-
- match_len = nameBitvector_lpm(new_prefix, curr_name);
- curr_prefix_len = nameBitvector_GetLength(curr_name);
-
- if(curr_prefix_len != match_len || //the new entry does not match the curr
- curr_prefix_len >= new_prefix_len) //in this case we cannot procede anymore
- break;
-
- last = curr;
- bool bit;
- int res = nameBitvector_testBit(new_prefix, curr_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_add)");
- if(bit)
- curr = curr->right;
- else
- curr = curr->left;
- }
-
- //this is the root (empty trie) or an empty child
- if(curr == NULL){
- FibNode * new_node = _createNode(NULL, NULL, entry, true);
- if(last == NULL){
- fib->root = new_node;
- }else{
- uint32_t last_prefix_len = nameBitvector_GetLength(
- name_GetContentName(fibEntry_GetPrefix(last->entry)));
- bool bit;
- int res = nameBitvector_testBit(new_prefix, last_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_add)");
- if(bit)
- last->right = new_node;
- else
- last->left = new_node;
- }
- fib->size++;
- return;
- }
-
- //curr is not null
-
- //the node already exist
- //if is not in use we turn it on and we set the rigth fib entry
- if(curr_prefix_len == match_len && new_prefix_len == match_len){
- if(!curr->is_used){
- curr->is_used = true;
- curr->entry = entry;
- fib->size++;
- return;
- }else{
- //this case should never happen beacuse of the way we add
- //entries in the fib
- const NumberSet * next_hops = fibEntry_GetNexthops(entry);
- unsigned size = (unsigned)fibEntry_NexthopCount(entry);
- for(unsigned i = 0; i < size; i++)
- fibEntry_AddNexthop(curr->entry,numberSet_GetItem(next_hops, i));
- }
- }
-
- //key is prefix of the curr node (so new_prefix_len < curr_prefix_len)
- if(new_prefix_len == match_len){
- FibNode * new_node = _createNode(NULL, NULL, entry, true);
- if(last == NULL){
- fib->root = new_node;
- }else{
- uint32_t last_prefix_len = nameBitvector_GetLength(
- name_GetContentName(fibEntry_GetPrefix(last->entry)));
-
- bool bit;
- int res = nameBitvector_testBit(new_prefix, last_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_add)");
- if(bit)
- last->right = new_node;
- else
- last->left = new_node;
- }
- bool bit;
- int res = nameBitvector_testBit(curr_name, match_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_add)");
- if(bit)
- new_node->right = curr;
- else
- new_node->left = curr;
- fib->size++;
- return;
- }
-
- //in the last case we need to add an inner node
- Name * inner_prefix = name_Copy(fibEntry_GetPrefix(entry));
- nameBitvector_clear(name_GetContentName(inner_prefix), match_len);
- name_setLen(inner_prefix, match_len);
-
- //this is an inner node, we don't want an acctive strategy
- //like low_latency that sends probes in this node
- FibEntry * inner_entry = fibEntry_Create(inner_prefix,
- SET_STRATEGY_LOADBALANCER, fib->forwarder);
-
- FibNode * inner_node = _createNode(NULL, NULL, inner_entry, false);
- FibNode * new_node = _createNode(NULL, NULL, entry, true);
-
- if(last == NULL){
- //we need to place the inner_node at the root
- fib->root = inner_node;
- }else{
- uint32_t last_prefix_len = nameBitvector_GetLength(
- name_GetContentName(fibEntry_GetPrefix(last->entry)));
- bool bit;
- int res = nameBitvector_testBit(name_GetContentName(inner_prefix),
- last_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_add)");
- if(bit)
- last->right = inner_node;
- else
- last->left = inner_node;
- }
-
- bool bit;
- int res = nameBitvector_testBit(new_prefix, match_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_add)");
-
- if(bit){
- inner_node -> left = curr;
- inner_node ->right = new_node;
- }else{
- inner_node -> left = new_node;
- inner_node ->right = curr;
- }
- fib->size ++;
-
- name_Release(&inner_prefix);
-}
-
-FibEntry *fib_Contains(const FIB *fib, const Name *prefix) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(prefix, "Parameter must be non-null");
-
- NameBitvector *key_name = name_GetContentName(prefix);
- uint32_t key_prefix_len = nameBitvector_GetLength(key_name);
-
- FibNode * curr = fib->root;
-
- while(curr != NULL){
- NameBitvector *curr_name =
- name_GetContentName(fibEntry_GetPrefix(curr->entry));
- uint32_t match_len = nameBitvector_lpm(key_name, curr_name);
- uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name);
-
- if(match_len < curr_prefix_len){
- //the current node does not match completelly the key, so
- //the key is not in the trie
- //this implies curr_prefix_len > key_prefix_len
- return NULL;
- }
-
- if(curr_prefix_len == key_prefix_len){ //== match_len
- //this is an exact match
- if(curr->is_used){
- //we found the key
- return curr->entry;
- }else{
- //the key does not exists
- return NULL;
- }
- }
-
- bool bit;
- int res = nameBitvector_testBit(key_name, curr_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_contains)");
-
- if(bit)
- curr = curr->right;
- else
- curr = curr->left;
- }
-
- return NULL;
-}
-
-void _removeNode(FIB *fib, const Name *prefix){
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(prefix, "Parameter must be non-null");
-
- NameBitvector *key_name = name_GetContentName(prefix);
- uint32_t key_prefix_len = nameBitvector_GetLength(key_name);
-
- FibNode * curr = fib->root;
- FibNode * parent = NULL;
- FibNode * grandpa = NULL;
-
- uint32_t match_len;
- uint32_t curr_prefix_len;
- while(curr != NULL){
- NameBitvector *curr_name =
- name_GetContentName(fibEntry_GetPrefix(curr->entry));
- match_len = nameBitvector_lpm(key_name, curr_name);
- curr_prefix_len = nameBitvector_GetLength(curr_name);
-
- if(match_len < curr_prefix_len ||
- curr_prefix_len == key_prefix_len){
- break;
- }
-
- grandpa = parent;
- parent = curr;
-
- bool bit;
- int res = nameBitvector_testBit(key_name, curr_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (_removeNode)");
-
- if(bit)
- curr = curr->right;
- else
- curr = curr->left;
- }
-
- if(curr == NULL ||
- !curr->is_used ||
- (curr_prefix_len != key_prefix_len)){
- //the node does not exists
- return;
- }
-
- //curr has 2 children, leave it there and mark it as inner
- if(curr->right != NULL && curr->left != NULL){
- curr->is_used = false;
- fib->size--;
- return;
- }
-
- //curr has no children
- if(curr->right == NULL && curr->left == NULL){
- if (parent == NULL){
- //curr is the root and is the only node in the fib
- fib->root = NULL;
- fib->size--;
- _destroyNode(curr);
- return;
- }
- if(grandpa == NULL){
- //parent is the root
- if(fib->root->left == curr)
- fib->root->left = NULL;
- else
- fib->root->right = NULL;
- fib->size--;
- _destroyNode(curr);
- return;
- }
- if(!parent->is_used){
- //parent is an inner node
- //remove curr and inner_node (parent), connect the other child
- //of the parent to the grandpa
- FibNode * tmp;
- if(parent->right == curr)
- tmp = parent->left;
- else
- tmp = parent->right;
-
- if(grandpa->right == parent)
- grandpa->right = tmp;
- else
- grandpa->left = tmp;
-
- fib->size--;
- _destroyNode(curr);
- _destroyNode(parent);
- return;
- }
- //parent is node not an inner_node
- //just remove curr the node
- if(parent->right == curr)
- parent->right = NULL;
- else
- parent->left = NULL;
- fib->size--;
- _destroyNode(curr);
- return;
- }
-
- //curr has one child
- if(curr->right != NULL || curr->left != NULL){
- if(parent == NULL){
- //curr is the root
- if(fib->root->right != NULL)
- fib->root = fib->root->right;
- else
- fib->root = fib->root->left;
- fib->size--;
- _destroyNode(curr);
- return;
- }
- //attach the child of curr to parent
- FibNode * tmp;
- if(curr->right != NULL)
- tmp = curr->right;
- else
- tmp = curr->left;
-
- if(parent->right == curr)
- parent->right = tmp;
- else
- parent->left = tmp;
-
- fib->size--;
- _destroyNode(curr);
- return;
- }
-}
-
-void fib_Remove(FIB *fib, const Name *name, unsigned connId) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(name, "Parameter must be non-null");
-
- FibEntry *entry = fib_Contains(fib, name);
-
- if (entry == NULL) {
- return;
- }
-
- fibEntry_RemoveNexthopByConnectionId(entry, connId);
-#ifndef WITH_MAPME
- if (fibEntry_NexthopCount(entry) == 0)
- _removeNode(fib, name);
-#endif /* WITH_MAPME */
-
- // XXX We never release the FIB entry here it seems, including the inner
- // prefix
-
-}
-
-void _removeConnectionId(FibNode *n, unsigned connectionId,
- FibEntryList *list) {
- if(n != NULL){
- if(n->is_used){
- fibEntry_RemoveNexthopByConnectionId(n->entry, connectionId);
-#ifndef WITH_MAPME
- if (fibEntry_NexthopCount(n->entry) == 0) {
- fibEntryList_Append(list, n->entry);
- }
-#endif /* WITH_MAPME */
- }
- _removeConnectionId(n->right, connectionId, list);
- _removeConnectionId(n->left, connectionId, list);
- }
-}
-
-void fib_RemoveConnectionId(FIB *fib, unsigned connectionId) {
- parcAssertNotNull(fib, "Parameter must be non-null");
-
- FibEntryList *list = fibEntryList_Create();
- _removeConnectionId(fib->root, connectionId, list);
-
- for (int i = 0; i < fibEntryList_Length(list); i++) {
- _removeNode(fib, fibEntry_GetPrefix(fibEntryList_Get(list, i)));
- }
-
- fibEntryList_Destroy(&list);
-}
-
-size_t fib_Length(const FIB *fib) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- return fib->size;
-}
-
-FibEntry *fib_MatchMessage(const FIB *fib, const Message *interestMessage) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(interestMessage, "Parameter must be non-null");
- return fib_MatchBitvector(fib, name_GetContentName(
- message_GetName(interestMessage)));
-}
-
-FibEntry *fib_MatchName(const FIB *fib, const Name *name) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(name, "Parameter must be non-null");
- return fib_MatchBitvector(fib, name_GetContentName(name));
-}
-
-
-FibEntry *fib_MatchBitvector(const FIB *fib, const NameBitvector *name){
- parcAssertNotNull(fib, "Parameter must be non-null");
- parcAssertNotNull(name, "Parameter must be non-null");
-
- uint32_t key_prefix_len = nameBitvector_GetLength(name);
-
- FibNode * curr = fib->root;
- FibNode * candidate = NULL;
-
- while(curr != NULL){
- NameBitvector *curr_name =
- name_GetContentName(fibEntry_GetPrefix(curr->entry));
- uint32_t match_len = nameBitvector_lpm(name, curr_name);
- uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name);
-
- if(match_len < curr_prefix_len){
- //the current node does not match completelly the key, so
- //return the parent of this node (saved in candidate)
- break;
- }
-
- if(curr->is_used)
- candidate = curr;
-
- //if we are here match_len == curr_prefix_len (can't be larger)
- //so this node is actually a good candidate for a match
- if(curr_prefix_len == key_prefix_len){
- //this an exact match, do not continue
- break;
- }
-
- bool bit;
- int res = nameBitvector_testBit(name, curr_prefix_len, &bit);
- parcAssertFalse(res < 0, "error testing name bit (fib_MatchBitvector)");
-
- if(bit)
- curr = curr->right;
- else
- curr = curr->left;
- }
-
- if(candidate != NULL){
- return candidate->entry;
- }
-
- return NULL;
-}
-
-void _collectFibEntries(FibNode *n, FibEntryList *list){
- if(n != NULL){
- if(n->is_used)
- fibEntryList_Append(list, n->entry);
- _collectFibEntries(n->right, list);
- _collectFibEntries(n->left, list);
- }
-}
-
-FibEntryList *fib_GetEntries(const FIB *fib) {
- parcAssertNotNull(fib, "Parameter must be non-null");
- FibEntryList *list = fibEntryList_Create();
-
- _collectFibEntries(fib->root, list);
-
- return list;
-}
diff --git a/hicn-light/src/hicn/processor/fib.h b/hicn-light/src/hicn/processor/fib.h
deleted file mode 100644
index ef9e121b8..000000000
--- a/hicn-light/src/hicn/processor/fib.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef fib_h
-#define fib_h
-
-#include <hicn/core/message.h>
-#include <hicn/core/name.h>
-#include <hicn/processor/fibEntry.h>
-#include <hicn/processor/fibEntryList.h>
-
-struct fib;
-typedef struct fib FIB;
-
-FIB *fib_Create(Forwarder *forwarder);
-
-void fib_Destroy(FIB **fibPtr);
-
-void fib_Add(FIB *fib, FibEntry *node);
-
-FibEntry *fib_Contains(const FIB *fib, const Name *prefix);
-
-void fib_Remove(FIB *fib, const Name *prefix, unsigned connId);
-
-void fib_RemoveConnectionId(FIB *fib, unsigned connectionId);
-
-FibEntry *fib_MatchMessage(const FIB *fib, const Message *interestMessage);
-FibEntry *fib_MatchName(const FIB *fib, const Name *name);
-FibEntry *fib_MatchBitvector(const FIB *fib, const NameBitvector *name);
-
-size_t fib_Length(const FIB *fib);
-
-FibEntryList *fib_GetEntries(const FIB *fib);
-#endif // fib_h
diff --git a/hicn-light/src/hicn/processor/fibEntry.c b/hicn-light/src/hicn/processor/fibEntry.c
deleted file mode 100644
index 00e8dfa11..000000000
--- a/hicn-light/src/hicn/processor/fibEntry.c
+++ /dev/null
@@ -1,894 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/core/numberSet.h>
-#include <hicn/processor/fibEntry.h>
-
-#include <hicn/core/nameBitvector.h>
-
-#include <hicn/strategies/loadBalancer.h>
-#include <hicn/strategies/lowLatency.h>
-#include <hicn/strategies/rnd.h>
-#include <hicn/strategies/strategyImpl.h>
-#ifdef WITH_MAPME
-#include <parc/algol/parc_HashMap.h>
-#include <hicn/core/ticks.h>
-#endif /* WITH_MAPME */
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/core/connectionState.h>
-
-#ifdef WITH_POLICY
-#include <hicn/core/forwarder.h>
-#include <hicn/policy.h>
-
-#ifdef WITH_MAPME
-#include <hicn/core/mapme.h>
-#endif /* WITH_MAPME */
-
-#define ALPHA 0.5
-
-#endif /* WITH_POLICY */
-
-struct fib_entry {
- Name *name;
- unsigned refcount;
- StrategyImpl *fwdStrategy;
-#ifdef WITH_POLICY
- NumberSet *nexthops;
- const Forwarder * forwarder;
- hicn_policy_t policy;
- policy_counters_t policy_counters;
-// NumberSet *available_nexthops;
-#ifdef WITH_MAPME
- /* In case of no multipath, this stores the previous decision taken by policy */
-#endif /* WITH_MAPME */
-#endif /* WITH_POLICY */
-#ifdef WITH_MAPME
- NumberSet * previous_nexthops;
- const void *userDataOwner;
- void *userData;
- void (*userDataRelease)(const void *owner, void **userData);
-#endif /* WITH_MAPME */
-};
-
-#ifdef WITH_POLICY
-FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy, const Forwarder * forwarder) {
-#else
-FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy) {
-#endif /* WITH_POLICY */
- FibEntry *fibEntry = parcMemory_AllocateAndClear(sizeof(FibEntry));
- parcAssertNotNull(fibEntry, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(FibEntry));
- fibEntry->name = name_Acquire(name);
-
- switch (fwdStrategy) {
- case SET_STRATEGY_LOADBALANCER:
- fibEntry->fwdStrategy = strategyLoadBalancer_Create();
- break;
-
- case SET_STRATEGY_RANDOM:
- fibEntry->fwdStrategy = strategyRnd_Create();
-
- case SET_STRATEGY_LOW_LATENCY:
- fibEntry->fwdStrategy = strategyLowLatency_Create();
- break;
-
- default:
- // LB is the default strategy
- fwdStrategy = SET_STRATEGY_LOADBALANCER;
- fibEntry->fwdStrategy = strategyLoadBalancer_Create();
- break;
- }
-
- fibEntry->refcount = 1;
-
-#ifdef WITH_MAPME
- fibEntry->userDataOwner = NULL;
- fibEntry->userData = NULL;
- fibEntry->userDataRelease = NULL;
-#endif /* WITH_MAPME */
-
-#ifdef WITH_POLICY
- fibEntry->nexthops = numberSet_Create();
- fibEntry->forwarder = forwarder;
- fibEntry->policy = POLICY_NONE;
- fibEntry->policy_counters = POLICY_COUNTERS_NONE;
-#endif /* WITH_POLICY */
-
- if(fwdStrategy == SET_STRATEGY_LOW_LATENCY){
- strategyLowLatency_SetStrategy(fibEntry->fwdStrategy,
- fibEntry->forwarder, fibEntry,
- 0, NULL);
- }
- return fibEntry;
-}
-
-FibEntry *fibEntry_Acquire(const FibEntry *fibEntry) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
- FibEntry *copy = (FibEntry *)fibEntry;
- copy->refcount++;
- return copy;
-}
-
-void fibEntry_Release(FibEntry **fibEntryPtr) {
- FibEntry *fibEntry = *fibEntryPtr;
- parcAssertTrue(fibEntry->refcount > 0, "Illegal state: refcount is 0");
- fibEntry->refcount--;
- if (fibEntry->refcount == 0) {
- name_Release(&fibEntry->name);
- fibEntry->fwdStrategy->destroy(&(fibEntry->fwdStrategy));
-#ifdef WITH_MAPME
- if (fibEntry->userData) {
- fibEntry->userDataRelease(fibEntry->userDataOwner, &fibEntry->userData);
- }
-#endif /* WITH_MAPME */
-#ifdef WITH_POLICY
- numberSet_Release(&fibEntry->nexthops);
-#endif /* WITH_POLICY */
- parcMemory_Deallocate((void **)&fibEntry);
- }
- *fibEntryPtr = NULL;
-}
-
-void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy,
- unsigned related_prefixes_len,
- Name **related_prefixes) {
- StrategyImpl *fwdStrategyImpl;
-
- switch (strategy) {
- case SET_STRATEGY_LOADBALANCER:
- fwdStrategyImpl = strategyLoadBalancer_Create();
- break;
-
- case SET_STRATEGY_RANDOM:
- fwdStrategyImpl = strategyRnd_Create();
- break;
-
- case SET_STRATEGY_LOW_LATENCY:
- fwdStrategyImpl = strategyLowLatency_Create();
- break;
-
- default:
- // LB is the default strategy
- strategy = SET_STRATEGY_LOADBALANCER;
- fwdStrategyImpl = strategyLoadBalancer_Create();
- break;
- }
-
- if(strategy == SET_STRATEGY_LOW_LATENCY){
- strategyLowLatency_SetStrategy(fwdStrategyImpl,
- fibEntry->forwarder, fibEntry,
- related_prefixes_len, related_prefixes);
- }
-
- const NumberSet *nexthops = fibEntry_GetNexthops(fibEntry);
- unsigned size = (unsigned)fibEntry_NexthopCount(fibEntry);
- for (unsigned i = 0; i < size; i++) {
- fwdStrategyImpl->addNexthop(fwdStrategyImpl,
- numberSet_GetItem(nexthops, i));
- }
- fibEntry->fwdStrategy->destroy(&(fibEntry->fwdStrategy));
- fibEntry->fwdStrategy = fwdStrategyImpl;
-}
-
-#ifdef WITH_POLICY
-
-/*
- * Update available next hops following policy update.
- */
-NumberSet *
-fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) {
- ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
- NumberSet * nexthops;
- bool dealloc_nexthops = false;
- hicn_policy_t policy = fibEntry_GetPolicy(fibEntry);
-
- /* Reset available next hops and start filtering */
- NumberSet * available_nexthops = numberSet_Create();
-
- /*
- * Give absolute preference to local faces, with no policy, unless
- * in_connection == ~0, which means we are searching faces on which to
- * advertise our prefix
- */
- if (in_connection == ~0) {
- /* We might advertise among all available up connections */
- nexthops = numberSet_Create();
- dealloc_nexthops = true;
-
- ConnectionList * list = connectionTable_GetEntries(table);
- for (size_t i = 0; i < connectionList_Length(list); i++) {
- Connection *conn = connectionList_Get(list, i);
- if (connection_IsLocal(conn))
- continue;
- if (connection_GetAdminState(conn) == CONNECTION_STATE_DOWN)
- continue;
- if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
- continue;
- numberSet_Add(nexthops, connection_GetConnectionId(conn));
- }
- connectionList_Destroy(&list);
- } else {
- nexthops = (NumberSet*)fibEntry_GetNexthops(fibEntry);
- for (size_t k = 0; k < numberSet_Length(nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(nexthops, k);
- /* Filtering out ingress face */
- if (conn_id == in_connection)
- continue;
- /* Filtering out DOWN faces */
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!conn)
- continue;
- if (connection_GetAdminState(conn) == CONNECTION_STATE_DOWN)
- continue;
- if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
- continue;
- if (!connection_IsLocal(conn))
- continue;
- numberSet_Add(available_nexthops, conn_id);
- }
-
- /* Terminate selection if there are any local face available */
- if (numberSet_Length(available_nexthops) > 0){
- if(dealloc_nexthops){
- numberSet_Release(&nexthops);
- }
- /* No filtering as all local faces are considered equivalent */
- return available_nexthops;
- }
- }
-
- for (size_t k = 0; k < numberSet_Length(nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(nexthops, k);
- const Connection * conn;
-
- /* Filtering out ingress face */
- if (conn_id == in_connection)
- continue;
-
- /* Filtering out DOWN faces */
- conn = connectionTable_FindById(table, conn_id);
- if (!conn)
- continue;
- if (connection_GetAdminState(conn) == CONNECTION_STATE_DOWN)
- continue;
- if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
- continue;
-
- /* Policy filtering : next hops */
- if ((policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_REQUIRE) &&
- (!connection_HasTag(conn, POLICY_TAG_WIRED)))
- continue;
- if ((policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PROHIBIT) &&
- (connection_HasTag(conn, POLICY_TAG_WIRED)))
- continue;
- if ((policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_REQUIRE) &&
- (!connection_HasTag(conn, POLICY_TAG_WIFI)))
- continue;
- if ((policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PROHIBIT) &&
- (connection_HasTag(conn, POLICY_TAG_WIFI)))
- continue;
- if ((policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_REQUIRE) &&
- (!connection_HasTag(conn, POLICY_TAG_CELLULAR)))
- continue;
- if ((policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PROHIBIT) &&
- (connection_HasTag(conn, POLICY_TAG_CELLULAR)))
- continue;
- if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) &&
- (!connection_HasTag(conn, POLICY_TAG_TRUSTED)))
- continue;
- if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PROHIBIT) &&
- (connection_HasTag(conn, POLICY_TAG_TRUSTED)))
- continue;
-
- numberSet_Add(available_nexthops, conn_id);
- }
-
- if(dealloc_nexthops)
- numberSet_Release(&nexthops);
-
- if (numberSet_Length(available_nexthops) == 0)
- return available_nexthops;
-
- /* We have at least one matching next hop, implement heuristic */
-
- /*
- * As VPN connections might trigger duplicate uses of one interface, we start
- * by filtering out interfaces based on trust status.
- */
- NumberSet * filtered_nexthops = numberSet_Create();
- if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) ||
- (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PREFER)) {
- /* Try to filter out NON TRUSTED faces */
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!connection_HasTag(conn, POLICY_TAG_TRUSTED))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- } else {
- /* Try to filter out TRUSTED faces */
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (connection_HasTag(conn, POLICY_TAG_TRUSTED))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
-
- /* Other preferences */
- if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_AVOID) {
- filtered_nexthops = numberSet_Create();
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (connection_HasTag(conn, POLICY_TAG_WIRED))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
- }
- if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_AVOID) {
- filtered_nexthops = numberSet_Create();
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (connection_HasTag(conn, POLICY_TAG_WIFI))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
- }
- if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_AVOID) {
- filtered_nexthops = numberSet_Create();
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (connection_HasTag(conn, POLICY_TAG_CELLULAR))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
- }
-
- if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PREFER) {
- filtered_nexthops = numberSet_Create();
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!connection_HasTag(conn, POLICY_TAG_WIRED))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
- }
- if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PREFER) {
- filtered_nexthops = numberSet_Create();
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!connection_HasTag(conn, POLICY_TAG_WIFI))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
- }
- if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PREFER) {
- filtered_nexthops = numberSet_Create();
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!connection_HasTag(conn, POLICY_TAG_CELLULAR))
- continue;
- numberSet_Add(filtered_nexthops, conn_id);
- }
- if (numberSet_Length(filtered_nexthops) > 0) {
- numberSet_Release(&available_nexthops);
- available_nexthops = numberSet_Create();
- numberSet_AddSet(available_nexthops, filtered_nexthops);
- }
- numberSet_Release(&filtered_nexthops);
- }
-
- /* Priority */
- NumberSet * priority_nexthops = numberSet_Create();
-
- uint32_t max_priority = 0;
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- uint32_t priority = connection_GetPriority(conn);
- if (priority < max_priority) {
- continue;
- } else if (priority == max_priority) {
- numberSet_Add(priority_nexthops, conn_id);
- } else { /* priority > max_priority */
- numberSet_Release(&priority_nexthops);
- priority_nexthops = numberSet_Create();
- numberSet_Add(priority_nexthops, conn_id);
- max_priority = priority;
- }
- }
-
- numberSet_Release(&available_nexthops);
-
- return priority_nexthops;
-}
-
-hicn_policy_t fibEntry_GetPolicy(const FibEntry *fibEntry) {
- return fibEntry->policy;
-}
-
-void fibEntry_SetPolicy(FibEntry *fibEntry, hicn_policy_t policy) {
- fibEntry->policy = policy;
- mapme_reconsiderFibEntry(forwarder_getMapmeInstance(fibEntry->forwarder), fibEntry);
-}
-
-NumberSet *
-fibEntry_GetPreviousNextHops(const FibEntry *fibEntry)
-{
- return fibEntry->previous_nexthops;
-}
-#endif /* WITH_POLICY */
-
-void
-fibEntry_SetPreviousNextHops(FibEntry *fibEntry, const NumberSet * nexthops)
-{
- if (fibEntry->previous_nexthops)
- numberSet_Release(&fibEntry->previous_nexthops);
- fibEntry->previous_nexthops = numberSet_Create();
- numberSet_AddSet(fibEntry->previous_nexthops, nexthops);
-}
-
-
-void fibEntry_AddNexthop(FibEntry *fibEntry, unsigned connectionId) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-#ifdef WITH_POLICY
- if (!numberSet_Contains(fibEntry->nexthops, connectionId)) {
- numberSet_Add(fibEntry->nexthops, connectionId);
- }
-#endif /* WITH_POLICY */
- fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId);
-}
-
-void fibEntry_RemoveNexthopByConnectionId(FibEntry *fibEntry,
- unsigned connectionId) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-#ifdef WITH_POLICY
- if (numberSet_Contains(fibEntry->nexthops, connectionId)) {
- numberSet_Remove(fibEntry->nexthops, connectionId);
- }
-#endif /* WITH_POLICY */
- fibEntry->fwdStrategy->removeNexthop(fibEntry->fwdStrategy, connectionId);
-}
-
-size_t fibEntry_NexthopCount(const FibEntry *fibEntry) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-#ifdef WITH_POLICY
- return numberSet_Length(fibEntry->nexthops);
-#else
- return fibEntry->fwdStrategy->countNexthops(fibEntry->fwdStrategy);
-#endif /* WITH_POLICY */
-}
-
-const NumberSet *fibEntry_GetNexthops(const FibEntry *fibEntry) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-#ifdef WITH_POLICY
- return fibEntry->nexthops;
-#else
- return fibEntry->fwdStrategy->returnNexthops(fibEntry->fwdStrategy);
-#endif /* WITH_POLICY */
-}
-
-const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy(
-#ifdef WITH_POLICY
- FibEntry *fibEntry, const Message *interestMessage, bool is_retransmission) {
-#else
- const FibEntry *fibEntry, const Message *interestMessage) {
-#endif /* WITH_POLICY */
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-#ifdef WITH_POLICY
- ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
- unsigned in_connection = message_GetIngressConnectionId(interestMessage);
-
- hicn_policy_t policy = fibEntry_GetPolicy(fibEntry);
-
- NumberSet * out;
-
- /* Filtering */
- NumberSet * available_nexthops = fibEntry_GetAvailableNextHops(fibEntry, in_connection);
- if (numberSet_Length(available_nexthops) == 0) {
- numberSet_Release(&available_nexthops);
- out = numberSet_Create();
- return out;
- }
-
- /*
- * Update statistics about loss rates. We only detect losses upon
- * retransmissions, and assume for the computation that the candidate set of
- * output faces is the same as previously (i.e. does not take into account
- * event such as face up/down, policy update, etc. Otherwise we would need to
- * know what was the previous choice !
- */
- if (is_retransmission) {
- for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
- unsigned conn_id = numberSet_GetItem(available_nexthops, k);
- const Connection * conn = connectionTable_FindById(table, conn_id);
-
- if (connection_HasTag(conn, POLICY_TAG_WIRED))
- fibEntry->policy_counters.wired.num_losses++;
- if (connection_HasTag(conn, POLICY_TAG_WIFI))
- fibEntry->policy_counters.wifi.num_losses++;
- if (connection_HasTag(conn, POLICY_TAG_CELLULAR))
- fibEntry->policy_counters.cellular.num_losses++;
- fibEntry->policy_counters.all.num_losses++;
- }
- }
-
- /*
- * NOTE: We might want to call a forwarding strategy even with no nexthop to
- * take a fallback decision.
- */
- if (numberSet_Length(available_nexthops) == 0) {
- out = numberSet_Create();
- } else {
- /* Multipath */
- if ((policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_PROHIBIT) &&
- (policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_AVOID)) {
- out = fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy, available_nexthops,
- interestMessage);
- } else {
- unsigned nexthop = numberSet_GetItem(available_nexthops, 0);
- out = numberSet_Create();
- numberSet_Add(out, nexthop);
- }
- }
-
- numberSet_Release(&available_nexthops);
-
- return out;
-#else
- return fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy,
- interestMessage);
-#endif /* WITH_POLICY */
-}
-
-#ifdef WITH_POLICY
-void fibEntry_ReceiveObjectMessage(FibEntry *fibEntry,
-#else
-void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry,
-#endif /* WITH_POLICY */
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-
-#ifdef WITH_POLICY
- ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
-
- /* Update statistic counters : */
-
- size_t msg_size = message_Length(objectMessage);
- Ticks rtt = objReception - pitEntryCreation;
-
- for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
- unsigned conn_id = numberSet_GetItem(egressId, i);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!conn)
- continue;
- if (connection_HasTag(conn, POLICY_TAG_WIRED)) {
- fibEntry->policy_counters.wired.num_packets++;
- fibEntry->policy_counters.wired.num_bytes += (uint32_t)msg_size;
- fibEntry->policy.stats.wired.latency = (float) (\
- ALPHA * fibEntry->policy.stats.wired.latency + \
- (1 - ALPHA) * (double)rtt);
- fibEntry->policy_counters.wired.latency_idle = 0;
- }
- if (connection_HasTag(conn, POLICY_TAG_WIFI)) {
- fibEntry->policy_counters.wifi.num_packets++;
- fibEntry->policy_counters.wifi.num_bytes += (uint32_t)msg_size;
- fibEntry->policy.stats.wifi.latency = (float)(\
- ALPHA * fibEntry->policy.stats.wifi.latency + \
- (1 - ALPHA) * (double)rtt);
- fibEntry->policy_counters.wifi.latency_idle = 0;
-
- }
- if (connection_HasTag(conn, POLICY_TAG_CELLULAR)) {
- fibEntry->policy_counters.cellular.num_packets++;
- fibEntry->policy_counters.cellular.num_bytes += (uint32_t)msg_size;
- fibEntry->policy.stats.cellular.latency = (float)(\
- ALPHA * fibEntry->policy.stats.cellular.latency + \
- (1 - ALPHA) * (double)rtt);
- fibEntry->policy_counters.cellular.latency_idle = 0;
- }
- }
-
- fibEntry->policy.stats.all.latency = (float)(\
- ALPHA * fibEntry->policy.stats.all.latency + \
- (1 - ALPHA) * (double)rtt);
- fibEntry->policy_counters.all.latency_idle = 0;
-
- fibEntry->policy_counters.all.num_packets++;
- fibEntry->policy_counters.all.num_bytes += (uint32_t)msg_size;
-
-#endif /* WITH_POLICY */
-
- fibEntry->fwdStrategy->receiveObject(fibEntry->fwdStrategy, egressId,
- objectMessage, pitEntryCreation, objReception);
-}
-
-#ifdef WITH_POLICY
-void fibEntry_OnTimeout(FibEntry *fibEntry, const NumberSet *egressId) {
-#else
-void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId) {
-#endif /* WITH_POLICY */
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
-
-#ifdef WITH_POLICY
-
- ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
-
- for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
- unsigned conn_id = numberSet_GetItem(egressId, i);
- const Connection * conn = connectionTable_FindById(table, conn_id);
- if (!conn)
- continue;
- if (connection_HasTag(conn, POLICY_TAG_WIRED)) {
- fibEntry->policy_counters.wired.num_losses++;
- }
- if (connection_HasTag(conn, POLICY_TAG_WIFI)) {
- fibEntry->policy_counters.wifi.num_losses++;
- }
- if (connection_HasTag(conn, POLICY_TAG_CELLULAR)) {
- fibEntry->policy_counters.cellular.num_losses++;
- }
- }
-
- fibEntry->policy_counters.all.num_losses++;
-
-#endif /* WITH_POLICY */
-
- fibEntry->fwdStrategy->onTimeout(fibEntry->fwdStrategy, egressId);
-}
-
-#ifdef WITH_POLICY
-void fibEntry_UpdateStats(FibEntry *fibEntry, uint64_t now) {
- double throughput;
- double loss_rate;
-
- if (now == fibEntry->policy_counters.last_update)
- return ;
-
- /* WIRED */
-
- /* a) throughput */
- if (fibEntry->policy_counters.wired.num_bytes > 0) {
- throughput = (float)(fibEntry->policy_counters.wired.num_bytes / \
- (now - fibEntry->policy_counters.last_update)) ;
- throughput = throughput * 8 / 1024;
- if (throughput < 0)
- throughput = 0;
- } else {
- throughput = 0;
- }
- fibEntry->policy.stats.wired.throughput = (float)(\
- ALPHA * fibEntry->policy.stats.wired.throughput + \
- (1-ALPHA) * throughput);
-
- /* b) loss rate */
- if ((fibEntry->policy_counters.wired.num_losses > 0) && \
- (fibEntry->policy_counters.wired.num_packets > 0)){
- loss_rate = fibEntry->policy_counters.wired.num_losses / \
- fibEntry->policy_counters.wired.num_packets;
- loss_rate *= 100;
- } else {
- loss_rate = 0;
- }
- fibEntry->policy.stats.wired.loss_rate = (float)(\
- ALPHA * fibEntry->policy.stats.wired.loss_rate + \
- (1-ALPHA) * loss_rate);
-
- /* Latency */
- fibEntry->policy_counters.wired.latency_idle++;
- if (fibEntry->policy_counters.wired.latency_idle > 1)
- fibEntry->policy.stats.wired.latency = 0;
- fibEntry->policy_counters.wifi.latency_idle++;
- if (fibEntry->policy_counters.wifi.latency_idle > 1)
- fibEntry->policy.stats.wifi.latency = 0;
- fibEntry->policy_counters.cellular.latency_idle++;
- if (fibEntry->policy_counters.cellular.latency_idle > 1)
- fibEntry->policy.stats.cellular.latency = 0;
- fibEntry->policy_counters.all.latency_idle++;
- if (fibEntry->policy_counters.all.latency_idle > 1)
- fibEntry->policy.stats.all.latency = 0;
-
- fibEntry->policy_counters.wired.num_bytes = 0;
- fibEntry->policy_counters.wired.num_losses = 0;
- fibEntry->policy_counters.wired.num_packets = 0;
-
- /* WIFI */
-
- /* a) throughput */
- if (fibEntry->policy_counters.wifi.num_bytes > 0) {
- throughput = (float)(fibEntry->policy_counters.wifi.num_bytes / \
- (now - fibEntry->policy_counters.last_update));
- throughput = throughput * 8 / 1024;
- if (throughput < 0)
- throughput = 0;
- } else {
- throughput = 0;
- }
- fibEntry->policy.stats.wifi.throughput = (float)( \
- ALPHA * fibEntry->policy.stats.wifi.throughput + \
- (1-ALPHA) * throughput);
-
- /* b) loss rate */
- if ((fibEntry->policy_counters.wifi.num_losses > 0) && \
- (fibEntry->policy_counters.wifi.num_packets > 0)) {
- loss_rate = fibEntry->policy_counters.wifi.num_losses / \
- fibEntry->policy_counters.wifi.num_packets;
- loss_rate *= 100;
- } else {
- loss_rate = 0;
- }
- fibEntry->policy.stats.wifi.loss_rate = (float)(\
- ALPHA * fibEntry->policy.stats.wifi.loss_rate + \
- (1-ALPHA) * loss_rate);
-
- fibEntry->policy_counters.wifi.num_bytes = 0;
- fibEntry->policy_counters.wifi.num_losses = 0;
- fibEntry->policy_counters.wifi.num_packets = 0;
-
- /* CELLULAR */
-
- /* a) throughput */
- if (fibEntry->policy_counters.cellular.num_bytes > 0) {
- throughput = (float)(fibEntry->policy_counters.cellular.num_bytes / \
- (now - fibEntry->policy_counters.last_update)) ;
- throughput = throughput * 8 / 1024;
- if (throughput < 0)
- throughput = 0;
- } else {
- throughput = 0;
- }
- fibEntry->policy.stats.cellular.throughput = (float)( \
- ALPHA * fibEntry->policy.stats.cellular.throughput + \
- (1-ALPHA) * throughput);
-
- /* b) loss rate */
- if ((fibEntry->policy_counters.cellular.num_losses > 0) && \
- (fibEntry->policy_counters.cellular.num_packets > 0)) {
- loss_rate = fibEntry->policy_counters.cellular.num_losses / \
- fibEntry->policy_counters.cellular.num_packets;
- loss_rate *= 100;
- } else {
- loss_rate = 0;
- }
- fibEntry->policy.stats.cellular.loss_rate = (float)( \
- ALPHA * fibEntry->policy.stats.cellular.loss_rate + \
- (1-ALPHA) * loss_rate);
-
- fibEntry->policy_counters.cellular.num_bytes = 0;
- fibEntry->policy_counters.cellular.num_losses = 0;
- fibEntry->policy_counters.cellular.num_packets = 0;
-
- /* ALL */
-
- /* a) throughput */
- if (fibEntry->policy_counters.all.num_bytes > 0) {
- throughput = (float)( fibEntry->policy_counters.all.num_bytes / \
- (now - fibEntry->policy_counters.last_update));
- throughput = throughput * 8 / 1024;
- if (throughput < 0)
- throughput = 0;
- } else {
- throughput = 0;
- }
- fibEntry->policy.stats.all.throughput = (float)(\
- ALPHA * fibEntry->policy.stats.all.throughput + \
- (1-ALPHA) * throughput);
-
- /* b) loss rate */
- if ((fibEntry->policy_counters.all.num_losses > 0) && \
- (fibEntry->policy_counters.all.num_packets > 0)) {
- loss_rate = fibEntry->policy_counters.all.num_losses / \
- fibEntry->policy_counters.all.num_packets;
- loss_rate *= 100;
- } else {
- loss_rate = 0;
- }
- fibEntry->policy.stats.all.loss_rate = (float)(\
- ALPHA * fibEntry->policy.stats.all.loss_rate + \
- (1-ALPHA) * loss_rate);
-
- fibEntry->policy_counters.all.num_bytes = 0;
- fibEntry->policy_counters.all.num_losses = 0;
- fibEntry->policy_counters.all.num_packets = 0;
-
- fibEntry->policy_counters.last_update = now;
-}
-#endif /* WITH_POLICY */
-
-Name *fibEntry_GetPrefix(const FibEntry *fibEntry) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
- return fibEntry->name;
- // return metisName_Acquire(fibEntry->name);
-}
-
-strategy_type fibEntry_GetFwdStrategyType(const FibEntry *fibEntry) {
- return fibEntry->fwdStrategy->getStrategy(fibEntry->fwdStrategy);
-}
-
-StrategyImpl *fibEntry_GetFwdStrategy(const FibEntry *fibEntry) {
- return fibEntry->fwdStrategy;
-}
-
-#ifdef WITH_MAPME
-
-void *fibEntry_getUserData(const FibEntry *fibEntry) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
- return fibEntry->userData;
-}
-
-void fibEntry_setUserData(FibEntry *fibEntry, const void *userDataOwner, const
- void *userData, void (*userDataRelease)(const void *, void **)) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
- fibEntry->userDataOwner = userDataOwner;
- fibEntry->userData = (void *)userData;
- fibEntry->userDataRelease = userDataRelease;
-}
-
-#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/processor/fibEntry.h b/hicn-light/src/hicn/processor/fibEntry.h
deleted file mode 100644
index cf267d6a6..000000000
--- a/hicn-light/src/hicn/processor/fibEntry.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file fibEntry.h
- * @brief A forwarding entry in the FIB table
- *
- * A Forwarding Information Base (FIB) entry (FibEntry) is a
- * set of nexthops for a name. It also indicates the forwarding strategy.
- *
- * Each nexthop contains the ConnectionId assocaited with it. This could be
- * something specific like a MAC address or point-to-point tunnel. Or, it
- * could be something general like a MAC group address or ip multicast overlay.
- *
- * See strategy.h for a description of forwarding strategies.
- * In short, a strategy is the algorithm used to select one or more nexthops
- * from the set of available nexthops.
- *
- * Each nexthop also contains a void* to a forwarding strategy data container.
- * This allows a strategy to keep proprietary information about each nexthop.
- *
- *
- */
-
-#ifndef fibEntry_h
-#define fibEntry_h
-
-#include <hicn/core/name.h>
-#include <hicn/strategies/strategyImpl.h>
-
-#ifdef WITH_POLICY
-#include <hicn/core/connectionTable.h>
-#endif /* WITH_POLICY */
-
-#ifdef WITH_MAPME
-#include <parc/algol/parc_EventTimer.h>
-#include <parc/algol/parc_Iterator.h>
-#endif /* WITH_MAPME */
-
-struct fib_entry;
-typedef struct fib_entry FibEntry;
-
-#ifdef WITH_POLICY
-struct forwarder;
-FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy, const struct forwarder * table);
-#else
-FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy);
-#endif
-
-/**
- * Decrements the reference count by one, and destroys the memory after last
- * release
- *
- */
-void fibEntry_Release(FibEntry **fibEntryPtr);
-
-/**
- * Returns a reference counted copy of the fib entry
- *
- * The reference count is increased by one. The returned value must be
- * released via fibEnty_Release().
- *
- * @param [in] fibEntry An allocated FibEntry
- *
- * @return non-null A reference counted copy of the fibEntry
- *
- */
-FibEntry *fibEntry_Acquire(const FibEntry *fibEntry);
-
-void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy,
- unsigned related_prefixes_len,
- Name **related_prefixes);
-
-void fibEntry_AddNexthop(FibEntry *fibEntry, unsigned connectionId);
-
-void fibEntry_RemoveNexthopByConnectionId(FibEntry *fibEntry,
- unsigned connectionId);
-
-size_t fibEntry_NexthopCount(const FibEntry *fibEntry);
-
-/**
- * @function fibEntry_GetNexthops
- * @abstract Returns the nexthop set of the FIB entry. You must Acquire if it
- * will be saved.
- * @discussion
- * Returns the next hop set for the FIB entry.
- */
-const NumberSet *fibEntry_GetNexthops(const FibEntry *fibEntry);
-
-#ifdef WITH_POLICY
-void fibEntry_ReceiveObjectMessage(FibEntry *fibEntry,
-#else
-void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry,
-#endif /* WITH_POLICY */
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-
-#ifdef WITH_POLICY
-hicn_policy_t fibEntry_GetPolicy(const FibEntry *fibEntry);
-void fibEntry_ReconsiderPolicy(FibEntry *fibEntry);
-void fibEntry_SetPolicy(FibEntry *fibEntry, hicn_policy_t policy);
-void fibEntry_UpdateStats(FibEntry *fibEntry, uint64_t now);
-NumberSet * fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection);
-NumberSet * fibEntry_GetPreviousNextHops(const FibEntry *fibEntry);
-void fibEntry_SetPreviousNextHops(FibEntry *fibEntry, const NumberSet * nexthops);
-
-void fibEntry_OnTimeout(FibEntry *fibEntry, const NumberSet *egressId);
-const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy(
- FibEntry *fibEntry, const Message *interestMessage, bool is_retransmission);
-
-#else
-void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId);
-const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy(
- const FibEntry *fibEntry, const Message *interestMessage);
-#endif /* WITH_POLICY */
-
-
-strategy_type fibEntry_GetFwdStrategyType(const FibEntry *fibEntry);
-
-StrategyImpl *fibEntry_GetFwdStrategy(const FibEntry *fibEntry);
-
-/**
- * @function fibEntry_GetPrefix
- * @abstract Returns a copy of the prefix.
- * @return A reference counted copy that you must destroy
- */
-Name *fibEntry_GetPrefix(const FibEntry *fibEntry);
-
-#ifdef WITH_MAPME
-
-/**
- * @function fibEntry_getUserData
- * @abstract Returns user data associated to the FIB entry.
- * @param [in] fibEntry - Pointer to the FIB entry.
- * @return User data as a void pointer
- */
-void *fibEntry_getUserData(const FibEntry *fibEntry);
-
-/**
- * @function fibEntry_getUserData
- * @abstract Associates user data and release callback to a FIB entry.
- * @param [in] fibEntry - Pointer to the FIB entry.
- * @param [in] userData - Generic pointer to user data
- * @param [in@ userDataRelease - Callback used to release user data upon change
- * of FIB entry removal.
- */
-void fibEntry_setUserData(FibEntry *fibEntry, const void *userDataOwner,
- const void *userData, void (*userDataRelease)(const void *, void **));
-
-#endif /* WITH_MAPME */
-
-#endif // fibEntry_h
diff --git a/hicn-light/src/hicn/processor/fibEntryList.c b/hicn-light/src/hicn/processor/fibEntryList.c
deleted file mode 100644
index 56d7b8bea..000000000
--- a/hicn-light/src/hicn/processor/fibEntryList.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/processor/fibEntryList.h>
-
-struct fib_entry_list {
- PARCArrayList *listOfFibEntries;
-};
-
-static void fibEntryList_ListDestroyer(void **voidPtr) {
- FibEntry **entryPtr = (FibEntry **)voidPtr;
- fibEntry_Release(entryPtr);
-}
-
-FibEntryList *fibEntryList_Create() {
- FibEntryList *fibEntryList =
- parcMemory_AllocateAndClear(sizeof(FibEntryList));
- parcAssertNotNull(fibEntryList,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(FibEntryList));
- fibEntryList->listOfFibEntries =
- parcArrayList_Create(fibEntryList_ListDestroyer);
- return fibEntryList;
-}
-
-void fibEntryList_Destroy(FibEntryList **listPtr) {
- parcAssertNotNull(listPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listPtr, "Parameter must dereference to non-null pointer");
-
- FibEntryList *list = *listPtr;
- parcArrayList_Destroy(&list->listOfFibEntries);
- parcMemory_Deallocate((void **)&list);
- listPtr = NULL;
-}
-
-void fibEntryList_Append(FibEntryList *list, FibEntry *fibEntry) {
- parcAssertNotNull(list, "Parameter list must be non-null pointer");
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null pointer");
-
- FibEntry *copy = fibEntry_Acquire(fibEntry);
- parcArrayList_Add(list->listOfFibEntries, copy);
-}
-
-size_t fibEntryList_Length(const FibEntryList *list) {
- parcAssertNotNull(list, "Parameter list must be non-null pointer");
- return parcArrayList_Size(list->listOfFibEntries);
-}
-
-const FibEntry *fibEntryList_Get(const FibEntryList *list, size_t index) {
- parcAssertNotNull(list, "Parameter list must be non-null pointer");
- FibEntry *entry = parcArrayList_Get(list->listOfFibEntries, index);
- return entry;
-}
diff --git a/hicn-light/src/hicn/processor/fibEntryList.h b/hicn-light/src/hicn/processor/fibEntryList.h
deleted file mode 100644
index 072a1b369..000000000
--- a/hicn-light/src/hicn/processor/fibEntryList.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file fibEntryList.h
- * @brief A typesafe list of FibEntry
- *
- * <#Detailed Description#>
- *
- */
-
-#ifndef fibEntryList_h
-#define fibEntryList_h
-
-#include <hicn/processor/fibEntry.h>
-
-struct fib_entry_list;
-typedef struct fib_entry_list FibEntryList;
-
-/**
- * Creates an emtpy FIB entry list
- *
- * Must be destroyed with fibEntryList_Destroy.
- *
- * @retval non-null An allocated FibEntryList
- * @retval null An error
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-FibEntryList *fibEntryList_Create(void);
-
-/**
- * @function FibEntryList_Detroy
- * @abstract Destroys the list and all entries.
- * @discussion
- * <#Discussion#>
- *
- * @param <#param1#>
- */
-void fibEntryList_Destroy(FibEntryList **listPtr);
-
-/**
- * @function fibEntryList_Append
- * @abstract Will store a reference counted copy of the entry.
- * @discussion
- * Will create and store a reference counted copy. You keep ownership
- * of the parameter <code>fibEntry</code>.
- *
- * @param <#param1#>
- * @return <#return#>
- */
-void fibEntryList_Append(FibEntryList *list, FibEntry *fibEntry);
-
-/**
- * Returns the number of entries in the list
- *
- * <#Paragraphs Of Explanation#>
- *
- * @param [in] list An allocated FibEntryList
- *
- * @retval number The number of entries in the list
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-size_t fibEntryList_Length(const FibEntryList *list);
-
-/**
- * @function fibEntryList_Get
- * @abstract Gets an element. This is the internal reference, do not destroy.
- * @discussion
- * Returns an internal reference from the list. You must not destroy it.
- * Will assert if you go off the end of the list.
- *
- * @param <#param1#>
- * @return <#return#>
- */
-const FibEntry *fibEntryList_Get(const FibEntryList *list, size_t index);
-#endif // fibEntryList_h
diff --git a/hicn-light/src/hicn/processor/hashTableFunction.c b/hicn-light/src/hicn/processor/hashTableFunction.c
deleted file mode 100644
index 98afa1294..000000000
--- a/hicn-light/src/hicn/processor/hashTableFunction.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/core/message.h>
-#include <hicn/processor/hashTableFunction.h>
-
-#include <parc/assert/parc_Assert.h>
-
-// ======================================================================
-// Hash table key functions
-// We use a Message as the key data type
-
-bool hashTableFunction_MessageNameEquals(const void *messageA,
- const void *messageB) {
- const Message *a = (const Message *)messageA;
- const Message *b = (const Message *)messageB;
-
- return name_Equals(message_GetName(a), message_GetName(b));
-}
-
-HashCodeType hashTableFunction_MessageNameHashCode(const void *messageA) {
- const Message *message = (const Message *)messageA;
- Name *name = message_GetName(message);
-
- // we want the cumulative hash for the whole name
- uint32_t hash = name_HashCode(name);
-
- return hash;
-} \ No newline at end of file
diff --git a/hicn-light/src/hicn/processor/hashTableFunction.h b/hicn-light/src/hicn/processor/hashTableFunction.h
deleted file mode 100644
index eb9989086..000000000
--- a/hicn-light/src/hicn/processor/hashTableFunction.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file hashTableFunction.h
- * @brief These functions are used in PARCHashCodeTables by the
- * MatchingRulesTable and ContentStore and PIT. They perform the equality
- * and has generation needed by the PARCHashCodeTable.
- *
- */
-#ifndef hashTableFunction_h
-#define hashTableFunction_h
-
-#include <parc/algol/parc_HashCodeTable.h>
-
-// ==========================================================
-// These functions operate on a message as the key in the HashTable.
-// The functions use void * rather than message instances in the function
-// signature because it is using generic has code tables from PARC Library
-
-/**
- * Determine if the Names of two `message` instances are equal.
- *
- * The following equivalence relations on non-null `message` instances are
- * maintained:
- *
- * * It is reflexive: for any non-null reference value x,
- * `hashTableFunction_MessageNameEquals(x, x)` must return true.
- *
- * * It is symmetric: for any non-null reference values x and y,
- * `message_Equals(x, y)` must return true if and only if
- * `hashTableFunction_MessageNameEquals(y, x)` returns true.
- *
- * * It is transitive: for any non-null reference values x, y, and z, if
- * `hashTableFunction_MessageNameEquals(x, y)` returns true and
- * `hashTableFunction_MessageNameEquals(y, z)` returns true,
- * then `hashTableFunction_MessageNameEquals(x, z)` must return true.
- *
- * * It is consistent: for any non-null reference values x and y, multiple
- * invocations of `hashTableFunction_MessageNameEquals(x, y)` consistently
- * return true or consistently return false.
- *
- * * For any non-null reference value x,
- * `hashTableFunction_MessageNameEquals(x, NULL)` must return false.
- *
- * @param a A pointer to a `message` instance.
- * @param b A pointer to a `message` instance.
- * @return true if the names of the two `message` instances are equal.
- */
-bool hashTableFunction_MessageNameEquals(const void *messageA,
- const void *messageB);
-
-/**
- * @function hashTableFunction_NameHashCode
- * @abstract Computes the hash of the entire name in a message
- *
- * @param messageA is a message
- * @return A non-cryptographic hash of Name
- */
-HashCodeType hashTableFunction_MessageNameHashCode(const void *messageA);
-#endif // hashTableFunction_h \ No newline at end of file
diff --git a/hicn-light/src/hicn/processor/matchingRulesTable.c b/hicn-light/src/hicn/processor/matchingRulesTable.c
deleted file mode 100644
index e57239321..000000000
--- a/hicn-light/src/hicn/processor/matchingRulesTable.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/processor/hashTableFunction.h>
-#include <hicn/processor/matchingRulesTable.h>
-
-struct matching_rules_table {
- // using this wrapper we can manatain multiple hash tables indexed in
- // different ways
- // for now we use only a table indexed by name
-
- PARCHashCodeTable *tableByName;
- PARCHashCodeTable_Destroyer dataDestroyer;
-};
-
-static PARCHashCodeTable *matchingRulesTable_GetTableForMessage(
- const MatchingRulesTable *pit, const Message *interestMessage);
-
-// ======================================================================
-
-MatchingRulesTable *matchingRulesTable_Create(
- PARCHashCodeTable_Destroyer dataDestroyer) {
- size_t initialSize = 65535;
-
- MatchingRulesTable *table =
- parcMemory_AllocateAndClear(sizeof(MatchingRulesTable));
- parcAssertNotNull(table, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(MatchingRulesTable));
- table->dataDestroyer = dataDestroyer;
-
- table->tableByName = parcHashCodeTable_Create_Size(
- hashTableFunction_MessageNameEquals,
- hashTableFunction_MessageNameHashCode, NULL, dataDestroyer, initialSize);
-
- return table;
-}
-
-void matchingRulesTable_Destroy(MatchingRulesTable **tablePtr) {
- parcAssertNotNull(tablePtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*tablePtr,
- "Parameter must dereference to non-null pointer");
-
- MatchingRulesTable *table = *tablePtr;
-
- parcHashCodeTable_Destroy(&table->tableByName);
-
- parcMemory_Deallocate((void **)&table);
- *tablePtr = NULL;
-}
-
-void *matchingRulesTable_Get(const MatchingRulesTable *rulesTable,
- const Message *message) {
- parcAssertNotNull(rulesTable, "Parameter rulesTable must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
-
- PARCHashCodeTable *hashTable =
- matchingRulesTable_GetTableForMessage(rulesTable, message);
- return parcHashCodeTable_Get(hashTable, message);
-}
-
-PARCArrayList *matchingRulesTable_GetUnion(const MatchingRulesTable *table,
- const Message *message) {
- PARCArrayList *list = parcArrayList_Create_Capacity(NULL, NULL, 3);
-
- void *dataByName = parcHashCodeTable_Get(table->tableByName, message);
- if (dataByName) {
- parcArrayList_Add(list, dataByName);
- }
-
- return list;
-}
-
-void matchingRulesTable_RemoveFromBest(MatchingRulesTable *rulesTable,
- const Message *message) {
- parcAssertNotNull(rulesTable, "Parameter rulesTable must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
-
- PARCHashCodeTable *hashTable =
- matchingRulesTable_GetTableForMessage(rulesTable, message);
- parcHashCodeTable_Del(hashTable, message);
-}
-
-void matchingRulesTable_RemoveFromAll(MatchingRulesTable *rulesTable,
- const Message *message) {
- parcAssertNotNull(rulesTable, "Parameter rulesTable must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
-
- parcHashCodeTable_Del(rulesTable->tableByName, message);
-}
-
-bool matchingRulesTable_AddToBestTable(MatchingRulesTable *rulesTable,
- Message *key, void *data) {
- parcAssertNotNull(rulesTable, "Parameter rulesTable must be non-null");
- parcAssertNotNull(key, "Parameter key must be non-null");
- parcAssertNotNull(data, "Parameter data must be non-null");
-
- PARCHashCodeTable *hashTable =
- matchingRulesTable_GetTableForMessage(rulesTable, key);
-
- bool success = parcHashCodeTable_Add(hashTable, key, data);
-
- return success;
-}
-
-// ========================================================================================
-
-static PARCHashCodeTable *matchingRulesTable_GetTableForMessage(
- const MatchingRulesTable *pit, const Message *interestMessage) {
- PARCHashCodeTable *table;
- table = pit->tableByName;
-
- return table;
-}
diff --git a/hicn-light/src/hicn/processor/matchingRulesTable.h b/hicn-light/src/hicn/processor/matchingRulesTable.h
deleted file mode 100644
index 64a57d854..000000000
--- a/hicn-light/src/hicn/processor/matchingRulesTable.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header matchingRulesTable
- * @abstract A generic table (void *) that matches a Message
- * @discussion
- * Matching is done based on Name
- *
- * When used in the PIT, one calls
- * <code>matchingRulesTable_AddToBestTable()</code> to add an interest to the
- * "best" (i.e. most restrictive match) table, then calls
- * <code>matchingRulesTable_GetUnion()</code> on a content object to match
- * against all of them.
- *
- * When used in a ContentStore, one calls
- * <code>matchingRulesTable_AddToAllTables()</code> to index a Content Object in
- * all the tables. one then calls <code>matchingRulesTable_Get()</code> with an
- * Interest to do the "best" matching (i.e by hash first, then keyid, then just
- * by name).
- *
- */
-
-#ifndef matchingRulesTable_h
-#define matchingRulesTable_h
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <hicn/core/message.h>
-
-struct matching_rules_table;
-typedef struct matching_rules_table MatchingRulesTable;
-
-/**
- * Creates a MatchigRulesTable and specifies the function to call to de-allocate
- * an entry
- *
- * The datadestroyer will be called when an entry is removed from a table. It
- * may be NULL.
- */
-MatchingRulesTable *matchingRulesTable_Create(
- PARCHashCodeTable_Destroyer dataDestroyer);
-
-/**
- * Destroys the table and removes all stored elements.
- *
- */
-void matchingRulesTable_Destroy(MatchingRulesTable **tablePtr);
-
-/**
- * @function matchingRulesTable_Get
- * @abstract Returns the data item that best matches the message.
- * @discussion
- * Indexed by NameAndContentObjectHash, NameAndKeyId, and Name, in that order.
- *
- * @return NULL if nothing matches, otherwise the stored value
- */
-void *matchingRulesTable_Get(const MatchingRulesTable *table,
- const Message *message);
-
-/**
- * @function matchingRulesTable_GetUnion
- * @abstract Returns matching data items from all index tables.
- * @discussion
- * The PARCArrayList does not have an item destructor, so destroying it will
- * not affect the underlying data.
- *
- * @return Will not be NULL, but may be empty
- */
-PARCArrayList *matchingRulesTable_GetUnion(const MatchingRulesTable *table,
- const Message *message);
-
-/**
- * @function matchingRulesTable_Add
- * @abstract Adds the data to the best table
- * @discussion
- * The key must be derived from the data and destroyed when the data is
- * destroyed. Only the data destroyer is called.
- *
- * No duplicates are allowed, will return false if not added.
- *
- * @return true if unique key and added, false if duplicate and no action taken.
- */
-bool matchingRulesTable_AddToBestTable(MatchingRulesTable *rulesTable,
- Message *key, void *data);
-
-/**
- * @function matchingRulesTable_Remove
- * @abstract Removes the matching entry from the best match table, calling the
- * destroyer on the data.
- */
-void matchingRulesTable_RemoveFromBest(MatchingRulesTable *rulesTable,
- const Message *message);
-
-/**
- * @function matchingRulesTable_RemoveFromAll
- * @abstract Removes the message from all tables
- */
-void matchingRulesTable_RemoveFromAll(MatchingRulesTable *rulesTable,
- const Message *message);
-#endif // matchingRulesTable_h
diff --git a/hicn-light/src/hicn/processor/messageProcessor.c b/hicn-light/src/hicn/processor/messageProcessor.c
deleted file mode 100644
index d3f07cbda..000000000
--- a/hicn-light/src/hicn/processor/messageProcessor.c
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-#ifdef WITH_POLICY
-#include <parc/algol/parc_EventTimer.h>
-#ifdef WITH_MAPME
-#include <hicn/core/connection.h>
-#endif /* WITH_MAPME */
-#endif /* WITH_POLICY */
-#include <hicn/processor/messageProcessor.h>
-
-#include <hicn/processor/fib.h>
-#include <hicn/processor/pitStandard.h>
-
-#include <hicn/content_store/contentStoreInterface.h>
-#include <hicn/content_store/contentStoreLRU.h>
-
-#include <hicn/strategies/loadBalancer.h>
-#include <hicn/strategies/lowLatency.h>
-#include <hicn/strategies/rnd.h>
-#include <hicn/strategies/strategyImpl.h>
-
-#include <hicn/io/streamConnection.h>
-#include <hicn/io/udpListener.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-#include <hicn/utils/address.h>
-#include <hicn/core/messageHandler.h>
-
-#ifdef WITH_POLICY
-#define STATS_INTERVAL 1000 /* ms */
-#endif /* WITH_POLICY */
-
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-typedef struct processor_stats {
- uint32_t countReceived;
- uint32_t countInterestsReceived;
- uint32_t countObjectsReceived;
-
- uint32_t countInterestsAggregated;
-
- uint32_t countDropped;
- uint32_t countInterestsDropped;
- uint32_t countDroppedNoRoute;
- uint32_t countDroppedNoReversePath;
-
- uint32_t countDroppedConnectionNotFound;
- uint32_t countObjectsDropped;
-
- uint32_t countSendFailures;
- uint32_t countInterestForwarded;
- uint32_t countObjectsForwarded;
- uint32_t countInterestsSatisfiedFromStore;
-
- uint32_t countDroppedNoHopLimit;
- uint32_t countDroppedZeroHopLimitFromRemote;
- uint32_t countDroppedZeroHopLimitToRemote;
-} _ProcessorStats;
-
-struct message_processor {
- Forwarder *forwarder;
- Logger *logger;
-
- PIT *pit;
- ContentStoreInterface *contentStore;
- FIB *fib;
-
- bool store_in_cache;
- bool serve_from_cache;
-
- _ProcessorStats stats;
-
-#ifdef WITH_POLICY
- void * timer;
-#endif /* WITH_POLICY */
-};
-
-static void messageProcessor_Drop(MessageProcessor *processor,
- Message *message);
-static void messageProcessor_ReceiveInterest(MessageProcessor *processor,
- Message *interestMessage);
-static void messageProcessor_ReceiveContentObject(MessageProcessor *processor,
- Message *objectMessage);
-static unsigned messageProcessor_ForwardToNexthops(MessageProcessor *processor,
- Message *message,
- const NumberSet *nexthops);
-
-static void messageProcessor_ForwardToInterfaceId(MessageProcessor *processor,
- Message *message,
- unsigned interfaceId);
-
-// ============================================================
-// Public API
-
-#ifdef WITH_POLICY
-static void
-messageProcessor_Tick(int fd, PARCEventType type, void *user_data)
-{
- MessageProcessor *processor = (MessageProcessor*)user_data;
- uint64_t now = (uint64_t)forwarder_GetTicks(processor->forwarder);
-
- /* Loop over FIB entries to compute statistics from counters */
- FibEntryList *fibList = forwarder_GetFibEntries(processor->forwarder);
-
- for (size_t i = 0; i < fibEntryList_Length(fibList); i++) {
- FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i);
- fibEntry_UpdateStats(entry, now);
- }
-
- fibEntryList_Destroy(&fibList);
-}
-#endif /* WITH_POLICY */
-
-MessageProcessor *messageProcessor_Create(Forwarder *forwarder) {
- size_t objectStoreSize =
- configuration_GetObjectStoreSize(forwarder_GetConfiguration(forwarder));
-
- MessageProcessor *processor =
- parcMemory_AllocateAndClear(sizeof(MessageProcessor));
- parcAssertNotNull(processor, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(MessageProcessor));
- memset(processor, 0, sizeof(MessageProcessor));
-
- processor->forwarder = forwarder;
- processor->logger = logger_Acquire(forwarder_GetLogger(forwarder));
- processor->pit = pitStandard_Create(forwarder);
-
- processor->fib = fib_Create(forwarder);
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "MessageProcessor %p created", (void *)processor);
- }
-
- ContentStoreConfig contentStoreConfig = {
- .objectCapacity = objectStoreSize,
- };
-
- processor->contentStore =
- contentStoreLRU_Create(&contentStoreConfig, processor->logger);
-
- // the two flags for the cache are set to true by default. If the cache
- // is active it always work as expected unless the use modifies this
- // values using controller
- processor->store_in_cache = true;
- processor->serve_from_cache = true;
-
-#ifdef WITH_POLICY
- /* Create statistics timer */
- Dispatcher *dispatcher = forwarder_GetDispatcher(forwarder);
- if (!dispatcher)
- goto ERR;
- processor->timer = dispatcher_CreateTimer(dispatcher, /* repeat */ true,
- messageProcessor_Tick, processor);
- if (!processor->timer)
- goto ERR;
- struct timeval timeout = {STATS_INTERVAL / 1000, (STATS_INTERVAL % 1000) * 1000};
- dispatcher_StartTimer(dispatcher, processor->timer, &timeout);
-ERR:
-#endif /* WITH_POLICY */
-
- return processor;
-}
-
-void messageProcessor_SetContentObjectStoreSize(
- MessageProcessor *processor, size_t maximumContentStoreSize) {
- parcAssertNotNull(processor, "Parameter processor must be non-null");
- contentStoreInterface_Release(&processor->contentStore);
-
- ContentStoreConfig contentStoreConfig = {.objectCapacity =
- maximumContentStoreSize};
-
- processor->contentStore =
- contentStoreLRU_Create(&contentStoreConfig, processor->logger);
-}
-
-void messageProcessor_ClearCache(MessageProcessor *processor) {
- parcAssertNotNull(processor, "Parameter processor must be non-null");
- size_t objectStoreSize = configuration_GetObjectStoreSize(
- forwarder_GetConfiguration(processor->forwarder));
-
- contentStoreInterface_Release(&processor->contentStore);
-
- ContentStoreConfig contentStoreConfig = {
- .objectCapacity = objectStoreSize,
- };
-
- processor->contentStore =
- contentStoreLRU_Create(&contentStoreConfig, processor->logger);
-}
-
-ContentStoreInterface *messageProcessor_GetContentObjectStore(
- const MessageProcessor *processor) {
- parcAssertNotNull(processor, "Parameter processor must be non-null");
- return processor->contentStore;
-}
-
-void messageProcessor_Destroy(MessageProcessor **processorPtr) {
- parcAssertNotNull(processorPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*processorPtr, "Parameter dereference to non-null pointer");
-
- MessageProcessor *processor = *processorPtr;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "MessageProcessor %p destroyed", (void *)processor);
- }
-
- logger_Release(&processor->logger);
- fib_Destroy(&processor->fib);
- contentStoreInterface_Release(&processor->contentStore);
- pit_Release(&processor->pit);
-
-#ifdef WITH_POLICY
- Dispatcher *dispatcher = forwarder_GetDispatcher(processor->forwarder);
- if (!dispatcher)
- goto ERR;
- dispatcher_StopTimer(dispatcher, processor->timer);
- dispatcher_DestroyTimerEvent(dispatcher, (PARCEventTimer**)&processor->timer);
-ERR:
-#endif /* WITH_POLICY */
-
- parcMemory_Deallocate((void **)&processor);
- *processorPtr = NULL;
-}
-
-void messageProcessor_Receive(MessageProcessor *processor, Message *message) {
- parcAssertNotNull(processor, "Parameter processor must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
-
- processor->stats.countReceived++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- char *nameString = name_ToString(message_GetName(message));
- logger_Log(processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "Message %p ingress %3u length %5u received name %s",
- (void *)message, message_GetIngressConnectionId(message),
- message_Length(message), nameString);
- parcMemory_Deallocate((void **)&nameString);
- }
-
- switch (message_GetType(message)) {
- case MessagePacketType_Interest:
- messageProcessor_ReceiveInterest(processor, message);
- break;
-
- case MessagePacketType_ContentObject:
- messageProcessor_ReceiveContentObject(processor, message);
- break;
-
- default:
- messageProcessor_Drop(processor, message);
- break;
- }
-
- // if someone wanted to save it, they made a copy
- message_Release(&message);
-}
-
-bool messageProcessor_AddOrUpdateRoute(MessageProcessor *processor,
- add_route_command *control,
- unsigned ifidx) {
- Configuration *config = forwarder_GetConfiguration(processor->forwarder);
-
- char *prefixStr = (char *) utils_PrefixLenToString(
- control->addressType, &control->address, &control->len);
- strategy_type fwdStrategy =
- configuration_GetForwardingStrategy(config, prefixStr);
-
- Name *prefix = name_CreateFromAddress(control->addressType, control->address,
- control->len);
- FibEntry *entry = fib_Contains(processor->fib, prefix);
- if (entry != NULL) {
- fibEntry_AddNexthop(entry, ifidx);
- } else {
-#ifdef WITH_POLICY
- entry = fibEntry_Create(prefix, fwdStrategy, processor->forwarder);
-#else
- entry = fibEntry_Create(prefix, fwdStrategy);
-#endif /* WITH_POLICY */
- fibEntry_AddNexthop(entry, ifidx);
- fib_Add(processor->fib, entry);
- }
-
- free(prefixStr);
- name_Release(&prefix);
-
- return true;
-}
-
-bool messageProcessor_RemoveRoute(MessageProcessor *processor,
- remove_route_command *control,
- unsigned ifidx) {
- Name *name = name_CreateFromAddress(control->addressType, control->address,
- control->len);
- fib_Remove(processor->fib, name, ifidx);
- name_Release(&name);
-
- return true;
-}
-
-#ifdef WITH_POLICY
-
-bool messageProcessor_AddOrUpdatePolicy(MessageProcessor *processor,
- add_policy_command *control) {
- Configuration *config = forwarder_GetConfiguration(processor->forwarder);
-
- const char *prefixStr = utils_PrefixLenToString(
- control->addressType, &control->address, &control->len);
-
- Name *prefix = name_CreateFromAddress(control->addressType, control->address,
- control->len);
- FibEntry *entry = fib_Contains(processor->fib, prefix);
- if (!entry) {
- strategy_type fwdStrategy =
- configuration_GetForwardingStrategy(config, prefixStr);
- entry = fibEntry_Create(prefix, fwdStrategy, processor->forwarder);
- fib_Add(processor->fib, entry);
- }
- fibEntry_SetPolicy(entry, control->policy);
-
- name_Release(&prefix);
-
- return true;
-}
-
-bool messageProcessor_RemovePolicy(MessageProcessor *processor,
- remove_policy_command *control) {
- Name *prefix = name_CreateFromAddress(control->addressType, control->address,
- control->len);
- FibEntry *entry = fib_Contains(processor->fib, prefix);
- name_Release(&prefix);
-
- if (!entry)
- return false;
-
- fibEntry_SetPolicy(entry, POLICY_NONE);
-
- return true;
-}
-
-#endif /* WITH_POLICY */
-
-void messageProcessor_RemoveConnectionIdFromRoutes(MessageProcessor *processor,
- unsigned connectionId) {
- fib_RemoveConnectionId(processor->fib, connectionId);
-}
-
-void processor_SetStrategy(MessageProcessor *processor, Name *prefix,
- strategy_type strategy,
- unsigned related_prefixes_len,
- Name **related_prefixes){
- FibEntry *entry = fib_Contains(processor->fib, prefix);
- if (entry != NULL) {
- fibEntry_SetStrategy(entry, strategy, related_prefixes_len,
- related_prefixes);
- }
-}
-
-FibEntryList *messageProcessor_GetFibEntries(MessageProcessor *processor) {
- parcAssertNotNull(processor, "Parameter processor must be non-null");
- return fib_GetEntries(processor->fib);
-}
-
-// ============================================================
-// Internal API
-
-/**
- * @function messageProcessor_Drop
- * @abstract Whenever we "drop" a message, increment countes
- * @discussion
- * This is a bookkeeping function. It increments the appropriate counters.
- *
- * The default action for a message is to destroy it in
- * <code>messageProcessor_Receive()</code>, so this function does not need to do
- * that.
- *
- */
-static void messageProcessor_Drop(MessageProcessor *processor,
- Message *message) {
- processor->stats.countDropped++;
-
- switch (message_GetType(message)) {
- case MessagePacketType_Interest:
- processor->stats.countInterestsDropped++;
- break;
-
- case MessagePacketType_ContentObject:
- processor->stats.countObjectsDropped++;
- break;
-
- default:
- break;
- }
-
- // dont destroy message here, its done at end of receive
-}
-
-/**
- * @function messageProcessor_AggregateInterestInPit
- * @abstract Try to aggregate the interest in the PIT
- * @discussion
- * Tries to aggregate the interest with another interest.
- *
- * @return true if interest aggregagted (no more forwarding needed), false if
- * need to keep processing it.
- */
-#ifdef WITH_POLICY
-static PITVerdict messageProcessor_AggregateInterestInPit(MessageProcessor *processor,
- Message *interestMessage) {
-#else
-static bool messageProcessor_AggregateInterestInPit(MessageProcessor *processor,
- Message *interestMessage) {
-#endif /* WITH_POLICY */
- PITVerdict verdict = pit_ReceiveInterest(processor->pit, interestMessage);
-
- if (verdict == PITVerdict_Aggregate) {
- // PIT has it, we're done
- processor->stats.countInterestsAggregated++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(
- processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "Message %p aggregated in PIT (aggregated count %u)",
- (void *)interestMessage, processor->stats.countInterestsAggregated);
- }
-
- return true;
- }
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(
- processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "Message %p not aggregated in PIT (aggregated count %u)",
- (void *)interestMessage, processor->stats.countInterestsAggregated);
- }
-
- return false;
-}
-
-static bool _satisfyFromContentStore(MessageProcessor *processor,
- Message *interestMessage) {
- bool result = false;
-
- if (message_GetInterestLifetimeTicks(interestMessage) == 0) {
- return false;
- }
-
- if (!processor->serve_from_cache) {
- return result;
- }
-
- // See if there's a match in the store.
- Message *objectMessage = contentStoreInterface_MatchInterest(
- processor->contentStore, interestMessage,
- forwarder_GetTicks(processor->forwarder));
-
- if (objectMessage != NULL) {
- // Remove it from the PIT. nexthops is allocated, so need to destroy
- NumberSet *nexthops = pit_SatisfyInterest(processor->pit, objectMessage);
- parcAssertNotNull(
- nexthops,
- "Illegal state: got a null nexthops for an interest we just inserted.");
-
- // send message in reply, then done
- processor->stats.countInterestsSatisfiedFromStore++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug, __func__,
- "Message %p satisfied from content store (satisfied count %u)",
- (void *)interestMessage,
- processor->stats.countInterestsSatisfiedFromStore);
- }
-
- message_ResetPathLabel(objectMessage);
-
- messageProcessor_ForwardToNexthops(processor, objectMessage, nexthops);
- numberSet_Release(&nexthops);
-
- result = true;
- }
-
- return result;
-}
-
-/**
- * @function messageProcessor_ForwardViaFib
- * @abstract Try to forward the interest via the FIB
- * @discussion
- * This calls <code>messageProcessor_ForwardToNexthops()</code>, so if we find
- * any nexthops, the interest will be sent on its way. Depending on the
- * IoOperations of each nexthop, it may be a deferred write and bump up the
- * <code>interestMessage</code> refernce count, or it may copy the data out.
- *
- * A TRUE return means we did our best to forward it via the routes. If those
- * routes are actually down or have errors, we still return TRUE. A FALSE
- * return means there were no routes to try.
- *
- * @return true if we found a route and tried to forward it, false if no route
- */
-#ifdef WITH_POLICY
-static bool messageProcessor_ForwardViaFib(MessageProcessor *processor,
- Message *interestMessage, PITVerdict verdict) {
-#else
-static bool messageProcessor_ForwardViaFib(MessageProcessor *processor,
- Message *interestMessage) {
-#endif /* WITH_POLICY */
- FibEntry *fibEntry = fib_MatchMessage(processor->fib, interestMessage);
- if (fibEntry == NULL) {
- return false;
- }
-
- if(messageHandler_IsAProbe(message_FixedHeader(interestMessage))){
- bool reply_to_probe = false;
- ConnectionTable * ct = forwarder_GetConnectionTable(processor->forwarder);
- const NumberSet * nexthops = fibEntry_GetNexthops(fibEntry);
- unsigned size = (unsigned) numberSet_Length(nexthops);
-
- for (unsigned i = 0; i < size; i++) {
- unsigned nhop = numberSet_GetItem(nexthops, i);
- Connection *conn =
- (Connection *)connectionTable_FindById(ct, nhop);
- if (!conn)
- continue;
- bool isLocal = connection_IsLocal(conn);
- if(isLocal){
- Connection * replyConn =
- (Connection *)connectionTable_FindById(ct,
- message_GetIngressConnectionId(interestMessage));
- connection_HandleProbe(replyConn,
- (uint8_t *) message_FixedHeader(interestMessage));
- reply_to_probe = true;
- break;
- }
- }
- if(reply_to_probe)
- return false;
- }
-
-
- PitEntry *pitEntry = pit_GetPitEntry(processor->pit, interestMessage);
- if (pitEntry == NULL) {
- return false;
- }
-
- pitEntry_AddFibEntry(pitEntry, fibEntry);
-
- NumberSet *nexthops = (NumberSet *)fibEntry_GetNexthopsFromForwardingStrategy(
-#ifdef WITH_POLICY
- fibEntry, interestMessage, verdict);
-#else
- fibEntry, interestMessage);
-#endif /* WITH_POLICY */
-
- // this requires some additional checks. It may happen that some of the output
- // faces selected by the forwarding strategy are not usable. So far all the
- // forwarding strategy return only valid faces (or an empty list)
- for (unsigned i = 0; i < numberSet_Length(nexthops); i++) {
- pitEntry_AddEgressId(pitEntry, numberSet_GetItem(nexthops, i));
- }
-
- // The function GetPitEntry encreases the ref counter in the pit entry
- // we need to decrease it
- pitEntry_Release(&pitEntry);
-
- if (messageProcessor_ForwardToNexthops(processor, interestMessage, nexthops) >
- 0) {
- numberSet_Release(&nexthops);
- return true;
- } else {
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug, __func__,
- "Message %p returned an emtpy next hop set",
- (void *)interestMessage);
- }
- }
-
- numberSet_Release(&nexthops);
- return false;
-}
-
-/**
- * @function messageProcessor_ReceiveInterest
- * @abstract Receive an interest from the network
- * @discussion
- * (1) if interest in the PIT, aggregate in PIT
- * (2) if interest in the ContentStore, reply
- * (3) if in the FIB, forward
- * (4) drop
- *
- */
-static void messageProcessor_ReceiveInterest(MessageProcessor *processor,
- Message *interestMessage) {
- processor->stats.countInterestsReceived++;
-
- // (1) Try to aggregate in PIT
-#ifdef WITH_POLICY
- PITVerdict verdict = messageProcessor_AggregateInterestInPit(processor, interestMessage);
- switch(verdict) {
- case PITVerdict_Aggregate:
- //done
- return;
-
- case PITVerdict_Forward:
- case PITVerdict_Retransmit:
- break;
- }
-#else
- if (messageProcessor_AggregateInterestInPit(processor, interestMessage)) {
- // done
- return;
- }
-#endif /* WITH_POLICY */
-
- // At this point, we just created a PIT entry. If we don't forward the
- // interest, we need to remove the PIT entry.
-
- // (2) Try to satisfy from content store
- if (_satisfyFromContentStore(processor, interestMessage)) {
- // done
- // If we found a content object in the CS,
- // messageProcess_SatisfyFromContentStore already cleared the PIT state
- return;
- }
-
- // (3) Try to forward it
-#ifdef WITH_POLICY
- if (messageProcessor_ForwardViaFib(processor, interestMessage, verdict)) {
-#else
- if (messageProcessor_ForwardViaFib(processor, interestMessage)) {
-#endif /* WITH_POLICY */
- // done
- return;
- }
-
- // Remove the PIT entry?
- processor->stats.countDroppedNoRoute++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "Message %p did not match FIB, no route (count %u)",
- (void *)interestMessage, processor->stats.countDroppedNoRoute);
- }
-
- messageProcessor_Drop(processor, interestMessage);
-}
-
-/**
- * @function messageProcessor_ReceiveContentObject
- * @abstract Process an in-bound content object
- * @discussion
- * (1) If it does not match anything in the PIT, drop it
- * (2) Add to Content Store
- * (3) Reverse path forward via PIT entries
- *
- * @param <#param1#>
- */
-static void messageProcessor_ReceiveContentObject(MessageProcessor *processor,
- Message *message) {
- processor->stats.countObjectsReceived++;
-
- NumberSet *ingressSetUnion = pit_SatisfyInterest(processor->pit, message);
-
- if (numberSet_Length(ingressSetUnion) == 0) {
- // (1) If it does not match anything in the PIT, drop it
- processor->stats.countDroppedNoReversePath++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug, __func__,
- "Message %p did not match PIT, no reverse path (count %u)",
- (void *)message, processor->stats.countDroppedNoReversePath);
- }
-
- //if the packet is a probe we need to analyze it
- if(messageHandler_IsAProbe(message_FixedHeader(message))){
- FibEntry *fibEntry = fib_MatchMessage(processor->fib, message);
- if(fibEntry &&
- fibEntry_GetFwdStrategyType(fibEntry) == SET_STRATEGY_LOW_LATENCY){
- unsigned connid = message_GetIngressConnectionId(message);
- NumberSet *outFace = numberSet_Create();
- numberSet_Add(outFace, connid);
- fibEntry_ReceiveObjectMessage(fibEntry, outFace, message, 0,
- forwarder_GetTicks(processor->forwarder));
- numberSet_Release(&(outFace));
- }
- }
-
- // we store the packets in the content store enven in the case where there
- // is no match in the PIT table in this way the applications can push the
- // content in the CS of the forwarder. We allow this only for local faces
- bool isLocal = connection_IsLocal(connectionTable_FindById(
- forwarder_GetConnectionTable(processor->forwarder),
- message_GetIngressConnectionId((const Message *)message)));
- if (processor->store_in_cache && isLocal) {
- uint64_t currentTimeTicks = forwarder_GetTicks(processor->forwarder);
- contentStoreInterface_PutContent(processor->contentStore, message,
- currentTimeTicks);
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug, __func__,
- "Message %p sotred in the CS anyway", (void *)message);
- }
- }
-
- messageProcessor_Drop(processor, message);
- } else {
- // (2) Add to Content Store. Store may remove expired content, if necessary,
- // depending on store policy.
- if (processor->store_in_cache) {
- uint64_t currentTimeTicks = forwarder_GetTicks(processor->forwarder);
- contentStoreInterface_PutContent(processor->contentStore, message,
- currentTimeTicks);
- }
- // (3) Reverse path forward via PIT entries
- messageProcessor_ForwardToNexthops(processor, message, ingressSetUnion);
-
- }
-
- numberSet_Release(&ingressSetUnion);
-}
-
-/**
- * @function messageProcessor_ForwardToNexthops
- * @abstract Try to forward to each nexthop listed in the NumberSet
- * @discussion
- * Will not forward to the ingress connection.
- *
- * @return The number of nexthops tried
- */
-static unsigned messageProcessor_ForwardToNexthops(MessageProcessor *processor,
- Message *message,
- const NumberSet *nexthops) {
- unsigned forwardedCopies = 0;
-
- size_t length = numberSet_Length(nexthops);
-
- unsigned ingressId = message_GetIngressConnectionId(message);
- uint32_t old_path_label = 0;
-
- if (message_GetType(message) == MessagePacketType_ContentObject) {
- old_path_label = message_GetPathLabel(message);
- }
-
- for (size_t i = 0; i < length; i++) {
- unsigned egressId = numberSet_GetItem(nexthops, i);
- if (egressId != ingressId) {
- forwardedCopies++;
- messageProcessor_ForwardToInterfaceId(processor, message, egressId);
-
- if (message_GetType(message) == MessagePacketType_ContentObject) {
- // everytime we send out a message we need to restore the original path
- // label of the message this is important because we keep a single copy
- // of the message (single pointer) and we modify the path label at each
- // send.
- message_SetPathLabel(message, old_path_label);
- }
- }
- }
- return forwardedCopies;
-}
-
-/**
- * caller has checked that the hop limit is ok. Try to send out the connection.
- */
-static void messageProcessor_SendWithGoodHopLimit(MessageProcessor *processor,
- Message *message,
- unsigned interfaceId,
- const Connection *conn) {
- bool success = connection_Send(conn, message);
- if (success) {
- switch (message_GetType(message)) {
- case MessagePacketType_Interest:
- processor->stats.countInterestForwarded++;
- break;
-
- case MessagePacketType_ContentObject:
- processor->stats.countObjectsForwarded++;
- break;
-
- default:
- break;
- }
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(
- processor->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "forward message %p to interface %u (int %u, obj %u)",
- (void *)message, interfaceId, processor->stats.countInterestForwarded,
- processor->stats.countObjectsForwarded);
- }
- } else {
- processor->stats.countSendFailures++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug, __func__,
- "forward message %p to interface %u send failure (count %u)",
- (void *)message, interfaceId,
- processor->stats.countSendFailures);
- }
- messageProcessor_Drop(processor, message);
- }
-}
-
-/*
- * If the hoplimit is equal to 0, then we may only forward it to local
- * applications. Otherwise, we may forward it off the system.
- *
- */
-static void messageProcessor_ForwardToInterfaceId(MessageProcessor *processor,
- Message *message,
- unsigned interfaceId) {
- ConnectionTable *connectionTable =
- forwarder_GetConnectionTable(processor->forwarder);
- const Connection *conn =
- connectionTable_FindById(connectionTable, interfaceId);
-
- if (conn != NULL) {
- messageProcessor_SendWithGoodHopLimit(processor, message, interfaceId,
- conn);
- } else {
- processor->stats.countDroppedConnectionNotFound++;
-
- if (logger_IsLoggable(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(processor->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug, __func__,
- "forward message %p to interface %u not found (count %u)",
- (void *)message, interfaceId,
- processor->stats.countDroppedConnectionNotFound);
- }
-
- messageProcessor_Drop(processor, message);
- }
-}
-
-void messageProcessor_SetCacheStoreFlag(MessageProcessor *processor, bool val) {
- processor->store_in_cache = val;
-}
-
-bool messageProcessor_GetCacheStoreFlag(MessageProcessor *processor) {
- return processor->store_in_cache;
-}
-
-void messageProcessor_SetCacheServeFlag(MessageProcessor *processor, bool val) {
- processor->serve_from_cache = val;
-}
-
-bool messageProcessor_GetCacheServeFlag(MessageProcessor *processor) {
- return processor->serve_from_cache;
-}
-
-#ifdef WITH_MAPME
-
-FIB *messageProcessor_getFib(MessageProcessor *processor) {
- return processor->fib;
-}
-
-#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/processor/messageProcessor.h b/hicn-light/src/hicn/processor/messageProcessor.h
deleted file mode 100644
index 6a863aa38..000000000
--- a/hicn-light/src/hicn/processor/messageProcessor.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file messageProcessor.h
- * @brief Executes the set of rules dictated by the PacketType
- *
- * This is a "run-to-completion" handling of a message based on the PacketType.
- *
- * The MessageProcessor also owns the PIT and FIB tables.
- *
- */
-
-#ifndef messageProcessor_h
-#define messageProcessor_h
-
-#include <hicn/content_store/contentStoreInterface.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/core/message.h>
-
-#include <hicn/utils/commands.h>
-
-#ifdef WITH_POLICY
-#ifdef WITH_MAPME
-#include <hicn/core/connection.h>
-#endif /* WITH_MAPME */
-#endif /* WITH_POLICY */
-
-struct message_processor;
-typedef struct message_processor MessageProcessor;
-
-/**
- * Allocates a MessageProcessor along with PIT, FIB and ContentStore tables
- *
- * The hicn-light pointer is primarily used for logging (forwarder_Log), getting
- * the configuration, and accessing the connection table.
- *
- * @param [in] Pointer to owning hicn-light process
- *
- * @retval non-null An allocated message processor
- * @retval null An error
- *
- */
-MessageProcessor *messageProcessor_Create(Forwarder *forwarder);
-
-/**
- * Deallocates a message processor an all internal tables
- *
- * @param [in,out] processorPtr Pointer to message processor to de-allocate,
- * will be NULL'd.
- */
-void messageProcessor_Destroy(MessageProcessor **processorPtr);
-
-/**
- * @function messageProcessor_Receive
- * @abstract Process the message, takes ownership of the memory.
- * @discussion
- * Will call destroy on the memory when done with it, so if the caller wants
- * to keep it, make a reference counted copy.
- *
- * Receive may modify some fields in the message, such as the HopLimit field.
- */
-void messageProcessor_Receive(MessageProcessor *procesor, Message *message);
-
-/**
- * Adds or updates a route in the FIB
- *
- * If the route already exists, it is replaced
- *
- * @param [in] procesor An allocated message processor
- * @param [in] route The route to update
- *
- * @retval true added or updated
- * @retval false An error
- */
-bool messageProcessor_AddOrUpdateRoute(MessageProcessor *processor,
- add_route_command *control,
- unsigned ifidx);
-
-/**
- * Removes a route from the FIB
- *
- * Removes a specific nexthop for a route. If there are no nexthops left after
- * the removal, the entire route is deleted from the FIB.
- *
- * @param [in] procesor An allocated message processor
- * @param [in] route The route to remove
- *
- * @retval true Route completely removed
- * @retval false There is still a nexthop for the route
- */
-
-bool messageProcessor_RemoveRoute(MessageProcessor *processor,
- remove_route_command *control,
- unsigned ifidx);
-
-#ifdef WITH_POLICY
-
-/**
- * Adds or updates a policy in the FIB
- *
- * If the policy is already set, it is replaced
- *
- * @param [in] procesor An allocated message processor
- * @param [in] control Control message
- *
- * @retval true added or updated
- * @retval false An error
- */
-bool messageProcessor_AddOrUpdatePolicy(MessageProcessor *processor,
- add_policy_command *control);
-
-/**
- * Removes a policy from the FIB
- *
- * Reset the policy in the FIB to the default (empty) policy.
- *
- * @param [in] procesor An allocated message processor
- * @param [in] control Control message
- *
- * @retval true Policy completely removed
- * @retval false There is still a nexthop for the policy
- */
-bool messageProcessor_RemovePolicy(MessageProcessor *processor,
- remove_policy_command *control);
-
-#endif /* WITH_POLICY */
-
-/**
- * Removes a given connection id from all FIB entries
- *
- * Iterates the FIB and removes the given connection ID from every route.
- */
-void messageProcessor_RemoveConnectionIdFromRoutes(MessageProcessor *processor,
- unsigned connectionId);
-
-/**
- * Returns a list of all FIB entries
- *
- * You must destroy the list.
- *
- * @retval non-null The list of FIB entries
- * @retval null An error
- */
-FibEntryList *messageProcessor_GetFibEntries(MessageProcessor *processor);
-
-/**
- * Adjusts the ContentStore to the given size.
- *
- * This will destroy and re-create the content store, so any cached objects will
- * be lost.
- *
- */
-void messageProcessor_SetContentObjectStoreSize(MessageProcessor *processor,
- size_t maximumContentStoreSize);
-
-/**
- * Return the interface to the currently instantiated ContentStore, if any.
- *
- * @param [in] processor the `MessageProcessor` from which to return the
- * ContentStoreInterface.
- *
- */
-ContentStoreInterface *messageProcessor_GetContentObjectStore(
- const MessageProcessor *processor);
-
-void messageProcessor_SetCacheStoreFlag(MessageProcessor *processor, bool val);
-
-bool messageProcessor_GetCacheStoreFlag(MessageProcessor *processor);
-
-void messageProcessor_SetCacheServeFlag(MessageProcessor *processor, bool val);
-
-bool messageProcessor_GetCacheServeFlag(MessageProcessor *processor);
-
-void messageProcessor_ClearCache(MessageProcessor *processor);
-
-void processor_SetStrategy(MessageProcessor *processor, Name *prefix,
- strategy_type strategy,
- unsigned related_prefixes_len,
- Name **related_prefixes);
-
-#ifdef WITH_MAPME
-
-/**
- * @function messageProcessor_getFib
- * @abstract Returns the hICN processor's FIB.
- * @param [in] forwarder - Pointer to the hICN processor.
- * @returns Pointer to the hICN FIB.
- */
-FIB *messageProcessor_getFib(MessageProcessor *processor);
-
-#endif /* WITH_MAPME */
-
-#endif // messageProcessor_h
diff --git a/hicn-light/src/hicn/processor/pit.c b/hicn-light/src/hicn/processor/pit.c
deleted file mode 100644
index 66ad85410..000000000
--- a/hicn-light/src/hicn/processor/pit.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Generic interface to PIT table
- *
- */
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/processor/pit.h>
-
-void *pit_Closure(const PIT *pit) { return pit->closure; }
-
-void pit_Release(PIT **pitPtr) { (*pitPtr)->release(pitPtr); }
-
-PITVerdict pit_ReceiveInterest(PIT *pit, Message *interestMessage) {
- return pit->receiveInterest(pit, interestMessage);
-}
-
-NumberSet *pit_SatisfyInterest(PIT *pit, const Message *objectMessage) {
- return pit->satisfyInterest(pit, objectMessage);
-}
-
-void pit_RemoveInterest(PIT *pit, const Message *interestMessage) {
- pit->removeInterest(pit, interestMessage);
-}
-
-PitEntry *pit_GetPitEntry(const PIT *pit, const Message *interestMessage) {
- return pit->getPitEntry(pit, interestMessage);
-}
diff --git a/hicn-light/src/hicn/processor/pit.h b/hicn-light/src/hicn/processor/pit.h
deleted file mode 100644
index 63a9b20e4..000000000
--- a/hicn-light/src/hicn/processor/pit.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file pit.h
- * @brief The Pending Interest Table interface
- *
- * Interface for implementing a PIT table
- *
- */
-
-#ifndef pit_h
-#define pit_h
-
-#include <hicn/core/forwarder.h>
-#include <hicn/core/message.h>
-#include <hicn/core/numberSet.h>
-#include <hicn/processor/pitEntry.h>
-#include <hicn/processor/pitVerdict.h>
-
-struct pit;
-typedef struct pit PIT;
-
-struct pit {
- void (*release)(PIT **pitPtr);
- PITVerdict (*receiveInterest)(PIT *pit, Message *interestMessage);
- NumberSet *(*satisfyInterest)(PIT *pit, const Message *objectMessage);
- void (*removeInterest)(PIT *pit, const Message *interestMessage);
- PitEntry *(*getPitEntry)(const PIT *pit, const Message *interestMessage);
- void *closure;
-};
-
-void *pit_Closure(const PIT *pit);
-
-/**
- * Destroys the PIT table and all entries contained in it.
- *
- * PIT entries are reference counted, so if the user has stored one outside the
- * PIT table it will still be valid.
- *
- * @param [in,out] pitPtr Double pointer to PIT table, will be NULLed
- */
-void pit_Release(PIT **pitPtr);
-
-/**
- * @function pit_ReceiveInterest
- * @abstract Receives an interest and adds to PIT table
- * @discussion
- * If not present, adds entry to the PIT table and returns
- * PIT_VERDICT_NEW_ENTRY. If present and aggregated, returns
- * PIT_VERDICT_EXISTING_ENTRY.
- *
- * Some aggregated interests may return PIT_VERDICT_NEW_ENTRY if the interest
- * needs to be forwarded again (e.g. the lifetime is extended).
- *
- * If the PIT stores the message in its table, it will store a reference
- * counted copy.
- *
- * @return Verdict of receiving the interest
- */
-PITVerdict pit_ReceiveInterest(PIT *pit, Message *interestMessage);
-
-/**
- * @function pit_SatisfyInterest
- * @abstract Tries to satisfy PIT entries based on the message, returning where
- * to send message
- * @discussion
- * If matching interests are in the PIT, will return the set of reverse
- * paths to use to forward the content object.
- *
- * The return value is allocated and must be destroyed.
- *
- * @return Set of ConnectionTable id's to forward the message, may be empty or
- * NULL. Must be destroyed.
- */
-NumberSet *pit_SatisfyInterest(PIT *pit, const Message *objectMessage);
-
-/**
- * @function pit_RemoveInterest
- * @abstract Unconditionally remove the interest from the PIT
- * @discussion
- * The PIT may store a specific name in several tables. This function will
- * remove the interest from the specific table it lives it. It will not
- * remove PIT entries in different tables with the same name.
- *
- * The different tables index interests based on their matching criteria,
- * such as by name, by name and keyid, etc.
- *
- */
-void pit_RemoveInterest(PIT *pit, const Message *interestMessage);
-
-/**
- * @function pit_GetPitEntry
- * @abstract Retrieve the best matching PIT entry for the message.
- * @discussion
- * Returns a reference counted copy of the entry, must call
- * <code>pitEntry_Destory()</code> on it.
- *
- * @return NULL if not in table, otherwise a reference counted copy of the entry
- */
-PitEntry *pit_GetPitEntry(const PIT *pit, const Message *interestMessage);
-#endif // pit_h
diff --git a/hicn-light/src/hicn/processor/pitEntry.c b/hicn-light/src/hicn/processor/pitEntry.c
deleted file mode 100644
index 99b3f1f2b..000000000
--- a/hicn-light/src/hicn/processor/pitEntry.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <hicn/core/numberSet.h>
-#include <hicn/processor/pitEntry.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct pit_entry {
- Message *message;
- NumberSet *ingressIdSet;
- NumberSet *egressIdSet;
-
- FibEntry *fibEntry;
-
- Ticks creationTime;
- Ticks expiryTime;
-
- unsigned refcount;
-};
-
-PitEntry *pitEntry_Create(Message *message, Ticks expiryTime,
- Ticks creationTime) {
- PitEntry *pitEntry = parcMemory_AllocateAndClear(sizeof(PitEntry));
- parcAssertNotNull(pitEntry, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(PitEntry));
- pitEntry->message = message;
- pitEntry->ingressIdSet = numberSet_Create();
- pitEntry->egressIdSet = numberSet_Create();
- pitEntry->refcount = 1;
-
- // add the message to the reverse path set
- numberSet_Add(pitEntry->ingressIdSet,
- message_GetIngressConnectionId(message));
-
- // hack in a 4-second timeout
- pitEntry->expiryTime = expiryTime;
- pitEntry->fibEntry = NULL;
-
- pitEntry->creationTime = creationTime;
- return pitEntry;
-}
-
-void pitEntry_Release(PitEntry **pitEntryPtr) {
- parcAssertNotNull(pitEntryPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*pitEntryPtr,
- "Parameter must dereference to non-null pointer");
-
- PitEntry *pitEntry = *pitEntryPtr;
- parcTrapIllegalValueIf(pitEntry->refcount == 0,
- "Illegal state: has refcount of 0");
-
- pitEntry->refcount--;
- if (pitEntry->refcount == 0) {
- if (pitEntry->fibEntry != NULL) {
- fibEntry_Release(&pitEntry->fibEntry);
- }
- numberSet_Release(&pitEntry->ingressIdSet);
- numberSet_Release(&pitEntry->egressIdSet);
- message_Release(&pitEntry->message);
- parcMemory_Deallocate((void **)&pitEntry);
- }
- *pitEntryPtr = NULL;
-}
-
-PitEntry *pitEntry_Acquire(PitEntry *original) {
- parcAssertNotNull(original, "Parameter original must be non-null");
- original->refcount++;
- return original;
-}
-
-void pitEntry_AddIngressId(PitEntry *pitEntry, unsigned ingressId) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- numberSet_Add(pitEntry->ingressIdSet, ingressId);
-}
-
-void pitEntry_AddEgressId(PitEntry *pitEntry, unsigned egressId) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- numberSet_Add(pitEntry->egressIdSet, egressId);
-}
-
-void pitEntry_AddFibEntry(PitEntry *pitEntry, FibEntry *fibEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
- // the fibEntry should be always the same for all the interests in the same
- // pitEntry
- if (pitEntry->fibEntry == NULL) {
- fibEntry_Acquire(fibEntry);
- pitEntry->fibEntry = fibEntry;
- }
-}
-
-FibEntry *pitEntry_GetFibEntry(PitEntry *pitEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- return pitEntry->fibEntry;
-}
-
-Ticks pitEntry_GetExpiryTime(const PitEntry *pitEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- return pitEntry->expiryTime;
-}
-
-Ticks pitEntry_GetCreationTime(const PitEntry *pitEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- return pitEntry->creationTime;
-}
-
-void pitEntry_SetExpiryTime(PitEntry *pitEntry, Ticks expiryTime) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- pitEntry->expiryTime = expiryTime;
-}
-
-const NumberSet *pitEntry_GetIngressSet(const PitEntry *pitEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- return pitEntry->ingressIdSet;
-}
-
-const NumberSet *pitEntry_GetEgressSet(const PitEntry *pitEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- return pitEntry->egressIdSet;
-}
-
-Message *pitEntry_GetMessage(const PitEntry *pitEntry) {
- parcAssertNotNull(pitEntry, "Parameter pitEntry must be non-null");
- return message_Acquire(pitEntry->message);
-}
diff --git a/hicn-light/src/hicn/processor/pitEntry.h b/hicn-light/src/hicn/processor/pitEntry.h
deleted file mode 100644
index 3cd5821bc..000000000
--- a/hicn-light/src/hicn/processor/pitEntry.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file pitEntry.h
- * @brief The embodiment of a PIT entry
- *
- * Embodies a PIT entry
- *
- */
-
-#ifndef pitEntry_h
-#define pitEntry_h
-
-#include <hicn/core/message.h>
-#include <hicn/core/numberSet.h>
-#include <hicn/core/ticks.h>
-#include <hicn/processor/fibEntry.h>
-
-struct pit_entry;
-typedef struct pit_entry PitEntry;
-
-/**
- * @function pitEntry_Create
- * @abstract Takes ownership of the message inside the PitEntry
- * @discussion
- * When the PIT entry is destroyed, will call <code>message_Release()</code>
- * on the message.
- *
- */
-PitEntry *pitEntry_Create(Message *message, Ticks expiryTime,
- Ticks CreationTime);
-
-/**
- * Release a previously acquired reference to the specified instance,
- * decrementing the reference count for the instance.
- *
- * The pointer to the instance is set to NULL as a side-effect of this function.
- *
- * If the invocation causes the last reference to the instance to be released,
- * the instance is deallocated and the instance's implementation will perform
- * additional cleanup and release other privately held references.
- *
- * @param [in,out] pitEntryPtr A pointer to a PitEntry instance pointer, which
- * will be set to zero on return.
- *
- */
-void pitEntry_Release(PitEntry **pitEntryPtr);
-
-/**
- * @function pitEntry_Acquire
- * @abstract Returns a reference counted copy
- * @discussion
- * A reference counted copy that shares the same state as the original.
- * Caller must use <code>pitEntry_Release()</code> on it when done.
- *
- * @return A reference counted copy, use Destroy on it.
- */
-PitEntry *pitEntry_Acquire(PitEntry *original);
-
-/**
- * @function pitEntry_AddIngressId
- * @abstract Add an ingress connection id to the list of reverse paths
- * @discussion
- * A PitEntry has two NumberSets. The first is the set of ingress ports,
- * which make up the reverse path. The second is the set of egress ports, which
- * make up its forward path.
- *
- * This function tracks which reverse paths have sent us the interest.
- *
- * @param ingressId the reverse path
- */
-void pitEntry_AddIngressId(PitEntry *pitEntry, unsigned ingressId);
-
-/**
- * @function pitEntry_AddEgressId
- * @abstract Add an egress connection id to the list of attempted paths
- * @discussion
- * A PitEntry has two NumberSets. The first is the set of ingress ports,
- * which make up the reverse path. The second is the set of egress ports, which
- * make up its forward path.
- *
- * This function tracks which forward paths we've tried for the interest.
- *
- * @param egressId the forwarded path
- */
-void pitEntry_AddEgressId(PitEntry *pitEntry, unsigned egressId);
-
-void pitEntry_AddFibEntry(PitEntry *pitEntry, FibEntry *fibEntry);
-
-FibEntry *pitEntry_GetFibEntry(PitEntry *pitEntry);
-
-/**
- * @function pitEntry_GetIngressSet
- * @abstract The Ingress connection id set
- * @discussion
- * You must acquire a copy of the number set if you will store the result.
- * This is the internal reference.
- *
- * @return May be empty, will not be null. Must be destroyed.
- */
-const NumberSet *pitEntry_GetIngressSet(const PitEntry *pitEntry);
-
-/**
- * @function pitEntry_GetEgressSet
- * @abstract The Egress connection id set
- * @discussion
- * You must acquire a copy of the number set if you will store the result.
- * This is the internal reference.
- *
- * @param <#param1#>
- * @return May be empty, will not be null. Must be destroyed.
- */
-const NumberSet *pitEntry_GetEgressSet(const PitEntry *pitEntry);
-
-/**
- * @function pitEntry_GetMessage
- * @abstract Gets the interest underpinning the PIT entry
- * @discussion
- * A reference counted copy, call <code>Message_Release()</code> on it.
- *
- * @return A reference counted copy, call <code>Message_Release()</code> on it.
- */
-Message *pitEntry_GetMessage(const PitEntry *pitEntry);
-
-/**
- * Returns the time (in ticks) at which the PIT entry is no longer valid
- *
- * The ExpiryTime is computed when the PIT entry is added (or via
- * pitEntry_SetExpiryTime). It is the aboslute time (in Ticks) at which the Pit
- * entry is no longer valid.
- *
- * @param [in] PitEntry An allocated PIT entry
- *
- * @retval number The abosolute time (in Ticks) of the Expiry
- */
-Ticks pitEntry_GetExpiryTime(const PitEntry *pitEntry);
-
-Ticks pitEntry_GetCreationTime(const PitEntry *pitEntry);
-/**
- * Sets the ExpriyTime of the PIT entry to the given value
- *
- * It is probalby an error to set the expiryTime to a smaller value than
- * currently set to, but this is not enforced. PIT entries use lazy delete.
- *
- * @param [in] pitEntry The allocated PIT entry to modify
- * @param [in] expiryTime The new expiryTime (UTC in forwarder Ticks)
- *
- */
-void pitEntry_SetExpiryTime(PitEntry *pitEntry, Ticks expiryTime);
-
-#endif // pitEntry_h
diff --git a/hicn-light/src/hicn/processor/pitStandard.c b/hicn-light/src/hicn/processor/pitStandard.c
deleted file mode 100644
index 04d886261..000000000
--- a/hicn-light/src/hicn/processor/pitStandard.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * The pending interest table.
- *
- * Interest aggregation strategy:
- * - The first Interest for a name is forwarded
- * - A second Interest for a name from a different reverse path may be
- * aggregated
- * - A second Interest for a name from an existing Interest is forwarded
- * - The Interest Lifetime is like a subscription time. A reverse path entry is
- * removed once the lifetime is exceeded.
- * - Whan an Interest arrives or is aggregated, the Lifetime for that reverse
- * hop is extended. As a simplification, we only keep a single lifetime not per
- * reverse hop.
- *
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
-#include <hicn/processor/hashTableFunction.h>
-#include <hicn/processor/pit.h>
-
-#include <hicn/core/ticks.h>
-
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/core/forwarder.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct standard_pit;
-typedef struct standard_pit StandardPIT;
-
-struct standard_pit {
- Forwarder *forwarder;
- Logger *logger;
- PARCHashCodeTable *table; // PIT indexed by name
-};
-
-static void _pit_StoreInTable(StandardPIT *pit, Message *interestMessage);
-
-static void _pit_PitEntryDestroyer(void **dataPtr) {
- pitEntry_Release((PitEntry **)dataPtr);
-}
-
-static bool _pit_IngressSetContains(PitEntry *pitEntry, unsigned connectionId) {
- const NumberSet *set = pitEntry_GetIngressSet(pitEntry);
- bool numberInSet = numberSet_Contains(set, connectionId);
- return numberInSet;
-}
-
-static Ticks _pit_CalculateLifetime(StandardPIT *pit,
- Message *interestMessage) {
- uint64_t interestLifetimeTicks =
- message_GetInterestLifetimeTicks(interestMessage);
- if (interestLifetimeTicks == 0) {
- interestLifetimeTicks = forwarder_NanosToTicks(4000000000ULL);
- }
-
- Ticks expiryTime = forwarder_GetTicks(pit->forwarder) + interestLifetimeTicks;
- return expiryTime;
-}
-
-static void _pit_StoreInTable(StandardPIT *pit, Message *interestMessage) {
- Message *key = message_Acquire(interestMessage);
-
- Ticks expiryTime = _pit_CalculateLifetime(pit, interestMessage);
-
- PitEntry *pitEntry =
- pitEntry_Create(key, expiryTime, forwarder_GetTicks(pit->forwarder));
-
- parcHashCodeTable_Add(pit->table, key, pitEntry);
-
- if (logger_IsLoggable(pit->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(pit->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "Message %p added to PIT (expiry %" PRIu64 ") ingress %u",
- (void *)interestMessage, pitEntry_GetExpiryTime(pitEntry),
- message_GetIngressConnectionId(interestMessage));
- }
-}
-
-static void _pit_ExtendLifetime(StandardPIT *pit, PitEntry *pitEntry,
- Message *interestMessage) {
- Ticks expiryTime = _pit_CalculateLifetime(pit, interestMessage);
-
- if (expiryTime > pitEntry_GetExpiryTime(pitEntry))
- pitEntry_SetExpiryTime(pitEntry, expiryTime);
-}
-
-// ======================================================================
-// Interface API
-
-static void _pitStandard_Destroy(PIT **pitPtr) {
- parcAssertNotNull(pitPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*pitPtr, "Parameter must dereference to non-null pointer");
-
- StandardPIT *pit = pit_Closure(*pitPtr);
-
- if (logger_IsLoggable(pit->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(pit->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "PIT %p destroyed", (void *)pit);
- }
-
- parcHashCodeTable_Destroy(&pit->table);
- logger_Release(&pit->logger);
- parcMemory_Deallocate(pitPtr);
-}
-
-static PITVerdict _pitStandard_ReceiveInterest(PIT *generic,
- Message *interestMessage) {
- parcAssertNotNull(generic, "Parameter pit must be non-null");
- parcAssertNotNull(interestMessage,
- "Parameter interestMessage must be non-null");
-
- StandardPIT *pit = pit_Closure(generic);
-
- PitEntry *pitEntry = parcHashCodeTable_Get(pit->table, interestMessage);
-
- if (pitEntry) {
- // has it expired?
- Ticks now = forwarder_GetTicks(pit->forwarder);
- if (now < pitEntry_GetExpiryTime(pitEntry)) {
- _pit_ExtendLifetime(pit, pitEntry, interestMessage);
-
- // Is the reverse path already in the PIT entry?
- if (_pit_IngressSetContains(
- pitEntry, message_GetIngressConnectionId(interestMessage))) {
- // It is already in the PIT entry, so this is a retransmission, so
- // forward it.
-
- if (logger_IsLoggable(pit->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(pit->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "Message %p existing entry (expiry %" PRIu64
- ") and reverse path, forwarding",
- (void *)interestMessage, pitEntry_GetExpiryTime(pitEntry));
- }
-#ifdef WITH_POLICY
- return PITVerdict_Retransmit;
-#else
- return PITVerdict_Forward;
-#endif /* WITH_POLICY */
- }
-
- // It is in the PIT but this is the first interest for the reverse path
- pitEntry_AddIngressId(pitEntry,
- message_GetIngressConnectionId(interestMessage));
-
- if (logger_IsLoggable(pit->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(pit->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "Message %p existing entry (expiry %" PRIu64
- ") and reverse path is new, aggregate",
- (void *)interestMessage, pitEntry_GetExpiryTime(pitEntry));
- }
-
- return PITVerdict_Aggregate;
- }
- // this is a timeout....
- FibEntry *fibEntry = pitEntry_GetFibEntry(pitEntry);
- if (fibEntry != NULL) {
- fibEntry_OnTimeout(fibEntry, pitEntry_GetEgressSet(pitEntry));
- }
-
- // it's an old entry, remove it
- parcHashCodeTable_Del(pit->table, interestMessage);
- }
-
- _pit_StoreInTable(pit, interestMessage);
-
- return PITVerdict_Forward;
-}
-
-static NumberSet *_pitStandard_SatisfyInterest(PIT *generic,
- const Message *objectMessage) {
- parcAssertNotNull(generic, "Parameter pit must be non-null");
- parcAssertNotNull(objectMessage, "Parameter objectMessage must be non-null");
-
- StandardPIT *pit = pit_Closure(generic);
-
- NumberSet *ingressSet = numberSet_Create();
-
- PitEntry *pitEntry = parcHashCodeTable_Get(pit->table, objectMessage);
- if (pitEntry) {
- // here we need to check if the PIT entry is expired
- // if so, remove the PIT entry.
- Ticks now = forwarder_GetTicks(pit->forwarder);
- if (now < pitEntry_GetExpiryTime(pitEntry)) {
- // PIT entry is not expired, use it
- FibEntry *fibEntry = pitEntry_GetFibEntry(pitEntry);
- if (fibEntry != NULL) {
- fibEntry_ReceiveObjectMessage(fibEntry, pitEntry_GetEgressSet(pitEntry),
- objectMessage,
- pitEntry_GetCreationTime(pitEntry),
- forwarder_GetTicks(pit->forwarder));
- }
- const NumberSet *is = pitEntry_GetIngressSet(pitEntry);
- numberSet_AddSet(ingressSet, is); // with this we do a copy so we can
- // remove the entry from the PIT
- }
- // remove the entry from the PIT. Key is a reference counted copy of the
- // pit entry message
- Message *key = pitEntry_GetMessage(pitEntry);
- parcHashCodeTable_Del(pit->table, key);
- message_Release(&key);
- }
-
- return ingressSet;
-}
-
-static void _pitStandard_RemoveInterest(PIT *generic,
- const Message *interestMessage) {
- parcAssertNotNull(generic, "Parameter pit must be non-null");
- parcAssertNotNull(interestMessage,
- "Parameter interestMessage must be non-null");
-
- StandardPIT *pit = pit_Closure(generic);
-
- if (logger_IsLoggable(pit->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(pit->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "Message %p removed from PIT",
- (void *)interestMessage);
- }
-
- parcHashCodeTable_Del(pit->table, interestMessage);
-}
-
-static PitEntry *_pitStandard_GetPitEntry(const PIT *generic,
- const Message *interestMessage) {
- parcAssertNotNull(generic, "Parameter pit must be non-null");
- parcAssertNotNull(interestMessage,
- "Parameter interestMessage must be non-null");
-
- StandardPIT *pit = pit_Closure(generic);
-
- PitEntry *entry = parcHashCodeTable_Get(pit->table, interestMessage);
- if (entry) {
- return pitEntry_Acquire(entry);
- }
- return NULL;
-}
-
-// ======================================================================
-// Public API
-
-PIT *pitStandard_Create(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
-
- size_t allocation = sizeof(PIT) + sizeof(StandardPIT);
-
- PIT *generic = parcMemory_AllocateAndClear(allocation);
- parcAssertNotNull(generic, "parcMemory_AllocateAndClear(%zu) returned NULL",
- allocation);
- generic->closure = (uint8_t *)generic + sizeof(PIT);
-
- StandardPIT *pit = pit_Closure(generic);
- pit->forwarder = forwarder;
- pit->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- size_t initialSize = 65535;
- pit->table =
- parcHashCodeTable_Create_Size(hashTableFunction_MessageNameEquals,
- hashTableFunction_MessageNameHashCode, NULL,
- _pit_PitEntryDestroyer, initialSize);
-
- if (logger_IsLoggable(pit->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(pit->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__, "PIT %p created", (void *)pit);
- }
-
- generic->getPitEntry = _pitStandard_GetPitEntry;
- generic->receiveInterest = _pitStandard_ReceiveInterest;
- generic->release = _pitStandard_Destroy;
- generic->removeInterest = _pitStandard_RemoveInterest;
- generic->satisfyInterest = _pitStandard_SatisfyInterest;
-
- return generic;
-}
diff --git a/hicn-light/src/hicn/processor/pitStandard.h b/hicn-light/src/hicn/processor/pitStandard.h
deleted file mode 100644
index 9d7ce6a23..000000000
--- a/hicn-light/src/hicn/processor/pitStandard.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file pitStandard.h
- * @brief The Pending Interest Table
- *
- * Implements the standard Pending Interest Table.
- *
- */
-
-#ifndef pitStandard_h
-#define pitStandard_h
-
-#include <hicn/processor/pit.h>
-
-/**
- * Creates a PIT table
- *
- * Creates and allocates an emtpy PIT table. The Forwarder reference is
- * used for logging and for time functions.
- *
- * @param [in] hicn-light The releated Forwarder
- *
- * @return non-null a PIT table
- * @return null An error
- */
-PIT *pitStandard_Create(Forwarder *forwarder);
-#endif // pit_h
diff --git a/hicn-light/src/hicn/processor/pitVerdict.h b/hicn-light/src/hicn/processor/pitVerdict.h
deleted file mode 100644
index f37242027..000000000
--- a/hicn-light/src/hicn/processor/pitVerdict.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file pitVerdict.h
- * @brief Adding an entry to the PIT will return NEW or EXISTING
- *
- * Adding an entry to the PIT will return NEW or EXISTING
- *
- */
-
-#ifndef pitVerdict_h
-#define pitVerdict_h
-
-/**
- * @typedef PitVerdict
- * @abstract The verdit of the PIT for receiving a message
- * @constant PITVerdict_Forward The message made a new PIT entry, the interest
- * should be forwarded
- * @constant PITVerdict_Aggregate The Interest was aggregated in the PIT, does
- * not need to be forwarded
- */
-#ifdef WITH_POLICY
-typedef enum { PITVerdict_Forward, PITVerdict_Aggregate, PITVerdict_Retransmit } PITVerdict;
-#else
-typedef enum { PITVerdict_Forward, PITVerdict_Aggregate } PITVerdict;
-#endif /* WITH_POLICY */
-#endif // pitVerdict_h
diff --git a/hicn-light/src/hicn/socket/CMakeLists.txt b/hicn-light/src/hicn/socket/CMakeLists.txt
index 8c8a757fb..41dbd2342 100644
--- a/hicn-light/src/hicn/socket/CMakeLists.txt
+++ b/hicn-light/src/hicn/socket/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -25,11 +25,5 @@ if (UNIX AND NOT APPLE)
)
endif()
-set(TO_INSTALL_HEADER_FILES
- ${TO_INSTALL_HEADER_FILES}
- ${HEADER_FILES}
- PARENT_SCOPE
-)
-
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/socket/api.c b/hicn-light/src/hicn/socket/api.c
index 34c0aae54..e39ebf4b5 100644
--- a/hicn-light/src/hicn/socket/api.c
+++ b/hicn-light/src/hicn/socket/api.c
@@ -10,8 +10,12 @@
#include <unistd.h> // close
#include "api.h"
-#include "error.h"
#include "ops.h"
+#include <hicn/util/sstrncpy.h>
+
+#if __linux__
+#include "error.h"
+#endif
#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN
@@ -72,8 +76,7 @@ hicn_socket_helper_t *hicn_create() {
}
hicn->conf = malloc(sizeof(hicn_conf_t));
- if (hicn->conf < 0)
- goto ERR_CONF;
+ if (hicn->conf < 0) goto ERR_CONF;
memcpy(hicn->conf, &hicn_default_conf, sizeof(hicn_conf_t));
/* Initialize socket tree to empty */
@@ -133,20 +136,16 @@ void hicn_destroy() {
/* Restore default rules */
printf("Restoring default configuration.\n");
rc = ops.del_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY);
- if (rc < 0)
- ret = -1;
+ if (rc < 0) ret = -1;
rc = ops.del_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY);
- if (rc < 0)
- ret = -1;
+ if (rc < 0) ret = -1;
rc = ops.add_lo_prio_rule(NULL, AF_INET6, 0);
- if (rc < 0)
- ret = -1;
+ if (rc < 0) ret = -1;
rc = ops.add_lo_prio_rule(NULL, AF_INET, 0);
- if (rc < 0)
- ret = -1;
+ if (rc < 0) ret = -1;
for (i = 0; i < rules_counter; i++) {
if (strcmp(rules_to_remove[i].tun_name, "NONE") != 0) {
@@ -158,20 +157,17 @@ void hicn_destroy() {
&rules_to_remove[i].prefix, rules_to_remove[i].address_family,
rules_to_remove[i].priority, rules_to_remove[i].table_id);
}
- if (rc < 0)
- ret = -1;
+ if (rc < 0) ret = -1;
}
for (i = 0; i < routes_counter; i++) {
rc = ops.del_out_route(routes_to_remove[i].remote_ip_address,
routes_to_remove[i].address_family,
routes_to_remove[i].table_id);
- if (rc < 0)
- ret = -1;
+ if (rc < 0) ret = -1;
}
- if (ret < 0)
- printf("Unexpected exit. Some state may not be deleted.\n");
+ if (ret < 0) printf("Unexpected exit. Some state may not be deleted.\n");
}
void hicn_free(hicn_socket_helper_t *hicn) {
@@ -259,10 +255,10 @@ int hicn_get_local_address(const ip_prefix_t *remote_address,
ip_prefix_t *local_address) {
int rc = 0;
uint32_t interface_id;
- char remote_address_str[INET_MAX_ADDRSTRLEN + 4 ];
+ char remote_address_str[INET_MAX_ADDRSTRLEN + 4];
rc = ip_prefix_ntop_short(remote_address, remote_address_str,
- sizeof(remote_address_str));
+ sizeof(remote_address_str));
if (rc < 0) {
rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR;
goto ERR;
@@ -331,7 +327,8 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket,
/////
/* Convert to representation format */
- rc = ip_prefix_ntop_short(&addr, local_ip_address, sizeof(local_ip_address));
+ rc =
+ ip_prefix_ntop_short(&addr, local_ip_address, sizeof(local_ip_address));
if (rc < 0) {
rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR;
goto ERR;
@@ -466,7 +463,9 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) {
return rc;
}
- strcpy(rules_to_remove[rules_counter].tun_name, "NONE");
+ rc = strcpy_s(rules_to_remove[rules_counter].tun_name,
+ sizeof(rules_to_remove[rules_counter].tun_name), "NONE");
+ if (rc != EOK) return -1;
rules_to_remove[rules_counter].prefix = ip_prefix;
rules_to_remove[rules_counter].address_family = ip_prefix.family;
@@ -533,7 +532,10 @@ int hicn_bind(hicn_socket_helper_t *hicn, int fd,
goto ERR;
}
- strcpy(rules_to_remove[rules_counter].tun_name, socket->tun_name);
+ rc = strcpy_s(rules_to_remove[rules_counter].tun_name,
+ sizeof(rules_to_remove[rules_counter].tun_name),
+ socket->tun_name);
+ if (rc != EOK) return -1;
rules_to_remove[rules_counter].address_family = addr_family;
rules_to_remove[rules_counter].table_id = socket->connection.table_id;
++rules_counter;
@@ -563,7 +565,13 @@ int hicn_bind(hicn_socket_helper_t *hicn, int fd,
goto ERR;
}
- strcpy(routes_to_remove[routes_counter].remote_ip_address, remote_ip_address);
+ rc = strcpy_s(routes_to_remove[routes_counter].remote_ip_address,
+ sizeof(rules_to_remove[rules_counter].tun_name),
+ remote_ip_address);
+ if (rc != EOK) {
+ rc = HICN_SOCKET_ERROR_UNSPEC;
+ goto ERR;
+ }
routes_to_remove[routes_counter].table_id = socket->connection.table_id;
routes_to_remove[routes_counter].address_family = (uint8_t)addr_family;
++routes_counter;
diff --git a/hicn-light/src/hicn/socket/api.h b/hicn-light/src/hicn/socket/api.h
index 1a7f5c700..a0356e035 100644
--- a/hicn-light/src/hicn/socket/api.h
+++ b/hicn-light/src/hicn/socket/api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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.
@@ -29,7 +29,6 @@
#include <stdlib.h>
#include <hicn/hicn.h>
-#include "error.h"
#define BUFSIZE 4096
#define MAX_CONNECTIONS \
diff --git a/hicn-light/src/hicn/socket/ops_linux.c b/hicn-light/src/hicn/socket/ops_linux.c
index 8bfc438f3..d741fd2e6 100644
--- a/hicn-light/src/hicn/socket/ops_linux.c
+++ b/hicn-light/src/hicn/socket/ops_linux.c
@@ -24,6 +24,8 @@
#include <stdint.h>
#include <stdlib.h>
+#include <hicn/ctrl/api.h>
+#include <hicn/util/sstrncpy.h>
/* Public interface */
@@ -338,7 +340,8 @@ uint32_t _nl_get_ifid(const char *interface_name) {
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
int fd;
- size_t len = interface_name ? strlen(interface_name) + 1 : 0;
+ size_t len =
+ interface_name ? strnlen_s(interface_name, INTERFACE_LEN) + 1 : 0;
uint8_t padding[RTA_ALIGNTO] = {0, 0, 0, 0};
if (len == 0) {
@@ -353,8 +356,8 @@ uint32_t _nl_get_ifid(const char *interface_name) {
.hdr.nlmsg_flags = FLAGS_GET,
.payload.ifi_family = AF_UNSPEC,
.payload.ifi_index = 0};
- struct rtattr a_ifname = {RTA_LENGTH(strlen(interface_name) + 1),
- IFLA_IFNAME};
+ struct rtattr a_ifname = {
+ RTA_LENGTH(strnlen_s(interface_name, INTERFACE_LEN) + 1), IFLA_IFNAME};
struct iovec iov[] = {{&msg, sizeof(msg)},
{&a_ifname, sizeof(a_ifname)},
@@ -621,13 +624,12 @@ int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) {
/* Set attributes = length/type/value */
struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(prefix->family)),
IFA_ADDRESS};
- const void * address = ip_address_get_buffer(&prefix->address, prefix->family);
- if (!address)
- goto ERR_ADDRESS;
+ const void *address = ip_address_get_buffer(&prefix->address, prefix->family);
+ if (!address) goto ERR_ADDRESS;
const struct iovec iov[] = {
{&msg, sizeof(msg)},
{&ifa_address, sizeof(ifa_address)},
- {(void*)address, ip_address_len(prefix->family)},
+ {(void *)address, ip_address_len(prefix->family)},
};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
@@ -993,17 +995,15 @@ int _nl_del_lo_route(const ip_prefix_t *prefix) {
uint32_t one = 1;
struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST};
struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF};
- const void * address = ip_address_get_buffer(&prefix->address, prefix->family);
- if (!address)
- goto ERR;
- const struct iovec iov[] = {
- {&msg, sizeof(msg)},
- /* Ip address */
- {&a_dst, sizeof(a_dst)},
- {(void*)address, ip_address_len(prefix->family)},
- /* Interface id */
- {&a_ifid_lo, sizeof(a_ifid_lo)},
- {&one, sizeof(one)}};
+ const void *address = ip_address_get_buffer(&prefix->address, prefix->family);
+ if (!address) goto ERR;
+ const struct iovec iov[] = {{&msg, sizeof(msg)},
+ /* Ip address */
+ {&a_dst, sizeof(a_dst)},
+ {(void *)address, ip_address_len(prefix->family)},
+ /* Interface id */
+ {&a_ifid_lo, sizeof(a_ifid_lo)},
+ {&one, sizeof(one)}};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
@@ -1048,7 +1048,7 @@ int _nl_add_rule(const char *interface_name, uint8_t address_family,
_nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE);
addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name,
- strlen(interface_name));
+ strnlen_s(interface_name, INTERFACE_LEN));
fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (fd < 0) {
@@ -1094,7 +1094,7 @@ int _nl_del_rule(const char *interface_name, uint8_t address_family,
_nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE);
addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name,
- strlen(interface_name));
+ strnlen_s(interface_name, INTERFACE_LEN));
fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (fd < 0) {
@@ -1158,16 +1158,15 @@ int _nl_add_neigh_proxy(const ip_prefix_t *prefix,
/* Message attributes = length/type/value */
struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), NDA_DST};
- const void * address = ip_address_get_buffer(&prefix->address, prefix->family);
- if (!address)
- goto ERR;
+ const void *address = ip_address_get_buffer(&prefix->address, prefix->family);
+ if (!address) goto ERR;
/* Iovec describing the packets */
const struct iovec iov[] = {
{&msg, sizeof(msg)},
/* Ip address */
{&a_dst, sizeof(a_dst)},
- {(void*)address, ip_address_len(prefix->family)},
+ {(void *)address, ip_address_len(prefix->family)},
};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
@@ -1240,16 +1239,15 @@ int _nl_add_in_route_table(const ip_prefix_t *prefix,
struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST};
struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF};
- const void * address = ip_address_get_buffer(&prefix->address, prefix->family);
- if (!address)
- goto ERR;
+ const void *address = ip_address_get_buffer(&prefix->address, prefix->family);
+ if (!address) goto ERR;
/* Iovec describing the packets */
const struct iovec iov[] = {
{&msg, sizeof(msg)},
/* Destination prefix / ip address */
{&a_dst, sizeof(a_dst)},
- {(void*)address, ip_address_len(prefix->family)},
+ {(void *)address, ip_address_len(prefix->family)},
/* Output interface */
{&a_oif, sizeof(a_oif)},
{(void *)&interface_id, sizeof(uint32_t)},
@@ -1346,15 +1344,15 @@ int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC};
struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY};
- const void * address = ip_address_get_buffer(&prefix->address, prefix->family);
- if (!address)
- goto ERR;
+ const void *address =
+ ip_address_get_buffer(&prefix->address, prefix->family);
+ if (!address) goto ERR;
/* Iovec describing the packets */
const struct iovec iov[] = {
{&msg, sizeof(msg)},
/* Source prefix / prefix */
{&a_src, sizeof(a_src)},
- {(void*)address, ip_address_len(prefix->family)},
+ {(void *)address, ip_address_len(prefix->family)},
/* Priority */
{&a_prio, sizeof(a_prio)},
{(void *)&priority, sizeof(uint32_t)},
@@ -1407,8 +1405,7 @@ ERR:
int _nl_add_lo_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
const uint32_t priority) {
- return _nl_add_prio_rule(prefix, address_family, priority,
- RT_TABLE_LOCAL);
+ return _nl_add_prio_rule(prefix, address_family, priority, RT_TABLE_LOCAL);
}
/* ip -6 rule del from all prio 0 table local */
@@ -1450,16 +1447,16 @@ int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC};
struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY};
- const void * address = ip_address_get_buffer(&prefix->address, prefix->family);
- if (!address)
- goto ERR;
+ const void *address =
+ ip_address_get_buffer(&prefix->address, prefix->family);
+ if (!address) goto ERR;
/* Iovec describing the packets */
const struct iovec iov[] = {
{&msg, sizeof(msg)},
/* Source prefix / prefix */
{&a_src, sizeof(a_src)},
- {(void*)address, ip_address_len(prefix->family)},
+ {(void *)address, ip_address_len(prefix->family)},
/* Priority */
{&a_prio, sizeof(a_prio)},
{(void *)&priority, sizeof(uint32_t)},
@@ -1539,7 +1536,7 @@ int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, uint8_t address_family,
int tun_alloc(char *dev, int flags) {
struct ifreq ifr;
- int fd, err;
+ int fd, err, rc;
char *clonedev = "/dev/net/tun";
/* Arguments taken by the function:
@@ -1563,7 +1560,8 @@ int tun_alloc(char *dev, int flags) {
/* if a device name was specified, put it in the structure; otherwise,
* the kernel will try to allocate the "next" device of the
* specified type */
- strncpy(ifr.ifr_name, dev, IF_NAMESIZE - 1);
+ rc = strcpy_s(ifr.ifr_name, IF_NAMESIZE - 1, dev);
+ if (rc != EOK) return -1;
}
/* try to create the device */
@@ -1576,7 +1574,8 @@ int tun_alloc(char *dev, int flags) {
* interface to the variable "dev", so the caller can know
* it. Note that the caller MUST reserve space in *dev (see calling
* code below) */
- strcpy(dev, ifr.ifr_name);
+ rc = strcpy_s(dev, IF_NAMESIZE, ifr.ifr_name);
+ if (rc != EOK) return -1;
/* this is the special file descriptor that the caller will use to talk
* with the virtual interface */
diff --git a/hicn-light/src/hicn/strategies/CMakeLists.txt b/hicn-light/src/hicn/strategies/CMakeLists.txt
index 886aa137c..15ae93fea 100644
--- a/hicn-light/src/hicn/strategies/CMakeLists.txt
+++ b/hicn-light/src/hicn/strategies/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -12,20 +12,23 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/strategyImpl.h
- ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/lowLatency.h
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.h
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateLowLatency.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rnd.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/random.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/replication.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/best_path.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/local_prefixes.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/probe_generator.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.c
- ${CMAKE_CURRENT_SOURCE_DIR}/lowLatency.c
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.c
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateLowLatency.c
- ${CMAKE_CURRENT_SOURCE_DIR}/rnd.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/random.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/replication.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/best_path.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/local_prefixes.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/probe_generator.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/strategies/best_path.c b/hicn-light/src/hicn/strategies/best_path.c
new file mode 100644
index 000000000..35a07c43f
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/best_path.c
@@ -0,0 +1,344 @@
+/*
+ * 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 <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <hicn/hicn-light/config.h>
+
+#include <hicn/core/forwarder.h>
+#include <hicn/core/nexthops.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+
+#include "best_path.h"
+
+#define MAX_NEXTHOP_COST 100
+#define MAX_RTT_ALLOWED 300.0 // ms
+#define MAX_LOSSES_ALLOWED 0.4 // 40%
+
+#define MAX_PROBING_DURATION 5000 // ticks (= ms)
+#define PROBES_WAINTING_TIME 500 // ticks (= ms)
+#define MAX_PROBES 50
+
+/* Shorthand */
+#define nexthop_state_t strategy_bestpath_nexthop_state_t
+#define strategy_state_t strategy_bestpath_state_t
+#define nexthop_state(nexthops, i) (&nexthops->state[i].bestpath)
+
+// nexthop state functions
+
+static const nexthop_state_t NEXTHOP_STATE_INIT = {
+ .sent_probes = 0,
+ .recv_probes = 0,
+ .rtt_sum = 0,
+};
+
+static inline unsigned int get_sent_probes(nexthop_state_t *state) {
+ return state->sent_probes;
+}
+
+static inline unsigned int inc_sent_probes(nexthop_state_t *state) {
+ state->sent_probes++;
+ return state->sent_probes;
+}
+
+static inline void add_rtt_sample(nexthop_state_t *state, Ticks rtt) {
+ state->recv_probes++;
+ state->rtt_sum += rtt;
+}
+
+static inline unsigned int get_nexthop_cost(nexthop_state_t *state) {
+ if (state->recv_probes == 0)
+ return 100; // we have no info for this nexthop, return max cost
+
+ assert(state->recv_probes <= state->sent_probes);
+
+ double rtt = (double)state->rtt_sum / (double)state->recv_probes;
+ double delay_cost = rtt / MAX_RTT_ALLOWED;
+ if (delay_cost > 1) delay_cost = 1;
+
+ double loss_rate = (double)(state->sent_probes - state->recv_probes) /
+ (double)state->sent_probes;
+ double loss_cost = loss_rate / MAX_LOSSES_ALLOWED;
+ if (loss_cost > 1) loss_cost = 1;
+
+ double total_cost = delay_cost * 0.5 + loss_cost * 0.5;
+ return round(total_cost * 100);
+}
+
+// options functions
+static void bestpath_update_remote_node(strategy_entry_t *entry,
+ nexthops_t *nexthops) {
+ strategy_state_t *state = &entry->state.bestpath;
+ strategy_bestpath_options_t *options = &entry->options.bestpath;
+ off_t offset = nexthops_find(nexthops, state->best_nexthop);
+ nexthops_select(nexthops, offset);
+ update_remote_node_paths(nexthops, entry->forwarder, options->local_prefixes);
+}
+
+// probing functions
+
+static void start_probing(strategy_entry_t *entry) {
+ strategy_state_t *state = &entry->state.bestpath;
+ if (state->probing_state == PROBING_OFF) {
+ state->probing_state = PROBING_ON;
+ state->probing_time = ticks_now();
+ }
+}
+
+static void stop_probing(strategy_entry_t *entry, nexthops_t *nexthops) {
+ strategy_state_t *state = &entry->state.bestpath;
+ nexthop_t best_nexthop, nexthop;
+ best_nexthop = state->best_nexthop;
+ unsigned i;
+ unsigned int min_cost = ~0;
+ unsigned current_nexthop_cost = ~0;
+
+ nexthops_enumerate(nexthops, i, nexthop, {
+ unsigned int cost = get_nexthop_cost(nexthop_state(nexthops, i));
+ if (cost < min_cost) {
+ min_cost = cost;
+ best_nexthop = nexthop;
+ }
+ if (nexthop == state->best_nexthop) current_nexthop_cost = cost;
+
+ nexthops->state[i].bestpath = NEXTHOP_STATE_INIT;
+ });
+
+ if (best_nexthop != state->best_nexthop) {
+ if (current_nexthop_cost > min_cost) {
+ // update best face
+ state->best_nexthop = best_nexthop;
+ }
+ }
+
+ // always update remote node
+ bestpath_update_remote_node(entry, nexthops);
+
+ state->probing_state = PROBING_OFF;
+ delete_all_probes(state->pg);
+}
+
+static void check_stop_probing(strategy_entry_t *entry, nexthops_t *nexthops) {
+ strategy_state_t *state = &entry->state.bestpath;
+ if (state->probing_state == PROBING_OFF) return;
+
+ if (state->probing_state == PROBING_ON) {
+ Ticks probing_duration = ticks_now() - state->probing_time;
+ if (probing_duration >= MAX_PROBING_DURATION) {
+ state->probing_state = PROBING_ENDING;
+ state->probing_time = ticks_now();
+ }
+ return;
+ }
+
+ if (state->probing_state == SENT_MAX_PROBES) {
+ state->probing_state = PROBING_ENDING;
+ state->probing_time = ticks_now();
+ return;
+ }
+
+ if (state->probing_state == PROBING_ENDING) {
+ Ticks ending_duration = ticks_now() - state->probing_time;
+ if (ending_duration >= PROBES_WAINTING_TIME) stop_probing(entry, nexthops);
+ }
+}
+
+static void send_probes(strategy_entry_t *entry, nexthops_t *nexthops,
+ const msgbuf_t *msgbuf) {
+ strategy_state_t *state = &entry->state.bestpath;
+
+ unsigned i;
+ nexthop_t nexthop;
+ bool sent_max_probes = false;
+ nexthops_enumerate(nexthops, i, nexthop, {
+ if (get_sent_probes(nexthop_state(nexthops, i)) < MAX_PROBES) {
+ int res = generate_probe(state->pg, msgbuf, entry->forwarder, nexthop);
+ if (res >= 0) inc_sent_probes(nexthop_state(nexthops, i));
+ } else {
+ sent_max_probes = true;
+ }
+ });
+
+ if (sent_max_probes) {
+ state->probing_state = SENT_MAX_PROBES;
+ check_stop_probing(entry, nexthops);
+ }
+}
+
+static void init_strategy_state(strategy_state_t *state) {
+ state->best_nexthop = ~0;
+ state->probing_state = PROBING_OFF;
+ state->pg = create_probe_generator();
+}
+
+// strategy functions
+static int strategy_bestpath_initialize(strategy_entry_t *entry,
+ const void *forwarder) {
+ if (entry->forwarder == NULL) {
+ srand((unsigned int)time(NULL));
+ entry->forwarder = forwarder;
+ init_strategy_state(&entry->state.bestpath);
+ } else {
+ strategy_state_t *state = &entry->state.bestpath;
+ if (!state->pg) {
+ // the previous strategy was a different one
+ init_strategy_state(state);
+ } else {
+ // all set, start probing
+ start_probing(entry);
+ }
+ }
+ return 0;
+}
+
+static int strategy_bestpath_finalize(strategy_entry_t *entry) {
+ strategy_state_t *state = &entry->state.bestpath;
+ free_local_prefixes(entry->options.bestpath.local_prefixes);
+ destroy_probe_generator(state->pg);
+ return 0;
+}
+
+static int strategy_bestpath_add_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops, off_t offset) {
+ // reset the strategy state
+ nexthops->state[offset].bestpath = NEXTHOP_STATE_INIT;
+ return 0;
+}
+
+static int strategy_bestpath_remove_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static nexthops_t *strategy_bestpath_lookup_nexthops(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const msgbuf_t *msgbuf) {
+ size_t nexthops_len = nexthops_get_curlen(nexthops);
+ if (nexthops_len == 0) {
+ // nexthops is empty, return
+ return nexthops;
+ }
+
+ strategy_state_t *state = &entry->state.bestpath;
+ off_t best_nexthop_offset = nexthops_find(nexthops, state->best_nexthop);
+
+ if (nexthops_len == 1) {
+ nexthop_t nh = nexthops_get_one(nexthops);
+ if (state->best_nexthop != nh) {
+ state->best_nexthop = nh;
+ bestpath_update_remote_node(entry, nexthops);
+ }
+ return nexthops;
+ }
+
+ if (state->best_nexthop == ~0 || best_nexthop_offset == INVALID_NEXTHOP) {
+ state->best_nexthop = nexthops_get_one(nexthops);
+ best_nexthop_offset = nexthops_find(nexthops, state->best_nexthop);
+ bestpath_update_remote_node(entry, nexthops);
+ // we have probe only in case the number of face is > 1
+ start_probing(entry);
+ // bestpath_update_remote_node sets the nexthops. in case of probing we want
+ // to send the packets on all faces, so we reset the nexthops here
+ nexthops_reset(nexthops);
+ }
+
+ if (state->probing_state == PROBING_ON) {
+ // send a probe for each interest received
+ send_probes(entry, nexthops, msgbuf);
+
+ uint32_t suffix = name_GetSuffix(msgbuf_get_name(msgbuf));
+ if (suffix >= MIN_PROBE_SUFFIX && suffix <= MAX_PROBE_SUFFIX) {
+ // this packet is a probe from the transport, so register it
+ Ticks time = get_probe_send_time(state->pg, suffix);
+ if (time == 0) {
+ // a probe with the same seq number is not pending, send the packet
+ // the stats for this probe will be collected by the transport
+ register_probe(state->pg, suffix);
+ } else {
+ // this probe is already pending. avoid duplicates and drop it
+ nexthops->flags = ~0;
+ nexthops->cur_elts = 0;
+ }
+ }
+ } else {
+ // we are not probing anymore. if in probing ending state (wait for probes
+ // to come back) keep replicating traffic, otherwise and on best path
+ if (state->probing_state != PROBING_ENDING)
+ nexthops_select(nexthops, best_nexthop_offset);
+ }
+
+ // in case we are still probing send all interest on all paths
+ // so do not select any next hop.
+ // XXX in this transition phase should we replicate also at the
+ // server side?
+ return nexthops;
+}
+
+static int strategy_bestpath_on_data(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *data_nexthops,
+ const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation,
+ Ticks objReception) {
+ strategy_state_t *state = &entry->state.bestpath;
+ if (state->probing_state == PROBING_OFF) return 0;
+
+ uint32_t seq = name_GetSuffix(msgbuf_get_name(msgbuf));
+ if (seq >= MIN_PROBE_SUFFIX && seq <= MAX_PROBE_SUFFIX) {
+ if (pitEntryCreation != 0) {
+ // this is not a probe sent by the forwader. do not use it in the probing
+ // statisitcs but remove it from the map if it exists
+ delete_probe(state->pg, seq);
+ return 0;
+ }
+
+ unsigned nexthop, i;
+ Ticks send_time = get_probe_send_time(state->pg, seq);
+ if (send_time != 0) {
+ Ticks rtt = ticks_now() - send_time;
+ delete_probe(state->pg, seq);
+ nexthops_enumerate(data_nexthops, i, nexthop, {
+ off_t pos = nexthops_find(nexthops, nexthop);
+ add_rtt_sample(nexthop_state(nexthops, pos), rtt);
+ });
+ }
+ }
+
+ check_stop_probing(entry, nexthops);
+
+ return 0;
+}
+
+static int strategy_bestpath_on_timeout(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops) {
+ /* Nothing to do */
+ return 0;
+}
+
+#undef nexthop_state_t
+#undef strategy_state_t
+
+DECLARE_STRATEGY(bestpath);
+
+#undef nexthop_state_t
+#undef strategy_state_t
diff --git a/hicn-light/src/hicn/strategies/best_path.h b/hicn-light/src/hicn/strategies/best_path.h
new file mode 100644
index 000000000..206214579
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/best_path.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+/**
+ * Forward on a single path. Every time the strategy is reset with a command the
+ * forwarder starts to probe the available paths matching the probes on the
+ * original flow. if after the probing phase a better path exists (lower
+ * latency, less losses) the forwarder switch path, otherwise does nothing
+ */
+
+#ifndef HICNLIGHT_STRATEGY_BESTPATH_H
+#define HICNLIGHT_STRATEGY_BESTPATH_H
+
+#include "probe_generator.h"
+#include "local_prefixes.h"
+
+typedef enum {
+ PROBING_OFF,
+ PROBING_ON,
+ SENT_MAX_PROBES,
+ PROBING_ENDING, // waiting for probes to come back
+ UNKWNOWN,
+} probing_state_t;
+
+typedef struct {
+ // number or probes sent during a probing phase
+ unsigned int sent_probes;
+ // number or probes received during a probing phase
+ unsigned int recv_probes;
+ // sum of all rtt collected
+ Ticks rtt_sum;
+} strategy_bestpath_nexthop_state_t;
+
+typedef struct {
+ unsigned best_nexthop;
+ Ticks probing_time;
+ probing_state_t probing_state;
+ probe_generator_t *pg;
+} strategy_bestpath_state_t;
+
+typedef struct {
+ local_prefixes_t *local_prefixes;
+} strategy_bestpath_options_t;
+
+#endif /* HICNLIGHT_STRATEGY_BESTPATH_H */
diff --git a/hicn-light/src/hicn/strategies/loadBalancer.c b/hicn-light/src/hicn/strategies/loadBalancer.c
deleted file mode 100644
index 82b5a6103..000000000
--- a/hicn-light/src/hicn/strategies/loadBalancer.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_Unsigned.h>
-
-#include <hicn/strategies/loadBalancer.h>
-#include <hicn/strategies/nexthopState.h>
-
-static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-static void _strategyLoadBalancer_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId);
-static NumberSet *_strategyLoadBalancer_LookupNexthop(
- StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
-static NumberSet *_strategyLoadBalancer_ReturnNexthops(StrategyImpl *strategy);
-static unsigned _strategyLoadBalancer_CountNexthops(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
-static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLoadBalancer_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLoadBalancer_ImplDestroy(StrategyImpl **strategyPtr);
-static strategy_type _strategyLoadBalancer_GetStrategy(StrategyImpl *strategy);
-
-static StrategyImpl _template = {
- .context = NULL,
- .receiveObject = &_strategyLoadBalancer_ReceiveObject,
- .onTimeout = &_strategyLoadBalancer_OnTimeout,
- .lookupNexthop = &_strategyLoadBalancer_LookupNexthop,
-#ifndef WITH_POLICY
- .returnNexthops = &_strategyLoadBalancer_ReturnNexthops,
- .countNexthops = &_strategyLoadBalancer_CountNexthops,
-#endif /* ! WITH_POLICY */
- .addNexthop = &_strategyLoadBalancer_AddNexthop,
- .removeNexthop = &_strategyLoadBalancer_RemoveNexthop,
- .destroy = &_strategyLoadBalancer_ImplDestroy,
- .getStrategy = &_strategyLoadBalancer_GetStrategy,
-};
-
-struct strategy_load_balancer;
-typedef struct strategy_load_balancer StrategyLoadBalancer;
-
-struct strategy_load_balancer {
-#ifndef WITH_POLICY
- double weights_sum;
-#endif /* ! WITH_POLICY */
- // hash map from connectionId to StrategyNexthopState
- PARCHashMap *strategy_state;
-#ifndef WITH_POLICY
- NumberSet *nexthops;
-#endif /* ! WITH_POLICY */
-};
-
-StrategyImpl *strategyLoadBalancer_Create() {
- StrategyLoadBalancer *strategy =
- parcMemory_AllocateAndClear(sizeof(StrategyLoadBalancer));
- parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyLoadBalancer));
-
-#ifndef WITH_POLICY
- strategy->weights_sum = 0.0;
-#endif /* ! WITH_POLICY */
- strategy->strategy_state = parcHashMap_Create();
-#ifndef WITH_POLICY
- strategy->nexthops = numberSet_Create();
-#endif /* ! WITH_POLICY */
- srand((unsigned int)time(NULL));
-
- StrategyImpl *impl = parcMemory_AllocateAndClear(sizeof(StrategyImpl));
- parcAssertNotNull(impl, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyImpl));
- memcpy(impl, &_template, sizeof(StrategyImpl));
- impl->context = strategy;
-
- return impl;
-}
-
-// =======================================================
-// Dispatch API
-
-strategy_type _strategyLoadBalancer_GetStrategy(StrategyImpl *strategy) {
- return SET_STRATEGY_LOADBALANCER;
-}
-
-static void _update_Stats(StrategyLoadBalancer *strategy,
- StrategyNexthopState *state, bool inc) {
- const double ALPHA = 0.9;
-#ifdef WITH_POLICY
- strategyNexthopState_UpdateState(state, inc, ALPHA);
-#else
- double w = strategyNexthopState_GetWeight(state);
- strategy->weights_sum -= w;
- w = strategyNexthopState_UpdateState(state, inc, ALPHA);
- strategy->weights_sum += w;
-#endif /* WITH_POLICY */
-}
-
-#ifndef WITH_POLICY
-static unsigned _select_Nexthop(StrategyLoadBalancer *strategy) {
- double rnd = (double)rand() / (double)RAND_MAX;
- double start_range = 0.0;
-
- PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
-
- unsigned nexthop = 100000;
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- const StrategyNexthopState *elem =
- parcHashMap_Get(strategy->strategy_state, cid);
-
- double w = strategyNexthopState_GetWeight(elem);
-
- double prob = w / strategy->weights_sum;
- if ((rnd >= start_range) && (rnd <= (start_range + prob))) {
- nexthop = parcUnsigned_GetUnsigned(cid);
- break;
- } else {
- start_range += prob;
- }
- }
-
- parcIterator_Release(&it);
-
- // if no face is selected by the algorithm (for example because of a wrong
- // round in the weights) we may always select the last face here. Double check
- // this!
- return nexthop;
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {
- _strategyLoadBalancer_OnTimeout(strategy, egressId);
-}
-
-static void _strategyLoadBalancer_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-
- for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
- unsigned outId = numberSet_GetItem(egressId, i);
- PARCUnsigned *cid = parcUnsigned_Create(outId);
-
- const StrategyNexthopState *state =
- parcHashMap_Get(lb->strategy_state, cid);
- if (state != NULL) {
- _update_Stats(lb, (StrategyNexthopState *)state, false);
- } else {
- // this may happen if we remove a face/route while downloading a file
- // we should ignore this timeout
- }
- parcUnsigned_Release(&cid);
- }
-}
-
-static NumberSet *_strategyLoadBalancer_LookupNexthop(
- StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
- NumberSet *outList = numberSet_Create();
-
-#ifdef WITH_POLICY
- /* Compute the sum of weights of potential next hops */
- double sum = 0;
- for (unsigned i = 0; i < numberSet_Length(nexthops); i++) {
- PARCUnsigned *cid = parcUnsigned_Create(numberSet_GetItem(nexthops, i));
- const StrategyNexthopState *elem =
- parcHashMap_Get(lb->strategy_state, cid);
- parcUnsigned_Release(&cid);
- if (!elem)
- continue;
- sum += strategyNexthopState_GetWeight(elem);
- }
-
- /* Perform weighted random selection */
- double distance = (double)rand() * sum / ((double)RAND_MAX + 1);
-
- for (unsigned i = 0; i < numberSet_Length(nexthops); i++) {
- PARCUnsigned *cid = parcUnsigned_Create(numberSet_GetItem(nexthops, i));
- const StrategyNexthopState *state =
- parcHashMap_Get(lb->strategy_state, cid);
- if (!state) {
- parcUnsigned_Release(&cid);
- continue;
- }
- distance -= strategyNexthopState_GetWeight(state);
- if (distance < 0) {
- numberSet_Add(outList, parcUnsigned_GetUnsigned(cid));
- _update_Stats(lb, (StrategyNexthopState *)state, true);
- parcUnsigned_Release(&cid);
- break;
- }
- parcUnsigned_Release(&cid);
- }
-#else
- unsigned in_connection = message_GetIngressConnectionId(interestMessage);
- PARCUnsigned *in = parcUnsigned_Create(in_connection);
-
- unsigned mapSize = (unsigned)parcHashMap_Size(lb->strategy_state);
-
- if ((mapSize == 0) ||
- ((mapSize == 1) && parcHashMap_Contains(lb->strategy_state, in))) {
- // there are no output faces or the input face is also the only output face.
- // return null to avoid loops
- parcUnsigned_Release(&in);
- return outList;
- }
-
- unsigned out_connection;
- do {
- out_connection = _select_Nexthop(lb);
- } while (out_connection == in_connection);
-
- PARCUnsigned *out = parcUnsigned_Create(out_connection);
-
- const StrategyNexthopState *state = parcHashMap_Get(lb->strategy_state, out);
- if (state == NULL) {
- // this is an error and should not happen!
- parcTrapNotImplemented(
- "Try to send an interest on a face that does not exists");
- }
-
- _update_Stats(lb, (StrategyNexthopState *)state, true);
-
- parcUnsigned_Release(&in);
- parcUnsigned_Release(&out);
-
- numberSet_Add(outList, out_connection);
-#endif /* WITH_POLICY */
-
- return outList;
-}
-
-#ifndef WITH_POLICY
-static NumberSet *_strategyLoadBalancer_ReturnNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
- return lb->nexthops;
-}
-
-unsigned _strategyLoadBalancer_CountNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
- return (unsigned)numberSet_Length(lb->nexthops);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyLoadBalancer_resetState(StrategyImpl *strategy) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-#ifndef WITH_POLICY
- lb->weights_sum = 0.0;
-#endif/* ! WITH_POLICY */
- PARCIterator *it = parcHashMap_CreateKeyIterator(lb->strategy_state);
-
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- StrategyNexthopState *elem =
- (StrategyNexthopState *)parcHashMap_Get(lb->strategy_state, cid);
-
- strategyNexthopState_Reset(elem);
-#ifndef WITH_POLICY
- lb->weights_sum += strategyNexthopState_GetWeight(elem);
-#endif /* ! WITH_POLICY */
- }
-
- parcIterator_Release(&it);
-}
-
-static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
-
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-
- if (!parcHashMap_Contains(lb->strategy_state, cid)) {
- StrategyNexthopState *state = strategyNexthopState_Create();
- parcHashMap_Put(lb->strategy_state, cid, state);
-#ifndef WITH_POLICY
- numberSet_Add(lb->nexthops, connectionId);
-#endif /* WITH_POLICY */
- _strategyLoadBalancer_resetState(strategy);
- }
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLoadBalancer_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- if (parcHashMap_Contains(lb->strategy_state, cid)) {
- StrategyNexthopState *state =
- (StrategyNexthopState *)parcHashMap_Get(lb->strategy_state, cid);
- parcObject_Release((void**)&state);
-
- parcHashMap_Remove(lb->strategy_state, cid);
-#ifndef WITH_POLICY
- numberSet_Remove(lb->nexthops, connectionId);
-#endif /* WITH_POLICY */
- _strategyLoadBalancer_resetState(strategy);
- }
-
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLoadBalancer_ImplDestroy(StrategyImpl **strategyPtr) {
- parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*strategyPtr,
- "Parameter must dereference to non-null pointer");
-
- StrategyImpl *impl = *strategyPtr;
- StrategyLoadBalancer *strategy = (StrategyLoadBalancer *)impl->context;
- if (parcHashMap_Size(strategy->strategy_state) > 0) {
- PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- StrategyNexthopState *state =
- (StrategyNexthopState *) parcHashMap_Get(strategy->strategy_state, cid);
- parcObject_Release((void **) &state);
- }
- parcIterator_Release(&it);
- }
-
- parcHashMap_Release(&(strategy->strategy_state));
-#ifndef WITH_POLICY
- numberSet_Release(&(strategy->nexthops));
-#endif /* ! WITH_POLICY */
-
- parcMemory_Deallocate((void **) &strategy);
- parcMemory_Deallocate((void **) &impl);
- *strategyPtr = NULL;
-}
diff --git a/hicn-light/src/hicn/strategies/load_balancer.c b/hicn-light/src/hicn/strategies/load_balancer.c
new file mode 100644
index 000000000..709efcf23
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/load_balancer.c
@@ -0,0 +1,153 @@
+/*
+ * 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/hicn-light/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <hicn/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+#include <hicn/core/nexthops.h>
+#include <hicn/core/fib_entry.h>
+
+#include "load_balancer.h"
+
+#define AVG_PI_THRESHOLD 1e-3
+#define AVG_PI_MIN 0.1
+
+#define ALPHA 0.9
+
+/* Shorthand */
+#define nexthop_state_t strategy_load_balancer_nexthop_state_t
+#define nexthop_state(nexthops, i) (&nexthops->state[i].load_balancer)
+
+static const nexthop_state_t NEXTHOP_STATE_INIT = {
+ .pi = 0,
+ .avg_pi = 0.0,
+ .weight = 1,
+};
+
+static inline void update_state(nexthop_state_t *state) {
+ state->avg_pi = (state->avg_pi * ALPHA) + (state->pi * 1 - ALPHA);
+ if (state->avg_pi < AVG_PI_THRESHOLD) state->avg_pi = AVG_PI_MIN;
+ state->weight = 1 / state->avg_pi;
+}
+
+static inline void update_state_inc(nexthop_state_t *state) {
+ state->pi++;
+ update_state(state);
+}
+
+static inline void update_state_dec(nexthop_state_t *state) {
+ if (state->pi > 0) state->pi--;
+ update_state(state);
+}
+
+static inline void reset_all(nexthops_t *nexthops) {
+ unsigned i;
+ nexthop_t nexthop;
+ nexthops_enumerate(nexthops, i, nexthop, {
+ (void)nexthop;
+ nexthops->state[i].load_balancer = NEXTHOP_STATE_INIT;
+ });
+}
+
+static int strategy_load_balancer_initialize(strategy_entry_t *entry,
+ const void *forwarder) {
+ /* No reset, this will be done when a nexthop is added */
+ entry->forwarder = forwarder;
+ return 0;
+}
+
+static int strategy_load_balancer_finalize(strategy_entry_t *entry) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_load_balancer_add_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ /* We reset the state of all nexthops */
+ reset_all(nexthops);
+ return 0;
+}
+
+static int strategy_load_balancer_remove_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ reset_all(nexthops);
+ return 0;
+}
+
+static nexthops_t *strategy_load_balancer_lookup_nexthops(
+ strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) {
+ /* Compute the sum of weights of potential next hops */
+ double sum = 0;
+ unsigned i, nexthop;
+ nexthops_enumerate(nexthops, i, nexthop, {
+ (void)nexthop;
+ sum += nexthops_state(nexthops, i).load_balancer.weight;
+ });
+
+ /* Perform weighted random selection */
+ double distance = (double)rand() * sum / ((double)RAND_MAX + 1);
+
+ nexthops_enumerate(nexthops, i, nexthop, {
+ distance -= nexthop_state(nexthops, i)->weight;
+ if (distance < 0) {
+ nexthops_select(nexthops, i);
+ update_state_inc(nexthop_state(nexthops, i));
+ break;
+ }
+ });
+ return nexthops;
+}
+
+static int strategy_load_balancer_on_timeout(
+ strategy_entry_t *entry, nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops) {
+ /*
+ * As we have few nexthops in FIB entry, and even fewer selected ones in
+ * nexthops, we can allow for linear search that will be very efficient
+ * CPU-wise.
+ */
+ nexthop_t timeout_nexthop;
+ nexthops_foreach(timeout_nexthops, timeout_nexthop, {
+ nexthop_t nexthop;
+ unsigned i;
+ nexthops_enumerate(nexthops, i, nexthop, {
+ if (nexthop == timeout_nexthop)
+ update_state_dec(nexthop_state(nexthops, i));
+ });
+ });
+ return 0;
+}
+
+static int strategy_load_balancer_on_data(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *data_nexthops,
+ const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation,
+ Ticks objReception) {
+ return strategy_load_balancer_on_timeout(entry, nexthops, data_nexthops);
+}
+
+#undef nexthop_state_t
+
+DECLARE_STRATEGY(load_balancer);
+
+#undef nexthop_state_t
diff --git a/hicn-light/src/hicn/config/controlUpdate.h b/hicn-light/src/hicn/strategies/load_balancer.h
index 0007ab653..f7447d928 100644
--- a/hicn-light/src/hicn/config/controlUpdate.h
+++ b/hicn-light/src/hicn/strategies/load_balancer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,22 +14,24 @@
*/
/**
- * @file control_Update.h
- * @brief Root node for the "update" commands
- *
- * Implements the "update" node of the CLI tree.
- *
+ * Forward on the less loaded path
*/
-#ifndef controlUpdate_h
-#define controlUpdate_h
+#ifndef HICNLIGHT_STRATEGY_LOAD_BALANCER_H
+#define HICNLIGHT_STRATEGY_LOAD_BALANCER_H
-#ifdef WITH_POLICY
+typedef struct {
+ unsigned int pi;
+ double avg_pi;
+ double weight;
+} strategy_load_balancer_nexthop_state_t;
-#include <hicn/config/controlState.h>
-CommandOps *controlUpdate_Create(ControlState *state);
-CommandOps *controlUpdate_HelpCreate(ControlState *state);
+typedef struct {
+ void *_;
+} strategy_load_balancer_state_t;
-#endif /* WITH_POLICY */
+typedef struct {
+ void *_;
+} strategy_load_balancer_options_t;
-#endif // controlUpdate_h
+#endif /* HICNLIGHT_STRATEGY_LOAD_BALANCER_H */
diff --git a/hicn-light/src/hicn/strategies/local_prefixes.c b/hicn-light/src/hicn/strategies/local_prefixes.c
new file mode 100644
index 000000000..23d72ae80
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/local_prefixes.c
@@ -0,0 +1,81 @@
+/*
+ * 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 "local_prefixes.h"
+#include <hicn/core/forwarder.h>
+#include <hicn/core/nexthops.h>
+#include <hicn/core/name.h>
+#include <hicn/core/mapme.h>
+
+#define MAX_PREFIXES 10
+
+struct local_prefixes_s {
+ Name local_prefixes[MAX_PREFIXES];
+ unsigned len;
+};
+
+local_prefixes_t *create_local_prefixes() {
+ local_prefixes_t *lp = calloc(1, sizeof(local_prefixes_t));
+ if (!lp) return NULL;
+ return lp;
+}
+
+void free_local_prefixes(local_prefixes_t *lp) { free(lp); }
+
+unsigned local_prefixes_get_len(local_prefixes_t *prefixes) {
+ return prefixes->len;
+}
+
+bool contain_prefix(local_prefixes_t *prefixes, Name *name) {
+ for (unsigned i = 0; i < prefixes->len; i++) {
+ if (name_Equals(&(prefixes->local_prefixes[i]), name)) return true;
+ }
+ return false;
+}
+
+void local_prefixes_add_prefixes(local_prefixes_t *prefixes,
+ local_prefixes_t *new_prefixes) {
+ // if there is not enough space for the new prefixes they are not added
+ unsigned i = 0;
+ while ((i < new_prefixes->len) && (prefixes->len < MAX_PREFIXES)) {
+ if (!contain_prefix(prefixes, &(new_prefixes->local_prefixes[i]))) {
+ name_Copy(&new_prefixes->local_prefixes[i],
+ &prefixes->local_prefixes[prefixes->len]);
+ prefixes->len++;
+ }
+ i++;
+ }
+}
+
+void local_prefixes_add_prefix(local_prefixes_t *prefixes, const void *prefix) {
+ if (prefixes->len >= MAX_PREFIXES) return;
+ Name *n = (Name *)prefix;
+ if (!contain_prefix(prefixes, n)) {
+ name_Copy(n, &(prefixes->local_prefixes[prefixes->len]));
+ prefixes->len++;
+ }
+}
+
+void update_remote_node_paths(const void *nexthops, const void *forwarder,
+ local_prefixes_t *prefixes) {
+ if (!prefixes) return;
+ struct mapme_s *mapme = forwarder_get_mapme((forwarder_t *)forwarder);
+ fib_t *fib = forwarder_get_fib((forwarder_t *)forwarder);
+ for (unsigned i = 0; i < prefixes->len; i++) {
+ fib_entry_t *entry = fib_match_name(fib, &prefixes->local_prefixes[i]);
+ if (!entry) continue;
+ mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops, false);
+ }
+}
diff --git a/hicn-light/src/hicn/strategies/local_prefixes.h b/hicn-light/src/hicn/strategies/local_prefixes.h
new file mode 100644
index 000000000..833a48057
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/local_prefixes.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * struct used to store prefixes that are served locally.
+ * these prefixes are used in mapme messages to tell to the server which
+ * path to use to retrive the content produced locally.
+ * using this strategy the path selection done by the client can be
+ * replicated at the server
+ */
+
+#ifndef HICNLIGHT_LOCAL_PREFIXES_H
+#define HICNLIGHT_LOCAL_PREFIXES_H
+
+typedef struct local_prefixes_s local_prefixes_t;
+
+local_prefixes_t* create_local_prefixes();
+
+void free_local_prefixes(local_prefixes_t* lp);
+
+unsigned local_prefixes_get_len(local_prefixes_t* prefixes);
+
+void local_prefixes_add_prefixes(local_prefixes_t* prefixes,
+ local_prefixes_t* new_prefixes);
+
+void local_prefixes_add_prefix(local_prefixes_t* prefixes, const void* prefix);
+
+void update_remote_node_paths(const void* nexthops, const void* forwarder,
+ local_prefixes_t* prefixes);
+
+#endif /* HICNLIGHT_LOCAL_PREFIXES */
diff --git a/hicn-light/src/hicn/strategies/lowLatency.c b/hicn-light/src/hicn/strategies/lowLatency.c
deleted file mode 100644
index 61bffe243..000000000
--- a/hicn-light/src/hicn/strategies/lowLatency.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <math.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_Unsigned.h>
-
-#include <hicn/core/messageHandler.h>
-
-#include <hicn/strategies/lowLatency.h>
-#include <hicn/strategies/nexthopStateLowLatency.h>
-
-const unsigned STABILITY_FACTOR = 15;
-const unsigned MAX_SWITCH_TRY = 10;
-const unsigned MAX_LATENCY_DIFF = 10;
-const unsigned MAX_TOLLERATED_LATENCY_DIFF = 15;
-const unsigned MAX_ROUNDS_MP_WITHOUT_CHECK = 2;
-const unsigned MAX_ROUNDS_AVOIDING_MULTIPATH = 40; //about 20 sec
-const unsigned MAX_ROUNDS_WITH_ERROR = 4;
-const unsigned PROBE_LIFETIME = 500; //ms
-
-static void _strategyLowLatency_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-static void _strategyLowLatency_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId);
-static NumberSet *_strategyLowLatency_LookupNexthop(
- StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
-static NumberSet *_strategyLowLatency_ReturnNexthops(StrategyImpl *strategy);
-static unsigned _strategyLowLatency_CountNexthops(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
-static void _strategyLowLatency_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLowLatency_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLowLatency_ImplDestroy(StrategyImpl **strategyPtr);
-static strategy_type _strategyLowLatency_GetStrategy(StrategyImpl *strategy);
-
-static StrategyImpl _template = {
- .context = NULL,
- .receiveObject = &_strategyLowLatency_ReceiveObject,
- .onTimeout = &_strategyLowLatency_OnTimeout,
- .lookupNexthop = &_strategyLowLatency_LookupNexthop,
-#ifndef WITH_POLICY
- .returnNexthops = &_strategyLowLatency_ReturnNexthops,
- .countNexthops = &_strategyLowLatency_CountNexthops,
-#endif /* ! WITH_POLICY */
- .addNexthop = &_strategyLowLatency_AddNexthop,
- .removeNexthop = &_strategyLowLatency_RemoveNexthop,
- .destroy = &_strategyLowLatency_ImplDestroy,
- .getStrategy = &_strategyLowLatency_GetStrategy,
-};
-
-struct strategy_low_latency;
-typedef struct strategy_low_latency StrategyLowLatency;
-
-struct strategy_low_latency {
- // hash map from connectionId to StrategyNexthopStateLL
- PARCHashMap *strategy_state;
- //hash map from sequence number to ticks (sent time)
- PARCHashMap *pending_probes_ticks;
- //hash map from sequence number to face id
- PARCHashMap *pending_probes_faces;
- const Forwarder * forwarder;
- PARCEventTimer *sendProbes;
- PARCEventTimer *computeBestFace;
- uint8_t * probe;
- hicn_name_t * name;
- StrategyNexthopStateLL * bestFaces[2];
- unsigned round;
- unsigned rounds_in_multipath;
- unsigned rounds_with_error;
- unsigned rounds_avoiding_multipath;
- bool use2paths;
- bool avoid_multipath;
- unsigned related_prefixes_len;
- Name **related_prefixes;
-#ifndef WITH_POLICY
- NumberSet *nexthops;
-#endif /* ! WITH_POLICY */
-};
-
-static void strategyLowLatency_SendProbesCB(int fd, PARCEventType which_event,
- void *data){
- parcAssertTrue(which_event & PARCEventType_Timeout,
- "Event incorrect, expecting %X set, got %X",
- PARCEventType_Timeout, which_event);
-
- StrategyLowLatency *ll = (StrategyLowLatency *) data;
-
- //delete old pending probes
- if(parcHashMap_Size(ll->pending_probes_ticks) != 0){
- Ticks now = forwarder_GetTicks(ll->forwarder);
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->pending_probes_ticks);
- NumberSet *to_remove = numberSet_Create();
- while(parcIterator_HasNext(iterator)) {
- PARCUnsigned *parc_seq = (PARCUnsigned *) parcIterator_Next(iterator);
- PARCUnsigned *parc_time = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_ticks, parc_seq);
- Ticks sent_time = parcUnsigned_GetUnsigned(parc_time);
- if((now - sent_time) > PROBE_LIFETIME){
- //probes to delete
- numberSet_Add(to_remove, parcUnsigned_GetUnsigned(parc_seq));
- }
- }
- parcIterator_Release(&iterator);
-
- for(int i = 0; i < numberSet_Length(to_remove); i++){
- PARCUnsigned *prob_seq = parcUnsigned_Create(numberSet_GetItem(to_remove,i));
- PARCUnsigned *cid = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_faces, prob_seq);
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
- strategyNexthopStateLL_LostProbe(state);
- parcHashMap_Remove(ll->pending_probes_ticks, prob_seq);
- parcHashMap_Remove(ll->pending_probes_faces, prob_seq);
- parcUnsigned_Release(&prob_seq);
- }
- numberSet_Release(&to_remove);
- }
-
- ConnectionTable * ct = forwarder_GetConnectionTable(ll->forwarder);
-
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while(parcIterator_HasNext(iterator)){
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- Connection *conn =
- (Connection *)connectionTable_FindById(ct,
- parcUnsigned_GetUnsigned(cid));
- if(!conn)
- continue;
-
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
-
- //probe only usable paths
- if(!strategyNexthopStateLL_IsAllowed(state))
- continue;
-
- uint32_t seq = rand();
- messageHandler_SetProbeName(ll->probe, HF_INET6_TCP,
- ll->name, seq);
- connection_Probe(conn, ll->probe);
-
- PARCUnsigned *parc_seq = parcUnsigned_Create(seq);
- Ticks now = forwarder_GetTicks(ll->forwarder);
- PARCUnsigned *parc_time = parcUnsigned_Create((unsigned int)now);
- parcHashMap_Put(ll->pending_probes_ticks, parc_seq, parc_time);
- parcHashMap_Put(ll->pending_probes_faces, parc_seq, cid);
- strategyNexthopStateLL_SentProbe(state);
- parcUnsigned_Release(&parc_seq);
- parcUnsigned_Release(&parc_time);
- }
- parcIterator_Release(&iterator);
-
- struct timeval timeout = {0,50000};
- parcEventTimer_Start(ll->sendProbes, &timeout);
-}
-
-static void strategyLowLatency_SendMapmeUpdate(StrategyLowLatency *ll,
- const NumberSet * nexthops){
- MapMe * mapme = forwarder_getMapmeInstance(ll->forwarder);
- FIB * fib = forwarder_getFib((Forwarder*) ll->forwarder);
- if(fib != NULL){
- for(unsigned i = 0; i < ll->related_prefixes_len; i++){
- FibEntry *fibEntry = fib_MatchName(fib, ll->related_prefixes[i]);
- if(fibEntry != NULL){
- mapme_maybe_send_updates(mapme, fibEntry, nexthops);
- }
- }
- }
-}
-
-static void strategyLowLatency_SelectBestFaces(StrategyLowLatency *ll,
- bool new_round){
-
- StrategyNexthopStateLL * old_faces[2];
- old_faces[0] = ll->bestFaces[0];
- old_faces[1] = ll->bestFaces[1];
-
- if(new_round){
- ll->round++;
- }
-
- if(parcHashMap_Size(ll->strategy_state) == 0){
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- if(ll->use2paths && ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL){
- //multipath case
-
- if(!strategyNexthopStateLL_IsLossy(ll->bestFaces[0])
- && !strategyNexthopStateLL_IsLossy(ll->bestFaces[1])
- && strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])
- && strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
-
- if(ll->rounds_in_multipath < MAX_ROUNDS_MP_WITHOUT_CHECK){
- //we are at the first rounds of the multipath let's wait a bit
- //(MAX_ROUNDS_MP_WITHOUT_CHECK) to make the queuing converge
- ll->rounds_in_multipath++;
- goto NEW_ROUND;
- }
-
- //we need to decide if we want ot keep using two paths or not
- ll->rounds_in_multipath++;
- double rtt0 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
- double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
- double diff = fabs(rtt0 - rtt1);
-
- if(diff < MAX_LATENCY_DIFF){
- //everything is working, keep using the two paths
- ll->rounds_with_error = 0;
- goto NEW_ROUND;
- }
-
- //check for how many rounds we had problems
- if(ll->rounds_with_error < MAX_ROUNDS_WITH_ERROR &&
- diff < MAX_TOLLERATED_LATENCY_DIFF){
- //we can tollerate few round with errors
- ll->rounds_with_error++;
- goto NEW_ROUND;
- }
-
- //prevent the usage of multiple paths
- ll->rounds_with_error = 0;
- ll->avoid_multipath = true;
- ll->rounds_avoiding_multipath = 0;
- } //else
- //at least one of the two path is lossy
- //or it is not allowed by the policies.
- //search for a better possibility
- }
-
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
-
- //check if there is at least one non lossy connection
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- bool check_losses = true;
- bool found_good_face = false;
- while(parcIterator_HasNext(iterator) && !found_good_face){
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- const StrategyNexthopStateLL *state = parcHashMap_Get(ll->strategy_state, cid);
- if(!strategyNexthopStateLL_IsLossy(state) &&
- strategyNexthopStateLL_IsAllowed(state)){
- found_good_face = true;
- }
- }
- parcIterator_Release(&iterator);
- if(!found_good_face){
- // all the available faces are lossy, so we take into account only
- // the latency computed with the probes
- check_losses = false;
- }
-
- if(ll->bestFaces[0] == NULL){
- //try to take a random face
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- bool face_found = false;
- while(parcIterator_HasNext(iterator) && !face_found) {
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid);
-
- if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
- !strategyNexthopStateLL_IsAllowed(state)){
- //skip the face
- continue;
- }
-
- ll->bestFaces[0] = state;
- face_found = true;
- }
- parcIterator_Release(&iterator);
- }
-
- if(ll->bestFaces[0] == NULL){
- //no usable face exists
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- double bestRtt = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
-
- if(ll->avoid_multipath)
- ll->rounds_avoiding_multipath++;
-
- if(ll->rounds_avoiding_multipath > MAX_ROUNDS_AVOIDING_MULTIPATH){
- ll->avoid_multipath = false;
- ll->rounds_avoiding_multipath = 0;
- }
-
- iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while (parcIterator_HasNext(iterator)) {
-
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid);
- double rtt = strategyNexthopStateLL_GetRTTLive(state);
-
- if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
- !strategyNexthopStateLL_IsAllowed(state)){
- //skip the face
- continue;
- }
-
- if(rtt + STABILITY_FACTOR < bestRtt){
- //maybe we found a better face
- double rttInUse = strategyNexthopStateLL_GetRTTInUse(state);
- unsigned try = strategyNexthopStateLL_GetTryToSwitch(state);
-
- //we check the rtt in use to check if the new face that we found
- //gets congested when we use it to send the traffic
- if(rttInUse < bestRtt || try > MAX_SWITCH_TRY){
- //we have a new best face!
- strategyNexthopStateLL_ResetTryToSwitch((StrategyNexthopStateLL*) state);
- bestRtt = rtt;
- if(ll->bestFaces[0] != NULL)
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[0]);
- ll->bestFaces[0] = (StrategyNexthopStateLL*) state;
- }else{
- //in this case we should switch but we wait MAX_SWITCH_TRY
- //before switch to avoid ossillations between different paths
- strategyNexthopStateLL_IncreaseTryToSwitch(
- (StrategyNexthopStateLL*) state, ll->round);
- }
- }
- }
-
- parcIterator_Release(&iterator);
-
- if(ll->bestFaces[0] == NULL){
- //we found no face so return
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- if(parcHashMap_Size(ll->strategy_state) == 1 || ll->avoid_multipath){
- //in this case (one face available or avoid multipath) we stop the
- //search here. Just reset face 1 if needed
- if(ll->bestFaces[1] != NULL){
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
- ll->bestFaces[1] = NULL;
- }
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- //if we are here we have more than 1 interface, so we search for a second one
- //to use in case of multipath
- iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while (parcIterator_HasNext(iterator)) {
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- if(parcUnsigned_GetUnsigned(cid) !=
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])){
-
- StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid);
-
- if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
- !strategyNexthopStateLL_IsAllowed(state)){
- //skip the face
- continue;
- }
-
- if(ll->bestFaces[1] == NULL){
- //in case of 2 faces we should pass always here
- ll->bestFaces[1] = state;
- }else{
- //TODO this must be tested with more then 2 faces
- double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
- double rttNewFace = strategyNexthopStateLL_GetRTTLive(state);
- if(rttNewFace + STABILITY_FACTOR < rtt1){
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
- ll->bestFaces[1] = state;
- }
- }
- }
- }
- parcIterator_Release(&iterator);
-
- if(ll->bestFaces[1] != NULL){
- //we are not using the second face yet so we use the normal rtt for comparison
- double rtt0 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[0]);
- double rtt1 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[1]);
- double diff = fabs(rtt0 - rtt1);
- if(diff < MAX_LATENCY_DIFF) {
- //let's start to use 2 paths
- ll->rounds_with_error = 0;
- ll->use2paths = true;
- ll->rounds_in_multipath = 0;
- }else{
- //we use only one path
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- }
- }else{
- ll->use2paths = false;
- }
-
- NEW_ROUND:
- {
- Logger * log = forwarder_GetLogger(ll->forwarder);
- if(log != NULL &&
- logger_IsLoggable(log, LoggerFacility_Strategy, PARCLogLevel_Info)){
- if(ll->use2paths){
- logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
- __func__, "use 2 paths. rtt face %d = %f queue = %f is_lossy = %d,"
- "rtt face %d = %f queue = %f is_lossy = %d\n",
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
- strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
- strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]),
- strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]),
- strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]),
- strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]),
- strategyNexthopStateLL_IsLossy(ll->bestFaces[1]));
- }else{
- if(ll->bestFaces[0] != NULL){
- logger_Log(log, LoggerFacility_Strategy,
- PARCLogLevel_Info, __func__,
- "use 1 path. rtt face %d = %f is_lossy = %d, "
- "(avoid multipath = %d)\n",
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
- strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
- strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
- ll->avoid_multipath);
- }else{
- logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
- __func__, "no face to use!\n");
- }
- }
- }
- }
-
- //update the round only at the end for all the faces
- if(new_round){
- PARCIterator * iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while (parcIterator_HasNext(iterator)) {
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- strategyNexthopStateLL_StartNewRound((StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid));
- }
- parcIterator_Release(&iterator);
- }
-
- //mapme updates
- //if ll->bestFaces[0] == NULL we don't have any output faces
- //so don't need to send any updates since we are disconnected
- if(ll->related_prefixes_len != 0){
- if(ll->bestFaces[0] != NULL){
- NumberSet *out = numberSet_Create();
- if(old_faces[0] == NULL ||
- (strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) !=
- strategyNexthopStateLL_GetFaceId(old_faces[0]))){
- //there is a new face 0 so we need a map me update
- //if ll->bestFaces[1] != NULL we need to send the update
- //even if it is the same as before
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- if(ll->bestFaces[1] != NULL){
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
- }
- strategyLowLatency_SendMapmeUpdate(ll,out);
- }else{
- if(ll->bestFaces[1] != NULL){
- if(old_faces[1] == NULL ||
- (strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) !=
- strategyNexthopStateLL_GetFaceId(old_faces[1]))){
- //send a mapme both with face 0 and face 1
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
- strategyLowLatency_SendMapmeUpdate(ll,out);
- }
- }else{
- if(old_faces[1] != NULL){
- //in the previuos round we were using two faces, now only one
- //send update with only face 0
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- strategyLowLatency_SendMapmeUpdate(ll,out);
- }
- }
- }
- numberSet_Release(&out);
- }
- }
-}
-
-static void strategyLowLatency_BestFaceCB(int fd, PARCEventType which_event,
- void *data){
- parcAssertTrue(which_event & PARCEventType_Timeout,
- "Event incorrect, expecting %X set, got %X",
- PARCEventType_Timeout, which_event);
-
- StrategyLowLatency * ll = (StrategyLowLatency *) data;
- strategyLowLatency_SelectBestFaces(ll, true);
-
- struct timeval timeout = {0, 500000};
- parcEventTimer_Start(ll->computeBestFace, &timeout);
-}
-
-StrategyImpl *strategyLowLatency_Create() {
- StrategyLowLatency *strategy =
- parcMemory_AllocateAndClear(sizeof(StrategyLowLatency));
- parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyLowLatency));
-
- strategy->strategy_state = parcHashMap_Create();
- strategy->pending_probes_ticks = parcHashMap_Create();
- strategy->pending_probes_faces = parcHashMap_Create();
-#ifndef WITH_POLICY
- strategy->nexthops = numberSet_Create();
-#endif /* ! WITH_POLICY */
- srand((unsigned int)time(NULL));
-
- StrategyImpl *impl = parcMemory_AllocateAndClear(sizeof(StrategyImpl));
- parcAssertNotNull(impl, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyImpl));
- memcpy(impl, &_template, sizeof(StrategyImpl));
- impl->context = strategy;
-
- return impl;
-}
-
-void strategyLowLatency_SetStrategy(StrategyImpl *strategy,
- const Forwarder * forwarder,
- const FibEntry * fibEntry,
- unsigned related_prefixes_len,
- Name **related_prefixes) {
- StrategyLowLatency *ll =
- (StrategyLowLatency *)strategy->context;
- ll->forwarder = forwarder;
-
- //create probe packet
- ll->probe = messageHandler_CreateProbePacket(HF_INET6_TCP, PROBE_LIFETIME);
- ip_prefix_t address;
- nameBitvector_ToIPAddress(name_GetContentName(
- fibEntry_GetPrefix(fibEntry)), &address);
- ll->name = messageHandler_CreateProbeName(&address);
-
-
- Dispatcher *dispatcher = forwarder_GetDispatcher((Forwarder *)ll->forwarder);
- ll->sendProbes = dispatcher_CreateTimer(dispatcher, false,
- strategyLowLatency_SendProbesCB, ll);
-
- ll->round = 0;
- ll->rounds_in_multipath = 0;
- ll->rounds_with_error = 0;
- ll->rounds_avoiding_multipath = 0;
- ll->use2paths = false;
- ll->avoid_multipath = false;
-
- ll->related_prefixes_len = related_prefixes_len;
- ll->related_prefixes = malloc(sizeof(Name *) * ll->related_prefixes_len);
- for(unsigned i = 0; i < ll->related_prefixes_len; i++){
- ll->related_prefixes[i] = name_Copy(related_prefixes[i]);
- }
-
- ll->computeBestFace = dispatcher_CreateTimer(dispatcher, false,
- strategyLowLatency_BestFaceCB, ll);
-}
-
-void _startTimers(StrategyImpl *strategy){
- StrategyLowLatency *ll =
- (StrategyLowLatency *)strategy->context;
-
- struct timeval timeoutProbes = {0,10000};
- parcEventTimer_Start(ll->sendProbes, &timeoutProbes);
- struct timeval timeoutBF = {1,0};
- parcEventTimer_Start(ll->computeBestFace, &timeoutBF);
-}
-
-void _stopTimers(StrategyImpl *strategy){
- StrategyLowLatency *ll =
- (StrategyLowLatency *)strategy->context;
-
- parcEventTimer_Stop(ll->sendProbes);
- parcEventTimer_Stop(ll->computeBestFace);
-}
-
-// =======================================================
-// Dispatch API
-
-strategy_type _strategyLowLatency_GetStrategy(StrategyImpl *strategy) {
- return SET_STRATEGY_LOW_LATENCY;
-}
-
-static void _strategyLowLatency_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- if(!messageHandler_IsAProbe(message_FixedHeader(objectMessage)))
- return;
-
- uint32_t seq = messageHandler_GetSegment(message_FixedHeader(objectMessage));
- PARCUnsigned *parc_seq = parcUnsigned_Create(seq);
- if (!parcHashMap_Contains(ll->pending_probes_ticks, parc_seq)){
- parcUnsigned_Release(&parc_seq);
- return;
- }
-
- //here numberSet_Length(egressId) should be 1
- for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
- unsigned outId = numberSet_GetItem(egressId, i);
- PARCUnsigned *cid = parcUnsigned_Create(outId);
-
- const StrategyNexthopStateLL *state =
- parcHashMap_Get(ll->strategy_state, cid);
- if (state != NULL) {
- Ticks time = parcUnsigned_GetUnsigned(
- parcHashMap_Get(ll->pending_probes_ticks, parc_seq));
- Ticks now = forwarder_GetTicks(ll->forwarder);
- Ticks RTT = now - time;
- if(RTT <= 0)
- RTT = 1;
- strategyNexthopStateLL_AddRttSample(
- (StrategyNexthopStateLL *) state, (unsigned int)RTT);
- parcHashMap_Remove(ll->pending_probes_ticks, parc_seq);
- } else {
- // this may happen if we remove a face/route while downloading a file
- // we should ignore this timeout
- }
- parcUnsigned_Release(&cid);
- }
- parcUnsigned_Release(&parc_seq);
-}
-
-static void _strategyLowLatency_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId) {}
-
-static NumberSet *_strategyLowLatency_LookupNexthop(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage) {
- //unsigned out_connection;
- NumberSet *out = numberSet_Create();
-
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- //update is_allowed flag of all the next hops
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while(parcIterator_HasNext(iterator)){
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
- if(numberSet_Contains(nexthops, parcUnsigned_GetUnsigned(cid))){
- strategyNexthopStateLL_SetIsAllowed(state,true);
- }else{
- strategyNexthopStateLL_SetIsAllowed(state,false);
- }
- }
- parcIterator_Release(&iterator);
-
- if(ll->bestFaces[0] != NULL &&
- !strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])){
- //if ll->bestFaces[0] is not allowed we need to find a new face
- strategyLowLatency_SelectBestFaces(ll, false);
- }
-
- //at this point ll->bestFaces[0] must be allowed
- //single path case
- if(ll->bestFaces[0] != NULL && (ll->bestFaces[1] == NULL || !ll->use2paths)){
- strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
-
- //multipath case
- }else if(ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL && ll->use2paths){
- //it may happen that ll->bestFaces[1] is not allowed, in that case we send on
- //ll->bestFaces[0] until the next best face selection
- if(!strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
- strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- }else{
- double queue0 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]);
- double queue1 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]);
- double prob0 = 0.5;
- if(queue0 > 1 || queue1 > 1){
- prob0 = 1.0 - (queue0 / (queue0 + queue1));
- }
- double coin = ((double) rand() / (RAND_MAX));
- if(coin < prob0){
- strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- }else{
- strategyNexthopStateLL_SendPacket(ll->bestFaces[1]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
- }
- }
- }
- return out;
-}
-
-
-#ifndef WITH_POLICY
-static NumberSet *_strategyLowLatency_ReturnNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancerLL *ll = (StrategyLoadBalancerLL *)strategy->context;
- return ll->nexthops;
-}
-
-unsigned _strategyLowLatency_CountNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancerLL *ll = (StrategyLoadBalancerLL *)strategy->context;
- return (unsigned)numberSet_Length(ll->nexthops);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyLowLatency_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- if (!parcHashMap_Contains(ll->strategy_state, cid)) {
- StrategyNexthopStateLL *state = strategyNexthopStateLL_Create(connectionId);
- parcHashMap_Put(ll->strategy_state, cid, state);
- if(ll->bestFaces[0] == NULL){
- ll->bestFaces[0] = state;
- }
-#ifndef WITH_POLICY
- numberSet_Add(ll->nexthops, connectionId);
-#endif /* WITH_POLICY */
- }
-
- if(parcHashMap_Size(ll->strategy_state) >= 2){
- _startTimers(strategy);
- }
-
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLowLatency_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- bool reset_bestFaces = false;
-
- if((ll->bestFaces[0] != NULL &&
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) == connectionId) ||
- (ll->bestFaces[1] != NULL &&
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) == connectionId)){
- reset_bestFaces = true;
- }
-
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- if (parcHashMap_Contains(ll->strategy_state, cid)) {
- parcHashMap_Remove(ll->strategy_state, cid);
-#ifndef WITH_POLICY
- numberSet_Remove(lb->nexthops, connectionId);
-#endif /* WITH_POLICY */
- }
-
- if(reset_bestFaces){
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- strategyLowLatency_SelectBestFaces(ll, false);
- }
-
- if(parcHashMap_Size(ll->strategy_state) < 2){
- _stopTimers(strategy);
- }
-
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLowLatency_ImplDestroy(StrategyImpl **strategyPtr) {
- parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*strategyPtr,
- "Parameter must dereference to non-null pointer");
-
- StrategyImpl *impl = *strategyPtr;
- StrategyLowLatency *strategy = (StrategyLowLatency *)impl->context;
-
- _stopTimers(impl);
-
- parcEventTimer_Destroy(&(strategy->sendProbes));
- parcEventTimer_Destroy(&(strategy->computeBestFace));
-
- if (parcHashMap_Size(strategy->strategy_state) > 0) {
- PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *)parcHashMap_Get(strategy->strategy_state, cid);
- parcObject_Release((void**)&state);
- }
- parcIterator_Release(&it);
- }
-
- parcHashMap_Release(&(strategy->strategy_state));
- parcHashMap_Release(&(strategy->pending_probes_ticks));
- parcHashMap_Release(&(strategy->pending_probes_faces));
-
- parcMemory_Deallocate(&(strategy->probe));
- parcMemory_Deallocate(&(strategy->name));
-
- for(unsigned i = 0; i < strategy->related_prefixes_len; i++){
- name_Release(&(strategy->related_prefixes[i]));
- }
- free(strategy->related_prefixes);
-
-#ifndef WITH_POLICY
- numberSet_Release(&(strategy->nexthops));
-#endif /* ! WITH_POLICY */
-
- parcMemory_Deallocate((void **)&strategy);
- parcMemory_Deallocate((void **)&impl);
- *strategyPtr = NULL;
-}
diff --git a/hicn-light/src/hicn/strategies/lowLatency.h b/hicn-light/src/hicn/strategies/lowLatency.h
deleted file mode 100644
index 736c8783d..000000000
--- a/hicn-light/src/hicn/strategies/lowLatency.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Forward on the path with lowest latency
- */
-
-#ifndef lowLatency_h
-#define lowLatency_h
-
-#include <hicn/strategies/strategyImpl.h>
-#include <hicn/core/forwarder.h>
-
-StrategyImpl *strategyLowLatency_Create();
-
-void strategyLowLatency_SetStrategy(StrategyImpl *strategy,
- const Forwarder * forwarder,
- const FibEntry * fibEntry,
- unsigned related_prefixes_len,
- Name **related_prefixes);
-#endif // lowLatency_h
diff --git a/hicn-light/src/hicn/strategies/low_latency.c b/hicn-light/src/hicn/strategies/low_latency.c
new file mode 100644
index 000000000..1e5a74c1a
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/low_latency.c
@@ -0,0 +1,776 @@
+/*
+ * 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.
+ */
+
+#if 0
+
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+#include <hicn/base/khash.h>
+
+#include <parc/assert/parc_Assert.h>
+#include <parc/algol/parc_HashMap.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_Unsigned.h>
+
+#include <hicn/core/messageHandler.h>
+
+#include "low_latency.h"
+
+#define STABILITY_FACTOR 15
+#define MAX_SWITCH_TRY 10
+#define MAX_LATENCY_DIFF 10
+#define MAX_TOLLERATED_LATENCY_DIFF 15
+#define MAX_ROUNDS_MP_WITHOUT_CHECK 2
+#define MAX_ROUNDS_AVOIDING_MULTIPATH 40 /* about 20 sec */
+#define MAX_ROUNDS_WITH_ERROR 4
+#define PROBE_LIFETIME 500 /* ms */
+
+#define MAX_ROUNS_WITHOUT_PROBES 4
+
+/*
+ * If we do not receives probes for 4 rounds it means that we had no responce
+ * from any producer for 2 sec we can say that this interface is daed
+ */
+#define MIN_NON_LOSSY_ROUNDS 10
+
+/*
+ * Number of rounds in non lossy mode before switch to no lossy state
+ * Defaults to 10 %
+ */
+#define MAX_LOSS_RATE 0.10
+
+/* Shorthands */
+#define nexthop_state_t strategy_low_latency_nexthop_state_t
+#define state_t strategy_low_latency_state_t
+
+#define NEXTHOP_STATE_INIT \
+ { \
+ .in_use = false, .is_allowed = true, .sent_packets = 0, \
+ .last_try_to_switch_round = 0, .try_to_switch_counter = 0, \
+ .recevied_probes = 0, .rounds_without_probes = 0, .sent_probes = 0, \
+ .lost_probes = 0, .non_lossy_rounds = MIN_NON_LOSSY_ROUNDS, \
+ .avg_rtt = -1.0, .avg_rtt_in_use = -1.0, .avg_queue = 0.0001, \
+ .avg_loss_rate = 0.0, \
+ }
+
+// XXX ????
+#define STATE_INIT \
+ {}
+
+static
+ void
+strategy_low_latency_SendProbesCB(int fd, PARCEventType which_event, void *data)
+{
+ parcAssertTrue(which_event & PARCEventType_Timeout,
+ "Event incorrect, expecting %X set, got %X",
+ PARCEventType_Timeout, which_event);
+
+ StrategyLowLatency *ll = (StrategyLowLatency *) data;
+
+ //delete old pending probes
+ if(parcHashMap_Size(ll->pending_probes_ticks) != 0){
+ Ticks now = forwarder_GetTicks(ll->forwarder);
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->pending_probes_ticks);
+ NumberSet *to_remove = numberSet_Create();
+ while(parcIterator_HasNext(iterator)) {
+ PARCUnsigned *parc_seq = (PARCUnsigned *) parcIterator_Next(iterator);
+ PARCUnsigned *parc_time = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_ticks, parc_seq);
+ Ticks sent_time = parcUnsigned_GetUnsigned(parc_time);
+ if((now - sent_time) > PROBE_LIFETIME){
+ //probes to delete
+ numberSet_Add(to_remove, parcUnsigned_GetUnsigned(parc_seq));
+ }
+ }
+ parcIterator_Release(&iterator);
+
+ for(int i = 0; i < numberSet_Length(to_remove); i++){
+ PARCUnsigned *prob_seq = parcUnsigned_Create(numberSet_GetItem(to_remove,i));
+ PARCUnsigned *cid = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_faces, prob_seq);
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
+ strategyNexthopStateLL_LostProbe(state);
+ parcHashMap_Remove(ll->pending_probes_ticks, prob_seq);
+ parcHashMap_Remove(ll->pending_probes_faces, prob_seq);
+ parcUnsigned_Release(&prob_seq);
+ }
+ numberSet_Release(&to_remove);
+ }
+
+ ConnectionTable * ct = forwarder_GetConnectionTable(ll->forwarder);
+
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while(parcIterator_HasNext(iterator)){
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ Connection *conn =
+ (Connection *)connectionTable_FindById(ct,
+ parcUnsigned_GetUnsigned(cid));
+ if(!conn)
+ continue;
+
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
+
+ //probe only usable paths
+ if(!strategyNexthopStateLL_IsAllowed(state))
+ continue;
+
+ uint32_t seq = rand();
+ messageHandler_SetProbeName(ll->probe, HF_INET6_TCP,
+ ll->name, seq);
+ connection_Probe(conn, ll->probe);
+
+ PARCUnsigned *parc_seq = parcUnsigned_Create(seq);
+ Ticks now = forwarder_GetTicks(ll->forwarder);
+ PARCUnsigned *parc_time = parcUnsigned_Create((unsigned int)now);
+ parcHashMap_Put(ll->pending_probes_ticks, parc_seq, parc_time);
+ parcHashMap_Put(ll->pending_probes_faces, parc_seq, cid);
+ strategyNexthopStateLL_SentProbe(state);
+ parcUnsigned_Release(&parc_seq);
+ parcUnsigned_Release(&parc_time);
+ }
+ parcIterator_Release(&iterator);
+
+ struct timeval timeout = {0,50000};
+ parcEventTimer_Start(ll->sendProbes, &timeout);
+}
+
+static
+void
+strategy_low_latency_SendMapmeUpdate(StrategyLowLatency *ll,
+ const NumberSet * nexthops){
+ MapMe * mapme = forwarder_getMapmeInstance(ll->forwarder);
+ FIB * fib = forwarder_getFib((Forwarder*) ll->forwarder);
+ for(unsigned i = 0; i < ll->related_prefixes_len; i++){
+ FibEntry *fibEntry = fib_MatchName(fib, ll->related_prefixes[i]);
+ if (!fibEntry)
+ continue;
+ mapme_maybe_send_to_nexthops(mapme, fibEntry, nexthops);
+ }
+}
+
+static
+void
+strategy_low_latency_SelectBestFaces(StrategyLowLatency *ll, bool new_round)
+{
+
+ StrategyNexthopStateLL * old_faces[2];
+ old_faces[0] = ll->bestFaces[0];
+ old_faces[1] = ll->bestFaces[1];
+
+ if(new_round){
+ ll->round++;
+ }
+
+ if(parcHashMap_Size(ll->strategy_state) == 0){
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ if(ll->use2paths && ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL){
+ //multipath case
+
+ if(!strategyNexthopStateLL_IsLossy(ll->bestFaces[0])
+ && !strategyNexthopStateLL_IsLossy(ll->bestFaces[1])
+ && strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])
+ && strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
+
+ if(ll->rounds_in_multipath < MAX_ROUNDS_MP_WITHOUT_CHECK){
+ //we are at the first rounds of the multipath let's wait a bit
+ //(MAX_ROUNDS_MP_WITHOUT_CHECK) to make the queuing converge
+ ll->rounds_in_multipath++;
+ goto NEW_ROUND;
+ }
+
+ //we need to decide if we want ot keep using two paths or not
+ ll->rounds_in_multipath++;
+ double rtt0 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
+ double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
+ double diff = fabs(rtt0 - rtt1);
+
+ if(diff < MAX_LATENCY_DIFF){
+ //everything is working, keep using the two paths
+ ll->rounds_with_error = 0;
+ goto NEW_ROUND;
+ }
+
+ //check for how many rounds we had problems
+ if(ll->rounds_with_error < MAX_ROUNDS_WITH_ERROR &&
+ diff < MAX_TOLLERATED_LATENCY_DIFF){
+ //we can tollerate few round with errors
+ ll->rounds_with_error++;
+ goto NEW_ROUND;
+ }
+
+ //prevent the usage of multiple paths
+ ll->rounds_with_error = 0;
+ ll->avoid_multipath = true;
+ ll->rounds_avoiding_multipath = 0;
+ } //else
+ //at least one of the two path is lossy
+ //or it is not allowed by the policies.
+ //search for a better possibility
+ }
+
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+
+ //check if there is at least one non lossy connection
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ bool check_losses = true;
+ bool found_good_face = false;
+ while(parcIterator_HasNext(iterator) && !found_good_face){
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ const StrategyNexthopStateLL *state = parcHashMap_Get(ll->strategy_state, cid);
+ if(!strategyNexthopStateLL_IsLossy(state) &&
+ strategyNexthopStateLL_IsAllowed(state)){
+ found_good_face = true;
+ }
+ }
+ parcIterator_Release(&iterator);
+ if(!found_good_face){
+ // all the available faces are lossy, so we take into account only
+ // the latency computed with the probes
+ check_losses = false;
+ }
+
+ if(ll->bestFaces[0] == NULL){
+ //try to take a random face
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ bool face_found = false;
+ while(parcIterator_HasNext(iterator) && !face_found) {
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid);
+
+ if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
+ !strategyNexthopStateLL_IsAllowed(state)){
+ //skip the face
+ continue;
+ }
+
+ ll->bestFaces[0] = state;
+ face_found = true;
+ }
+ parcIterator_Release(&iterator);
+ }
+
+ if(ll->bestFaces[0] == NULL){
+ //no usable face exists
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ double bestRtt = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
+
+ if(ll->avoid_multipath)
+ ll->rounds_avoiding_multipath++;
+
+ if(ll->rounds_avoiding_multipath > MAX_ROUNDS_AVOIDING_MULTIPATH){
+ ll->avoid_multipath = false;
+ ll->rounds_avoiding_multipath = 0;
+ }
+
+ iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while (parcIterator_HasNext(iterator)) {
+
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid);
+ double rtt = strategyNexthopStateLL_GetRTTLive(state);
+
+ if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
+ !strategyNexthopStateLL_IsAllowed(state)){
+ //skip the face
+ continue;
+ }
+
+ if(rtt + STABILITY_FACTOR < bestRtt){
+ //maybe we found a better face
+ double rttInUse = strategyNexthopStateLL_GetRTTInUse(state);
+ unsigned try = strategyNexthopStateLL_GetTryToSwitch(state);
+
+ //we check the rtt in use to check if the new face that we found
+ //gets congested when we use it to send the traffic
+ if(rttInUse < bestRtt || try > MAX_SWITCH_TRY){
+ //we have a new best face!
+ strategyNexthopStateLL_ResetTryToSwitch((StrategyNexthopStateLL*) state);
+ bestRtt = rtt;
+ if(ll->bestFaces[0] != NULL)
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[0]);
+ ll->bestFaces[0] = (StrategyNexthopStateLL*) state;
+ }else{
+ //in this case we should switch but we wait MAX_SWITCH_TRY
+ //before switch to avoid ossillations between different paths
+ strategyNexthopStateLL_IncreaseTryToSwitch(
+ (StrategyNexthopStateLL*) state, ll->round);
+ }
+ }
+ }
+
+ parcIterator_Release(&iterator);
+
+ if(ll->bestFaces[0] == NULL){
+ //we found no face so return
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ if(parcHashMap_Size(ll->strategy_state) == 1 || ll->avoid_multipath){
+ //in this case (one face available or avoid multipath) we stop the
+ //search here. Just reset face 1 if needed
+ if(ll->bestFaces[1] != NULL){
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
+ ll->bestFaces[1] = NULL;
+ }
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ //if we are here we have more than 1 interface, so we search for a second one
+ //to use in case of multipath
+ iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while (parcIterator_HasNext(iterator)) {
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ if(parcUnsigned_GetUnsigned(cid) !=
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])){
+
+ StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid);
+
+ if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
+ !strategyNexthopStateLL_IsAllowed(state)){
+ //skip the face
+ continue;
+ }
+
+ if(ll->bestFaces[1] == NULL){
+ //in case of 2 faces we should pass always here
+ ll->bestFaces[1] = state;
+ }else{
+ //TODO this must be tested with more then 2 faces
+ double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
+ double rttNewFace = strategyNexthopStateLL_GetRTTLive(state);
+ if(rttNewFace + STABILITY_FACTOR < rtt1){
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
+ ll->bestFaces[1] = state;
+ }
+ }
+ }
+ }
+ parcIterator_Release(&iterator);
+
+ if(ll->bestFaces[1] != NULL){
+ //we are not using the second face yet so we use the normal rtt for comparison
+ double rtt0 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[0]);
+ double rtt1 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[1]);
+ double diff = fabs(rtt0 - rtt1);
+ if(diff < MAX_LATENCY_DIFF) {
+ //let's start to use 2 paths
+ ll->rounds_with_error = 0;
+ ll->use2paths = true;
+ ll->rounds_in_multipath = 0;
+ }else{
+ //we use only one path
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ }
+ }else{
+ ll->use2paths = false;
+ }
+
+NEW_ROUND:
+ {
+ Logger * log = forwarder_GetLogger(ll->forwarder);
+ if(log != NULL &&
+ logger_IsLoggable(log, LoggerFacility_Strategy, PARCLogLevel_Info)){
+ if(ll->use2paths){
+ logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
+ __func__, "use 2 paths. rtt face %d = %f queue = %f is_lossy = %d,"
+ "rtt face %d = %f queue = %f is_lossy = %d\n",
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]),
+ strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]),
+ strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]),
+ strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]),
+ strategyNexthopStateLL_IsLossy(ll->bestFaces[1]));
+ }else{
+ if(ll->bestFaces[0] != NULL){
+ logger_Log(log, LoggerFacility_Strategy,
+ PARCLogLevel_Info, __func__,
+ "use 1 path. rtt face %d = %f is_lossy = %d, "
+ "(avoid multipath = %d)\n",
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
+ strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
+ ll->avoid_multipath);
+ }else{
+ logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
+ __func__, "no face to use!\n");
+ }
+ }
+ }
+ }
+
+ //update the round only at the end for all the faces
+ if(new_round){
+ PARCIterator * iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while (parcIterator_HasNext(iterator)) {
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ strategyNexthopStateLL_StartNewRound((StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid));
+ }
+ parcIterator_Release(&iterator);
+ }
+
+ //mapme updates
+ //if ll->bestFaces[0] == NULL we don't have any output faces
+ //so don't need to send any updates since we are disconnected
+ if(ll->related_prefixes_len != 0){
+ if(ll->bestFaces[0] != NULL){
+ NumberSet *out = numberSet_Create();
+ if(old_faces[0] == NULL ||
+ (strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) !=
+ strategyNexthopStateLL_GetFaceId(old_faces[0]))){
+ //there is a new face 0 so we need a map me update
+ //if ll->bestFaces[1] != NULL we need to send the update
+ //even if it is the same as before
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ if(ll->bestFaces[1] != NULL){
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
+ }
+ strategy_low_latency_SendMapmeUpdate(ll,out);
+ }else{
+ if(ll->bestFaces[1] != NULL){
+ if(old_faces[1] == NULL ||
+ (strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) !=
+ strategyNexthopStateLL_GetFaceId(old_faces[1]))){
+ //send a mapme both with face 0 and face 1
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
+ strategy_low_latency_SendMapmeUpdate(ll,out);
+ }
+ }else{
+ if(old_faces[1] != NULL){
+ //in the previuos round we were using two faces, now only one
+ //send update with only face 0
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ strategy_low_latency_SendMapmeUpdate(ll,out);
+ }
+ }
+ }
+ numberSet_Release(&out);
+ }
+ }
+}
+
+static
+void
+strategy_low_latency_BestFaceCB(int fd, PARCEventType which_event, void *data)
+{
+ parcAssertTrue(which_event & PARCEventType_Timeout,
+ "Event incorrect, expecting %X set, got %X",
+ PARCEventType_Timeout, which_event);
+
+ StrategyLowLatency * ll = (StrategyLowLatency *) data;
+ strategy_low_latency_SelectBestFaces(ll, true);
+
+ struct timeval timeout = {0, 500000};
+ parcEventTimer_Start(ll->computeBestFace, &timeout);
+}
+
+static
+void
+_startTimers(strategy_entry_t * entry)
+{
+ struct timeval timeoutProbes = {0, 10000};
+ struct timeval timeoutBF = {1, 0};
+
+ parcEventTimer_Start(entry->state.sendProbes, &timeoutProbes);
+ parcEventTimer_Start(entry->state.computeBestFace, &timeoutBF);
+}
+
+static
+void
+_stopTimers(strategy_entry_t * entry)
+{
+ parcEventTimer_Stop(entry->state.sendProbes);
+ parcEventTimer_Stop(entry->state.computeBestFace);
+}
+
+static
+void
+strategy_low_latency_initialize(strategy_entry_t * entry)
+{
+ srand((unsigned int)time(NULL));
+
+ /* XXX TODO Three hashmaps to initialize */
+ strategy->strategy_state = parcHashMap_Create();
+ strategy->pending_probes_ticks = parcHashMap_Create();
+ strategy->pending_probes_faces = parcHashMap_Create();
+
+ Dispatcher *dispatcher = forwarder_GetDispatcher((Forwarder *)ll->forwarder);
+ ip_prefix_t address;
+ nameBitvector_ToIPAddress(name_GetContentName(
+ fibEntry_GetPrefix(fibEntry)), &address);
+
+ entry->state = {
+ .probe = messageHandler_CreateProbePacket(HF_INET6_TCP, PROBE_LIFETIME),
+ .name = messageHandler_CreateProbeName(&address);
+ .sendProbes = dispatcher_CreateTimer(dispatcher, false,
+ strategy_low_latency_SendProbesCB, ll);
+ .round = 0;
+ .rounds_in_multipath = 0;
+ .rounds_with_error = 0;
+ .rounds_avoiding_multipath = 0;
+ .use2paths = false;
+ .avoid_multipath = false;
+ .computeBestFace = dispatcher_CreateTimer(dispatcher, false,
+ strategy_low_latency_BestFaceCB, ll);
+ .related_prefixes_len = related_prefixes_len;
+ // XXX TODO
+ .related_prefixes = malloc(sizeof(Name *) * related_prefixes_len);
+ };
+
+ for(unsigned i = 0; i < entry->state.related_prefixes_len; i++){
+ entry->state.related_prefixes[i] = name_Copy(related_prefixes[i]);
+ }
+}
+
+static
+void
+strategy_low_latency_finalize(strategy_entry_t * entry)
+{
+ _stopTimers(entry);
+
+ parcEventTimer_Destroy(&(strategy->sendProbes));
+ parcEventTimer_Destroy(&(strategy->computeBestFace));
+
+ if (parcHashMap_Size(strategy->strategy_state) > 0) {
+ PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
+ while (parcIterator_HasNext(it)) {
+ PARCUnsigned *cid = parcIterator_Next(it);
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *)parcHashMap_Get(strategy->strategy_state, cid);
+ parcObject_Release((void**)&state);
+ }
+ parcIterator_Release(&it);
+ }
+
+ parcHashMap_Release(&(strategy->strategy_state));
+ parcHashMap_Release(&(strategy->pending_probes_ticks));
+ parcHashMap_Release(&(strategy->pending_probes_faces));
+
+ parcMemory_Deallocate(&(strategy->probe));
+ parcMemory_Deallocate(&(strategy->name));
+
+ for(unsigned i = 0; i < strategy->related_prefixes_len; i++){
+ name_Release(&(strategy->related_prefixes[i]));
+ }
+ free(strategy->related_prefixes);
+
+ parcMemory_Deallocate((void **)&strategy);
+ parcMemory_Deallocate((void **)&impl);
+ *strategyPtr = NULL;
+}
+
+static
+void
+strategy_low_latency_add_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state)
+{
+ PARCUnsigned *cid = parcUnsigned_Create(connectionId);
+
+ StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
+
+ if (!parcHashMap_Contains(ll->strategy_state, cid)) {
+ StrategyNexthopStateLL *state = strategyNexthopStateLL_Create(connectionId);
+ parcHashMap_Put(ll->strategy_state, cid, state);
+ if(ll->bestFaces[0] == NULL){
+ ll->bestFaces[0] = state;
+ }
+ }
+
+ if(parcHashMap_Size(ll->strategy_state) >= 2){
+ _startTimers(strategy);
+ }
+
+ parcUnsigned_Release(&cid);
+}
+
+static
+void
+strategy_low_latency_remove_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state)
+{
+ bool reset_bestFaces = false;
+
+ if((entry->state.bestFaces[0] != NULL &&
+ strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[0]) == connectionId) ||
+ (entry->state.bestFaces[1] != NULL &&
+ strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[1]) == connectionId)){
+ reset_bestFaces = true;
+ }
+
+ PARCUnsigned *cid = parcUnsigned_Create(connectionId);
+
+ if (parcHashMap_Contains(entry->state.strategy_state, cid)) {
+ parcHashMap_Remove(entry->state.strategy_state, cid);
+ }
+
+ if(reset_bestFaces){
+ entry->state.bestFaces[0] = NULL;
+ entry->state.bestFaces[1] = NULL;
+ strategy_low_latency_SelectBestFaces(ll, false);
+ }
+
+ if(parcHashMap_Size(entry->state.strategy_state) < 2){
+ _stopTimers(strategy);
+ }
+
+ parcUnsigned_Release(&cid);
+}
+
+static
+nexthops_t *
+strategy_low_latency_lookup_nexthops(strategy_entry_t * entry,
+ const msgbuf_t * msgbuf)
+{
+ //unsigned out_connection;
+ NumberSet *out = numberSet_Create();
+
+ StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
+
+ //update is_allowed flag of all the next hops
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while(parcIterator_HasNext(iterator)){
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
+ if(numberSet_Contains(nexthops, parcUnsigned_GetUnsigned(cid))){
+ strategyNexthopStateLL_SetIsAllowed(state,true);
+ }else{
+ strategyNexthopStateLL_SetIsAllowed(state,false);
+ }
+ }
+ parcIterator_Release(&iterator);
+
+ if(ll->bestFaces[0] != NULL &&
+ !strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])){
+ //if ll->bestFaces[0] is not allowed we need to find a new face
+ strategy_low_latency_SelectBestFaces(ll, false);
+ }
+
+ //at this point ll->bestFaces[0] must be allowed
+ //single path case
+ if(ll->bestFaces[0] != NULL && (ll->bestFaces[1] == NULL || !ll->use2paths)){
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+
+ //multipath case
+ }else if(ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL && ll->use2paths){
+ //it may happen that ll->bestFaces[1] is not allowed, in that case we send on
+ //ll->bestFaces[0] until the next best face selection
+ if(!strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ }else{
+ double queue0 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]);
+ double queue1 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]);
+ double prob0 = 0.5;
+ if(queue0 > 1 || queue1 > 1){
+ prob0 = 1.0 - (queue0 / (queue0 + queue1));
+ }
+ double coin = ((double) rand() / (RAND_MAX));
+ if(coin < prob0){
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ }else{
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[1]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
+ }
+ }
+ }
+ return out;
+}
+
+
+
+static
+void
+strategy_low_latency_on_data(strategy_entry_t * entry,
+ const nexthops_t * nexthops, const msgbuf_t * msgbuf,
+ Ticks pitEntryCreation, Ticks objReception)
+{
+ if (!msgbuf_is_probe(msgbuf))
+ return;
+
+ uint32_t seq = messageHandler_GetSegment(message_FixedHeader(objectMessage));
+ if (!parcHashMap_Contains(ll->pending_probes_ticks, seq))
+ return; // unexpected
+
+ /* A single nexthop is expected */
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ const StrategyNexthopStateLL *state =
+ parcHashMap_Get(ll->strategy_state, nexthop);
+ if (!state)
+ // this may happen if we remove a face/route while downloading a file
+ // we should ignore this timeout
+ continue;
+
+ Ticks time = parcUnsigned_GetUnsigned(
+ parcHashMap_Get(ll->pending_probes_ticks, seq));
+ Ticks now = forwarder_GetTicks(ll->forwarder);
+ Ticks RTT = now - time;
+ if(RTT <= 0)
+ RTT = 1;
+ strategyNexthopStateLL_AddRttSample(
+ (StrategyNexthopStateLL *) state, (unsigned int)RTT);
+ parcHashMap_Remove(ll->pending_probes_ticks, seq);
+ }
+ };
+}
+
+static
+void
+strategy_low_latency_on_timeout(strategy_entry_t * entry, const nexthops_t * nexthops)
+{
+ /* Nothing to do */
+}
+
+DECLARE_STRATEGY(low_latency);
+
+#undef nexthop_state_t
+#undef state_t
+
+#endif
diff --git a/hicn-light/src/hicn/strategies/low_latency.h b/hicn-light/src/hicn/strategies/low_latency.h
new file mode 100644
index 000000000..6b3001637
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/low_latency.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+/**
+ * Forward on the path with lowest latency
+ */
+
+#ifndef HICNLIGHT_STRATEGY_LOW_LATENCY_H
+#define HICNLIGHT_STRATEGY_LOW_LATENCY_H
+
+struct name_s;
+
+#include <hicn/strategy.h>
+
+typedef struct {
+ void *_;
+} strategy_low_latency_nexthop_state_t;
+
+typedef struct {
+ void *_;
+} strategy_low_latency_state_t;
+
+typedef struct {
+ // Name ** related_prefixes;
+ struct name_s *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ unsigned related_prefixes_len;
+} strategy_low_latency_options_t;
+
+#if 0
+
+/*
+ * We have global state in addition to state associated for each next hop :
+ */
+typedef struct {
+ bool in_use;
+ bool is_allowed; // XXX TODO the policy may not allow the use of this face
+// unsigned face_id;
+ unsigned sent_packets;
+ /* switch metrics */
+ unsigned last_try_to_switch_round;
+ unsigned try_to_switch_counter;
+ /* probes counters */
+ unsigned recevied_probes;
+ unsigned rounds_without_probes;
+ unsigned sent_probes;
+ unsigned lost_probes;
+ unsigned non_lossy_rounds;
+ /* Averages */
+ double avg_rtt;
+ double avg_rtt_in_use;
+ double avg_queue;
+ double avg_loss_rate;
+} strategy_low_latency_nexthop_state_t;
+
+typedef struct {
+ // hash map from connectionId to StrategyNexthopStateLL
+ //PARCHashMap *strategy_state;
+ // XXX This is now store in each nexthop state
+
+ /*
+ * Hhash map from sequence number to ticks (sent time)
+ *
+ * TODO improvement: the tick and face id could be stored in the probe and
+ * repeated in the reply to avoid state to be maintained.
+ *
+ * Also, in case we have few probes, linear scan might be more effective
+ */
+ PARCHashMap *pending_probes_ticks;
+
+ /* hash map from sequence number to face id */
+ PARCHashMap *pending_probes_faces;
+
+ const Forwarder * forwarder;
+ PARCEventTimer *sendProbes;
+ PARCEventTimer *computeBestFace;
+ uint8_t * probe;
+ hicn_name_t * name;
+ StrategyNexthopStateLL * bestFaces[2];
+ unsigned round;
+ unsigned rounds_in_multipath;
+ unsigned rounds_with_error;
+ unsigned rounds_avoiding_multipath;
+ bool use2paths;
+ bool avoid_multipath;
+} strategy_low_latency_state_t;
+
+#endif
+
+#endif /* HICNLIGHT_STRATEGY_LOW_LATENCY_H */
diff --git a/hicn-light/src/hicn/strategies/nexthopState.c b/hicn-light/src/hicn/strategies/nexthopState.c
deleted file mode 100644
index 40af14832..000000000
--- a/hicn-light/src/hicn/strategies/nexthopState.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_DisplayIndented.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/strategies/nexthopState.h>
-
-#define AVG_PI_THRESHOLD 1e-3
-
-struct strategy_nexthop_state {
- unsigned int pi;
- double avg_pi;
- double weight;
-};
-
-static bool _strategyNexthopState_Destructor(
- StrategyNexthopState **instancePtr) {
- return true;
-}
-
-parcObject_ImplementAcquire(strategyNexthopState, StrategyNexthopState);
-
-parcObject_ImplementRelease(strategyNexthopState, StrategyNexthopState);
-
-parcObject_Override(
- StrategyNexthopState, PARCObject,
- .destructor = (PARCObjectDestructor *)_strategyNexthopState_Destructor,
- .copy = (PARCObjectCopy *)strategyNexthopState_Copy,
- .display = (PARCObjectDisplay *)strategyNexthopState_Display,
- .toString = (PARCObjectToString *)strategyNexthopState_ToString,
- .equals = (PARCObjectEquals *)strategyNexthopState_Equals,
- .compare = (PARCObjectCompare *)strategyNexthopState_Compare,
- .hashCode = (PARCObjectHashCode *)strategyNexthopState_HashCode,
- .display = (PARCObjectDisplay *)strategyNexthopState_Display);
-
-void strategyNexthopState_AssertValid(const StrategyNexthopState *instance) {
- parcAssertTrue(strategyNexthopState_IsValid(instance),
- "StrategyNexthopState is not valid.");
-}
-
-StrategyNexthopState *strategyNexthopState_Create() {
- StrategyNexthopState *result =
- parcObject_CreateInstance(StrategyNexthopState);
- if (result != NULL) {
- result->pi = 0;
- result->avg_pi = 0.0;
- result->weight = 1;
- }
- return result;
-}
-
-void strategyNexthopState_Reset(StrategyNexthopState *x) {
- x->pi = 0;
- x->avg_pi = 0.0;
- x->weight = 1;
-}
-
-int strategyNexthopState_Compare(const StrategyNexthopState *val,
- const StrategyNexthopState *other) {
- if (val == NULL) {
- if (other != NULL) {
- return -1;
- }
- } else if (other == NULL) {
- return 1;
- } else {
- strategyNexthopState_OptionalAssertValid(val);
- strategyNexthopState_OptionalAssertValid(other);
-
- if (val->pi < other->pi) {
- return -1;
- } else if (val->pi > other->pi) {
- return 1;
- }
-
- if (val->avg_pi < other->avg_pi) {
- return -1;
- } else if (val->avg_pi > other->avg_pi) {
- return 1;
- }
-
- if (val->weight < other->weight) {
- return -1;
- } else if (val->weight > other->weight) {
- return 1;
- }
- }
-
- return 0;
-}
-
-StrategyNexthopState *strategyNexthopState_Copy(
- const StrategyNexthopState *original) {
- StrategyNexthopState *result = strategyNexthopState_Create();
- result->pi = original->pi;
- result->avg_pi = original->avg_pi;
- result->weight = original->weight;
-
- return result;
-}
-
-void strategyNexthopState_Display(const StrategyNexthopState *instance,
- int indentation) {
- parcDisplayIndented_PrintLine(indentation, "StrategyNexthopState@%p {",
- instance);
- parcDisplayIndented_PrintLine(indentation + 1, "%d", instance->pi);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_pi);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->weight);
- parcDisplayIndented_PrintLine(indentation, "}");
-}
-
-bool strategyNexthopState_Equals(const StrategyNexthopState *x,
- const StrategyNexthopState *y) {
- bool result = false;
-
- if (x == y) {
- result = true;
- } else if (x == NULL || y == NULL) {
- result = false;
- } else {
- strategyNexthopState_OptionalAssertValid(x);
- strategyNexthopState_OptionalAssertValid(y);
-
- if (strategyNexthopState_Compare(x, y) == 0) {
- result = true;
- }
- }
-
- return result;
-}
-
-PARCHashCode strategyNexthopState_HashCode(const StrategyNexthopState *x) {
- PARCHashCode result = 0;
- char str[128];
- sprintf(str, "PI:%d: AVG_PI:%f: W:%f", x->pi, x->avg_pi, x->weight);
- result = parcHashCode_Hash((uint8_t *)&str, strlen(str));
- return result;
-}
-
-bool strategyNexthopState_IsValid(const StrategyNexthopState *x) {
- bool result = false;
-
- if (x != NULL) {
- result = true;
- }
-
- return result;
-}
-
-char *strategyNexthopState_ToString(const StrategyNexthopState *x) {
- // this is not implemented
- parcTrapNotImplemented("strategyNexthopState_ToString is not implemented");
- return NULL;
-}
-
-unsigned strategyNexthopState_GetPI(const StrategyNexthopState *x) {
- strategyNexthopState_OptionalAssertValid(x);
-
- return x->pi;
-}
-
-double strategyNexthopState_GetAvgPI(const StrategyNexthopState *x) {
- strategyNexthopState_OptionalAssertValid(x);
-
- return x->avg_pi;
-}
-
-double strategyNexthopState_GetWeight(const StrategyNexthopState *x) {
- strategyNexthopState_OptionalAssertValid(x);
-
- return x->weight;
-}
-
-double strategyNexthopState_UpdateState(StrategyNexthopState *x, bool inc,
- double alpha) {
- if (inc) {
- x->pi++;
- } else {
- if (x->pi > 0) {
- x->pi--;
- }
- }
- x->avg_pi = (x->avg_pi * alpha) + (x->pi * (1 - alpha));
-#ifdef WITH_POLICY
- if (x->avg_pi < AVG_PI_THRESHOLD) {
-#else
- if (x->avg_pi == 0.0) {
-#endif /* WITH_POLICY */
- x->avg_pi = 0.1;
- }
- x->weight = 1 / x->avg_pi;
-
- return x->weight;
-}
diff --git a/hicn-light/src/hicn/strategies/nexthopState.h b/hicn-light/src/hicn/strategies/nexthopState.h
deleted file mode 100644
index 35a9f497b..000000000
--- a/hicn-light/src/hicn/strategies/nexthopState.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef nexthopstate_h
-#define nexthopstate_h
-
-#include <parc/algol/parc_HashCode.h>
-#include <parc/algol/parc_Object.h>
-
-struct strategy_nexthop_state;
-typedef struct strategy_nexthop_state StrategyNexthopState;
-extern parcObjectDescriptor_Declaration(StrategyNexthopState);
-
-/**
- */
-StrategyNexthopState *strategyNexthopState_Acquire(
- const StrategyNexthopState *instance);
-
-#ifdef PARCLibrary_DISABLE_VALIDATION
-#define strategyNexthopState_OptionalAssertValid(_instance_)
-#else
-#define strategyNexthopState_OptionalAssertValid(_instance_) \
- strategyNexthopState_AssertValid(_instance_)
-#endif
-
-/**
- */
-void strategyNexthopState_AssertValid(const StrategyNexthopState *instance);
-
-/**
- */
-StrategyNexthopState *strategyNexthopState_Create();
-
-void strategyNexthopState_Reset(StrategyNexthopState *x);
-/**
- */
-int strategyNexthopState_Compare(const StrategyNexthopState *instance,
- const StrategyNexthopState *other);
-
-/**
- */
-StrategyNexthopState *strategyNexthopState_Copy(
- const StrategyNexthopState *original);
-
-/**
- */
-void strategyNexthopState_Display(const StrategyNexthopState *instance,
- int indentation);
-
-/**
- */
-bool strategyNexthopState_Equals(const StrategyNexthopState *x,
- const StrategyNexthopState *y);
-
-/**
- */
-PARCHashCode strategyNexthopState_HashCode(
- const StrategyNexthopState *instance);
-
-/**
- */
-bool strategyNexthopState_IsValid(const StrategyNexthopState *instance);
-
-/**
- */
-void strategyNexthopState_Release(StrategyNexthopState **instancePtr);
-
-/**
- */
-char *strategyNexthopState_ToString(const StrategyNexthopState *instance);
-
-/**
- */
-unsigned strategyNexthopState_GetPI(const StrategyNexthopState *x);
-
-double strategyNexthopState_GetAvgPI(const StrategyNexthopState *x);
-
-double strategyNexthopState_GetWeight(const StrategyNexthopState *x);
-
-double strategyNexthopState_UpdateState(StrategyNexthopState *x, bool inc,
- double alpha);
-#endif
diff --git a/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c b/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c
index a3953987f..3caed8130 100644
--- a/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c
+++ b/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,303 +24,17 @@
#include <parc/assert/parc_Assert.h>
#include <hicn/strategies/nexthopStateLowLatency.h>
-const unsigned MAX_ROUNS_WITHOUT_PROBES = 4;
- //if we do not receives probes for 4 rounds it means
- //that we had no responce from any producer for 2 sec
- //we can say that this interface is daed
-const unsigned MIN_NON_LOSSY_ROUNDS = 10;
- //number of rounds in non lossy mode before switch to
- //no lossy state
-const double MAX_LOSS_RATE = 0.10; //10%
-
-struct strategy_nexthop_state_ll {
- bool in_use;
- bool is_allowed; // the policy may not allow the use of this face
- unsigned face_id;
- unsigned sent_packets;
- //switch metrics
- unsigned last_try_to_switch_round;
- unsigned try_to_switch_counter;
- //probes counters
- unsigned recevied_probes;
- unsigned rounds_without_probes;
- unsigned sent_probes;
- unsigned lost_probes;
- unsigned non_lossy_rounds;
- //avgs
- double avg_rtt;
- double avg_rtt_in_use;
- double avg_queue;
- double avg_loss_rate;
-
-};
-
-static bool _strategyNexthopStateLL_Destructor(
- StrategyNexthopStateLL **instancePtr) {
- return true;
-}
-
-parcObject_ImplementAcquire(strategyNexthopStateLL, StrategyNexthopStateLL);
-
-parcObject_ImplementRelease(strategyNexthopStateLL, StrategyNexthopStateLL);
-
-parcObject_Override(
- StrategyNexthopStateLL, PARCObject,
- .destructor = (PARCObjectDestructor *)_strategyNexthopStateLL_Destructor,
- .copy = (PARCObjectCopy *)strategyNexthopStateLL_Copy,
- .display = (PARCObjectDisplay *)strategyNexthopStateLL_Display,
- .toString = (PARCObjectToString *)strategyNexthopStateLL_ToString,
- .equals = (PARCObjectEquals *)strategyNexthopStateLL_Equals,
- .compare = (PARCObjectCompare *)strategyNexthopStateLL_Compare,
- .hashCode = (PARCObjectHashCode *)strategyNexthopStateLL_HashCode,
- .display = (PARCObjectDisplay *)strategyNexthopStateLL_Display);
-
-void strategyNexthopStateLL_AssertValid(const StrategyNexthopStateLL *instance) {
- parcAssertTrue(strategyNexthopStateLL_IsValid(instance),
- "StrategyNexthopState is not valid.");
-}
-
-StrategyNexthopStateLL *strategyNexthopStateLL_Create(unsigned face_id) {
- StrategyNexthopStateLL *result =
- parcObject_CreateInstance(StrategyNexthopStateLL);
- if (result != NULL) {
- result->in_use = false;
- result->is_allowed = true;
- result->face_id = face_id;
- result->sent_packets = 0;
- result->last_try_to_switch_round = 0;
- result->try_to_switch_counter = 0;
- result->recevied_probes = 0;
- result->rounds_without_probes = 0;
- result->sent_probes = 0;
- result->lost_probes = 0;
- result->non_lossy_rounds = MIN_NON_LOSSY_ROUNDS;
- result->avg_rtt = -1.0;
- result->avg_rtt_in_use = -1.0;
- result->avg_queue = 0.0001;
- result->avg_loss_rate = 0.0;
- }
- return result;
-}
-
-void strategyNexthopStateLL_Reset(StrategyNexthopStateLL *x) {
- x->in_use = false;
- x->is_allowed = true;
- x->sent_packets = 0;
- x->last_try_to_switch_round = 0;
- x->try_to_switch_counter = 0;
- x->recevied_probes = 0;
- x->rounds_without_probes = 0;
- x->sent_probes = 0;
- x->lost_probes = 0;
- x->non_lossy_rounds = MIN_NON_LOSSY_ROUNDS;
- x->avg_rtt = -1.0;
- x->avg_rtt_in_use = -1.0;
- x->avg_queue = 0.0001;
- x->avg_loss_rate = 0.0;
-}
-
-
-int strategyNexthopStateLL_Compare(const StrategyNexthopStateLL *val,
- const StrategyNexthopStateLL *other) {
- if (val == NULL) {
- if (other != NULL) {
- return -1;
- }
- } else if (other == NULL) {
- return 1;
- } else {
- strategyNexthopStateLL_OptionalAssertValid(val);
- strategyNexthopStateLL_OptionalAssertValid(other);
-
- if (val->in_use < other->in_use){
- return -1;
- }else if (val->in_use > other->in_use){
- return 1;
- }
-
- if (val->is_allowed < other->is_allowed){
- return -1;
- }else if (val->is_allowed> other->is_allowed){
- return 1;
- }
-
- if (val->face_id < other->face_id) {
- return -1;
- } else if (val->face_id > other->face_id) {
- return 1;
- }
-
- if (val->sent_packets < other->sent_packets){
- return -1;
- } else if (val->sent_packets > other->sent_packets){
- return 1;
- }
-
- if (val->last_try_to_switch_round <
- other->last_try_to_switch_round) {
- return -1;
- } else if (val->last_try_to_switch_round >
- other->last_try_to_switch_round) {
- return 1;
- }
-
- if (val->try_to_switch_counter <
- other->try_to_switch_counter) {
- return -1;
- } else if (val->try_to_switch_counter >
- other->try_to_switch_counter) {
- return 1;
- }
-
- if (val->recevied_probes < other->recevied_probes) {
- return -1;
- } else if (val->recevied_probes > other->recevied_probes) {
- return 1;
- }
-
- if (val->rounds_without_probes < other->rounds_without_probes) {
- return -1;
- } else if (val->rounds_without_probes > other->rounds_without_probes) {
- return 1;
- }
-
- if (val->sent_probes < other->sent_probes) {
- return -1;
- } else if (val->sent_probes > other->sent_probes) {
- return 1;
- }
-
- if (val->lost_probes < other->lost_probes) {
- return -1;
- } else if (val->lost_probes > other->lost_probes) {
- return 1;
- }
-
- if (val->non_lossy_rounds < other->non_lossy_rounds) {
- return -1;
- } else if (val->non_lossy_rounds > other->non_lossy_rounds) {
- return 1;
- }
-
- if (val->avg_rtt < other->avg_rtt) {
- return -1;
- } else if (val->avg_rtt > other->avg_rtt) {
- return 1;
- }
-
- if (val->avg_rtt_in_use < other->avg_rtt_in_use) {
- return -1;
- } else if (val->avg_rtt_in_use > other->avg_rtt_in_use) {
- return 1;
- }
-
- if (val->avg_queue < other->avg_queue) {
- return -1;
- } else if (val->avg_queue > other->avg_queue) {
- return 1;
- }
-
- if (val->avg_loss_rate < other->avg_loss_rate) {
- return -1;
- } else if (val->avg_loss_rate > other->avg_loss_rate) {
- return 1;
- }
- }
-
- return 0;
-}
-
-StrategyNexthopStateLL *strategyNexthopStateLL_Copy(
- const StrategyNexthopStateLL *original) {
- StrategyNexthopStateLL *result = strategyNexthopStateLL_Create(original->face_id);
- result->in_use = original->in_use;
- result->is_allowed = original->is_allowed;
- result->sent_packets = original->sent_packets;
- result->last_try_to_switch_round = original->last_try_to_switch_round;
- result->try_to_switch_counter = original->try_to_switch_counter;
- result->recevied_probes = original->recevied_probes;
- result->rounds_without_probes = original->rounds_without_probes;
- result->sent_probes = original->sent_probes;
- result->lost_probes = original->lost_probes;
- result->non_lossy_rounds = original->non_lossy_rounds;
- result->avg_rtt = original->avg_rtt;
- result->avg_rtt_in_use = original->avg_rtt_in_use;
- result->avg_queue = original->avg_queue;
- result->avg_loss_rate = original->avg_loss_rate;
- return result;
-}
-
-void strategyNexthopStateLL_Display(const StrategyNexthopStateLL *instance,
- int indentation) {
- parcDisplayIndented_PrintLine(indentation, "StrategyNexthopStateLL@%p {",
- instance);
- parcDisplayIndented_PrintLine(indentation + 1, "%d", instance->face_id);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_rtt);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_rtt_in_use);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_queue);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_loss_rate);
- parcDisplayIndented_PrintLine(indentation, "}");
-}
-
-
-bool strategyNexthopStateLL_Equals(const StrategyNexthopStateLL *x,
- const StrategyNexthopStateLL *y) {
- bool result = false;
-
- if (x == y) {
- result = true;
- } else if (x == NULL || y == NULL) {
- result = false;
- } else {
- strategyNexthopStateLL_OptionalAssertValid(x);
- strategyNexthopStateLL_OptionalAssertValid(y);
-
- if (strategyNexthopStateLL_Compare(x, y) == 0) {
- result = true;
- }
- }
-
- return result;
-}
-
-PARCHashCode strategyNexthopStateLL_HashCode(const StrategyNexthopStateLL *x) {
- PARCHashCode result = 0;
- char str[128];
- sprintf(str, "ID:%d: RTT:%f: RTTUSE:%f: Q:%f L:%f", x->face_id, x->avg_rtt,
- x->avg_rtt_in_use, x->avg_queue, x->avg_loss_rate);
- result = parcHashCode_Hash((uint8_t *)&str, strlen(str));
- return result;
-}
-
-bool strategyNexthopStateLL_IsValid(const StrategyNexthopStateLL *x) {
- bool result = false;
-
- if (x != NULL) {
- result = true;
- }
-
- return result;
-}
-
-char *strategyNexthopStateLL_ToString(const StrategyNexthopStateLL *x) {
- // this is not implemented
- parcTrapNotImplemented("strategyNexthopStateLL_ToString is not implemented");
- return NULL;
-}
-
double strategyNexthopStateLL_GetRTTProbe(StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
- if(x->rounds_without_probes > MAX_ROUNS_WITHOUT_PROBES)
- return DBL_MAX;
+ if (x->rounds_without_probes > MAX_ROUNS_WITHOUT_PROBES) return DBL_MAX;
- if(x->avg_rtt == -1.0){
- if(x->avg_rtt_in_use == -1.0){
+ if (x->avg_rtt == -1.0) {
+ if (x->avg_rtt_in_use == -1.0) {
return 0.0;
- }else{
- //this happens if the face recevied probes only in in_use mode
- //we set the avf_rtt with rtt_in_use
+ } else {
+ // this happens if the face recevied probes only in in_use mode
+ // we set the avf_rtt with rtt_in_use
x->avg_rtt = x->avg_rtt_in_use;
}
}
@@ -331,11 +45,9 @@ double strategyNexthopStateLL_GetRTTProbe(StrategyNexthopStateLL *x) {
double strategyNexthopStateLL_GetRTTInUse(StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
- if(x->rounds_without_probes > MAX_ROUNS_WITHOUT_PROBES)
- return DBL_MAX;
+ if (x->rounds_without_probes > MAX_ROUNS_WITHOUT_PROBES) return DBL_MAX;
- if(x->avg_rtt_in_use == -1.0)
- return strategyNexthopStateLL_GetRTTProbe(x);
+ if (x->avg_rtt_in_use == -1.0) return strategyNexthopStateLL_GetRTTProbe(x);
return x->avg_rtt_in_use;
}
@@ -343,9 +55,9 @@ double strategyNexthopStateLL_GetRTTInUse(StrategyNexthopStateLL *x) {
double strategyNexthopStateLL_GetRTTLive(StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
- if(x->in_use){
+ if (x->in_use) {
return strategyNexthopStateLL_GetRTTInUse(x);
- }else{
+ } else {
return strategyNexthopStateLL_GetRTTProbe(x);
}
}
@@ -353,46 +65,45 @@ double strategyNexthopStateLL_GetRTTLive(StrategyNexthopStateLL *x) {
double strategyNexthopStateLL_GetQueuing(const StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
- if(x->rounds_without_probes > MAX_ROUNS_WITHOUT_PROBES)
- return 0.0;
+ if (x->rounds_without_probes > MAX_ROUNS_WITHOUT_PROBES) return 0.0;
return x->avg_queue;
}
void strategyNexthopStateLL_AddRttSample(StrategyNexthopStateLL *x,
- unsigned int rtt){
+ unsigned int rtt) {
strategyNexthopStateLL_OptionalAssertValid(x);
x->recevied_probes++;
- //form uint to double
+ // form uint to double
double drtt = rtt;
- if(x->in_use){
- if(x->avg_rtt_in_use == -1.0){
+ if (x->in_use) {
+ if (x->avg_rtt_in_use == -1.0) {
x->avg_rtt_in_use = drtt;
- }else{
+ } else {
x->avg_rtt_in_use = (x->avg_rtt_in_use * 0.9) + (drtt * 0.1);
}
- }else{
- if(x->avg_rtt == -1.0){
- x->avg_rtt = drtt;
- }else{
+ } else {
+ if (x->avg_rtt == -1.0) {
+ x->avg_rtt = drtt;
+ } else {
x->avg_rtt = (x->avg_rtt * 0.9) + (drtt * 0.1);
}
}
- if(x->avg_rtt_in_use == -1.0 || x->avg_rtt == -1.0){
+ if (x->avg_rtt_in_use == -1.0 || x->avg_rtt == -1.0) {
x->avg_queue = 0.0001;
- }else{
+ } else {
double queue = x->avg_rtt_in_use - x->avg_rtt;
- if(queue < 0){
+ if (queue < 0) {
queue = 0.0001;
}
x->avg_queue = (x->avg_queue * 0.95) + (0.05 * queue);
}
}
-void strategyNexthopStateLL_SetUnusedFace(StrategyNexthopStateLL *x){
+void strategyNexthopStateLL_SetUnusedFace(StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
x->in_use = false;
}
@@ -403,75 +114,76 @@ unsigned strategyNexthopStateLL_GetFaceId(StrategyNexthopStateLL *x) {
}
void strategyNexthopStateLL_IncreaseTryToSwitch(StrategyNexthopStateLL *x,
- unsigned round){
- if(x->try_to_switch_counter == 0 ||
- round == (x->last_try_to_switch_round + 1)){
+ unsigned round) {
+ if (x->try_to_switch_counter == 0 ||
+ round == (x->last_try_to_switch_round + 1)) {
x->last_try_to_switch_round = round;
x->try_to_switch_counter++;
- }else{
+ } else {
x->try_to_switch_counter = 0;
}
}
-unsigned strategyNexthopStateLL_GetTryToSwitch(const StrategyNexthopStateLL *x){
+unsigned strategyNexthopStateLL_GetTryToSwitch(
+ const StrategyNexthopStateLL *x) {
return x->try_to_switch_counter;
}
-void strategyNexthopStateLL_ResetTryToSwitch(StrategyNexthopStateLL *x){
+void strategyNexthopStateLL_ResetTryToSwitch(StrategyNexthopStateLL *x) {
x->try_to_switch_counter = 0;
}
-void strategyNexthopStateLL_SendPacket(StrategyNexthopStateLL *x){
+void strategyNexthopStateLL_SendPacket(StrategyNexthopStateLL *x) {
x->in_use = true;
x->sent_packets++;
}
-void strategyNexthopStateLL_SentProbe(StrategyNexthopStateLL *x){
+void strategyNexthopStateLL_SentProbe(StrategyNexthopStateLL *x) {
x->sent_probes++;
}
-void strategyNexthopStateLL_LostProbe(StrategyNexthopStateLL *x){
+void strategyNexthopStateLL_LostProbe(StrategyNexthopStateLL *x) {
x->lost_probes++;
}
-bool strategyNexthopStateLL_IsLossy(const StrategyNexthopStateLL *x){
- if(x->non_lossy_rounds < 10 ||
- x->avg_loss_rate > MAX_LOSS_RATE){
+bool strategyNexthopStateLL_IsLossy(const StrategyNexthopStateLL *x) {
+ if (x->non_lossy_rounds < 10 || x->avg_loss_rate > MAX_LOSS_RATE) {
return true;
}
return false;
}
-void strategyNexthopStateLL_SetIsAllowed(StrategyNexthopStateLL *x, bool allowed){
+void strategyNexthopStateLL_SetIsAllowed(StrategyNexthopStateLL *x,
+ bool allowed) {
x->is_allowed = allowed;
}
-bool strategyNexthopStateLL_IsAllowed(const StrategyNexthopStateLL *x){
+bool strategyNexthopStateLL_IsAllowed(const StrategyNexthopStateLL *x) {
return x->is_allowed;
}
-void strategyNexthopStateLL_StartNewRound(StrategyNexthopStateLL *x){
+void strategyNexthopStateLL_StartNewRound(StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
- if(x->sent_packets == 0) //the face was not used in the last round
+ if (x->sent_packets == 0) // the face was not used in the last round
x->in_use = false;
x->sent_packets = 0;
- if(x->recevied_probes == 0){
+ if (x->recevied_probes == 0) {
x->rounds_without_probes++;
- }else{
+ } else {
x->rounds_without_probes = 0;
}
x->recevied_probes = 0;
- //compute losses in this round
- if(x->sent_probes != 0){
- double loss_rate = (double) x->lost_probes / (double) x->sent_probes;
+ // compute losses in this round
+ if (x->sent_probes != 0) {
+ double loss_rate = (double)x->lost_probes / (double)x->sent_probes;
x->avg_loss_rate = x->avg_loss_rate * 0.7 + loss_rate * 0.3;
- if(x->avg_loss_rate > MAX_LOSS_RATE){
+ if (x->avg_loss_rate > MAX_LOSS_RATE) {
x->non_lossy_rounds = 0;
- }else{
+ } else {
x->non_lossy_rounds++;
}
}
diff --git a/hicn-light/src/hicn/strategies/nexthopStateLowLatency.h b/hicn-light/src/hicn/strategies/nexthopStateLowLatency.h
index 34dbb8262..7f4181d44 100644
--- a/hicn-light/src/hicn/strategies/nexthopStateLowLatency.h
+++ b/hicn-light/src/hicn/strategies/nexthopStateLowLatency.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -47,7 +47,7 @@ void strategyNexthopStateLL_Reset(StrategyNexthopStateLL *x);
/**
*/
int strategyNexthopStateLL_Compare(const StrategyNexthopStateLL *instance,
- const StrategyNexthopStateLL *other);
+ const StrategyNexthopStateLL *other);
/**
*/
@@ -57,12 +57,12 @@ StrategyNexthopStateLL *strategyNexthopStateLL_Copy(
/**
*/
void strategyNexthopStateLL_Display(const StrategyNexthopStateLL *instance,
- int indentation);
+ int indentation);
/**
*/
bool strategyNexthopStateLL_Equals(const StrategyNexthopStateLL *x,
- const StrategyNexthopStateLL *y);
+ const StrategyNexthopStateLL *y);
/**
*/
@@ -88,11 +88,10 @@ double strategyNexthopStateLL_GetRTTInUse(StrategyNexthopStateLL *x);
double strategyNexthopStateLL_GetRTTLive(StrategyNexthopStateLL *x);
double strategyNexthopStateLL_GetQueuing(const StrategyNexthopStateLL *x);
void strategyNexthopStateLL_AddRttSample(StrategyNexthopStateLL *x,
- unsigned int rtt);
-
+ unsigned int rtt);
void strategyNexthopStateLL_IncreaseTryToSwitch(StrategyNexthopStateLL *x,
- unsigned round);
+ unsigned round);
unsigned strategyNexthopStateLL_GetTryToSwitch(const StrategyNexthopStateLL *x);
void strategyNexthopStateLL_ResetTryToSwitch(StrategyNexthopStateLL *x);
@@ -108,7 +107,8 @@ void strategyNexthopStateLL_LostProbe(StrategyNexthopStateLL *x);
bool strategyNexthopStateLL_IsLossy(const StrategyNexthopStateLL *x);
-void strategyNexthopStateLL_SetIsAllowed(StrategyNexthopStateLL *x, bool allowed);
+void strategyNexthopStateLL_SetIsAllowed(StrategyNexthopStateLL *x,
+ bool allowed);
bool strategyNexthopStateLL_IsAllowed(const StrategyNexthopStateLL *x);
diff --git a/hicn-light/src/hicn/strategies/probe_generator.c b/hicn-light/src/hicn/strategies/probe_generator.c
new file mode 100644
index 000000000..439de0a12
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/probe_generator.c
@@ -0,0 +1,114 @@
+/*
+ * 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 "probe_generator.h"
+
+#include <hicn/core/forwarder.h>
+#include <hicn/core/nexthops.h>
+
+// map functions
+static void add_to_map(probe_generator_t *pg, unsigned seq, Ticks now) {
+ khiter_t k;
+ int ret;
+ k = kh_put_bp_map(pg->ticks_by_seq, seq, &ret);
+ kh_value(pg->ticks_by_seq, k) = now;
+}
+
+static Ticks get_from_map(probe_generator_t *pg, unsigned seq) {
+ khiter_t k;
+ k = kh_get_bp_map(pg->ticks_by_seq, seq);
+ if (k == kh_end(pg->ticks_by_seq)) return 0;
+ Ticks t = kh_value(pg->ticks_by_seq, k);
+ return t;
+}
+
+static void remove_from_map(probe_generator_t *pg, unsigned seq) {
+ khiter_t k;
+ k = kh_get_bp_map(pg->ticks_by_seq, seq);
+ if (k != kh_end(pg->ticks_by_seq)) kh_del_bp_map(pg->ticks_by_seq, k);
+}
+
+static void clear_map(probe_generator_t *pg) {
+ kh_clear(bp_map, pg->ticks_by_seq);
+}
+
+// seq number generator
+
+static uint32_t get_seq_number(probe_generator_t *pg) {
+ uint32_t seq = 0;
+ uint32_t try = 0;
+ while (try < 3) { // try up to 3 times
+ seq =
+ (rand() % (MAX_PROBE_SUFFIX - MIN_PROBE_SUFFIX + 1)) + MIN_PROBE_SUFFIX;
+ Ticks time = get_from_map(pg, seq);
+ if (time == 0) return seq; // seq does not exists
+ try++;
+ }
+ return 0;
+}
+
+// probing functions
+
+probe_generator_t *create_probe_generator() {
+ probe_generator_t *pg = calloc(1, sizeof(probe_generator_t));
+ if (!pg) return NULL;
+
+ pg->ticks_by_seq = kh_init_bp_map();
+ return pg;
+}
+
+void destroy_probe_generator(probe_generator_t *pg) {
+ kh_destroy_bp_map(pg->ticks_by_seq);
+ free(pg);
+}
+
+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);
+ if (!conn) return -1;
+
+ msgbuf_t *probe;
+ off_t msg_id = msgbuf_pool_get_id(msgbuf_pool, (msgbuf_t *)msgbuf);
+ off_t probe_offset = msgbuf_pool_clone(msgbuf_pool, &probe, msg_id);
+
+ uint32_t seq = get_seq_number(pg);
+ if (seq == 0) return -1;
+
+ messageHandler_ModifySuffix(msgbuf_get_packet(probe), seq);
+ connection_send(conn, probe_offset, true);
+ connection_flush(conn);
+ add_to_map(pg, seq, ticks_now());
+ msgbuf_pool_put(msgbuf_pool, probe);
+
+ return 0;
+}
+
+Ticks register_probe(probe_generator_t *pg, unsigned seq) {
+ Ticks now = ticks_now();
+ add_to_map(pg, seq, now);
+ return now;
+}
+
+Ticks get_probe_send_time(probe_generator_t *pg, unsigned seq) {
+ return get_from_map(pg, seq);
+}
+
+void delete_probe(probe_generator_t *pg, unsigned seq) {
+ remove_from_map(pg, seq);
+}
+
+void delete_all_probes(probe_generator_t *pg) { clear_map(pg); }
diff --git a/hicn-light/src/hicn/strategies/probe_generator.h b/hicn-light/src/hicn/strategies/probe_generator.h
new file mode 100644
index 000000000..26d6a3a22
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/probe_generator.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICNLIGHT_PROBE_GENERATOR
+#define HICNLIGHT_PROBE_GENERATOR
+
+#include "../base/khash.h"
+#include <hicn/core/ticks.h>
+#include <hicn/core/msgbuf.h>
+
+KHASH_MAP_INIT_INT64(bp_map, Ticks);
+
+struct forwarder_s;
+
+typedef struct probe_generator {
+ kh_bp_map_t *ticks_by_seq;
+} probe_generator_t;
+
+probe_generator_t *create_probe_generator();
+
+void destroy_probe_generator(probe_generator_t *pg);
+
+int generate_probe(probe_generator_t *pg, const msgbuf_t *msgbuf,
+ const struct forwarder_s *forwarder, unsigned nexthop);
+
+Ticks register_probe(probe_generator_t *pg, unsigned seq);
+
+Ticks get_probe_send_time(probe_generator_t *pg, unsigned seq);
+
+void delete_probe(probe_generator_t *pg, unsigned seq);
+
+void delete_all_probes(probe_generator_t *pg);
+
+#endif /* HICNLIGHT_PROBE_GENERATOR */
diff --git a/hicn-light/src/hicn/strategies/random.c b/hicn-light/src/hicn/strategies/random.c
new file mode 100644
index 000000000..5b076df7c
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/random.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <hicn/hicn-light/config.h>
+
+#include <hicn/core/nexthops.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+
+#include "random.h"
+
+static int strategy_random_initialize(strategy_entry_t *entry,
+ const void *forwarder) {
+ srand((unsigned int)time(NULL));
+ entry->forwarder = forwarder;
+ return 0;
+}
+
+static int strategy_random_finalize(strategy_entry_t *entry) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_random_add_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops, off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_random_remove_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops, off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static nexthops_t *strategy_random_lookup_nexthops(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const msgbuf_t *msgbuf) {
+ nexthops_select(nexthops, rand() % nexthops_get_len(nexthops));
+ return nexthops;
+}
+
+static int strategy_random_on_data(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *data_nexthops,
+ const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation, Ticks objReception) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_random_on_timeout(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops) {
+ /* Nothing to do */
+ return 0;
+}
+
+DECLARE_STRATEGY(random);
diff --git a/hicn-light/src/hicn/config/controlRemovePunting.h b/hicn-light/src/hicn/strategies/random.h
index 858d6f969..bdea5e4dd 100644
--- a/hicn-light/src/hicn/config/controlRemovePunting.h
+++ b/hicn-light/src/hicn/strategies/random.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,14 +14,22 @@
*/
/**
- * @file control_RemovePunting.h
- *
+ * Forward randomly
*/
-#ifndef Control_RemovePunting_h
-#define Control_RemovePunting_h
+#ifndef HICNLIGHT_STRATEGY_RANDOM_H
+#define HICNLIGHT_STRATEGY_RANDOM_H
+
+typedef struct {
+ void *_;
+} strategy_random_nexthop_state_t;
+
+typedef struct {
+ void *_;
+} strategy_random_state_t;
+
+typedef struct {
+ void *_;
+} strategy_random_options_t;
-#include <hicn/config/controlState.h>
-CommandOps *controlRemovePunting_Create(ControlState *state);
-CommandOps *controlRemovePunting_HelpCreate(ControlState *state);
-#endif // Control_RemovePunting_h
+#endif /* HICNLIGHT_STRATEGY_RANDOM_H */
diff --git a/hicn-light/src/hicn/strategies/replication.c b/hicn-light/src/hicn/strategies/replication.c
new file mode 100644
index 000000000..86a3e3431
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/replication.c
@@ -0,0 +1,98 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <hicn/hicn-light/config.h>
+
+#include <hicn/core/nexthops.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+
+#include "replication.h"
+
+/* Shorthand */
+#define strategy_state_t strategy_replication_state_t
+
+static int strategy_replication_initialize(strategy_entry_t *entry,
+ const void *forwarder) {
+ entry->forwarder = forwarder;
+ strategy_state_t *state = &entry->state.replication;
+ state->prev_nexthops = malloc(sizeof(nexthops_t));
+ *((nexthops_t *)state->prev_nexthops) = NEXTHOPS_EMPTY;
+ return 0;
+}
+
+static int strategy_replication_finalize(strategy_entry_t *entry) {
+ /* Nothing to do */
+ strategy_state_t *state = &entry->state.replication;
+ free(state->prev_nexthops);
+ return 0;
+}
+
+static int strategy_replication_add_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_replication_remove_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static nexthops_t *strategy_replication_lookup_nexthops(
+ strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) {
+ // if nexthops is different from prev_nexthops send updates
+ strategy_state_t *state = &entry->state.replication;
+
+ if (!nexthops_equal((nexthops_t *)state->prev_nexthops, nexthops)) {
+ // send updates
+ strategy_replication_options_t *options = &entry->options.replication;
+ update_remote_node_paths(nexthops, entry->forwarder,
+ options->local_prefixes);
+
+ // update next hops
+ nexthops_copy(nexthops, (nexthops_t *)state->prev_nexthops);
+ }
+
+ // Return all next hops
+ return nexthops;
+}
+
+static int strategy_replication_on_data(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *data_nexthops,
+ const msgbuf_t *msgbuf,
+ Ticks pitEntryCreation,
+ Ticks objReception) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_replication_on_timeout(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops) {
+ /* Nothing to do */
+ return 0;
+}
+
+DECLARE_STRATEGY(replication);
diff --git a/hicn-light/src/hicn/config/controlAddPolicy.h b/hicn-light/src/hicn/strategies/replication.h
index 273e3a476..753ae4744 100644
--- a/hicn-light/src/hicn/config/controlAddPolicy.h
+++ b/hicn-light/src/hicn/strategies/replication.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,22 +14,24 @@
*/
/**
- * @file control_AddPolicy.h
- * @brief Add a static policy
- *
- * Implements the "add policy" node of the CLI tree
- *
+ * Forward replication of the interest on all the paths
*/
-#ifndef Control_AddPolicy_h
-#define Control_AddPolicy_h
+#ifndef HICNLIGHT_STRATEGY_REPLICATION_H
+#define HICNLIGHT_STRATEGY_REPLICATION_H
+
+#include "local_prefixes.h"
-#ifdef WITH_POLICY
+typedef struct {
+ void *_;
+} strategy_replication_nexthop_state_t;
-#include <hicn/config/controlState.h>
-CommandOps *controlAddPolicy_Create(ControlState *state);
-CommandOps *controlAddPolicy_HelpCreate(ControlState *state);
+typedef struct {
+ void *prev_nexthops;
+} strategy_replication_state_t;
-#endif /* WITH_POLICY */
+typedef struct {
+ local_prefixes_t *local_prefixes;
+} strategy_replication_options_t;
-#endif // Control_AddPolicy_h
+#endif /* HICNLIGHT_STRATEGY_REPLICATION_H */
diff --git a/hicn-light/src/hicn/strategies/rnd.c b/hicn-light/src/hicn/strategies/rnd.c
deleted file mode 100644
index 064f3965b..000000000
--- a/hicn-light/src/hicn/strategies/rnd.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/strategies/rnd.h>
-
-static void _strategyRnd_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-static void _strategyRnd_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId);
-
-static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
-static NumberSet *_strategyRnd_ReturnNexthops(StrategyImpl *strategy);
-static unsigned _strategyRnd_CountNexthops(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
-static void _strategyRnd_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyRnd_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyRnd_ImplDestroy(StrategyImpl **strategyPtr);
-static strategy_type _strategyRnd_GetStrategy(StrategyImpl *strategy);
-
-static StrategyImpl _template = {
- .context = NULL,
- .receiveObject = &_strategyRnd_ReceiveObject,
- .onTimeout = &_strategyRnd_OnTimeout,
- .lookupNexthop = &_strategyRnd_LookupNexthop,
-#ifndef WITH_POLICY
- .returnNexthops = &_strategyRnd_ReturnNexthops,
- .countNexthops = &_strategyRnd_CountNexthops,
-#endif /* ! WITH_POLICY */
- .addNexthop = &_strategyRnd_AddNexthop,
- .removeNexthop = &_strategyRnd_RemoveNexthop,
- .destroy = &_strategyRnd_ImplDestroy,
- .getStrategy = &_strategyRnd_GetStrategy,
-};
-
-#ifndef WITH_POLICY
-struct strategy_rnd;
-typedef struct strategy_rnd StrategyRnd;
-
-struct strategy_rnd {
- NumberSet *nexthops;
-};
-#endif /* ! WITH_POLICY */
-
-StrategyImpl *strategyRnd_Create() {
-#ifndef WITH_POLICY
- StrategyRnd *strategy = parcMemory_AllocateAndClear(sizeof(StrategyRnd));
- parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyRnd));
-
- strategy->nexthops = numberSet_Create();
-#endif /* ! WITH_POLICY */
- srand((unsigned int)time(NULL));
-
- StrategyImpl *impl = parcMemory_AllocateAndClear(sizeof(StrategyImpl));
- parcAssertNotNull(impl, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyImpl));
- memcpy(impl, &_template, sizeof(StrategyImpl));
-#ifndef WITH_POLICY
- impl->context = strategy;
-#endif /* ! WITH_POLICY */
- return impl;
-}
-
-// =======================================================
-// Dispatch API
-
-strategy_type _strategyRnd_GetStrategy(StrategyImpl *strategy) {
- return SET_STRATEGY_RANDOM;
-}
-
-#ifndef WITH_POLICY
-static int _select_Nexthop(StrategyRnd *strategy) {
- unsigned len = (unsigned)numberSet_Length(strategy->nexthops);
- if (len == 0) {
- return -1;
- }
-
- int rnd = (rand() % len);
- return numberSet_GetItem(strategy->nexthops, rnd);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyRnd_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {}
-
-static void _strategyRnd_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId) {}
-
-static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage) {
- unsigned out_connection;
- NumberSet *out = numberSet_Create();
-
-#ifdef WITH_POLICY
- // We return one next hop at random
- out_connection = numberSet_GetItem(nexthops, rand() % numberSet_Length(nexthops));
-
-#else
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- unsigned in_connection = message_GetIngressConnectionId(interestMessage);
- unsigned nexthopSize = (unsigned)numberSet_Length(srnd->nexthops);
-
- if ((nexthopSize == 0) ||
- ((nexthopSize == 1) &&
- numberSet_Contains(srnd->nexthops, in_connection))) {
- // there are no output faces or the input face is also the only output face.
- // return null to avoid loops
- return out;
- }
-
- do {
- out_connection = _select_Nexthop(srnd);
- } while (out_connection == in_connection);
-
- if (out_connection == -1) {
- return out;
- }
-#endif /* WITH_POLICY */
-
- numberSet_Add(out, out_connection);
- return out;
-}
-
-#ifndef WITH_POLICY
-static NumberSet *_strategyRnd_ReturnNexthops(StrategyImpl *strategy) {
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- return srnd->nexthops;
-}
-
-unsigned _strategyRnd_CountNexthops(StrategyImpl *strategy) {
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- return (unsigned)numberSet_Length(srnd->nexthops);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyRnd_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
-#ifndef WITH_POLICY
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- if (!numberSet_Contains(srnd->nexthops, connectionId)) {
- numberSet_Add(srnd->nexthops, connectionId);
- }
-#endif /* ! WITH_POLICY */
-}
-
-static void _strategyRnd_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
-#ifndef WITH_POLICY
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
-
- if (numberSet_Contains(srnd->nexthops, connectionId)) {
- numberSet_Remove(srnd->nexthops, connectionId);
- }
-#endif /* ! WITH_POLICY */
-}
-
-static void _strategyRnd_ImplDestroy(StrategyImpl **strategyPtr) {
- parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*strategyPtr,
- "Parameter must dereference to non-null pointer");
-
- StrategyImpl *impl = *strategyPtr;
-
-#ifndef WITH_POLICY
- StrategyRnd *strategy = (StrategyRnd *)impl->context;
- numberSet_Release(&(strategy->nexthops));
- parcMemory_Deallocate((void **)&strategy);
-#endif /* ! WITH_POLICY */
-
- parcMemory_Deallocate((void **)&impl);
- *strategyPtr = NULL;
-}
diff --git a/hicn-light/src/hicn/strategies/strategyImpl.h b/hicn-light/src/hicn/strategies/strategyImpl.h
deleted file mode 100644
index 140da5bf8..000000000
--- a/hicn-light/src/hicn/strategies/strategyImpl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file strategyImpl.h
- * @brief Defines the function structure for a Strategy implementation
- *
- * <#Detailed Description#>
- *
- */
-
-/**
- * A dispatch structure for a concrete implementation of a forwarding strategy.
- */
-
-#ifndef strategyImpl_h
-#define strategyImpl_h
-
-#include <hicn/core/message.h>
-#include <hicn/core/numberSet.h>
-
-struct strategy_impl;
-typedef struct strategy_impl StrategyImpl;
-
-/**
- * @typedef StrategyImpl
- * @abstract Forwarding strategy implementation
- * @constant receiveObject is called when we receive an object and have a
- * measured round trip time. This allows a strategy to update its performance
- * data.
- * @constant lookupNexthop Find the set of nexthops to use for the Interest.
- * May be empty, should not be NULL. Must be destroyed.
- * @constant addNexthop Add a nexthop to the list of available nexthops with a
- * routing protocol-specific cost.
- * @constant destroy cleans up the strategy, freeing all memory and state. A
- * strategy is reference counted, so the final destruction only happens after
- * the last reference is released.
- * @discussion <#Discussion#>
- */
-struct strategy_impl {
- void *context;
- void (*receiveObject)(StrategyImpl *strategy, const NumberSet *egressId,
- const Message *objectMessage, Ticks pitEntryCreation,
- Ticks objReception);
- void (*onTimeout)(StrategyImpl *strategy, const NumberSet *egressId);
- NumberSet *(*lookupNexthop)(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
- NumberSet *(*returnNexthops)(StrategyImpl *strategy);
- unsigned (*countNexthops)(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
- void (*addNexthop)(StrategyImpl *strategy, unsigned connectionId);
- void (*removeNexthop)(StrategyImpl *strategy, unsigned connectionId);
- void (*destroy)(StrategyImpl **strategyPtr);
- strategy_type (*getStrategy)(StrategyImpl *strategy);
-};
-
-#endif // strategyImpl_h
diff --git a/hicn-light/src/hicn/test/CMakeLists.txt b/hicn-light/src/hicn/test/CMakeLists.txt
new file mode 100644
index 000000000..0ded4253d
--- /dev/null
+++ b/hicn-light/src/hicn/test/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+
+include(BuildMacros)
+
+list(APPEND TESTS_SRC
+ test-bitmap.cc
+ test-configuration.cc
+ test-hash.cc
+ test-khash.cc
+ test-loop.cc
+ test-pool.cc
+ test-parser.cc
+ test-ctrl.cc
+ test-ring.cc
+ test-vector.cc
+ test-msgbuf_pool.cc
+ test-nexthops.cc
+ test-connection_table.cc
+ test-listener_table.cc
+ test-packet_cache.cc
+ test-strategy-load-balancing.cc
+ test-strategy-random.cc
+ test-strategy-replication.cc
+ test-strategy-best-path.cc
+ test-subscription.cc
+ test-local_prefixes.cc
+ test-probe_generator.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/../config/command_listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../config/command_route.c
+ main.cc
+)
+
+build_executable(hicn_light_tests
+ NO_INSTALL
+ SOURCES ${TESTS_SRC}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
+ INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBHICNCTRL_STATIC} ${LIBHICN_LIGHT_SHARED}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS "${COMPILER_DEFINITIONS}"
+)
+
+add_test_internal(hicn_light_tests)
diff --git a/hicn-light/src/hicn/strategies/loadBalancer.h b/hicn-light/src/hicn/test/main.cc
index 74920768d..49cc28f66 100644
--- a/hicn-light/src/hicn/strategies/loadBalancer.h
+++ b/hicn-light/src/hicn/test/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,15 +13,9 @@
* limitations under the License.
*/
-/**
- * Forward on the less loaded path
- */
-
-#ifndef loadBalancer_h
-#define loadBalancer_h
-
-#include <hicn/strategies/strategyImpl.h>
-
-StrategyImpl *strategyLoadBalancer_Create();
+#include <gtest/gtest.h>
-#endif // loadBalancer_h
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/hicn-light/src/hicn/test/test-bitmap.cc b/hicn-light/src/hicn/test/test-bitmap.cc
new file mode 100644
index 000000000..f1bf1ae5a
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-bitmap.cc
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <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/bitmap.h>
+}
+
+#define DEFAULT_SIZE 10
+
+class BitmapTest : public ::testing::Test {
+ protected:
+ BitmapTest() {}
+
+ virtual ~BitmapTest() {}
+
+ bitmap_t* bitmap;
+};
+
+/*
+ * TEST: bitmap allocation
+ */
+TEST_F(BitmapTest, BitmapAllocation) {
+ int rc;
+
+ /*
+ * We take a value < 32 on purpose to avoid confusion on the choice of a 32
+ * or 64 bit integer for storage
+ */
+ size_t size_not_pow2 = DEFAULT_SIZE;
+ bitmap_init(bitmap, size_not_pow2, 0);
+
+ /*
+ * Bitmap should have been allocated with a size rounded to the next power
+ * of 2
+ */
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
+
+ /* By default, no element should be set */
+ EXPECT_FALSE(bitmap_is_set(bitmap, 0));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 0));
+
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
+
+ EXPECT_FALSE(bitmap_is_set(bitmap, size_not_pow2 - 1));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, size_not_pow2 - 1));
+
+ /* Bitmap should not have been reallocated */
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
+
+ /* After setting a bit after the end, bitmap should have been reallocated */
+ bitmap_set(bitmap, sizeof(bitmap[0]) * 8 - 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
+
+ /* After setting a bit after the end, bitmap should have been reallocated */
+ rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL);
+
+ rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8 + 1);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL);
+
+ bitmap_free(bitmap);
+
+ size_t size_pow2 = 16;
+
+ /* Limiting test for allocation size */
+ bitmap_init(bitmap, size_pow2, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL);
+
+ bitmap_free(bitmap);
+}
+
+TEST_F(BitmapTest, BitmapSet) {
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set(bitmap, 20);
+ EXPECT_TRUE(bitmap_is_set(bitmap, 20));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 20));
+ EXPECT_FALSE(bitmap_is_set(bitmap, 19));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 19));
+
+ bitmap_free(bitmap);
+}
+
+TEST_F(BitmapTest, BitmapUnSet) {
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set(bitmap, 20);
+ bitmap_set(bitmap, 19);
+ bitmap_unset(bitmap, 20);
+ EXPECT_FALSE(bitmap_is_set(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_set(bitmap, 19));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 19));
+
+ bitmap_free(bitmap);
+}
+
+TEST_F(BitmapTest, BitmapSetTo) {
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set_to(bitmap, 40);
+ EXPECT_TRUE(bitmap_is_set(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_set(bitmap, 21));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 41));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 42));
+
+ bitmap_free(bitmap);
+}
diff --git a/hicn-light/src/hicn/test/test-configuration.cc b/hicn-light/src/hicn/test/test-configuration.cc
new file mode 100644
index 000000000..b631bb20b
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-configuration.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C" {
+#include <hicn/config/configuration.h>
+}
+
+static inline size_t CS_SIZE = 10;
+static inline char CONFIG_FILE[] = "setup.conf";
+static inline int LOG_LEVEL = LOG_DEBUG;
+static inline char LOG_FILE[] = "/dev/null";
+static inline uint16_t PORT = 1234;
+static inline uint16_t CONF_PORT = 5678;
+static inline bool IS_DAEMON_MODE = true;
+static inline char PREFIX[] = "b001::/16";
+static inline char PREFIX_2[] = "c001::/16";
+static inline strategy_type_t STRATEGY_TYPE = STRATEGY_TYPE_BESTPATH;
+
+class ConfigurationTest : public ::testing::Test {
+ protected:
+ ConfigurationTest() {
+ config = configuration_create();
+ log_conf.log_level = LOG_FATAL;
+ log_conf.log_file = NULL;
+ }
+ virtual ~ConfigurationTest() { configuration_free(config); }
+
+ configuration_t *config;
+};
+
+TEST_F(ConfigurationTest, CreateConfiguration) {
+ // Check configuration creation
+ ASSERT_NE(config, nullptr);
+}
+
+TEST_F(ConfigurationTest, SetGeneralParameters) {
+ configuration_set_cs_size(config, CS_SIZE);
+ size_t cs_size = configuration_get_cs_size(config);
+ EXPECT_EQ(cs_size, CS_SIZE);
+
+ configuration_set_fn_config(config, CONFIG_FILE);
+ const char *config_file = configuration_get_fn_config(config);
+ EXPECT_EQ(config_file, CONFIG_FILE);
+
+ configuration_set_port(config, PORT);
+ uint16_t port = configuration_get_port(config);
+ EXPECT_EQ(port, PORT);
+
+ configuration_set_configuration_port(config, CONF_PORT);
+ uint16_t conf_port = configuration_get_configuration_port(config);
+ EXPECT_EQ(conf_port, CONF_PORT);
+
+ configuration_set_daemon(config, IS_DAEMON_MODE);
+ bool is_daemon_mode = configuration_get_daemon(config);
+ EXPECT_EQ(is_daemon_mode, IS_DAEMON_MODE);
+}
+
+TEST_F(ConfigurationTest, SetLogParameters) {
+ configuration_set_loglevel(config, LOG_LEVEL);
+ int log_level = configuration_get_loglevel(config);
+ EXPECT_EQ(log_level, LOG_LEVEL);
+ EXPECT_EQ(log_conf.log_level, LOG_LEVEL);
+
+ configuration_set_logfile(config, LOG_FILE);
+ const char *log_file = configuration_get_logfile(config);
+ EXPECT_EQ(log_file, LOG_FILE);
+ int write_fd = configuration_get_logfile_fd(config);
+ EXPECT_NE(write_fd, -1);
+}
+
+TEST_F(ConfigurationTest, SetStrategyParameter) {
+ configuration_set_strategy(config, PREFIX, STRATEGY_TYPE);
+ strategy_type_t strategy_type = configuration_get_strategy(config, PREFIX);
+ EXPECT_EQ(strategy_type, STRATEGY_TYPE);
+
+ // Check strategy for non-registered prefix
+ strategy_type = configuration_get_strategy(config, PREFIX_2);
+ EXPECT_EQ(strategy_type, STRATEGY_TYPE_UNDEFINED);
+}
diff --git a/hicn-light/src/hicn/test/test-connection_table.cc b/hicn-light/src/hicn/test/test-connection_table.cc
new file mode 100644
index 000000000..6bbf478e2
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-connection_table.cc
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.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/core/connection_table.h>
+}
+
+#define CONNECTION_NAME "connection_name_test"
+#define CONNECTION_NAME_2 "connection_name_test_2"
+
+class ConnectionTableTest : public ::testing::Test {
+ protected:
+ ConnectionTableTest() {
+ log_conf.log_level = LOG_INFO;
+
+ conn_table_ = connection_table_create();
+ pair_ =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+ }
+ virtual ~ConnectionTableTest() { connection_table_free(conn_table_); }
+
+ connection_table_t *conn_table_;
+ connection_t *connection_;
+ address_pair_t pair_;
+};
+
+TEST_F(ConnectionTableTest, CreateTable) {
+ /* Check connection_table allocation */
+ EXPECT_NE(conn_table_, nullptr);
+
+ /* Check connection_table size */
+ size_t conn_table_size = connection_table_len(conn_table_);
+ EXPECT_EQ(conn_table_size, (size_t)0);
+}
+
+TEST_F(ConnectionTableTest, AddConnection) {
+ // Add connection to connection table
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ size_t conn_table_size = connection_table_len(conn_table_);
+ EXPECT_EQ(conn_table_size, (size_t)1);
+ EXPECT_NE(connection_, nullptr);
+
+ // Get connection by name and by pair
+ khiter_t k_name = kh_get_ct_name(conn_table_->id_by_name, CONNECTION_NAME);
+ EXPECT_NE(k_name, kh_end(conn_table_->id_by_name));
+ khiter_t k_pair = kh_get_ct_pair(conn_table_->id_by_pair, &pair_);
+ EXPECT_NE(k_pair, kh_end(conn_table_->id_by_pair));
+}
+
+TEST_F(ConnectionTableTest, GetConnection) {
+ // Add connection to connection table
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ size_t conn_table_size = connection_table_len(conn_table_);
+ EXPECT_EQ(conn_table_size, (size_t)1);
+ EXPECT_NE(connection_, nullptr);
+
+ // Get connection by name
+ connection_t *connection_retrieved =
+ connection_table_get_by_name(conn_table_, CONNECTION_NAME);
+ ASSERT_NE(connection_retrieved, nullptr);
+ EXPECT_EQ(connection_retrieved, connection_);
+
+ // Get connection by pair
+ connection_retrieved = connection_table_get_by_pair(conn_table_, &pair_);
+ ASSERT_NE(connection_retrieved, nullptr);
+ EXPECT_EQ(connection_retrieved, connection_);
+}
+
+TEST_F(ConnectionTableTest, GetConnectionWithIdOutOfRange) {
+ connection_t *connection = _connection_table_get_by_id(conn_table_, ~0);
+ EXPECT_EQ(connection, nullptr);
+}
+
+TEST_F(ConnectionTableTest, GetConnectionWithInvalidId) {
+ // First connection inserted has always id equal to 0
+ int non_valid_id = 5;
+
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ connection_t *connection_not_found =
+ connection_table_get_by_id(conn_table_, non_valid_id);
+ ASSERT_EQ(connection_not_found, nullptr);
+}
+
+TEST_F(ConnectionTableTest, GetConnectionWithValidId) {
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ int id = connection_table_get_connection_id(conn_table_, connection_);
+ connection_t *connection_found = connection_table_get_by_id(conn_table_, id);
+ ASSERT_EQ(connection_found, connection_);
+}
+
+TEST_F(ConnectionTableTest, GetConnectionIdFromValidName) {
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ int id = connection_table_get_id_by_name(conn_table_, CONNECTION_NAME);
+ ASSERT_TRUE(listener_id_is_valid(id));
+}
+
+TEST_F(ConnectionTableTest, GetConnectionIdFromInvalidName) {
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ int id = connection_table_get_id_by_name(conn_table_, CONNECTION_NAME_2);
+ ASSERT_FALSE(listener_id_is_valid(id));
+}
+
+TEST_F(ConnectionTableTest, RemoveConnection) {
+ // Add connection (connection name and pair must be set)
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ connection_->name = (char *)CONNECTION_NAME;
+ connection_->pair = pair_;
+
+ // Remove connection
+ int id = connection_table_get_connection_id(conn_table_, connection_);
+ connection_table_remove_by_id(conn_table_, id);
+
+ // Check connection table size
+ size_t conn_table_size = connection_table_len(conn_table_);
+ EXPECT_EQ(conn_table_size, (size_t)0);
+
+ // Check that previous connection is not valid anymore
+ connection_t *connection_not_found =
+ connection_table_get_by_id(conn_table_, id);
+ EXPECT_EQ(connection_not_found, nullptr);
+ connection_not_found =
+ connection_table_get_by_name(conn_table_, CONNECTION_NAME);
+ EXPECT_EQ(connection_not_found, nullptr);
+ connection_not_found = connection_table_get_by_pair(conn_table_, &pair_);
+ EXPECT_EQ(connection_not_found, nullptr);
+}
+
+TEST_F(ConnectionTableTest, PrintTable) {
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ // Insert an additional connection
+ address_pair_t pair_2 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(3), _ADDRESS4_LOCALHOST(4));
+ connection_t *connection_2 =
+ connection_table_allocate(conn_table_, &pair_2, CONNECTION_NAME_2);
+ connection_2->type = FACE_TYPE_TCP;
+
+ testing::internal::CaptureStdout();
+ connection_table_print_by_pair(conn_table_);
+ std::string std_out = testing::internal::GetCapturedStdout();
+
+ ASSERT_NE(std_out, "");
+
+ EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:1"));
+ 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"));
+}
+
+TEST_F(ConnectionTableTest, AddMultipleConnections) {
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ // Insert an additional connection
+ address_pair_t pair_2 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(3), _ADDRESS4_LOCALHOST(4));
+ connection_t *connection_2 =
+ connection_table_allocate(conn_table_, &pair_2, CONNECTION_NAME_2);
+ connection_2->type = FACE_TYPE_TCP;
+
+ // Check connection table size
+ size_t conn_table_size = connection_table_len(conn_table_);
+ EXPECT_EQ(conn_table_size, (size_t)2);
+
+ connection_t *c1 = connection_table_get_by_name(conn_table_, CONNECTION_NAME);
+ ASSERT_NE(c1, nullptr);
+ connection_t *c2 =
+ connection_table_get_by_name(conn_table_, CONNECTION_NAME_2);
+ ASSERT_NE(c2, nullptr);
+ EXPECT_NE(c1, c2);
+}
+
+TEST_F(ConnectionTableTest, Iterate) {
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+ connection_->pair = pair_;
+
+ // Insert an additional connection
+ address_pair_t pair_2 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(3), _ADDRESS4_LOCALHOST(4));
+ connection_t *connection_2 =
+ connection_table_allocate(conn_table_, &pair_2, CONNECTION_NAME_2);
+ connection_2->type = FACE_TYPE_TCP;
+ connection_2->pair = pair_2;
+
+ // Iterate over the connection table and count the connections
+ connection_t *c;
+ int count = 0;
+ connection_table_foreach(conn_table_, c, { count++; });
+ EXPECT_EQ(count, 2);
+
+ // Iterate over the connection table and check the connections
+ char local_addr_str[NI_MAXHOST], remote_addr_str[NI_MAXHOST];
+ int local_port, remote_port;
+ testing::internal::CaptureStdout();
+ connection_table_foreach(conn_table_, c, {
+ const address_pair_t *pair = connection_get_pair(c);
+ address_to_string(&pair->local, local_addr_str, &local_port);
+ address_to_string(&pair->remote, remote_addr_str, &remote_port);
+
+ printf("%s:%d\t%s:%d\n", local_addr_str, local_port, remote_addr_str,
+ remote_port);
+ });
+
+ std::string std_out = testing::internal::GetCapturedStdout();
+ ASSERT_NE(std_out, "");
+ EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:1"));
+ 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"));
+}
diff --git a/hicn-light/src/hicn/test/test-ctrl.cc b/hicn-light/src/hicn/test/test-ctrl.cc
new file mode 100644
index 000000000..77b16a8af
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-ctrl.cc
@@ -0,0 +1,164 @@
+/*
+ * 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/util/log.h>
+#include <hicn/ctrl.h>
+#include <hicn/config/parse.h>
+#include <hicn/ctrl/route.h>
+#include <hicn/util/sstrncpy.h>
+}
+
+class CtrlTest : public ::testing::Test {
+ protected:
+ CtrlTest() {
+ log_conf.log_level = LOG_INFO;
+ s_ = hc_sock_create_forwarder(HICNLIGHT_NG);
+ }
+ virtual ~CtrlTest() { hc_sock_free(s_); }
+
+ hc_sock_t *s_ = nullptr;
+ hc_command_t command_ = {};
+};
+
+/**
+ * The parse() function is used to easily create the command.
+ * Here we test the serialization of the commands i.e. from command
+ * to message sent to the forwarder.
+ */
+
+TEST_F(CtrlTest, AddValidListener) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_TRUE(success);
+}
+
+TEST_F(CtrlTest, AddListenerInvalidProtocol) {
+ // Set invalid protocol (icmp)
+ std::string cmd = "add listener icmp udp0 10.0.0.1 9696 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddListenerInvalidLocalPort) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ // Override with invalid port
+ command_.object.listener.local_port = 0;
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddListenerInvalidLocalAddress) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ // Override with invalid family
+ command_.object.listener.family = -1;
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddListenerEmptyLocalAddress) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ // Override with invalid address
+ command_.object.listener.local_addr = IP_ADDRESS_EMPTY;
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddListenerInvalidSymbolicName) {
+ std::string cmd = "add listener udp 0udp 10.0.0.1 9695 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddListenerInvalidSymbolicName2) {
+ std::string cmd = "add listener udp udp! 10.0.0.1 9695 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddListenerInvalidInterfaceName) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth/0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddValidRoute) {
+ std::string cmd = "add route conn0 c001::/64 1";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ hc_result_t *result = hc_route_create_conf(s_, &command_.object.route);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_TRUE(success);
+}
+
+TEST_F(CtrlTest, AddRouteInvalidLength) {
+ std::string cmd = "add route conn0 c001::/64 1";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ // Override with invalid prfix len
+ command_.object.route.len = MAX_IPV6_PREFIX_LEN + 1;
+
+ hc_result_t *result = hc_route_create_conf(s_, &command_.object.route);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+}
+
+TEST_F(CtrlTest, AddRouteInvalidCost) {
+ std::string cmd = "add route conn0 c001::/64 1";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+
+ // Override with invalid cost
+ command_.object.route.cost = MAX_ROUTE_COST + 1;
+
+ hc_result_t *result = hc_route_create_conf(s_, &command_.object.route);
+ bool success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+
+ // Override with invalid cost
+ command_.object.route.cost = MIN_ROUTE_COST - 1;
+
+ result = hc_route_create_conf(s_, &command_.object.route);
+ success = hc_result_get_success(s_, result);
+ EXPECT_FALSE(success);
+} \ 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
new file mode 100644
index 000000000..2b72e194a
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-hash.cc
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+// #include <hicn/transport/utils/hash.h>
+
+extern "C" {
+#include <hicn/base/hash.h>
+#include <hicn/core/address_pair.h>
+#include <hicn/core/listener.h>
+}
+
+TEST(HashTest, MultipleHashesForSameAddrPair) {
+ address_pair_t pair =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+
+ unsigned h1 = hash_struct(&pair);
+ unsigned h2 = hash_struct(&pair);
+ EXPECT_EQ(h1, h2);
+}
+
+TEST(HashTest, SameAddrPairs) {
+ address_pair_t pair1 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+ address_pair_t pair2 = pair1;
+
+ unsigned h1 = hash_struct(&pair1);
+ unsigned h2 = hash_struct(&pair2);
+ EXPECT_EQ(h1, h2);
+}
+
+TEST(HashTest, DifferentAddrPairs) {
+ address_pair_t pair1 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+
+ address_pair_t pair2 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(3), _ADDRESS4_LOCALHOST(4));
+
+ unsigned h1 = hash_struct(&pair1);
+ unsigned h2 = hash_struct(&pair2);
+ EXPECT_NE(h1, h2);
+}
+
+TEST(HashTest, SameLocalDifferentRemote) {
+ address_pair_t pair1 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+
+ address_pair_t pair2 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(4));
+
+ unsigned h1 = hash_struct(&pair1);
+ unsigned h2 = hash_struct(&pair2);
+ EXPECT_NE(h1, h2);
+}
+
+TEST(HashTest, SameRemoteDifferentLocal) {
+ address_pair_t pair1 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+
+ address_pair_t pair2 =
+ address_pair_factory(_ADDRESS4_LOCALHOST(3), _ADDRESS4_LOCALHOST(2));
+
+ unsigned h1 = hash_struct(&pair1);
+ unsigned h2 = hash_struct(&pair2);
+ EXPECT_NE(h1, h2);
+}
+
+TEST(HashTest, SameAddresses) {
+ address_t addr1 = _ADDRESS4_LOCALHOST(1);
+ address_t addr2 = _ADDRESS4_LOCALHOST(1);
+
+ unsigned h1 = hash_struct(&addr1);
+ unsigned h2 = hash_struct(&addr2);
+
+ EXPECT_EQ(h1, h2);
+}
+
+TEST(HashTest, SameListenerKeys) {
+ listener_key_t key1 =
+ listener_key_factory(_ADDRESS4_LOCALHOST(1), FACE_TYPE_UDP_LISTENER);
+ listener_key_t key2 =
+ listener_key_factory(_ADDRESS4_LOCALHOST(1), FACE_TYPE_UDP_LISTENER);
+
+ unsigned h1 = hash_struct(&key1);
+ unsigned h2 = hash_struct(&key2);
+
+ EXPECT_EQ(h1, h2);
+}
+
+TEST(HashTest, Collisions) {
+ uint32_t init_val = 2166136261UL;
+ (void)init_val;
+
+ std::map<u32, uint32_t> hashes;
+ 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 = hash(&seg, sizeof(seg));
+ EXPECT_FALSE(hashes.find(h) != hashes.end()) << seg << " - " << hashes[h];
+ hashes[h] = seg;
+ }
+} \ 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
new file mode 100644
index 000000000..4fcb48c31
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-khash.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <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" {
+#include <hicn/base/khash.h>
+}
+
+KHASH_MAP_INIT_INT(int, unsigned char)
+
+typedef struct {
+ unsigned key;
+ unsigned char val;
+} int_unpack_t;
+
+typedef struct {
+ unsigned key;
+ unsigned char val;
+} __attribute__((__packed__)) int_packed_t;
+
+#define hash_eq(a, b) ((a).key == (b).key)
+#define hash_func(a) ((a).key)
+
+KHASH_INIT(iun, int_unpack_t, char, 0, hash_func, hash_eq)
+KHASH_INIT(ipk, int_packed_t, char, 0, hash_func, hash_eq)
+
+class KHashTest : public ::testing::Test {
+ protected:
+ KHashTest() {}
+
+ virtual ~KHashTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() { khash = kh_init(int); }
+
+ virtual void TearDown() { kh_destroy(int, khash); }
+ khash_t(int) * khash;
+};
+
+TEST_F(KHashTest, KhashIntSize) {
+ int ret;
+ int k;
+ int size = kh_size(khash);
+
+ EXPECT_EQ(size, 0);
+ k = kh_put(int, khash, 10, &ret);
+ if (ret == 1) {
+ kh_val(khash, k) = 10;
+ }
+ size = kh_size(khash);
+ EXPECT_EQ(size, 1);
+}
+
+TEST_F(KHashTest, KhashIntPut) {
+ int ret;
+ int k;
+ k = kh_put(int, khash, 10, &ret);
+ if (ret == 1) {
+ kh_val(khash, k) = 10;
+ }
+ int size = kh_size(khash);
+ EXPECT_EQ(size, 1);
+ k = kh_put(int, khash, 20, &ret);
+ if (ret == 1) {
+ kh_val(khash, k) = 20;
+ }
+ size = kh_size(khash);
+ EXPECT_EQ(size, 2);
+}
+
+TEST_F(KHashTest, KhashCheckValue) {
+ int ret;
+ int k;
+ k = kh_put(int, khash, 10, &ret);
+ if (ret == 1) {
+ kh_val(khash, k) = 100;
+ }
+ k = kh_put(int, khash, 20, &ret);
+ if (ret == 1) {
+ kh_val(khash, k) = 200;
+ }
+
+ k = kh_put(int, khash, 10, &ret);
+ int val = -1;
+ if (!ret) val = kh_val(khash, k);
+ EXPECT_EQ(val, 100);
+
+ k = kh_put(int, khash, 20, &ret);
+ val = -1;
+ if (!ret) val = kh_val(khash, k);
+ EXPECT_EQ(val, 200);
+}
+
+// Check that there are no collisions in case of same key hash
+typedef struct {
+ int x;
+} Key;
+#define hash_key(key) 1 // Hash is always 1 to simulate collisions
+#define key_hash_eq(a, b) (a->x == b->x) // Function used in case of collisions
+KHASH_INIT(test_map, const Key *, unsigned, 1, hash_key, key_hash_eq);
+
+TEST_F(KHashTest, Collisions) {
+ int ret;
+ khiter_t k;
+
+ kh_test_map_t *map = kh_init(test_map);
+ Key key1 = {.x = 10};
+ Key key2 = {.x = 11};
+
+ k = kh_put_test_map(map, &key1, &ret);
+ EXPECT_EQ(ret, 1);
+ kh_val(map, k) = 15;
+
+ k = kh_put_test_map(map, &key2, &ret);
+ EXPECT_EQ(ret, 1);
+ kh_val(map, k) = 27;
+
+ k = kh_get_test_map(map, &key1);
+ ASSERT_NE(k, kh_end(map));
+ unsigned val = kh_val(map, k);
+ EXPECT_EQ(val, 15u);
+
+ k = kh_get_test_map(map, &key2);
+ ASSERT_NE(k, kh_end(map));
+ val = kh_val(map, k);
+ EXPECT_EQ(val, 27u);
+
+ kh_destroy_test_map(map);
+}
diff --git a/hicn-light/src/hicn/test/test-listener_table.cc b/hicn-light/src/hicn/test/test-listener_table.cc
new file mode 100644
index 000000000..b2ed0c276
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-listener_table.cc
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.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/core/listener_table.h>
+}
+
+#define LISTENER_NAME "listener_name_test"
+#define LISTENER_NAME_2 "listener_name_test_2"
+
+class ListenerTableTest : public ::testing::Test {
+ protected:
+ ListenerTableTest() {
+ log_conf.log_level = LOG_INFO;
+
+ listener_table_ = listener_table_create();
+ key_ = listener_key_factory(_ADDRESS4_LOCALHOST(1), FACE_TYPE_UDP_LISTENER);
+ }
+ virtual ~ListenerTableTest() { listener_table_free(listener_table_); }
+
+ listener_table_t *listener_table_;
+ listener_t *listener_;
+ listener_key_t key_;
+};
+
+TEST_F(ListenerTableTest, CreateTable) {
+ // Check listener_table allocation
+ EXPECT_NE(listener_table_, nullptr);
+
+ // Check listener_table size
+ size_t listener_table_size = listener_table_len(listener_table_);
+ EXPECT_EQ(listener_table_size, (size_t)0);
+}
+
+TEST_F(ListenerTableTest, AddListener) {
+ // Add listener to listener table
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ size_t listener_table_size = listener_table_len(listener_table_);
+ EXPECT_EQ(listener_table_size, (size_t)1);
+ EXPECT_NE(listener_, nullptr);
+
+ // Get listener by name and by key
+ khiter_t k_name = kh_get_lt_name(listener_table_->id_by_name, LISTENER_NAME);
+ EXPECT_NE(k_name, kh_end(listener_table_->id_by_name));
+ khiter_t k_key = kh_get_lt_key(listener_table_->id_by_key, &key_);
+ EXPECT_NE(k_key, kh_end(listener_table_->id_by_key));
+}
+
+TEST_F(ListenerTableTest, GetListener) {
+ // Add listener to listener table
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ size_t listener_table_size = listener_table_len(listener_table_);
+ EXPECT_EQ(listener_table_size, (size_t)1);
+ ASSERT_NE(listener_, nullptr);
+
+ // Get listener by name
+ listener_t *listener_retrieved =
+ listener_table_get_by_name(listener_table_, LISTENER_NAME);
+ ASSERT_NE(listener_retrieved, nullptr);
+ EXPECT_EQ(listener_retrieved, listener_);
+
+ // Get listener by key
+ listener_retrieved = listener_table_get_by_key(listener_table_, &key_);
+ ASSERT_NE(listener_retrieved, nullptr);
+ EXPECT_EQ(listener_retrieved, listener_);
+}
+
+TEST_F(ListenerTableTest, GetListenerWithIdOutOfRange) {
+ listener_t *listener = _listener_table_get_by_id(listener_table_, ~0);
+ EXPECT_EQ(listener, nullptr);
+}
+
+TEST_F(ListenerTableTest, GetListenerWithInvalidId) {
+ // First listener inserted has always id equal to 0
+ int non_valid_id = 5;
+
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ listener_t *listener_not_found =
+ listener_table_get_by_id(listener_table_, non_valid_id);
+ ASSERT_EQ(listener_not_found, nullptr);
+}
+
+TEST_F(ListenerTableTest, GetListenerWithValidId) {
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ int id = listener_table_get_listener_id(listener_table_, listener_);
+ listener_t *listener_found = listener_table_get_by_id(listener_table_, id);
+ ASSERT_EQ(listener_found, listener_);
+}
+
+TEST_F(ListenerTableTest, GetListenerIdFromValidName) {
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ int id = listener_table_get_id_by_name(listener_table_, LISTENER_NAME);
+ ASSERT_TRUE(listener_id_is_valid(id));
+}
+
+TEST_F(ListenerTableTest, GetListenerIdFromInvalidName) {
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ int id = listener_table_get_id_by_name(listener_table_, LISTENER_NAME_2);
+ ASSERT_FALSE(listener_id_is_valid(id));
+}
+
+TEST_F(ListenerTableTest, RemoveListener) {
+ // Add listener (listerner name and key must be set)
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+ listener_->name = (char *)LISTENER_NAME;
+ listener_->key = key_;
+
+ // Remove listener
+ int id = listener_table_get_listener_id(listener_table_, listener_);
+ listener_table_remove_by_id(listener_table_, id);
+
+ // Check listener table size
+ size_t listener_table_size = listener_table_len(listener_table_);
+ EXPECT_EQ(listener_table_size, (size_t)0);
+
+ // Check that previous listener is not valid anymore
+ listener_t *listener_not_found =
+ listener_table_get_by_id(listener_table_, id);
+ EXPECT_EQ(listener_not_found, nullptr);
+ listener_not_found =
+ listener_table_get_by_name(listener_table_, LISTENER_NAME);
+ EXPECT_EQ(listener_not_found, nullptr);
+ listener_not_found = listener_table_get_by_key(listener_table_, &key_);
+ EXPECT_EQ(listener_not_found, nullptr);
+}
+
+TEST_F(ListenerTableTest, PrintTable) {
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ // Insert an additional listener
+ listener_key_t key_2 =
+ listener_key_factory(_ADDRESS4_LOCALHOST(2), FACE_TYPE_TCP_LISTENER);
+ listener_t *listener_2 =
+ listener_table_allocate(listener_table_, &key_2, LISTENER_NAME_2);
+ listener_2->type = FACE_TYPE_UDP_LISTENER;
+
+ testing::internal::CaptureStdout();
+ listener_table_print_by_key(listener_table_);
+ std::string std_out = testing::internal::GetCapturedStdout();
+
+ ASSERT_NE(std_out, "");
+ EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:1"));
+ EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:2"));
+}
+
+TEST_F(ListenerTableTest, AddMultipleListeners) {
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+
+ // Insert an additional listener
+ listener_key_t key_2 =
+ listener_key_factory(_ADDRESS4_LOCALHOST(2), FACE_TYPE_TCP_LISTENER);
+ listener_t *listener_2 =
+ listener_table_allocate(listener_table_, &key_2, LISTENER_NAME_2);
+ listener_2->type = FACE_TYPE_UDP_LISTENER;
+
+ // Check listener table size
+ size_t listener_table_size = listener_table_len(listener_table_);
+ EXPECT_EQ(listener_table_size, (size_t)2);
+
+ listener_t *l1 = listener_table_get_by_name(listener_table_, LISTENER_NAME);
+ ASSERT_NE(l1, nullptr);
+ listener_t *l2 = listener_table_get_by_name(listener_table_, LISTENER_NAME_2);
+ ASSERT_NE(l2, nullptr);
+ EXPECT_NE(l1, l2);
+}
+
+TEST_F(ListenerTableTest, Iterate) {
+ listener_ = listener_table_allocate(listener_table_, &key_, LISTENER_NAME);
+ listener_->type = FACE_TYPE_UDP_LISTENER;
+ listener_->key = key_;
+
+ // Insert an additional listener
+ listener_key_t key_2 =
+ listener_key_factory(_ADDRESS4_LOCALHOST(2), FACE_TYPE_TCP_LISTENER);
+ listener_t *listener_2 =
+ listener_table_allocate(listener_table_, &key_2, LISTENER_NAME_2);
+ listener_2->type = FACE_TYPE_UDP_LISTENER;
+ listener_2->key = key_2;
+
+ // Iterate over the listener table and count the listeners
+ listener_t *l;
+ int count = 0;
+ listener_table_foreach(listener_table_, l, { count++; });
+ EXPECT_EQ(count, 2);
+
+ // Iterate over the listener table and check the listeners
+ char addr_str[NI_MAXHOST];
+ int port;
+ testing::internal::CaptureStdout();
+ listener_table_foreach(listener_table_, l, {
+ address_to_string(&l->address, addr_str, &port);
+ printf("%s\t%s:%d\n", face_type_str(l->type), addr_str, port);
+ });
+
+ std::string std_out = testing::internal::GetCapturedStdout();
+ ASSERT_NE(std_out, "");
+ EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:1"));
+ EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:2"));
+ EXPECT_THAT(std_out, testing::HasSubstr("UDP"));
+ EXPECT_THAT(std_out, testing::HasSubstr("TCP"));
+}
diff --git a/hicn-light/src/hicn/test/test-local_prefixes.cc b/hicn-light/src/hicn/test/test-local_prefixes.cc
new file mode 100644
index 000000000..80eb46501
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-local_prefixes.cc
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/strategies/local_prefixes.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/name.h>
+}
+
+const char *name_str1 = "b001::0";
+const char *name_str2 = "b002::0";
+const char *name_str3 = "b003::0";
+const char *name_str4 = "b004::0";
+const char *name_str5 = "b005::0";
+const char *name_str6 = "b006::0";
+const char *name_str7 = "b007::0";
+const char *name_str8 = "b008::0";
+const char *name_str9 = "b009::0";
+const char *name_str10 = "b010::0";
+const char *name_str11 = "b011::0";
+
+class LocalPrefixesTest : public ::testing::Test {
+ protected:
+ LocalPrefixesTest() {}
+
+ virtual ~LocalPrefixesTest() {}
+};
+
+TEST_F(LocalPrefixesTest, LocalPrefixesAddName) {
+ local_prefixes_t *lp = create_local_prefixes();
+ EXPECT_FALSE(lp == nullptr);
+
+ ip_address_t result;
+ inet_pton(AF_INET6, name_str1, (struct in6_addr *)&result);
+ Name name1;
+ name_CreateFromAddress(&name1, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str2, (struct in6_addr *)&result);
+ Name name2;
+ name_CreateFromAddress(&name2, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str3, (struct in6_addr *)&result);
+ Name name3;
+ name_CreateFromAddress(&name3, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str4, (struct in6_addr *)&result);
+ Name name4;
+ name_CreateFromAddress(&name4, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str5, (struct in6_addr *)&result);
+ Name name5;
+ name_CreateFromAddress(&name5, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str6, (struct in6_addr *)&result);
+ Name name6;
+ name_CreateFromAddress(&name6, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str7, (struct in6_addr *)&result);
+ Name name7;
+ name_CreateFromAddress(&name7, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str8, (struct in6_addr *)&result);
+ Name name8;
+ name_CreateFromAddress(&name8, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str9, (struct in6_addr *)&result);
+ Name name9;
+ name_CreateFromAddress(&name9, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str10, (struct in6_addr *)&result);
+ Name name10;
+ name_CreateFromAddress(&name10, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str11, (struct in6_addr *)&result);
+ Name name11;
+ name_CreateFromAddress(&name11, AF_INET6, result, 128);
+
+ local_prefixes_add_prefix(lp, &name1);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)1);
+
+ local_prefixes_add_prefix(lp, &name1);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)1);
+
+ local_prefixes_add_prefix(lp, &name2);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)2);
+
+ local_prefixes_add_prefix(lp, &name2);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)2);
+
+ local_prefixes_add_prefix(lp, &name3);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)3);
+
+ local_prefixes_add_prefix(lp, &name4);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)4);
+
+ local_prefixes_add_prefix(lp, &name5);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)5);
+
+ local_prefixes_add_prefix(lp, &name6);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)6);
+
+ local_prefixes_add_prefix(lp, &name7);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)7);
+
+ local_prefixes_add_prefix(lp, &name8);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)8);
+
+ local_prefixes_add_prefix(lp, &name9);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)9);
+
+ local_prefixes_add_prefix(lp, &name10);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)10);
+
+ local_prefixes_add_prefix(lp, &name11);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)10);
+
+ free_local_prefixes(lp);
+}
+
+TEST_F(LocalPrefixesTest, LocalPrefixesAddPrefixes) {
+ local_prefixes_t *lp = create_local_prefixes();
+ EXPECT_FALSE(lp == nullptr);
+
+ ip_address_t result;
+
+ local_prefixes_t *lp1 = create_local_prefixes();
+ EXPECT_FALSE(lp1 == nullptr);
+
+ inet_pton(AF_INET6, name_str1, (struct in6_addr *)&result);
+ Name name1;
+ name_CreateFromAddress(&name1, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str2, (struct in6_addr *)&result);
+ Name name2;
+ name_CreateFromAddress(&name2, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str3, (struct in6_addr *)&result);
+ Name name3;
+ name_CreateFromAddress(&name3, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str4, (struct in6_addr *)&result);
+ Name name4;
+ name_CreateFromAddress(&name4, AF_INET6, result, 128);
+
+ local_prefixes_add_prefix(lp1, &name1);
+ local_prefixes_add_prefix(lp1, &name2);
+ local_prefixes_add_prefix(lp1, &name3);
+ local_prefixes_add_prefix(lp1, &name4);
+
+ EXPECT_EQ(local_prefixes_get_len(lp1), (unsigned)4);
+
+ local_prefixes_add_prefixes(lp, lp1);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)4);
+
+ local_prefixes_add_prefixes(lp, lp1);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)4);
+
+ local_prefixes_t *lp2 = create_local_prefixes();
+ EXPECT_FALSE(lp2 == nullptr);
+
+ inet_pton(AF_INET6, name_str5, (struct in6_addr *)&result);
+ Name name5;
+ name_CreateFromAddress(&name5, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str6, (struct in6_addr *)&result);
+ Name name6;
+ name_CreateFromAddress(&name6, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str7, (struct in6_addr *)&result);
+ Name name7;
+ name_CreateFromAddress(&name7, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str8, (struct in6_addr *)&result);
+ Name name8;
+ name_CreateFromAddress(&name8, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str9, (struct in6_addr *)&result);
+ Name name9;
+ name_CreateFromAddress(&name9, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str10, (struct in6_addr *)&result);
+ Name name10;
+ name_CreateFromAddress(&name10, AF_INET6, result, 128);
+
+ inet_pton(AF_INET6, name_str11, (struct in6_addr *)&result);
+ Name name11;
+ name_CreateFromAddress(&name11, AF_INET6, result, 128);
+
+ local_prefixes_add_prefix(lp2, &name5);
+ local_prefixes_add_prefix(lp2, &name6);
+ local_prefixes_add_prefix(lp2, &name7);
+ local_prefixes_add_prefix(lp2, &name8);
+ local_prefixes_add_prefix(lp2, &name9);
+ local_prefixes_add_prefix(lp2, &name10);
+ local_prefixes_add_prefix(lp2, &name11);
+
+ EXPECT_EQ(local_prefixes_get_len(lp2), (unsigned)7);
+
+ local_prefixes_add_prefixes(lp, lp2);
+ EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)10);
+
+ free_local_prefixes(lp);
+ free_local_prefixes(lp1);
+ free_local_prefixes(lp2);
+}
diff --git a/hicn-light/src/hicn/test/test-loop.cc b/hicn-light/src/hicn/test/test-loop.cc
new file mode 100644
index 000000000..f783b0ada
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-loop.cc
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+
+extern "C" {
+#include <hicn/base/loop.h>
+}
+
+class LoopTest : public ::testing::Test {
+ static constexpr uint16_t BUFFER_SIZE = 1024;
+
+ protected:
+ LoopTest()
+ : server_port_(9191),
+ loop_(nullptr),
+ timer_tick_(2000),
+ connection_socket_(-1),
+ event_(nullptr),
+ timer_(nullptr) {}
+
+ virtual ~LoopTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ static int onFirstTimerExpiration(void *owner, int fd, void *arg) {
+ std::cout << "This function should never be called" << std::endl;
+ EXPECT_TRUE(false);
+ return -1;
+ }
+
+ static int onSecondTimerExpiration(void *owner, int fd, void *arg) {
+ std::cout << "First timer expired. Cancel second timer." << std::endl;
+ LoopTest *test = (LoopTest *)(arg);
+ loop_event_unregister(test->timer_);
+ return 0;
+ }
+
+ static int onTimerExpiration(void *owner, int fd, void *arg) {
+ // Create client socket
+ struct sockaddr_in addr;
+ int client_socket;
+ LoopTest *test = (LoopTest *)(arg);
+
+ client_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (client_socket == -1) {
+ perror("socket");
+ return -1;
+ }
+
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(test->server_port_);
+
+ if (connect(client_socket, (struct sockaddr *)&addr,
+ sizeof(struct sockaddr)) == -1) {
+ perror("connect");
+ return -1;
+ }
+
+ if (send(client_socket, "Hello, world!\n", 14, 0) == -1) {
+ perror("send");
+ return -1;
+ }
+
+ close(client_socket);
+ loop_event_unregister(test->timer_);
+
+ return 0;
+ }
+
+ static int onNewConnection(void *owner, int fd, void *arg) {
+ LoopTest *test = (LoopTest *)arg;
+ struct sockaddr_in addr;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_family = AF_INET;
+
+ socklen_t addr_len = sizeof(struct sockaddr_in);
+ int ret;
+
+ int client_fd =
+ accept(test->connection_socket_, (struct sockaddr *)(&addr), &addr_len);
+ if (client_fd == -1) {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
+ fprintf(stderr, "accept failed");
+ }
+
+ perror("accept");
+ return -1;
+ }
+
+ // Read whatever data available and close connection.
+ ret = read(client_fd, test->buffer, BUFFER_SIZE);
+ if (ret < 0) {
+ perror("read");
+ return -1;
+ }
+
+ test->buffer[ret] = '\0';
+ std::cout << "Received: " << (char *)test->buffer << std::endl;
+
+ close(client_fd);
+ loop_event_unregister(test->event_);
+
+ return 0;
+ }
+
+ void createTcpSocketServer() {
+ struct sockaddr_in addr;
+ int ret;
+
+ /* Create local socket. */
+
+ connection_socket_ = socket(AF_INET, SOCK_STREAM, 0);
+ if (connection_socket_ == -1) {
+ perror("socket");
+ return;
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(server_port_);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ ret = bind(connection_socket_, (const struct sockaddr *)&addr,
+ sizeof(struct sockaddr_in));
+ if (ret == -1) {
+ perror("bind");
+ return;
+ }
+
+ ret = listen(connection_socket_, 20);
+ if (ret == -1) {
+ perror("listen");
+ return;
+ }
+ }
+
+ uint16_t server_port_;
+ loop_t *loop_;
+ unsigned timer_tick_;
+ int connection_socket_;
+ event_t *event_;
+ event_t *timer_;
+ char buffer[BUFFER_SIZE];
+};
+
+TEST_F(LoopTest, LoopCreateAndFree) {
+ loop_ = loop_create();
+ EXPECT_TRUE(loop_ != NULL);
+ loop_free(loop_);
+ EXPECT_TRUE(loop_ != NULL);
+}
+
+TEST_F(LoopTest, EventCreateAndFree) {
+ int ret;
+
+ // Fake fd
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ loop_ = loop_create();
+
+ ret = loop_fd_event_create(&event_, loop_, fd, nullptr,
+ &LoopTest::onNewConnection, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(event_);
+
+ // Register the event
+ ret = loop_fd_event_register(event_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Unregister the event
+ ret = loop_event_free(event_);
+ EXPECT_TRUE(ret >= 0);
+
+ // close fd
+ ret = close(fd);
+ EXPECT_EQ(ret, 0);
+
+ // Free event loop
+ loop_free(loop_);
+}
+
+TEST_F(LoopTest, TimerCreateAndCancel) {
+ int ret;
+ event_t *timer2;
+ loop_ = loop_create();
+
+ ret = loop_timer_create(&timer_, loop_, nullptr,
+ &LoopTest::onFirstTimerExpiration, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(timer_);
+
+ ret = loop_timer_create(&timer2, loop_, nullptr,
+ &LoopTest::onSecondTimerExpiration, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(timer2);
+
+ // Register the 1st timer
+ ret = loop_timer_register(timer_, timer_tick_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Register the 2nd timer
+ ret = loop_timer_register(timer2, timer_tick_ / 2);
+ EXPECT_TRUE(ret >= 0);
+
+ _loop_dispatch(loop_, 0);
+
+ loop_undispatch(loop_);
+
+ // Unregister the events
+ ret = loop_event_free(timer_);
+ ret += loop_event_free(timer2);
+ EXPECT_TRUE(ret >= 0);
+
+ // Free event loop
+ loop_free(loop_);
+}
+
+TEST_F(LoopTest, LoopDispatch) {
+ int ret;
+
+ // Create new unix socket
+ createTcpSocketServer();
+ loop_ = loop_create();
+
+ ret = loop_fd_event_create(&event_, loop_, connection_socket_, nullptr,
+ &LoopTest::onNewConnection, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(event_);
+
+ ret = loop_fd_event_register(event_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Create timer.
+ ret = loop_timer_create(&timer_, loop_, nullptr, &LoopTest::onTimerExpiration,
+ this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(timer_);
+
+ ret = loop_timer_register(timer_, timer_tick_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Start event dispatching
+ _loop_dispatch(loop_, 0);
+
+ // Stop dispatching
+ loop_undispatch(loop_);
+
+ // Free events
+ loop_event_free(timer_);
+ loop_event_free(event_);
+
+ // Free event loop
+ loop_free(loop_);
+}
diff --git a/hicn-light/src/hicn/test/test-msgbuf_pool.cc b/hicn-light/src/hicn/test/test-msgbuf_pool.cc
new file mode 100644
index 000000000..5537aa216
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-msgbuf_pool.cc
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <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/core/msgbuf_pool.h>
+#include <hicn/base/pool.h>
+}
+
+class MsgbufPoolTest : public ::testing::Test {
+ protected:
+ MsgbufPoolTest() { msgbuf_pool = msgbuf_pool_create(); }
+ virtual ~MsgbufPoolTest() { msgbuf_pool_free(msgbuf_pool); }
+
+ msgbuf_pool_t *msgbuf_pool;
+};
+
+TEST_F(MsgbufPoolTest, Create) {
+ /* Check msgbuf_pool allocation */
+ EXPECT_NE(msgbuf_pool, nullptr);
+
+ /* Check msgbuf_pool size */
+ size_t msgbuf_pool_size = pool_hdr(msgbuf_pool->buffers)->alloc_size;
+ EXPECT_EQ(msgbuf_pool_size, (size_t)PACKET_POOL_DEFAULT_INIT_SIZE);
+}
+
+TEST_F(MsgbufPoolTest, GetMsgbuf) {
+ msgbuf_t *msgbuf = NULL;
+
+ /* Get valid msgbuf from msgbuf_pool */
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0);
+
+ /* Check if the returned id is correct */
+ off_t id = msgbuf_pool_get_id(msgbuf_pool, msgbuf);
+ EXPECT_EQ(id, msgbuf_id);
+
+ /* Check if the returned msgbuf is correct */
+ msgbuf_t *msgbuf_retrieved = msgbuf_pool_at(msgbuf_pool, id);
+ EXPECT_EQ(msgbuf_retrieved, msgbuf);
+}
+
+TEST_F(MsgbufPoolTest, PutMsgbuf) {
+ /* Check that asking a msgbuf right after releasing another one
+ returns the same msgbuf */
+
+ msgbuf_t *msgbuf = NULL;
+
+ off_t id1 = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+
+ msgbuf_pool_put(msgbuf_pool, msgbuf);
+
+ off_t id2 = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+
+ EXPECT_EQ(id2, id1);
+}
+
+TEST_F(MsgbufPoolTest, GetMultipleMsgbufs) {
+ const int NUM_MSG = 3;
+ msgbuf_t *msgbufs[NUM_MSG];
+
+ /* Check if successful allocation */
+ int ret = msgbuf_pool_getn(msgbuf_pool, msgbufs, NUM_MSG);
+ EXPECT_EQ(ret, 0);
+
+ /* Check if all msgbufs are valid */
+ for (unsigned i = 0; i < NUM_MSG; i++) {
+ msgbuf_pool_get_id(msgbuf_pool, msgbufs[i]);
+ EXPECT_NE(msgbufs[i], nullptr) << "Invalid index: " << i;
+ }
+}
+
+TEST_F(MsgbufPoolTest, AcquireMsgbuf) {
+ msgbuf_t *msgbuf = NULL;
+
+ // Get msgbuf from msgbuf_pool
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ msgbuf->type = MSGBUF_TYPE_COMMAND;
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0);
+
+ // Acquire the msgbuf
+ msgbuf_pool_acquire(msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_EQ(msgbuf->refs, 1u);
+
+ msgbuf_pool_acquire(msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_EQ(msgbuf->refs, 2u);
+}
+
+TEST_F(MsgbufPoolTest, ReleaseMsgbuf) {
+ msgbuf_t *msgbuf = NULL;
+
+ // Get msgbuf from msgbuf_pool
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ msgbuf->type = MSGBUF_TYPE_COMMAND;
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0);
+
+ // Acquire the msgbuf
+ msgbuf_pool_acquire(msgbuf);
+ EXPECT_EQ(msgbuf->refs, 1u);
+
+ // Release the msgbuf
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+ EXPECT_EQ(msgbuf, nullptr);
+}
+
+TEST_F(MsgbufPoolTest, ReleaseNotAcquiredMsgbuf) {
+ msgbuf_t *msgbuf = NULL;
+
+ // Get valid msgbuf from msgbuf_pool
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ msgbuf->type = MSGBUF_TYPE_COMMAND;
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0);
+
+#ifndef NDEBUG
+ // Release the msgbuf even if it is not been acquired
+ ASSERT_DEATH(
+ {
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+ ;
+ },
+ ".*Assertion.*");
+#endif
+}
+
+TEST_F(MsgbufPoolTest, MultipleAcquireAndReleaseMsgbuf) {
+ msgbuf_t *msgbuf = NULL;
+
+ // Get msgbuf from msgbuf_pool
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ msgbuf->type = MSGBUF_TYPE_COMMAND;
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0);
+
+ // Acquire the msgbuf multiple times
+ msgbuf_pool_acquire(msgbuf);
+ msgbuf_pool_acquire(msgbuf);
+ EXPECT_EQ(msgbuf->refs, 2u);
+
+ // Release the msgbuf
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_EQ(msgbuf->refs, 1u);
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+ EXPECT_EQ(msgbuf, nullptr);
+}
+
+TEST_F(MsgbufPoolTest, CloneMsgbuf) {
+ msgbuf_t *msgbuf = NULL;
+ off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf);
+ msgbuf->type = MSGBUF_TYPE_COMMAND;
+ EXPECT_NE(msgbuf, nullptr);
+ EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0);
+
+ msgbuf_t *new_msgbuf;
+ off_t new_msg_id = msgbuf_pool_clone(msgbuf_pool, &new_msgbuf, msgbuf_id);
+
+ EXPECT_EQ(new_msgbuf, msgbuf_pool_at(msgbuf_pool, new_msg_id));
+ EXPECT_NE(new_msgbuf, msgbuf_pool_at(msgbuf_pool, msgbuf_id));
+ EXPECT_NE(new_msgbuf, msgbuf);
+ EXPECT_TRUE(memcmp(msgbuf, new_msgbuf, sizeof(msgbuf_t)) == 0);
+}
diff --git a/hicn-light/src/hicn/test/test-nexthops.cc b/hicn-light/src/hicn/test/test-nexthops.cc
new file mode 100644
index 000000000..9063298fd
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-nexthops.cc
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/core/nexthops.h>
+#include <hicn/core/strategy.h>
+}
+
+#define NEXTHOP1 50
+#define NEXTHOP2 51
+#define NEXTHOP3 52
+
+class NexthopsTest : public ::testing::Test {
+ protected:
+ NexthopsTest() {}
+
+ virtual ~NexthopsTest() {}
+
+ nexthops_t nexthops;
+};
+
+TEST_F(NexthopsTest, NexthopsAdd) {
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 1);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+}
+
+TEST_F(NexthopsTest, NexthopsRemove) {
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ nexthops_remove(&nexthops, NEXTHOP2);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 2);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ nexthops_remove(&nexthops, NEXTHOP3);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 1);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ nexthops_remove(&nexthops, NEXTHOP3);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 1);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ nexthops_remove(&nexthops, NEXTHOP1);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 0);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+}
+
+TEST_F(NexthopsTest, NexthopsClear) {
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ nexthops_clear(&nexthops);
+
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 0);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+}
+
+TEST_F(NexthopsTest, NexthopsGetOne) {
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+
+ unsigned nexthop = nexthops_get_one(&nexthops);
+
+ EXPECT_TRUE(nexthops_contains(&nexthops, nexthop));
+}
+
+TEST_F(NexthopsTest, NexthopsSelect) {
+ int ret;
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+
+ ret = nexthops_select(&nexthops, 2);
+
+ EXPECT_TRUE(ret == 0);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 1);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ ret = nexthops_select(&nexthops, 0);
+
+ EXPECT_TRUE(ret == 0);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 1);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ nexthops_reset(&nexthops);
+
+ EXPECT_TRUE(ret == 0);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ ret = nexthops_select(&nexthops, 4);
+
+ EXPECT_TRUE(ret == -1);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ ret = nexthops_select(&nexthops, 3);
+
+ EXPECT_TRUE(ret == -1);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+}
+
+TEST_F(NexthopsTest, NexthopsDisable) {
+ int ret;
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+
+ ret = nexthops_disable(&nexthops, 0);
+
+ EXPECT_TRUE(ret == 0);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 2);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ ret = nexthops_disable(&nexthops, 2);
+
+ EXPECT_TRUE(ret == 0);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 1);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ ret = nexthops_disable(&nexthops, 3);
+ EXPECT_TRUE(ret == -1);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 3);
+ EXPECT_TRUE(nexthops_get_curlen(&nexthops) == 1);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP3));
+}
+
+TEST_F(NexthopsTest, NexthopsState) {
+ strategy_nexthop_state_t state;
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP2);
+ nexthops_add(&nexthops, NEXTHOP3);
+ nexthops.state[0].load_balancer.pi = 100;
+ nexthops.state[1].load_balancer.pi = 200;
+ nexthops.state[2].load_balancer.pi = 300;
+
+ state = nexthops_state(&nexthops, 0);
+ EXPECT_TRUE(state.load_balancer.pi == 100);
+
+ state = nexthops_state(&nexthops, 1);
+ EXPECT_TRUE(state.load_balancer.pi == 200);
+
+ state = nexthops_state(&nexthops, 2);
+ EXPECT_TRUE(state.load_balancer.pi == 300);
+
+ nexthops_remove(&nexthops, NEXTHOP1);
+ EXPECT_TRUE(nexthops_get_len(&nexthops) == 2);
+ EXPECT_FALSE(nexthops_contains(&nexthops, NEXTHOP1));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP2));
+ EXPECT_TRUE(nexthops_contains(&nexthops, NEXTHOP3));
+
+ state = nexthops_state(&nexthops, 0);
+ EXPECT_TRUE(state.load_balancer.pi == 300);
+
+ state = nexthops_state(&nexthops, 1);
+ EXPECT_TRUE(state.load_balancer.pi == 200);
+}
+
+TEST_F(NexthopsTest, NexthopsEqual) {
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_t nexthops_eq = NEXTHOPS_EMPTY;
+ nexthops_t nexthops_not_eq = NEXTHOPS_EMPTY;
+
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP3);
+ nexthops_add(&nexthops_eq, NEXTHOP1);
+ nexthops_add(&nexthops_eq, NEXTHOP3);
+ nexthops_add(&nexthops_not_eq, NEXTHOP2);
+
+ bool ret = nexthops_equal(&nexthops, &nexthops_eq);
+ EXPECT_TRUE(ret);
+
+ ret = nexthops_equal(&nexthops, &nexthops_not_eq);
+ EXPECT_FALSE(ret);
+}
+
+TEST_F(NexthopsTest, NexthopsCopy) {
+ nexthops = NEXTHOPS_EMPTY;
+ nexthops_t nexthops_eq = NEXTHOPS_EMPTY;
+
+ nexthops_add(&nexthops, NEXTHOP1);
+ nexthops_add(&nexthops, NEXTHOP3);
+ nexthops_copy(&nexthops, &nexthops_eq);
+
+ bool ret = nexthops_equal(&nexthops, &nexthops_eq);
+ EXPECT_TRUE(ret);
+}
diff --git a/hicn-light/src/hicn/test/test-packet_cache.cc b/hicn-light/src/hicn/test/test-packet_cache.cc
new file mode 100644
index 000000000..bb24daeb8
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-packet_cache.cc
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <thread>
+#include <optional>
+
+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;
+
+class PacketCacheTest : public ::testing::Test {
+ protected:
+ PacketCacheTest() {
+ pkt_cache = pkt_cache_create(CS_SIZE);
+ name = (Name *)malloc(sizeof(Name));
+ name_CreateFromAddress(name, AF_INET, IPV4_ANY, IPV4_LEN);
+ msgbuf_pool = msgbuf_pool_create();
+ }
+ virtual ~PacketCacheTest() {
+ pkt_cache_free(pkt_cache);
+ msgbuf_pool_free(msgbuf_pool);
+ }
+
+ 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, CreatePacketCache) {
+ // Check packet cache allocation
+ EXPECT_NE(pkt_cache, nullptr);
+ pit_t *pit = pkt_cache_get_pit(pkt_cache);
+ ASSERT_NE(pit, nullptr);
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ ASSERT_NE(cs, nullptr);
+
+ // Check sizes
+ ASSERT_EQ(pkt_cache_get_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+}
+
+TEST_F(PacketCacheTest, AddPacketCacheEntry) {
+ // Add entry to the packet cache
+ entry = pkt_cache_allocate(pkt_cache, name);
+ 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));
+}
+
+TEST_F(PacketCacheTest, GetCS) {
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ ASSERT_NE(cs, nullptr);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ EXPECT_EQ(cs->type, CS_TYPE_LRU);
+ EXPECT_EQ(cs->num_entries, 0);
+ EXPECT_EQ(cs->lru.head, (off_t)INVALID_ENTRY_ID);
+ EXPECT_EQ(cs->lru.tail, (off_t)INVALID_ENTRY_ID);
+}
+
+TEST_F(PacketCacheTest, GetPIT) {
+ pit_t *pit = pkt_cache_get_pit(pkt_cache);
+ ASSERT_NE(pit, nullptr);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+}
+
+TEST_F(PacketCacheTest, LookupEmpty) {
+ 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_EQ(lookup_result, PKT_CACHE_LU_NONE);
+ EXPECT_EQ(entry, nullptr);
+}
+
+TEST_F(PacketCacheTest, AddEntryAndLookup) {
+ // Add entry to the packet cache
+ entry = pkt_cache_allocate(pkt_cache, name);
+ entry->entry_type = PKT_CACHE_PIT_TYPE;
+ ASSERT_NE(entry, nullptr);
+
+ // Perform lookup
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+
+ EXPECT_TRUE(lookup_result == PKT_CACHE_LU_INTEREST_NOT_EXPIRED ||
+ lookup_result == PKT_CACHE_LU_INTEREST_EXPIRED);
+ EXPECT_NE(lu_entry, nullptr);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+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);
+ 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);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+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);
+ cs_entry_t *cs_entry = &entry->u.cs_entry;
+ ASSERT_NE(entry, nullptr);
+ EXPECT_EQ(entry->entry_type, PKT_CACHE_CS_TYPE);
+ EXPECT_EQ(cs_entry->msgbuf_id, MSGBUF_ID);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 1u);
+
+ // Check if CS properly updated
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ EXPECT_EQ(cs->num_entries, 1);
+ EXPECT_EQ(cs->lru.head, entry_id);
+ EXPECT_EQ(cs->lru.tail, entry_id);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+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);
+ 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);
+
+ // Check if entry properly updated
+ pkt_cache_pit_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, MSGBUF_ID,
+ entry_id);
+ cs_entry_t *cs_entry = &entry->u.cs_entry;
+ ASSERT_NE(entry, nullptr);
+ EXPECT_EQ(entry->entry_type, PKT_CACHE_CS_TYPE);
+ EXPECT_EQ(cs_entry->msgbuf_id, MSGBUF_ID);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 1u);
+
+ // Check if CS properly updated
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ EXPECT_EQ(cs->num_entries, 1);
+ EXPECT_EQ(cs->lru.head, entry_id);
+ EXPECT_EQ(cs->lru.tail, entry_id);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+TEST_F(PacketCacheTest, CsToPIT) {
+ // Prepare msgbuf and CS entry
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ 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);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 1u);
+
+ // Check if entry properly updated
+ pkt_cache_cs_to_pit(pkt_cache, entry, msgbuf_pool, msgbuf, MSGBUF_ID,
+ 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);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+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);
+ 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);
+
+ // Check if entry properly updated
+ pkt_cache_update_pit(pkt_cache, entry, new_msgbuf);
+ 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_2), true);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+TEST_F(PacketCacheTest, UpdateInCS) {
+ // Prepare msgbuf and CS entry
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ 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);
+
+ // Check if entry properly updated
+ pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, new_msgbuf, MSGBUF_ID_2);
+ cs_entry_t *cs_entry = &entry->u.cs_entry;
+ ASSERT_NE(entry, nullptr);
+ EXPECT_EQ(entry->entry_type, PKT_CACHE_CS_TYPE);
+ EXPECT_EQ(cs_entry->msgbuf_id, MSGBUF_ID_2);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 1u);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+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);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ pkt_cache_pit_remove_entry(pkt_cache, entry, name);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE);
+ EXPECT_EQ(lu_entry, nullptr);
+}
+
+TEST_F(PacketCacheTest, RemoveFromCS) {
+ // Prepare msgbuf and CS entry
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ 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);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 1u);
+
+ pkt_cache_cs_remove_entry(pkt_cache, entry, msgbuf_pool, false);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // Check if CS properly updated
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ EXPECT_EQ(cs->num_entries, 0);
+ EXPECT_EQ(cs->lru.head, (off_t)INVALID_ENTRY_ID);
+ EXPECT_EQ(cs->lru.tail, (off_t)INVALID_ENTRY_ID);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE);
+ EXPECT_EQ(lu_entry, nullptr);
+}
+
+TEST_F(PacketCacheTest, AddTwoEntriesToCS) {
+ // Prepare msgbufs
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ 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);
+
+ pkt_cache_entry_t *entry_1 =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ pkt_cache_entry_t *entry_2 =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, new_msgbuf, MSGBUF_ID_2);
+ off_t entry_id_1 = pkt_cache_get_entry_id(pkt_cache, entry_1);
+ off_t entry_id_2 = pkt_cache_get_entry_id(pkt_cache, entry_2);
+
+ // Check if the CS and LRU cache are properly updated
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+ EXPECT_EQ(cs->num_entries, 2);
+ EXPECT_EQ(cs->lru.head, entry_id_2);
+ EXPECT_EQ(cs->lru.tail, entry_id_1);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 2u);
+}
+
+TEST_F(PacketCacheTest, AggregateInPIT) {
+ // Prepare msgbufs
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ 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);
+
+ // 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);
+ 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);
+ Ticks new_lifetime = entry->expire_ts;
+
+ ASSERT_NE(entry, nullptr);
+ EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE);
+ EXPECT_GT(new_lifetime, old_lifetime);
+ ASSERT_EQ(is_aggregated, true);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+TEST_F(PacketCacheTest, RetransmissionInPIT) {
+ // Prepare msgbufs (using same connection ID)
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ 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);
+
+ // 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);
+ 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);
+ Ticks new_lifetime = entry->expire_ts;
+
+ ASSERT_NE(entry, nullptr);
+ EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE);
+ EXPECT_GT(new_lifetime, old_lifetime);
+ ASSERT_EQ(is_aggregated, false);
+
+ // Check if hashtable correctly updated
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *lu_entry = pkt_cache_lookup(
+ pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED);
+ EXPECT_EQ(lu_entry, entry);
+}
+
+TEST_F(PacketCacheTest, LookupExpiredInterest) {
+ // Prepare msgbuf with 0 as interest lifetime
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name, 0);
+
+ // Add to PIT
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ ASSERT_NE(entry, nullptr);
+
+ // Wait to make the interest expire
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id,
+ true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_EXPIRED);
+}
+
+TEST_F(PacketCacheTest, LookupExpiredData) {
+ // Prepare msgbuf with 0 as data expiry time
+ msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name, 0);
+
+ // Add to CS
+ pkt_cache_entry_t *entry =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ ASSERT_NE(entry, nullptr);
+
+ // Wait to make the interest expire
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id,
+ true);
+ EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_EXPIRED);
+}
+
+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);
+ 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);
+ 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);
+ 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);
+ EXPECT_EQ(num_stale_entries, 2u);
+}
+
+TEST_F(PacketCacheTest, GetMultipleStaleEntries) {
+ ip_address_t addr;
+ char name[30];
+ const int NUM_STALES = 10;
+
+ // Add to CS multiple msgbufs with immediate expiration (i.e. 0 seconds),
+ // resulting in stale entries
+ for (int i = 0; i < NUM_STALES; i++) {
+ snprintf(name, 30, "b001::%d", i);
+ 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);
+
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i);
+ }
+
+ // Add to CS multiple msgbufs with 5-seconds expiration,
+ // resulting in non-stale entries
+ for (int i = NUM_STALES; i < 15; i++) {
+ snprintf(name, 30, "b001::%d", i);
+ 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);
+
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i);
+ }
+
+ size_t num_stale_entries = pkt_cache_get_num_cs_stale_entries(pkt_cache);
+ EXPECT_EQ(num_stale_entries, (size_t)NUM_STALES);
+}
diff --git a/hicn-light/src/hicn/test/test-parser.cc b/hicn-light/src/hicn/test/test-parser.cc
new file mode 100644
index 000000000..3a8d2cdb2
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-parser.cc
@@ -0,0 +1,71 @@
+/*
+ * 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/util/log.h>
+#include <hicn/config/parse.h>
+}
+
+class ParserTest : public ::testing::Test {
+ protected:
+ ParserTest() { log_conf.log_level = LOG_INFO; }
+ virtual ~ParserTest() {}
+
+ hc_command_t command_ = {};
+};
+
+TEST_F(ParserTest, AddValidListener) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0";
+
+ ASSERT_EQ(parse(cmd.c_str(), &command_), 0);
+ EXPECT_EQ(command_.object.listener.type, FACE_TYPE_UDP_LISTENER);
+ EXPECT_EQ(std::string(command_.object.listener.name), "udp0");
+ EXPECT_EQ(command_.object.listener.family, AF_INET);
+ EXPECT_EQ(command_.object.listener.local_port, 9695);
+ EXPECT_EQ(std::string(command_.object.listener.interface_name), "eth0");
+}
+
+TEST_F(ParserTest, AddListenerSymbolicOverflow) {
+ std::string cmd =
+ "add listener udp super-long-symbolic-name 10.0.0.1 9696 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), -1);
+}
+
+TEST_F(ParserTest, AddListenerInvalidAddress) {
+ std::string cmd = "add listener udp udp0 10.0.0.0.1 9696 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), -1);
+}
+
+TEST_F(ParserTest, AddListenerInvalidAddressString) {
+ std::string cmd = "add listener udp udp0 invalid-addr 9696 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), -1);
+}
+
+TEST_F(ParserTest, AddListenerInvalidPortOutsideRange) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 0 eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), -1);
+}
+
+TEST_F(ParserTest, AddListenerInvalidPortString) {
+ std::string cmd = "add listener udp udp0 10.0.0.1 invalid-port eth0";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), -1);
+}
+
+TEST_F(ParserTest, UnknownCommnad) {
+ std::string cmd = "add face";
+ ASSERT_EQ(parse(cmd.c_str(), &command_), -1);
+} \ 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
new file mode 100644
index 000000000..c631415ca
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-pool.cc
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <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/pool.h>
+}
+
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+
+class PoolTest : public ::testing::Test {
+ protected:
+ PoolTest() {}
+ virtual ~PoolTest() {}
+
+ int *pool;
+};
+
+TEST_F(PoolTest, PoolAllocation) {
+ int rc;
+
+ pool_init(pool, DEFAULT_SIZE, 0);
+
+ size_t pool_size = next_pow2(DEFAULT_SIZE);
+
+ EXPECT_EQ(pool_get_alloc_size(pool), pool_size);
+
+ /* Check that free indices and bitmaps are correctly initialize */
+ off_t *fi = pool_get_free_indices(pool);
+ EXPECT_EQ(vector_len(fi), pool_size);
+ EXPECT_EQ(fi[0], (long)(pool_size - 1));
+ EXPECT_EQ(fi[pool_size - 1], 0);
+
+ /* The allocated size of the underlying vector should be the next power of two
+ */
+ EXPECT_EQ(vector_get_alloc_size(fi), pool_size);
+
+ bitmap_t *fb = pool_get_free_bitmap(pool);
+ EXPECT_TRUE(bitmap_is_set(fb, 0));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size - 2));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size - 1));
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size));
+
+ /* Getting elements from the pool should correctly update the free indices
+ * and bitmap */
+ int *elt;
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), pool_size - 1);
+ EXPECT_TRUE(bitmap_is_unset(fb, 0));
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), pool_size - 2);
+ EXPECT_TRUE(bitmap_is_unset(fb, 1));
+
+ for (unsigned i = 0; i < pool_size - 4; i++) {
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ }
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), 1UL);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 2));
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), 0UL);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
+
+ /*
+ * Getting elements within the allocated range should not have triggered a
+ * resize
+ */
+ EXPECT_EQ(pool_len(pool), pool_size);
+
+ /*
+ * Getting elements once the allocated range has been exceeded should
+ * trigger a resize
+ */
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+
+ EXPECT_EQ(pool_get_alloc_size(pool), pool_size * 2);
+
+ EXPECT_EQ(pool_len(pool), pool_size + 1);
+
+ /*
+ * Doubling the size, we should have again pool_size elements free, minus 1
+ */
+ EXPECT_EQ(pool_get_free_indices_size(pool), pool_size - 1);
+
+ /*
+ * NOTE: this is wrong as there has been a realloc and the old fi
+ * pointer is now invalid
+ */
+ // EXPECT_EQ(vector_len(fi), pool_size - 1);
+
+ /* And the bitmap should also be correctly modified */
+ fb = pool_get_free_bitmap(pool);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size));
+
+ /* Check that surrounding values are also correct */
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size + 1));
+
+ /* Setting elements after should through */
+
+ /* Check that free indices and bitmaps are correctly updated */
+
+ pool_free(pool);
+}
+
+TEST_F(PoolTest, PoolPut) {
+ pool_init(pool, DEFAULT_SIZE, 0);
+
+ int *elt;
+ pool_get(pool, elt);
+ *elt = 10;
+ pool_put(pool, elt);
+
+ pool_free(pool);
+}
+
+TEST_F(PoolTest, PoolGetForceBitmapRealloc) {
+ const int N = 64;
+ int *elts[N];
+ int *elt = NULL;
+ pool_init(pool, N, 0);
+
+ for (int i = 0; i < N; i++) pool_get(pool, elts[i]);
+ pool_get(pool, elt);
+
+ pool_free(pool);
+}
+
+TEST_F(PoolTest, PoolGetAfterReleasing) {
+ int *elt1 = NULL, *elt2 = NULL, *tmp = NULL;
+ pool_init(pool, DEFAULT_SIZE, 0);
+
+ // If two elements are requested...
+ off_t id1 = pool_get(pool, elt1);
+ pool_get(pool, tmp);
+
+ // ...and the first one is released...
+ pool_put(pool, elt1);
+
+ // ...requesting a new one should return
+ // the first one (that was freed)
+ off_t id2 = pool_get(pool, elt2);
+ EXPECT_EQ(id1, id2);
+ EXPECT_EQ(elt1, elt2);
+
+ pool_free(pool);
+}
+
+TEST_F(PoolTest, PoolGetMultipleElementsAfterReleasing) {
+ const int N = 2;
+ int *elts[N];
+ pool_init(pool, N, 0);
+
+ for (int i = 0; i < N; i++) pool_get(pool, elts[i]);
+ for (int i = 0; i < N; i++) pool_put(pool, elts[i]);
+ for (int i = 0; i < N; i++) pool_get(pool, elts[i]);
+
+ pool_free(pool);
+}
diff --git a/hicn-light/src/hicn/test/test-probe_generator.cc b/hicn-light/src/hicn/test/test-probe_generator.cc
new file mode 100644
index 000000000..4d6cfa8f7
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-probe_generator.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/strategies/probe_generator.h>
+}
+
+class ProbeGeneratorTest : public ::testing::Test {
+ protected:
+ ProbeGeneratorTest() {}
+
+ virtual ~ProbeGeneratorTest() {}
+};
+
+TEST_F(ProbeGeneratorTest, ProbeGeneratorRegisterProbe) {
+ probe_generator_t *pg = create_probe_generator();
+ EXPECT_FALSE(pg == nullptr);
+
+ register_probe(pg, 1);
+ register_probe(pg, 2);
+ register_probe(pg, 3);
+ register_probe(pg, 4);
+
+ Ticks t = get_probe_send_time(pg, 1);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 2);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 3);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 4);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 5);
+ EXPECT_FALSE(t != 0);
+
+ destroy_probe_generator(pg);
+}
+
+TEST_F(ProbeGeneratorTest, ProbeGeneratorTime) {
+ probe_generator_t *pg = create_probe_generator();
+ EXPECT_FALSE(pg == nullptr);
+
+ Ticks t1 = register_probe(pg, 1);
+ Ticks t2 = get_probe_send_time(pg, 1);
+
+ EXPECT_TRUE(t2 != 0);
+ EXPECT_TRUE(t1 == t2);
+
+ destroy_probe_generator(pg);
+}
+
+TEST_F(ProbeGeneratorTest, ProbeGeneratorDeleteProbe) {
+ probe_generator_t *pg = create_probe_generator();
+ EXPECT_FALSE(pg == nullptr);
+
+ register_probe(pg, 1);
+ register_probe(pg, 2);
+ register_probe(pg, 3);
+ register_probe(pg, 4);
+
+ Ticks t = get_probe_send_time(pg, 1);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 2);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 3);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 4);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 5);
+ EXPECT_FALSE(t != 0);
+
+ delete_probe(pg, 1);
+ delete_probe(pg, 3);
+
+ t = get_probe_send_time(pg, 1);
+ EXPECT_FALSE(t != 0);
+
+ t = get_probe_send_time(pg, 3);
+ EXPECT_FALSE(t != 0);
+
+ destroy_probe_generator(pg);
+}
+
+TEST_F(ProbeGeneratorTest, ProbeGeneratorDeleteAll) {
+ probe_generator_t *pg = create_probe_generator();
+ EXPECT_FALSE(pg == nullptr);
+
+ register_probe(pg, 1);
+ register_probe(pg, 2);
+ register_probe(pg, 3);
+ register_probe(pg, 4);
+
+ Ticks t = get_probe_send_time(pg, 1);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 2);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 3);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 4);
+ EXPECT_TRUE(t != 0);
+
+ t = get_probe_send_time(pg, 5);
+ EXPECT_FALSE(t != 0);
+
+ delete_all_probes(pg);
+
+ t = get_probe_send_time(pg, 1);
+ EXPECT_FALSE(t != 0);
+
+ t = get_probe_send_time(pg, 2);
+ EXPECT_FALSE(t != 0);
+
+ t = get_probe_send_time(pg, 3);
+ EXPECT_FALSE(t != 0);
+
+ t = get_probe_send_time(pg, 4);
+ EXPECT_FALSE(t != 0);
+
+ destroy_probe_generator(pg);
+}
diff --git a/hicn-light/src/hicn/test/test-ring.cc b/hicn-light/src/hicn/test/test-ring.cc
new file mode 100644
index 000000000..51f1f5327
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-ring.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <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/ring.h>
+}
+
+#define DEFAULT_SIZE 10UL
+
+class RingTest : public ::testing::Test {
+ protected:
+ RingTest() { ring_init(ring, DEFAULT_SIZE); }
+ virtual ~RingTest() { ring_free(ring); }
+
+ int *ring = NULL;
+};
+
+/* TEST: Ring allocation and initialization */
+TEST_F(RingTest, RingAddOne) {
+ int val = -1;
+ /* Allocated size should be the next power of two */
+ EXPECT_EQ(ring_get_size(ring), 0UL);
+ ring_add_value(ring, 1);
+ EXPECT_EQ(ring_get_size(ring), 1UL);
+ ring_get(ring, 0, &val);
+ EXPECT_EQ(val, 1);
+ EXPECT_EQ(ring_get_size(ring), 1UL);
+ ring_advance(ring, 1);
+ EXPECT_EQ(ring_get_size(ring), 0UL);
+}
+
+TEST_F(RingTest, RingAddMany) {
+ size_t i = 0;
+ int val = -1;
+ size_t count = 0;
+
+ /* Allocated size should be the next power of two */
+ EXPECT_EQ(ring_get_size(ring), 0UL);
+ for (unsigned i = 0; i < DEFAULT_SIZE; i++) ring_add_value(ring, i);
+ EXPECT_EQ(ring_get_size(ring), DEFAULT_SIZE);
+
+ count = 0;
+ ring_enumerate_n(ring, i, &val, 1, {
+ EXPECT_EQ(val, (int)(i));
+ count++;
+ });
+ EXPECT_EQ(count, 1UL);
+
+ count = 0;
+ ring_enumerate_n(ring, i, &val, DEFAULT_SIZE, {
+ EXPECT_EQ(val, (int)(i));
+ count++;
+ });
+ EXPECT_EQ(count, DEFAULT_SIZE);
+
+ count = 0;
+ ring_enumerate_n(ring, i, &val, DEFAULT_SIZE + 1, {
+ EXPECT_EQ(val, (int)(i));
+ count++;
+ });
+ EXPECT_EQ(count, DEFAULT_SIZE);
+
+ // Drop one
+ ring_add_value(ring, DEFAULT_SIZE);
+ EXPECT_EQ(ring_get_size(ring), DEFAULT_SIZE);
+
+ count = 0;
+ ring_enumerate_n(ring, i, &val, DEFAULT_SIZE, {
+ EXPECT_EQ(val, (int)(i + 1)); // all values shoud be shifted
+ count++;
+ });
+ EXPECT_EQ(count, DEFAULT_SIZE);
+
+ ring_advance(ring, DEFAULT_SIZE);
+ EXPECT_EQ(ring_get_size(ring), 0UL);
+}
diff --git a/hicn-light/src/hicn/test/test-strategy-best-path.cc b/hicn-light/src/hicn/test/test-strategy-best-path.cc
new file mode 100644
index 000000000..327c47144
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-strategy-best-path.cc
@@ -0,0 +1,107 @@
+/*
+ * 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/core/strategy.h>
+#include <hicn/strategies/best_path.h>
+}
+
+#define MAX_TESTS 10
+
+#define NEXTHOP_ID1 NEXTHOP(28)
+#define NEXTHOP_ID2 NEXTHOP(29)
+#define UNKNOWN_ID1 NEXTHOP(0)
+#define UNKNOWN_ID2 NEXTHOP(1)
+
+class StrategyBestpathTest : public ::testing::Test {
+ protected:
+ StrategyBestpathTest() {
+ /* Strategy and strategy entry */
+ entry = {
+ .type = STRATEGY_TYPE_BESTPATH,
+ .options =
+ {
+ .bestpath = {},
+ },
+ .state = {.bestpath = {}},
+ };
+
+ strategy_initialize(&entry, nullptr);
+
+ // test init
+ EXPECT_EQ(entry.forwarder, nullptr);
+ EXPECT_EQ(entry.state.bestpath.best_nexthop, (unsigned)~0);
+ EXPECT_EQ(entry.state.bestpath.probing_state, PROBING_OFF);
+
+ /* Available nexthops */
+ available_nexthops_ = NEXTHOPS_EMPTY;
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)0);
+
+ /* Message buffer */
+ msgbuf_ = NULL;
+ ticks_ = ticks_now();
+ }
+
+ virtual ~StrategyBestpathTest() {}
+
+ strategy_entry_t entry;
+ nexthops_t available_nexthops_;
+ msgbuf_t *msgbuf_;
+ Ticks ticks_;
+};
+
+TEST_F(StrategyBestpathTest, emptyNexthop) {
+ nexthops_t *nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)0);
+}
+
+TEST_F(StrategyBestpathTest, faceExists) {
+ nexthops_t *nexthops;
+
+ nexthops_add(&available_nexthops_, NEXTHOP_ID1);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ nexthops_add(&available_nexthops_, NEXTHOP_ID2);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)2);
+
+ entry.state.bestpath.probing_state = PROBING_OFF;
+ entry.state.bestpath.best_nexthop = NEXTHOP_ID2;
+
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID2));
+ EXPECT_FALSE(nexthops_contains(nexthops, NEXTHOP_ID1));
+
+ EXPECT_TRUE(entry.state.bestpath.probing_state == PROBING_OFF);
+ EXPECT_EQ(entry.state.bestpath.best_nexthop, NEXTHOP_ID2);
+}
diff --git a/hicn-light/src/hicn/test/test-strategy-load-balancing.cc b/hicn-light/src/hicn/test/test-strategy-load-balancing.cc
new file mode 100644
index 000000000..edac5669f
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-strategy-load-balancing.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.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/core/strategy.h>
+#include <hicn/strategies/random.h>
+}
+
+#define MAX_TESTS 10
+
+#define NEXTHOP_ID NEXTHOP(28)
+#define NEXTHOP_ID2 NEXTHOP(29)
+#define UNKNOWN_ID1 NEXTHOP(0)
+#define UNKNOWN_ID2 NEXTHOP(1)
+
+class StrategyLoadBalancing : public ::testing::Test {
+ protected:
+ StrategyLoadBalancing() {
+ /* Strategy and strategy entry */
+ entry = {
+ .type = STRATEGY_TYPE_LOADBALANCER,
+ .options =
+ {
+ .random = {},
+ },
+ .state = {.random = {}},
+ };
+
+ strategy_initialize(&entry, nullptr);
+
+ /* Available nexthops */
+ available_nexthops_ = NEXTHOPS_EMPTY;
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)0);
+
+ /* Message buffer */
+ msgbuf_ = NULL;
+ ticks_ = ticks_now();
+ }
+ virtual ~StrategyLoadBalancing() {}
+
+ strategy_entry_t entry;
+ nexthops_t available_nexthops_;
+ msgbuf_t* msgbuf_;
+ Ticks ticks_;
+};
+
+TEST_F(StrategyLoadBalancing, SingleNexthop) {
+ /* Add a single nexthop */
+ off_t id;
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID2));
+
+ /* Lookup */
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID2));
+
+ /* Retrieve candidate */
+
+ unsigned nexthop;
+ for (unsigned i = 0; i < MAX_TESTS; i++) {
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, NEXTHOP_ID);
+ }
+
+ /* Disable (move to nexthop unit tests) */
+ nexthops_disable(nexthops, 0);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)0);
+
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, INVALID_NEXTHOP);
+}
+
+TEST_F(StrategyLoadBalancing, MultipleNexthops) {
+ off_t id, id2;
+ /* Add a single nexthop */
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID);
+ id2 = nexthops_add(&available_nexthops_, NEXTHOP_ID2);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)2);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ strategy_add_nexthop(&entry, &available_nexthops_, id2);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)2);
+
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID));
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID2));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID2));
+
+ /* Lookup */
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+
+ EXPECT_TRUE((nexthops_contains(nexthops, NEXTHOP_ID)) ||
+ (nexthops_contains(nexthops, NEXTHOP_ID2)));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID2));
+
+ /* Retrieve candidate */
+
+ unsigned nexthop;
+ for (unsigned i = 0; i < MAX_TESTS; i++) {
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_TRUE((nexthop == NEXTHOP_ID) || (nexthop == NEXTHOP_ID2));
+ }
+}
diff --git a/hicn-light/src/hicn/test/test-strategy-random.cc b/hicn-light/src/hicn/test/test-strategy-random.cc
new file mode 100644
index 000000000..bd9b70120
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-strategy-random.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.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/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+#include <hicn/strategies/random.h>
+}
+
+#define MAX_TESTS 10
+
+#define NEXTHOP_ID NEXTHOP(28)
+#define UNKNOWN_ID1 NEXTHOP(0)
+#define UNKNOWN_ID2 NEXTHOP(1)
+
+class StrategyRandomTest : public ::testing::Test {
+ protected:
+ StrategyRandomTest() {
+ /* Strategy and strategy entry */
+ entry = {
+ .type = STRATEGY_TYPE_RANDOM,
+ .options =
+ {
+ .random = {},
+ },
+ .state = {.random = {}},
+ };
+
+ strategy_initialize(&entry, nullptr);
+
+ /* Available nexthops */
+ available_nexthops_ = NEXTHOPS_EMPTY;
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)0);
+
+ /* Message buffer */
+ msgbuf_ = NULL;
+ ticks_ = ticks_now();
+ }
+ virtual ~StrategyRandomTest() {}
+
+ strategy_entry_t entry;
+ nexthops_t available_nexthops_;
+ msgbuf_t* msgbuf_;
+ Ticks ticks_;
+};
+
+TEST_F(StrategyRandomTest, SingleNexthop) {
+ off_t id;
+
+ /* Add a single nexthop */
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID2));
+
+ /* Lookup */
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID2));
+
+ /* Retrieve candidate */
+
+ unsigned nexthop;
+ for (unsigned i = 0; i < MAX_TESTS; i++) {
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, NEXTHOP_ID);
+ }
+
+ /* Disable (move to nexthop unit tests) */
+ nexthops_disable(nexthops, 0);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)0);
+
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, INVALID_NEXTHOP);
+}
+
+TEST_F(StrategyRandomTest, MultipleNexthops) {
+ off_t id;
+
+ /* Add a single nexthop */
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID2));
+
+ /* Lookup */
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID2));
+
+ /* Retrieve candidate */
+
+ unsigned nexthop;
+ for (unsigned i = 0; i < MAX_TESTS; i++) {
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, NEXTHOP_ID);
+ }
+}
diff --git a/hicn-light/src/hicn/test/test-strategy-replication.cc b/hicn-light/src/hicn/test/test-strategy-replication.cc
new file mode 100644
index 000000000..ab7dae1f7
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-strategy-replication.cc
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.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/core/strategy.h>
+#include <hicn/strategies/random.h>
+}
+
+#define MAX_TESTS 10
+
+#define NEXTHOP_ID1 NEXTHOP(28)
+#define NEXTHOP_ID2 NEXTHOP(29)
+#define UNKNOWN_ID1 NEXTHOP(0)
+#define UNKNOWN_ID2 NEXTHOP(1)
+
+class StrategyReplicationTest : public ::testing::Test {
+ protected:
+ StrategyReplicationTest() {
+ /* Strategy and strategy entry */
+ entry = {
+ .type = STRATEGY_TYPE_REPLICATION,
+ .options =
+ {
+ .replication = {},
+ },
+ .state = {.replication = {}},
+ };
+
+ strategy_initialize(&entry, nullptr);
+
+ /* Available nexthops */
+ available_nexthops_ = NEXTHOPS_EMPTY;
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)0);
+
+ /* Message buffer */
+ msgbuf_ = NULL;
+ ticks_ = ticks_now();
+ }
+
+ virtual ~StrategyReplicationTest() {}
+
+ strategy_entry_t entry;
+ nexthops_t available_nexthops_;
+ msgbuf_t* msgbuf_;
+ Ticks ticks_;
+};
+
+TEST_F(StrategyReplicationTest, SingleNexthop) {
+ off_t id;
+
+ /* Add a single nexthop */
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID1);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID2));
+
+ /* Lookup */
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID2));
+
+ /* Retrieve candidate */
+
+ unsigned nexthop;
+ for (unsigned i = 0; i < MAX_TESTS; i++) {
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, NEXTHOP_ID1);
+ }
+
+ /* Disable (move to nexthop unit tests) */
+ nexthops_disable(nexthops, 0);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)0);
+
+ nexthop = nexthops_get_one(nexthops);
+ EXPECT_EQ(nexthop, INVALID_NEXTHOP);
+}
+
+TEST_F(StrategyReplicationTest, MultipleNexthops) {
+ off_t id;
+
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID1);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)1);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)1);
+
+ id = nexthops_add(&available_nexthops_, NEXTHOP_ID2);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)2);
+
+ strategy_add_nexthop(&entry, &available_nexthops_, id);
+ EXPECT_EQ(nexthops_get_len(&available_nexthops_), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(&available_nexthops_), (size_t)2);
+
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID1));
+ EXPECT_TRUE(nexthops_contains(&available_nexthops_, NEXTHOP_ID2));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(&available_nexthops_, UNKNOWN_ID2));
+
+ /* Lookup */
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry, &available_nexthops_, msgbuf_);
+
+ EXPECT_EQ(nexthops_get_len(nexthops), (size_t)2);
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)2);
+
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID1));
+ EXPECT_TRUE(nexthops_contains(nexthops, NEXTHOP_ID2));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID1));
+ EXPECT_FALSE(nexthops_contains(nexthops, UNKNOWN_ID2));
+
+ /* Retrieve candidate */
+
+ unsigned nexthop;
+ unsigned tests = 0;
+ nexthops_foreach(nexthops, nexthop, {
+ EXPECT_TRUE(nexthop == NEXTHOP_ID1 || nexthop == NEXTHOP_ID2);
+ tests++;
+ });
+
+ EXPECT_EQ(tests, (unsigned)2);
+}
diff --git a/hicn-light/src/hicn/test/test-subscription.cc b/hicn-light/src/hicn/test/test-subscription.cc
new file mode 100644
index 000000000..18ef60c0d
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-subscription.cc
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C" {
+#include <hicn/core/subscription.h>
+#include <hicn/base/vector.h>
+}
+
+static inline unsigned CONN_ID = 1;
+static inline unsigned CONN_ID_2 = 2;
+
+class SubscriptionTest : public ::testing::Test {
+ protected:
+ SubscriptionTest() { subscriptions = subscription_table_create(); }
+ virtual ~SubscriptionTest() { subscription_table_free(subscriptions); }
+
+ subscription_table_t *subscriptions;
+};
+
+TEST_F(SubscriptionTest, CreateSubscriptionTable) {
+ // Check subscription table allocation
+ ASSERT_NE(subscriptions, nullptr);
+}
+
+TEST_F(SubscriptionTest, SetTopic) {
+ hc_topics_t topics = TOPIC_STRATEGY;
+
+ // Check that only the topic desired has been subscribed to
+ for (int topic = TOPIC_UNDEFINED; topic < TOPIC_N; topic <<= 1) {
+ if (topic == TOPIC_STRATEGY) {
+ EXPECT_TRUE(topics_contains(topics, (hc_topic_t)topic));
+ continue;
+ }
+ EXPECT_FALSE(topics_contains(topics, (hc_topic_t)topic));
+ }
+}
+
+TEST_F(SubscriptionTest, GetObjectFromTopic) {
+ hc_object_type_t object_type = object_from_topic(TOPIC_STRATEGY);
+ EXPECT_EQ(object_type, OBJECT_STRATEGY);
+
+ object_type = object_from_topic(TOPIC_FACE);
+ EXPECT_EQ(object_type, OBJECT_FACE);
+}
+
+TEST_F(SubscriptionTest, AddSubscription) {
+ hc_topics_t topics = TOPIC_STRATEGY;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, topics);
+}
+
+TEST_F(SubscriptionTest, AddAndRemoveSubscriptionForAllTopics) {
+ hc_topics_t topics = ALL_TOPICS;
+ int ret = subscription_table_add_topics_for_connection(subscriptions,
+ ALL_TOPICS, CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ int num_subscriptions_removed =
+ subscription_table_remove_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(num_subscriptions_removed, NUM_TOPICS);
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, 0u);
+}
+
+// Failure while adding subscription cannot be tested since it depends on vector
+// reallocation
+
+TEST_F(SubscriptionTest, AddSubscriptionAlreadyAdded) {
+ hc_topics_t topics = TOPIC_STRATEGY;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ // Subscribe again to same topic
+ ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, -2); // -2 = already-added subscription
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, topics);
+}
+
+TEST_F(SubscriptionTest, GetSubscriptionsForConnectionWithoutSubscriptions) {
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, (hc_topics_t)0);
+}
+
+TEST_F(SubscriptionTest, GetSubscriptionsForConnectionWithMultipleSubs) {
+ hc_topics_t topics = TOPIC_STRATEGY | TOPIC_FACE;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, topics);
+
+ // Add another subscription
+ ret = subscription_table_add_topics_for_connection(subscriptions, TOPIC_PROBE,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, topics |= TOPIC_PROBE);
+}
+
+TEST_F(SubscriptionTest, RemoveSubscription) {
+ // Add subscriptions
+ hc_topics_t topics = TOPIC_STRATEGY | TOPIC_FACE;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ // Remove one of the previously added subscriptions
+ int num_subscriptions_removed =
+ subscription_table_remove_topics_for_connection(subscriptions,
+ TOPIC_STRATEGY, CONN_ID);
+ EXPECT_EQ(num_subscriptions_removed, 1);
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, TOPIC_FACE);
+}
+
+TEST_F(SubscriptionTest, RemoveMultipleSubscriptions) {
+ // Add subscriptions
+ hc_topics_t topics = TOPIC_STRATEGY | TOPIC_FACE | TOPIC_PROBE;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ // Remove two of the previously added subscriptions
+ int num_subscriptions_removed =
+ subscription_table_remove_topics_for_connection(
+ subscriptions, TOPIC_STRATEGY | TOPIC_FACE, CONN_ID);
+ EXPECT_EQ(num_subscriptions_removed, 2);
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, TOPIC_PROBE);
+}
+
+TEST_F(SubscriptionTest, RemoveNonRegistredSubscription) {
+ // Remove a subscription that is not present
+ int num_subscriptions_removed =
+ subscription_table_remove_topics_for_connection(subscriptions,
+ TOPIC_PROBE, CONN_ID);
+ EXPECT_EQ(num_subscriptions_removed, 0);
+
+ // Add two new subscriptions
+ hc_topics_t topics = TOPIC_STRATEGY | TOPIC_FACE;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ // Remove subscription that was not registred previously
+ num_subscriptions_removed = subscription_table_remove_topics_for_connection(
+ subscriptions, TOPIC_PROBE, CONN_ID);
+ EXPECT_EQ(num_subscriptions_removed, 0);
+
+ hc_topics_t topics_ret =
+ subscription_table_get_topics_for_connection(subscriptions, CONN_ID);
+ EXPECT_EQ(topics_ret, topics);
+}
+
+TEST_F(SubscriptionTest, GetConnectionsForSubscription) {
+ // Add subscriptions for two connections
+ hc_topics_t topics = TOPIC_STRATEGY | TOPIC_FACE;
+ int ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ topics = TOPIC_STRATEGY;
+ ret = subscription_table_add_topics_for_connection(subscriptions, topics,
+ CONN_ID_2);
+ EXPECT_EQ(ret, 0); // 0 = success
+
+ // Check the connections associated with the strategy topic
+ unsigned *conn_ids = subscription_table_get_connections_for_topic(
+ subscriptions, TOPIC_STRATEGY);
+ EXPECT_EQ(vector_len(conn_ids), 2u);
+ EXPECT_TRUE(conn_ids[0] == CONN_ID || conn_ids[0] == CONN_ID_2);
+ EXPECT_TRUE(conn_ids[1] == CONN_ID || conn_ids[1] == CONN_ID_2);
+
+ // Check the connections associated with the face topic
+ conn_ids =
+ subscription_table_get_connections_for_topic(subscriptions, TOPIC_FACE);
+ EXPECT_EQ(vector_len(conn_ids), 1u);
+ EXPECT_EQ(conn_ids[0], (unsigned)CONN_ID);
+} \ 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
new file mode 100644
index 000000000..fb30a8228
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-vector.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <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>
+}
+
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+const size_t N_ELEMENTS = 5;
+
+class VectorTest : public ::testing::Test {
+ protected:
+ VectorTest() { vector_init(vector, DEFAULT_SIZE, 0); }
+ virtual ~VectorTest() { vector_free(vector); }
+
+ int *vector = NULL;
+};
+
+/* TEST: Vector allocation and initialization */
+TEST_F(VectorTest, VectorAllocate) {
+ /* 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 */
+ vector_ensure_pos(vector, 15);
+ EXPECT_EQ(vector_get_alloc_size(vector), 16UL);
+
+ /* 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);
+}
+
+TEST_F(VectorTest, VectorCheckValue) {
+ 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);
+}
+
+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);
+
+ // Remove element
+ int value_to_remove = 3;
+ int num_removed = vector_remove_unordered(vector, value_to_remove);
+
+ 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);
+}
+
+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
+
+ // Remove (duplicated) elements
+ int value_to_remove = 3;
+ int num_removed = vector_remove_unordered(vector, value_to_remove);
+
+ 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);
+}
+
+TEST_F(VectorTest, Iterate) {
+ for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i);
+
+ int count = 0;
+ int *elem;
+ vector_foreach(vector, elem, { EXPECT_EQ(*elem, count++); });
+}
+
+TEST_F(VectorTest, MultipleResize) {
+ // Use small vector (size=1) to force multiple realloc operations
+ int *small_vector;
+ vector_init(small_vector, 1, 0);
+
+ 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);
+
+ EXPECT_EQ(vector_len(small_vector), 5UL);
+ EXPECT_EQ(vector_get_alloc_size(small_vector), 8UL);
+
+ vector_free(small_vector);
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/utils/CMakeLists.txt b/hicn-light/src/hicn/utils/CMakeLists.txt
index c8c9b8487..72a918cac 100644
--- a/hicn-light/src/hicn/utils/CMakeLists.txt
+++ b/hicn-light/src/hicn/utils/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,30 +11,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# XXX This is installed in hicn/utils...
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/address.h
- ${CMAKE_CURRENT_SOURCE_DIR}/addressList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/commands.h
- ${CMAKE_CURRENT_SOURCE_DIR}/interface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/commands.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/interface.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.h
${CMAKE_CURRENT_SOURCE_DIR}/punting.h
${CMAKE_CURRENT_SOURCE_DIR}/token.h
- ${CMAKE_CURRENT_SOURCE_DIR}/utils.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/address.c
- ${CMAKE_CURRENT_SOURCE_DIR}/addressList.c
- ${CMAKE_CURRENT_SOURCE_DIR}/interface.c
- ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/interface.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.c
${CMAKE_CURRENT_SOURCE_DIR}/punting.c
- ${CMAKE_CURRENT_SOURCE_DIR}/utils.c
-)
-
-set(TO_INSTALL_HEADER_FILES
- ${TO_INSTALL_HEADER_FILES}
- ${HEADER_FILES}
- PARENT_SCOPE
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/utils/address.c b/hicn-light/src/hicn/utils/address.c
deleted file mode 100644
index 619097e1d..000000000
--- a/hicn-light/src/hicn/utils/address.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/utils/address.h>
-
-#include <parc/algol/parc_Base64.h>
-#include <parc/algol/parc_BufferComposer.h>
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/algol/parc_Object.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct address {
- address_type addressType;
- PARCBuffer *blob;
-};
-
-static struct address_type_str {
- address_type type;
- const char *str;
-} addressTypeString[] = {
- {.type = ADDR_INET, .str = "INET"}, {.type = ADDR_INET6, .str = "INET6"},
- {.type = ADDR_LINK, .str = "LINK"}, {.type = ADDR_IFACE, .str = "IFACE"},
- {.type = ADDR_UNIX, .str = "UNIX"}, {.type = 0, .str = NULL}};
-
-void addressDestroy(Address **addressPtr) {
- parcAssertNotNull(addressPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*addressPtr,
- "Parameter must dereference to non-null pointer");
-
- Address *address = *addressPtr;
- parcBuffer_Release(&address->blob);
- parcMemory_Deallocate((void **)&address);
- *addressPtr = NULL;
-}
-
-void addressAssertValid(const Address *address) {
- parcAssertNotNull(address, "Parameter must be non-null Address *");
-}
-
-const char *addressTypeToString(address_type type) {
- for (int i = 0; addressTypeString[i].str != NULL; i++) {
- if (addressTypeString[i].type == type) {
- return addressTypeString[i].str;
- }
- }
- parcTrapIllegalValue(type, "Unknown value: %d", type);
- const char *result = NULL;
- return result;
-}
-
-address_type addressStringToType(const char *str) {
- for (int i = 0; addressTypeString[i].str != NULL; i++) {
- if (strcasecmp(addressTypeString[i].str, str) == 0) {
- return addressTypeString[i].type;
- }
- }
- parcTrapIllegalValue(str, "Unknown type '%s'", str);
- return 0;
-}
-
-static Address *_addressCreate(address_type addressType, PARCBuffer *buffer) {
- Address *result = parcMemory_AllocateAndClear(sizeof(Address));
-
- parcAssertNotNull(result, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Address));
- if (result != NULL) {
- result->addressType = addressType;
- result->blob = buffer;
- }
- return result;
-}
-
-Address *addressCreateFromInet(struct sockaddr_in *addr_in) {
- parcAssertNotNull(addr_in, "Parameter must be non-null");
-
- addr_in->sin_family = AF_INET;
-
- PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_in));
- parcBuffer_PutArray(buffer, sizeof(struct sockaddr_in), (uint8_t *)addr_in);
- parcBuffer_Flip(buffer);
-
- Address *result = _addressCreate(ADDR_INET, buffer);
-
- return result;
-}
-
-Address *addressCreateFromInet6(struct sockaddr_in6 *addr_in6) {
- parcAssertNotNull(addr_in6, "Parameter must be non-null");
-
- PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_in6));
- parcBuffer_PutArray(buffer, sizeof(struct sockaddr_in6), (uint8_t *)addr_in6);
- parcBuffer_Flip(buffer);
-
- Address *result = _addressCreate(ADDR_INET6, buffer);
-
- return result;
-}
-
-Address *addressFromInaddr4Port(in_addr_t *addr4, in_port_t *port) {
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
-
- // We assume address and port are already written in memory in network byte
- // order
- addr.sin_family = AF_INET;
- addr.sin_port = *port;
- addr.sin_addr.s_addr = *addr4;
-
- Address *result = addressCreateFromInet(&addr);
- return result;
-}
-
-Address *addressFromInaddr6Port(struct in6_addr *addr6, in_port_t *port) {
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
-
- // We assume address and port are already written in memory in network byte
- // order
- addr.sin6_port = *port;
- addr.sin6_addr = *addr6;
- addr.sin6_scope_id = 0;
- // Other 2 fields: scope_id and flowinfo, do not know what to put inside.
-
- Address *result = addressCreateFromInet6(&addr);
- return result;
-}
-
-Address *addressCreateFromLink(const uint8_t *linkaddr, size_t length) {
- parcAssertNotNull(linkaddr, "Parameter must be non-null");
-
- PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_in6));
- parcBuffer_PutArray(buffer, length, linkaddr);
- parcBuffer_Flip(buffer);
-
- Address *result = _addressCreate(ADDR_LINK, buffer);
- return result;
-}
-
-Address *addressCreateFromInterface(unsigned interfaceIndex) {
- unsigned netbyteorder = htonl(interfaceIndex);
-
- PARCBuffer *buffer = parcBuffer_Allocate(sizeof(netbyteorder));
- parcBuffer_PutArray(buffer, sizeof(netbyteorder), (uint8_t *)&netbyteorder);
- parcBuffer_Flip(buffer);
-
- Address *result = _addressCreate(ADDR_IFACE, buffer);
- return result;
-}
-
-Address *addressCreateFromUnix(struct sockaddr_un *addr_un) {
- parcAssertNotNull(addr_un, "Parameter must be non-null");
-
- PARCBuffer *buffer = parcBuffer_Allocate(sizeof(struct sockaddr_un));
- parcBuffer_PutArray(buffer, sizeof(struct sockaddr_un), (uint8_t *)addr_un);
- parcBuffer_Flip(buffer);
-
- Address *result = _addressCreate(ADDR_UNIX, buffer);
- return result;
-}
-
-Address *addressCopy(const Address *original) {
- addressAssertValid(original);
-
- Address *result =
- _addressCreate(original->addressType, parcBuffer_Copy(original->blob));
- return result;
-}
-
-bool addressEquals(const Address *a, const Address *b) {
- if (a == b) {
- return true;
- }
-
- if (a == NULL || b == NULL) {
- return false;
- }
-
- if (a->addressType == b->addressType) {
- if (parcBuffer_Equals(a->blob, b->blob)) {
- return true;
- }
- }
-
- return false;
-}
-
-address_type addressGetType(const Address *address) {
- addressAssertValid(address);
-
- return address->addressType;
-}
-
-// The Get functions need better names, what they do (Get from what? Put to
-// what?) is not clear from their names. Case 1028
-bool addressGetInet(const Address *address, struct sockaddr_in *addr_in) {
- addressAssertValid(address);
- parcAssertNotNull(addr_in, "Parameter addr_in must be non-null");
-
- if (address->addressType == ADDR_INET) {
- parcAssertTrue(
- parcBuffer_Remaining(address->blob) == sizeof(struct sockaddr_in),
- "Address corrupted. Expected length %zu, actual length %zu",
- sizeof(struct sockaddr_in), parcBuffer_Remaining(address->blob));
-
- memcpy(addr_in, parcBuffer_Overlay(address->blob, 0),
- sizeof(struct sockaddr_in));
- return true;
- }
- return false;
-}
-
-bool addressGetInet6(const Address *address, struct sockaddr_in6 *addr_in6) {
- addressAssertValid(address);
- parcAssertNotNull(addr_in6, "Parameter addr_in6 must be non-null");
-
- if (address->addressType == ADDR_INET6) {
- parcAssertTrue(
- parcBuffer_Remaining(address->blob) == sizeof(struct sockaddr_in6),
- "Address corrupted. Expected length %zu, actual length %zu",
- sizeof(struct sockaddr_in6), parcBuffer_Remaining(address->blob));
-
- memcpy(addr_in6, parcBuffer_Overlay(address->blob, 0),
- sizeof(struct sockaddr_in6));
- return true;
- }
- return false;
-}
-
-bool addressGetUnix(const Address *address, struct sockaddr_un *addr_un) {
- addressAssertValid(address);
- parcAssertNotNull(addr_un, "Parameter addr_in6 must be non-null");
-
- if (address->addressType == ADDR_UNIX) {
- parcAssertTrue(
- parcBuffer_Remaining(address->blob) == sizeof(struct sockaddr_un),
- "Address corrupted. Expected length %zu, actual length %zu",
- sizeof(struct sockaddr_un), parcBuffer_Remaining(address->blob));
-
- memcpy(addr_un, parcBuffer_Overlay(address->blob, 0),
- sizeof(struct sockaddr_un));
- return true;
- }
- return false;
-}
-
-bool addressGetInterfaceIndex(const Address *address, uint32_t *ifidx) {
- addressAssertValid(address);
- parcAssertNotNull(ifidx, "Parameter ifidx must be non-null");
-
- if (address->addressType == ADDR_IFACE) {
- parcAssertTrue(parcBuffer_Remaining(address->blob) == sizeof(uint32_t),
- "Address corrupted. Expected length %zu, actual length %zu",
- sizeof(uint32_t), parcBuffer_Remaining(address->blob));
-
- uint32_t netbyteorder;
- memcpy(&netbyteorder, parcBuffer_Overlay(address->blob, 0),
- sizeof(uint32_t));
- *ifidx = ntohl(netbyteorder);
- return true;
- }
- return false;
-}
-
-PARCBuffer *addressGetLinkAddress(const Address *address) {
- addressAssertValid(address);
- if (address->addressType == ADDR_LINK) {
- return address->blob;
- }
- return NULL;
-}
-
-static PARCBufferComposer *_Inet_BuildString(const Address *address,
- PARCBufferComposer *composer) {
- addressAssertValid(address);
-
- struct sockaddr_in *saddr =
- (struct sockaddr_in *)parcBuffer_Overlay(address->blob, 0);
- return parcNetwork_SockInet4Address_BuildString(saddr, composer);
-}
-
-static PARCBufferComposer *_Inet6_BuildString(const Address *address,
- PARCBufferComposer *composer) {
- addressAssertValid(address);
-
- struct sockaddr_in6 *saddr =
- (struct sockaddr_in6 *)parcBuffer_Overlay(address->blob, 0);
- return parcNetwork_SockInet6Address_BuildString(saddr, composer);
-}
-
-static PARCBufferComposer *_Link_BuildString(const Address *address,
- PARCBufferComposer *composer) {
- addressAssertValid(address);
-
- const unsigned char *addr = parcBuffer_Overlay(address->blob, 0);
-
- size_t length = parcBuffer_Remaining(address->blob);
-
- return parcNetwork_LinkAddress_BuildString(addr, length, composer);
-}
-
-static ssize_t _UnixToString(char *output, size_t remaining_size,
- const PARCBuffer *addr) {
- parcAssertNotNull(output, "parameter output must be non-null");
- parcBuffer_AssertValid(addr);
-
- parcAssertTrue(parcBuffer_Remaining(addr) == sizeof(struct sockaddr_un),
- "Address corrupted. Expected %zu actual %zu",
- sizeof(struct sockaddr_un), parcBuffer_Remaining(addr));
-
- // sockaddr length for the path, 16 for the ascii stuff, 3 for the length
- // number
- struct sockaddr_un *saddr =
- (struct sockaddr_un *)parcBuffer_Overlay((PARCBuffer *)addr, 0);
- size_t min_remaining = strlen(saddr->sun_path) + 16 + 3;
- parcAssertTrue(remaining_size >= min_remaining,
- "Remaining size too small, need at least %zu", min_remaining);
-
- ssize_t output_length = sprintf(output, "{ .path=%s, .len=%zu }",
- saddr->sun_path, strlen(saddr->sun_path));
- return output_length;
-}
-
-static ssize_t _IfaceToString(char *output, size_t remaining_size,
- const PARCBuffer *addr) {
- parcAssertNotNull(output, "parameter output must be non-null");
- parcBuffer_AssertValid(addr);
-
- parcAssertTrue(parcBuffer_Remaining(addr) == sizeof(uint32_t),
- "Address corrupted. Expected %zu actual %zu", sizeof(uint32_t),
- parcBuffer_Remaining(addr));
-
- uint32_t *ifidx = (uint32_t *)parcBuffer_Overlay((PARCBuffer *)addr, 0);
-
- ssize_t output_length = sprintf(output, "{ .ifidx=%u }", ntohl(*ifidx));
-
- return output_length;
-}
-
-PARCBufferComposer *addressBuildString(const Address *address,
- PARCBufferComposer *composer) {
- if (address != NULL) {
- char *str = addressToString(address);
- parcBufferComposer_PutString(composer, str);
- parcMemory_Deallocate((void **)&str);
- }
- return composer;
-}
-
-char *addressToString(const Address *address) {
- addressAssertValid(address);
-
- char addrstr[256];
-
- switch (address->addressType) {
- case ADDR_INET: {
- PARCBufferComposer *composer = parcBufferComposer_Create();
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
- _Inet_BuildString(address, composer));
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- parcBufferComposer_Release(&composer);
- return result;
- } break;
-
- case ADDR_INET6: {
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
- _Inet6_BuildString(address, composer));
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
-
- parcBufferComposer_Release(&composer);
- return result;
- } break;
-
- case ADDR_LINK:
- _UnixToString(addrstr, 256, address->blob);
- break;
-
- case ADDR_IFACE: {
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
- _Link_BuildString(address, composer));
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
-
- parcBufferComposer_Release(&composer);
- return result;
- } break;
-
- case ADDR_UNIX:
- _IfaceToString(addrstr, 256, address->blob);
- break;
-
- default:
- sprintf(addrstr, "UNKNOWN type = %d", address->addressType);
- break;
- }
-
- ssize_t alloc_size = 1024;
- char *output = parcMemory_Allocate(alloc_size);
- parcAssertNotNull(output, "parcMemory_Allocate(%zu) returned NULL",
- alloc_size);
- ssize_t output_length =
- snprintf(output, alloc_size, "{ .type=%s, .data=%s }",
- addressTypeToString(address->addressType), addrstr);
-
- parcAssertTrue(output_length < alloc_size,
- "allocated size too small, needed %zd", output_length);
- parcAssertFalse(output_length < 0, "snprintf error: (%d) %s", errno,
- strerror(errno));
-
- return output;
-}
-
-PARCHashCode addressHashCode(const Address *address) {
- addressAssertValid(address);
-
- PARCHashCode hash = parcBuffer_HashCode(address->blob);
- hash = parcHashCode_HashImpl((uint8_t *)&address->addressType,
- sizeof(address->addressType), hash);
-
- return hash;
-}
diff --git a/hicn-light/src/hicn/utils/address.h b/hicn-light/src/hicn/utils/address.h
deleted file mode 100644
index 6ca98347a..000000000
--- a/hicn-light/src/hicn/utils/address.h
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @brief Represents an endpoint address.
- *
- * Represents an endpoint address. May be INET, INET6, or a multi-byte LINK,
- * or an Interface Index.
- *
- * INET and INET6 must contain the .sa_addr member, and other members as needed
- * by the use of the address.
- *
- * The Interface Index address is essentially a pointer to a device.
- *
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-#ifndef address_h
-#define address_h
-
-#ifndef _WIN32
-#include <netinet/in.h>
-#include <sys/un.h>
-#endif
-#include <stdbool.h>
-
-#include <parc/algol/parc_Buffer.h>
-#include <parc/algol/parc_BufferComposer.h>
-#include <hicn/utils/commands.h>
-
-/**
- * Return a string representation of the given `address_type`
- *
- * @param [in] type A valid address_type value.
- *
- * @return NULL An error occurred
- * @return non-NULL A pointer to a static string representation of the
- * `address_type`.
- *
- * Example:
- * @code
- * {
- * const char *typeAsString = addressTypeToString(commandAddrType_INET);
- * }
- * @endcode
- *
- * @see addressStringToType
- */
-const char *addressTypeToString(address_type type);
-
-/**
- * Return a `address_type` from the given nul-terminated C string.
- *
- * @param [in] typeAsString A nul-terminated, C string representation of a
- * `address_type`.
- *
- * @return A address_type
- *
- * Example:
- * @code
- * {
- * address_type type = addressTypeToString("INET");
- * }
- * @endcode
- *
- * @see addressTypeToString
- */
-address_type addressStringToType(const char *typeAsString);
-
-struct address;
-typedef struct address Address;
-
-/**
- * Create a new `Address` instance from an IPv4 IP address, the port is
- * optional.
- *
- * The sockaddr_in should be filled in network byte order. The newly created
- * instance must eventually be destroyed by calling {@link addressDestroy}().
- *
- * @param [in] addr_in The `sockaddr_in` representing the IPv4 IP address with
- * which to initialize the new `Address` instance.
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}().
- *
- * Example:
- * @code
- * {
- * Address *dest = addressCreateFromInet(
- * &(struct sockaddr_in) {
- * .sa_addr =
- * inet_addr("foo.bar.com"), .sa_port = htons(9695) } ); addressDestroy(&dest);
- * }
- * @endcode
- * @see addressDestroy
- */
-Address *addressCreateFromInet(struct sockaddr_in *addr_in);
-
-/**
- * Create a new `Address` instance from an IPv6 IP address, the port is
- * optional.
- *
- *
- * The sockaddr_in should be filled in network byte order. The newly created
- * instance must eventually be destroyed by calling {@link addressDestroy}().
- *
- * @param [in] addr_in6 A `sockaddr_in6` from which to initialize a new instance
- * of Address
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}()
- *
- * Example:
- * @code
- * {
- * struct sockaddr_in6 addr_in6;
- * memset(&addr_in6, 0, sizeof(struct sockaddr_in6));
- *
- * inet_pton(AF_INET6, "2001:720:1500:1::a100", &(addr_in6.sin6_addr));
- * addr_in6.sin6_family = AF_INET6;
- * addr_in6.sin6_port = 0x0A0B;
- * addr_in6.sin6_flowinfo = 0x01020304;
- *
- * Address *address = addressCreateFromInet6(&addr_in6);
- *
- * addressDestroy(&address);
- * }
- * @endcode
- * @see addressDestroy
- */
-Address *addressCreateFromInet6(struct sockaddr_in6 *addr_in6);
-
-/**
- * Convert an internet address family (IPv4) to the address format used by the
- * Fwd.
- *
- * @param [in] addr4 IPV4 address in *Network byte order*
- * @param [in] port Port number in *Network byte order*
- *
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}()
- */
-Address *addressFromInaddr4Port(in_addr_t *addr4, in_port_t *port);
-
-/**
- * Convert an internet address family (IPv6) to the address format used by the
- * Fwd
- *
- * @param [in] addr6 IPV4 address in *Network byte order*
- * @param [in] port Port number in *Network byte order*
- *
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}()
- */
-Address *addressFromInaddr6Port(struct in6_addr *addr6, in_port_t *port);
-
-/**
- * Create a new `Address` instance, initialized from a Link address.
- *
- * User must know the link address format (i.e. token ring vs ethernet) and have
- * the address in a byte array. The array is encoded in left-to-right order. The
- * newly created instance must eventually be destroyed by calling {@link
- * addressDestroy}().
- *
- * @param [in] linkaddr A byte array containing the link address
- * @param [in] length The length of the link address byte array
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}()
- *
- * Example:
- * @code
- * {
- * uint8_t mac[] = { 0x14, 0x10, 0x9f, 0xd7, 0x0b, 0x89 };
- * Address *address = addressCreateFromLink(mac, sizeof(mac));
- *
- * addressDestroy(&address);
- * }
- * @endcode
- * @see addressDestroy
- */
-Address *addressCreateFromLink(const uint8_t *linkaddr, size_t length);
-
-/**
- * Create a new `Address` instance from a network interface index.
- *
- * The interfaceIndex should be in host byte order. The newly created instance
- * must eventually be destroyed by calling {@link addressDestroy}().
- *
- * @param [in] interfaceIndex The index of the interface to encode
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}()
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(2);
- *
- * addressDestroy(&address);
- * }
- * @endcode
- * @see addressDestroy
- */
-Address *addressCreateFromInterface(uint32_t interfaceIndex);
-
-/**
- * Create a new Address instance from a PF_UNIX address domain.
- *
- * The newly created instance must eventually be destroyed by calling {@link
- * addressDestroy}().
- *
- * @param [in] addr_un The `struct sockaddr_un` specifying the local PF_UNIX
- * socket address
- * @return A new instance of `Address` that must eventually be destroyed by
- * calling {@link addressDestroy}()
- *
- * Example:
- * @code
- * {
- * struct sockaddr_un addr_unix;
- * memset(&addr_unix, 0, sizeof(struct sockaddr_un));
- * char path[] = "/Hello/Cruel/World";
- * strcpy(addr_un.sun_path, path);
- * addr_un.sun_family = AF_UNIX;
- *
- * Address *address = addressCreateFromUnix(&addr_un);
- *
- * addressDestroy(&address);
- * }
- * @endcode
- * @see addressDestroy
- */
-Address *addressCreateFromUnix(struct sockaddr_un *addr_un);
-
-/**
- * Create a deep copy of an instance of a `Address`. A completely new,
- * indedependent instance is created.
- *
- * The newly created instance must eventually be destroyed by calling {@link
- * addressDestroy}().
- *
- * @param [in] original A pointer to a `Address` instance to be copied.
- * @return A new instance of a Address, deep copied from the `original`
- * instance.
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(2);
- *
- * Address *copy = addressCopy(address);
- *
- * addressDestroy(&address);
- * addressDestroy(&copy);
- * }
- * @endcode
- * @see addressDestroy
- */
-Address *addressCopy(const Address *original);
-
-/**
- * Deallocate an instance of a Address.
- *
- * The Address instance is deallocated, and any referenced data is also
- * deallocated. The referenced pointer is set to NULL upon return.
- *
- * @param [in] addressPtr A pointer to a pointer to an instance of Address.
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(2);
- *
- * addressDestroy(&address);
- * }
- * @endcode
- */
-void addressDestroy(Address **addressPtr);
-
-/**
- * Determine if two Address instances are equal.
- *
- *
- * The following equivalence relations on non-null `Address` instances are
- * maintained:
- *
- * * It is reflexive: for any non-null reference value x, `addressEquals(x, x)`
- * must return true.
- *
- * * It is symmetric: for any non-null reference values x and y,
- * `addressEquals(x, y)` must return true if and only if
- * `addressEquals(y, x)` returns true.
- *
- * * It is transitive: for any non-null reference values x, y, and z, if
- * `addressEquals(x, y)` returns true and
- * `addressEquals(y, z)` returns true,
- * then `addressEquals(x, z)` must return true.
- *
- * * It is consistent: for any non-null reference values x and y, multiple
- * invocations of `addressEquals(x, y)` consistently return true or
- * consistently return false.
- *
- * * For any non-null reference value x, `addressEquals(x, NULL)` must
- * return false.
- *
- * If one address specifies more information than other,
- * e.g. a is INET with a port and b is not, they are not equal.
- *
- * `a` and `b` may be NULL, and NULL == NULL.
- *
- * @param a A pointer to a Address instance
- * @param b A pointer to a Address instance
- * @return true if the two instances are equal
- * @return false if the two instances are not equal
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(2);
- * Address *copy = addressCopy(address);
- *
- * if (addressEquals(address, copy)) {
- * // true
- * } else {
- * // false
- * }
- *
- * addressDestroy(&address);
- * addressDestroy(&copy);
- * }
- * @endcode
- */
-bool addressEquals(const Address *a, const Address *b);
-
-/**
- * Return the {@link address_type} from a specified Address.
- *
- * @param [in] A pointer to a Address instance
- *
- * @return the {@link address_type} of the specified Address instance
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(2);
- *
- * address_type type = addressGetType(address);
- *
- * addressDestroy(&address);
- * }
- * @endcode
- *
- * @see address_type
- */
-address_type addressGetType(const Address *address);
-
-/**
- * Fills in the output parameter with an INET address.
- *
- * @param addr_in must be non-NULL
- * @return true if INET address and output filled in, false otherwise.
- *
- */
-bool addressGetInet(const Address *address, struct sockaddr_in *addr_in);
-
-/**
- * Retrieve the INET6 address associated with a `Address` instance.
- *
- * If the specified Address instance is of type {@link commandAddrType_INET6},
- * then populate the supplied `struct sockaddr_in6` from the Address and return
- * true. If the Address is not of type `commandAddrType_INET6`, this function
- * returns false.
- *
- * @param [in] address A pointer to a `Address` instance of type {@link
- * commandAddrType_INET6}.
- * @param [in] addr_in6 A pointer to a `struct sockaddr_in6`. Must be non-NULL.
- * @return true If the Address instance is of type `commandAddrType_INET6` and
- * `addr_in6` was filled in
- * @return false If the Address instance was not of type `commandAddrType_INET6`
- * or `addr_in6` could not be filled in.
- *
- * @see addressGetType
- */
-bool addressGetInet6(const Address *address, struct sockaddr_in6 *addr_in6);
-
-/**
- * Retrieve the interface index associated with a `Address` instance.
- *
- * If the specified `Address` instance is of type {@link commandAddrType_IFACE},
- * then populate the supplied `uint32_t` from the Address and return true. If
- * the `Address` is not of type `commandAddrType_INET6`, this function returns
- * false.
- *
- * @param [in] address A pointer to a `Address` instance of type {@link
- * commandAddrType_IFACE}.
- * @param [in] interfaceIndex A pointer to a `uint32_t` to fill in. Must be
- * non-NULL.
- * @return true If the Address instance is of type `commandAddrType_IFACE` and
- * `interfaceIndex` was filled in.
- * @return false If the Address instance was not of type `commandAddrType_IFACE`
- * or `interfaceIndex` could not be filled in.
- *
- * @see addressGetType
- */
-bool addressGetInterfaceIndex(const Address *address, uint32_t *interfaceIndex);
-
-/**
- * Retrieve the link address associated with a `Address` instance.
- *
- * If the specified `Address` instance is of type {@link commandAddrType_LINK},
- * then return a pointer to the {@link PARCBuffer} containing the link address.
- * If the `Address` is not of type {@link commandAddrType_LINK}, then return
- * NULL. The returned PARCBuffer pointer points to memory managed by the Address
- * instance, and does not need to be destroyed or released on its own.
- *
- * @param [in] address A pointer to a `Address` instance of type {@link
- * commandAddrType_LINK}.
- * @return A pointer to the {@link PARCBuffer} containing the link address.
- *
- * Example:
- * @code
- * {
- * uint8_t mac[] = { 0x14, 0x10, 0x9f, 0xd7, 0x0b, 0x89 };
- * Address *address = addressCreateFromLink(mac, sizeof(mac));
- *
- * PARCBuffer *macBuffer = addressGetLinkAddress(address);
- *
- * addressDestroy(&address);
- * }
- * @endcode
- * @see addressGetType
- */
-PARCBuffer *addressGetLinkAddress(const Address *address);
-
-/**
- * Append the string representation of a `Address` to a specified
- * `PARCBufferComposer`.
- *
- * @param [in] address A pointer to a `Address` instance.
- * @param [in] composer A pointer to a `PARCBufferComposer` instance to which to
- * append the string.
- *
- * @return The `PARCBufferComposer` instance that was passed in.
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(1);
- * PARCBufferComposer *composer = addressBuildString(address,
- * parcBufferComposer_Create()); parcBufferComposer_Release(&composer);
- * addressDestroy(&address);
- * }
- * @endcode
- *
- * @see PARCBufferComposer
- */
-PARCBufferComposer *addressBuildString(const Address *address,
- PARCBufferComposer *composer);
-
-/**
- * Produce a nil-terminated string representation of the specified instance.
- *
- * The result must be freed by the caller via {@link parcMemory_Deallocate}.
- *
- * @param [in] interest A pointer to the instance.
- *
- * @return NULL Cannot allocate memory.
- * @return non-NULL A pointer to an allocated, nul-terminated C string that must
- * be deallocated via {@link parcMemory_Deallocate}().
- *
- * Example:
- * @code
- * {
- * Address *address = addressCreateFromInterface(1);
- *
- * char *string = addressToString(address);
- *
- * if (string != NULL) {
- * printf("Address looks like: %s\n", string);
- * parcMemory_Deallocate(string);
- * } else {
- * printf("Cannot allocate memory\n");
- * }
- *
- * addressDestroy(&address);
- * }
- * @endcode
- * @see parcMemory_Deallocate
- * @see addressBuildString
- */
-char *addressToString(const Address *address);
-
-/**
- * Return a non-cryptographic hash code consistent with Equals
- *
- * If commandAddrA == commandAddrB, then addressHashCode(commandAddrA) ==
- * addressHashCode(commandAddrB)
- *
- * @param [in] address A pointer to a Address instance.
- * @return A 32-bit hashcode for the specified Address instance.
- *
- * Example:
- * @code
- * Address *address = addressCreateFromInterface(1);
- *
- * uint32_t hashCode = addressHashCode(address);
- *
- * addressDestroy(&address);
- * @endcode
- */
-PARCHashCode addressHashCode(const Address *address);
-#endif // address_h
diff --git a/hicn-light/src/hicn/utils/addressList.c b/hicn-light/src/hicn/utils/addressList.c
deleted file mode 100644
index a64fd6f9e..000000000
--- a/hicn-light/src/hicn/utils/addressList.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/utils/addressList.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Buffer.h>
-#include <parc/algol/parc_Memory.h>
-
-struct address_list {
- PARCArrayList *listOfAddress;
-};
-
-static void _addressListFreeAddress(void **addressVoidPtr) {
- Address **addressPtr = (Address **)addressVoidPtr;
- addressDestroy(addressPtr);
-}
-
-AddressList *addressListCreate() {
- AddressList *list = parcMemory_AllocateAndClear(sizeof(AddressList));
- parcAssertNotNull(list, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(AddressList));
- list->listOfAddress = parcArrayList_Create(_addressListFreeAddress);
- parcAssertNotNull(list->listOfAddress, "Got null from parcArrayList_Create");
-
- return list;
-}
-
-void addressListDestroy(AddressList **addressListPtr) {
- parcAssertNotNull(addressListPtr,
- "Parameter must be non-null double pointer");
- parcAssertNotNull(*addressListPtr,
- "Parameter must dereference to non-null pointer");
- AddressList *list = *addressListPtr;
-
- parcArrayList_Destroy(&list->listOfAddress);
- parcMemory_Deallocate((void **)&list);
- *addressListPtr = NULL;
-}
-
-AddressList *addressListAppend(AddressList *list, Address *address) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- parcAssertNotNull(address, "Parameter address must be non-null");
-
- parcArrayList_Add(list->listOfAddress, (PARCObject *)address);
- return list;
-}
-
-AddressList *addressListCopy(const AddressList *original) {
- parcAssertNotNull(original, "Parameter must be non-null");
-
- AddressList *copy = addressListCreate();
- for (int i = 0; i < parcArrayList_Size(original->listOfAddress); i++) {
- Address *address = (Address *)parcArrayList_Get(original->listOfAddress, i);
- parcArrayList_Add(copy->listOfAddress, (PARCObject *)addressCopy(address));
- }
-
- return copy;
-}
-
-bool addressListEquals(const AddressList *a, const AddressList *b) {
- parcAssertNotNull(a, "Parameter a must be non-null");
- parcAssertNotNull(b, "Parameter b must be non-null");
-
- if (a == b) {
- return true;
- }
-
- if (parcArrayList_Size(a->listOfAddress) !=
- parcArrayList_Size(b->listOfAddress)) {
- return false;
- }
-
- for (size_t i = 0; i < parcArrayList_Size(a->listOfAddress); i++) {
- const Address *addr_a = (Address *)parcArrayList_Get(a->listOfAddress, i);
- const Address *addr_b = (Address *)parcArrayList_Get(b->listOfAddress, i);
- if (!addressEquals(addr_a, addr_b)) {
- return false;
- }
- }
- return true;
-}
-
-size_t addressListLength(const AddressList *list) {
- parcAssertNotNull(list, "Parameter must be non-null");
- return parcArrayList_Size(list->listOfAddress);
-}
-
-const Address *addressListGetItem(const AddressList *list, size_t item) {
- parcAssertNotNull(list, "Parameter must be non-null");
- parcAssertTrue(item < addressListLength(list),
- "Asked for item %zu beyond end of list %zu", item,
- addressListLength(list));
-
- return (Address *)parcArrayList_Get(list->listOfAddress, item);
-}
-
-char *addressListToString(const AddressList *list) {
- PARCBufferComposer *composer = parcBufferComposer_Create();
-
- for (size_t i = 0; i < addressListLength(list); i++) {
- char *addressString = addressToString(addressListGetItem(list, i));
- parcBufferComposer_PutString(composer, addressString);
- if (i < (addressListLength(list) - 1)) {
- parcBufferComposer_PutString(composer, " ");
- }
- parcMemory_Deallocate((void **)&addressString);
- }
-
- PARCBuffer *buffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(buffer);
- parcBuffer_Release(&buffer);
- parcBufferComposer_Release(&composer);
-
- return result;
-}
diff --git a/hicn-light/src/hicn/utils/addressList.h b/hicn-light/src/hicn/utils/addressList.h
deleted file mode 100644
index 823b0c8cb..000000000
--- a/hicn-light/src/hicn/utils/addressList.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @brief A list of Address instances.
- *
- * An AddressList is a list of addresses.
- * It wraps a PARCLinkedList for type saftey with Address.
- *
- */
-#ifndef address_list_h
-#define address_list_h
-
-#include <hicn/utils/address.h>
-
-struct address_list;
-/**
- * @typedef AddressList
- * @abstract A list of Address instance pointers.
- */
-typedef struct address_list AddressList;
-
-/**
- * Create an instance of {@link AddressList}
- *
- * @return NULL An error occurred
- * @return non-NULL A pointer to a valid AddressList instance.
- *
- * Example:
- * @code
- * {
- * AddressList *list = addressListCreate();
- *
- * }
- * @endcode
- *
- * @see addressListDestroy
- */
-AddressList *addressListCreate(void);
-
-/**
- * Dellocate and destroy a AddressList instance.
- *
- * @param [in] addressListPtr A pointer to a pointer to a valid {@link
- * AddressList}.
- *
- *
- * Example:
- * @code
- * {
- * AddressList *list = addressListCreate(void);
- * addressListDestroy(&list);
- * }
- * @endcode
- *
- * @see addressListCreate
- */
-void addressListDestroy(AddressList **addressListPtr);
-
-/**
- * Appends the address, taking ownership of the memory
- *
- * @param list A pointer to a AddressList.
- * @param address must be non-null
- * @return The input list
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-AddressList *addressListAppend(AddressList *list, Address *address);
-
-/**
- * Creates a reference counted copy
- *
- * @param list A pointer to a valid {@link AddressList}.
- *
- * @return An allocated list, you must destroy it.
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-AddressList *addressListCopy(const AddressList *list);
-
-/**
- * Determine if two AddressList instances are equal.
- *
- * Two AddressList instances are equal if, and only if, they have the same
- * length, with the same elements in the same order.
- *
- *
- * The following equivalence relations on non-null `AddressList` instances are
- * maintained:
- *
- * * It is reflexive: for any non-null reference value x,
- * `AddressList_Equals(x, x)` must return true.
- *
- * * It is symmetric: for any non-null reference values x and y,
- * `AddressList_Equals(x, y)` must return true if and only if
- * `addressListEquals(y, x)` returns true.
- *
- * * It is transitive: for any non-null reference values x, y, and z, if
- * `addressListEquals(x, y)` returns true and
- * `addressListEquals(y, z)` returns true,
- * then `addressListEquals(x, z)` must return true.
- *
- * * It is consistent: for any non-null reference values x and y, multiple
- * invocations of `addressListEquals(x, y)` consistently return true or
- * consistently return false.
- *
- * * For any non-null reference value x, `addressListEquals(x, NULL)` must
- * return false.
- *
- * @param a A pointer to a `AddressList` instance.
- * @param b A pointer to a `AddressList` instance.
- * @return true if the two `AddressList` instances are equal.
- *
- * Example:
- * @code
- * {
- * AddressList *a = addressListCreate();
- * AddressList *b = addressListCreate();
- *
- * if (addressListEquals(a, b)) {
- * // true
- * } else {
- * // false
- * }
- * }
- * @endcode
- */
-bool addressListEquals(const AddressList *a, const AddressList *b);
-
-/**
- * Get the number of items in the list
- *
- * @param list A pointer to a {@link AddressList}.
- * @return The number of items in the list.
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-size_t addressListLength(const AddressList *list);
-
-/**
- * Returns a const reference to an item.
- * Use addressCopy if needed.
- *
- * Do not free or modify the returned value.
- * Use addressCopy if you need a mutable instance.
- *
- * @param list A pointer to a AddressList.
- * @param item A value less than the number of items in the given {@link
- * AddressList}.
- * @return Asserts if item off end of list.
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-const Address *addressListGetItem(const AddressList *list, size_t item);
-
-/**
- * Get a nul-terminated, C-string representation of the given {@link
- * AddressList}.
- *
- * @param list A pointer to a valid {@link AddressList} instance.
- *
- * @return An allocate string representation of the {@link AddressList} that
- * must be freed via `parcMemory_Deallocate()`.
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-char *addressListToString(const AddressList *list);
-#endif // address_list_h
diff --git a/hicn-light/src/hicn/utils/interface.c b/hicn-light/src/hicn/utils/interface.c
index d8597f3ed..c3f8793a4 100644
--- a/hicn-light/src/hicn/utils/interface.c
+++ b/hicn-light/src/hicn/utils/interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,12 +22,14 @@
#include <parc/algol/parc_BufferComposer.h>
#include <parc/algol/parc_Memory.h>
#include <parc/algol/parc_Object.h>
-#include <hicn/utils/addressList.h>
+//#include <hicn/utils/addressList.h>
#include <hicn/utils/interface.h>
#include <parc/assert/parc_Assert.h>
#include <hicn/utils/commands.h>
+#if 0
+
struct interface {
char *name;
unsigned interfaceIndex;
@@ -166,3 +168,5 @@ unsigned interfaceGetMTU(const Interface *iface) {
parcAssertNotNull(iface, "Parameter iface must be non-null");
return iface->mtu;
}
+
+#endif
diff --git a/hicn-light/src/hicn/utils/interface.h b/hicn-light/src/hicn/utils/interface.h
index fd91edb1d..365624e4a 100644
--- a/hicn-light/src/hicn/utils/interface.h
+++ b/hicn-light/src/hicn/utils/interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,8 +22,7 @@
#ifndef interface_h
#define interface_h
-#include <hicn/utils/address.h>
-#include <hicn/utils/addressList.h>
+#include <hicn/core/address.h>
struct interface;
typedef struct interface Interface;
@@ -59,7 +58,7 @@ void interfaceDestroy(Interface **interfacePtr);
* <#example#>
* @endcode
*/
-void interfaceAddAddress(Interface *iface, Address *address);
+void interfaceAddAddress(Interface *iface, address_t *address);
/**
* Retrieves a list of interface addresses
@@ -74,7 +73,7 @@ void interfaceAddAddress(Interface *iface, Address *address);
* <#example#>
* @endcode
*/
-const AddressList *interfaceGetAddresses(const Interface *iface);
+const address_t **interfaceGetAddresses(const Interface *iface);
/**
* The interface index
diff --git a/hicn-light/src/hicn/utils/interfaceSet.c b/hicn-light/src/hicn/utils/interfaceSet.c
index 3ae52bb80..e06643fc7 100644
--- a/hicn-light/src/hicn/utils/interfaceSet.c
+++ b/hicn-light/src/hicn/utils/interfaceSet.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-light/src/hicn/utils/interfaceSet.h b/hicn-light/src/hicn/utils/interfaceSet.h
index e43f985fe..6723bc493 100644
--- a/hicn-light/src/hicn/utils/interfaceSet.h
+++ b/hicn-light/src/hicn/utils/interfaceSet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-light/src/hicn/utils/punting.c b/hicn-light/src/hicn/utils/punting.c
index 8f33cf763..60a8d2355 100644
--- a/hicn-light/src/hicn/utils/punting.c
+++ b/hicn-light/src/hicn/utils/punting.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#if 0
#include <hicn/hicn-light/config.h>
#include <stdio.h>
@@ -23,11 +24,11 @@
struct punting {
char *symbolic;
- Address *prefix;
+ address_t *prefix;
uint32_t len;
};
-Punting *puntingCreate(const char *listenerName, Address *prefix,
+Punting *puntingCreate(const char *listenerName, address_t *prefix,
uint32_t len) {
parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
parcAssertNotNull(prefix, "Parameter prefix must be non-null");
@@ -87,7 +88,7 @@ const char *puntingGetSymbolicName(const Punting *punting) {
return punting->symbolic;
}
-Address *puntingGetAddress(const Punting *punting) {
+address_t * puntingGetAddress(const Punting *punting) {
parcAssertNotNull(punting, "Parameter listener must be non-null");
return punting->prefix;
}
@@ -96,3 +97,4 @@ uint32_t puntingPrefixLen(const Punting *punting) {
parcAssertNotNull(punting, "Parameter listener must be non-null");
return punting->len;
}
+#endif
diff --git a/hicn-light/src/hicn/utils/punting.h b/hicn-light/src/hicn/utils/punting.h
index 9be1baed4..46cec8a91 100644
--- a/hicn-light/src/hicn/utils/punting.h
+++ b/hicn-light/src/hicn/utils/punting.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,10 +16,21 @@
#ifndef punting_h
#define punting_h
+#include <hicn/core/address.h>
+
+typedef struct {
+ char *symbolic;
+ address_t prefix;
+ uint32_t len;
+} punting_t;
+
+#define punting_address(punting) (&((punting)->prefix))
+#define punting_len(punting) ((punting)->len)
+
+#if 0
struct punting;
typedef struct punting Punting;
-#include <hicn/utils/address.h>
/**
* Creates a Punting object
@@ -36,7 +47,7 @@ typedef struct punting Punting;
* @return null An error
*
*/
-Punting *puntingCreate(const char *symbolic, Address *prefix, uint32_t len);
+Punting *puntingCreate(const char *symbolic, address_t *prefix, uint32_t len);
/**
* Releases a reference count to the object
@@ -66,7 +77,9 @@ const char *puntingGetSymbolicName(const Punting *punting);
* Returns the address (INET or INET6 ip address)
*
*/
-Address *puntingGetAddress(const Punting *punting);
+address_t * puntingGetAddress(const Punting *punting);
uint32_t puntingPrefixLen(const Punting *punting);
+#endif
+
#endif // punting_h
diff --git a/hicn-light/src/hicn/utils/token.h b/hicn-light/src/hicn/utils/token.h
index 43e0a77b2..138916f31 100644
--- a/hicn-light/src/hicn/utils/token.h
+++ b/hicn-light/src/hicn/utils/token.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,7 +19,7 @@
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
-#define PPCAT_NX(A, B) A ## B
+#define PPCAT_NX(A, B) A##B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
diff --git a/hicn-light/src/hicn/utils/utils.c b/hicn-light/src/hicn/utils/utils.c
deleted file mode 100644
index 36596f943..000000000
--- a/hicn-light/src/hicn/utils/utils.c
+++ /dev/null
@@ -1,235 +0,0 @@
-// Utility function for commands
-
-#ifndef _WIN32
-#include <netinet/in.h>
-#endif
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-#include <parc/assert/parc_Assert.h>
-#include <pthread.h>
-#include <hicn/utils/utils.h>
-
-// This is the unique sequence number used by all messages and its thread locks
-static pthread_mutex_t nextSequenceNumberMutex = PTHREAD_MUTEX_INITIALIZER;
-static uint32_t nextSequenceNumber = 1;
-
-uint32_t utils_GetNextSequenceNumber(void) {
- uint32_t seqnum;
-
- int result = pthread_mutex_lock(&nextSequenceNumberMutex);
- parcAssertTrue(result == 0, "Got error from pthread_mutex_lock: %d", result);
-
- seqnum = nextSequenceNumber++;
-
- result = pthread_mutex_unlock(&nextSequenceNumberMutex);
- parcAssertTrue(result == 0, "Got error from pthread_mutex_unlock: %d",
- result);
-
- return seqnum;
-}
-
-/**
- * Return true if string is purely an integer
- */
-bool utils_IsNumber(const char *string) {
- size_t len = strlen(string);
- for (size_t i = 0; i < len; i++) {
- if (!isdigit(string[i])) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * A symbolic name must be at least 1 character and must begin with an alpha.
- * The remainder must be an alphanum.
- */
-bool utils_ValidateSymbolicName(const char *symbolic) {
- bool success = false;
- size_t len = strlen(symbolic);
- if (len > 0) {
- if (isalpha(symbolic[0])) {
- success = true;
- for (size_t i = 1; i < len; i++) {
- if (!isalnum(symbolic[i])) {
- success = false;
- break;
- }
- }
- }
- }
- return success;
-}
-
-struct iovec *utils_CreateAck(header_control_message *header, void *payload,
- size_t payloadLen) {
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- header->messageType = ACK_LIGHT;
-
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payload;
- response[1].iov_len = payloadLen;
-
- return response;
-}
-
-struct iovec *utils_CreateNack(header_control_message *header, void *payload,
- size_t payloadLen) {
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- header->messageType = NACK_LIGHT;
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payload;
- response[1].iov_len = payloadLen;
-
- return response;
-}
-
-char *utils_BuildStringFromInet(in_addr_t *addr4, in_port_t *port) {
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = *port;
- addr.sin_addr.s_addr = *addr4;
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
- parcNetwork_SockInet4Address_BuildString(&addr, composer));
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- parcBufferComposer_Release(&composer);
- return result;
-}
-
-char *utils_BuildStringFromInet6(struct in6_addr *addr6, in_port_t *port) {
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
- addr.sin6_port = *port;
- addr.sin6_addr = *addr6;
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(
- parcNetwork_SockInet6Address_BuildString(&addr, composer));
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- parcBufferComposer_Release(&composer);
- return result;
-}
-
-char *utils_CommandAddressToString(address_type addressType,
- ip_address_t *address,
- in_port_t *port) {
- char *result;
-
- switch (addressType) {
- case ADDR_INET: {
- result = utils_BuildStringFromInet(&address->v4.as_u32, port);
- break;
- }
-
- case ADDR_INET6: {
- result = utils_BuildStringFromInet6(&address->v6.as_in6addr, port);
- break;
- }
-
- default: {
- char *addrStr = (char *)parcMemory_Allocate(sizeof(char) * 32);
- sprintf(addrStr, "Error: UNKNOWN address type = %d", addressType);
- result = addrStr;
- break;
- }
- }
- return result;
-}
-
-struct iovec *utils_SendRequest(ControlState *state, command_id command,
- void *payload, size_t payloadLen) {
- bool success = false;
-
- // get sequence number for the header
- uint32_t currentSeqNum = utils_GetNextSequenceNumber();
-
- // Allocate and fill the header
- header_control_message *headerControlMessage =
- parcMemory_AllocateAndClear(sizeof(header_control_message));
- headerControlMessage->messageType = REQUEST_LIGHT;
- headerControlMessage->commandID = command;
- headerControlMessage->seqNum = currentSeqNum;
- if (payloadLen > 0) {
- headerControlMessage->length = 1;
- }
-
- struct iovec msg[2];
- msg[0].iov_base = headerControlMessage;
- msg[0].iov_len = sizeof(header_control_message);
- msg[1].iov_base = payload;
- msg[1].iov_len = payloadLen;
-
- struct iovec *response = controlState_WriteRead(state, msg);
-
- header_control_message *receivedHeader =
- (header_control_message *)response[0].iov_base;
- if (receivedHeader->seqNum != currentSeqNum) {
- printf("Seq number is NOT correct: expected %d got %d \n", currentSeqNum,
- receivedHeader->seqNum);
- // failure
- } else {
- if (receivedHeader->messageType == RESPONSE_LIGHT) {
- return response; // command needs both payload and header
- } else {
- if (receivedHeader->messageType == ACK_LIGHT) {
- success = true;
- } else if (receivedHeader->messageType == NACK_LIGHT) {
- success = true;
- } else {
- printf("Error: unrecognized message type"); // failure
- }
- }
- }
-
- // deallocate when payload & header of the response are not needed
- if (receivedHeader->length > 0) {
- parcMemory_Deallocate(&response[1].iov_base); // free received payload
- }
- parcMemory_Deallocate(&response[0].iov_base); // free receivedHeader
-
- // return response
- if (success) {
- return response;
- } else {
- parcMemory_Deallocate(&response); // free iovec pointer
- return NULL; // will generate a failure
- }
-}
-
-const char *utils_PrefixLenToString(address_type addressType,
- ip_address_t *address,
- uint8_t *prefixLen) {
- char len[4]; // max size + 1
- sprintf(len, "%u", (unsigned)*prefixLen);
- in_port_t port = htons(1234); // this is a random port number that is ignored
-
- char *prefix = utils_CommandAddressToString(addressType, address, &port);
- char *prefixStr = malloc(strlen(prefix) + strlen(len) + 2);
- strcpy(prefixStr, prefix);
- strcat(prefixStr, "/");
- strcat(prefixStr, len);
-
- free(prefix);
-
- return prefixStr;
-}
diff --git a/hicn-light/src/hicn/utils/utils.h b/hicn-light/src/hicn/utils/utils.h
deleted file mode 100644
index 1fe88e62c..000000000
--- a/hicn-light/src/hicn/utils/utils.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef utils_h
-#define utils_h
-
-#include <hicn/config/controlState.h>
-#include <hicn/utils/address.h>
-#include <hicn/utils/commands.h>
-
-/**
- * Return true if string is purely an integer
- */
-bool utils_IsNumber(const char *string);
-
-/**
- * A symbolic name must be at least 1 character and must begin with an alpha.
- * The remainder must be an alphanum.
- */
-bool utils_ValidateSymbolicName(const char *symbolic);
-
-/**
- *Create an Ack message instance as a response of a control successfully
- *completed.
- */
-struct iovec *utils_CreateAck(header_control_message *header, void *payload,
- size_t payloadLen);
-
-/**
- *Create a Nack message instance as a response of a control unsuccessfully
- *completed.
- */
-struct iovec *utils_CreateNack(header_control_message *header, void *payload,
- size_t payloadLen);
-
-/**
- *Convert IPv4/IPv6 address from binary to text string. `uint8_t *ipAddress` has
- *to be a `in_addr_t * or `a struct in6_addr *.
- */
-char *utils_CommandAddressToString(address_type addressType,
- ip_address_t *address, in_port_t *port);
-
-/**
- *Given a command payload, it generates the header and send the request to the
- *deamon.
- */
-struct iovec *utils_SendRequest(ControlState *state, command_id command,
- void *payload, size_t payloadLen);
-
-/**
- *Convert a IPv4/IPv6 address plus Netmask len from binary to text string in the
- *form [add]:[port]/[len].
- */
-const char *utils_PrefixLenToString(address_type addressType,
- ip_address_t *address,
- uint8_t *prefixLen);
-
-#endif
diff --git a/hicn-plugin/CMakeLists.txt b/hicn-plugin/CMakeLists.txt
index 9f5553857..965fa5263 100644
--- a/hicn-plugin/CMakeLists.txt
+++ b/hicn-plugin/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,32 +11,51 @@
# 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(hicn-plugin)
-include(GNUInstallDirs)
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
- "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules/"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/"
+ ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules/
)
-include(BuildMacros)
-
-set (CMAKE_CXX_STANDARD 11)
-set (CMAKE_C_STANDARD 11)
-# Check for memfd_create syscall
-include(CheckSymbolExists)
-CHECK_SYMBOL_EXISTS ( "__NR_memfd_create" "sys/syscall.h" HAVE_MEMFD_CREATE )
-if ( HAVE_MEMFD_CREATE )
- add_definitions ( -DHAVE_MEMFD_CREATE )
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ include(CommonSetup)
endif()
+
+##############################################################
+# Libs and Bins names
+##############################################################
set(HICN_PLUGIN hicn-plugin CACHE INTERNAL "" FORCE)
+set(HICNPLUGIN hicn_plugin CACHE INTERNAL "" FORCE)
+set(HICN_API_TEST_PLUGIN hicn_api_test_plugin CACHE INTERNAL "" FORCE)
+set(HICNPLUGIN_SHARED ${HICNPLUGIN}.shared CACHE INTERNAL "" FORCE)
+set(HICN_API_TEST_PLUGIN_SHARED ${HICN_API_TEST_PLUGIN}.shared CACHE INTERNAL "" FORCE)
-include (Packaging)
-add_subdirectory(src)
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+
+##############################################################
+# C Standard
+##############################################################
+set (CMAKE_C_STANDARD 11)
+
+
+##############################################################
+# Subdirectories
+##############################################################
+add_subdirectory(includes/vpp_plugins/hicn)
+add_subdirectory(src)
add_subdirectory(vapi)
diff --git a/hicn-plugin/cmake/Modules/Packaging.cmake b/hicn-plugin/cmake/Modules/Packaging.cmake
deleted file mode 100644
index c0176e78f..000000000
--- a/hicn-plugin/cmake/Modules/Packaging.cmake
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-######################
-# Packages section
-######################
-
-set(${HICN_PLUGIN}_DESCRIPTION
- "A high-performance Hybrid ICN forwarder as a plugin to VPP."
- CACHE STRING "Description for deb/rpm package."
-)
-
-set(${HICN_PLUGIN}_DEB_DEPENDENCIES
- "vpp (>= stable_version-release), vpp (<< next_version-release), vpp-plugin-core (>= stable_version-release), vpp-plugin-core (<< next_version-release)"
- CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${HICN_PLUGIN}-dev_DEB_DEPENDENCIES
- "vpp-dev (>= stable_version-release), vpp-dev (<< next_version-release), libvppinfra-dev (>= stable_version-release), libvppinfra-dev (<< next_version-release)"
- CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${HICN_PLUGIN}_RPM_DEPENDENCIES
- "vpp >= stable_version-release, vpp < next_version-release, vpp-plugins >= stable_version-release, vpp-plugins < next_version-release"
- CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${HICN_PLUGIN}-dev_RPM_DEPENDENCIES
- "vpp-devel >= stable_version-release, vpp-devel < next_version-release"
- CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${HICN_PLUGIN}_DEB_PACKAGE_CONTROL_EXTRA
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/postinst"
- CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
-)
-
-set(${HICN_PLUGIN}_RPM_POST_INSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/post"
- CACHE STRING "Install script that will be copied in the %post section"
-)
-
-set(${HICN_PLUGIN}_RPM_POST_UNINSTALL_SCRIPT_FILE
- "${CMAKE_CURRENT_SOURCE_DIR}/scripts/postun"
- CACHE STRING "Uninstall script that will be copied in the %postun section"
-) \ No newline at end of file
diff --git a/hicn-plugin/cmake/packaging.cmake b/hicn-plugin/cmake/packaging.cmake
new file mode 100644
index 000000000..276fc0b95
--- /dev/null
+++ b/hicn-plugin/cmake/packaging.cmake
@@ -0,0 +1,69 @@
+# Copyright (c) 2021-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.
+
+######################
+# Packages section
+######################
+
+##############################################################
+# Get VPP version
+##############################################################
+list(GET VPP_DEFAULT_VERSION 0 VPP_VERSION)
+
+set(${HICN_PLUGIN}_DESCRIPTION
+ "A high-performance Hybrid ICN forwarder as a plugin to VPP."
+ CACHE STRING "Description for deb/rpm package."
+)
+
+string(REGEX REPLACE "([0-9]+).([0-9]+)(.[0-9]+)?" "\\1\\2" VER_NO_DOTS ${VPP_DEFAULT_VERSION})
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/scripts/postinst
+"#!/bin/bash
+
+#########################################################
+# Complete VPP config file with hicn configuration
+#########################################################
+
+if [ -e /etc/vpp/startup.conf ]; then
+ RESULTS=$(sed -n '/hicn[ ]*{/p' /etc/vpp/startup.conf | wc -l)
+ if [[ $RESULTS = 0 ]]; then
+ printf '\n hicn {
+ ## Set PIT size. Default is 131072 entries
+ # pit-size 500000
+ #
+ ## Set CS size. Default is 4096
+ # cs-size 50000
+ #
+ ## Set maximum PIT entries lifetime in milliseconds. Assigned to a PIT entry in case an interest carries a bigger lifetime
+ # pit-lifetime-max 20
+ #
+ ## Percentage of CS to reserve for application producer faces
+ # cs-reserved-app 20\n}' >> /etc/vpp/startup.conf
+ fi;
+fi;
+")
+
+set(${HICN_PLUGIN}_DEB_DEPENDENCIES
+ "${LIBHICN_COMPONENT} (= stable_version), vpp (>= ${VPP_VERSION}), vpp-plugin-core (>= ${VPP_VERSION})"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
+set(${HICN_PLUGIN}-dev_DEB_DEPENDENCIES
+ "${LIBHICN_COMPONENT}-dev (= stable_version), vpp-dev (>= ${VPP_VERSION}), libvppinfra-dev (>= ${VPP_VERSION})"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
+set(${HICN_PLUGIN}_DEB_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_CURRENT_BINARY_DIR}/scripts/postinst"
+ CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
+)
diff --git a/cmake/Modules/IosMacros.cmake b/hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt
index b1e5cc438..9b463e525 100644
--- a/cmake/Modules/IosMacros.cmake
+++ b/hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,14 +11,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-if(COMPILE_FOR_IOS)
- include_directories(iOS)
-endif()
+include(GNUInstallDirs)
-macro(find_package_wrapper)
- if(COMPILE_FOR_IOS)
- find_host_package(${ARGN})
- else()
- find_package(${ARGN})
- endif()
-endmacro() \ No newline at end of file
+set(HICNPLUGIN_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/../..
+ CACHE INTERNAL
+ "" FORCE
+)
+
+set(HICNPLUGIN_TO_INSTALL_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/error.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h ""
+ CACHE INTERNAL
+ "" FORCE
+) \ No newline at end of file
diff --git a/hicn-plugin/src/error.h b/hicn-plugin/includes/vpp_plugins/hicn/error.h
index b33a1b50d..a8a941a79 100644
--- a/hicn-plugin/src/error.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -83,7 +83,9 @@
_ (STRATEGY_NOT_FOUND, -179, "Strategy not found") \
_ (UDP_TUNNEL_NOT_FOUND, -180, "Udp tunnel not found") \
_ (UDP_TUNNEL_SRC_DST_TYPE, -181, \
- "Src and dst addresses have different type (ipv4 and ipv6)")
+ "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")
typedef enum
{
@@ -97,7 +99,7 @@ extern const char *HICN_ERROR_STRING[];
#define get_error_string(errno) \
(char *) (errno ? HICN_ERROR_STRING[(-errno) - 127] : \
- HICN_ERROR_STRING[errno])
+ HICN_ERROR_STRING[errno])
#endif /* //__HICN_ERROR_H__ */
diff --git a/hicn-plugin/src/hicn_all_api_h.h b/hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h
index 1263ea4a2..13769dd58 100644
--- a/hicn-plugin/src/hicn_all_api_h.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-#include <hicn/hicn.api.h>
+#include <vpp_plugins/hicn/hicn.api.h>
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/hicn_api.h b/hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h
index e32b785b6..ac45fbf17 100644
--- a/hicn-plugin/src/hicn_api.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -25,7 +25,7 @@
/* define message structures */
#define vl_typedefs
-#include <hicn/hicn_all_api_h.h>
+#include <vpp_plugins/hicn/hicn_all_api_h.h>
#undef vl_typedefs
#endif /* // __HICN_API_H___ */
diff --git a/hicn-plugin/src/hicn_msg_enum.h b/hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h
index fcf2a1e87..903fbf8c0 100644
--- a/hicn-plugin/src/hicn_msg_enum.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,7 +24,7 @@
#define vl_msg_id(n, h) n,
typedef enum
{
-#include <hicn/hicn_all_api_h.h>
+#include <vpp_plugins/hicn/hicn_all_api_h.h>
/* We'll want to know how many messages IDs we need... */
VL_MSG_FIRST_AVAILABLE,
} vl_msg_id_t;
diff --git a/hicn-plugin/scripts/post b/hicn-plugin/scripts/post
deleted file mode 100644
index dd0a9fbf5..000000000
--- a/hicn-plugin/scripts/post
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-if [ -e /etc/vpp/startup.conf ]; then
- RESULTS=$(sed -n '/hicn[ ]*{/p' /etc/vpp/startup.conf | wc -l)
- if [[ $RESULTS = 0 ]]; then
- printf '\n hicn {
- ## Set PIT size. Default is 131 072 entries
- # pit-size 500000
- #
- ## Set CS size. Default is 4096
- # cs-size 50000
- #
- ## Set maximum PIT entries lifetime in milliseconds. Assigned to a PIT entry in case an interest carries a bigger lifetime
- # pit-lifetime-max 20
- #
- ## Percentage of CS to reserve for application producer faces
- # cs-reserved-app 20\n}' >> /etc/vpp/startup.conf
- fi;
-fi;
-ln -s /usr/lib64/vpp_plugins/hicn_plugin.so /usr/lib/vpp_plugins/hicn_plugin.so \ No newline at end of file
diff --git a/hicn-plugin/scripts/postinst b/hicn-plugin/scripts/postinst
deleted file mode 100644
index d6d48509c..000000000
--- a/hicn-plugin/scripts/postinst
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-if [ -e /etc/vpp/startup.conf ]; then
- RESULTS=$(sed -n '/hicn[ ]*{/p' /etc/vpp/startup.conf | wc -l)
- if [[ $RESULTS = 0 ]]; then
- printf '\n hicn {
- ## Set PIT size. Default is 131 072 entries
- # pit-size 500000
- #
- ## Set CS size. Default is 4096
- # cs-size 50000
- #
- ## Set maximum PIT entries lifetime in milliseconds. Assigned to a PIT entry in case an interest carries a bigger lifetime
- # pit-lifetime-max 20
- #
- ## Percentage of CS to reserve for application producer faces
- # cs-reserved-app 20\n}' >> /etc/vpp/startup.conf
- fi;
-fi; \ No newline at end of file
diff --git a/hicn-plugin/scripts/postun b/hicn-plugin/scripts/postun
deleted file mode 100644
index c319f014e..000000000
--- a/hicn-plugin/scripts/postun
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-if [ -L /usr/lib/vpp_plugins/hicn_plugin.so ]; then
- rm /usr/lib/vpp_plugins/hicn_plugin.so
-fi; \ No newline at end of file
diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt
index 124d9b5cb..2141ec596 100644
--- a/hicn-plugin/src/CMakeLists.txt
+++ b/hicn-plugin/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,290 +11,234 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Dependencies
-find_package(Vpp REQUIRED)
-
-include_directories(${HICN_INCLUDE_DIRS} ${VPP_INCLUDE_DIR})
-
-set(LIBHICN_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/mapme.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/name.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/ops.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ah.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/icmp.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ipv4.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ipv6.c
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/tcp.c
-)
-
-set(LIBHICN_HEADER_FILES_SRC
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/hicn.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/base.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/common.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/error.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/header.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/name.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/ops.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/mapme.h
-)
-
-set(LIBHICN_HEADER_FILES_PROTOCOL
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ah.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/icmp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/icmprd.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ipv4.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ipv6.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/tcp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/udp.h
-)
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(Vpp ${VPP_DEFAULT_VERSION} EXACT REQUIRED)
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
+ list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE})
+else()
+ set(LIBHICN_LIBRARIES ${LIBHICN_SHARED})
+ list(APPEND DEPENDENCIES
+ ${LIBHICN_LIBRARIES}
+ )
+endif()
-set(LIBHICN_HEADER_FILES_UTIL
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/ip_address.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/token.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/types.h
-)
+##############################################################
+# Source/Header files
+##############################################################
set(HICN_PLUGIN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn.c
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.c
- ${CMAKE_CURRENT_SOURCE_DIR}/cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pcs.c
- ${CMAKE_CURRENT_SOURCE_DIR}/route.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategy_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/data_input_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/error.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_app_cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pg.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw_cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.c
- ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.c
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_decap_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cli.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/infra.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pcs.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/route.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/data_input_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/error.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_cli.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_app_cli.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pg.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw_cli.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rp.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rp.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_decap_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.c
)
set(HICN_PLUGIN_HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.h
- ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.h
- ${CMAKE_CURRENT_SOURCE_DIR}/params.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pcs.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h
- ${CMAKE_CURRENT_SOURCE_DIR}/state.h
- ${CMAKE_CURRENT_SOURCE_DIR}/infra.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h
- ${CMAKE_CURRENT_SOURCE_DIR}/parser.h
- ${CMAKE_CURRENT_SOURCE_DIR}/route.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup.h
- ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit.h
- ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs.h
- ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup.h
- ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd.h
- ${CMAKE_CURRENT_SOURCE_DIR}/error.h
- ${CMAKE_CURRENT_SOURCE_DIR}/face_db.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/inlines.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_dpo.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pg.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_policy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.h
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack.h
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl.h
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_logging.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/params.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/pcs.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/state.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/infra.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/parser.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/route.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/error.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/face_db.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/inlines.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_dpo.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/pg.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rp.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rp.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_policy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.h
)
set(HICN_API_TEST_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api_test.c
- ${CMAKE_CURRENT_SOURCE_DIR}/error.c)
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api_test.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/error.c
+)
set(HICN_API_HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h
- ${CMAKE_CURRENT_SOURCE_DIR}/error.h)
+ ${HICNPLUGIN_TO_INSTALL_HEADER_FILES}
+)
set(HICN_API_GENERATED_FILES
- ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h
- ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_types.h
- ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_enum.h
+ ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h
+ ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_types.h
+ ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_enum.h
)
set(HICN_VAPI_GENERATED_FILES
- ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.h
- ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.hpp)
+ ${PROJECT_BINARY_DIR}/vapi/hicn.api.vapi.h
+ ${PROJECT_BINARY_DIR}/vapi/hicn.api.vapi.hpp
+)
-set(HICN_VPP_STARTUP_CONF_FILE
- ${CMAKE_BINARY_DIR}/startup.conf)
+##############################################################
+# Assume VPP is installed in standard location
+##############################################################
if (NOT VPP_HOME)
- set(VPP_HOME /usr)
+ set(VPP_HOME /usr)
endif()
-if (NOT CMAKE_BUILD_TYPE)
- set (CMAKE_BUILD_TYPE "Release")
-endif (NOT CMAKE_BUILD_TYPE)
-
-SET(HICN_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} CACHE STRING "hicn_install_prefix")
-
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hicn)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vapi)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn)
-include(Packager)
-extract_version()
-
-# These files are missing from vpp binary distribution
-execute_process(
- COMMAND
- bash -c
- "if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ]; then
- curl https://raw.githubusercontent.com/FDio/vpp/stable/2106/src/vpp-api/vapi/vapi_json_parser.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py;
- fi;
- if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ]; then
- curl https://raw.githubusercontent.com/FDio/vpp/stable/2106/src/vpp-api/vapi/vapi_c_gen.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py;
- fi;
- if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py ]; then
- curl https://raw.githubusercontent.com/FDio/vpp/stable/2106/src/vpp-api/vapi/vapi_cpp_gen.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py;
- fi;
- if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_types.api ]; then
- curl https://raw.githubusercontent.com/FDio/vpp/stable/2106/src/vnet/ip/ip_types.api -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_types.api;
- fi;
- if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h ]; then
- curl https://raw.githubusercontent.com/FDio/vpp/stable/2106/src/vnet/fib/fib_entry_track.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h;
- fi;
- if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h ]; then
- curl https://raw.githubusercontent.com/FDio/vpp/stable/2106/src/vnet/udp/udp_encap.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h;
- fi;
-
- chmod +x ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py"
+##############################################################
+# RPath
+##############################################################
+SET(HICN_INSTALL_PREFIX
+ ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
)
-execute_process(
- COMMAND ${VPP_HOME}/bin/vppapigen --includedir ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h --outputdir ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/
- COMMAND ${VPP_HOME}/bin/vppapigen JSON --includedir ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json --outputdir ${CMAKE_CURRENT_BINARY_DIR}/vapi/
-)
-execute_process(
- COMMAND ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json
- COMMAND ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json
-)
-
-include_directories(SYSTEM)
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHICN_VPP_PLUGIN=1")
-add_library(hicn_plugin SHARED
- ${LIBHICN_FILES}
- ${HICN_PLUGIN_SOURCE_FILES}
- ${HICN_API_GENERATED_FILES}
- ${HICN_VAPI_GENERATED_FILES})
-file(COPY ${HICN_API_HEADER_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn)
-include_directories(${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins)
-
-file(COPY ${LIBHICN_HEADER_FILES_SRC} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn)
-file(COPY ${LIBHICN_HEADER_FILES_PROTOCOL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/protocol)
-file(COPY ${LIBHICN_HEADER_FILES_UTIL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/util)
-
-add_library(hicn_api_test_plugin SHARED
- ${HICN_API_TEST_SOURCE_FILES}
- ${HICN_API_GENERATED_FILES})
+##############################################################
+# Compiler Options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ ${MARCH_COMPILER_OPTIONS}
+ PRIVATE "-Wno-address-of-packed-member"
+)
-set(VPP_INSTALL_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_plugins)
-set(VPP_INSTALL_API_TEST_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_api_test_plugins CACHE STRING "vpp_install_api_test_plugin")
-set(VPP_STARTUP_CONF /etc/vpp/)
-set_target_properties(hicn_plugin
- PROPERTIES
- LINKER_LANGUAGE C
- INSTALL_RPATH ${VPP_INSTALL_PLUGIN}
- COMPILE_FLAGS "-march=native -Wno-address-of-packed-member"
- PREFIX "")
-set_target_properties(hicn_api_test_plugin
- PROPERTIES
- LINKER_LANGUAGE C
- COMPILE_FLAGS "-march=native -Wno-address-of-packed-member"
- PREFIX "")
+##############################################################
+# Compiler Definitions
+##############################################################
+set(COMPILE_DEFINITIONS
+ "-DHICN_VPP_PLUGIN=1"
+)
if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
- target_compile_definitions(hicn_plugin PRIVATE "CLIB_DEBUG")
- target_compile_definitions(hicn_api_test_plugin PRIVATE "CLIB_DEBUG")
+ list(APPEND COMPILE_DEFINITIONS
+ "-DHICN_DDEBUG"
+ "-DCLIB_DEBUG"
+ )
endif()
-message (STATUS "hicn-plugin variable ${HICN_PLUGIN}")
-install(DIRECTORY
- DESTINATION ${VPP_INSTALL_PLUGIN}
- COMPONENT ${HICN_PLUGIN})
-install(TARGETS hicn_plugin
- DESTINATION
- ${VPP_INSTALL_PLUGIN}
- COMPONENT ${HICN_PLUGIN})
+##############################################################
+# VPP API Generation
+##############################################################
+file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vapi)
+file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vpp_plugins/hicn)
-install(DIRECTORY
- DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN}
- COMPONENT ${HICN_PLUGIN})
-install(TARGETS hicn_api_test_plugin
- DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN}
- COMPONENT ${HICN_PLUGIN})
+execute_process(
+ COMMAND ${VPP_HOME}/bin/vppapigen --includedir ${VPP_HOME}/include --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h --outputdir ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/
+ COMMAND ${VPP_HOME}/bin/vppapigen JSON --includedir ${VPP_HOME}/include --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${PROJECT_BINARY_DIR}/vapi/hicn.api.json --outputdir ${PROJECT_BINARY_DIR}/vapi/
+)
+execute_process(
+ COMMAND ${VPP_HOME}/bin/vapi_c_gen.py ${PROJECT_BINARY_DIR}/vapi/hicn.api.json
+ COMMAND ${VPP_HOME}/bin/vapi_cpp_gen.py ${PROJECT_BINARY_DIR}/vapi/hicn.api.json
+)
-install(FILES ${HICN_API_HEADER_FILES} ${HICN_API_GENERATED_FILES}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn
- COMPONENT ${HICN_PLUGIN}-dev)
-install(FILES ${HICN_API_GENERATED_FILES}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn
- COMPONENT ${HICN_PLUGIN}-dev)
+##############################################################
+# Include directories
+##############################################################
+set(HICN_PLUGIN_INCLUDE_DIRS_INTERNAL
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${VPP_INCLUDE_DIR}
+ PUBLIC
+ $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
+ $<BUILD_INTERFACE:${HICNPLUGIN_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
-install(FILES ${HICN_VAPI_GENERATED_FILES}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vapi
- COMPONENT ${HICN_PLUGIN}-dev)
+##############################################################
+# Build hicn plugins for VPP
+##############################################################
+build_module(${HICNPLUGIN}
+ SOURCES ${HICN_PLUGIN_SOURCE_FILES}
+ INSTALL_HEADERS ${HICN_API_HEADER_FILES} ${HICN_API_GENERATED_FILES}
+ LINK_LIBRARIES PRIVATE ${LIBHICN_LIBRARIES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${HICN_PLUGIN}
+ INCLUDE_DIRS ${HICN_PLUGIN_INCLUDE_DIRS_INTERNAL}
+ HEADER_ROOT_DIR "vpp_plugins"
+ LIBRARY_ROOT_DIR "vpp_plugins"
+ DEFINITIONS PUBLIC ${COMPILE_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ INSTALL_RPATH "${VPP_INSTALL_PLUGIN}:${HICN_INSTALL_PREFIX}:${VPP_HOME}/lib"
+)
-#Set variables for other project depending on hicn-plugin
-set(HICNPLUGIN_INCLUDE_DIRS
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins
- ${VPP_INCLUDE_DIRS}
- CACHE INTERNAL "" FORCE)
-set(HICNPLUGIN_LIBRARIES ${VPP_LIBRARIES} CACHE INTERNAL "" FORCE)
+build_module(${HICN_API_TEST_PLUGIN}
+ SOURCES ${HICN_API_TEST_SOURCE_FILES}
+ INSTALL_HEADERS ${HICN_VAPI_GENERATED_FILES}
+ COMPONENT ${HICN_PLUGIN}
+ INCLUDE_DIRS ${HICN_PLUGIN_INCLUDE_DIRS_INTERNAL}
+ HEADER_ROOT_DIR "vapi"
+ LIBRARY_ROOT_DIR "vpp_api_test_plugins"
+ DEFINITIONS PUBLIC ${COMPILE_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+ INSTALL_RPATH "${VPP_INSTALL_PLUGIN}:${HICN_INSTALL_PREFIX}:${VPP_HOME}/lib"
+)
diff --git a/hicn-plugin/src/cache_policies/cs_lru.c b/hicn-plugin/src/cache_policies/cs_lru.c
index 408a6cb49..e65f487e1 100644
--- a/hicn-plugin/src/cache_policies/cs_lru.c
+++ b/hicn-plugin/src/cache_policies/cs_lru.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/cache_policies/cs_lru.h b/hicn-plugin/src/cache_policies/cs_lru.h
index c939b45df..35b82ff2c 100644
--- a/hicn-plugin/src/cache_policies/cs_lru.h
+++ b/hicn-plugin/src/cache_policies/cs_lru.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/cache_policies/cs_policy.h b/hicn-plugin/src/cache_policies/cs_policy.h
index 505138943..73f3de107 100644
--- a/hicn-plugin/src/cache_policies/cs_policy.h
+++ b/hicn-plugin/src/cache_policies/cs_policy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c
index 8ecbf7a95..cd45607ca 100644
--- a/hicn-plugin/src/cli.c
+++ b/hicn-plugin/src/cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -22,6 +22,9 @@
#include <vnet/ip/ip6_packet.h> // ip46_address_t
#include <vnet/ip/format.h>
#include <vnet/fib/fib_types.h>
+#include <vnet/pg/pg.h>
+
+#include <vpp_plugins/hicn/hicn_api.h>
#include "hicn.h"
#include "infra.h"
@@ -33,7 +36,6 @@
#include "error.h"
#include "faces/face.h"
#include "route.h"
-#include "hicn_api.h"
static vl_api_hicn_api_node_params_set_t node_ctl_params = {
.pit_max_size = -1,
@@ -65,8 +67,8 @@ hicn_cli_node_ctl_start_set_command_fn (vlib_main_t *vm,
get_error_string (ret));
return (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, get_error_string (ret));
+ 0 :
+ clib_error_return (0, get_error_string (ret));
}
/*
@@ -91,7 +93,7 @@ hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t *vm,
{
return (0);
}
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ if (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
return clib_error_return (0, "%s '%U'",
get_error_string (HICN_ERROR_CLI_INVAL),
@@ -103,8 +105,8 @@ hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t *vm,
node_ctl_params.pit_max_lifetime_sec, node_ctl_params.cs_max_size, ~0);
return (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, get_error_string (ret));
+ 0 :
+ clib_error_return (0, get_error_string (ret));
}
#define DFLTD_RANGE_OK(val, min, max) \
@@ -201,8 +203,8 @@ hicn_cli_node_ctl_param_set_command_fn (vlib_main_t *vm,
"compilation time for better performances\n");
return (rv == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, "%s '%U'", get_error_string (rv),
+ 0 :
+ clib_error_return (0, "%s '%U'", get_error_string (rv),
format_unformat_error, line_input);
}
@@ -213,7 +215,7 @@ static clib_error_t *
hicn_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
vlib_cli_command_t *cmd)
{
- int face_p = 0, fib_p = 0, all_p, internal_p = 0, strategies_p = 0,
+ int face_p = 0, fib_p = 0, all_p = 0, internal_p = 0, strategies_p = 0,
ret = HICN_ERROR_NONE;
/* Get a line of input. */
@@ -348,8 +350,8 @@ done:
hicn_main.pitcs.pcs_table->ht_overflow_buckets_used);
}
return (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, "%s\n", get_error_string (ret));
+ 0 :
+ clib_error_return (0, "%s\n", get_error_string (ret));
}
/*
@@ -408,8 +410,8 @@ hicn_cli_strategy_set_command_fn (vlib_main_t *vm,
rv = hicn_route_set_strategy (&prefix, strategy_id);
cl_err = (rv == HICN_ERROR_NONE) ?
- NULL :
- clib_error_return (0, get_error_string (rv));
+ NULL :
+ clib_error_return (0, get_error_string (rv));
done:
return (cl_err);
@@ -727,12 +729,25 @@ hicn_enable_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
goto done;
}
}
- rv = hicn_route_enable (&pfx);
+ hicn_face_id_t *vec_faces = NULL;
+ rv = hicn_route_enable (&pfx, &vec_faces);
+
+ if (vec_faces != NULL)
+ {
+ hicn_face_id_t *face_id;
+ u8 *str = 0;
+ vec_foreach (face_id, vec_faces)
+ {
+ str = format (str, " %d", *face_id);
+ }
+ vec_free (vec_faces);
+ vlib_cli_output (vm, "Faces for this prefix: %s", str);
+ }
done:
cl_err = (rv == HICN_ERROR_NONE) ?
- NULL :
- clib_error_return (0, get_error_string (rv));
+ NULL :
+ clib_error_return (0, get_error_string (rv));
return cl_err;
}
@@ -776,8 +791,8 @@ hicn_disable_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
done:
cl_err = (rv == HICN_ERROR_NONE) ?
- NULL :
- clib_error_return (0, get_error_string (rv));
+ NULL :
+ clib_error_return (0, get_error_string (rv));
return cl_err;
}
diff --git a/hicn-plugin/src/data_fwd.h b/hicn-plugin/src/data_fwd.h
index 96d8399e4..b21fa0a2f 100644
--- a/hicn-plugin/src/data_fwd.h
+++ b/hicn-plugin/src/data_fwd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c
index fe79b33fa..6acb5915b 100644
--- a/hicn-plugin/src/data_fwd_node.c
+++ b/hicn-plugin/src/data_fwd_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -428,9 +428,9 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
clones += 2;
next0 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT :
- HICN_DATA_FWD_NEXT_IFACE4_OUT;
+ HICN_DATA_FWD_NEXT_IFACE4_OUT;
next1 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT :
- HICN_DATA_FWD_NEXT_IFACE4_OUT;
+ HICN_DATA_FWD_NEXT_IFACE4_OUT;
vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0;
vnet_buffer (h1)->ip.adj_index[VLIB_TX] = face1;
@@ -481,7 +481,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
clones += 1;
next0 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT :
- HICN_DATA_FWD_NEXT_IFACE4_OUT;
+ HICN_DATA_FWD_NEXT_IFACE4_OUT;
vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0;
stats->pkts_data_count++;
@@ -548,10 +548,7 @@ clone_data_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
* the PIT part of the union as we update the CS part, so don't
* expect the PIT part to be valid after this point.
*/
- hicn_buffer_t *hicnb0 = hicn_get_buffer (b0);
- hicn_pit_to_cs (vm, pitcs, pitp, hash_entry, nodep, dpo_vft, hicn_dpo_id,
- hicnb->face_id,
- hicnb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP);
+ hicn_pit_to_cs (vm, pitcs, pitp, hash_entry, nodep, dpo_vft, hicn_dpo_id);
pitp->shared.create_time = tnow;
diff --git a/hicn-plugin/src/data_input_node.c b/hicn-plugin/src/data_input_node.c
index c94443a6b..46fda1080 100644
--- a/hicn-plugin/src/data_input_node.c
+++ b/hicn-plugin/src/data_input_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * 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:
@@ -75,6 +75,23 @@ format_hicn_data_input_trace (u8 *s, va_list *args)
return s;
}
+static void
+hicn_data_input_set_adj_index (vlib_buffer_t *b,
+ const ip46_address_t *dst_addr,
+ const hicn_dpo_ctx_t *dpo_ctx)
+{
+ for (u8 pos = 0; pos < dpo_ctx->entry_count; pos++)
+ {
+ hicn_face_t *face = hicn_dpoi_get_from_idx (dpo_ctx->next_hops[pos]);
+ assert (face);
+ if (ip46_address_cmp (&(face->nat_addr), dst_addr) == 0)
+ {
+ vnet_buffer (b)->ip.adj_index[VLIB_RX] = face->dpo.dpoi_index;
+ break;
+ }
+ }
+}
+
static uword
hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame)
@@ -100,6 +117,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
ip_lookup_next_t next0, next1;
ip6_header_t *ip0, *ip1;
ip6_address_t *src_addr0, *src_addr1;
+ ip46_address_t dst_addr0, dst_addr1;
const dpo_id_t *dpo0, *dpo1;
const load_balance_t *lb0, *lb1;
@@ -128,6 +146,9 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
src_addr0 = &ip0->src_address;
src_addr1 = &ip1->src_address;
+ ip46_address_set_ip6 (&dst_addr0, &ip0->dst_address);
+ ip46_address_set_ip6 (&dst_addr0, &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);
@@ -150,14 +171,22 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
dpo1 = load_balance_get_bucket_i (lb1, 0);
if (dpo_is_hicn (dpo0))
- next0 = HICN_DATA_INPUT_IP6_NEXT_FACE;
+ {
+ next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_FACE;
+ hicn_data_input_set_adj_index (
+ p0, &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
+ }
else
- next0 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
+ next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
if (dpo_is_hicn (dpo1))
- next1 = HICN_DATA_INPUT_IP6_NEXT_FACE;
+ {
+ next1 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_FACE;
+ hicn_data_input_set_adj_index (
+ p1, &dst_addr1, hicn_strategy_dpo_ctx_get (dpo1->dpoi_index));
+ }
else
- next1 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
+ next1 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
(p0->flags & VLIB_BUFFER_IS_TRACED))
@@ -235,6 +264,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
ip_lookup_next_t next0;
load_balance_t *lb0;
ip6_address_t *src_addr0;
+ ip46_address_t dst_addr0;
const dpo_id_t *dpo0;
pi0 = from[0];
@@ -243,6 +273,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
p0 = vlib_get_buffer (vm, pi0);
ip0 = vlib_buffer_get_current (p0);
src_addr0 = &ip0->src_address;
+ ip46_address_set_ip6 (&dst_addr0, &ip0->dst_address);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0);
lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index,
src_addr0);
@@ -255,9 +286,13 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
dpo0 = load_balance_get_bucket_i (lb0, 0);
if (dpo_is_hicn (dpo0))
- next0 = HICN_DATA_INPUT_IP6_NEXT_FACE;
+ {
+ next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_FACE;
+ hicn_data_input_set_adj_index (
+ p0, &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
+ }
else
- next0 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
+ next0 = (ip_lookup_next_t) HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL;
if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
(p0->flags & VLIB_BUFFER_IS_TRACED))
@@ -312,7 +347,7 @@ VLIB_REGISTER_NODE (hicn_data_input_ip6) = {
VNET_FEATURE_INIT (hicn_data_input_ip6_arc, static) = {
.arc_name = "ip6-local",
.node_name = "hicn-data-input-ip6",
- .runs_before = VNET_FEATURES ("ip6-local-end-of-arc"),
+ .runs_before = VNET_FEATURES ("ip6-local-end-of-arc")
};
always_inline uword
@@ -337,9 +372,8 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
ip4_header_t *ip0, *ip1, *ip2, *ip3;
const load_balance_t *lb0, *lb1, *lb2, *lb3;
- ip4_fib_mtrie_t *mtrie0, *mtrie1, *mtrie2, *mtrie3;
- ip4_fib_mtrie_leaf_t leaf0, leaf1, leaf2, leaf3;
ip4_address_t *src_addr0, *src_addr1, *src_addr2, *src_addr3;
+ ip46_address_t dst_addr0, dst_addr1, dst_addr2, dst_addr3;
u32 lb_index0, lb_index1, lb_index2, lb_index3;
const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
@@ -367,35 +401,21 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
src_addr2 = &ip2->src_address;
src_addr3 = &ip3->src_address;
+ ip46_address_set_ip4 (&dst_addr0, &ip0->dst_address);
+ ip46_address_set_ip4 (&dst_addr1, &ip1->dst_address);
+ ip46_address_set_ip4 (&dst_addr2, &ip2->dst_address);
+ ip46_address_set_ip4 (&dst_addr3, &ip3->dst_address);
+
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[2]);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[3]);
- mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie;
- mtrie1 = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie;
- mtrie2 = &ip4_fib_get (vnet_buffer (b[2])->ip.fib_index)->mtrie;
- mtrie3 = &ip4_fib_get (vnet_buffer (b[3])->ip.fib_index)->mtrie;
-
- leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0);
- leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, src_addr1);
- leaf2 = ip4_fib_mtrie_lookup_step_one (mtrie2, src_addr2);
- leaf3 = ip4_fib_mtrie_lookup_step_one (mtrie3, src_addr3);
-
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 2);
- leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, src_addr2, 2);
- leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, src_addr3, 2);
-
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 3);
- leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, src_addr2, 3);
- leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, src_addr3, 3);
-
- lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
- lb_index2 = ip4_fib_mtrie_leaf_get_adj_index (leaf2);
- lb_index3 = ip4_fib_mtrie_leaf_get_adj_index (leaf3);
+ ip4_fib_forwarding_lookup_x4 (
+ vnet_buffer (b[0])->ip.fib_index, vnet_buffer (b[1])->ip.fib_index,
+ vnet_buffer (b[2])->ip.fib_index, vnet_buffer (b[3])->ip.fib_index,
+ src_addr0, src_addr1, src_addr2, src_addr3, &lb_index0, &lb_index1,
+ &lb_index2, &lb_index3);
ASSERT (lb_index0 && lb_index1 && lb_index2 && lb_index3);
lb0 = load_balance_get (lb_index0);
@@ -418,22 +438,38 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
dpo3 = load_balance_get_bucket_i (lb3, 0);
if (dpo_is_hicn (dpo0))
- next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[0] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[0], &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
+ }
else
next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
if (dpo_is_hicn (dpo1))
- next[1] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[1] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[1], &dst_addr1, hicn_strategy_dpo_ctx_get (dpo1->dpoi_index));
+ }
else
next[1] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
if (dpo_is_hicn (dpo2))
- next[2] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[2] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[2], &dst_addr2, hicn_strategy_dpo_ctx_get (dpo2->dpoi_index));
+ }
else
next[2] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
if (dpo_is_hicn (dpo3))
- next[3] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[3] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[3], &dst_addr3, hicn_strategy_dpo_ctx_get (dpo3->dpoi_index));
+ }
else
next[3] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
@@ -495,9 +531,8 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
ip4_header_t *ip0, *ip1;
const load_balance_t *lb0, *lb1;
- ip4_fib_mtrie_t *mtrie0, *mtrie1;
- ip4_fib_mtrie_leaf_t leaf0, leaf1;
ip4_address_t *src_addr0, *src_addr1;
+ ip46_address_t dst_addr0, dst_addr1;
u32 lb_index0, lb_index1;
flow_hash_config_t flow_hash_config0, flow_hash_config1;
u32 hash_c0, hash_c1;
@@ -518,23 +553,15 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
src_addr0 = &ip0->src_address;
src_addr1 = &ip1->src_address;
+ ip46_address_set_ip4 (&dst_addr0, &ip0->dst_address);
+ ip46_address_set_ip4 (&dst_addr1, &ip1->dst_address);
+
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]);
- mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie;
- mtrie1 = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie;
-
- leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0);
- leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, src_addr1);
-
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 2);
-
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3);
- leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 3);
-
- lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
- lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
+ ip4_fib_forwarding_lookup_x2 (
+ vnet_buffer (b[0])->ip.fib_index, vnet_buffer (b[1])->ip.fib_index,
+ src_addr0, src_addr1, &lb_index0, &lb_index1);
ASSERT (lb_index0 && lb_index1);
lb0 = load_balance_get (lb_index0);
@@ -549,12 +576,20 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
dpo1 = load_balance_get_bucket_i (lb1, 0);
if (dpo_is_hicn (dpo0))
- next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[0] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[0], &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
+ }
else
next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
if (dpo_is_hicn (dpo1))
- next[1] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[1] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[1], &dst_addr1, hicn_strategy_dpo_ctx_get (dpo1->dpoi_index));
+ }
else
next[1] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
@@ -592,21 +627,18 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
ip4_header_t *ip0;
const load_balance_t *lb0;
- ip4_fib_mtrie_t *mtrie0;
- ip4_fib_mtrie_leaf_t leaf0;
ip4_address_t *src_addr0;
+ ip46_address_t dst_addr0;
u32 lbi0;
const dpo_id_t *dpo0;
ip0 = vlib_buffer_get_current (b[0]);
src_addr0 = &ip0->src_address;
+ ip46_address_set_ip4 (&dst_addr0, &ip0->dst_address);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
- mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie;
- leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2);
- leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3);
- lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
+ lbi0 = ip4_fib_forwarding_lookup (vnet_buffer (b[0])->ip.fib_index,
+ src_addr0);
ASSERT (lbi0);
lb0 = load_balance_get (lbi0);
@@ -617,7 +649,11 @@ hicn_data_input_ip4_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
dpo0 = load_balance_get_bucket_i (lb0, 0);
if (dpo_is_hicn (dpo0))
- next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE;
+ {
+ next[0] = (ip_lookup_next_t) HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
+ hicn_data_input_set_adj_index (
+ b[0], &dst_addr0, hicn_strategy_dpo_ctx_get (dpo0->dpoi_index));
+ }
else
next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL;
diff --git a/hicn-plugin/src/data_pcslookup.h b/hicn-plugin/src/data_pcslookup.h
index b548497b6..32fca952a 100644
--- a/hicn-plugin/src/data_pcslookup.h
+++ b/hicn-plugin/src/data_pcslookup.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c
index 073d06c96..69278c306 100644
--- a/hicn-plugin/src/data_pcslookup_node.c
+++ b/hicn-plugin/src/data_pcslookup_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -74,7 +74,7 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u32 node_id0 = 0;
index_t dpo_ctx_id0 = 0;
int ret0;
- u8 vft_id0;
+ u8 vft_id0 = 0;
u8 is_cs0;
u8 hash_entry_id = 0;
u8 bucket_is_overflown = 0;
diff --git a/hicn-plugin/src/error.c b/hicn-plugin/src/error.c
index 4c6986999..a64066d67 100644
--- a/hicn-plugin/src/error.c
+++ b/hicn-plugin/src/error.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-#include "error.h"
+#include <vpp_plugins/hicn/error.h>
const char *HICN_ERROR_STRING[] = {
#define _(a, b, c) c,
diff --git a/hicn-plugin/src/face_db.h b/hicn-plugin/src/face_db.h
index 1bc061721..37a2af9ca 100644
--- a/hicn-plugin/src/face_db.h
+++ b/hicn-plugin/src/face_db.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -78,8 +78,8 @@ hicn_face_db_get_dpo_face (u32 index, hicn_face_db_t *face_db)
ASSERT (index < face_db->n_faces);
return index < HICN_FACE_DB_INLINE_FACES ?
- (face_db->inline_faces[index]) :
- (pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket)
+ (face_db->inline_faces[index]) :
+ (pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket)
->faces[(index - HICN_FACE_DB_INLINE_FACES) &
(HICN_PIT_N_HOP_BUCKET - 1)]);
}
@@ -106,8 +106,8 @@ hicn_face_db_add_face (hicn_face_id_t face_id, hicn_face_db_t *face_db)
hicn_face_id_t *element =
face_db->n_faces < HICN_FACE_DB_INLINE_FACES ?
- &(face_db->inline_faces[face_db->n_faces]) :
- &(faces_bkt->faces[(face_db->n_faces - HICN_FACE_DB_INLINE_FACES) &
+ &(face_db->inline_faces[face_db->n_faces]) :
+ &(faces_bkt->faces[(face_db->n_faces - HICN_FACE_DB_INLINE_FACES) &
(HICN_PIT_N_HOP_BUCKET - 1)]);
*element = face_id;
diff --git a/hicn-plugin/src/faces/app/address_mgr.c b/hicn-plugin/src/faces/app/address_mgr.c
index b5d8ce7cb..44729fd69 100644
--- a/hicn-plugin/src/faces/app/address_mgr.c
+++ b/hicn-plugin/src/faces/app/address_mgr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -14,7 +14,7 @@
*/
/*
- * Copyright (c) 2017-2019 by cisco systems inc. All rights reserved.
+ * Copyright (c) 2021 by cisco systems inc. All rights reserved.
*
*/
@@ -31,10 +31,11 @@
#include <vnet/interface.h> //appif_flags
#include <vnet/interface_funcs.h> //vnet_sw_interface_set_flags
+#include <vpp_plugins/hicn/error.h>
+
#include "address_mgr.h"
#include "../../hicn.h"
#include "../../infra.h"
-#include "../../error.h"
#include "../face.h"
#include "../../strategy_dpo_ctx.h"
#include "../../route.h"
diff --git a/hicn-plugin/src/faces/app/address_mgr.h b/hicn-plugin/src/faces/app/address_mgr.h
index bd834f063..32545f8ca 100644
--- a/hicn-plugin/src/faces/app/address_mgr.h
+++ b/hicn-plugin/src/faces/app/address_mgr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/faces/app/face_app_cli.c b/hicn-plugin/src/faces/app/face_app_cli.c
index ccdee4450..b3488c462 100644
--- a/hicn-plugin/src/faces/app/face_app_cli.c
+++ b/hicn-plugin/src/faces/app/face_app_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -114,8 +114,8 @@ hicn_face_app_cli_set_command_fn (vlib_main_t *vm,
if (prod)
{
prefix.fp_proto = ip46_address_is_ip4 (&prefix.fp_addr) ?
- FIB_PROTOCOL_IP4 :
- FIB_PROTOCOL_IP6;
+ FIB_PROTOCOL_IP4 :
+ FIB_PROTOCOL_IP6;
rv = hicn_face_prod_add (&prefix, sw_if, &cs_reserved, &prod_addr,
&face_id1);
if (rv == HICN_ERROR_NONE)
@@ -175,8 +175,8 @@ hicn_face_app_cli_set_command_fn (vlib_main_t *vm,
break;
}
return (rv == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, "%s\n", get_error_string (rv));
+ 0 :
+ clib_error_return (0, "%s\n", get_error_string (rv));
}
/* cli declaration for 'cfg face' */
diff --git a/hicn-plugin/src/faces/app/face_cons.c b/hicn-plugin/src/faces/app/face_cons.c
index 53b955775..edb03387d 100644
--- a/hicn-plugin/src/faces/app/face_cons.c
+++ b/hicn-plugin/src/faces/app/face_cons.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -69,10 +69,10 @@ hicn_face_cons_add (ip4_address_t *nh_addr4, ip6_address_t *nh_addr6, u32 swif,
0 /* is_del */);
ip46_address_t nh_addr = to_ip46 (0, (u8 *) nh_addr6);
- index_t adj_index = adj_nbr_find (FIB_PROTOCOL_IP6, VNET_LINK_IP6, &nh_addr, swif);
+ index_t adj_index =
+ adj_nbr_find (FIB_PROTOCOL_IP6, VNET_LINK_IP6, &nh_addr, swif);
- hicn_iface_add ((ip46_address_t *) nh_addr6, swif, faceid2, DPO_PROTO_IP6,
- adj_index);
+ hicn_iface_add ((ip46_address_t *) nh_addr6, swif, faceid2, adj_index, 0);
hicn_face_t *face = hicn_dpoi_get_from_idx (*faceid2);
face->flags |= HICN_FACE_FLAGS_APPFACE_CONS;
@@ -90,7 +90,7 @@ hicn_face_cons_del (hicn_face_id_t face_id)
if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS)
{
- return hicn_face_del (face_id);
+ return hicn_face_unlock_with_id (face_id);
}
else
{
diff --git a/hicn-plugin/src/faces/app/face_cons.h b/hicn-plugin/src/faces/app/face_cons.h
index 3ff246f4f..9df6f773f 100644
--- a/hicn-plugin/src/faces/app/face_cons.h
+++ b/hicn-plugin/src/faces/app/face_cons.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c
index 16b6e6158..1e569b82b 100644
--- a/hicn-plugin/src/faces/app/face_prod.c
+++ b/hicn-plugin/src/faces/app/face_prod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -30,7 +30,7 @@ hicn_face_prod_state_t *face_state_vec;
u32 *face_state_pool;
static int
-hicn_app_state_create (u32 swif, fib_prefix_t *prefix)
+hicn_app_state_create (u32 swif, index_t adj_index, fib_prefix_t *prefix)
{
/* Make sure that the pool is not empty */
pool_validate_index (face_state_pool, 0);
@@ -49,6 +49,7 @@ hicn_app_state_create (u32 swif, fib_prefix_t *prefix)
/* Create the appif and store in the vector */
vec_validate (face_state_vec, swif);
+ face_state_vec[swif].adj_index = adj_index;
clib_memcpy (&(face_state_vec[swif].prefix), prefix, sizeof (fib_prefix_t));
/* Set as busy the element in the vector */
@@ -119,7 +120,7 @@ hicn_face_prod_add (fib_prefix_t *prefix, u32 sw_if, u32 *cs_reserved,
hicn_main_t *hm = &hicn_main;
- ip46_address_t local_app_ip;
+ ip46_address_t local_app_ip = { .as_u64 = { 0, 0 } };
CLIB_UNUSED (ip46_address_t remote_app_ip);
u32 if_flags = 0;
@@ -139,10 +140,11 @@ hicn_face_prod_add (fib_prefix_t *prefix, u32 sw_if, u32 *cs_reserved,
if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
vnet_sw_interface_set_flags (vnm, sw_if, if_flags);
+#ifdef HICN_DDEBUG
u8 *s0;
s0 = format (0, "Prefix %U", format_fib_prefix, prefix);
-
- vlib_cli_output (vm, "Received request for %s, swif %d\n", s0, sw_if);
+ HICN_DEBUG ("Received request for %s, swif %d\n", s0, sw_if);
+#endif
if (ip46_address_is_zero (&prefix->fp_addr))
{
@@ -268,15 +270,21 @@ hicn_face_prod_add (fib_prefix_t *prefix, u32 sw_if, u32 *cs_reserved,
fib_table_entry_path_add2 (fib_index, prefix, FIB_SOURCE_CLI,
FIB_ENTRY_FLAG_NONE, rpaths);
- hicn_route_enable (prefix);
- hicn_app_state_create (sw_if, prefix);
+ HICN_DEBUG ("Calling hicn enable for producer face");
+
+ hicn_face_id_t *vec_faces = NULL;
+ hicn_route_enable (prefix, &vec_faces);
+ if (vec_faces != NULL)
+ vec_free (vec_faces);
+
+ adj_index =
+ adj_nbr_find (isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4,
+ isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if);
+
+ hicn_app_state_create (sw_if, adj_index, prefix);
}
- adj_index =
- adj_nbr_find (isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4,
- isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if);
- face = hicn_face_get (&local_app_ip, sw_if, &hicn_face_hashtb,
- adj_index); // HICN_FACE_FLAGS_APPFACE_PROD);
+ face = hicn_face_get (&local_app_ip, sw_if, &hicn_face_hashtb, adj_index);
*faceid = hicn_dpoi_get_index (face);
@@ -289,6 +297,7 @@ hicn_face_prod_add (fib_prefix_t *prefix, u32 sw_if, u32 *cs_reserved,
/* Cleanup in case of something went wrong. */
if (ret)
{
+ HICN_ERROR ("Somethig went wrong while adding producer face. Cleanup.");
hicn_app_state_del (sw_if);
}
return ret;
@@ -304,17 +313,32 @@ hicn_face_prod_del (hicn_face_id_t face_id)
if (face->flags & HICN_FACE_FLAGS_APPFACE_PROD)
{
- /* Remove the face from the fib */
- hicn_route_disable (&(face_state_vec[face->sw_if].prefix));
- // hicn_route_del_nhop (&(face_state_vec[face->sw_if].prefix),
- // face_id);
-
- // int ret = hicn_face_del (face_id);
- return hicn_app_state_del (face->sw_if);
- // ret == HICN_ERROR_NONE ? hicn_app_state_del (face->sw_if) : ret;
+ /* Remove the face from the hicn fib */
+ fib_prefix_t *prefix = &(face_state_vec[face->sw_if].prefix);
+ HICN_DEBUG ("Calling hicn_route_disable from hicn_face_prod_del");
+ int ret = hicn_route_disable (prefix);
+ if (ret)
+ {
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_cli_output (vm, "Error disabling route: %s",
+ get_error_string (ret));
+ }
+ /* Also remove it from main fib, as we sre the owners of this prefix */
+ u32 fib_index = fib_table_find (prefix->fp_proto, 0);
+ fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_CLI);
+ ret = hicn_app_state_del (face->sw_if);
+ if (ret)
+ {
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_cli_output (vm, "Error deelting app state: %s",
+ get_error_string (ret));
+ }
}
else
{
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_cli_output (vm, "APPFACE not found.",
+ get_error_string (HICN_ERROR_APPFACE_NOT_FOUND));
return HICN_ERROR_APPFACE_NOT_FOUND;
}
diff --git a/hicn-plugin/src/faces/app/face_prod.h b/hicn-plugin/src/faces/app/face_prod.h
index 4acf89dfc..51373d541 100644
--- a/hicn-plugin/src/faces/app/face_prod.h
+++ b/hicn-plugin/src/faces/app/face_prod.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -50,6 +50,7 @@
typedef struct
{
fib_prefix_t prefix;
+ index_t adj_index;
} hicn_face_prod_state_t;
extern hicn_face_prod_state_t *face_state_vec;
diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c
index c4c9edc32..5d2b54040 100644
--- a/hicn-plugin/src/faces/app/face_prod_node.c
+++ b/hicn-plugin/src/faces/app/face_prod_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -24,7 +24,6 @@
*/
#include "face_prod.h"
-#include "../../hicn_api.h"
#include "../../mgmt.h"
static __clib_unused char *face_prod_input_error_strings[] = {
@@ -114,7 +113,7 @@ hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t *node, vlib_buffer_t *b,
}
return match_res ? HICN_FACE_PROD_NEXT_DATA_IP4 + (v == 0x60) :
- HICN_FACE_PROD_NEXT_ERROR_DROP;
+ HICN_FACE_PROD_NEXT_ERROR_DROP;
}
static_always_inline void
@@ -151,6 +150,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from >= 8 && n_left_to_next >= 4)
{
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;
@@ -190,11 +190,30 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
b2 = vlib_get_buffer (vm, bi2);
b3 = vlib_get_buffer (vm, bi3);
+ hicnb0 = hicn_get_buffer (b0);
+ hicnb1 = hicn_get_buffer (b1);
+ hicnb2 = hicn_get_buffer (b2);
+ hicnb3 = hicn_get_buffer (b3);
+
+ hicnb0->flags = HICN_FACE_FLAGS_DEFAULT;
+ hicnb1->flags = HICN_FACE_FLAGS_DEFAULT;
+ 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 =
@@ -226,6 +245,7 @@ hicn_face_prod_input_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;
+ hicn_buffer_t *hicnb0;
u32 bi0, swif;
hicn_face_prod_state_t *prod_face = NULL;
u32 next0;
@@ -245,11 +265,15 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
n_left_to_next -= 1;
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;
stats.pkts_data_count++;
/* trace */
diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c
index d62054365..854fd81d3 100644
--- a/hicn-plugin/src/faces/face.c
+++ b/hicn-plugin/src/faces/face.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -57,11 +57,8 @@ face_show (u8 *s, int face_id, u32 indent)
return (s);
}
-mhash_t hicn_face_vec_hashtb;
mhash_t hicn_face_hashtb;
-hicn_face_vec_t *hicn_vec_pool;
-
const static char *const hicn_face6_nodes[] = {
"hicn6-face-output", // this is the name you give your node in
// VLIB_REGISTER_NODE
@@ -163,14 +160,9 @@ hicn_face_module_init (vlib_main_t *vm)
counters = vec_new (vlib_combined_counter_main_t,
HICN_PARAM_FACES_MAX * HICN_N_COUNTER);
- mhash_init (&hicn_face_vec_hashtb,
- sizeof (hicn_face_input_faces_t) /* value */,
- sizeof (hicn_face_key_t) /* key */);
mhash_init (&hicn_face_hashtb, sizeof (hicn_face_id_t) /* value */,
sizeof (hicn_face_key_t) /* key */);
- pool_alloc (hicn_vec_pool, 100);
-
/*
* How much useful is the following registration?
* So far it seems that we need it only for setting the dpo_type.
@@ -182,7 +174,7 @@ hicn_face_module_init (vlib_main_t *vm)
* corresponding to a face is updated
*/
hicn_face_fib_node_type =
- fib_node_register_new_type (&hicn_face_fib_node_vft);
+ fib_node_register_new_type ("hicn_face_fib_node", &hicn_face_fib_node_vft);
}
u8 *
@@ -256,46 +248,11 @@ format_hicn_face_all (u8 *s, int n, ...)
int
hicn_face_del (hicn_face_id_t face_id)
{
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- hicn_face_key_t key;
- hicn_face_key_t old_key;
- hicn_face_key_t old_key2;
-
- hicn_face_get_key (&(face->nat_addr), face->sw_if, &(face->dpo), &key);
- hicn_face_input_faces_t *in_faces_vec =
- hicn_face_get_vec (&(face->nat_addr), &hicn_face_vec_hashtb);
- if (in_faces_vec != NULL)
- {
- hicn_face_vec_t *vec =
- pool_elt_at_index (hicn_vec_pool, in_faces_vec->vec_id);
- u32 index_face = vec_search (*vec, face_id);
- vec_del1 (*vec, index_face);
-
- if (vec_len (*vec) == 0)
- {
- pool_put_index (hicn_vec_pool, in_faces_vec->vec_id);
- mhash_unset (&hicn_face_vec_hashtb, &key, (uword *) &old_key);
- vec_free (*vec);
- }
- else
- {
- /* Check if the face we are deleting is the preferred one. */
- /* If so, repleace with another. */
- if (in_faces_vec->face_id == face_id)
- {
- in_faces_vec->face_id = (*vec)[0];
- }
- }
-
- mhash_unset (&hicn_face_hashtb, &key, (uword *) &old_key2);
- }
-
int ret = HICN_ERROR_NONE;
if (hicn_dpoi_idx_is_valid (face_id))
{
hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- face->locks--;
if (face->locks == 0)
pool_put_index (hicn_dpoi_face_pool, face_id);
else
@@ -320,7 +277,7 @@ hicn_iface_to_face (hicn_face_t *face, const dpo_id_t *dpo)
fib_node_init (&face->fib_node, hicn_face_fib_node_type);
fib_node_lock (&face->fib_node);
- if (dpo->dpoi_type != DPO_ADJACENCY_MIDCHAIN ||
+ if (dpo->dpoi_type != DPO_ADJACENCY_MIDCHAIN &&
dpo->dpoi_type != DPO_ADJACENCY_MCAST_MIDCHAIN)
{
ip_adjacency_t *adj = adj_get (dpo->dpoi_index);
@@ -375,8 +332,7 @@ hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, int sw_if,
if (face == NULL)
{
- hicn_iface_add (nat_address, sw_if, pfaceid, dpo_nh->dpoi_proto,
- dpo_nh->dpoi_index);
+ hicn_iface_add (nat_address, sw_if, pfaceid, dpo_nh->dpoi_index, 0);
face = hicn_dpoi_get_from_idx (*pfaceid);
mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0);
@@ -395,52 +351,6 @@ hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, int sw_if,
temp_dpo.dpoi_index = ~0;
- hicn_face_input_faces_t *in_faces =
- hicn_face_get_vec (nat_address, &hicn_face_vec_hashtb);
-
- if (in_faces == NULL)
- {
- hicn_face_input_faces_t in_faces_temp;
- hicn_face_vec_t *vec;
- pool_get (hicn_vec_pool, vec);
- *vec = vec_new (hicn_face_id_t, 0);
- u32 index = vec - hicn_vec_pool;
- in_faces_temp.vec_id = index;
- vec_add1 (*vec, *pfaceid);
-
- in_faces_temp.face_id = *pfaceid;
-
- hicn_face_get_key (nat_address, 0, &temp_dpo, &key);
-
- mhash_set_mem (&hicn_face_vec_hashtb, &key, (uword *) &in_faces_temp, 0);
- }
- else
- {
- hicn_face_vec_t *vec =
- pool_elt_at_index (hicn_vec_pool, in_faces->vec_id);
-
- /* */
- if (vec_search (*vec, *pfaceid) != ~0)
- return HICN_ERROR_FACE_ALREADY_CREATED;
-
- vec_add1 (*vec, *pfaceid);
-
- hicn_iface_to_face (face, dpo_nh);
-
- hicn_face_get_key (nat_address, 0, &temp_dpo, &key);
-
- mhash_set_mem (&hicn_face_vec_hashtb, &key, (uword *) in_faces, 0);
-
- /* If the face is an application producer face, we set it as the
- * preferred incoming face. */
- /* This is required to handle the CS separation, and the push api in a
- * lightway */
- if (is_app_prod)
- {
- in_faces->face_id = *pfaceid;
- }
- }
-
retx_t *retx = vlib_process_signal_event_data (
vlib_get_main (), hicn_mapme_eventmgr_process_node.index,
HICN_MAPME_EVENT_FACE_ADD, 1, sizeof (retx_t));
diff --git a/hicn-plugin/src/faces/face.h b/hicn-plugin/src/faces/face.h
index cb706eeca..39505c942 100644
--- a/hicn-plugin/src/faces/face.h
+++ b/hicn-plugin/src/faces/face.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -25,7 +25,11 @@
#include <vppinfra/bihash_8_8.h>
#include <vnet/adj/adj_midchain.h>
-#include "../error.h"
+#include <vpp_plugins/hicn/error.h>
+
+#include "../udp_tunnels/udp_tunnel.h"
+#include "../hicn_logging.h"
+
typedef u8 hicn_face_flags_t;
typedef index_t hicn_face_id_t;
@@ -66,12 +70,8 @@ typedef index_t hicn_face_id_t;
* - fib_node, fib_entry_index and fib_sibling are information used to be
* notified of changes in the adjacency pointed by the dpo.
*
- * We maintain two hash tables to retrieve faces and ifaces. In particular one
- * hash table which index faces and ifaces for nat_address, sw_if and dpo. This
- * is used to retrieve existing faces or ifaces when an interest is received
- * and when an new face is created. A second hash table that indexes vectors of
- * faces for nat_address and sw_if. This is used to retrieve a list of possible
- * incoming faces when a data is received.
+ * We maintain one hash tables to retrieve faces and ifaces, which indexes
+ * faces and ifaces for nat_address, sw_if and dpo.
*/
/**
@@ -129,14 +129,17 @@ extern hicn_face_t *hicn_dpoi_face_pool;
#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_FACE_IS_APP 0x01
+#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,
@@ -148,16 +151,6 @@ STATIC_ASSERT ((1 << HICN_FACE_FLAGS_APPFACE_CONS_BIT) ==
"HICN_FACE_FLAGS_APPFACE_CONS_BIT and "
"HICN_FACE_FLAGS_APPFACE_CONS must correspond");
-STATIC_ASSERT (
- (HICN_FACE_FLAGS_APPFACE_PROD >> HICN_FACE_FLAGS_APPFACE_PROD_BIT) ==
- HICN_BUFFER_FLAGS_FACE_IS_APP,
- "hicn buffer app flag does not correspond to HICN_FACE_FLAGS_APPFACE_PROD");
-
-STATIC_ASSERT (
- (HICN_FACE_FLAGS_APPFACE_CONS >> HICN_FACE_FLAGS_APPFACE_CONS_BIT) ==
- HICN_BUFFER_FLAGS_FACE_IS_APP,
- "hicn buffer app flag does not correspond to HICN_FACE_FLAGS_APPFACE_PROD");
-
/**
* @brief Definition of the virtual functin table for an hICN FACE DPO.
*/
@@ -257,6 +250,15 @@ hicn_dpoi_idx_is_valid (hicn_face_id_t face_id)
}
/**
+ * @brief Delete a face
+ *
+ * @param face_id Id of the face to delete
+ * @return HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise
+ * HICN_ERROR_NONE
+ */
+int hicn_face_del (hicn_face_id_t face_id);
+
+/**
* @brief Add a lock to the face dpo
*
* @param dpo Pointer to the face dpo
@@ -274,12 +276,24 @@ hicn_face_lock_with_id (hicn_face_id_t face_id)
*
* @param dpo Pointer to the face dpo
*/
-always_inline void
+always_inline int
hicn_face_unlock_with_id (hicn_face_id_t face_id)
{
hicn_face_t *face;
face = hicn_dpoi_get_from_idx (face_id);
- face->locks--;
+
+ if (face->locks > 0)
+ {
+ face->locks--;
+
+ if (face->locks == 0)
+ {
+ HICN_DEBUG ("Deleting face %d", face_id);
+ return hicn_face_del (face_id);
+ }
+ }
+
+ return HICN_ERROR_NONE;
}
/**
@@ -324,15 +338,6 @@ u8 *format_hicn_face (u8 *s, va_list *args);
u8 *format_hicn_face_all (u8 *s, int n, ...);
/**
- * @brief Delete a face
- *
- * @param face_id Id of the face to delete
- * @return HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise
- * HICN_ERROR_NONE
- */
-int hicn_face_del (hicn_face_id_t face_id);
-
-/**
* @bried vector of faces used to collect faces having the same local address
*
*/
@@ -355,17 +360,6 @@ typedef struct hicn_input_faces_s_
} hicn_face_input_faces_t;
/**
- * Pool containing the vector of possible incoming faces.
- */
-extern hicn_face_vec_t *hicn_vec_pool;
-
-/**
- * Hash tables that indexes a face by remote address. For fast lookup when an
- * interest arrives.
- */
-extern mhash_t hicn_face_vec_hashtb;
-
-/**
* Key definition for the mhash table. An face is uniquely identified by ip
* address, the interface id and a dpo pointing to the next node in the vlib
* graph. The ip address can correspond to the remote ip address of the next
@@ -437,7 +431,7 @@ hicn_face_get (const ip46_address_t *addr, u32 sw_if, mhash_t *hashtb,
hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb, &key);
- if (dpoi_index != NULL)
+ if (dpoi_index != NULL && hicn_dpoi_idx_is_valid (*dpoi_index))
{
hicn_face_lock_with_id (*dpoi_index);
return hicn_dpoi_get_from_idx (*dpoi_index);
@@ -467,7 +461,7 @@ hicn_face_get_with_dpo (const ip46_address_t *addr, u32 sw_if,
hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb, &key);
- if (dpoi_index != NULL)
+ if (dpoi_index != NULL && hicn_dpoi_idx_is_valid (*dpoi_index))
{
hicn_face_lock_with_id (*dpoi_index);
return hicn_dpoi_get_from_idx (*dpoi_index);
@@ -477,28 +471,6 @@ hicn_face_get_with_dpo (const ip46_address_t *addr, u32 sw_if,
}
/**
- * @brief Get the vector of faces from the ip v4 address. Does not add any
- * lock.
- *
- * @param addr Ip v4 address used to create the key for the hash table.
- * @param sw_if Software interface id used to create the key for the hash
- * table.
- * @param hashtb Hash table (remote or local) where to perform the lookup.
- *
- * @result Pointer to the face.
- */
-always_inline hicn_face_input_faces_t *
-hicn_face_get_vec (const ip46_address_t *addr, mhash_t *hashtb)
-{
- hicn_face_key_t key;
-
- dpo_id_t dpo = DPO_INVALID;
-
- hicn_face_get_key (addr, 0, &dpo, &key);
- return (hicn_face_input_faces_t *) mhash_get (hashtb, &key);
-}
-
-/**
* @brief Create a new face ip. API for other modules (e.g., routing)
*
* @param dpo_nh dpo contained in the face that points to the next node in
@@ -526,7 +498,7 @@ int hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address,
*/
always_inline void
hicn_iface_add (ip46_address_t *nat_address, int sw_if,
- hicn_face_id_t *pfaceid, dpo_proto_t proto, u32 adj_index)
+ hicn_face_id_t *pfaceid, u32 adj_index, u8 flags)
{
hicn_face_t *face;
pool_get (hicn_dpoi_face_pool, face);
@@ -534,16 +506,19 @@ hicn_iface_add (ip46_address_t *nat_address, int sw_if,
clib_memcpy (&(face->nat_addr), nat_address, sizeof (ip46_address_t));
face->sw_if = sw_if;
- face->dpo.dpoi_type = DPO_FIRST;
- face->dpo.dpoi_proto = DPO_PROTO_NONE;
+ face->dpo = (dpo_id_t) DPO_INVALID;
face->dpo.dpoi_index = adj_index;
- face->dpo.dpoi_next_node = 0;
+
+ hicn_face_key_t key;
+ hicn_face_get_key (nat_address, sw_if, &face->dpo, &key);
+
+ face->dpo.dpoi_next_node = 1;
+
face->pl_id = pl_index++;
face->flags = HICN_FACE_FLAGS_IFACE;
+ face->flags |= flags;
face->locks = 1;
- hicn_face_key_t key;
- hicn_face_get_key (nat_address, sw_if, &face->dpo, &key);
*pfaceid = hicn_dpoi_get_index (face);
mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0);
@@ -560,79 +535,6 @@ hicn_iface_add (ip46_address_t *nat_address, int sw_if,
* ****/
/**
- * @brief Retrieve a vector of faces from the ip4 local address and returns its
- * index.
- *
- * @param vec: Result of the lookup. If no face exists for the local address
- * vec = NULL
- * @param hicnb_flags: Flags that indicate whether the face is an application
- * face or not
- * @param local_addr: Ip v4 nat address of the face
- * @param sw_if: software interface id of the face
- *
- * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise
- * HICN_ERROR_NONE.
- */
-always_inline int
-hicn_face_ip4_lock (hicn_face_id_t *face_id, u32 *in_faces_vec_id,
- u8 *hicnb_flags, const ip4_address_t *nat_addr)
-{
- ip46_address_t ip_address = { 0 };
- ip46_address_set_ip4 (&ip_address, nat_addr);
- hicn_face_input_faces_t *in_faces_vec =
- hicn_face_get_vec (&ip_address, &hicn_face_vec_hashtb);
-
- if (PREDICT_FALSE (in_faces_vec == NULL))
- return HICN_ERROR_FACE_NOT_FOUND;
-
- *in_faces_vec_id = in_faces_vec->vec_id;
- hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |= (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- *face_id = in_faces_vec->face_id;
-
- return HICN_ERROR_NONE;
-}
-
-/**
- * @brief Retrieve a face from the ip6 local address and returns its dpo. This
- * method adds a lock on the face state.
- *
- * @param dpo: Result of the lookup. If the face doesn't exist dpo = NULL
- * @param hicnb_flags: Flags that indicate whether the face is an application
- * face or not
- * @param nat_addr: Ip v6 nat address of the face
- * @param sw_if: software interface id of the face
- *
- * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise
- * HICN_ERROR_NONE.
- */
-always_inline int
-hicn_face_ip6_lock (hicn_face_id_t *face_id, u32 *in_faces_vec_id,
- u8 *hicnb_flags, const ip6_address_t *nat_addr)
-{
- hicn_face_input_faces_t *in_faces_vec =
- hicn_face_get_vec ((ip46_address_t *) nat_addr, &hicn_face_vec_hashtb);
-
- if (PREDICT_FALSE (in_faces_vec == NULL))
- return HICN_ERROR_FACE_NOT_FOUND;
-
- *in_faces_vec_id = in_faces_vec->vec_id;
- hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |= (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- *face_id = in_faces_vec->face_id;
-
- return HICN_ERROR_NONE;
-}
-
-/**
* @brief Call back to get the adj of the tunnel
*/
static adj_walk_rc_t
@@ -658,11 +560,12 @@ hicn4_iface_adj_walk_cb (adj_index_t ai, void *ctx)
* @param sw_if: software interface id of the face
* @param node_index: vlib edge index to use in the packet processing
*/
-always_inline void
-hicn_iface_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
- const ip4_address_t *nat_addr, u32 sw_if,
- u32 adj_index, u32 node_index)
+always_inline int
+hicn_face_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
+ const ip4_address_t *nat_addr, u32 sw_if,
+ u32 adj_index, u32 node_index)
{
+ int ret = HICN_ERROR_NONE;
/*All (complete) faces are indexed by remote addess as well */
ip46_address_t ip_address = { 0 };
@@ -675,12 +578,30 @@ hicn_iface_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
if (face == NULL)
{
hicn_face_id_t idx;
- hicn_iface_add (&ip_address, sw_if, &idx, DPO_PROTO_IP4, adj_index);
+ u8 face_flags = 0;
+
+ hicn_iface_add (&ip_address, sw_if, &idx, adj_index, face_flags);
face = hicn_dpoi_get_from_idx (idx);
- face->dpo.dpoi_type = DPO_FIRST;
- face->dpo.dpoi_proto = DPO_PROTO_IP4;
+ if (*hicnb_flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL &&
+ adj_index != ADJ_INDEX_INVALID)
+ {
+ face->dpo.dpoi_type = dpo_type_udp_ip6;
+ face->dpo.dpoi_proto = DPO_PROTO_IP6;
+ }
+ else if (*hicnb_flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL &&
+ adj_index != ADJ_INDEX_INVALID)
+ {
+ face->dpo.dpoi_type = dpo_type_udp_ip4;
+ face->dpo.dpoi_proto = DPO_PROTO_IP4;
+ }
+ else
+ {
+ face->dpo.dpoi_type = DPO_FIRST;
+ face->dpo.dpoi_proto = DPO_PROTO_IP6;
+ }
+
face->dpo.dpoi_index = adj_index;
face->dpo.dpoi_next_node = node_index;
@@ -691,15 +612,17 @@ hicn_iface_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
/* } */
*hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
+ *hicnb_flags |= HICN_BUFFER_FLAGS_NEW_FACE;
*index = idx;
- return;
+ return ret;
}
else
{
/* unlock the face. We don't take a lock on each interest we receive */
hicn_face_id_t face_id = hicn_dpoi_get_index (face);
hicn_face_unlock_with_id (face_id);
+ ret = HICN_ERROR_FACE_ALREADY_CREATED;
}
/* Code replicated on purpose */
@@ -708,6 +631,8 @@ hicn_iface_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
HICN_FACE_FLAGS_APPFACE_PROD_BIT;
*index = hicn_dpoi_get_index (face);
+
+ return ret;
}
/**
@@ -723,7 +648,8 @@ hicn6_iface_adj_walk_cb (adj_index_t ai, void *ctx)
if ((adj->lookup_next_index == IP_LOOKUP_NEXT_MIDCHAIN) ||
(adj->lookup_next_index == IP_LOOKUP_NEXT_MCAST_MIDCHAIN))
{
- dpo_set (&face->dpo, DPO_ADJACENCY_MIDCHAIN, adj->ia_nh_proto, ai);
+ dpo_set (&face->dpo, DPO_ADJACENCY_MIDCHAIN,
+ (dpo_proto_t) adj->ia_nh_proto, ai);
adj_nbr_midchain_stack (ai, &face->dpo);
}
@@ -741,11 +667,13 @@ hicn6_iface_adj_walk_cb (adj_index_t ai, void *ctx)
* @param sw_if: software interface id of the face
* @param node_index: vlib edge index to use in the packet processing
*/
-always_inline void
-hicn_iface_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
- const ip6_address_t *nat_addr, u32 sw_if,
- u32 adj_index, u32 node_index)
+always_inline int
+hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
+ const ip6_address_t *nat_addr, u32 sw_if,
+ u32 adj_index, u32 node_index)
{
+ int ret = HICN_ERROR_NONE;
+
/*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,
@@ -754,13 +682,30 @@ hicn_iface_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
if (face == NULL)
{
hicn_face_id_t idx;
- hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, DPO_PROTO_IP6,
- adj_index);
+ u8 face_flags = 0;
+
+ hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, adj_index,
+ face_flags);
face = hicn_dpoi_get_from_idx (idx);
- face->dpo.dpoi_type = DPO_FIRST;
- face->dpo.dpoi_proto = DPO_PROTO_IP6;
+ if (*hicnb_flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL &&
+ adj_index != ADJ_INDEX_INVALID)
+ {
+ face->dpo.dpoi_type = dpo_type_udp_ip6;
+ face->dpo.dpoi_proto = DPO_PROTO_IP6;
+ }
+ else if (*hicnb_flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL &&
+ adj_index != ADJ_INDEX_INVALID)
+ {
+ face->dpo.dpoi_type = dpo_type_udp_ip4;
+ face->dpo.dpoi_proto = DPO_PROTO_IP4;
+ }
+ else
+ {
+ face->dpo.dpoi_type = DPO_FIRST;
+ face->dpo.dpoi_proto = DPO_PROTO_IP6;
+ }
face->dpo.dpoi_index = adj_index;
face->dpo.dpoi_next_node = node_index;
@@ -768,16 +713,18 @@ hicn_iface_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
face);
*hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
+ *hicnb_flags |= HICN_BUFFER_FLAGS_NEW_FACE;
*index = idx;
- return;
+ return ret;
}
else
{
/* unlock the face. We don't take a lock on each interest we receive */
hicn_face_id_t face_id = hicn_dpoi_get_index (face);
hicn_face_unlock_with_id (face_id);
+ ret = HICN_ERROR_FACE_ALREADY_CREATED;
}
/* Code replicated on purpose */
@@ -786,6 +733,8 @@ hicn_iface_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
HICN_FACE_FLAGS_APPFACE_PROD_BIT;
*index = hicn_dpoi_get_index (face);
+
+ return ret;
}
#endif // __HICN_FACE_H__
diff --git a/hicn-plugin/src/faces/face_cli.c b/hicn-plugin/src/faces/face_cli.c
index a4092e6f4..20acefc5b 100644
--- a/hicn-plugin/src/faces/face_cli.c
+++ b/hicn-plugin/src/faces/face_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c
index 5fe682bd0..dc9bfffd0 100644
--- a/hicn-plugin/src/faces/face_node.c
+++ b/hicn-plugin/src/faces/face_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * 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:
@@ -95,9 +95,6 @@ typedef enum
#define IP_HEADER_4 ip4_header_t
#define IP_HEADER_6 ip6_header_t
-#define LOCK_DPO_FACE_IP4 hicn_face_ip4_lock
-#define LOCK_DPO_FACE_IP6 hicn_face_ip6_lock
-
#define TRACE_INPUT_PKT_IP4 hicn4_face_input_trace_t
#define TRACE_INPUT_PKT_IP6 hicn6_face_input_trace_t
@@ -111,11 +108,12 @@ typedef enum
do \
{ \
vlib_buffer_t *b0; \
- u32 bi0; \
+ u32 bi0, sw_if0; \
u32 next0 = NEXT_ERROR_DROP_IP##ipv; \
IP_HEADER_##ipv *ip_hdr = NULL; \
hicn_buffer_t *hicnb0; \
- int ret; \
+ int from_tunnel0; \
+ int ret0; \
/* Prefetch for next iteration. */ \
if (n_left_from > 1) \
{ \
@@ -138,23 +136,26 @@ typedef enum
\
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); \
+ \
next0 = \
is_icmp * NEXT_MAPME_IP##ipv + (1 - is_icmp) * NEXT_DATA_IP##ipv; \
\
- ret = LOCK_DPO_FACE_IP##ipv (&(hicnb0->face_id), \
- &(hicnb0->in_faces_vec_id), \
- &hicnb0->flags, &(ip_hdr->dst_address)); \
- \
- if (PREDICT_FALSE (ret != HICN_ERROR_NONE)) \
- next0 = NEXT_ERROR_DROP_IP##ipv; \
- else \
- { \
- vlib_increment_combined_counter ( \
- &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \
- HICN_FACE_COUNTERS_DATA_RX, 1, \
- vlib_buffer_length_in_chain (vm, b0)); \
- stats.pkts_data_count += 1; \
- } \
+ vlib_increment_combined_counter ( \
+ &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \
+ HICN_FACE_COUNTERS_DATA_RX, 1, vlib_buffer_length_in_chain (vm, b0)); \
+ stats.pkts_data_count += 1; \
\
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
(b0->flags & VLIB_BUFFER_IS_TRACED))) \
@@ -178,13 +179,14 @@ typedef enum
do \
{ \
vlib_buffer_t *b0, *b1; \
- u32 bi0, bi1; \
+ u32 bi0, bi1, sw_if0, sw_if1; \
u32 next0 = NEXT_ERROR_DROP_IP##ipv; \
u32 next1 = NEXT_ERROR_DROP_IP##ipv; \
IP_HEADER_##ipv *ip_hdr0 = NULL; \
IP_HEADER_##ipv *ip_hdr1 = NULL; \
hicn_buffer_t *hicnb0; \
hicn_buffer_t *hicnb1; \
+ int from_tunnel0, from_tunnel1; \
int ret0, ret1; \
/* Prefetch for next iteration. */ \
{ \
@@ -216,41 +218,47 @@ typedef enum
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; \
\
- ret0 = LOCK_DPO_FACE_IP##ipv (&(hicnb0->face_id), \
- &(hicnb0->in_faces_vec_id), \
- &hicnb0->flags, &(ip_hdr0->dst_address)); \
+ 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; \
\
- ret1 = LOCK_DPO_FACE_IP##ipv (&(hicnb1->face_id), \
- &(hicnb1->in_faces_vec_id), \
- &hicnb1->flags, &(ip_hdr1->dst_address)); \
- \
- if (PREDICT_FALSE (ret0 != HICN_ERROR_NONE)) \
- next0 = NEXT_ERROR_DROP_IP##ipv; \
- else \
- { \
- vlib_increment_combined_counter ( \
- &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \
- HICN_FACE_COUNTERS_DATA_RX, 1, \
- vlib_buffer_length_in_chain (vm, b0)); \
- stats.pkts_data_count += 1; \
- } \
- \
- if (PREDICT_FALSE (ret1 != HICN_ERROR_NONE)) \
- next1 = NEXT_ERROR_DROP_IP##ipv; \
- else \
- { \
- vlib_increment_combined_counter ( \
- &counters[hicnb1->face_id * HICN_N_COUNTER], thread_index, \
- HICN_FACE_COUNTERS_DATA_RX, 1, \
- vlib_buffer_length_in_chain (vm, b1)); \
- stats.pkts_data_count += 1; \
- } \
+ vlib_increment_combined_counter ( \
+ &counters[hicnb1->face_id * HICN_N_COUNTER], thread_index, \
+ HICN_FACE_COUNTERS_DATA_RX, 1, vlib_buffer_length_in_chain (vm, b1)); \
+ stats.pkts_data_count += 1; \
\
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
(b0->flags & VLIB_BUFFER_IS_TRACED))) \
@@ -437,6 +445,7 @@ VLIB_REGISTER_NODE(hicn6_face_input_node) =
typedef enum
{
+ HICN4_FACE_OUTPUT_NEXT_ERROR_DROP,
HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY,
HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP,
HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP,
@@ -445,6 +454,7 @@ typedef enum
typedef enum
{
+ HICN6_FACE_OUTPUT_NEXT_ERROR_DROP,
HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY,
HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP,
HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP,
@@ -546,7 +556,9 @@ hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0,
if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
{
- ensure_offload_flags (b0, ip46_address_is_ip4 (&face->nat_addr));
+ u8 is_v4 = ip46_address_is_ip4 (&face->nat_addr) &&
+ !ip6_address_is_loopback (&face->nat_addr.ip6);
+ ensure_offload_flags (b0, is_v4);
}
ASSERT (face->flags & HICN_FACE_FLAGS_FACE);
@@ -593,8 +605,8 @@ typedef struct
{ \
vlib_buffer_t *b0; \
u32 bi0; \
- u32 next0 = ~0; \
- hicn_face_t *face; \
+ u32 next0 = HICN##ipv##_FACE_OUTPUT_NEXT_ERROR_DROP; \
+ hicn_face_t *face = NULL; \
\
/* Prefetch for next iteration. */ \
if (n_left_from > 1) \
@@ -615,9 +627,10 @@ typedef struct
b0 = vlib_get_buffer (vm, bi0); \
\
hicn_face_id_t face_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \
- face = hicn_dpoi_get_from_idx (face_id); \
+ if (PREDICT_TRUE (hicn_dpoi_idx_is_valid (face_id))) \
+ face = hicn_dpoi_get_from_idx (face_id); \
\
- if (PREDICT_TRUE (face != NULL)) \
+ if (PREDICT_TRUE (face != NULL) && face->flags & HICN_FACE_FLAGS_FACE) \
{ \
hicn_face_rewrite_interest (vm, b0, face, &next0); \
stats.pkts_interest_count += 1; \
@@ -650,9 +663,9 @@ typedef struct
{ \
vlib_buffer_t *b0, *b1; \
u32 bi0, bi1; \
- u32 next0 = ~0; \
- u32 next1 = ~0; \
- hicn_face_t *face0, *face1; \
+ u32 next0 = HICN##ipv##_FACE_OUTPUT_NEXT_ERROR_DROP; \
+ u32 next1 = HICN##ipv##_FACE_OUTPUT_NEXT_ERROR_DROP; \
+ hicn_face_t *face0 = NULL, *face1 = NULL; \
\
/* Prefetch for next iteration. */ \
{ \
@@ -679,10 +692,13 @@ typedef struct
\
hicn_face_id_t face_id0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \
hicn_face_id_t face_id1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; \
- face0 = hicn_dpoi_get_from_idx (face_id0); \
- face1 = hicn_dpoi_get_from_idx (face_id1); \
+ if (PREDICT_TRUE (hicn_dpoi_idx_is_valid (face_id0))) \
+ face0 = hicn_dpoi_get_from_idx (face_id0); \
+ if (PREDICT_TRUE (hicn_dpoi_idx_is_valid (face_id1))) \
+ face1 = hicn_dpoi_get_from_idx (face_id1); \
\
- if (PREDICT_TRUE (face0 != NULL)) \
+ if (PREDICT_TRUE (face0 != NULL) && \
+ face0->flags & HICN_FACE_FLAGS_FACE) \
{ \
hicn_face_rewrite_interest (vm, b0, face0, &next0); \
stats.pkts_interest_count += 1; \
@@ -692,7 +708,8 @@ typedef struct
vlib_buffer_length_in_chain (vm, b0)); \
} \
\
- if (PREDICT_TRUE (face1 != NULL)) \
+ if (PREDICT_TRUE (face1 != NULL) && \
+ face1->flags & HICN_FACE_FLAGS_FACE) \
{ \
hicn_face_rewrite_interest (vm, b1, face1, &next1); \
stats.pkts_interest_count += 1; \
@@ -797,7 +814,8 @@ VLIB_REGISTER_NODE (hicn4_face_output_node) = {
.error_strings = hicn4_face_output_error_strings,
.n_next_nodes = HICN4_FACE_OUTPUT_N_NEXT,
/* Reusing the list of nodes from lookup to be compatible with arp */
- .next_nodes = { [HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn4-face-input",
+ .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" }
};
@@ -867,7 +885,8 @@ VLIB_REGISTER_NODE (hicn6_face_output_node) = {
.n_next_nodes = HICN6_FACE_OUTPUT_N_NEXT,
/* Reusing the list of nodes from lookup to be compatible with neighbour
discovery */
- .next_nodes = { [HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn6-face-input",
+ .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" }
};
diff --git a/hicn-plugin/src/faces/face_node.h b/hicn-plugin/src/faces/face_node.h
index 3b38e71b3..70daa1393 100644
--- a/hicn-plugin/src/faces/face_node.h
+++ b/hicn-plugin/src/faces/face_node.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c
index bf9c56515..84205af9b 100644
--- a/hicn-plugin/src/faces/iface_node.c
+++ b/hicn-plugin/src/faces/iface_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * 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:
@@ -107,8 +107,8 @@ typedef enum
ip6_address_t *local_address1 = \
ip6_interface_first_address (&ip6_main, swif1);
-#define DPO_ADD_LOCK_IFACE_IP4 hicn_iface_ip4_add_and_lock
-#define DPO_ADD_LOCK_IFACE_IP6 hicn_iface_ip6_add_and_lock
+#define 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
@@ -144,6 +144,7 @@ typedef struct
typedef enum
{
+ HICN4_IFACE_OUTPUT_NEXT_DROP,
HICN4_IFACE_OUTPUT_NEXT_LOOKUP,
HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP,
HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP,
@@ -161,6 +162,7 @@ typedef struct
typedef enum
{
+ HICN6_IFACE_OUTPUT_NEXT_DROP,
HICN6_IFACE_OUTPUT_NEXT_LOOKUP,
HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP,
HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP,
@@ -188,7 +190,7 @@ typedef enum
do \
{ \
vlib_buffer_t *b0; \
- u32 bi0, next0, next_iface0; \
+ u32 bi0, next0, next_iface0, sw_if0; \
IP_HEADER_##ipv *ip_hdr = NULL; \
hicn_buffer_t *hicnb0; \
/* Prefetch for next iteration. */ \
@@ -219,15 +221,23 @@ typedef enum
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) \
- next_iface0 = NEXT_UDP_ENCAP_IP4; \
- else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \
- next_iface0 = NEXT_UDP_ENCAP_IP6; \
+ 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; \
+ } \
\
- DPO_ADD_LOCK_IFACE_IP##ipv ( \
- &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr->src_address), \
- vnet_buffer (b0)->sw_if_index[VLIB_RX], \
+ 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) && \
@@ -236,7 +246,7 @@ typedef enum
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
t->pkt_type = HICN_PKT_TYPE_INTEREST; \
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ t->sw_if_index = sw_if0; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
sizeof (t->packet_data)); \
@@ -257,7 +267,7 @@ typedef enum
do \
{ \
vlib_buffer_t *b0, *b1; \
- u32 bi0, bi1, next0, next1, next_iface0, next_iface1; \
+ u32 bi0, bi1, next0, next1, next_iface0, next_iface1, sw_if0, sw_if1; \
IP_HEADER_##ipv *ip_hdr0 = NULL; \
IP_HEADER_##ipv *ip_hdr1 = NULL; \
hicn_buffer_t *hicnb0, *hicnb1; \
@@ -300,27 +310,43 @@ typedef enum
(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) \
- next_iface0 = NEXT_UDP_ENCAP_IP4; \
- else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \
- next_iface0 = NEXT_UDP_ENCAP_IP6; \
+ 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; \
+ } \
\
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) \
- next_iface1 = NEXT_UDP_ENCAP_IP4; \
- else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \
- next_iface1 = NEXT_UDP_ENCAP_IP6; \
+ 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; \
+ } \
\
- DPO_ADD_LOCK_IFACE_IP##ipv ( \
- &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), \
- vnet_buffer (b0)->sw_if_index[VLIB_RX], \
+ 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_IFACE_IP##ipv ( \
- &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), \
- vnet_buffer (b1)->sw_if_index[VLIB_RX], \
+ 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) && \
@@ -329,7 +355,7 @@ typedef enum
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
t->pkt_type = HICN_PKT_TYPE_INTEREST; \
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ t->sw_if_index = sw_if0; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
sizeof (t->packet_data)); \
@@ -341,7 +367,7 @@ typedef enum
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b1, sizeof (*t)); \
t->pkt_type = HICN_PKT_TYPE_INTEREST; \
- t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
+ t->sw_if_index = sw_if1; \
t->next_index = next1; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \
sizeof (t->packet_data)); \
@@ -588,7 +614,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
vlib_buffer_t *b0; \
u32 bi0; \
u32 next0 = next_index; \
- hicn_face_t *face; \
+ hicn_face_t *face = NULL; \
\
/* Prefetch for next iteration. */ \
if (n_left_from > 1) \
@@ -609,7 +635,8 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
b0 = vlib_get_buffer (vm, bi0); \
\
hicn_face_id_t face_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \
- face = hicn_dpoi_get_from_idx (face_id); \
+ if (PREDICT_TRUE (hicn_dpoi_idx_is_valid (face_id))) \
+ face = hicn_dpoi_get_from_idx (face_id); \
\
if (PREDICT_TRUE (face != NULL)) \
{ \
@@ -646,7 +673,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
u32 bi0, bi1; \
u32 next0 = next_index; \
u32 next1 = next_index; \
- hicn_face_t *face0, *face1; \
+ hicn_face_t *face0 = NULL, *face1 = NULL; \
\
/* Prefetch for next iteration. */ \
{ \
@@ -674,8 +701,10 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
\
hicn_face_id_t face_id0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \
hicn_face_id_t face_id1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; \
- face0 = hicn_dpoi_get_from_idx (face_id0); \
- face1 = hicn_dpoi_get_from_idx (face_id1); \
+ if (PREDICT_TRUE (hicn_dpoi_idx_is_valid (face_id0))) \
+ face0 = hicn_dpoi_get_from_idx (face_id0); \
+ if (PREDICT_TRUE (hicn_dpoi_idx_is_valid (face_id1))) \
+ face1 = hicn_dpoi_get_from_idx (face_id1); \
\
if (PREDICT_TRUE (face0 != NULL)) \
{ \
@@ -738,7 +767,7 @@ hicn4_iface_output_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
+ next_index = HICN4_IFACE_OUTPUT_NEXT_DROP;
while (n_left_from > 0)
{
@@ -792,7 +821,8 @@ VLIB_REGISTER_NODE (hicn4_iface_output_node) = {
.error_strings = hicn4_iface_output_error_strings,
.n_next_nodes = HICN4_IFACE_OUTPUT_N_NEXT,
/* edit / add dispositions here */
- .next_nodes = { [HICN4_IFACE_OUTPUT_NEXT_LOOKUP] = "ip4-lookup",
+ .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" },
};
@@ -807,7 +837,7 @@ hicn6_iface_output_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
+ next_index = HICN6_IFACE_OUTPUT_NEXT_DROP;
while (n_left_from > 0)
{
@@ -860,11 +890,10 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) = {
.error_strings = hicn6_iface_output_error_strings,
.n_next_nodes = HICN6_IFACE_OUTPUT_N_NEXT,
/* edit / add dispositions here */
- .next_nodes = { [HICN6_IFACE_OUTPUT_NEXT_LOOKUP] = "ip6-lookup",
+ .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" },
};
/*
diff --git a/hicn-plugin/src/faces/iface_node.h b/hicn-plugin/src/faces/iface_node.h
index acb3cab0f..3fa6bb484 100644
--- a/hicn-plugin/src/faces/iface_node.h
+++ b/hicn-plugin/src/faces/iface_node.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/faces/inlines.h b/hicn-plugin/src/faces/inlines.h
index 95a1c2ad2..ad9e26b62 100644
--- a/hicn-plugin/src/faces/inlines.h
+++ b/hicn-plugin/src/faces/inlines.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -21,24 +21,19 @@
always_inline void
ensure_offload_flags (vlib_buffer_t *b, int is_v4)
{
- vnet_buffer_offload_flags_set(b, VNET_BUFFER_OFFLOAD_F_TCP_CKSUM);
- vnet_buffer_offload_flags_set(b, is_v4 * VNET_BUFFER_OFFLOAD_F_IP_CKSUM);
+ vnet_buffer_offload_flags_set (b, VNET_BUFFER_OFFLOAD_F_TCP_CKSUM);
+ vnet_buffer_offload_flags_set (b, is_v4 * VNET_BUFFER_OFFLOAD_F_IP_CKSUM);
size_t l3_header_size =
is_v4 * sizeof (ip4_header_t) + (!is_v4) * sizeof (ip6_header_t);
/* Make sure l3_hdr_offset and l4_hdr_offset are set */
- if (!(b->flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID))
- {
- b->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
- vnet_buffer (b)->l3_hdr_offset = b->current_data;
- }
- if (!(b->flags & VNET_BUFFER_F_L4_HDR_OFFSET_VALID))
- {
- b->flags |= VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
- vnet_buffer (b)->l4_hdr_offset =
- vnet_buffer (b)->l3_hdr_offset + l3_header_size;
- }
+ b->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
+ vnet_buffer (b)->l3_hdr_offset = b->current_data;
+
+ b->flags |= VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
+ vnet_buffer (b)->l4_hdr_offset =
+ vnet_buffer (b)->l3_hdr_offset + l3_header_size;
}
#endif /* __HICN_FACE_INLINES_H__ */ \ No newline at end of file
diff --git a/hicn-plugin/src/hashtb.c b/hicn-plugin/src/hashtb.c
index a74353239..eb7da81f2 100644
--- a/hicn-plugin/src/hashtb.c
+++ b/hicn-plugin/src/hashtb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -187,7 +187,7 @@ hicn_hashtb_alloc (hicn_hashtb_h *ph, u32 max_elems, size_t app_data_size)
}
pool_get_aligned (h->ht_nodes, nodep, 8);
// alloc node 0
- nodep = nodep; /* Silence 'not used' warning */
+ (void) nodep; /* Silence 'not used' warning */
h->ht_node_count = max_elems;
h->ht_nodes_used = 1;
@@ -206,7 +206,7 @@ hicn_hashtb_alloc (hicn_hashtb_h *ph, u32 max_elems, size_t app_data_size)
}
/* 'Hide' the zero-th node so we can use zero as an 'empty' value */
pool_get_aligned (h->ht_overflow_buckets, bucket, 8);
- bucket = bucket; /* Silence 'not used' warning */
+ (void) bucket; /* Silence 'not used' warning */
h->ht_overflow_bucket_count = count;
h->ht_overflow_buckets_used = 1;
diff --git a/hicn-plugin/src/hashtb.h b/hicn-plugin/src/hashtb.h
index 3965ec65d..4b787e2d7 100644
--- a/hicn-plugin/src/hashtb.h
+++ b/hicn-plugin/src/hashtb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api
index 9643f2098..44382c743 100644
--- a/hicn-plugin/src/hicn.api
+++ b/hicn-plugin/src/hicn.api
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -437,8 +437,14 @@ define hicn_api_enable_disable_reply
/* Arbitrary context, so client can match reply to request */
u32 context;
-/* Return value, zero means all OK */
+ /* Return value, zero means all OK */
i32 retval;
+
+ /* Number of faces created */
+ u8 nfaces;
+
+ /* IDs of new faces */
+ u32 faceids[16];
};
define hicn_api_register_prod_app
diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c
index 9bec91455..1131d4339 100644
--- a/hicn-plugin/src/hicn.c
+++ b/hicn-plugin/src/hicn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -149,8 +149,8 @@ hicn_infra_plugin_enable_disable (int enable_disable, int pit_size_req,
// check if CS is bugger tha PIT or bigger than the available
// vlib_buffers
uword cs_buffers = (n_buffers > HICN_PARAM_CS_MIN_MBUF) ?
- n_buffers - HICN_PARAM_CS_MIN_MBUF :
- 0;
+ n_buffers - HICN_PARAM_CS_MIN_MBUF :
+ 0;
if (cs_size_req > (pit_size_req / 2) || cs_size_req > cs_buffers)
{
diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h
index 4ff4f6ae6..aaf16c917 100644
--- a/hicn-plugin/src/hicn.h
+++ b/hicn-plugin/src/hicn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -61,10 +61,8 @@ typedef u8 weight_t;
* 2*CLIB_CACHE_LINE_BYTES. */
/* This flag is used to mark packets whose lenght is less that
* 2*CLIB_CACHE_LINE_BYTES. */
-#define HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL 0x02
-#define HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL 0x04
-#define HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL 0x08
-#define HICN_BUFFER_FLAGS_FROM_CS 0x10
+#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
@@ -83,7 +81,6 @@ typedef struct
u8 vft_id; /* " */
hicn_face_id_t face_id; /* ingress iface, sizeof(u32) */
- u32 in_faces_vec_id; /* vector of possible input face for a data packet */
hicn_type_t type;
} hicn_buffer_t;
diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c
index b72675f63..85279eb0b 100644
--- a/hicn-plugin/src/hicn_api.c
+++ b/hicn-plugin/src/hicn_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -40,12 +40,12 @@
#include "route.h"
/* define message IDs */
-#include <hicn/hicn.api_enum.h>
-#include <hicn/hicn.api_types.h>
+#include <vpp_plugins/hicn/hicn.api_enum.h>
+#include <vpp_plugins/hicn/hicn.api_types.h>
/* define generated endian-swappers */
#define vl_endianfun
-#include <hicn/hicn_all_api_h.h>
+#include <vpp_plugins/hicn/hicn_all_api_h.h>
#undef vl_endianfun
#define REPLY_MSG_ID_BASE sm->msg_id_base
@@ -79,8 +79,8 @@ vl_api_hicn_api_node_params_set_t_handler (
f64 pit_max_lifetime_sec = mp->pit_max_lifetime_sec;
pit_max_lifetime_sec = pit_max_lifetime_sec == -1 ?
- HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS :
- pit_max_lifetime_sec;
+ HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS :
+ pit_max_lifetime_sec;
int cs_max_size = clib_net_to_host_i32 (mp->cs_max_size);
cs_max_size = cs_max_size == -1 ? HICN_PARAM_CS_ENTRIES_DFLT : cs_max_size;
@@ -159,7 +159,7 @@ send_face_details (hicn_face_t *face, vl_api_hicn_face_t *mp)
{
sbuf =
format (0, "%U", format_vnet_sw_interface_name, vnm, sw_interface);
- strcpy ((char *) (mp->if_name), (char *) sbuf);
+ strcpy_s ((char *) (mp->if_name), sizeof (mp->if_name), (char *) sbuf);
}
}
@@ -567,17 +567,34 @@ vl_api_hicn_api_enable_disable_t_handler (vl_api_hicn_api_enable_disable_t *mp)
fib_prefix_t prefix;
ip_prefix_decode (&mp->prefix, &prefix);
+ hicn_face_id_t *vec_faces = NULL;
+
switch (clib_net_to_host_u32 (mp->enable_disable))
{
case HICN_ENABLE:
- rv = hicn_route_enable (&prefix);
+ HICN_DEBUG ("Calling hicn enable from API.");
+ rv = hicn_route_enable (&prefix, &vec_faces);
break;
case HICN_DISABLE:
+ HICN_DEBUG ("Calling hicn disable from API.");
rv = hicn_route_disable (&prefix);
break;
}
- REPLY_MACRO (VL_API_HICN_API_ENABLE_DISABLE_REPLY /* , rmp, mp, rv */);
+ REPLY_MACRO2 (VL_API_HICN_API_ENABLE_DISABLE_REPLY, ({
+ rmp->nfaces = 0;
+ if (vec_faces != NULL)
+ {
+ hicn_face_id_t *face;
+ vec_foreach (face, vec_faces)
+ {
+ rmp->faceids[rmp->nfaces++] =
+ clib_host_to_net_u32 (*face);
+ }
+
+ vec_free (vec_faces);
+ }
+ }));
}
/*********************************** UDP TUNNELS
@@ -632,7 +649,7 @@ done:
/************************************************************************************/
-#include <hicn/hicn.api.c>
+#include <vpp_plugins/hicn/hicn.api.c>
/* Set up the API message handling tables */
clib_error_t *
diff --git a/hicn-plugin/src/hicn_api_test.c b/hicn-plugin/src/hicn_api_test.c
index 04e216e38..fbba5ffc3 100644
--- a/hicn-plugin/src/hicn_api_test.c
+++ b/hicn-plugin/src/hicn_api_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -31,11 +31,11 @@
#include <vpp/api/vpe.api_types.h>
-#include <hicn/hicn_api.h>
-#include "error.h"
+#include <vpp_plugins/hicn/hicn_api.h>
+#include <vpp_plugins/hicn/error.h>
/* Declare message IDs */
-#include "hicn_msg_enum.h"
+#include <vpp_plugins/hicn/hicn_msg_enum.h>
/* SUPPORTING FUNCTIONS NOT LOADED BY VPP_API_TEST */
uword
@@ -1000,8 +1000,8 @@ api_hicn_api_enable_disable (vat_main_t *vam)
}
prefix.fp_proto = ip46_address_is_ip4 (&(prefix.fp_addr)) ?
- FIB_PROTOCOL_IP4 :
- FIB_PROTOCOL_IP6;
+ FIB_PROTOCOL_IP4 :
+ FIB_PROTOCOL_IP6;
// Construct the API message
M (HICN_API_ENABLE_DISABLE, mp);
@@ -1053,8 +1053,8 @@ api_hicn_api_register_prod_app (vat_main_t *vam)
}
prefix.fp_proto = ip46_address_is_ip4 (&(prefix.fp_addr)) ?
- FIB_PROTOCOL_IP4 :
- FIB_PROTOCOL_IP6;
+ FIB_PROTOCOL_IP4 :
+ FIB_PROTOCOL_IP6;
/* Construct the API message */
M (HICN_API_REGISTER_PROD_APP, mp);
ip_prefix_encode (&prefix, &mp->prefix);
@@ -1310,7 +1310,7 @@ vl_api_hicn_api_udp_tunnel_add_del_reply_t_handler (
fformat (vam->ofp, "udp-encap %d\n", uei);
}
-#include <hicn/hicn.api_test.c>
+#include <vpp_plugins/hicn/hicn.api_test.c>
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/hicn_logging.h b/hicn-plugin/src/hicn_logging.h
new file mode 100644
index 000000000..a960a7212
--- /dev/null
+++ b/hicn-plugin/src/hicn_logging.h
@@ -0,0 +1,32 @@
+/*
+ * 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_DEBUG_H__
+#define __HICN_DEBUG_H__
+
+#ifdef HICN_DDEBUG
+#define HICN_DEBUG(...) \
+ do \
+ { \
+ clib_warning (__VA_ARGS__); \
+ } \
+ while (0)
+#else
+#define HICN_DEBUG(...)
+#endif /* HICN_DEBUG */
+
+#define HICN_ERROR(...) clib_error_return (0, __VA_ARGS__)
+
+#endif /* __HICN_DEBUG_H__ */ \ No newline at end of file
diff --git a/libtransport/src/protocols/fec_base.cc b/hicn-plugin/src/infra.c
index 9252bc473..e0dba5efd 100644
--- a/libtransport/src/protocols/fec_base.cc
+++ b/hicn-plugin/src/infra.c
@@ -13,12 +13,13 @@
* limitations under the License.
*/
-#include <protocols/fec/rs.h>
-#include <protocols/fec_base.h>
+#include "infra.h"
-namespace transport {
-namespace protocol {
+/**
+ * @file infra.c
+ *
+ */
-namespace fec {} // namespace fec
-} // namespace protocol
-} // namespace transport \ No newline at end of file
+/* PIT and CS size */
+u32 hicn_infra_pit_size;
+u32 hicn_infra_cs_size;
diff --git a/hicn-plugin/src/infra.h b/hicn-plugin/src/infra.h
index 900ecedde..c942ad581 100644
--- a/hicn-plugin/src/infra.h
+++ b/hicn-plugin/src/infra.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -57,8 +57,8 @@ extern hicn_main_t hicn_main;
extern int hicn_infra_fwdr_initialized;
/* PIT and CS size */
-u32 hicn_infra_pit_size;
-u32 hicn_infra_cs_size;
+extern u32 hicn_infra_pit_size;
+extern u32 hicn_infra_cs_size;
/**
* @brief Enable and disable the hicn plugin
diff --git a/hicn-plugin/src/interest_hitcs.h b/hicn-plugin/src/interest_hitcs.h
index 05a790688..0df987778 100644
--- a/hicn-plugin/src/interest_hitcs.h
+++ b/hicn-plugin/src/interest_hitcs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/interest_hitcs_node.c b/hicn-plugin/src/interest_hitcs_node.c
index e29b173a9..947b4cb68 100644
--- a/hicn-plugin/src/interest_hitcs_node.c
+++ b/hicn-plugin/src/interest_hitcs_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -189,7 +189,7 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
* the data through it
*/
next0 = isv6 ? HICN_INTEREST_HITCS_NEXT_IFACE6_OUT :
- HICN_INTEREST_HITCS_NEXT_IFACE4_OUT;
+ HICN_INTEREST_HITCS_NEXT_IFACE4_OUT;
vnet_buffer (b0)->ip.adj_index[VLIB_TX] = hicnb0->face_id;
clone_from_cs (vm, &pitp->u.cs.cs_pkt_buf, b0, isv6);
diff --git a/hicn-plugin/src/interest_hitpit.h b/hicn-plugin/src/interest_hitpit.h
index 44cf2c879..18ef94aa7 100644
--- a/hicn-plugin/src/interest_hitpit.h
+++ b/hicn-plugin/src/interest_hitpit.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/interest_hitpit_node.c b/hicn-plugin/src/interest_hitpit_node.c
index 837eddca7..33dc782cd 100644
--- a/hicn-plugin/src/interest_hitpit_node.c
+++ b/hicn-plugin/src/interest_hitpit_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -88,7 +88,8 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u8 dpo_ctx_id0;
u8 found = 0;
int nh_idx;
- hicn_face_id_t outface;
+ hicn_face_id_t outfaces[MAX_OUT_FACES];
+ u32 outfaces_len;
hicn_hash_entry_t *hash_entry0;
hicn_buffer_t *hicnb0;
int ret;
@@ -171,23 +172,77 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (found)
{
- strategy_vft0->hicn_select_next_hop (dpo_ctx_id0,
- &nh_idx, &outface);
+ strategy_vft0->hicn_select_next_hop (
+ dpo_ctx_id0, &nh_idx, outfaces, &outfaces_len);
/* Retransmission */
/*
* Prepare the packet for the
* forwarding
*/
- next0 = isv6 ? HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT :
- HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface;
-
- /*
- * Update the egress face in
- * the PIT
- */
- pitp->u.pit.pe_txnh = nh_idx;
- stats.interests_retx++;
+ if (outfaces_len == 1)
+ {
+ next0 = isv6 ?
+ HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT :
+ HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT;
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
+ outfaces[0];
+
+ /*
+ * Update the egress face in
+ * the PIT
+ */
+ pitp->u.pit.pe_txnh = nh_idx;
+ stats.interests_retx++;
+ }
+ else
+ {
+ // restore pointers
+ to_next -= 1;
+ n_left_to_next += 1;
+ u32 clones[outfaces_len];
+ int ret =
+ vlib_buffer_clone (vm, bi0, clones, outfaces_len,
+ CLIB_CACHE_LINE_BYTES * 2);
+ ASSERT (ret == outfaces_len);
+ for (u32 nh = 0; nh < outfaces_len; nh++)
+ {
+ vlib_buffer_t *local_b0 =
+ vlib_get_buffer (vm, clones[nh]);
+ to_next[0] = clones[nh];
+ to_next += 1;
+ n_left_to_next -= 1;
+
+ next0 =
+ isv6 ? HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT :
+ HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT;
+ vnet_buffer (local_b0)->ip.adj_index[VLIB_TX] =
+ outfaces[nh];
+ stats.interests_retx++;
+
+ /* Maybe trace */
+ if (PREDICT_FALSE (
+ (node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (local_b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicn_interest_hitpit_trace_t *t =
+ vlib_add_trace (vm, node, local_b0,
+ sizeof (*t));
+ t->pkt_type = HICN_PKT_TYPE_INTEREST;
+ t->sw_if_index = vnet_buffer (local_b0)
+ ->sw_if_index[VLIB_RX];
+ t->next_index = next0;
+ }
+
+ /*
+ * Verify speculative enqueue, maybe switch
+ * current next frame
+ */
+ vlib_validate_buffer_enqueue_x1 (
+ vm, node, next_index, to_next, n_left_to_next,
+ clones[nh], next0);
+ }
+ continue;
+ }
}
else
{
diff --git a/hicn-plugin/src/interest_pcslookup.h b/hicn-plugin/src/interest_pcslookup.h
index 87d093e91..4da9c1939 100644
--- a/hicn-plugin/src/interest_pcslookup.h
+++ b/hicn-plugin/src/interest_pcslookup.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c
index d3f6c7bca..ff0da12d7 100644
--- a/hicn-plugin/src/interest_pcslookup_node.c
+++ b/hicn-plugin/src/interest_pcslookup_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/mapme.h b/hicn-plugin/src/mapme.h
index 63bd42610..1d46ea9f3 100644
--- a/hicn-plugin/src/mapme.h
+++ b/hicn-plugin/src/mapme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -21,9 +21,9 @@
#include <hicn/mapme.h>
#include "hicn.h"
-#include "route.h"
#include "strategy_dpo_ctx.h"
#include "strategy_dpo_manager.h" // dpo_is_hicn
+#include "udp_tunnels/udp_tunnel.h"
/**
* @file
@@ -63,7 +63,6 @@ typedef struct hicn_mapme_conf_s
bool remove_dpo; // FIXME used ?
vlib_main_t *vm;
- vlib_log_class_t log_class;
} hicn_mapme_main_t;
/**
@@ -100,65 +99,33 @@ STATIC_ASSERT (sizeof (hicn_mapme_tfib_t) <= sizeof (hicn_dpo_ctx_t),
#define TFIB(dpo_ctx) ((hicn_mapme_tfib_t *) (dpo_ctx))
-static_always_inline int
-hicn_mapme_nh_set (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
-{
- hicn_dpo_ctx_t *strategy_ctx = (hicn_dpo_ctx_t *) tfib;
- const fib_prefix_t *prefix =
- fib_entry_get_prefix (strategy_ctx->fib_entry_index);
-
- u32 n_entries = tfib->entry_count;
- /* Remove all the existing next hops and set the new one */
- for (int i = 0; i < n_entries; i++)
- {
- hicn_face_t *face = hicn_dpoi_get_from_idx (strategy_ctx->next_hops[0]);
- ip_adjacency_t *adj = adj_get (face->dpo.dpoi_index);
- ip_nh_del_helper (face->dpo.dpoi_proto, prefix,
- &adj->sub_type.nbr.next_hop, face->sw_if);
- }
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- ip_nh_add_helper (face->dpo.dpoi_proto, prefix, &face->nat_addr,
- face->sw_if);
- return 0;
-}
-
/**
- * @brief Add a next hop iif it is not already a next hops
+ * @brief Check whether a face is already included in the TFIB.
+ *
+ * NOTE: linear scan on a contiguous small array should be the most efficient.
*/
static_always_inline int
-hicn_mapme_nh_add (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
+hicn_mapme_tfib_has (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
{
- for (u8 pos = 0; pos < tfib->entry_count; pos++)
- if (tfib->next_hops[pos] == face_id)
- return 0;
-
- /* Add the next hop in the vrf 0 which will add it to the entry in the hICN
- * vrf */
- hicn_dpo_ctx_t *strategy_ctx = (hicn_dpo_ctx_t *) tfib;
- const fib_prefix_t *prefix =
- fib_entry_get_prefix (strategy_ctx->fib_entry_index);
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- ip_nh_add_helper (face->dpo.dpoi_proto, prefix, &face->nat_addr,
- face->sw_if);
-
+ u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count;
+ for (u8 pos2 = pos; pos2 < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos2++)
+ if (tfib->next_hops[pos2] == face_id)
+ return 1;
return 0;
}
/**
* Add a 'previous' hop to the TFIB
- *
- * XXX we should have the for look in the reverse order for simpler code.
*/
static_always_inline int
hicn_mapme_tfib_add (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
{
- u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count;
+ // Don't add if it already exists
+ // (eg. an old IU received on a face on which we are retransmitting)
+ if (hicn_mapme_tfib_has (tfib, face_id))
+ return 0;
- // XXX don 't add if it already exist
- // eg.an old IU received on a face on which we are retransmitting
- for (u8 pos2 = pos; pos2 < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos2++)
- if (tfib->next_hops[pos2] == face_id)
- return 0;
+ u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count;
// Make sure we have enough room
if (pos <= tfib->entry_count)
@@ -190,7 +157,6 @@ hicn_mapme_tfib_clear (hicn_mapme_tfib_t *tfib)
{
hicn_face_unlock_with_id (tfib->next_hops[pos]);
tfib->next_hops[pos] = invalid;
- break;
}
tfib->tfib_entry_count = 0;
@@ -358,10 +324,6 @@ hicn_mapme_get_dpo_face_node (hicn_face_id_t face_id)
}
}
-#define DEBUG(...) // vlib_log_debug(mapme_main.log_class, __VA_ARGS__)
-#define WARN(...) // vlib_log_warn(mapme_main.log_class, __VA_ARGS__)
-#define ERROR(...) // vlib_log_err(mapme_main.log_class, __VA_ARGS__)
-
#endif /* __HICN_MAPME__ */
/*
diff --git a/hicn-plugin/src/mapme_ack.h b/hicn-plugin/src/mapme_ack.h
index 821baf203..72ed7a0c4 100644
--- a/hicn-plugin/src/mapme_ack.h
+++ b/hicn-plugin/src/mapme_ack.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,7 +14,7 @@
*/
/*
- * Copyright (c) 2017-2019 by Cisco Systems Inc. All Rights Reserved.
+ * Copyright (c) 2021 by Cisco Systems Inc. All Rights Reserved.
*
*/
diff --git a/hicn-plugin/src/mapme_ack_node.c b/hicn-plugin/src/mapme_ack_node.c
index fad344b73..ea4834665 100644
--- a/hicn-plugin/src/mapme_ack_node.c
+++ b/hicn-plugin/src/mapme_ack_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -14,6 +14,7 @@
*/
#include <vnet/ip/ip6_packet.h>
+#include <vlib/log.h>
#include "hicn.h"
#include "mapme.h"
@@ -69,7 +70,8 @@ hicn_mapme_process_ack (vlib_main_t *vm, vlib_buffer_t *b,
dpo = fib_epm_lookup (&(prefix.name), prefix.len);
if (!dpo)
{
- DEBUG ("Ignored ACK for non-existing FIB entry. Ignored.");
+ HICN_ERROR ("Ignored ACK for non-existing FIB entry %U. Ignored.",
+ format_ip_prefix, &prefix);
return true;
}
@@ -80,7 +82,7 @@ hicn_mapme_process_ack (vlib_main_t *vm, vlib_buffer_t *b,
if (tfib == NULL)
{
- WARN ("Unable to get strategy ctx.");
+ HICN_ERROR ("Unable to get strategy ctx.");
return false;
}
@@ -92,7 +94,7 @@ hicn_mapme_process_ack (vlib_main_t *vm, vlib_buffer_t *b,
*/
if (params.seq < fib_seq)
{
- DEBUG ("Ignored ACK for low seq");
+ HICN_ERROR ("MAPME: Ignored ACK for low seq");
return true;
}
diff --git a/hicn-plugin/src/mapme_ctrl.h b/hicn-plugin/src/mapme_ctrl.h
index a40a969b0..76382c6d2 100644
--- a/hicn-plugin/src/mapme_ctrl.h
+++ b/hicn-plugin/src/mapme_ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -14,7 +14,7 @@
*/
/*
- * Copyright (c) 2017-2019 by Cisco Systems Inc. All Rights Reserved.
+ * Copyright (c) 2021 by Cisco Systems Inc. All Rights Reserved.
*
*/
diff --git a/hicn-plugin/src/mapme_ctrl_node.c b/hicn-plugin/src/mapme_ctrl_node.c
index 613958d9c..5314c49a0 100644
--- a/hicn-plugin/src/mapme_ctrl_node.c
+++ b/hicn-plugin/src/mapme_ctrl_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -18,6 +18,7 @@
*/
#include <vnet/ip/ip6_packet.h>
#include <vnet/dpo/load_balance.h>
+#include <vlib/log.h>
#include "hicn.h"
#include "mapme.h"
@@ -30,6 +31,7 @@
#include "strategy_dpo_ctx.h"
#include "error.h"
#include "state.h"
+#include "route.h"
extern hicn_mapme_main_t mapme_main;
@@ -47,6 +49,110 @@ static char *hicn_mapme_ctrl_error_strings[] = {
#undef _
};
+static_always_inline int
+hicn_mapme_nh_set (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
+{
+ hicn_dpo_ctx_t *strategy_ctx = (hicn_dpo_ctx_t *) tfib;
+ const fib_prefix_t *prefix =
+ fib_entry_get_prefix (strategy_ctx->fib_entry_index);
+
+ int ret = 0;
+
+ if ((tfib->entry_count == 1) && (tfib->next_hops[0] == face_id))
+ return ret;
+
+ u32 n_entries = tfib->entry_count;
+ /* Remove all the existing next hops and set the new one */
+ for (int i = 0; i < n_entries; i++)
+ {
+ hicn_face_t *face = hicn_dpoi_get_from_idx (strategy_ctx->next_hops[0]);
+ if (dpo_is_adj (&face->dpo))
+ {
+ ip_adjacency_t *adj = adj_get (face->dpo.dpoi_index);
+ ip_nh_adj_add_del_helper (prefix->fp_proto, prefix,
+ &adj->sub_type.nbr.next_hop, face->sw_if,
+ 0);
+ }
+ else if (face->dpo.dpoi_type == dpo_type_udp_ip4 ||
+ face->dpo.dpoi_type == dpo_type_udp_ip6)
+ {
+ ip_nh_udp_tunnel_add_del_helper (prefix->fp_proto, prefix,
+ face->dpo.dpoi_index,
+ face->dpo.dpoi_proto, 0);
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ ret = HICN_ERROR_MAPME_NEXT_HOP_ADDED;
+ hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
+ if (face->dpo.dpoi_type == dpo_type_udp_ip4 ||
+ face->dpo.dpoi_type == dpo_type_udp_ip6)
+ {
+ ip_nh_udp_tunnel_add_del_helper (prefix->fp_proto, prefix,
+ face->dpo.dpoi_index,
+ face->dpo.dpoi_proto, 1);
+ }
+ else if (dpo_is_adj (&face->dpo))
+ {
+ ip_nh_adj_add_del_helper (prefix->fp_proto, prefix, &face->nat_addr,
+ face->sw_if, 1);
+ }
+ else
+ {
+ ret = HICN_ERROR_MAPME_NEXT_HOP_NOT_ADDED;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Check whether a face is already included in the FIB nexthops.
+ *
+ * NOTE: linear scan on a contiguous small array should be the most efficient.
+ */
+static_always_inline int
+hicn_mapme_nh_has (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
+{
+ for (u8 pos = 0; pos < tfib->entry_count; pos++)
+ if (tfib->next_hops[pos] == face_id)
+ return 1;
+ return 0;
+}
+
+/**
+ * @brief Add a next hop iif it is not already a next hops
+ */
+static_always_inline int
+hicn_mapme_nh_add (hicn_mapme_tfib_t *tfib, hicn_face_id_t face_id)
+{
+ if (hicn_mapme_nh_has (tfib, face_id))
+ return 0;
+
+ /* Add the next hop in the vrf 0 which will add it to the entry in the hICN
+ * vrf */
+ hicn_dpo_ctx_t *strategy_ctx = (hicn_dpo_ctx_t *) tfib;
+ const fib_prefix_t *prefix =
+ fib_entry_get_prefix (strategy_ctx->fib_entry_index);
+ hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
+ if (face->dpo.dpoi_type == dpo_type_udp_ip4 ||
+ face->dpo.dpoi_type == dpo_type_udp_ip6)
+ {
+ ip_nh_udp_tunnel_add_del_helper ((fib_protocol_t) face->dpo.dpoi_proto,
+ prefix, face->dpo.dpoi_index,
+ face->dpo.dpoi_proto, 1);
+ }
+ else
+ {
+ ip_nh_adj_add_del_helper ((fib_protocol_t) face->dpo.dpoi_proto, prefix,
+ &face->nat_addr, face->sw_if, 1);
+ }
+
+ return 0;
+}
+
/*
* @brief Process incoming control messages (Interest Update)
* @param vm vlib main data structure
@@ -97,7 +203,7 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
* Destroying the face has led to removing all corresponding FIB
* entries. In that case, we need to correctly restore the FIB entries.
*/
- DEBUG ("Re-creating FIB entry with next hop on connection")
+ HICN_DEBUG ("Re-creating FIB entry with next hop on connection")
#error "not implemented"
#else
// ERROR("Received IU for non-existing FIB entry");
@@ -109,7 +215,7 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
if (!dpo_is_hicn ((dpo)))
{
/* We have an IP DPO */
- WARN ("Not implemented yet.");
+ HICN_ERROR ("Not implemented yet.");
return false;
}
#endif
@@ -119,7 +225,7 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
if (tfib == NULL)
{
- WARN ("Unable to get strategy ctx.");
+ HICN_ERROR ("Unable to get strategy ctx.");
return false;
}
@@ -127,7 +233,7 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
if (params.seq > fib_seq)
{
- DEBUG (
+ HICN_DEBUG (
"Higher sequence number than FIB %d > %d, updating seq and next hops",
params.seq, fib_seq);
@@ -139,25 +245,29 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
/* Remove ingress face from TFIB in case it was present */
hicn_mapme_tfib_del (tfib, in_face_id);
+ HICN_DEBUG ("Locks on face %d: %d", in_face_id,
+ hicn_dpoi_get_from_idx (in_face_id)->locks);
+
/* Move next hops to TFIB... but in_face... */
for (u8 pos = 0; pos < tfib->entry_count; pos++)
{
- hicn_face_t *face = hicn_dpoi_get_from_idx (tfib->next_hops[pos]);
- hicn_face_t *in_face = hicn_dpoi_get_from_idx (in_face_id);
- if (dpo_is_adj (&face->dpo))
- {
- ip_adjacency_t *adj = adj_get (dpo->dpoi_index);
- if (ip46_address_cmp (&(adj->sub_type.nbr.next_hop),
- &(in_face->nat_addr)) == 0)
- break;
- }
- DEBUG ("Adding nexthop to the tfib, dpo index in_face %d, dpo index "
- "tfib %d",
- in_face_id, tfib->next_hops[pos]);
+ if (tfib->next_hops[pos] == in_face_id)
+ continue;
+ HICN_DEBUG (
+ "Adding nexthop to the tfib, dpo index in_face %d, dpo index "
+ "tfib %d",
+ in_face_id, tfib->next_hops[pos]);
hicn_mapme_tfib_add (tfib, tfib->next_hops[pos]);
}
- hicn_mapme_nh_set (tfib, in_face_id);
+ int ret = hicn_mapme_nh_set (tfib, in_face_id);
+ HICN_DEBUG ("Locks on face %d: %d", in_face_id,
+ hicn_dpoi_get_from_idx (in_face_id)->locks);
+ if (ret == HICN_ERROR_MAPME_NEXT_HOP_ADDED &&
+ hicn_get_buffer (b)->flags & HICN_BUFFER_FLAGS_NEW_FACE)
+ {
+ hicn_face_unlock_with_id (in_face_id);
+ }
/* We transmit both the prefix and the full dpo (type will be needed to
* pick the right transmit node */
@@ -168,15 +278,22 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
}
else if (params.seq == fib_seq)
{
- DEBUG ("Same sequence number than FIB %d > %d, adding next hop",
- params.seq, fib_seq);
+ HICN_DEBUG ("Same sequence number than FIB %d > %d, adding next hop",
+ params.seq, fib_seq);
- /* Remove ingress face from TFIB in case it was present */
- hicn_mapme_tfib_del (tfib, in_face_id);
+ /**
+ * Add nh BEFORE removing the face from the tfib, as if the last lock is
+ * held by the tfib, deleting it first would also delete the face,
+ * resulting in a undefined behavior after (Debug mode -> SIGABRT,
+ * Release Mode -> Corrupted memory / SIGSEGV).
+ **/
/* Add ingress face to next hops */
hicn_mapme_nh_add (tfib, in_face_id);
+ /* Remove ingress face from TFIB in case it was present */
+ hicn_mapme_tfib_del (tfib, in_face_id);
+
/* Multipath, multihoming, multiple producers or duplicate interest */
retx_t *retx = vlib_process_signal_event_data (
vm, hicn_mapme_eventmgr_process_node.index,
@@ -187,8 +304,17 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b,
{
/*
* face is propagating outdated information, we can just consider it as a
- * prevHops
+ * prevHops, unless it is the current nexthop.
*/
+ if (hicn_mapme_nh_has (tfib, in_face_id))
+ {
+ HICN_DEBUG ("Ignored seq %d < fib_seq %d from current nexthop",
+ params.seq, fib_seq);
+ return true;
+ }
+ HICN_DEBUG ("Received seq %d < fib_seq %d, sending backwards",
+ params.seq, fib_seq);
+
hicn_mapme_tfib_add (tfib, in_face_id);
retx_t *retx = vlib_process_signal_event_data (
diff --git a/hicn-plugin/src/mapme_eventmgr.c b/hicn-plugin/src/mapme_eventmgr.c
index 49a9b5c57..c7ae4ecd7 100644
--- a/hicn-plugin/src/mapme_eventmgr.c
+++ b/hicn-plugin/src/mapme_eventmgr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -24,6 +24,11 @@
#define DEFAULT_TIMEOUT 1.0 /* s */
+/**
+ * @brief This is a process node reacting to face events.
+ */
+vlib_node_registration_t hicn_mapme_eventmgr_process_node;
+
hicn_mapme_main_t mapme_main;
hicn_prefix_t *retx_pool;
@@ -33,7 +38,6 @@ void
hicn_mapme_init (vlib_main_t *vm)
{
mapme_main.vm = vm;
- mapme_main.log_class = vlib_log_register_class ("hicn_mapme", 0);
}
/* borrowed from vnet/fib/ip4_fib.c */
@@ -77,7 +81,6 @@ hicn_mapme_process_fib_entry (vlib_main_t *vm, hicn_face_id_t face,
const dpo_id_t *load_balance_dpo_id;
load_balance_t *lb;
dpo_id_t *dpo_id;
- fib_entry_t *fib_entry;
load_balance_dpo_id = fib_entry_contribute_ip_forwarding (*fib_entry_index);
@@ -92,12 +95,14 @@ hicn_mapme_process_fib_entry (vlib_main_t *vm, hicn_face_id_t face,
{
/* un-const */
dpo_id = (dpo_id_t *) load_balance_get_bucket_i (lb, i);
-
if (dpo_is_hicn (dpo_id))
{
+#ifdef HICN_DDEBUG
+ fib_entry_t *fib_entry;
fib_entry = fib_entry_get (*fib_entry_index);
- vlib_cli_output (vm, "set face pending %U", format_fib_prefix,
- &fib_entry->fe_prefix);
+ HICN_DEBUG ("set face pending %U", format_fib_prefix,
+ &fib_entry->fe_prefix);
+#endif
}
}
}
@@ -107,16 +112,10 @@ hicn_mapme_process_ip4_fib (vlib_main_t *vm, hicn_face_id_t face)
{
ip4_main_t *im4 = &ip4_main;
fib_table_t *fib_table;
- int table_id = -1, fib_index = ~0;
pool_foreach (fib_table, im4->fibs)
{
- ip4_fib_t *fib = pool_elt_at_index (im4->v4_fibs, fib_table->ft_index);
-
- if (table_id >= 0 && table_id != (int) fib->table_id)
- continue;
- if (fib_index != ~0 && fib_index != (int) fib->index)
- continue;
+ ip4_fib_t *fib = pool_elt_at_index (ip4_fibs, fib_table->ft_index);
fib_node_index_t *fib_entry_index;
ip4_fib_show_walk_ctx_t ctx = {
@@ -241,8 +240,8 @@ hicn_mapme_send_message (vlib_main_t *vm, const hicn_prefix_t *prefix,
size_t n;
/* This should be retrieved from face information */
- DEBUG ("Retransmission for prefix %U seq=%d", format_ip46_address,
- &prefix->name, IP46_TYPE_ANY, params->seq);
+ HICN_DEBUG ("Retransmission for prefix %U seq=%d", format_ip46_address,
+ &prefix->name, IP46_TYPE_ANY, params->seq);
char *node_name = hicn_mapme_get_dpo_face_node (face);
if (!node_name)
@@ -257,7 +256,7 @@ hicn_mapme_send_message (vlib_main_t *vm, const hicn_prefix_t *prefix,
u8 *buffer = get_packet_buffer (
vm, node_index, face, (ip46_address_t *) prefix,
(params->protocol == IPPROTO_IPV6) ? HICN_TYPE_IPV6_ICMP :
- HICN_TYPE_IPV4_ICMP);
+ HICN_TYPE_IPV4_ICMP);
n = hicn_mapme_create_packet (buffer, prefix, params);
if (n <= 0)
{
@@ -275,7 +274,7 @@ hicn_mapme_send_updates (vlib_main_t *vm, hicn_prefix_t *prefix, dpo_id_t dpo,
hicn_mapme_tfib_t *tfib = TFIB (hicn_strategy_dpo_ctx_get (dpo.dpoi_index));
if (!tfib)
{
- DEBUG ("NULL TFIB entry id=%d", dpo.dpoi_index);
+ HICN_ERROR ("NULL TFIB entry id=%d", dpo.dpoi_index);
return;
}
@@ -337,7 +336,7 @@ hicn_mapme_eventmgr_process (vlib_main_t *vm, vlib_node_runtime_t *rt,
* Also, we only run a timer when there are pending retransmissions.
*/
timeout = (due_time > current_time) ? due_time - current_time :
- DEFAULT_TIMEOUT;
+ DEFAULT_TIMEOUT;
due_time = current_time + timeout;
}
else
@@ -493,8 +492,8 @@ hicn_mapme_eventmgr_process (vlib_main_t *vm, vlib_node_runtime_t *rt,
TFIB (hicn_strategy_dpo_ctx_get (retx->dpo.dpoi_index));
if (!tfib)
{
- DEBUG ("NULL TFIB entry for dpoi_index=%d",
- retx->dpo.dpoi_index);
+ HICN_ERROR ("NULL TFIB entry for dpoi_index=%d",
+ retx->dpo.dpoi_index);
continue;
}
diff --git a/hicn-plugin/src/mapme_eventmgr.h b/hicn-plugin/src/mapme_eventmgr.h
index 2100a6f90..559ba2e75 100644
--- a/hicn-plugin/src/mapme_eventmgr.h
+++ b/hicn-plugin/src/mapme_eventmgr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -39,8 +39,7 @@ typedef struct
/**
* @brief This is a process node reacting to face events.
*/
-// not static !
-vlib_node_registration_t hicn_mapme_eventmgr_process_node;
+extern vlib_node_registration_t hicn_mapme_eventmgr_process_node;
/**
* @brief Initialize MAP-Me on forwarder
diff --git a/hicn-plugin/src/mgmt.c b/hicn-plugin/src/mgmt.c
index b820a378f..6e9ce9fd8 100644
--- a/hicn-plugin/src/mgmt.c
+++ b/hicn-plugin/src/mgmt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,7 +21,7 @@
#include "mgmt.h"
/* define message IDs */
-#include "hicn_msg_enum.h"
+#include <vpp_plugins/hicn/hicn_msg_enum.h>
/* shared routine betweeen API and CLI, leveraging API message structure */
int
@@ -46,7 +46,8 @@ hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t *rmp)
vlib_error_main_t *em;
vlib_node_t *n;
- foreach_vlib_main() {
+ foreach_vlib_main ()
+ {
em = &this_vlib_main->error_main;
n = vlib_get_node (this_vlib_main, hicn_interest_pcslookup_node.index);
u32 node_cntr_base_idx = n->error_heap_index;
diff --git a/hicn-plugin/src/mgmt.h b/hicn-plugin/src/mgmt.h
index 8eaa18fa8..03e73999f 100644
--- a/hicn-plugin/src/mgmt.h
+++ b/hicn-plugin/src/mgmt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,7 +18,7 @@
#include <vppinfra/error.h>
#include "faces/face.h"
-#include "hicn_api.h"
+#include <vpp_plugins/hicn/hicn_api.h>
/**
* @file mgmt.h
diff --git a/hicn-plugin/src/params.h b/hicn-plugin/src/params.h
index 7c7850d30..324429abe 100644
--- a/hicn-plugin/src/params.h
+++ b/hicn-plugin/src/params.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -60,9 +60,9 @@ STATIC_ASSERT ((HICN_PARAM_FACES_MAX & (HICN_PARAM_FACES_MAX - 1)) == 0,
// HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two
#define HICN_PARAM_PIT_ENTRY_PHOPS_MAX 20
-STATIC_ASSERT ((ceil (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))) ==
- (floor (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))),
- "HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two");
+// STATIC_ASSERT ((ceil (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))) ==
+// (floor (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))),
+// "HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two");
STATIC_ASSERT (
(HICN_PARAM_PIT_ENTRY_PHOPS_MAX <= HICN_PARAM_FACES_MAX),
@@ -113,7 +113,7 @@ STATIC_ASSERT (
#define IPV6_DEFAULT_VERSION 6
#define IPV6_DEFAULT_TRAFFIC_CLASS 0
#define IPV6_DEFAULT_FLOW_LABEL 0
-#define HCIN_IP6_VERSION_TRAFFIC_FLOW \
+#define HICN_IP6_VERSION_TRAFFIC_FLOW \
(IPV6_DEFAULT_VERSION << 28) | (IPV6_DEFAULT_TRAFFIC_CLASS << 20) | \
(IPV6_DEFAULT_FLOW_LABEL & 0xfffff)
#define HICN_IP6_PROTOCOL IP_PROTOCOL_TCP
diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h
index 5c75ce3bd..0e60c526f 100644
--- a/hicn-plugin/src/parser.h
+++ b/hicn-plugin/src/parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -59,10 +59,13 @@ hicn_interest_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen,
u8 next_proto_offset = 6 + (1 - *isv6) * 3;
// in the ipv6 header the next header field is at byte 6
// in the ipv4 header the protocol field is at byte 9
- hicn_type_t type = (hicn_type_t){ { .l4 = IPPROTO_NONE,
- .l3 = IPPROTO_NONE,
- .l2 = ip_pkt[next_proto_offset],
- .l1 = ip_proto } };
+ hicn_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 } };
hicn_get_buffer (pkt)->type = type;
hicn_ops_vft[type.l1]->get_interest_name (type, &pkt_hdr->protocol, name);
@@ -97,10 +100,13 @@ hicn_data_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen,
* header the protocol field is at byte 9
*/
u8 next_proto_offset = 6 + (1 - *isv6) * 3;
- hicn_type_t type = (hicn_type_t){ { .l4 = IPPROTO_NONE,
- .l3 = IPPROTO_NONE,
- .l2 = ip_pkt[next_proto_offset],
- .l1 = ip_proto } };
+ hicn_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 } };
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;
diff --git a/hicn-plugin/src/pcs.c b/hicn-plugin/src/pcs.c
index d9e0baf6f..d6e4fd954 100644
--- a/hicn-plugin/src/pcs.c
+++ b/hicn-plugin/src/pcs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h
index 083efa901..b98b72a53 100644
--- a/hicn-plugin/src/pcs.h
+++ b/hicn-plugin/src/pcs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -91,7 +91,7 @@ typedef struct __attribute__ ((packed)) hicn_pit_entry_s
} hicn_pit_entry_t;
-#define HICN_CS_ENTRY_OPAQUE_SIZE HICN_HASH_NODE_APP_DATA_SIZE - 36
+#define HICN_CS_ENTRY_OPAQUE_SIZE HICN_HASH_NODE_APP_DATA_SIZE - 32
/*
* CS entry, unioned with a PIT entry below
@@ -105,17 +105,17 @@ typedef struct __attribute__ ((packed)) hicn_cs_entry_s
/* 20B + 4B = 24B */
u32 cs_pkt_buf;
- /* Ingress face */
- /* 24B + 4B = 28B */
- hicn_face_id_t cs_rxface;
+ // /* Ingress face */
+ // /* 24B + 4B = 28B */
+ // hicn_face_id_t cs_rxface;
/* Linkage for LRU, in the form of hashtable node indexes */
- /* 28B + 8B = 36B */
+ /* 24B + 8B = 32B */
u32 cs_lru_prev;
u32 cs_lru_next;
/* Reserved for implementing cache policy different than LRU */
- /* 36B + (64 - 36)B = 64B */
+ /* 32B + (64 - 32)B = 64B */
u8 opaque[HICN_CS_ENTRY_OPAQUE_SIZE];
} __attribute__ ((packed)) hicn_cs_entry_t;
@@ -167,8 +167,7 @@ always_inline void hicn_pit_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
hicn_hash_entry_t *hash_entry,
hicn_hash_node_t *node,
const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id,
- hicn_face_id_t inface_id, u8 is_appface);
+ dpo_id_t *hicn_dpo_id);
always_inline void hicn_pcs_cs_update (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
hicn_pcs_entry_t *old_entry,
@@ -193,7 +192,7 @@ always_inline int hicn_pcs_cs_insert_update (
vlib_main_t *vm, hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
hicn_hash_node_t *node, hicn_hash_entry_t **hash_entry, u64 hashval,
u32 *node_id, index_t *dpo_ctx_id, u8 *vft_id, u8 *is_cs, u8 *hash_entry_id,
- u32 *bucket_id, u8 *bucket_is_overflow, hicn_face_id_t inface);
+ u32 *bucket_id, u8 *bucket_is_overflow);
always_inline int
hicn_pcs_pit_insert (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *entry,
@@ -352,7 +351,6 @@ hicn_pcs_delete_internal (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t **pcs_entryp,
else
{
pitcs->pcs_pit_dealloc++;
- hicn_strategy_dpo_ctx_unlock (hicn_dpo_id);
/* Flush faces */
hicn_faces_flush (&(pcs->u.pit.faces));
@@ -370,7 +368,7 @@ always_inline void
hicn_pit_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
hicn_pcs_entry_t *pcs_entry, hicn_hash_entry_t *hash_entry,
hicn_hash_node_t *node, const hicn_dpo_vft_t *dpo_vft,
- dpo_id_t *hicn_dpo_id, hicn_face_id_t inface_id, u8 is_appface)
+ dpo_id_t *hicn_dpo_id)
{
/*
@@ -378,7 +376,6 @@ hicn_pit_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
* hash entry.
*/
pitcs->pcs_pit_count--;
- hicn_strategy_dpo_ctx_unlock (hicn_dpo_id);
/* Flush faces */
hicn_faces_flush (&(pcs_entry->u.pit.faces));
@@ -386,8 +383,6 @@ hicn_pit_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
node->hn_flags |= HICN_HASH_NODE_CS_FLAGS;
pcs_entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG;
- pcs_entry->u.cs.cs_rxface = inface_id;
-
/* Update the CS according to the policy */
hicn_cs_policy_t *policy_state;
hicn_cs_policy_vft_t *policy_vft;
@@ -432,40 +427,8 @@ hicn_pcs_cs_update (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
policy_state = &pitcs->policy_state;
policy_vft = &pitcs->policy_vft;
- if (entry->u.cs.cs_rxface != old_entry->u.cs.cs_rxface)
- {
- /* Dequeue content from the old queue */
- policy_vft->hicn_cs_dequeue (pitcs, node, old_entry, policy_state);
-
- old_entry->u.cs.cs_rxface = entry->u.cs.cs_rxface;
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->policy_vft;
-
- policy_vft->hicn_cs_insert (pitcs, node, old_entry, policy_state);
-
- if (policy_state->count > policy_state->max)
- {
- hicn_hash_node_t *node;
- hicn_pcs_entry_t *pcs_entry;
- hicn_hash_entry_t *hash_entry;
- policy_vft->hicn_cs_delete_get (pitcs, policy_state, &node,
- &pcs_entry, &hash_entry);
-
- /*
- * We don't have to decrease the lock (therefore we cannot
- * use hicn_pcs_cs_delete function)
- */
- policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state);
-
- hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm);
-
- /* Update the global CS counter */
- pitcs->pcs_cs_count--;
- }
- }
- else
- /* Update the CS LRU, moving this item to the head */
- policy_vft->hicn_cs_update (pitcs, node, old_entry, policy_state);
+ /* Update the CS LRU, moving this item to the head */
+ policy_vft->hicn_cs_update (pitcs, node, old_entry, policy_state);
}
always_inline void
@@ -565,13 +528,12 @@ hicn_pcs_cs_insert_update (vlib_main_t *vm, hicn_pit_cs_t *pitcs,
hicn_hash_entry_t **hash_entry, u64 hashval,
u32 *node_id, index_t *dpo_ctx_id, u8 *vft_id,
u8 *is_cs, u8 *hash_entry_id, u32 *bucket_id,
- u8 *bucket_is_overflow, hicn_face_id_t inface)
+ u8 *bucket_is_overflow)
{
int ret;
ASSERT (entry == hicn_hashtb_node_data (node));
- entry->u.cs.cs_rxface = inface;
ret = hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval,
node_id, dpo_ctx_id, vft_id, is_cs, hash_entry_id,
bucket_id, bucket_is_overflow);
diff --git a/hicn-plugin/src/pg.c b/hicn-plugin/src/pg.c
index 2f98e9c16..b77e8fcac 100644
--- a/hicn-plugin/src/pg.c
+++ b/hicn-plugin/src/pg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -203,11 +203,11 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
iface = (hpgm->index_ifaces % hpgm->n_ifaces);
/* Rewrite and send */
isv6_0 ?
- hicn_rewrite_interestv6 (
+ 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 (
+ hicn_rewrite_interestv4 (
vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
@@ -216,7 +216,7 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hpgm->index++;
next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
- HICNPG_INTEREST_NEXT_V4_LOOKUP;
+ HICNPG_INTEREST_NEXT_V4_LOOKUP;
}
if (hicn_interest_parse_pkt (b1, &name1, &namelen1, &hicn1,
&isv6_1) == HICN_ERROR_NONE)
@@ -229,11 +229,11 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
iface = (hpgm->index_ifaces % hpgm->n_ifaces);
/* Rewrite and send */
isv6_1 ?
- hicn_rewrite_interestv6 (
+ 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 (
+ hicn_rewrite_interestv4 (
vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
@@ -242,7 +242,7 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hpgm->index++;
next1 = isv6_1 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
- HICNPG_INTEREST_NEXT_V4_LOOKUP;
+ HICNPG_INTEREST_NEXT_V4_LOOKUP;
}
/* Send pkt to next node */
vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
@@ -320,11 +320,11 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
/* Rewrite and send */
isv6_0 ?
- hicn_rewrite_interestv6 (
+ 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 (
+ hicn_rewrite_interestv4 (
vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
@@ -333,7 +333,7 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hpgm->index++;
next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
- HICNPG_INTEREST_NEXT_V4_LOOKUP;
+ HICNPG_INTEREST_NEXT_V4_LOOKUP;
}
/* Send pkt to ip lookup */
vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
@@ -386,12 +386,12 @@ hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number,
.ip4 = hicnpg_main.pgen_clt_src_addr.ip4,
};
hicn_name_t dst_name = {
- .ip4.prefix_as_ip4 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4,
- .ip4.suffix = seq_number,
+ .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.ip4.prefix_as_ip4.as_u32 += clib_net_to_host_u32 (next_flow);
+ 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;
@@ -432,11 +432,11 @@ hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number,
.ip6 = hicnpg_main.pgen_clt_src_addr.ip6,
};
hicn_name_t dst_name = {
- .ip6.prefix_as_ip6 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6,
- .ip6.suffix = seq_number,
+ .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.ip6.prefix_as_ip6.as_u32[3] += clib_net_to_host_u32 (next_flow);
+ 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;
@@ -1011,10 +1011,10 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
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);
+ convert_interest_to_data_v4 (vm, b0, rb, bi0);
next0 = isv6_0 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
- HICNPG_SERVER_NEXT_V4_LOOKUP;
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
}
if (match1)
@@ -1029,10 +1029,10 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
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);
+ convert_interest_to_data_v4 (vm, b1, rb, bi1);
next1 = isv6_1 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
- HICNPG_SERVER_NEXT_V4_LOOKUP;
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
}
pkts_processed += 2;
@@ -1107,10 +1107,10 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
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);
+ convert_interest_to_data_v4 (vm, b0, rb, bi0);
next0 = isv6_0 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
- HICNPG_SERVER_NEXT_V4_LOOKUP;
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
}
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
(b0->flags & VLIB_BUFFER_IS_TRACED)))
diff --git a/hicn-plugin/src/pg.h b/hicn-plugin/src/pg.h
index 059b076fb..7855248e6 100644
--- a/hicn-plugin/src/pg.h
+++ b/hicn-plugin/src/pg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c
index 34a94936e..a84891b9a 100644
--- a/hicn-plugin/src/route.c
+++ b/hicn-plugin/src/route.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -33,6 +33,7 @@
#include "strategies/dpo_mw.h"
#include "infra.h"
#include "udp_tunnels/udp_tunnel.h"
+#include "mapme.h"
#define FIB_SOURCE_HICN 0x04 // Right after the FIB_SOURCE_INTERFACE priority
@@ -105,94 +106,76 @@ int
hicn_route_set_strategy (fib_prefix_t *prefix, u8 strategy_id)
{
const dpo_id_t *hicn_dpo_id;
- dpo_id_t new_dpo_id = DPO_INVALID;
int ret;
- hicn_dpo_ctx_t *old_hicn_dpo_ctx;
- const hicn_dpo_vft_t *new_dpo_vft;
- index_t new_hicn_dpo_idx;
+ hicn_dpo_ctx_t *hicn_dpo_ctx;
u32 fib_index;
ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index);
if (ret == HICN_ERROR_NONE)
{
- old_hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index);
+ hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index);
+ const hicn_dpo_vft_t *dpo_vft = hicn_dpo_get_vft_from_id (strategy_id);
- new_dpo_vft = hicn_dpo_get_vft_from_id (strategy_id);
-
- if (new_dpo_vft == NULL || old_hicn_dpo_ctx == NULL)
+ if (hicn_dpo_ctx == NULL || dpo_vft == NULL)
return HICN_ERROR_STRATEGY_NOT_FOUND;
- /* Create a new dpo for the new strategy */
- new_dpo_vft->hicn_dpo_create (
- hicn_dpo_id->dpoi_proto, old_hicn_dpo_ctx->next_hops,
- old_hicn_dpo_ctx->entry_count, &new_hicn_dpo_idx);
-
- /* the value we got when we registered */
- dpo_set (&new_dpo_id, new_dpo_vft->hicn_dpo_get_type (),
- (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 :
- DPO_PROTO_IP6),
- new_hicn_dpo_idx);
-
- /* Here is where we create the "via" like route */
- /*
- * For the moment we use the global one the prefix you want
- * to match Neale suggested -- FIB_SOURCE_HICN the client
- * that is adding them -- no easy explanation at this time…
- */
- fib_node_index_t new_fib_node_index =
- fib_table_entry_special_dpo_update (fib_index, prefix, hicn_fib_src,
- FIB_ENTRY_FLAG_EXCLUSIVE,
- &new_dpo_id);
-
- dpo_unlock (&new_dpo_id);
- ret = (new_fib_node_index != FIB_NODE_INDEX_INVALID) ?
- HICN_ERROR_NONE :
- HICN_ERROR_ROUTE_NOT_UPDATED;
+ dpo_vft->hicn_dpo_update_type (hicn_dpo_ctx);
}
// Remember to remove the lock from the table when removing the entry
return ret;
}
-int
-ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t *rpfx,
- ip46_address_t *nh, u32 sw_if)
+static int
+ip_nh_add_del_helper (fib_protocol_t fib_proto, const fib_prefix_t *rpfx,
+ ip46_address_t *nh, u32 sw_if, u32 udp_encap_id,
+ dpo_proto_t proto, u8 is_add)
{
fib_route_path_t *rpaths = NULL, rpath;
u32 fib_index = fib_table_find (fib_proto, 0);
-
clib_memset (&rpath, 0, sizeof (rpath));
+
+ if (nh)
+ {
+ rpath.frp_addr = *nh;
+ rpath.frp_sw_if_index = sw_if;
+ }
+ else if (udp_encap_id != ~0)
+ {
+ rpath.frp_udp_encap_id = udp_encap_id;
+ rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
+ }
+
rpath.frp_weight = 1;
- rpath.frp_sw_if_index = sw_if;
- rpath.frp_addr = *nh;
- rpath.frp_proto = ip46_address_is_ip4 (nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6;
+ rpath.frp_proto = proto;
vec_add1 (rpaths, rpath);
- fib_table_entry_path_add2 (fib_index, rpfx, FIB_SOURCE_CLI,
- FIB_ENTRY_FLAG_NONE, rpaths);
+ if (is_add)
+ fib_table_entry_path_add2 (fib_index, rpfx, FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_NONE, rpaths);
+ else
+ fib_table_entry_path_remove2 (fib_index, rpfx, FIB_SOURCE_API, rpaths);
+
return 0;
}
int
-ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t *rpfx,
- ip46_address_t *nh, u32 sw_if)
+ip_nh_adj_add_del_helper (fib_protocol_t fib_proto, const fib_prefix_t *rpfx,
+ ip46_address_t *nh, u32 sw_if, u8 is_add)
{
- fib_route_path_t *rpaths = NULL, rpath;
-
- u32 fib_index = fib_table_find (fib_proto, 0);
-
- clib_memset (&rpath, 0, sizeof (rpath));
- rpath.frp_weight = 1;
- rpath.frp_sw_if_index = sw_if;
- rpath.frp_addr = *nh;
- rpath.frp_proto = ip46_address_is_ip4 (nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6;
-
- vec_add1 (rpaths, rpath);
+ return ip_nh_add_del_helper (
+ fib_proto, rpfx, nh, sw_if, ~0,
+ ip46_address_is_ip4 (nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6, is_add);
+}
- fib_table_entry_path_remove2 (fib_index, rpfx, FIB_SOURCE_CLI, rpaths);
- return 0;
+int
+ip_nh_udp_tunnel_add_del_helper (fib_protocol_t fib_proto,
+ const fib_prefix_t *rpfx, u32 uei,
+ dpo_proto_t proto, u8 is_add)
+{
+ return ip_nh_add_del_helper (fib_proto, rpfx, NULL, ~0, uei, proto, is_add);
}
static ip46_address_t *
@@ -234,13 +217,14 @@ get_address (ip46_address_t *nh, u32 sw_if, fib_protocol_t proto)
}
static void
-sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry)
+sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry, hicn_face_id_t **pvec_faces)
{
+ hicn_face_id_t *vec_faces = NULL;
const dpo_id_t *dpo_loadbalance =
fib_entry_contribute_ip_forwarding (fib_entry->fib_entry_index);
+ const fib_entry_t *_fib_entry = fib_entry_get (fib_entry->fib_entry_index);
const load_balance_t *lb0 = load_balance_get (dpo_loadbalance->dpoi_index);
index_t hicn_fib_entry_index = hicn_strategy_dpo_ctx_get_index (fib_entry);
- hicn_face_id_t *vec_faces = 0;
dpo_id_t temp = DPO_INVALID;
const dpo_id_t *former_dpo = &temp;
@@ -287,32 +271,31 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry)
nh = get_address (&(adj->sub_type.nbr.next_hop), sw_if,
fib_entry->proto);
ADD_FACE (nh);
+ HICN_DEBUG ("Added new HICN face: %d because of route prefix %U",
+ face_id, format_ip_prefix, &_fib_entry->fe_prefix);
}
else if (dpo->dpoi_type == dpo_type_udp_ip4 ||
dpo->dpoi_type == dpo_type_udp_ip6)
{
- u8 proto = dpo->dpoi_type == dpo_type_udp_ip4 ? FIB_PROTOCOL_IP4 :
- FIB_PROTOCOL_IP6;
+ dpo_proto_t proto =
+ dpo->dpoi_type == dpo_type_udp_ip4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6;
ip46_address_t _nh = { 0 };
nh = &_nh;
- switch (dpo->dpoi_proto)
+ switch (_fib_entry->fe_prefix.fp_proto)
{
case FIB_PROTOCOL_IP6:
- case FIB_PROTOCOL_IP4:
- /**
- * Independently of the type of tunnel, encapsulated packet
- * can be either v6 or v4, so we need to create 2 faces for each
- * version. Tunneled hicn packet MUST have locator set to the
- * loopback address, so ::1 for IPv6 and 127.0.0.1 for IPv4.
- */
ip46_address_set_ip6 (nh, &localhost6);
ADD_FACE (nh);
+ break;
+ case FIB_PROTOCOL_IP4:
ip46_address_set_ip4 (nh, &localhost4);
ADD_FACE (nh);
break;
default:
continue;
}
+ HICN_DEBUG ("Added new UDP face: %d because of route prefix %s",
+ face_id, format_ip_prefix, &_fib_entry->fe_prefix);
udp_tunnel_add_existing (dpo->dpoi_index, proto);
}
}
@@ -345,7 +328,8 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry)
/* Remove the lock added by hicn_face_add */
hicn_face_unlock_with_id (*face_id);
}
- vec_free (vec_faces);
+
+ *pvec_faces = vec_faces;
}
static void
@@ -380,7 +364,7 @@ disable_data_receiving_rm_fib_entry (vnet_main_t *vnm, vnet_sw_interface_t *si,
}
int
-hicn_route_enable (fib_prefix_t *prefix)
+hicn_route_enable (fib_prefix_t *prefix, hicn_face_id_t **pvec_faces)
{
int ret = HICN_ERROR_NONE;
@@ -413,10 +397,14 @@ hicn_route_enable (fib_prefix_t *prefix)
if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID)
{
+ HICN_DEBUG (
+ "No route found for %U. Creating DPO and tracking fib prefix.",
+ format_ip_prefix, prefix);
dpo_id_t dpo = DPO_INVALID;
index_t dpo_idx;
default_dpo.hicn_dpo_create (prefix->fp_proto, 0, NEXT_HOP_INVALID,
&dpo_idx);
+ HICN_DEBUG ("Created new DPO_MW_CTX_T: %d.", dpo_idx);
/* the value we got when we registered */
/*
@@ -425,8 +413,14 @@ hicn_route_enable (fib_prefix_t *prefix)
*/
dpo_set (&dpo, default_dpo.hicn_dpo_get_type (),
(ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 :
- DPO_PROTO_IP6),
+ DPO_PROTO_IP6),
dpo_idx);
+ HICN_DEBUG (
+ "dpo_set called with parameters: type=%d, proto=%s, index=%d",
+ default_dpo.hicn_dpo_get_type (),
+ ip46_address_is_ip4 (&prefix->fp_addr) ? "DPO_PROTO_IP4" :
+ "DPO_PROTO_IP6",
+ dpo_idx);
hicn_dpo_ctx_t *fib_entry = hicn_strategy_dpo_ctx_get (dpo_idx);
@@ -448,7 +442,8 @@ hicn_route_enable (fib_prefix_t *prefix)
fib_hicn_index, prefix, hicn_fib_src,
(FIB_ENTRY_FLAG_EXCLUSIVE | FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), &dpo);
- sync_hicn_fib_entry (fib_entry);
+ HICN_DEBUG ("Calling sync_hicn_fib_entry");
+ sync_hicn_fib_entry (fib_entry, pvec_faces);
/* We added a route, therefore add one lock to the table */
fib_table_lock (fib_index, prefix->fp_proto, hicn_fib_src);
@@ -470,6 +465,8 @@ hicn_route_enable (fib_prefix_t *prefix)
}
else
{
+ HICN_DEBUG ("Found a route for %U. Updating DPO.", format_ip_prefix,
+ &prefix);
const dpo_id_t *load_balance_dpo_id;
const dpo_id_t *strategy_dpo_id;
@@ -481,6 +478,7 @@ hicn_route_enable (fib_prefix_t *prefix)
if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE)
{
ret = HICN_ERROR_ROUTE_NO_LD;
+ HICN_ERROR ("DPO is not a load balance.");
goto done;
}
else
@@ -493,19 +491,22 @@ hicn_route_enable (fib_prefix_t *prefix)
if (!dpo_is_hicn (strategy_dpo_id))
{
ret = HICN_ERROR_ROUTE_DPO_NO_HICN;
+ HICN_ERROR ("DPO is not hicn.");
goto done;
}
if (lb->lb_n_buckets > 1)
{
ret = HICN_ERROR_ROUTE_MLT_LD;
+ HICN_ERROR ("Too many load balance buckets.");
goto done;
}
hicn_dpo_ctx_t *hicn_fib_entry =
hicn_strategy_dpo_ctx_get (strategy_dpo_id->dpoi_index);
- sync_hicn_fib_entry (hicn_fib_entry);
+ HICN_DEBUG ("Calling sync_hicn_fib_entry");
+ sync_hicn_fib_entry (hicn_fib_entry, pvec_faces);
}
}
@@ -527,6 +528,7 @@ hicn_route_disable (fib_prefix_t *prefix)
if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID)
{
+ HICN_ERROR ("Route %U not found", format_ip_prefix, prefix);
return HICN_ERROR_ROUTE_NOT_FOUND;
}
else
@@ -542,6 +544,8 @@ hicn_route_disable (fib_prefix_t *prefix)
/* The dpo is not a load balance dpo as expected */
if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE)
{
+ HICN_ERROR ("DPO for route %U is not a load balance.",
+ format_ip_prefix, prefix);
ret = HICN_ERROR_ROUTE_NO_LD;
goto done;
}
@@ -554,12 +558,16 @@ hicn_route_disable (fib_prefix_t *prefix)
if (!dpo_is_hicn (strategy_dpo_id))
{
+ HICN_ERROR ("ERROR: DPO for route %U is not a hicn.",
+ format_ip_prefix, prefix);
ret = HICN_ERROR_ROUTE_DPO_NO_HICN;
goto done;
}
if (lb->lb_n_buckets > 1)
{
+ HICN_ERROR ("DPO for route %U contains multiple next hops.",
+ format_ip_prefix, prefix);
ret = HICN_ERROR_ROUTE_MLT_LD;
goto done;
}
@@ -567,17 +575,37 @@ hicn_route_disable (fib_prefix_t *prefix)
hicn_fib_entry =
hicn_strategy_dpo_ctx_get (strategy_dpo_id->dpoi_index);
+ HICN_DEBUG ("Found from hicn_strategy_dpo_ctx_get with index %d: %p",
+ strategy_dpo_id->dpoi_index, hicn_fib_entry);
+
+ if (PREDICT_FALSE (!hicn_fib_entry))
+ {
+ HICN_ERROR (
+ "hicn_strategy_dpo_ctx_get for index %d returned NULL",
+ strategy_dpo_id->dpoi_index);
+ ret = HICN_ERROR_ROUTE_DPO_NO_HICN;
+ goto done;
+ }
+
for (int i = 0; i < hicn_fib_entry->entry_count; i++)
{
hicn_strategy_dpo_ctx_del_nh (hicn_fib_entry->next_hops[i],
hicn_fib_entry);
}
+
+ hicn_mapme_tfib_clear ((hicn_mapme_tfib_t *) hicn_fib_entry);
}
+ HICN_DEBUG (
+ "Calling fib_entry_untrack and fib_table_entry_special_remove "
+ "for route %U.",
+ format_ip_prefix, prefix);
+
fib_entry_untrack (hicn_fib_entry->fib_entry_index,
hicn_fib_entry->fib_sibling);
fib_table_entry_special_remove (fib_hicn_index, prefix, hicn_fib_src);
+ fib_node_unlock (&hicn_fib_entry->fib_node);
/* Disable the feature to punt data packet every time we enable a new
* hicn route */
@@ -618,7 +646,11 @@ hicn_fib_back_walk_notify (fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
hicn_dpo_ctx_t *fib_entry = hicn_ctx_from_fib_node (node);
- sync_hicn_fib_entry (fib_entry);
+ hicn_face_id_t *vec_faces = NULL;
+ HICN_DEBUG ("Calling sync_hicn_fib_entry from hicn_fib_back_walk_notify");
+ sync_hicn_fib_entry (fib_entry, &vec_faces);
+ if (vec_faces != NULL)
+ vec_free (vec_faces);
return (FIB_NODE_BACK_WALK_CONTINUE);
}
@@ -661,7 +693,8 @@ enable_data_on_existing_hicn (fib_node_index_t fei, void *ctx)
goto done;
}
- enable_disable_data_receiving (strategy_dpo_id->dpoi_proto, sw_if, 1);
+ enable_disable_data_receiving (
+ (fib_protocol_t) strategy_dpo_id->dpoi_proto, sw_if, 1);
}
done:
@@ -673,18 +706,18 @@ set_table_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
{
if (!is_add)
- return HICN_ERROR_NONE;
+ return NULL;
- int rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, HICN_FIB_TABLE, 1);
+ int rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, HICN_FIB_TABLE);
if (!rv)
{
- rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, HICN_FIB_TABLE, 1);
+ rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, HICN_FIB_TABLE);
if (rv)
{
/* An error occurred. Bind the interface back to the default fib */
- ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, 0, 1);
+ ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, 0);
}
}
@@ -707,10 +740,11 @@ set_table_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
}
return rv ? clib_error_return (0, "unable to add hicn table to interface") :
- 0;
+ 0;
}
-VNET_SW_INTERFACE_ADD_DEL_FUNCTION (set_table_interface_add_del);
+VNET_SW_INTERFACE_ADD_DEL_FUNCTION_PRIO (set_table_interface_add_del,
+ VNET_ITF_FUNC_PRIORITY_HIGH);
void
hicn_route_init ()
@@ -720,7 +754,8 @@ hicn_route_init ()
hicn_fib_src =
fib_source_allocate ("hicn", FIB_SOURCE_HICN, FIB_SOURCE_BH_API);
- hicn_fib_node_type = fib_node_register_new_type (&hicn_fib_vft);
+ hicn_fib_node_type =
+ fib_node_register_new_type ("hicn_route_fib_node", &hicn_fib_vft);
ip_table_create (FIB_PROTOCOL_IP4, HICN_FIB_TABLE, 1, (const u8 *) "hicn4");
ip_table_create (FIB_PROTOCOL_IP6, HICN_FIB_TABLE, 1, (const u8 *) "hicn6");
diff --git a/hicn-plugin/src/route.h b/hicn-plugin/src/route.h
index 19b18b8c6..072926498 100644
--- a/hicn-plugin/src/route.h
+++ b/hicn-plugin/src/route.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -73,28 +73,31 @@ int hicn_route_get_dpo (const fib_prefix_t *prefix, const dpo_id_t **hicn_dpo,
int hicn_route_set_strategy (fib_prefix_t *prefix, u32 strategy_id);
/**
- * @Brief Helper to add a nex hop in the vrf 0. If there are no entries in the
- * vrf 0 that matches with the prefix (epm), a new one is created.
+ * @Brief Helper to add an adj nex hop in the vrf 0. If there are no entries in
+ * the vrf 0 that matches with the prefix (epm), a new one is created.
*
* @param fib_proto FIB_PROTOCOL_IP6 or FIB_PROTOCOL_IP4 (mpls not supported)
- * @param pfx Prefix for which to add a next hop
+ * @param rpfx Prefix for which to add a next hop
* @param nh Next hop to add
* @param sw_if Software interface index to add in the next hop
*/
-int ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t *pfx,
- ip46_address_t *nh, u32 sw_if);
+int ip_nh_adj_add_del_helper (fib_protocol_t fib_proto,
+ const fib_prefix_t *rpfx, ip46_address_t *nh,
+ u32 sw_if, u8 is_add);
/**
- * @Brief Helper to remove a nex hop in the vrf 0. If there are no entries in
- * the vrf 0 nothing happens.
+ * @Brief Helper to add an udp-tunnel nex hop in the vrf 0. If there are no
+ * entries in the vrf 0 that matches with the prefix (epm), a new one is
+ * created.
*
* @param fib_proto FIB_PROTOCOL_IP6 or FIB_PROTOCOL_IP4 (mpls not supported)
- * @param pfx Prefix for which to remove a next hop
- * @param nh Next hop to remove
- * @param sw_if Software interface index in the next hop definition
+ * @param rpfx Prefix for which to add a next hop
+ * @param uei The UDP ENCAP ID
+ * @param sw_if The
*/
-int ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t *rpfx,
- ip46_address_t *nh, u32 sw_if);
+int ip_nh_udp_tunnel_add_del_helper (fib_protocol_t fib_proto,
+ const fib_prefix_t *rpfx, u32 uei,
+ dpo_proto_t proto, u8 is_add);
/**
* @Brief Enable an hICN for an ip prefix
@@ -106,7 +109,7 @@ int ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t *rpfx,
* loadbalancer in the vrf HICN already contains a dpo which is not an hICN one
* HICN_ERROR_ROUTE_MLT_LD if there are more than a dpo in the vpp loadbalancer
*/
-int hicn_route_enable (fib_prefix_t *prefix);
+int hicn_route_enable (fib_prefix_t *prefix, hicn_face_id_t **vec_faces);
/**
* @Brief Disable an hICN for an ip prefix. If hICN wasn't enable on the prefix
diff --git a/hicn-plugin/src/state.h b/hicn-plugin/src/state.h
index 561aef2db..39953722d 100644
--- a/hicn-plugin/src/state.h
+++ b/hicn-plugin/src/state.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/strategies/dpo_mw.c b/hicn-plugin/src/strategies/dpo_mw.c
index 70ef7d7c9..1a7d2e495 100644
--- a/hicn-plugin/src/strategies/dpo_mw.c
+++ b/hicn-plugin/src/strategies/dpo_mw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -28,6 +28,7 @@ static const hicn_dpo_vft_t hicn_dpo_mw_vft = {
.hicn_dpo_get_type = &hicn_dpo_strategy_mw_get_type,
.hicn_dpo_module_init = &hicn_dpo_strategy_mw_module_init,
.hicn_dpo_create = &hicn_strategy_mw_ctx_create,
+ .hicn_dpo_update_type = &hicn_strategy_mw_update_ctx_type,
.hicn_dpo_add_update_nh = &hicn_strategy_mw_ctx_add_nh,
.hicn_dpo_del_nh = &hicn_strategy_mw_ctx_del_nh,
.hicn_dpo_format = &hicn_strategy_mw_format_ctx
@@ -117,8 +118,22 @@ hicn_strategy_mw_ctx_create (fib_protocol_t proto,
*dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx);
- init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_mw, proto);
+ HICN_DEBUG ("Successful hicn_strategy_dpo_ctx_alloc with index %d",
+ *dpo_idx);
+ init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_mw,
+ (dpo_proto_t) proto);
+
+ memset (hicn_strategy_mw_ctx->weight, 0, HICN_PARAM_FIB_ENTRY_NHOPS_MAX);
+}
+
+void
+hicn_strategy_mw_update_ctx_type (hicn_dpo_ctx_t *hicn_strategy_ctx)
+{
+ hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx;
+ hicn_strategy_mw_ctx = (hicn_strategy_mw_ctx_t *) hicn_strategy_ctx->data;
+
+ hicn_strategy_ctx->dpo_type = hicn_dpo_type_mw;
memset (hicn_strategy_mw_ctx->weight, 0, HICN_PARAM_FIB_ENTRY_NHOPS_MAX);
}
diff --git a/hicn-plugin/src/strategies/dpo_mw.h b/hicn-plugin/src/strategies/dpo_mw.h
index 1a174631a..d2807d1a5 100644
--- a/hicn-plugin/src/strategies/dpo_mw.h
+++ b/hicn-plugin/src/strategies/dpo_mw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -72,6 +72,13 @@ void hicn_strategy_mw_ctx_create (fib_protocol_t proto,
index_t *dpo_idx);
/**
+ * @brief Update existing ctx setting it to mw
+ *
+ * @param hicn_strategy_ctx pointer to the ctx to update
+ */
+void hicn_strategy_mw_update_ctx_type (hicn_dpo_ctx_t *hicn_strategy_ctx);
+
+/**
* @brief Add or update a next hop in the dpo ctx.
*
* This function is meant to be used in the control plane and not in the data
diff --git a/hicn-plugin/src/strategies/dpo_rp.c b/hicn-plugin/src/strategies/dpo_rp.c
new file mode 100644
index 000000000..7f527cdb6
--- /dev/null
+++ b/hicn-plugin/src/strategies/dpo_rp.c
@@ -0,0 +1,155 @@
+/*
+ * 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 "dpo_rp.h"
+#include "strategy_rp.h"
+#include "../strategy_dpo_manager.h"
+#include "../strategy_dpo_ctx.h"
+
+/**
+ * @brief DPO type value for the rp_strategy
+ */
+static dpo_type_t hicn_dpo_type_rp;
+
+static const hicn_dpo_vft_t hicn_dpo_rp_vft = {
+ .hicn_dpo_is_type = &hicn_dpo_is_type_strategy_rp,
+ .hicn_dpo_get_type = &hicn_dpo_strategy_rp_get_type,
+ .hicn_dpo_module_init = &hicn_dpo_strategy_rp_module_init,
+ .hicn_dpo_create = &hicn_strategy_rp_ctx_create,
+ .hicn_dpo_update_type = &hicn_strategy_rp_update_ctx_type,
+ .hicn_dpo_add_update_nh = &hicn_strategy_rp_ctx_add_nh,
+ .hicn_dpo_del_nh = &hicn_strategy_rp_ctx_del_nh,
+ .hicn_dpo_format = &hicn_strategy_rp_format_ctx
+};
+
+int
+hicn_dpo_is_type_strategy_rp (const dpo_id_t *dpo)
+{
+ return dpo->dpoi_type == hicn_dpo_type_rp;
+}
+
+void
+hicn_dpo_strategy_rp_module_init (void)
+{
+ /*
+ * Register our type of dpo
+ */
+ hicn_dpo_type_rp = hicn_dpo_register_new_type (
+ hicn_nodes_strategy, &hicn_dpo_rp_vft, hicn_rp_strategy_get_vft (),
+ &dpo_strategy_rp_ctx_vft);
+}
+
+dpo_type_t
+hicn_dpo_strategy_rp_get_type (void)
+{
+ return hicn_dpo_type_rp;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+u8 *
+hicn_strategy_rp_format_ctx (u8 *s, int n, ...)
+{
+ va_list args;
+ va_start (args, n);
+ s = format_hicn_strategy_rp_ctx (s, &args);
+ return s;
+}
+
+u8 *
+format_hicn_strategy_rp_ctx (u8 *s, va_list *ap)
+{
+ int i = 0;
+ index_t index = va_arg (*ap, index_t);
+ hicn_dpo_ctx_t *dpo_ctx = NULL;
+ u32 indent = va_arg (*ap, u32);
+
+ dpo_ctx = hicn_strategy_dpo_ctx_get (index);
+ if (dpo_ctx == NULL)
+ return s;
+
+ for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++)
+ {
+ u8 *buf = NULL;
+ if (i < dpo_ctx->entry_count)
+ buf = format (NULL, "FIB");
+ else if (i >= HICN_PARAM_FIB_ENTRY_NHOPS_MAX - dpo_ctx->tfib_entry_count)
+ buf = format (NULL, "TFIB");
+ else
+ continue;
+
+ s = format (s, "\n");
+ s = format (s, "%U ", format_hicn_face, dpo_ctx->next_hops[i], indent);
+ s = format (s, " %s", buf);
+ }
+
+ return (s);
+}
+
+void
+hicn_strategy_rp_ctx_create (fib_protocol_t proto,
+ const hicn_face_id_t *next_hop, int nh_len,
+ index_t *dpo_idx)
+{
+ hicn_dpo_ctx_t *hicn_strategy_ctx;
+
+ /* Allocate a hicn_dpo_ctx on the vpp pool and initialize it */
+ hicn_strategy_ctx = hicn_strategy_dpo_ctx_alloc ();
+
+ *dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx);
+
+ init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_rp,
+ (dpo_proto_t) proto);
+}
+
+void
+hicn_strategy_rp_update_ctx_type (hicn_dpo_ctx_t *hicn_strategy_ctx)
+{
+ hicn_strategy_ctx->dpo_type = hicn_dpo_type_rp;
+ // don't care to reset data, it is not used
+}
+
+int
+hicn_strategy_rp_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx)
+{
+ hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
+ u8 pos = 0;
+
+ if (hicn_strategy_dpo_ctx == NULL)
+ {
+ return HICN_ERROR_STRATEGY_NOT_FOUND;
+ }
+
+ hicn_strategy_dpo_ctx_add_nh (nh, hicn_strategy_dpo_ctx, &pos);
+ // nothing else to initialize in this strategy
+ return HICN_ERROR_NONE;
+}
+
+int
+hicn_strategy_rp_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx)
+{
+ hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
+ // No need to change the current_nhop. It will be updated at the next
+ // selection.
+ return hicn_strategy_dpo_ctx_del_nh (face_id, hicn_strategy_dpo_ctx);
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/strategies/dpo_rp.h b/hicn-plugin/src/strategies/dpo_rp.h
new file mode 100644
index 000000000..4fe645add
--- /dev/null
+++ b/hicn-plugin/src/strategies/dpo_rp.h
@@ -0,0 +1,152 @@
+/*
+ * 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_DPO_RP_H__
+#define __HICN_DPO_RP_H__
+
+#include <vnet/dpo/dpo.h>
+#include "../strategy_dpo_ctx.h"
+
+/**
+ * @file dpo_rp.h
+ *
+ * This file implements the strategy vtf (see strategy.h) and
+ * the dpo vft (see strategy_dpo_manager.h) for the strategy
+ * replication.
+ */
+
+typedef struct hicn_strategy_rp_ctx_s
+{
+} hicn_strategy_rp_ctx_t;
+
+/**
+ * @brief Format the dpo ctx for a human-readable string
+ *
+ * @param s String to which to append the formatted dpo ctx
+ * @param ap List of parameters for the formatting
+ *
+ * @result The string with the formatted dpo ctx
+ */
+u8 *format_hicn_strategy_rp_ctx (u8 *s, va_list *ap);
+
+const static dpo_vft_t dpo_strategy_rp_ctx_vft = {
+ .dv_lock = hicn_strategy_dpo_ctx_lock,
+ .dv_unlock = hicn_strategy_dpo_ctx_unlock,
+ .dv_format = format_hicn_strategy_rp_ctx,
+};
+
+/**
+ * @brief Retrieve an hicn_strategy_rp_ctx object
+ *
+ * @param indext Index of the hicn_dpo_ctx to retrieve
+ * @return The hicn_dpo_ctx object or NULL
+ */
+hicn_dpo_ctx_t *hicn_strategy_rp_ctx_get (index_t index);
+
+/**
+ * @brief Create a new replication ctx
+ *
+ * @param proto The protocol to which the dpo is meant for (see vpp docs)
+ * @param next_hop A list of next hops to be inserted in the dpo ctx
+ * @param nh_len Size of the list
+ * @param dpo_idx index_t that will hold the index of the created dpo ctx
+ * @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL
+ */
+void hicn_strategy_rp_ctx_create (fib_protocol_t proto,
+ const hicn_face_id_t *next_hop, int nh_len,
+ index_t *dpo_idx);
+
+/**
+ * @brief Update existing ctx setting it to rp
+ *
+ * @param hicn_strategy_ctx pointer to the ctx to update
+ */
+void hicn_strategy_rp_update_ctx_type (hicn_dpo_ctx_t *hicn_strategy_ctx);
+
+/**
+ * @brief Add or update a next hop in the dpo ctx.
+ *
+ * This function is meant to be used in the control plane and not in the data
+ * plane, as it is not optimized for the latter.
+ *
+ * @param nh Next hop to insert in the dpo ctx
+ * @param dpo_idx Index of the dpo ctx to update with the new or updated next
+ * hop
+ * @return HICN_ERROR_NONE if the update or insert was fine,
+ * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND
+ */
+int hicn_strategy_rp_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx);
+
+/**
+ * @brief Delete a next hop in the dpo ctx.
+ *
+ * @param face_id Face identifier of the next hop
+ * @param dpo_idx Index of the dpo ctx to update with the new or updated next
+ * hop
+ * @return HICN_ERROR_NONE if the update or insert was fine,
+ * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND
+ */
+int hicn_strategy_rp_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx);
+
+/**
+ * @brief Prefetch a dpo
+ *
+ * @param dpo_idx Index of the dpo ctx to prefetch
+ */
+void hicn_strategy_rp_ctx_prefetch (index_t dpo_idx);
+
+/**
+ * @brief Return true if the dpo is of type strategy rp
+ *
+ * @param dpo Dpo to check the type
+ */
+int hicn_dpo_is_type_strategy_rp (const dpo_id_t *dpo);
+
+/**
+ * @brief Initialize the Replication strategy
+ */
+void hicn_dpo_strategy_rp_module_init (void);
+
+/**
+ * @brief Return the dpo type for the Replication strategy
+ */
+dpo_type_t hicn_dpo_strategy_rp_get_type (void);
+
+/**
+ * @brief Format the dpo ctx for the strategy Replication
+ *
+ * @param s String to append the formatted dpo ctx
+ * @param ap List of arguments to format
+ */
+u8 *format_hicn_dpo_strategy_rp (u8 *s, va_list *ap);
+
+/**
+ * @brief Format the dpo ctx for the strategy Replication. To
+ * call from other functions
+ *
+ * @param s String to append the formatted dpo ctx
+ * @param ... List of arguments to format
+ */
+u8 *hicn_strategy_rp_format_ctx (u8 *s, int n, ...);
+
+#endif // __HICN_DPO_RP_H__
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/strategies/dpo_rr.c b/hicn-plugin/src/strategies/dpo_rr.c
index 3fe506bd1..86b68186b 100644
--- a/hicn-plugin/src/strategies/dpo_rr.c
+++ b/hicn-plugin/src/strategies/dpo_rr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -28,6 +28,7 @@ static const hicn_dpo_vft_t hicn_dpo_rr_vft = {
.hicn_dpo_get_type = &hicn_dpo_strategy_rr_get_type,
.hicn_dpo_module_init = &hicn_dpo_strategy_rr_module_init,
.hicn_dpo_create = &hicn_strategy_rr_ctx_create,
+ .hicn_dpo_update_type = &hicn_strategy_rr_update_ctx_type,
.hicn_dpo_add_update_nh = &hicn_strategy_rr_ctx_add_nh,
.hicn_dpo_del_nh = &hicn_strategy_rr_ctx_del_nh,
.hicn_dpo_format = &hicn_strategy_rr_format_ctx
@@ -117,11 +118,22 @@ hicn_strategy_rr_ctx_create (fib_protocol_t proto,
*dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx);
- init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_rr, proto);
+ init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_rr,
+ (dpo_proto_t) proto);
hicn_strategy_rr_ctx->current_nhop = 0;
}
+void
+hicn_strategy_rr_update_ctx_type (hicn_dpo_ctx_t *hicn_strategy_ctx)
+{
+ hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx;
+ hicn_strategy_rr_ctx = (hicn_strategy_rr_ctx_t *) hicn_strategy_ctx->data;
+
+ hicn_strategy_ctx->dpo_type = hicn_dpo_type_rr;
+ hicn_strategy_rr_ctx->current_nhop = 0;
+}
+
int
hicn_strategy_rr_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx)
{
diff --git a/hicn-plugin/src/strategies/dpo_rr.h b/hicn-plugin/src/strategies/dpo_rr.h
index e68e2917d..72ec7b5df 100644
--- a/hicn-plugin/src/strategies/dpo_rr.h
+++ b/hicn-plugin/src/strategies/dpo_rr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -74,6 +74,13 @@ void hicn_strategy_rr_ctx_create (fib_protocol_t proto,
index_t *dpo_idx);
/**
+ * @brief Update existing ctx setting it to rr
+ *
+ * @param hicn_strategy_ctx pointer to the ctx to update
+ */
+void hicn_strategy_rr_update_ctx_type (hicn_dpo_ctx_t *hicn_strategy_ctx);
+
+/**
* @brief Add or update a next hop in the dpo ctx.
*
* This function is meant to be used in the control plane and not in the data
diff --git a/hicn-plugin/src/strategies/strategy_mw.c b/hicn-plugin/src/strategies/strategy_mw.c
index 9409ec856..990e64a5d 100644
--- a/hicn-plugin/src/strategies/strategy_mw.c
+++ b/hicn-plugin/src/strategies/strategy_mw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -25,7 +25,7 @@ void hicn_receive_data_mw (index_t dpo_idx, int nh_idx);
void hicn_add_interest_mw (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
void hicn_on_interest_timeout_mw (index_t dpo_idx);
u32 hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outface);
+ hicn_face_id_t *outfaces, uint32_t *len);
u32 get_strategy_node_index_mw (void);
u8 *hicn_strategy_format_trace_mw (u8 *s, hicn_strategy_trace_t *t);
u8 *hicn_strategy_format_mw (u8 *s, va_list *ap);
@@ -51,12 +51,16 @@ hicn_mw_strategy_get_vft (void)
/* DPO should be give in input as it containes all the information to calculate
* the next hops*/
u32
-hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, hicn_face_id_t *outface)
+hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx,
+ hicn_face_id_t *outfaces, uint32_t *len)
{
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
if (dpo_ctx == NULL)
- return HICN_ERROR_STRATEGY_NOT_FOUND;
+ {
+ *len = 0;
+ return HICN_ERROR_STRATEGY_NOT_FOUND;
+ }
hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx =
(hicn_strategy_mw_ctx_t *) dpo_ctx->data;
@@ -71,7 +75,8 @@ hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, hicn_face_id_t *outface)
}
}
- *outface = dpo_ctx->next_hops[next_hop_index];
+ outfaces[0] = dpo_ctx->next_hops[next_hop_index];
+ *len = 1;
return HICN_ERROR_NONE;
}
@@ -84,7 +89,6 @@ hicn_add_interest_mw (index_t dpo_ctx_idx, hicn_hash_entry_t *hash_entry)
.dpoi_proto = 0,
.dpoi_next_node = 0,
.dpoi_index = dpo_ctx_idx };
- hicn_strategy_dpo_ctx_lock (&hicn_dpo_id);
hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id);
}
diff --git a/hicn-plugin/src/strategies/strategy_mw.h b/hicn-plugin/src/strategies/strategy_mw.h
index 9e0078b23..186e8c5ab 100644
--- a/hicn-plugin/src/strategies/strategy_mw.h
+++ b/hicn-plugin/src/strategies/strategy_mw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/strategies/strategy_mw_cli.c b/hicn-plugin/src/strategies/strategy_mw_cli.c
index 6b56e9fd5..4ace68423 100644
--- a/hicn-plugin/src/strategies/strategy_mw_cli.c
+++ b/hicn-plugin/src/strategies/strategy_mw_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -76,7 +76,7 @@ hicn_mw_strategy_cli_set_weight_command_fn (vlib_main_t *vm,
}
prefix.fp_proto = ip46_address_is_ip4 (&prefix.fp_addr) ? FIB_PROTOCOL_IP4 :
- FIB_PROTOCOL_IP6;
+ FIB_PROTOCOL_IP6;
ret = hicn_route_get_dpo (&prefix, &hicn_dpo_id, &fib_index);
if (ret == HICN_ERROR_NONE)
diff --git a/hicn-plugin/src/strategies/strategy_rp.c b/hicn-plugin/src/strategies/strategy_rp.c
new file mode 100644
index 000000000..748cd69b1
--- /dev/null
+++ b/hicn-plugin/src/strategies/strategy_rp.c
@@ -0,0 +1,118 @@
+/*
+ * 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 "dpo_rp.h"
+#include "../strategy.h"
+#include "../strategy_dpo_ctx.h"
+#include "../faces/face.h"
+#include "../hashtb.h"
+#include "../strategy_dpo_manager.h"
+
+/* Simple strategy that forwards intertests to all next hops */
+/* It does not require to exend the hicn_dpo */
+void hicn_receive_data_rp (index_t dpo_idx, int nh_idx);
+void hicn_add_interest_rp (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
+void hicn_on_interest_timeout_rp (index_t dpo_idx);
+u32 hicn_select_next_hop_rp (index_t dpo_idx, int *nh_idx,
+ hicn_face_id_t *outfaces, uint32_t *len);
+u8 *hicn_strategy_format_trace_rp (u8 *s, hicn_strategy_trace_t *t);
+u8 *hicn_strategy_format_rp (u8 *s, va_list *ap);
+
+static hicn_strategy_vft_t hicn_strategy_rp_vft = {
+ .hicn_receive_data = &hicn_receive_data_rp,
+ .hicn_add_interest = &hicn_add_interest_rp,
+ .hicn_on_interest_timeout = &hicn_on_interest_timeout_rp,
+ .hicn_select_next_hop = &hicn_select_next_hop_rp,
+ .hicn_format_strategy_trace = &hicn_strategy_format_trace_rp,
+ .hicn_format_strategy = &hicn_strategy_format_rp
+};
+
+/*
+ * Return the vft of the strategy.
+ */
+hicn_strategy_vft_t *
+hicn_rp_strategy_get_vft (void)
+{
+ return &hicn_strategy_rp_vft;
+}
+
+/* DPO should be give in input as it containes all the information to calculate
+ * the next hops*/
+u32
+hicn_select_next_hop_rp (index_t dpo_idx, int *nh_idx,
+ hicn_face_id_t *outfaces, uint32_t *len)
+{
+ hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
+
+ if (dpo_ctx == NULL || dpo_ctx->entry_count == 0)
+ {
+ *len = 0;
+ return HICN_ERROR_STRATEGY_NOT_FOUND;
+ }
+
+ int i = 0;
+ while (i < MAX_OUT_FACES && i < dpo_ctx->entry_count)
+ {
+ outfaces[i] = dpo_ctx->next_hops[i];
+ i++;
+ }
+ *len = i;
+
+ return HICN_ERROR_NONE;
+}
+
+void
+hicn_add_interest_rp (index_t dpo_ctx_idx, hicn_hash_entry_t *hash_entry)
+{
+ /* Nothing to do */
+}
+
+void
+hicn_on_interest_timeout_rp (index_t dpo_idx)
+{
+ /* Nothing to do in the rp strategy when we receive an interest */
+}
+
+void
+hicn_receive_data_rp (index_t dpo_idx, int nh_idx)
+{
+ /* nothing to do */
+}
+
+/* packet trace format function */
+u8 *
+hicn_strategy_format_trace_rp (u8 *s, hicn_strategy_trace_t *t)
+{
+ s = format (s, "Strategy_rp: pkt: %d, sw_if_index %d, next index %d",
+ (int) t->pkt_type, t->sw_if_index, t->next_index);
+ return (s);
+}
+
+u8 *
+hicn_strategy_format_rp (u8 *s, va_list *ap)
+{
+
+ u32 indent = va_arg (*ap, u32);
+ s = format (s, "Replication: send to all the next hops \n", indent);
+ return (s);
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-light/src/hicn/config/controlRemovePolicy.h b/hicn-plugin/src/strategies/strategy_rp.h
index ebe098985..c308497cc 100644
--- a/hicn-light/src/hicn/config/controlRemovePolicy.h
+++ b/hicn-plugin/src/strategies/strategy_rp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,24 +13,29 @@
* limitations under the License.
*/
+#ifndef __HICN_STRATEGY_RP_H__
+#define __HICN_STRATEGY_RP_H__
+
+#include "../strategy.h"
+
/**
- * @file control_RemovePolicy.h
- * @brief Remove a policy from the FIB
- *
- * Implements the "remove policy" and "help remove policy" nodes of the command
- * tree
+ * @file strategy_rp.h
*
+ * This file implements the replication strategy. In this
+ * strategy all the next hops are used to send an intertest.
*/
-#ifndef Control_RemovePolicy_h
-#define Control_RemovePolicy_h
-
-#ifdef WITH_POLICY
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRemovePolicy_Create(ControlState *state);
-CommandOps *controlRemovePolicy_HelpCreate(ControlState *state);
+/**
+ * @brief Return the vft for the Replication strategy
+ */
+hicn_strategy_vft_t *hicn_rp_strategy_get_vft (void);
-#endif /* WITH_POLICY */
+#endif // __HICN_STRATEGY_RP_H__
-#endif // Control_RemovePolicy_h
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/strategies/strategy_rr.c b/hicn-plugin/src/strategies/strategy_rr.c
index 9995191b7..192cf5fc3 100644
--- a/hicn-plugin/src/strategies/strategy_rr.c
+++ b/hicn-plugin/src/strategies/strategy_rr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -26,7 +26,7 @@ void hicn_receive_data_rr (index_t dpo_idx, int nh_idx);
void hicn_add_interest_rr (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
void hicn_on_interest_timeout_rr (index_t dpo_idx);
u32 hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outface);
+ hicn_face_id_t *outfaces, uint32_t *len);
u8 *hicn_strategy_format_trace_rr (u8 *s, hicn_strategy_trace_t *t);
u8 *hicn_strategy_format_rr (u8 *s, va_list *ap);
@@ -51,17 +51,22 @@ hicn_rr_strategy_get_vft (void)
/* DPO should be give in input as it containes all the information to calculate
* the next hops*/
u32
-hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, hicn_face_id_t *outface)
+hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx,
+ hicn_face_id_t *outfaces, uint32_t *len)
{
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx);
if (dpo_ctx == NULL)
- return HICN_ERROR_STRATEGY_NOT_FOUND;
+ {
+ *len = 0;
+ return HICN_ERROR_STRATEGY_NOT_FOUND;
+ }
hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx =
(hicn_strategy_rr_ctx_t *) dpo_ctx->data;
- *outface = dpo_ctx->next_hops[hicn_strategy_rr_ctx->current_nhop];
+ outfaces[0] = dpo_ctx->next_hops[hicn_strategy_rr_ctx->current_nhop];
+ *len = 1;
hicn_strategy_rr_ctx->current_nhop =
(hicn_strategy_rr_ctx->current_nhop + 1) % dpo_ctx->entry_count;
@@ -77,7 +82,6 @@ hicn_add_interest_rr (index_t dpo_ctx_idx, hicn_hash_entry_t *hash_entry)
.dpoi_proto = 0,
.dpoi_next_node = 0,
.dpoi_index = dpo_ctx_idx };
- hicn_strategy_dpo_ctx_lock (&hicn_dpo_id);
hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id);
}
diff --git a/hicn-plugin/src/strategies/strategy_rr.h b/hicn-plugin/src/strategies/strategy_rr.h
index 4dfe76b43..fb7520180 100644
--- a/hicn-plugin/src/strategies/strategy_rr.h
+++ b/hicn-plugin/src/strategies/strategy_rr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/strategy.h b/hicn-plugin/src/strategy.h
index 28af55f01..efc6e464e 100644
--- a/hicn-plugin/src/strategy.h
+++ b/hicn-plugin/src/strategy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -53,7 +53,7 @@ typedef struct hicn_strategy_vft_s
void (*hicn_on_interest_timeout) (index_t dpo_idx);
void (*hicn_add_interest) (index_t dpo_idx, hicn_hash_entry_t *pit_entry);
u32 (*hicn_select_next_hop) (index_t dpo_idx, int *nh_idx,
- hicn_face_id_t *outface);
+ hicn_face_id_t *outfaces, uint32_t *len);
u8 *(*hicn_format_strategy_trace) (u8 *, hicn_strategy_trace_t *);
u8 *(*hicn_format_strategy) (u8 *s, va_list *ap);
/**< Format an hICN dpo*/
@@ -86,6 +86,8 @@ const static char *const *const hicn_nodes_strategy[DPO_PROTO_NUM] = {
[DPO_PROTO_IP4] = hicn_ip4_nodes,
};
+const static uint32_t MAX_OUT_FACES = 8;
+
extern vlib_node_registration_t hicn_strategy_node;
#endif /* //__HICN_STRATEGY__ */
diff --git a/hicn-plugin/src/strategy_dpo_ctx.c b/hicn-plugin/src/strategy_dpo_ctx.c
index edfe75aa8..2279ecc75 100644
--- a/hicn-plugin/src/strategy_dpo_ctx.c
+++ b/hicn-plugin/src/strategy_dpo_ctx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -21,7 +21,7 @@ hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool;
void
hicn_strategy_init_dpo_ctx_pool ()
{
- pool_init_fixed (hicn_strategy_dpo_ctx_pool, 256);
+ // pool_init_fixed (hicn_strategy_dpo_ctx_pool, 256);
}
void
@@ -29,9 +29,16 @@ hicn_strategy_dpo_ctx_lock (dpo_id_t *dpo)
{
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo->dpoi_index);
- if (dpo_ctx != NULL)
+ if (PREDICT_TRUE (dpo_ctx != NULL))
{
dpo_ctx->locks++;
+ HICN_DEBUG ("Locking DPO CTX with index %d. Lock now: %d",
+ dpo->dpoi_index, dpo_ctx->locks);
+ }
+ else
+ {
+ HICN_ERROR ("Trying to lock NULL spo_ctx with index %d",
+ dpo->dpoi_index);
}
}
@@ -41,15 +48,23 @@ hicn_strategy_dpo_ctx_unlock (dpo_id_t *dpo)
hicn_dpo_ctx_t *hicn_strategy_dpo_ctx =
(hicn_dpo_ctx_t *) hicn_strategy_dpo_ctx_get (dpo->dpoi_index);
- if (hicn_strategy_dpo_ctx != NULL)
+ if (PREDICT_TRUE (hicn_strategy_dpo_ctx != NULL))
{
hicn_strategy_dpo_ctx->locks--;
+ HICN_DEBUG ("Unlcking DPO CTX with index %d. Lock now: %d",
+ dpo->dpoi_index, hicn_strategy_dpo_ctx->locks);
if (0 == hicn_strategy_dpo_ctx->locks)
{
+ HICN_DEBUG ("Releasing DPO CTX %d", dpo->dpoi_index);
pool_put (hicn_strategy_dpo_ctx_pool, hicn_strategy_dpo_ctx);
}
}
+ else
+ {
+ HICN_ERROR ("Trying to unlock NULL spo_ctx with index %d",
+ dpo->dpoi_index);
+ }
}
u8 *
@@ -90,8 +105,11 @@ hicn_strategy_dpo_ctx_get (index_t index)
hicn_dpo_ctx_t *
hicn_strategy_dpo_ctx_alloc ()
{
+ HICN_DEBUG ("Allocating new DPO CTX");
hicn_dpo_ctx_t *dpo_ctx;
- pool_get (hicn_strategy_dpo_ctx_pool, dpo_ctx);
+ pool_get_aligned (hicn_strategy_dpo_ctx_pool, dpo_ctx,
+ 2 * CLIB_CACHE_LINE_BYTES);
+ dpo_ctx->locks = 0;
return dpo_ctx;
}
diff --git a/hicn-plugin/src/strategy_dpo_ctx.h b/hicn-plugin/src/strategy_dpo_ctx.h
index fe63a4258..cb8ca4051 100644
--- a/hicn-plugin/src/strategy_dpo_ctx.h
+++ b/hicn-plugin/src/strategy_dpo_ctx.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -108,7 +108,7 @@ init_dpo_ctx (hicn_dpo_ctx_t *dpo_ctx, const hicn_face_id_t *next_hop,
dpo_ctx->seq = INIT_SEQ;
dpo_ctx->dpo_type = dpo_type;
- dpo_ctx->proto = proto;
+ dpo_ctx->proto = (fib_protocol_t) proto;
for (int i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX && i < nh_len; i++)
{
diff --git a/hicn-plugin/src/strategy_dpo_manager.c b/hicn-plugin/src/strategy_dpo_manager.c
index 3c441ccac..6c5767bc9 100644
--- a/hicn-plugin/src/strategy_dpo_manager.c
+++ b/hicn-plugin/src/strategy_dpo_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,6 +19,7 @@
#include "strategy_dpo_ctx.h"
#include "strategies/dpo_mw.h"
#include "strategies/dpo_rr.h"
+#include "strategies/dpo_rp.h"
#include "strategy.h"
#include "faces/face.h"
@@ -98,11 +99,13 @@ hicn_dpos_init (void)
hicn_strategy_init_dpo_ctx_pool ();
hicn_dpo_strategy_mw_module_init ();
hicn_dpo_strategy_rr_module_init ();
+ hicn_dpo_strategy_rp_module_init ();
default_dpo.hicn_dpo_is_type = &hicn_dpo_is_type_strategy_mw;
default_dpo.hicn_dpo_get_type = &hicn_dpo_strategy_mw_get_type;
default_dpo.hicn_dpo_module_init = &hicn_dpo_strategy_mw_module_init;
default_dpo.hicn_dpo_create = &hicn_strategy_mw_ctx_create;
+ default_dpo.hicn_dpo_update_type = &hicn_strategy_mw_update_ctx_type;
default_dpo.hicn_dpo_add_update_nh = &hicn_strategy_mw_ctx_add_nh;
default_dpo.hicn_dpo_del_nh = &hicn_strategy_mw_ctx_del_nh;
default_dpo.hicn_dpo_format = &hicn_strategy_mw_format_ctx;
@@ -128,12 +131,12 @@ format_hicn_strategy_list (u8 *s, int n, ...)
return (s);
}
-u8
+int
hicn_dpo_strategy_id_is_valid (int strategy_id)
{
return vec_len (strategies_id) > strategy_id ?
- HICN_ERROR_NONE :
- HICN_ERROR_DPO_MGR_ID_NOT_VALID;
+ HICN_ERROR_NONE :
+ HICN_ERROR_DPO_MGR_ID_NOT_VALID;
}
int
diff --git a/hicn-plugin/src/strategy_dpo_manager.h b/hicn-plugin/src/strategy_dpo_manager.h
index 7a2ce3fee..b8a0c9e92 100644
--- a/hicn-plugin/src/strategy_dpo_manager.h
+++ b/hicn-plugin/src/strategy_dpo_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -53,6 +53,8 @@ typedef struct hicn_dpo_vft_s
void (*hicn_dpo_create) (
fib_protocol_t proto, const hicn_face_id_t *nh, int nh_len,
index_t *dpo_idx); /**< Create the context of the hICN dpo */
+ void (*hicn_dpo_update_type) (
+ hicn_dpo_ctx_t *hicn_strategy_ctx); /**change dpo type */
int (*hicn_dpo_add_update_nh) (
hicn_face_id_t nh,
index_t dpo_idx); /**< Add a next hop to the hICN dpo context */
@@ -171,7 +173,7 @@ u8 *format_hicn_strategy_list (u8 *s, int n, ...);
*
* @result HICN_ERROR_NONE is the id is valid, otherwise EINVAL
*/
-u8 hicn_dpo_strategy_id_is_valid (int strategy_id);
+int hicn_dpo_strategy_id_is_valid (int strategy_id);
/**
* @brief Return the number of available strategies. This number can be used to
diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c
index ec57d76e2..66d9c2dbb 100644
--- a/hicn-plugin/src/strategy_node.c
+++ b/hicn-plugin/src/strategy_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -25,6 +25,7 @@
#include "mgmt.h"
#include "pcs.h"
#include "state.h"
+#include "data_fwd.h"
#include "strategies/strategy_mw.h"
/* Registration struct for a graph node */
@@ -65,7 +66,8 @@ 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)
+ u8 isv6, vl_api_hicn_api_node_stats_get_reply_t *stats,
+ u8 is_replication)
{
int ret;
hicn_hash_node_t *nodep;
@@ -80,6 +82,17 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
u8 bucket_is_overflow = 0;
u32 bucket_id = ~0;
+ if (is_replication)
+ {
+ // an entry for this message alredy exists in the PIT so just send it
+ *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 :
+ HICN_STRATEGY_NEXT_INTEREST_FACE4;
+
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface;
+ stats->pkts_interest_count++;
+ return HICN_ERROR_NONE;
+ }
+
/* Create PIT node and init PIT entry */
nodep = hicn_hashtb_alloc_node (rt->pitcs->pcs_table);
if (PREDICT_FALSE (nodep == NULL))
@@ -101,6 +114,7 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
{
imsg_lifetime = sm->pit_lifetime_max_ms;
}
+
pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, imsg_lifetime);
/* Set up the hash node and insert it */
@@ -121,7 +135,7 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
hicn_face_db_add_face (hicnb0->face_id, &(pitp->u.pit.faces));
*next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 :
- HICN_STRATEGY_NEXT_INTEREST_FACE4;
+ HICN_STRATEGY_NEXT_INTEREST_FACE4;
vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface;
stats->pkts_interest_count++;
@@ -137,9 +151,15 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
bucket_id, bucket_is_overflow);
// We need to take a lock as the lock is not taken on the hash
// entry because it is a CS entry (hash_insert function).
- hash_entry->locks++;
- *next = is_cs0 ? HICN_STRATEGY_NEXT_INTEREST_HITCS :
- HICN_STRATEGY_NEXT_INTEREST_HITPIT;
+ if (is_cs0)
+ {
+ hash_entry->locks++;
+ *next = HICN_STRATEGY_NEXT_INTEREST_HITCS;
+ }
+ else
+ {
+ *next = HICN_STRATEGY_NEXT_INTEREST_HITPIT;
+ }
}
else
{
@@ -189,7 +209,8 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_header_t *hicn0;
vlib_buffer_t *b0;
u32 bi0;
- hicn_face_id_t outface;
+ hicn_face_id_t outfaces[MAX_OUT_FACES];
+ u32 outfaces_len;
int nh_idx;
u32 next0 = next_index;
int ret;
@@ -207,15 +228,23 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
bi0 = from[0];
from += 1;
n_left_from -= 1;
- to_next[0] = bi0;
- to_next += 1;
- n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
next0 = HICN_STRATEGY_NEXT_ERROR_DROP;
hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (
vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
+
+ if (PREDICT_FALSE (!dpo_ctx))
+ {
+ to_next[0] = bi0;
+ to_next += 1;
+ n_left_to_next -= 1;
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+ continue;
+ }
+
const hicn_strategy_vft_t *strategy =
hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type);
@@ -231,7 +260,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
HICN_IS_NAMEHASH_CACHED (b0) &&
strategy->hicn_select_next_hop (
vnet_buffer (b0)->ip.adj_index[VLIB_TX], &nh_idx,
- &outface) == HICN_ERROR_NONE))
+ outfaces, &outfaces_len) == HICN_ERROR_NONE))
{
/*
* No need to check if parsing was successful
@@ -239,32 +268,72 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
* node
*/
nameptr = (u8 *) (&name);
- hicn_new_interest (rt, b0, &next0, tnow, nameptr, namelen,
- outface, nh_idx,
- vnet_buffer (b0)->ip.adj_index[VLIB_TX],
- strategy, dpo_ctx->dpo_type, isv6, &stats);
+ u32 clones[outfaces_len];
+ if (outfaces_len > 1)
+ {
+ int ret = vlib_buffer_clone (vm, bi0, clones, outfaces_len,
+ CLIB_CACHE_LINE_BYTES * 2);
+ ASSERT (ret == outfaces_len);
+ }
+ else
+ {
+ clones[0] = bi0;
+ }
+
+ for (u32 nh = 0; nh < outfaces_len; nh++)
+ {
+ vlib_buffer_t *local_b0 = vlib_get_buffer (vm, clones[nh]);
+
+ to_next[0] = clones[nh];
+ to_next += 1;
+ n_left_to_next -= 1;
+
+ if (nh == 0)
+ {
+ // send first interest
+ hicn_new_interest (
+ 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);
+ }
+ else
+ {
+ // send duplicated interests, avoid aggregation/drop
+ hicn_new_interest (
+ 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);
+ }
+
+ /* Maybe trace */
+ if (PREDICT_FALSE (
+ (node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (local_b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicn_strategy_trace_t *t =
+ vlib_add_trace (vm, node, local_b0, sizeof (*t));
+ t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->sw_if_index =
+ vnet_buffer (local_b0)->sw_if_index[VLIB_RX];
+ t->next_index = next0;
+ t->dpo_type = dpo_ctx->dpo_type;
+ }
+
+ /*
+ * Verify speculative enqueue, maybe switch current
+ * next frame
+ */
+ /*
+ * Fix in case of a wrong speculation. Needed for
+ * cloning the data in the right frame
+ */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next, n_left_to_next,
+ clones[nh], next0);
+ }
}
- /* Maybe trace */
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicn_strategy_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- t->next_index = next0;
- t->dpo_type = dpo_ctx->dpo_type;
- }
- /*
- * Verify speculative enqueue, maybe switch current
- * next frame
- */
- /*
- * Fix in case of a wrong speculation. Needed for
- * cloning the data in the right frame
- */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
diff --git a/hicn-plugin/src/udp_tunnels/udp_decap.h b/hicn-plugin/src/udp_tunnels/udp_decap.h
index 9ddb8a73b..7dc13f272 100644
--- a/hicn-plugin/src/udp_tunnels/udp_decap.h
+++ b/hicn-plugin/src/udp_tunnels/udp_decap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/src/udp_tunnels/udp_decap_node.c b/hicn-plugin/src/udp_tunnels/udp_decap_node.c
index 06eb8da71..2ac1b1ecb 100644
--- a/hicn-plugin/src/udp_tunnels/udp_decap_node.c
+++ b/hicn-plugin/src/udp_tunnels/udp_decap_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * 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:
@@ -223,7 +223,7 @@ udp4_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip4_header_t *) outer_ptr0)->dst_address);
udp0 = (udp_header_t *) (outer_ptr0 + sizeof (ip4_header_t));
next0 = v0 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4 :
- UDP4_DECAP_NEXT_LOOKUP_IP6;
+ UDP4_DECAP_NEXT_LOOKUP_IP6;
ip46_address_set_ip4 (&src1,
&((ip4_header_t *) outer_ptr1)->src_address);
@@ -231,7 +231,7 @@ udp4_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip4_header_t *) outer_ptr1)->dst_address);
udp1 = (udp_header_t *) (outer_ptr1 + sizeof (ip4_header_t));
next1 = v1 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4 :
- UDP4_DECAP_NEXT_LOOKUP_IP6;
+ UDP4_DECAP_NEXT_LOOKUP_IP6;
ip46_address_set_ip4 (&src2,
&((ip4_header_t *) outer_ptr2)->src_address);
@@ -239,7 +239,7 @@ udp4_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip4_header_t *) outer_ptr2)->dst_address);
udp2 = (udp_header_t *) (outer_ptr2 + sizeof (ip4_header_t));
next2 = v2 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4 :
- UDP4_DECAP_NEXT_LOOKUP_IP6;
+ UDP4_DECAP_NEXT_LOOKUP_IP6;
ip46_address_set_ip4 (&src3,
&((ip4_header_t *) outer_ptr3)->src_address);
@@ -247,7 +247,7 @@ udp4_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip4_header_t *) outer_ptr3)->dst_address);
udp3 = (udp_header_t *) (outer_ptr3 + sizeof (ip4_header_t));
next3 = v3 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4 :
- UDP4_DECAP_NEXT_LOOKUP_IP6;
+ UDP4_DECAP_NEXT_LOOKUP_IP6;
hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3;
hicnb0 = hicn_get_buffer (b0);
@@ -257,34 +257,39 @@ udp4_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
/* Udp encap-decap tunnels have dst and src addresses and port
* swapped */
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] =
- udp_tunnel_get (&dst0, &src0, udp0->dst_port, udp0->src_port);
- vnet_buffer (b1)->ip.adj_index[VLIB_RX] =
- udp_tunnel_get (&dst1, &src1, udp1->dst_port, udp1->src_port);
- vnet_buffer (b2)->ip.adj_index[VLIB_RX] =
- udp_tunnel_get (&dst2, &src2, udp2->dst_port, udp2->src_port);
- vnet_buffer (b3)->ip.adj_index[VLIB_RX] =
- udp_tunnel_get (&dst3, &src3, udp3->dst_port, udp3->src_port);
-
- if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
- hicnb0->flags |=
- (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
-
- if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
- hicnb1->flags |=
- (outer_v1 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
-
- if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
- hicnb2->flags |=
- (outer_v2 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
-
- if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
- hicnb3->flags |=
- (outer_v3 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get_create (
+ &dst0, &src0, udp0->dst_port, udp0->src_port);
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get_create (
+ &dst1, &src1, udp1->dst_port, udp1->src_port);
+ vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get_create (
+ &dst2, &src2, udp2->dst_port, udp2->src_port);
+ vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get_create (
+ &dst3, &src3, udp3->dst_port, udp3->src_port);
+
+ ASSERT (vnet_buffer (b0)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID);
+ ASSERT (vnet_buffer (b1)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID);
+ ASSERT (vnet_buffer (b2)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID);
+ ASSERT (vnet_buffer (b3)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID);
+
+ hicnb0->flags =
+ (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ hicnb1->flags =
+ (outer_v1 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ hicnb2->flags =
+ (outer_v2 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ hicnb3->flags =
+ (outer_v3 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
udp_decap_trace_buffer (vm, node, 1, b0);
udp_decap_trace_buffer (vm, node, 1, b1);
@@ -346,17 +351,19 @@ udp4_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip4_header_t *) outer_ptr0)->dst_address);
udp0 = (udp_header_t *) (outer_ptr0 + sizeof (ip4_header_t));
next0 = v0 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4 :
- UDP4_DECAP_NEXT_LOOKUP_IP6;
+ UDP4_DECAP_NEXT_LOOKUP_IP6;
hicn_buffer_t *hicnb0 = hicn_get_buffer (b0);
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] =
- udp_tunnel_get (&dst0, &src0, udp0->dst_port, udp0->src_port);
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get_create (
+ &dst0, &src0, udp0->dst_port, udp0->src_port);
- if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
- hicnb0->flags |=
- (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ ASSERT (vnet_buffer (b0)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID);
+
+ hicnb0->flags |=
+ (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
udp_decap_trace_buffer (vm, node, 1, b0);
@@ -488,7 +495,7 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip6_header_t *) outer_ptr0)->dst_address);
udp0 = (udp_header_t *) (outer_ptr0 + sizeof (ip6_header_t));
next0 = v0 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 :
- UDP6_DECAP_NEXT_LOOKUP_IP6;
+ UDP6_DECAP_NEXT_LOOKUP_IP6;
ip46_address_set_ip6 (&src1,
&((ip6_header_t *) outer_ptr1)->src_address);
@@ -496,7 +503,7 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip6_header_t *) outer_ptr1)->dst_address);
udp1 = (udp_header_t *) (outer_ptr1 + sizeof (ip6_header_t));
next1 = v1 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 :
- UDP6_DECAP_NEXT_LOOKUP_IP6;
+ UDP6_DECAP_NEXT_LOOKUP_IP6;
ip46_address_set_ip6 (&src2,
&((ip6_header_t *) outer_ptr2)->src_address);
@@ -504,7 +511,7 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip6_header_t *) outer_ptr2)->dst_address);
udp2 = (udp_header_t *) (outer_ptr2 + sizeof (ip6_header_t));
next2 = v2 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 :
- UDP6_DECAP_NEXT_LOOKUP_IP6;
+ UDP6_DECAP_NEXT_LOOKUP_IP6;
ip46_address_set_ip6 (&src3,
&((ip6_header_t *) outer_ptr3)->src_address);
@@ -512,7 +519,7 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip6_header_t *) outer_ptr3)->dst_address);
udp3 = (udp_header_t *) (outer_ptr3 + sizeof (ip6_header_t));
next3 = v3 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 :
- UDP6_DECAP_NEXT_LOOKUP_IP6;
+ UDP6_DECAP_NEXT_LOOKUP_IP6;
hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3;
hicnb0 = hicn_get_buffer (b0);
@@ -534,22 +541,22 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
hicnb0->flags |=
(outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
hicnb1->flags |=
(outer_v1 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
hicnb2->flags |=
(outer_v2 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
hicnb3->flags |=
(outer_v3 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
udp_decap_trace_buffer (vm, node, 0, b0);
udp_decap_trace_buffer (vm, node, 0, b1);
@@ -610,7 +617,7 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
&((ip6_header_t *) outer_ptr0)->dst_address);
udp0 = (udp_header_t *) (outer_ptr0 + sizeof (ip6_header_t));
next0 = v0 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 :
- UDP6_DECAP_NEXT_LOOKUP_IP6;
+ UDP6_DECAP_NEXT_LOOKUP_IP6;
hicn_buffer_t *hicnb0 = hicn_get_buffer (b0);
@@ -620,7 +627,7 @@ udp6_decap_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != UDP_TUNNEL_INVALID)
hicnb0->flags |=
(outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL :
- HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+ HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
udp_decap_trace_buffer (vm, node, 0, b0);
diff --git a/hicn-plugin/src/udp_tunnels/udp_tunnel.c b/hicn-plugin/src/udp_tunnels/udp_tunnel.c
index 8ea2cb503..d03d6a74e 100644
--- a/hicn-plugin/src/udp_tunnels/udp_tunnel.c
+++ b/hicn-plugin/src/udp_tunnels/udp_tunnel.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * 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:
@@ -156,6 +156,27 @@ udp_tunnel_get (const ip46_address_t *src_ip, const ip46_address_t *dst_ip,
return ret == 0 ? (u32) value.value : UDP_TUNNEL_INVALID;
}
+u32
+udp_tunnel_get_create (const ip46_address_t *src_ip,
+ const ip46_address_t *dst_ip, u16 src_port,
+ u16 dst_port)
+{
+ u32 ret = udp_tunnel_get (src_ip, dst_ip, src_port, dst_port);
+ if (ret == UDP_TUNNEL_INVALID)
+ {
+ fib_protocol_t proto =
+ ip46_address_is_ip4 (src_ip) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+
+ index_t fib_index = fib_table_find (proto, HICN_FIB_TABLE);
+
+ ret = udp_tunnel_add (
+ proto, fib_index, src_ip, dst_ip, clib_net_to_host_u16 (src_port),
+ clib_net_to_host_u16 (dst_port), UDP_ENCAP_FIXUP_NONE);
+ }
+
+ return ret;
+}
+
void
udp_tunnel_init ()
{
@@ -255,8 +276,8 @@ udp_tunnel_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
int ret = udp_tunnel_del (fproto, fib_index, &src_ip, &dst_ip, src_port,
dst_port, UDP_ENCAP_FIXUP_NONE);
error = (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, "%s\n", get_error_string (ret));
+ 0 :
+ clib_error_return (0, "%s\n", get_error_string (ret));
}
else
{
diff --git a/hicn-plugin/src/udp_tunnels/udp_tunnel.h b/hicn-plugin/src/udp_tunnels/udp_tunnel.h
index 2e57b7857..376adf5fa 100644
--- a/hicn-plugin/src/udp_tunnels/udp_tunnel.h
+++ b/hicn-plugin/src/udp_tunnels/udp_tunnel.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -70,6 +70,19 @@ u32 udp_tunnel_get (const ip46_address_t *src_ip, const ip46_address_t *dst_ip,
u16 src_port, u16 dst_port);
/**
+ * @brief Get udp tunnel UEI. Creates the tunnel if does not exist already.
+ *
+ * @param src_ip source address of the tunnel
+ * @param dst_ip destination address of the tunnel
+ * @param src_port source port
+ * @param src_port destination port
+ * @return id of the udp tunnel/encap
+ */
+u32 udp_tunnel_get_create (const ip46_address_t *src_ip,
+ const ip46_address_t *dst_ip, u16 src_port,
+ u16 dst_port);
+
+/**
* @brief Delete a udp tunnel
*
* @param proto FIB_PROTOCOL_IP4 or FIB_PROTOCOL_IP6
diff --git a/hicn-plugin/src/utils.h b/hicn-plugin/src/utils.h
index 847f2f388..7a3492732 100644
--- a/hicn-plugin/src/utils.h
+++ b/hicn-plugin/src/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/hicn-plugin/vapi/CMakeLists.txt b/hicn-plugin/vapi/CMakeLists.txt
index 6c176b9f3..2005cdaf7 100644
--- a/hicn-plugin/vapi/CMakeLists.txt
+++ b/hicn-plugin/vapi/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,51 +11,102 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-
-set(SAFE_VAPI safe_vapi CACHE INTERNAL "" FORCE)
+##############################################################
+# Libs and Bins names
+##############################################################
+set(SAFE_VAPI safevapi CACHE INTERNAL "" FORCE)
set(SAFE_VAPI_SHARED ${SAFE_VAPI}.shared CACHE INTERNAL "" FORCE)
-set(SAFE_VAPI_STATIC ${SAFE_VAPI}.static CACHE INTERNAL "" FORCE)
+set(SAFE_VAPI_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes CACHE INTERNAL "" FORCE)
+set(SAFE_VAPI_LIBRARIES ${SAFE_VAPI_SHARED} CACHE INTERNAL "" FORCE)
+
+
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(Vpp ${VPP_DEFAULT_VERSION} EXACT REQUIRED)
-# Dependencies
-find_package(Vpp REQUIRED)
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ include(CommonSetup)
+ find_package(HicnPlugin ${CURRENT_VERSION} EXACT REQUIRED)
+else()
+ list(APPEND DEPENDENCIES
+ ${HICNPLUGIN}
+ )
+endif()
+
+##############################################################
+# Sources
+##############################################################
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/include/vapi/vapi_safe.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/includes/vapi/vapi_safe.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vapi_safe.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/vapi_safe.c
)
+
+##############################################################
+# Compiler Options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ ${MARCH_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Libraries to link
+##############################################################
set (LIBRARIES
- ${VPP_LIBRARY_VAPICLIENT})
+ ${VPP_LIBRARY_VAPICLIENT}
+)
+
+##############################################################
+# Include directories
+##############################################################
list (APPEND INCLUDE_DIRS
- ${VPP_INCLUDE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/include)
+ PUBLIC
+ $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
+ $<BUILD_INTERFACE:${HICNPLUGIN_INCLUDE_DIRS}>
+ $<BUILD_INTERFACE:${VPP_INCLUDE_DIR}>
+ $<BUILD_INTERFACE:${SAFE_VAPI_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
-build_library(${SAFE_VAPI}
- SHARED STATIC
- SOURCES ${SOURCE_FILES} ${HEADER_FILES}
- INSTALL_HEADERS ${HEADER_FILES}
- LINK_LIBRARIES ${LIBRARIES}
- COMPONENT ${HICN_PLUGIN}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- HEADER_ROOT_DIR /
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
-set(SAFE_VAPI_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR}/include
- "" CACHE INTERNAL
- "" FORCE
+##############################################################
+# Build library
+##############################################################
+build_library(${SAFE_VAPI}
+ SHARED
+ SOURCES ${SOURCE_FILES} ${HEADER_FILES}
+ INSTALL_HEADERS ${HEADER_FILES}
+ LINK_LIBRARIES PRIVATE ${LIBRARIES}
+ COMPONENT ${HICN_PLUGIN}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ HEADER_ROOT_DIR ""
+ DEFINITIONS PUBLIC ${COMPILER_DEFINITIONS}
+ DEPENDS ${HICNPLUGIN}.shared
+ VERSION ${CURRENT_VERSION}
+ EXPORT_NAME "libsafevapi"
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
-set(SAFE_VAPI_LIBRARIES
- ${SAFE_VAPI_SHARED}
- "" CACHE INTERNAL
- "" FORCE
-)
+##############################################################
+# Create cmake configuration
+##############################################################
+create_cmake_config (
+ "libsafevapi"
+ INCLUDE_DIRS ${SAFE_VAPI_INCLUDE_DIRS}
+ VERSION ${CURRENT_VERSION}
+ COMPONENT ${HICN_PLUGIN}
+ NAMESPACE hicn
+)
diff --git a/hicn-plugin/vapi/include/vapi/vapi_safe.h b/hicn-plugin/vapi/include/vapi/vapi_safe.h
deleted file mode 100644
index df1114cde..000000000
--- a/hicn-plugin/vapi/include/vapi/vapi_safe.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef VAPI_SAFE
-#include <vapi/vapi.h>
-#include <pthread.h>
-
-extern pthread_mutex_t *mutex;
-
-vapi_error_e vapi_connect_safe(vapi_ctx_t * vapi_ctx_ret, int async);
-
-vapi_error_e vapi_disconnect_safe();
-void vapi_lock();
-
-void vapi_unlock();
-
-#define VAPI_SAFE (NAME, res, ...) \
- vapi_lock(); \
- res = ## NAME (__ARGS__); \
- vapi_unlock();
-
-#endif //VAPI_SAFE
diff --git a/hicn-light/src/hicn/config/controlAddPunting.h b/hicn-plugin/vapi/includes/vapi/vapi_safe.h
index 9cab76359..423034730 100644
--- a/hicn-light/src/hicn/config/controlAddPunting.h
+++ b/hicn-plugin/vapi/includes/vapi/vapi_safe.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,10 +13,21 @@
* limitations under the License.
*/
-#ifndef controlAddPunting_h
-#define controlAddPunting_h
+#ifndef __VAPI_SAFE__
+#define __VAPI_SAFE__
+
+#include <vapi/vapi.h>
+#include <pthread.h>
+
+#include <vapi/hicn.api.vapi.h>
+#include <vapi/interface.api.vapi.h>
+#include <vapi/ip.api.vapi.h>
+#include <vapi/memif.api.vapi.h>
+#include <vapi/udp.api.vapi.h>
+
+vapi_error_e vapi_connect_safe (vapi_ctx_t *vapi_ctx_ret, int async);
+vapi_error_e vapi_disconnect_safe ();
+void vapi_lock ();
+void vapi_unlock ();
-#include <hicn/config/controlState.h>
-CommandOps *controlAddPunting_Create(ControlState *state);
-CommandOps *controlAddPunting_HelpCreate(ControlState *state);
#endif
diff --git a/hicn-plugin/vapi/libsafevapi-config.cmake.in b/hicn-plugin/vapi/libsafevapi-config.cmake.in
new file mode 100644
index 000000000..feb278c1f
--- /dev/null
+++ b/hicn-plugin/vapi/libsafevapi-config.cmake.in
@@ -0,0 +1,8 @@
+@PACKAGE_INIT@
+
+set(Libsafevapi_VERSION_MAJOR "@VERSION_MAJOR@")
+set(Libsafevapi_VERSION_MINOR "@VERSION_MINOR@")
+set(Libsafevapi_VERSION_PATCH "@VERSION_PATCH@")
+
+set_and_check(Libsafe_vapi_INCLUDE_DIRS "@PACKAGE_Libsafevapi_INCLUDE_DIRS@")
+include("${CMAKE_CURRENT_LIST_DIR}/libsafevapi-targets.cmake")
diff --git a/hicn-plugin/vapi/src/vapi_safe.c b/hicn-plugin/vapi/src/vapi_safe.c
new file mode 100644
index 000000000..a91793674
--- /dev/null
+++ b/hicn-plugin/vapi/src/vapi_safe.c
@@ -0,0 +1,98 @@
+/*
+ * 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 <vapi/vapi_safe.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define APP_NAME "hicn_plugin"
+#define MAX_OUTSTANDING_REQUESTS 4
+#define RESPONSE_QUEUE_SIZE 2
+
+DEFINE_VAPI_MSG_IDS_HICN_API_JSON
+DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
+DEFINE_VAPI_MSG_IDS_IP_API_JSON
+DEFINE_VAPI_MSG_IDS_UDP_API_JSON
+DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
+
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+vapi_ctx_t g_vapi_ctx_instance = NULL;
+u32 count = 0;
+
+vapi_error_e
+vapi_connect_safe (vapi_ctx_t *vapi_ctx_ret, int async)
+{
+ vapi_error_e rv = VAPI_OK;
+
+ vapi_lock ();
+
+ if (!g_vapi_ctx_instance)
+ {
+ rv = vapi_ctx_alloc (&g_vapi_ctx_instance);
+ if (rv != VAPI_OK)
+ goto err;
+ }
+
+ if (!count)
+ {
+ rv = vapi_connect (g_vapi_ctx_instance, APP_NAME, NULL,
+ MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE,
+ async ? VAPI_MODE_NONBLOCKING : VAPI_MODE_BLOCKING,
+ true);
+
+ if (rv != VAPI_OK)
+ goto err;
+ }
+
+ count++;
+ *vapi_ctx_ret = g_vapi_ctx_instance;
+
+ vapi_unlock ();
+ return rv;
+
+err:
+ vapi_unlock ();
+ return VAPI_ENOMEM;
+}
+
+vapi_error_e
+vapi_disconnect_safe ()
+{
+ vapi_error_e rv = VAPI_OK;
+
+ vapi_lock ();
+ count--;
+ if (count == 0)
+ {
+ rv = vapi_disconnect (g_vapi_ctx_instance);
+ vapi_ctx_free (g_vapi_ctx_instance);
+ g_vapi_ctx_instance = NULL;
+ }
+ vapi_unlock ();
+
+ return rv;
+}
+
+void
+vapi_lock ()
+{
+ pthread_mutex_lock (&mutex);
+}
+
+void
+vapi_unlock ()
+{
+ pthread_mutex_unlock (&mutex);
+}
diff --git a/hicn-plugin/vapi/vapi_safe.c b/hicn-plugin/vapi/vapi_safe.c
deleted file mode 100644
index e9353497f..000000000
--- a/hicn-plugin/vapi/vapi_safe.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <vapi/vapi_safe.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define APP_NAME "hicn_plugin"
-#define MAX_OUTSTANDING_REQUESTS 4
-#define RESPONSE_QUEUE_SIZE 2
-
-pthread_mutex_t *mutex = NULL;
-vapi_ctx_t g_vapi_ctx_instance = NULL;
-u32 count = 0;
-int lock = 0;
-
-vapi_error_e vapi_connect_safe(vapi_ctx_t *vapi_ctx_ret, int async) {
- vapi_error_e rv = VAPI_OK;
-
- while (!__sync_bool_compare_and_swap(&lock, 0, 1));
-
- if (!g_vapi_ctx_instance && !mutex)
- {
- rv = vapi_ctx_alloc(&g_vapi_ctx_instance);
- if (rv != VAPI_OK)
- goto err;
-
- mutex = malloc(sizeof(pthread_mutex_t));
- if (!mutex)
- goto err_mutex_alloc;
-
- if (pthread_mutex_init(mutex, NULL) != 0) {
- printf("Mutex init failed\n");
- goto err_mutex_init;
- }
- }
-
- if (!count)
- {
- rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL,
- MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE,
- async ? VAPI_MODE_NONBLOCKING : VAPI_MODE_BLOCKING, true);
-
- if (rv != VAPI_OK)
- goto err;
-
- count++;
- }
-
- *vapi_ctx_ret = g_vapi_ctx_instance;
-
- while (!__sync_bool_compare_and_swap(&lock, 1, 0));
- return rv;
-
- err_mutex_init:
- free(mutex);
- err_mutex_alloc:
- err:
- while (!__sync_bool_compare_and_swap(&lock, 1, 0));
- return VAPI_ENOMEM;
-}
-
-vapi_error_e vapi_disconnect_safe() {
- pthread_mutex_lock(mutex);
- vapi_error_e rv = VAPI_OK;
- pthread_mutex_unlock(mutex);
- return rv;
-}
-
-void vapi_lock() {
- pthread_mutex_lock(mutex);
-}
-
-void vapi_unlock() {
- pthread_mutex_unlock(mutex);
-}
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 65c1cd4ee..ca845ab48 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,41 +11,50 @@
# 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(libhicn C)
-#include(CTest)
+
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ include(CommonSetup)
endif()
+
+##############################################################
+# Libs and Bins names
+##############################################################
set(LIBHICN hicn CACHE INTERNAL "" FORCE)
+set(LIBHICN_COMPONENT lib${LIBHICN} CACHE INTERNAL "" FORCE)
set(LIBHICN_SHARED ${LIBHICN}.shared CACHE INTERNAL "" FORCE)
set(LIBHICN_STATIC ${LIBHICN}.static CACHE INTERNAL "" FORCE)
-set(HICN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes CACHE INTERNAL "" FORCE)
-
-include (Packaging)
-option(CMAKE_BUILD_TEST "Build unit tests" OFF)
+##############################################################
+# Dependencies
+##############################################################
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
+if(INTERNAL_ENVIRONMENT)
+ include(ImportInternal)
+ ImportInternal()
+ set(INTERNAL_ENVIRONMENT_FOUND True CACHE STRING "Internal dependency found")
endif()
-if (NOT WIN32)
- set(CMAKE_C_FLAGS -Wall)
-else ()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
-endif ()
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
-add_subdirectory(includes)
-add_subdirectory (src)
+add_subdirectory(includes)
+add_subdirectory(src)
diff --git a/lib/cmake/Modules/Packaging.cmake b/lib/cmake/packaging.cmake
index 2ceda1426..5f1691722 100644
--- a/lib/cmake/Modules/Packaging.cmake
+++ b/lib/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -32,11 +32,21 @@ set(lib${LIBHICN}-dev_DESCRIPTION ${${LIBHICN}_DESCRIPTION}
)
set(lib${LIBHICN}-dev_DEB_DEPENDENCIES
- "libhicn (>= stable_version)"
+ "libhicn (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
+
+if (INTERNAL_ENVIRONMENT)
+ include(CheckSafeC)
+ CheckSafeC()
+ set(lib${LIBHICN}-dev_DEB_DEPENDENCIES
+ "${lib${LIBHICN}-dev_DEB_DEPENDENCIES}, ${SAFEC_DEPENDENCY}"
+ CACHE STRING "Dependencies for deb/rpm package."
+ )
+endif()
+
set(lib${LIBHICN}-dev_RPM_DEPENDENCIES
- "libhicn >= stable_version"
+ "libhicn = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt
index 6c2c34b86..821feb2bb 100644
--- a/lib/includes/CMakeLists.txt
+++ b/lib/includes/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,8 +11,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(HICN_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR} ""
+##############################################################
+# Public headers directory
+##############################################################
+set(Libhicn_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
CACHE INTERNAL
"" FORCE
)
@@ -23,12 +26,15 @@ set(LIBHICN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn/common.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/compat.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/error.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/face.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/header.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/mapme.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/name.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/policy.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ops.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/strategy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/validation.h
PARENT_SCOPE
)
@@ -40,19 +46,14 @@ set(LIBHICN_HEADER_FILES_PROTOCOL
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ipv6.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/tcp.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/udp.h
- PARENT_SCOPE
-)
-
-set(LIBHICN_HEADER_FILES_UTIL
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/new.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/array.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ip_address.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/map.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
PARENT_SCOPE
)
-
-set_property(GLOBAL PROPERTY LIBHICN_HEADER_FILES_UTIL_PROPERTY "${LIBHICN_HEADER_FILES_UTIL}")
-
diff --git a/lib/includes/hicn/base.h b/lib/includes/hicn/base.h
index 1061724ce..844814d57 100644
--- a/lib/includes/hicn/base.h
+++ b/lib/includes/hicn/base.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -34,16 +34,17 @@ typedef u32 hicn_faceid_t;
typedef u8 hicn_pathlabel_t;
typedef u32 hicn_lifetime_t;
-#define HICN_MAX_LIFETIME_SCALED 0xFFFF
-#define HICN_MAX_LIFETIME_MULTIPLIER 0x0F /* 4 bits */
-#define HICN_MAX_LIFETIME HICN_MAX_LIFETIME_SCALED << HICN_MAX_LIFETIME_MULTIPLIER
+#define HICN_MAX_LIFETIME_SCALED 0xFFFF
+#define HICN_MAX_LIFETIME_MULTIPLIER 0x0F /* 4 bits */
+#define HICN_MAX_LIFETIME \
+ HICN_MAX_LIFETIME_SCALED << HICN_MAX_LIFETIME_MULTIPLIER
/**
* @brief hICN packet format type
*
- * The hICN type represents the sequence of protocols that we can find in packet
- * headers. They are represented as a quartet of u8 values, correponding to
- * IANA protocol assignment, and read from right to left. This is done to
+ * The hICN type represents the sequence of protocols that we can find in
+ * packet headers. They are represented as a quartet of u8 values, correponding
+ * to IANA protocol assignment, and read from right to left. This is done to
* faciliate decapsulation of packet header by simple shift/mask operations.
*
* For instance, an IPv6/TCP packet will be identified as :
@@ -55,19 +56,19 @@ typedef u32 hicn_lifetime_t;
*/
typedef union
{
- /** protocol layers representation */
+ /** protocol layers representation */
struct
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- u8 l1; /**< First layer */
- u8 l2; /**< Second layer */
- u8 l3; /**< Third layer */
- u8 l4; /**< Fourth layer */
+ u8 l1; /**< First layer */
+ u8 l2; /**< Second layer */
+ u8 l3; /**< Third layer */
+ u8 l4; /**< Fourth layer */
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- u8 l4; /**< Fourth layer */
- u8 l3; /**< Third layer */
- u8 l2; /**< Second layer */
- u8 l1; /**< First layer */
+ u8 l4; /**< Fourth layer */
+ u8 l3; /**< Third layer */
+ u8 l2; /**< Second layer */
+ u8 l1; /**< First layer */
#elif _WIN32 /* Windows is assumed little-endian */
u8 l1;
u8 l2;
@@ -77,46 +78,73 @@ typedef union
#error "Unsupported endianness"
#endif
};
- /** u32 representation */
+ /** u32 representation */
u32 as_u32;
} hicn_type_t;
/* Common protocol layers */
/* Common protocol layers */
#ifndef _WIN32
-#define HICN_TYPE(x,y,z,t) (hicn_type_t) {{ .l1 = x, .l2 = y, .l3 = z, .l4 = t }}
+#define HICN_TYPE(x, y, z, t) \
+ (hicn_type_t) \
+ { \
+ { \
+ .l1 = x, .l2 = y, .l3 = z, .l4 = t \
+ } \
+ }
#else
inline hicn_type_t
-HICN_TYPE(int x, int y, int z, int t)
+HICN_TYPE (int x, int y, int z, int t)
{
- hicn_type_t type;
- type.l1 = x;
- type.l2 = y;
- type.l3 = z;
- type.l4 = t;
- return type;
+ hicn_type_t type;
+ type.l1 = x;
+ type.l2 = y;
+ type.l3 = z;
+ type.l4 = t;
+ return type;
}
#endif
-#define HICN_TYPE_IPV4_TCP HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_ICMP HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_TCP HICN_TYPE(IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_ICMP HICN_TYPE(IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_TCP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_ICMP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_TCP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_ICMP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_NONE HICN_TYPE(IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_TCP \
+ HICN_TYPE (IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_ICMP \
+ HICN_TYPE (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV6_TCP \
+ HICN_TYPE (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV6_ICMP \
+ HICN_TYPE (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_NEW \
+ HICN_TYPE (IPPROTO_ENCAP, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_UDP \
+ HICN_TYPE (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE)
+#define HICN_TYPE_IPV6_UDP \
+ HICN_TYPE (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_TCP_AH \
+ HICN_TYPE (IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_ICMP_AH \
+ HICN_TYPE (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_TYPE_IPV6_TCP_AH \
+ HICN_TYPE (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_TYPE_IPV6_ICMP_AH \
+ HICN_TYPE (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_TYPE_NEW_AH \
+ HICN_TYPE (IPPROTO_ENCAP, IPPROTO_AH, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV6_UDP_AH \
+ HICN_TYPE (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH)
+#define HICN_TYPE_IPV4_UDP_AH \
+ HICN_TYPE (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH)
+#define HICN_TYPE_NONE \
+ HICN_TYPE (IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
/**
* @brief Check if type is none.
* @return 1 if none, 0 otherwise
*/
-always_inline int
-hicn_type_is_none(hicn_type_t type)
+static inline int
+hicn_type_is_none (hicn_type_t type)
{
return (type.l1 == IPPROTO_NONE) && (type.l2 == IPPROTO_NONE) &&
- (type.l3 == IPPROTO_NONE) && (type.l4 == IPPROTO_NONE);
+ (type.l3 == IPPROTO_NONE) && (type.l4 == IPPROTO_NONE);
}
/**
@@ -151,11 +179,12 @@ typedef enum
* @param [in] face_id The face identifier to combine into the path label
* @param [out] new_label Computed pathlabel
*
- * This function updates the current_label based on the new face_id, and returns
+ * This function updates the current_label based on the new face_id, and
+ * returns
*/
-always_inline void
+static inline void
update_pathlabel (hicn_pathlabel_t current_label, hicn_faceid_t face_id,
- hicn_pathlabel_t * new_label)
+ hicn_pathlabel_t *new_label)
{
hicn_pathlabel_t pl_face_id =
(hicn_pathlabel_t) (face_id & HICN_PATH_LABEL_MASK);
diff --git a/lib/includes/hicn/common.h b/lib/includes/hicn/common.h
index 05f8ad95f..b0898ce1f 100644
--- a/lib/includes/hicn/common.h
+++ b/lib/includes/hicn/common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -51,13 +51,17 @@ typedef uint8_t u8;
#ifndef HICN_VPP_PLUGIN
-#define PREDICT_FALSE(x) (x)
-#define PREDICT_TRUE(x) (x)
-#define always_inline static inline
-#define static_always_inline static inline
-#define STRUCT_SIZE_OF(type, member) sizeof(((type *)0)->member)
+#define PREDICT_FALSE(x) (x)
+#define PREDICT_TRUE(x) (x)
+#define STRUCT_SIZE_OF(type, member) sizeof (((type *) 0)->member)
#define ASSERT
+#ifndef NDEBUG
+#define _ASSERT(x) assert (x)
+#else
+#define _ASSERT(x) ((void) (x))
+#endif
+
#define STATIC_ASSERT(x)
/* Architecture-dependent uword size */
@@ -82,13 +86,17 @@ typedef u32 uword;
typedef uword ip_csum_t;
+#else
+
+#include <vppinfra/clib.h>
+
#endif /* ! HICN_VPP_PLUGIN */
/*
- * Windows compilers do not support named initilizers when .h files are included
- * inside C++ files. For readability, we either use the following macro, or
- * duplicate some code, with the intent of preserving those safeguards for
- * non-Windows platforms.
+ * Windows compilers do not support named initilizers when .h files are
+ * included inside C++ files. For readability, we either use the following
+ * macro, or duplicate some code, with the intent of preserving those
+ * safeguards for non-Windows platforms.
*/
#ifndef _WIN32
#define ATTR_INIT(key, value) .key = value
@@ -97,12 +105,12 @@ typedef uword ip_csum_t;
#endif
#ifdef _WIN32
- /* Endianness detection for Windows platforms */
+/* Endianness detection for Windows platforms */
#define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
-#define __ORDER_BIG_ENDIAN__ 0x44434241UL
-#define __BYTE_ORDER__ ('ABCD')
+#define __ORDER_BIG_ENDIAN__ 0x44434241UL
+#define __BYTE_ORDER__ ('ABCD')
- /* Windows compatibility headers */
+/* Windows compatibility headers */
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
@@ -116,10 +124,10 @@ typedef uword ip_csum_t;
#define strdup _strdup
#define __attribute__(A)
-#ifndef IOVEC
+#ifndef IOVEC
#define IOVEC
#define UIO_MAXIOV 16
-#define IOV_MAX UIO_MAXIOV
+#define IOV_MAX UIO_MAXIOV
struct iovec
{
void *iov_base;
@@ -132,66 +140,20 @@ struct iovec
* Portable attribute packed.
*/
#ifndef _WIN32
-#define PACKED( __Declaration__ ) __Declaration__ __attribute__((__packed__))
+#define PACKED(__Declaration__) __Declaration__ __attribute__ ((__packed__))
#else
-#define PACKED( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
+#define PACKED(__Declaration__) \
+ __pragma (pack (push, 1)) __Declaration__ __pragma (pack (pop))
#endif
-
/*
* IP address types
*/
-#ifdef HICN_VPP_PLUGIN
-
-#include <vnet/ip/ip4_packet.h> // ip4_address_t
-#include <vnet/ip/ip6_packet.h> // ip6_address_t
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
-#endif
-
-#include <vnet/ip/ip46_address.h>
-
-#if __GNUC__ >= 9
-#pragma GCC diagnostic pop
-#endif
-
-#else
-
-
#ifndef _WIN32
#include <netinet/in.h>
#endif
-typedef union
-{
- u32 as_u32;
- struct in_addr as_inaddr;
-} ip4_address_t;
-
-typedef union
-{
- u64 as_u64[2];
- u32 as_u32[4];
- u8 as_u8[16];
- struct in6_addr as_in6addr;
-} ip6_address_t;
-
-typedef union
-{
- struct
- {
- u32 pad[3];
- ip4_address_t ip4;
- };
- ip6_address_t ip6;
-} ip46_address_t;
-
-#define ip46_address_is_ip4(ip46) (((ip46)->pad[0] | (ip46)->pad[1] | (ip46)->pad[2]) == 0)
-
-#endif /* ! HICN_VPP_PLUGIN */
-
/**
* @brief Returns the family of an IP address
* @param [in] ip_address - IP address in presentation format
@@ -215,7 +177,7 @@ int get_addr_family (const char *ip_address);
* borrow this code here.
*/
-static_always_inline u16
+static inline u16
ip_csum_fold (ip_csum_t c)
{
/* Reduce to 16 bits. */
@@ -227,10 +189,10 @@ ip_csum_fold (ip_csum_t c)
c = (c & 0xffff) + (c >> 16);
c = (c & 0xffff) + (c >> 16);
- return (u16)c;
+ return (u16) c;
}
-static_always_inline ip_csum_t
+static inline ip_csum_t
ip_csum_with_carry (ip_csum_t sum, ip_csum_t x)
{
ip_csum_t t = sum + x;
@@ -238,7 +200,7 @@ ip_csum_with_carry (ip_csum_t sum, ip_csum_t x)
}
/* Update checksum changing field at even byte offset from x -> 0. */
-static_always_inline ip_csum_t
+static inline ip_csum_t
ip_csum_add_even (ip_csum_t c, ip_csum_t x)
{
ip_csum_t d;
@@ -252,19 +214,19 @@ ip_csum_add_even (ip_csum_t c, ip_csum_t x)
}
/* Update checksum changing field at even byte offset from 0 -> x. */
-static_always_inline ip_csum_t
+static inline ip_csum_t
ip_csum_sub_even (ip_csum_t c, ip_csum_t x)
{
return ip_csum_with_carry (c, x);
}
+#endif /* ! HICN_VPP_PLUGIN */
+
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);
-
-#endif /* ! HICN_VPP_PLUGIN */
+void hicn_packet_dump (const uint8_t *buffer, size_t len);
/**
* @brief Computes buffer checksum
@@ -273,7 +235,7 @@ void hicn_packet_dump (const uint8_t * buffer, size_t len);
* @param [in] init - Checksum initial value
* @return Checksum of specified buffer
*/
-always_inline u16
+static inline u16
csum (const void *addr, size_t size, u16 init)
{
u32 sum = init;
@@ -291,7 +253,7 @@ csum (const void *addr, size_t size, u16 init)
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
- return (u16) ~ sum;
+ return (u16) ~sum;
}
/*
@@ -305,17 +267,24 @@ csum (const void *addr, size_t size, u16 init)
* Query IP version from packet (either 4 or 6)
* (version is located as same offsets in both protocol headers)
*/
-#define HICN_IP_VERSION(packet) ((hicn_header_t *)packet)->v4.ip.version
+#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))
+#define htonll(x) \
+ ((1 == htonl (1)) ? \
+ (x) : \
+ ((uint64_t) htonl ((x) &0xFFFFFFFF) << 32) | htonl ((x) >> 32))
#endif
#ifndef ntohll
-#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
+#define ntohll(x) \
+ ((1 == ntohl (1)) ? \
+ (x) : \
+ ((uint64_t) ntohl ((x) &0xFFFFFFFF) << 32) | ntohl ((x) >> 32))
#endif
#endif /* HICN_COMMON_H */
diff --git a/lib/includes/hicn/compat.h b/lib/includes/hicn/compat.h
index 486c82348..8de3f9d7e 100644
--- a/lib/includes/hicn/compat.h
+++ b/lib/includes/hicn/compat.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -35,14 +35,18 @@
#define HFO_INET 1 << 0
#define HFO_INET6 1 << 1
#define HFO_TCP 1 << 2
-#define HFO_ICMP 1 << 3
-#define HFO_AH 1 << 4
+#define HFO_UDP 1 << 3
+#define HFO_ICMP 1 << 4
+#define HFO_CMPR 1 << 5
+#define HFO_AH 1 << 6
#define _is_ipv4(format) ((format & HFO_INET))
#define _is_ipv6(format) ((format & HFO_INET6) >> 1)
#define _is_tcp(format) ((format & HFO_TCP) >> 2)
-#define _is_icmp(format) ((format & HFO_ICMP) >> 3)
-#define _is_ah(format) ((format & HFO_AH) >> 4)
+#define _is_udp(format) ((format & HFO_UDP) >> 3)
+#define _is_icmp(format) ((format & HFO_ICMP) >> 4)
+#define _is_cmpr(format) ((format & HFO_CMPR) >> 5)
+#define _is_ah(format) ((format & HFO_AH) >> 6)
typedef enum
{
@@ -51,13 +55,32 @@ typedef enum
HF_INET6_TCP = HFO_INET6 | HFO_TCP,
HF_INET_ICMP = HFO_INET | HFO_ICMP,
HF_INET6_ICMP = HFO_INET6 | HFO_ICMP,
+ HF_NEW = HFO_CMPR,
+ HF_INET_UDP = HFO_INET | HFO_UDP | HFO_CMPR,
+ HF_INET6_UDP = HFO_INET6 | HFO_UDP | HFO_CMPR,
HF_INET_TCP_AH = HFO_INET | HFO_TCP | HFO_AH,
HF_INET6_TCP_AH = HFO_INET6 | HFO_TCP | HFO_AH,
HF_INET_ICMP_AH = HFO_INET | HFO_ICMP | HFO_AH,
HF_INET6_ICMP_AH = HFO_INET6 | HFO_ICMP | HFO_AH,
+ HF_NEW_AH = HFO_CMPR | HFO_AH,
+ HF_INET_UDP_AH = HFO_INET | HFO_UDP | HFO_CMPR | HFO_AH,
+ HF_INET6_UDP_AH = HFO_INET6 | HFO_UDP | HFO_CMPR | HFO_AH,
} hicn_format_t;
/**
+ * @brief Add AH header to current format. E.g. if format is IP + TCP, this
+ * will change it to IP = TCP + AH
+ *
+ * @param [in] format - The input format
+ * @return The format with the AH bit set to 1
+ */
+static inline hicn_format_t
+hicn_get_ah_format (hicn_format_t format)
+{
+ return (hicn_format_t) (format | HFO_AH);
+}
+
+/**
* Minimum required header length to determine the type and length of a
* supposed hICN packet. This should be equal to the maximum value over all
* possible hICN packet formats, and less than the minimum possible IP packet
@@ -351,18 +374,49 @@ int hicn_packet_get_hoplimit (const hicn_header_t *packet, u8 *hops);
*/
int hicn_packet_set_hoplimit (hicn_header_t *packet, u8 hops);
+/**
+ * @brief Check if this packet is interest
+ *
+ * @param format - hICN format
+ * @param packet - Packet header
+ * @return hICN error code
+ */
+int hicn_packet_is_interest (hicn_format_t format, const hicn_header_t *h,
+ int *ret);
+
+/**
+ * @brief Mark this packet as interest
+ *
+ * @param format - hICN format
+ * @param packet - Packet header
+ * @return hICN error code
+ */
+int hicn_packet_set_interest (hicn_format_t format, hicn_header_t *packet);
+
+/**
+ * @brief Mark this packet as data
+ *
+ * @param format - hICN format
+ * @param packet - Packet header
+ * @return hICN error code
+ */
+int hicn_packet_set_data (hicn_format_t format, hicn_header_t *h);
+
int hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet,
hicn_header_t *destination, bool copy_ah);
-int hicn_packet_get_lifetime (const hicn_header_t *packet, u32 *lifetime);
-int hicn_packet_set_lifetime (hicn_header_t *packet, u32 lifetime);
+int hicn_packet_get_lifetime (hicn_format_t format,
+ const hicn_header_t *packet, u32 *lifetime);
+int hicn_packet_set_lifetime (hicn_format_t format, hicn_header_t *packet,
+ u32 lifetime);
int hicn_packet_get_reserved_bits (const hicn_header_t *packet,
u8 *reserved_bits);
int hicn_packet_set_reserved_bits (hicn_header_t *packet,
const u8 reserved_bits);
-int hicn_packet_get_payload_type (const hicn_header_t *packet,
+int hicn_packet_get_payload_type (hicn_format_t format,
+ const hicn_header_t *packet,
hicn_payload_type_t *payload_type);
-int hicn_packet_set_payload_type (hicn_header_t *packet,
+int hicn_packet_set_payload_type (hicn_format_t format, hicn_header_t *packet,
const hicn_payload_type_t payload_type);
int hicn_packet_set_syn (hicn_format_t format, hicn_header_t *packet);
@@ -454,10 +508,14 @@ int hicn_data_get_payload_type (const hicn_header_t *data,
int hicn_data_set_payload_type (hicn_header_t *data,
hicn_payload_type_t payload_type);
int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet);
-int hicn_packet_get_signature_gap (hicn_format_t format,
- const hicn_header_t *h, uint8_t *bytes);
-int hicn_packet_set_signature_gap (hicn_format_t format, hicn_header_t *h,
- uint8_t bytes);
+int hicn_data_is_last (hicn_format_t format, hicn_header_t *h, int *is_last);
+int hicn_data_set_last (hicn_format_t format, hicn_header_t *h);
+
+int hicn_packet_get_signature_padding (hicn_format_t format,
+ const hicn_header_t *h, size_t *bytes);
+int hicn_packet_set_signature_padding (hicn_format_t format, hicn_header_t *h,
+ size_t bytes);
+
#endif /* HICN_COMPAT_H */
/*
diff --git a/lib/includes/hicn/error.h b/lib/includes/hicn/error.h
index 9303aeb7e..d769ef693 100644
--- a/lib/includes/hicn/error.h
+++ b/lib/includes/hicn/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,21 +24,22 @@
* Error definitions
******************************************************************************/
-#define foreach_libhicn_error \
-_(NONE, 0, "OK") \
-_(UNSPECIFIED, 128, "Unspecified Error") \
-_(NOT_IMPLEMENTED, 180, "Function not yet implemented") \
-_(NOT_HICN, 202, "Non hICN packet") \
-_(UNKNOWN_ADDRESS, 210, "Unknown address") \
-_(INVALID_PARAMETER, 220, "Invalid parameter") \
-_(INVALID_IP_ADDRESS, 221, "Invalid IP address") \
-_(CORRUPTED_PACKET, 222, "Corrupted packet ") \
-_(REWRITE_CKSUM_REQUIRED, 223, "Incremental csum calculation error: cksum required.") \
-_(UNEXPECTED, 298, "Unexpected error")
+#define foreach_libhicn_error \
+ _ (NONE, 0, "OK") \
+ _ (UNSPECIFIED, 128, "Unspecified Error") \
+ _ (NOT_IMPLEMENTED, 180, "Function not yet implemented") \
+ _ (NOT_HICN, 202, "Non hICN packet") \
+ _ (UNKNOWN_ADDRESS, 210, "Unknown address") \
+ _ (INVALID_PARAMETER, 220, "Invalid parameter") \
+ _ (INVALID_IP_ADDRESS, 221, "Invalid IP address") \
+ _ (CORRUPTED_PACKET, 222, "Corrupted packet ") \
+ _ (REWRITE_CKSUM_REQUIRED, 223, \
+ "Incremental csum calculation error: cksum required.") \
+ _ (UNEXPECTED, 298, "Unexpected error")
typedef enum
{
-#define _(a,b,c) HICN_LIB_ERROR_##a = (-b),
+#define _(a, b, c) HICN_LIB_ERROR_##a = (-b),
foreach_libhicn_error
#undef _
HICN_LIB_N_ERROR,
@@ -46,7 +47,7 @@ typedef enum
extern const char *HICN_LIB_ERROR_STRING[];
-#define hicn_strerror(errno) (char *)(HICN_LIB_ERROR_STRING[-errno])
+#define hicn_strerror(errno) (char *) (HICN_LIB_ERROR_STRING[-errno])
#endif /* HICN_ERROR_H */
diff --git a/lib/includes/hicn/face.h b/lib/includes/hicn/face.h
new file mode 100644
index 000000000..31906afab
--- /dev/null
+++ b/lib/includes/hicn/face.h
@@ -0,0 +1,233 @@
+/*
+ * 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 face.h
+ * \brief Face abstraction
+ */
+#ifndef HICN_FACE_H
+#define HICN_FACE_H
+
+#ifndef SPACES
+#define SPACES(x) x
+#endif
+#ifndef SPACE
+#define SPACE 1
+#endif
+#ifndef NULLTERM
+#define NULLTERM 1
+#endif
+
+#include <hicn/policy.h>
+
+#include <hicn/util/ip_address.h>
+
+/* Netdevice type */
+
+#include <net/if.h> // IFNAMSIZ
+
+#define foreach_netdevice_type \
+ _ (UNDEFINED) \
+ _ (LOOPBACK) \
+ _ (WIRED) \
+ _ (WIFI) \
+ _ (CELLULAR) \
+ _ (VPN) \
+ _ (MEMIF) \
+ _ (N)
+
+#define MAXSZ_NETDEVICE_TYPE_ 9
+#define MAXSZ_NETDEVICE_TYPE MAXSZ_NETDEVICE_TYPE_ + NULLTERM
+
+typedef enum
+{
+#define _(x) NETDEVICE_TYPE_##x,
+ foreach_netdevice_type
+#undef _
+} netdevice_type_t;
+
+extern const char *_netdevice_type_str[];
+#define netdevice_type_str(x) _netdevice_type_str[x]
+
+#define NETDEVICE_INVALID_INDEX ~0
+
+/* Netdevice */
+
+/**
+ * \brief Netdevice type
+ *
+ * NOTE
+ * - This struct cannot be made opaque as it is currently part of face_t
+ * - We recommand using the API as to keep redundant attributes consistent
+ */
+
+typedef struct
+{
+ u32 index;
+ char name[IFNAMSIZ];
+} netdevice_t;
+
+#define NETDEVICE_EMPTY \
+ (netdevice_t) \
+ { \
+ .index = 0, .name = { 0 } \
+ }
+
+netdevice_t *netdevice_create_from_index (u32 index);
+netdevice_t *netdevice_create_from_name (const char *name);
+#define netdevice_initialize_from_index netdevice_set_index
+#define netdevice_initialize_from_name netdevice_set_name
+void netdevice_free (netdevice_t *netdevice);
+int netdevice_get_index (const netdevice_t *netdevice, u32 *index);
+int netdevice_set_index (netdevice_t *netdevice, u32 index);
+int netdevice_get_name (const netdevice_t *netdevice, const char **name);
+int netdevice_set_name (netdevice_t *netdevice, const char *name);
+int netdevice_update_index (netdevice_t *netdevice);
+int netdevice_update_name (netdevice_t *netdevice);
+int netdevice_cmp (const netdevice_t *nd1, const netdevice_t *nd2);
+
+#define NETDEVICE_UNDEFINED_INDEX 0
+
+/* Face state */
+
+#define foreach_face_state \
+ _ (UNDEFINED) \
+ _ (DOWN) \
+ _ (UP) \
+ _ (N)
+
+#define MAXSZ_FACE_STATE_ 9
+#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1
+
+typedef enum
+{
+#define _(x) FACE_STATE_##x,
+ foreach_face_state
+#undef _
+} face_state_t;
+
+extern const char *_face_state_str[];
+
+#define face_state_str(x) _face_state_str[x]
+
+/* Face type */
+
+#define foreach_face_type \
+ _ (UNDEFINED) \
+ _ (HICN) \
+ _ (HICN_LISTENER) \
+ _ (TCP) \
+ _ (TCP_LISTENER) \
+ _ (UDP) \
+ _ (UDP_LISTENER) \
+ _ (N)
+
+#define MAXSZ_FACE_TYPE_ 13
+#define MAXSZ_FACE_TYPE MAXSZ_FACE_TYPE_ + 1
+
+typedef enum
+{
+#define _(x) FACE_TYPE_##x,
+ foreach_face_type
+#undef _
+} face_type_t;
+
+typedef enum
+{
+ FACE_PROTOCOL_HICN,
+ FACE_PROTOCOL_UDP,
+ FACE_PROTOCOL_TCP,
+ FACE_PROTOCOL_UNKNOWN,
+} face_protocol_t;
+
+#define face_type_is_valid(face_type) \
+ (((face_type) >= FACE_TYPE_UNDEFINED) && (face_type < FACE_TYPE_N))
+#define face_type_is_defined(face_type) \
+ (((face_type) > FACE_TYPE_UNDEFINED) && (face_type < FACE_TYPE_N))
+
+extern const char *_face_type_str[];
+#define face_type_str(x) _face_type_str[x]
+
+face_type_t face_type_from_str (const char *str);
+
+#ifdef WITH_POLICY
+#define MAXSZ_FACE_ \
+ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + \
+ MAXSZ_POLICY_TAGS_ + 7
+#else
+#define MAXSZ_FACE_ \
+ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_URL_ + 2 * MAXSZ_FACE_STATE_ + 4
+#endif /* WITH_POLICY */
+#define MAXSZ_FACE MAXSZ_FACE_ + 1
+
+/* Face */
+
+typedef u32 face_id_t;
+
+typedef struct
+{
+ face_type_t type;
+ face_state_t admin_state;
+ face_state_t state;
+#ifdef WITH_POLICY
+ uint32_t priority;
+ policy_tags_t tags; /**< \see policy_tag_t */
+#endif /* WITH_POLICY */
+
+ /*
+ * Depending on the face type, some of the following fields will be unused
+ */
+ netdevice_t netdevice;
+ int family; /* To access family independently of face type */
+ ip_address_t local_addr;
+ ip_address_t remote_addr;
+ u16 local_port;
+ u16 remote_port;
+} face_t;
+
+int face_initialize (face_t *face);
+int face_initialize_udp (face_t *face, const char *interface_name,
+ const ip_address_t *local_addr, u16 local_port,
+ const ip_address_t *remote_addr, u16 remote_port,
+ int family);
+int face_initialize_udp_sa (face_t *face, const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr);
+
+face_t *face_create ();
+face_t *face_create_udp (const char *interface_name,
+ const ip_address_t *local_addr, u16 local_port,
+ const ip_address_t *remote_addr, u16 remote_port,
+ int family);
+face_t *face_create_udp_sa (const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr);
+
+int face_finalize (face_t *face);
+
+void face_free (face_t *face);
+
+typedef int (*face_cmp_t) (const face_t *f1, const face_t *f2);
+
+int face_cmp (const face_t *f1, const face_t *f2);
+
+size_t face_snprintf (char *s, size_t size, const face_t *face);
+
+policy_tags_t face_get_tags (const face_t *face);
+int face_set_tags (face_t *face, policy_tags_t tags);
+
+face_protocol_t get_protocol (face_type_t face_type);
+
+#endif /* HICN_FACE_H */
diff --git a/lib/includes/hicn/header.h b/lib/includes/hicn/header.h
index b21fe5c84..8af9170f8 100644
--- a/lib/includes/hicn/header.h
+++ b/lib/includes/hicn/header.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,8 +20,8 @@
* NOTE: These structures are used as convenient facade for accessing
* the encapsulated headers. They are not written taking compiler padding
* into account, then a sizeof() on these struct could not give the expected
- * result. For accessing the size of the hicn headers use the macros at the end of
- * this file.
+ * result. For accessing the size of the hicn headers use the macros at the end
+ * of this file.
*/
#ifndef HICN_HEADER_H
@@ -36,6 +36,11 @@ typedef struct
union
{
_tcp_header_t tcp;
+ struct
+ {
+ _udp_header_t udp;
+ _new_header_t newhdr;
+ };
_icmp_header_t icmp;
_icmp_wldr_header_t wldr;
};
@@ -53,25 +58,36 @@ typedef struct
};
struct
{
+ _udp_header_t udp;
+ _new_header_t newhdr;
+ _ah_header_t udp_ah;
+ };
+ struct
+ {
_icmp_header_t icmp;
_ah_header_t icmp_ah;
};
};
} hicn_v6ah_hdr_t;
-typedef struct
-{
+// For ipv4 we need to use packed structs as fields may be aligned to 64 bits
+// (So for instance tcp header may start at byte #24 instead of byte 20)
+typedef PACKED (struct {
_ipv4_header_t ip;
union
{
_tcp_header_t tcp;
+ struct
+ {
+ _udp_header_t udp;
+ _new_header_t newhdr;
+ };
_icmp_header_t icmp;
_icmp_wldr_header_t wldr;
};
-} hicn_v4_hdr_t;
+}) hicn_v4_hdr_t;
-typedef struct
-{
+typedef PACKED (struct {
_ipv4_header_t ip;
union
{
@@ -82,11 +98,17 @@ typedef struct
};
struct
{
+ _udp_header_t udp;
+ _new_header_t newhdr;
+ _ah_header_t udp_ah;
+ };
+ struct
+ {
_icmp_header_t icmp;
_ah_header_t icmp_ah;
};
};
-} hicn_v4ah_hdr_t;
+}) hicn_v4ah_hdr_t;
typedef union
{
@@ -99,24 +121,19 @@ typedef union
hicn_protocol_t protocol;
} hicn_header_t;
+#define HICN_V6_TCP_HDRLEN (IPV6_HDRLEN + TCP_HDRLEN)
+#define HICN_V6_ICMP_HDRLEN (IPV6_HDRLEN + ICMP_HDRLEN)
+#define HICN_V6_WLDR_HDRLEN (IPV6_HDRLEN + ICMPWLDR_HDRLEN)
-#define HICN_V6_TCP_HDRLEN (IPV6_HDRLEN + TCP_HDRLEN)
-#define HICN_V6_ICMP_HDRLEN (IPV6_HDRLEN + ICMP_HDRLEN)
-#define HICN_V6_WLDR_HDRLEN (IPV6_HDRLEN + ICMPWLDR_HDRLEN)
-
-#define HICN_V6_TCP_AH_HDRLEN (HICN_V6_TCP_HDRLEN + AH_HDRLEN)
-#define HICN_V6_ICMP_AH_HDRLEN (HICN_V6_ICMP_HDRLEN + AH_HDRLEN)
-
-
-#define HICN_V4_TCP_HDRLEN (IPV4_HDRLEN + TCP_HDRLEN)
-#define HICN_V4_ICMP_HDRLEN (IPV4_HDRLEN + ICMP_HDRLEN)
-#define HICN_V4_WLDR_HDRLEN (IPV4_HDRLEN + ICMPWLDR_HDRLEN)
-
-#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_V6_TCP_AH_HDRLEN (HICN_V6_TCP_HDRLEN + AH_HDRLEN)
+#define HICN_V6_ICMP_AH_HDRLEN (HICN_V6_ICMP_HDRLEN + AH_HDRLEN)
+#define HICN_V4_TCP_HDRLEN (IPV4_HDRLEN + TCP_HDRLEN)
+#define HICN_V4_ICMP_HDRLEN (IPV4_HDRLEN + ICMP_HDRLEN)
+#define HICN_V4_WLDR_HDRLEN (IPV4_HDRLEN + ICMPWLDR_HDRLEN)
+#define HICN_V4_TCP_AH_HDRLEN (HICN_V4_TCP_HDRLEN + AH_HDRLEN)
+#define HICN_V4_ICMP_AH_HDRLEN (HICN_V4_ICMP_HDRLEN + AH_HDRLEN)
#endif /* HICN_HEADER_H */
diff --git a/lib/includes/hicn/hicn.h b/lib/includes/hicn/hicn.h
index 749fd4247..4a5b4dd56 100644
--- a/lib/includes/hicn/hicn.h
+++ b/lib/includes/hicn/hicn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -31,15 +31,17 @@
*
* [1] Hybrid Information-Centric Networking
* L. Muscariello, G. Carofiglio, J. Augé, M. Papalini
- * IETF draft (intarea) @ https://tools.ietf.org/html/draft-muscariello-intarea-hicn
+ * IETF draft (intarea) @
+ * https://tools.ietf.org/html/draft-muscariello-intarea-hicn
*
- * [2] Leveraging ICN in-network control for loss detection and recovery in wireless mobile networks
- * G. Carofiglio, L. Muscariello, M. Papalini, N. Rozhnova, X. Zeng
- * In proc. ICN'2016, Kyoto, JP
+ * [2] Leveraging ICN in-network control for loss detection and recovery in
+ * wireless mobile networks G. Carofiglio, L. Muscariello, M. Papalini, N.
+ * Rozhnova, X. Zeng In proc. ICN'2016, Kyoto, JP
*
* [3] Anchorless mobility through hICN
* J. Augé, G. Carofiglio, L. Muscariello, M. Papalini
- * IETF draft (DMM) @ https://tools.ietf.org/html/draft-auge-dmm-hicn-mobility
+ * IETF draft (DMM) @
+ * https://tools.ietf.org/html/draft-auge-dmm-hicn-mobility
*
*
* [4] MAP-Me : Managing Anchorless Mobility in Content Centric Networking
diff --git a/lib/includes/hicn/mapme.h b/lib/includes/hicn/mapme.h
index 8fae44530..63a5cd77e 100644
--- a/lib/includes/hicn/mapme.h
+++ b/lib/includes/hicn/mapme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,7 +20,7 @@
#ifndef HICN_MAPME_H
#define HICN_MAPME_H
-#include <stdint.h> // u32
+#include <stdint.h> // u32
#include <stdbool.h>
#include "common.h"
@@ -32,16 +32,16 @@
*/
typedef struct
{
- /** MAP-Me enabled flag (default: false) */
+ /** MAP-Me enabled flag (default: false) */
bool enabled;
- /** timescale (T_U parameter) in ms (default: 0 for no notifications) */
+ /** timescale (T_U parameter) in ms (default: 0 for no notifications) */
u32 timescale;
- /** retransmission timer in ms (default: 50) */
+ /** retransmission timer in ms (default: 50) */
u32 retx;
- /**
- * Discovery enabled flag (default: true, should be true if mandatory is
- * notifications are enabled)
- */
+ /**
+ * Discovery enabled flag (default: true, should be true if mandatory is
+ * notifications are enabled)
+ */
bool discovery;
} hicn_mapme_conf_t;
@@ -74,37 +74,45 @@ typedef struct
seq_t seq;
} mapme_params_t;
-
/* MAP-Me API */
-size_t hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params);
-size_t hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params);
-int hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params);
+size_t hicn_mapme_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params);
+size_t hicn_mapme_create_ack (u8 *buf, const mapme_params_t *params);
+int hicn_mapme_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params);
/* Implementation & parsing : ICMP Redirect */
#define HICN_MAPME_ACK_FLAG (0x20 | 0x60)
-#define HICN_MAPME_ICMP_TYPE_IPV4 5
-#define HICN_MAPME_ICMP_TYPE_IPV6 137
-#define HICN_MAPME_ICMP_TYPE_ACK_IPV4 (HICN_MAPME_ICMP_TYPE_IPV4 | HICN_MAPME_ACK_FLAG)
-#define HICN_MAPME_ICMP_TYPE_ACK_IPV6 (HICN_MAPME_ICMP_TYPE_IPV6 | HICN_MAPME_ACK_FLAG)
-#define HICN_MAPME_ICMP_CODE 0 /* Redirect Datagrams for the Network (or subnet) */
-
-#define HICN_MAPME_TYPE_IS_IU(type) ((type == HICN_MAPME_ICMP_TYPE_IPV4) || (type == HICN_MAPME_ICMP_TYPE_IPV6))
-#define HICN_MAPME_TYPE_IS_IU_ACK(type) ((type == HICN_MAPME_ICMP_TYPE_ACK_IPV4) || (type == HICN_MAPME_ICMP_TYPE_ACK_IPV6))
-
-#define HICN_MAPME_IS_IU(type, code) (HICN_MAPME_TYPE_IS_IU(type) && (code == HICN_MAPME_ICMP_CODE))
-#define HICN_MAPME_IS_ACK(type, code) (HICN_MAPME_TYPE_IS_IU_ACK(type) && (code == HICN_MAPME_ICMP_CODE))
-
-#define HICN_IS_MAPME(type, code) (HICN_MAPME_IS_IU(type, code) || HICN_MAPME_IS_ACK(type, code))
+#define HICN_MAPME_ICMP_TYPE_IPV4 5
+#define HICN_MAPME_ICMP_TYPE_IPV6 137
+#define HICN_MAPME_ICMP_TYPE_ACK_IPV4 \
+ (HICN_MAPME_ICMP_TYPE_IPV4 | HICN_MAPME_ACK_FLAG)
+#define HICN_MAPME_ICMP_TYPE_ACK_IPV6 \
+ (HICN_MAPME_ICMP_TYPE_IPV6 | HICN_MAPME_ACK_FLAG)
+#define HICN_MAPME_ICMP_CODE \
+ 0 /* Redirect Datagrams for the Network (or subnet) */
+
+#define HICN_MAPME_TYPE_IS_IU(type) \
+ ((type == HICN_MAPME_ICMP_TYPE_IPV4) || (type == HICN_MAPME_ICMP_TYPE_IPV6))
+#define HICN_MAPME_TYPE_IS_IU_ACK(type) \
+ ((type == HICN_MAPME_ICMP_TYPE_ACK_IPV4) || \
+ (type == HICN_MAPME_ICMP_TYPE_ACK_IPV6))
+
+#define HICN_MAPME_IS_IU(type, code) \
+ (HICN_MAPME_TYPE_IS_IU (type) && (code == HICN_MAPME_ICMP_CODE))
+#define HICN_MAPME_IS_ACK(type, code) \
+ (HICN_MAPME_TYPE_IS_IU_ACK (type) && (code == HICN_MAPME_ICMP_CODE))
+
+#define HICN_IS_MAPME(type, code) \
+ (HICN_MAPME_IS_IU (type, code) || HICN_MAPME_IS_ACK (type, code))
/* Fast check for ACK flag */
#define HICN_MAPME_IS_ACK_FAST(icmp_type) (icmp_type & HICN_MAPME_ACK_FLAG)
/* Default TTL */
-#define HICN_MAPME_TTL 255 // typical for redirect (ref?)
+#define HICN_MAPME_TTL 255 // typical for redirect (ref?)
/*
* The length of the MAPME4 header struct must be 120 bytes.
@@ -143,8 +151,8 @@ typedef union
hicn_mapme_v6_header_t v6;
} hicn_mapme_header_t;
-#define HICN_MAPME_V4_HDRLEN sizeof(hicn_mapme_v4_header_t)
-#define HICN_MAPME_V6_HDRLEN sizeof(hicn_mapme_v6_header_t)
+#define HICN_MAPME_V4_HDRLEN sizeof (hicn_mapme_v4_header_t)
+#define HICN_MAPME_V6_HDRLEN sizeof (hicn_mapme_v6_header_t)
static_assert (EXPECTED_MAPME_V4_HDRLEN == HICN_MAPME_V4_HDRLEN,
"Size of MAPME_V4 struct does not match its expected size.");
diff --git a/lib/includes/hicn/name.h b/lib/includes/hicn/name.h
index d5202068b..f85b0bc3f 100644
--- a/lib/includes/hicn/name.h
+++ b/lib/includes/hicn/name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,7 +26,7 @@
#include <stdbool.h>
#ifndef _WIN32
-#include <netinet/in.h> // struct sockadd
+#include <netinet/in.h> // struct sockadd
#endif
#include <hicn/util/ip_address.h>
#include "common.h"
@@ -35,12 +35,16 @@
* hICN names
******************************************************************************/
-#define TCP_SEQNO_LEN 4 /* bytes */
+#define TCP_SEQNO_LEN 4 /* bytes */
#define HICN_V4_PREFIX_LEN IPV4_ADDR_LEN
#define HICN_V6_PREFIX_LEN IPV6_ADDR_LEN
-#define HICN_SEGMENT_LEN TCP_SEQNO_LEN
-#define HICN_V6_NAME_LEN (HICN_V6_PREFIX_LEN + HICN_SEGMENT_LEN) /* 20 bytes */
-#define HICN_V4_NAME_LEN (HICN_V4_PREFIX_LEN + HICN_SEGMENT_LEN) /* 8 bytes */
+#define HICN_SEGMENT_LEN TCP_SEQNO_LEN
+#define HICN_V6_NAME_LEN \
+ (HICN_V6_PREFIX_LEN + HICN_SEGMENT_LEN) /* 20 bytes \
+ */
+#define HICN_V4_NAME_LEN \
+ (HICN_V4_PREFIX_LEN + HICN_SEGMENT_LEN) /* 8 bytes \
+ */
/* Prefix */
@@ -48,7 +52,7 @@ typedef u32 hicn_name_suffix_t;
typedef struct
{
- ip46_address_t name;
+ ip_address_t name;
u8 len;
} hicn_prefix_t;
@@ -58,85 +62,17 @@ typedef struct
* A name is a prefix + a segment name (suffix)
*/
-typedef union
-{
- struct
- {
- union
- {
- u32 prefix;
- u8 prefix_as_u8[4];
- ip4_address_t prefix_as_ip4;
- };
- hicn_name_suffix_t suffix;
- };
- u8 buffer[HICN_V4_NAME_LEN];
-} hicn_v4_name_t;
-
-typedef union
-{
- struct
- {
- union
- {
- u64 prefix[2];
- u8 prefix_as_u8[16];
- ip6_address_t prefix_as_ip6;
- };
- hicn_name_suffix_t suffix;
- };
- u8 buffer[HICN_V6_NAME_LEN];
-} hicn_v6_name_t;
-
-#ifndef HICN_VPP_PLUGIN
-#define HICN_NAME_COMPONENT_SIZE 2
-
-typedef struct
-{
- struct iovec buffers[HICN_NAME_COMPONENT_SIZE];
-} hicn_iov_name_t;
-
-#define UNSPEC 1 << 0
-#define HNT_CONTIGUOUS 1 << 1
-#define HNT_IOV 1 << 2
-#define HNT_INET 1 << 3
-#define HNT_INET6 1 << 4
-
-typedef enum
-{
- HNT_UNSPEC = UNSPEC,
- HNT_CONTIGUOUS_V4 = HNT_CONTIGUOUS | HNT_INET,
- HNT_CONTIGUOUS_V6 = HNT_CONTIGUOUS | HNT_INET6,
- HNT_IOV_V4 = HNT_IOV | HNT_INET,
- HNT_IOV_V6 = HNT_IOV | HNT_INET6,
-} hicn_name_type_t;
-#endif /* HICN_VPP_PLUGIN */
-
typedef struct
{
-#ifndef HICN_VPP_PLUGIN
- hicn_name_type_t type;
- u8 len;
-#endif /* HICN_VPP_PLUGIN */
- union
- {
- hicn_v4_name_t ip4;
- hicn_v6_name_t ip6;
- ip46_address_t ip46;
-#ifndef HICN_VPP_PLUGIN
- hicn_iov_name_t iov;
- u8 buffer[HICN_V6_NAME_LEN];
-#endif /* HICN_VPP_PLUGIN */
- };
+ ip_address_t prefix;
+ hicn_name_suffix_t suffix;
} hicn_name_t;
-#ifndef HICN_VPP_PLUGIN
-#define _is_unspec(name) ((name->type & UNSPEC))
-#define _is_contiguous(name) ((name->type & HNT_CONTIGUOUS) >> 1)
-#define _is_iov(name) ((name->type & HNT_IOV) >> 2)
-#define _is_inet4(name) ((name->type & HNT_INET) >> 3)
-#define _is_inet6(name) ((name->type & HNT_INET6) >> 4)
-#endif /* HICN_VPP_PLUGIN */
+#define _is_unspec(name) \
+ (((name)->prefix.pad[0] | (name)->prefix.pad[1] | (name)->prefix.pad[2] | \
+ (name)->prefix.v4.as_u32) == 0)
+#define _is_inet4(name) (ip_address_is_v4 (&name->prefix))
+#define _is_inet6(name) (!_is_inet4 (name))
/**
* @brief Create an hICN name from IP address in presentation format
@@ -145,7 +81,7 @@ typedef struct
* @param [out] Resulting hICN name
* @return hICN error code
*/
-int hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name);
+int hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name);
/**
* @brief Create an hICN name from IP address
@@ -154,28 +90,21 @@ int hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name);
* @param [out] Resulting - hICN name
* @return hICN error code
*/
-int hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id,
- hicn_name_t * name);
-
-/**
- * @brief Returns the length of an hICN name
- * @param [in] name - hICN name
- * @return Name length
- */
-u8 hicn_name_get_length (const hicn_name_t * name);
+int hicn_name_create_from_ip_prefix (const ip_prefix_t *prefix, u32 id,
+ hicn_name_t *name);
/**
* @brief Compare two hICN names
* @param [in] name_1 - First name to compare
* @param [in] name_2 - Second name to compare
- * @param [in] consider_segment - Flag indicating whether the segment part has to be
- * considered
+ * @param [in] consider_segment - Flag indicating whether the segment part has
+ * to be considered
* @return An integer less than, equal to, or greater than zero if name_1 is
* found, respectively, to be lest than, to match, or be greater than name_2
* based on numeric order.
*/
-int hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
- bool consider_segment);
+int hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2,
+ bool consider_segment);
/**
* @brief Provides a 32-bit hash of an hICN name
@@ -184,7 +113,7 @@ int hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
* @param [in] consider_suffix - Consider the suffix in the hash computation
* @return hICN error code
*/
-int hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix);
+int hicn_name_hash (const hicn_name_t *name, u32 *hash, bool consider_suffix);
/**
* @brief Test whether an hICN name is empty
@@ -192,7 +121,7 @@ int hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix);
* @return 0 if the name is empty, any other value otherwise (implementation
* returns 1)
*/
-int hicn_name_empty (hicn_name_t * name);
+int hicn_name_empty (hicn_name_t *name);
/**
* @brief Copy an hICN name
@@ -200,7 +129,7 @@ int hicn_name_empty (hicn_name_t * name);
* @param [in] src - Source name to copy
* @return hICN error code
*/
-int hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src);
+int hicn_name_copy (hicn_name_t *dst, const hicn_name_t *src);
/**
* @brief Copy an hICN name to a buffer
@@ -209,8 +138,7 @@ int hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src);
* @param [in] copy_suffix - Flag indicating whether the suffix has to be
* considered
*/
-int hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
- bool copy_suffix);
+int hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *src);
/**
* @brief Sets the segment part of an hICN name
@@ -218,7 +146,7 @@ int hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
* @param [in] seq_number - Segment identifier
* @return hICN error code
*/
-int hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number);
+int hicn_name_set_seq_number (hicn_name_t *name, u32 seq_number);
/**
* @brief Retrieves the segment part of an hICN name
@@ -226,7 +154,7 @@ int hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number);
* @param [in] seq_number - Segment identifier
* @return hICN error code
*/
-int hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number);
+int hicn_name_get_seq_number (const hicn_name_t *name, u32 *seq_number);
/**
* @brief Convert an hICN name to a socket address
@@ -234,8 +162,8 @@ int hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number);
* @param [out] ip_address - Resulting socket address
* @return hICN error code
*/
-int hicn_name_to_sockaddr_address (const hicn_name_t * name,
- struct sockaddr *ip_address);
+int hicn_name_to_sockaddr_address (const hicn_name_t *name,
+ struct sockaddr *ip_address);
/**
* @brief Convert an hICN name to an IP address
@@ -243,8 +171,7 @@ int hicn_name_to_sockaddr_address (const hicn_name_t * name,
* @param [out] ip_address - Resulting IP address
* @return hICN error code
*/
-int hicn_name_to_ip_prefix (const hicn_name_t * name,
- ip_prefix_t * ip_prefix);
+int hicn_name_to_ip_prefix (const hicn_name_t *name, ip_prefix_t *ip_prefix);
/**
* @brief Convert an hICN name to presentation format
@@ -253,7 +180,7 @@ int hicn_name_to_ip_prefix (const hicn_name_t * name,
* @param [in] len - Number of bytes available in the buffer
* @return hICN error code
*/
-int hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len);
+int hicn_name_ntop (const hicn_name_t *src, char *dst, size_t len);
/**
* @brief Convert an hICN name from presentation format
@@ -261,7 +188,7 @@ int hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len);
* @param [out] dst - Resulting name
* @return hICN error code
*/
-int hicn_name_pton (const char *src, hicn_name_t * dst);
+int hicn_name_pton (const char *src, hicn_name_t *dst);
/**
* @brief Returns the IP address family of an hICN name
@@ -269,7 +196,7 @@ int hicn_name_pton (const char *src, hicn_name_t * dst);
* @param [out] family - Resulting IP address family (AF_INET or AF_INET6)
* @return hICN error code
*/
-int hicn_name_get_family (const hicn_name_t * name, int *family);
+int hicn_name_get_family (const hicn_name_t *name, int *family);
/**
* @brief Creates an hICN prefix from an IP address
@@ -277,8 +204,8 @@ int hicn_name_get_family (const hicn_name_t * name, int *family);
* @param [out] prefix - Resulting prefix
* @return hICN error code
*/
-int hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
- hicn_prefix_t * prefix);
+int hicn_prefix_create_from_ip_prefix (const ip_prefix_t *ip_prefix,
+ hicn_prefix_t *prefix);
#endif /* HICN_NAME_H */
diff --git a/lib/includes/hicn/ops.h b/lib/includes/hicn/ops.h
index e5b1c088c..e9eebc76c 100644
--- a/lib/includes/hicn/ops.h
+++ b/lib/includes/hicn/ops.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,6 +23,7 @@
#include <stdlib.h>
+#include "common.h"
#include "error.h"
#include "header.h"
#include "name.h"
@@ -52,7 +53,7 @@ typedef struct hicn_ops_s
* @return hICN error code
*/
int (*get_interest_locator) (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address);
+ ip_address_t *ip_address);
/**
* @brief Sets an Interest locator
@@ -62,7 +63,7 @@ typedef struct hicn_ops_s
* @return hICN error code
*/
int (*set_interest_locator) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address);
+ const ip_address_t *ip_address);
/**
* @brief Retrieves an Interest name
@@ -105,6 +106,15 @@ typedef struct hicn_ops_s
const hicn_name_suffix_t *suffix);
/**
+ * @brief Check if packet is an interest
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest packet
+ * @param [out] h - 1 if interest, 0 otherwise
+ * @return hICN error code
+ */
+ int (*is_interest) (hicn_type_t type, const hicn_protocol_t *h, int *ret);
+
+ /**
* @brief Set flag to mark current packet as interest
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the Interest packet
@@ -136,7 +146,7 @@ typedef struct hicn_ops_s
* @return hICN error code
*/
int (*get_data_locator) (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address);
+ ip_address_t *ip_address);
/**
* @brief Sets a Data locator
@@ -146,7 +156,7 @@ typedef struct hicn_ops_s
* @return hICN error code
*/
int (*set_data_locator) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address);
+ const ip_address_t *ip_address);
/**
* @brief Retrieves a Data name
@@ -282,8 +292,8 @@ typedef struct hicn_ops_s
* @return hICN error code
*/
int (*rewrite_interest) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old);
+ const ip_address_t *addr_new,
+ ip_address_t *addr_old);
/**
* @brief Rewrite a Data packet header (locator + pathlabel)
@@ -298,9 +308,8 @@ typedef struct hicn_ops_s
* @return hICN error code
*/
int (*rewrite_data) (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old, const hicn_faceid_t face_id,
- u8 reset_pl);
+ const ip_address_t *addr_new, ip_address_t *addr_old,
+ const hicn_faceid_t face_id, u8 reset_pl);
/**
* @brief Return the packet length
@@ -373,27 +382,27 @@ typedef struct hicn_ops_s
size_t signature_size);
/**
- * @brief Sets an Interest or Data signature gap between maximum size and
+ * @brief Sets an Interest or Data signature padding between maximum size and
* real size
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the Interest or Data packet
* @param [in] signature_size - Signature size to set
* @return hICN error code
*/
- int (*set_signature_gap) (hicn_type_t type, hicn_protocol_t *h,
- uint8_t signature_gap);
+ int (*set_signature_padding) (hicn_type_t type, hicn_protocol_t *h,
+ size_t signature_padding);
/**
- * @brief gets an Interest or Data signature gap between maximum size and
+ * @brief gets an Interest or Data signature padding between maximum size and
* real size
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [in] signature_size - retrieve the gap between maximum size and
+ * @param [in] signature_size - retrieve the padding between maximum size and
* real size
* @return hICN error code
*/
- int (*get_signature_gap) (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *signature_gap);
+ int (*get_signature_padding) (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_padding);
/**
* @brief Gets the signature timestamp
@@ -464,6 +473,44 @@ typedef struct hicn_ops_s
*/
int (*get_signature) (hicn_type_t type, hicn_protocol_t *h,
uint8_t **signature);
+
+ /**
+ * @brief Set payload type of the packet
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] payload_type - The payload type of this packet
+ * @return hICN error code
+ */
+ int (*set_payload_type) (hicn_type_t type, hicn_protocol_t *h,
+ hicn_payload_type_t payload_type);
+
+ /**
+ * @brief Get payload type from the packet
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] payload_type - The payload type of this packet
+ * @return hICN error code
+ */
+ int (*get_payload_type) (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_payload_type_t *payload_type);
+
+ /**
+ * @brief Check if data packet is last one.
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] is_last - 1 if last data, 0 otherwise
+ * @return hICN error code
+ */
+ int (*is_last_data) (hicn_type_t type, const hicn_protocol_t *h,
+ int *is_last);
+
+ /**
+ * @brief Mark data packet as last
+ * @param [in] type - hICN packet type
+ * @param [in, out] h - Buffer holding the Interest or Data packet
+ * @return hICN error code
+ */
+ int (*set_last_data) (hicn_type_t type, hicn_protocol_t *h);
} hicn_ops_t;
#define DECLARE_HICN_OPS(protocol) \
@@ -477,6 +524,7 @@ typedef struct hicn_ops_s
protocol##_get_interest_name_suffix), \
ATTR_INIT (set_interest_name_suffix, \
protocol##_set_interest_name_suffix), \
+ ATTR_INIT (is_interest, protocol##_is_interest), \
ATTR_INIT (mark_packet_as_interest, protocol##_mark_packet_as_interest), \
ATTR_INIT (mark_packet_as_data, protocol##_mark_packet_as_data), \
ATTR_INIT (reset_interest_for_hash, protocol##_reset_interest_for_hash), \
@@ -502,6 +550,8 @@ typedef struct hicn_ops_s
ATTR_INIT (get_header_length, protocol##_get_header_length), \
ATTR_INIT (get_payload_length, protocol##_get_payload_length), \
ATTR_INIT (set_payload_length, protocol##_set_payload_length), \
+ ATTR_INIT (get_payload_type, protocol##_get_payload_type), \
+ ATTR_INIT (set_payload_type, protocol##_set_payload_type), \
ATTR_INIT (get_signature_size, protocol##_get_signature_size), \
ATTR_INIT (get_signature_timestamp, protocol##_get_signature_timestamp), \
ATTR_INIT (set_signature_timestamp, protocol##_set_signature_timestamp), \
@@ -512,9 +562,11 @@ typedef struct hicn_ops_s
ATTR_INIT (get_key_id, protocol##_get_key_id), \
ATTR_INIT (set_key_id, protocol##_set_key_id), \
ATTR_INIT (get_signature, protocol##_get_signature), \
- ATTR_INIT (set_signature_gap, protocol##_set_signature_gap), \
+ ATTR_INIT (set_signature_padding, protocol##_set_signature_padding), \
ATTR_INIT (set_signature_size, protocol##_set_signature_size), \
- ATTR_INIT (get_signature_gap, protocol##_get_signature_gap), \
+ ATTR_INIT (get_signature_padding, protocol##_get_signature_padding), \
+ ATTR_INIT (is_last_data, protocol##_is_last_data), \
+ ATTR_INIT (set_last_data, protocol##_set_last_data), \
}
/**
@@ -529,7 +581,7 @@ extern const hicn_ops_t *const hicn_ops_vft[];
* NOTE : we cannot use a shift operation as IPPROTO_NONE != 0 (and 0 is
* IPv4...)
*/
-always_inline hicn_type_t
+static inline hicn_type_t
TYPE_POP (hicn_type_t type)
{
#ifndef _WIN32
@@ -544,7 +596,7 @@ TYPE_POP (hicn_type_t type)
#endif
}
-always_inline hicn_protocol_t *
+static inline hicn_protocol_t *
PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
{
size_t header_length;
@@ -573,14 +625,14 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
#define DECLARE_get_interest_locator(protocol, error) \
int protocol##_get_interest_locator ( \
- hicn_type_t type, const hicn_protocol_t *h, ip46_address_t *ip_address) \
+ hicn_type_t type, const hicn_protocol_t *h, ip_address_t *ip_address) \
{ \
return HICN_LIB_ERROR_##error; \
}
#define DECLARE_set_interest_locator(protocol, error) \
int protocol##_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, \
- const ip46_address_t *ip_address) \
+ const ip_address_t *ip_address) \
{ \
return HICN_LIB_ERROR_##error; \
}
@@ -613,6 +665,13 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
return HICN_LIB_ERROR_##error; \
}
+#define DECLARE_is_interest(protocol, error) \
+ int protocol##_is_interest (hicn_type_t type, const hicn_protocol_t *h, \
+ int *ret) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
#define DECLARE_mark_packet_as_interest(protocol, error) \
int protocol##_mark_packet_as_interest (hicn_type_t type, \
hicn_protocol_t *h) \
@@ -635,14 +694,14 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
#define DECLARE_get_data_locator(protocol, error) \
int protocol##_get_data_locator ( \
- hicn_type_t type, const hicn_protocol_t *h, ip46_address_t *ip_address) \
+ hicn_type_t type, const hicn_protocol_t *h, ip_address_t *ip_address) \
{ \
return HICN_LIB_ERROR_##error; \
}
#define DECLARE_set_data_locator(protocol, error) \
int protocol##_set_data_locator (hicn_type_t type, hicn_protocol_t *h, \
- const ip46_address_t *ip_address) \
+ const ip_address_t *ip_address) \
{ \
return HICN_LIB_ERROR_##error; \
}
@@ -732,16 +791,16 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
#define DECLARE_rewrite_interest(protocol, error) \
int protocol##_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, \
- const ip46_address_t *addr_new, \
- ip46_address_t *addr_old) \
+ const ip_address_t *addr_new, \
+ ip_address_t *addr_old) \
{ \
return HICN_LIB_ERROR_##error; \
}
#define DECLARE_rewrite_data(protocol, error) \
int protocol##_rewrite_data ( \
- hicn_type_t type, hicn_protocol_t *h, const ip46_address_t *addr_new, \
- ip46_address_t *addr_old, const hicn_faceid_t face_id, u8 reset_pl) \
+ hicn_type_t type, hicn_protocol_t *h, const ip_address_t *addr_new, \
+ ip_address_t *addr_old, const hicn_faceid_t face_id, u8 reset_pl) \
{ \
return HICN_LIB_ERROR_##error; \
}
@@ -781,6 +840,21 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
return HICN_LIB_ERROR_##error; \
}
+#define DECLARE_get_payload_type(protocol, error) \
+ int protocol##_get_payload_type (hicn_type_t type, \
+ const hicn_protocol_t *h, \
+ hicn_payload_type_t *payload_type) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_payload_type(protocol, error) \
+ int protocol##_set_payload_type (hicn_type_t type, hicn_protocol_t *h, \
+ hicn_payload_type_t payload_type) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
#define DECLARE_get_signature_size(protocol, error) \
int protocol##_get_signature_size ( \
hicn_type_t type, const hicn_protocol_t *h, size_t *signature_size) \
@@ -795,16 +869,16 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
return HICN_LIB_ERROR_##error; \
}
-#define DECLARE_set_signature_gap(protocol, error) \
- int protocol##_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, \
- uint8_t signature_size) \
+#define DECLARE_set_signature_padding(protocol, error) \
+ int protocol##_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, \
+ size_t padding) \
{ \
return HICN_LIB_ERROR_##error; \
}
-#define DECLARE_get_signature_gap(protocol, error) \
- int protocol##_get_signature_gap ( \
- hicn_type_t type, const hicn_protocol_t *h, uint8_t *signature_size) \
+#define DECLARE_get_signature_padding(protocol, error) \
+ int protocol##_get_signature_padding ( \
+ hicn_type_t type, const hicn_protocol_t *h, size_t *padding) \
{ \
return HICN_LIB_ERROR_##error; \
}
@@ -860,6 +934,19 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
return HICN_LIB_ERROR_##error; \
}
+#define DECLARE_is_last_data(protocol, error) \
+ int protocol##_is_last_data (hicn_type_t type, const hicn_protocol_t *h, \
+ int *is_last) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_last_data(protocol, error) \
+ int protocol##_set_last_data (hicn_type_t type, hicn_protocol_t *h) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
#endif /* HICN_OPS_H */
/*
diff --git a/lib/includes/hicn/policy.h b/lib/includes/hicn/policy.h
index e29888bd2..f39fa9272 100644
--- a/lib/includes/hicn/policy.h
+++ b/lib/includes/hicn/policy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -30,37 +30,44 @@
/* POLICY TAG */
-#define foreach_policy_tag \
- /* Interface type */ \
- _(WIRED, 'E') \
- _(WIFI, 'W') \
- _(CELLULAR, 'C') \
- /* QoS */ \
- _(BEST_EFFORT, 'b') \
- _(REALTIME, 'r') \
- _(MULTIPATH, 'M') \
- /* Security */ \
- _(TRUSTED, 'T')
-
-typedef enum {
-#define _(x, y) POLICY_TAG_ ## x,
-foreach_policy_tag
+#define foreach_policy_tag \
+ /* Interface type */ \
+ _ (WIRED, 'E') \
+ _ (WIFI, 'W') \
+ _ (CELLULAR, 'C') \
+ /* QoS */ \
+ _ (BEST_EFFORT, 'b') \
+ _ (REALTIME, 'r') \
+ _ (MULTIPATH, 'M') \
+ /* Security */ \
+ _ (TRUSTED, 'T')
+
+typedef enum
+{
+#define _(x, y) POLICY_TAG_##x,
+ foreach_policy_tag
#undef _
POLICY_TAG_N
} policy_tag_t;
+#define IS_VALID_POLICY_TAG(x) (x != POLICY_TAG_N)
+
#define MAXSZ_POLICY_TAG_ 11
-#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
+#define MAXSZ_POLICY_TAG MAXSZ_POLICY_TAG_ + 1
-extern const char * policy_tag_str[];
+extern const char *policy_tag_str[];
extern const char policy_tag_short_str[];
-static inline
-policy_tag_t
-policy_tag_from_str(const char * str)
+static inline policy_tag_t
+policy_tag_from_str (const char *str)
{
-#define _(x, y) if (strcasecmp(str, policy_tag_str[POLICY_TAG_ ## x] ) == 0) { return POLICY_TAG_ ## x; } else
-foreach_policy_tag
+#define _(x, y) \
+ if (strcasecmp (str, policy_tag_str[POLICY_TAG_##x]) == 0) \
+ { \
+ return POLICY_TAG_##x; \
+ } \
+ else
+ foreach_policy_tag
#undef _
return POLICY_TAG_N;
}
@@ -69,182 +76,188 @@ foreach_policy_tag
typedef int policy_tags_t;
-static inline
-void policy_tags_add(policy_tags_t * tags, policy_tag_t tag)
+static inline void
+policy_tags_add (policy_tags_t *tags, policy_tag_t tag)
{
- *tags |= (1 << tag);
+ *tags |= (1 << tag);
}
-static inline
-void policy_tags_remove(policy_tags_t * tags, policy_tag_t tag)
+static inline void
+policy_tags_remove (policy_tags_t *tags, policy_tag_t tag)
{
- *tags &= ~(1 << tag);
+ *tags &= ~(1 << tag);
}
-static inline
-int policy_tags_has(policy_tags_t tags, policy_tag_t tag)
+static inline int
+policy_tags_has (policy_tags_t tags, policy_tag_t tag)
{
- return tags & (1 << tag);
+ return tags & (1 << tag);
}
-static inline
-void policy_tags_union(policy_tags_t * tags, policy_tags_t * tags_to_union)
+static inline void
+policy_tags_union (policy_tags_t *tags, policy_tags_t *tags_to_union)
{
-#define _(x, y) *tags |= policy_tags_has(*tags_to_union, POLICY_TAG_ ## x) ? (1 << POLICY_TAG_ ## x) : 0;
-foreach_policy_tag
+#define _(x, y) \
+ *tags |= policy_tags_has (*tags_to_union, POLICY_TAG_##x) ? \
+ (1 << POLICY_TAG_##x) : \
+ 0;
+ foreach_policy_tag
#undef _
}
#define POLICY_TAGS_EMPTY 0
-static inline
-int
-policy_tags_snprintf(char * s, size_t size, policy_tags_t tags)
+static inline int
+policy_tags_snprintf (char *s, size_t size, policy_tags_t tags)
{
-#define _(x, y) s[POLICY_TAG_ ## x] = policy_tags_has(tags, POLICY_TAG_ ## x) ? y : '.';
-foreach_policy_tag
+#define _(x, y) \
+ s[POLICY_TAG_##x] = policy_tags_has (tags, POLICY_TAG_##x) ? y : '.';
+ foreach_policy_tag
#undef _
s[POLICY_TAG_N] = '\0';
- return POLICY_TAG_N + 1;
+ return POLICY_TAG_N + 1;
}
#define MAXSZ_POLICY_TAGS_ POLICY_TAG_N + 1
-#define MAXSZ_POLICY_TAGS MAXSZ_POLICY_TAGS_ + 1
+#define MAXSZ_POLICY_TAGS MAXSZ_POLICY_TAGS_ + 1
/* POLICY STATE */
/* TODO vs. weight */
-#define foreach_policy_state \
- _(NEUTRAL) \
- _(REQUIRE) \
- _(PREFER) \
- _(AVOID) \
- _(PROHIBIT) \
- _(N)
-
-typedef enum {
-#define _(x) POLICY_STATE_ ## x,
-foreach_policy_state
+#define foreach_policy_state \
+ _ (NEUTRAL) \
+ _ (REQUIRE) \
+ _ (PREFER) \
+ _ (AVOID) \
+ _ (PROHIBIT) \
+ _ (N)
+
+typedef enum
+{
+#define _(x) POLICY_STATE_##x,
+ foreach_policy_state
#undef _
} policy_state_t;
#define MAXSZ_POLICY_STATE_ 8
-#define MAXSZ_POLICY_STATE MAXSZ_POLICY_STATE_ + 1
+#define MAXSZ_POLICY_STATE MAXSZ_POLICY_STATE_ + 1
+
+extern const char *policy_state_str[];
-extern const char * policy_state_str[];
+#define policy_state_str(x) policy_state_str[x]
+policy_state_t policy_state_from_str (const char *str);
/* POLICY TAG STATE */
-typedef struct {
- policy_state_t state;
- uint8_t disabled;
+typedef struct
+{
+ policy_state_t state;
+ uint8_t disabled;
} policy_tag_state_t;
#define MAXSZ_POLICY_TAG_STATE_ 8
-#define MAXSZ_POLICY_TAG_STATE MAXSZ_POLICY_TAG_STATE_ + 1
-
-int policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t * tag_state);
+#define MAXSZ_POLICY_TAG_STATE MAXSZ_POLICY_TAG_STATE_ + 1
+int policy_tag_state_snprintf (char *s, size_t size,
+ const policy_tag_state_t *tag_state);
/* INTERFACE STATS */
-typedef struct {
- float throughput;
- float latency;
- float loss_rate;
+typedef struct
+{
+ float throughput;
+ float latency;
+ float loss_rate;
} interface_stats_t;
-#define INTERFACE_STATS_NONE { \
- .throughput = 0, \
- .latency = 0, \
- .loss_rate = 0, \
-}
-
+#define INTERFACE_STATS_EMPTY \
+ { \
+ .throughput = 0, .latency = 0, .loss_rate = 0, \
+ }
/* POLICY STATS */
-typedef struct {
- interface_stats_t wired;
- interface_stats_t wifi;
- interface_stats_t cellular;
- interface_stats_t all;
+typedef struct
+{
+ interface_stats_t wired;
+ interface_stats_t wifi;
+ interface_stats_t cellular;
+ interface_stats_t all;
} policy_stats_t;
-#define POLICY_STATS_NONE { \
- .wired = INTERFACE_STATS_NONE, \
- .wifi = INTERFACE_STATS_NONE, \
- .cellular = INTERFACE_STATS_NONE, \
- .all = INTERFACE_STATS_NONE, \
-}
+#define POLICY_STATS_EMPTY \
+ (policy_stats_t) \
+ { \
+ .wired = INTERFACE_STATS_EMPTY, .wifi = INTERFACE_STATS_EMPTY, \
+ .cellular = INTERFACE_STATS_EMPTY, .all = INTERFACE_STATS_EMPTY, \
+ }
-typedef struct {
- uint32_t num_packets;
- uint32_t num_bytes;
- uint32_t num_losses;
- uint32_t latency_idle;
+typedef struct
+{
+ uint32_t num_packets;
+ uint32_t num_bytes;
+ uint32_t num_losses;
+ uint32_t latency_idle;
} interface_counters_t;
-#define INTERFACE_COUNTERS_NONE { \
- .num_packets = 0, \
- .num_bytes = 0, \
- .num_losses = 0, \
- .latency_idle = 0, \
-}
+#define INTERFACE_COUNTERS_EMPTY \
+ { \
+ .num_packets = 0, .num_bytes = 0, .num_losses = 0, .latency_idle = 0, \
+ }
-typedef struct {
- interface_counters_t wired;
- interface_counters_t wifi;
- interface_counters_t cellular;
- interface_counters_t all;
- uint64_t last_update;
+typedef struct
+{
+ interface_counters_t wired;
+ interface_counters_t wifi;
+ interface_counters_t cellular;
+ interface_counters_t all;
+ uint64_t last_update;
} policy_counters_t;
-#define POLICY_COUNTERS_NONE (policy_counters_t) { \
- .wired = INTERFACE_COUNTERS_NONE, \
- .wifi = INTERFACE_COUNTERS_NONE, \
- .cellular = INTERFACE_COUNTERS_NONE, \
- .all = INTERFACE_COUNTERS_NONE, \
- .last_update = 0, \
-}
+#define POLICY_COUNTERS_EMPTY \
+ (policy_counters_t) \
+ { \
+ .wired = INTERFACE_COUNTERS_EMPTY, .wifi = INTERFACE_COUNTERS_EMPTY, \
+ .cellular = INTERFACE_COUNTERS_EMPTY, .all = INTERFACE_COUNTERS_EMPTY, \
+ .last_update = 0, \
+ }
/* POLICY */
#define APP_NAME_LEN 128
-typedef struct {
- char app_name[APP_NAME_LEN];
- policy_tag_state_t tags[POLICY_TAG_N];
- policy_stats_t stats;
+typedef struct
+{
+ char app_name[APP_NAME_LEN];
+ policy_tag_state_t tags[POLICY_TAG_N];
+ policy_stats_t stats;
} hicn_policy_t;
-static const hicn_policy_t POLICY_NONE = {
+static const hicn_policy_t POLICY_EMPTY = {
.app_name = { 0 },
.tags = {
-#ifdef __ANDROID__
#define _(x, y) { POLICY_STATE_NEUTRAL, 0 },
-#else
-#define _(x, y) [POLICY_TAG_ ## x] = { POLICY_STATE_NEUTRAL, 0 },
-#endif
foreach_policy_tag
#undef _
},
- .stats = POLICY_STATS_NONE,
+ .stats = POLICY_STATS_EMPTY,
};
-
/* POLICY DESCRIPTION */
#define PFX_STRLEN 4 /* eg. /128 */
-typedef struct {
- int family;
- union {
- char ipv4_prefix[INET_ADDRSTRLEN + PFX_STRLEN];
- char ipv6_prefix[INET6_ADDRSTRLEN + PFX_STRLEN];
- };
- hicn_policy_t policy;
+typedef struct
+{
+ int family;
+ union
+ {
+ char ipv4_prefix[INET_ADDRSTRLEN + PFX_STRLEN];
+ char ipv6_prefix[INET6_ADDRSTRLEN + PFX_STRLEN];
+ };
+ hicn_policy_t policy;
} policy_description_t;
#endif /* HICN_POLICY_H */
diff --git a/lib/includes/hicn/protocol.h b/lib/includes/hicn/protocol.h
index a97cc99cf..fb142e4c3 100644
--- a/lib/includes/hicn/protocol.h
+++ b/lib/includes/hicn/protocol.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -27,9 +27,11 @@
#include "protocol/icmprd.h"
#include "protocol/tcp.h"
#include "protocol/udp.h"
+#include "protocol/new.h"
typedef union
{
+ _new_header_t newhdr;
_ipv4_header_t ipv4;
_ipv6_header_t ipv6;
_tcp_header_t tcp;
diff --git a/lib/includes/hicn/protocol/ah.h b/lib/includes/hicn/protocol/ah.h
index 575da80d7..36fd7d509 100644
--- a/lib/includes/hicn/protocol/ah.h
+++ b/lib/includes/hicn/protocol/ah.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -35,19 +35,19 @@
typedef struct
{
- u8 nh; // (to match with reserved in IPSEC AH)
- u8 payloadlen; // Len of signature/HMAC in 4-bytes words (maximum size)
+ u8 nh; // To match with reserved in IPSEC AH
+ // Length of the signature field. Note that the signature might be smaller
+ // than the field: the actual size is computed from the field size and
+ // signaturePadding.
+ u8 payloadlen;
union
{
u16 reserved;
struct
{
- u8 validationAlgorithm; // As defined in parc_SignerAlgorithm.h
- u8 signatureGap; // used to match IPSEC specification and to
- // have the real size of the signature(without
- // padding). It is the result of Maximum
- // signature size - real size
+ u8 validationAlgorithm;
+ u8 signaturePadding;
};
};
union
diff --git a/lib/includes/hicn/protocol/icmp.h b/lib/includes/hicn/protocol/icmp.h
index 36954bb6d..9315e1e56 100644
--- a/lib/includes/hicn/protocol/icmp.h
+++ b/lib/includes/hicn/protocol/icmp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -34,7 +34,7 @@ typedef struct
u16 csum;
} _icmp_header_t;
-#define ICMP_HDRLEN sizeof(_icmp_header_t)
+#define ICMP_HDRLEN sizeof (_icmp_header_t)
static_assert (EXPECTED_ICMP_HDRLEN == ICMP_HDRLEN,
"Size of ICMP struct does not match its expected size.");
@@ -54,13 +54,13 @@ typedef struct
{
u16 id;
u16 sequence;
- } echo; /* echo datagram */
- u32 gateway; /* gateway address */
+ } echo; /* echo datagram */
+ u32 gateway; /* gateway address */
struct
{
u16 _unused;
u16 mtu;
- } frag; /* path mtu discovery */
+ } frag; /* path mtu discovery */
struct
{
u16 expected_lbl;
@@ -69,7 +69,7 @@ typedef struct
};
} _icmp_wldr_header_t;
-#define ICMPWLDR_HDRLEN sizeof(_icmp_wldr_header_t)
+#define ICMPWLDR_HDRLEN sizeof (_icmp_wldr_header_t)
static_assert (EXPECTED_ICMPWLDR_HDRLEN == ICMPWLDR_HDRLEN,
"Size of ICMPWLDR struct does not match its expected size.");
diff --git a/lib/includes/hicn/protocol/icmprd.h b/lib/includes/hicn/protocol/icmprd.h
index aa1fa01ae..897e7969e 100644
--- a/lib/includes/hicn/protocol/icmprd.h
+++ b/lib/includes/hicn/protocol/icmprd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -38,7 +38,7 @@ typedef struct
u8 data[64];
} _icmprd4_header_t;
-#define ICMPRD4_HDRLEN sizeof(_icmprd4_header_t)
+#define ICMPRD4_HDRLEN sizeof (_icmprd4_header_t)
static_assert (EXPECTED_ICMPRD4_HDRLEN == ICMPRD4_HDRLEN,
"Size of ICMPWLDR struct does not match its expected size.");
@@ -57,7 +57,7 @@ typedef struct
ip6_address_t dst;
} _icmprd_header_t;
-#define ICMPRD_HDRLEN sizeof(_icmprd_header_t)
+#define ICMPRD_HDRLEN sizeof (_icmprd_header_t)
static_assert (EXPECTED_ICMPRD_HDRLEN == ICMPRD_HDRLEN,
"Size of ICMPWLDR struct does not match its expected size.");
diff --git a/lib/includes/hicn/protocol/ipv4.h b/lib/includes/hicn/protocol/ipv4.h
index 8a5b6683b..44e95c1e3 100644
--- a/lib/includes/hicn/protocol/ipv4.h
+++ b/lib/includes/hicn/protocol/ipv4.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,9 +16,10 @@
#ifndef HICN_PROTOCOL_IPV4
#define HICN_PROTOCOL_IPV4
+#include <hicn/util/ip_address.h>
+
#include "../base.h"
#include "../common.h"
-#include "../protocol.h"
/* Headers were adapted from linux' definitions in netinet/ip.h */
@@ -34,11 +35,11 @@ typedef struct
struct
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- u8 ihl:4;
- u8 version:4;
+ u8 ihl : 4;
+ u8 version : 4;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
- u8 version:4;
- u8 ihl:4;
+ u8 version : 4;
+ u8 ihl : 4;
#else
#error "Unsupported endianness"
#endif
@@ -57,9 +58,10 @@ typedef struct
ip4_address_t daddr;
} _ipv4_header_t;
-#define ipv4_header_bytes(ipv4_header) (sizeof(u32) * (ipv4_header->version_ihl & 0xf))
+#define ipv4_header_bytes(ipv4_header) \
+ (sizeof (u32) * (ipv4_header->version_ihl & 0xf))
-#define IPV4_HDRLEN sizeof(_ipv4_header_t)
+#define IPV4_HDRLEN sizeof (_ipv4_header_t)
static_assert (EXPECTED_IPV4_HDRLEN == IPV4_HDRLEN,
"Size of IPV4 struct does not match its expected size.");
@@ -77,22 +79,21 @@ typedef struct
u16 size;
} ipv4_pseudo_header_t;
-#define IPV4_PSHDRLEN sizeof(ipv4_pseudo_header_t)
+#define IPV4_PSHDRLEN sizeof (ipv4_pseudo_header_t)
static_assert (EXPECTED_IPV4_PSHDRLEN == IPV4_PSHDRLEN,
"Size of IPV4_PSHDR struct does not match its expected size.");
/* Default field values */
-#define IPV4_DEFAULT_VERSION 4
-#define IPV4_DEFAULT_IHL 5
-#define IPV4_DEFAULT_TOS 0
-#define IPV4_DEFAULT_PAYLOAD_LENGTH 0
-#define IPV4_DEFAULT_ID 300
-#define IPV4_DEFAULT_FRAG_OFF 0x000
-#define IPV4_DEFAULT_TTL 64
-#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP
-#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0
-#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0
-
+#define IPV4_DEFAULT_VERSION 4
+#define IPV4_DEFAULT_IHL 5
+#define IPV4_DEFAULT_TOS 0
+#define IPV4_DEFAULT_PAYLOAD_LENGTH 0
+#define IPV4_DEFAULT_ID 300
+#define IPV4_DEFAULT_FRAG_OFF 0x000
+#define IPV4_DEFAULT_TTL 64
+#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP
+#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0
+#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0
#endif /* HICN_PROTOCOL_IPV4 */
diff --git a/lib/includes/hicn/protocol/ipv6.h b/lib/includes/hicn/protocol/ipv6.h
index 5a83abcae..86301e7d1 100644
--- a/lib/includes/hicn/protocol/ipv6.h
+++ b/lib/includes/hicn/protocol/ipv6.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,8 @@
#ifndef HICN_PROTOCOL_IPV6_H
#define HICN_PROTOCOL_IPV6_H
+#include <hicn/util/ip_address.h>
+
#include "../common.h"
/*
@@ -25,22 +27,26 @@
typedef struct
{
+#if 0 // TEMPORARY FIX
union
{
struct
{
- u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
- u16 len; /* payload length */
- u8 nxt; /* next header */
- u8 hlim; /* hop limit */
+#endif
+ u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */
+ u16 len; /* payload length */
+ u8 nxt; /* next header */
+ u8 hlim; /* hop limit */
+#if 0
};
u8 vfc; /* 4 bits version, top 4 bits class */
};
- ip6_address_t saddr; /* source address */
- ip6_address_t daddr; /* destination address */
+#endif
+ ip6_address_t saddr; /* source address */
+ ip6_address_t daddr; /* destination address */
} _ipv6_header_t;
-#define IPV6_HDRLEN sizeof(_ipv6_header_t)
+#define IPV6_HDRLEN sizeof (_ipv6_header_t)
static_assert (EXPECTED_IPV6_HDRLEN == IPV6_HDRLEN,
"Size of IPV6 struct does not match its expected size.");
@@ -59,15 +65,15 @@ typedef struct
u8 protocol;
} ipv6_pseudo_header_t;
-#define IPV6_PSHDRLEN sizeof(ipv6_pseudo_header_t)
+#define IPV6_PSHDRLEN sizeof (ipv6_pseudo_header_t)
static_assert (EXPECTED_IPV6_PSHDRLEN == IPV6_PSHDRLEN,
"Size of IPV6_PSHDR struct does not match its expected size.");
/* Default field values */
-#define IPV6_DEFAULT_VERSION 6
-#define IPV6_DEFAULT_TRAFFIC_CLASS 0
-#define IPV6_DEFAULT_FLOW_LABEL 0
-#define IPV6_DEFAULT_PAYLOAD_LENGTH 0
+#define IPV6_DEFAULT_VERSION 6
+#define IPV6_DEFAULT_TRAFFIC_CLASS 0
+#define IPV6_DEFAULT_FLOW_LABEL 0
+#define IPV6_DEFAULT_PAYLOAD_LENGTH 0
#endif
diff --git a/lib/includes/hicn/protocol/new.h b/lib/includes/hicn/protocol/new.h
new file mode 100644
index 000000000..47f7758d2
--- /dev/null
+++ b/lib/includes/hicn/protocol/new.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file protocol/ah.h
+ * @brief AH packet header
+ */
+#ifndef HICN_PROTOCOL_NEW_H
+#define HICN_PROTOCOL_NEW_H
+
+#include "../common.h"
+#include "../name.h"
+
+/*
+ * The length of the new header struct must be 28 bytes.
+ */
+#define EXPECTED_NEW_HDRLEN 32
+
+typedef struct
+{
+ u8 version_reserved;
+ u8 flags;
+ u16 payload_length;
+ u32 lifetime;
+ ip_address_t prefix;
+ u32 suffix;
+ u32 path_label;
+} _new_header_t;
+
+#define NEW_HDRLEN sizeof (_new_header_t)
+static_assert (EXPECTED_NEW_HDRLEN == NEW_HDRLEN,
+ "Size of new_header Struct does not match its expected size.");
+
+/* TCP flags bit 0 first. */
+#define foreach_hicn_new_flag \
+ _ (SIG) /**< Signature header after. */ \
+ _ (MAN) /**< Payload type is manifest. */ \
+ _ (INT) /**< Packet is interest. */ \
+ _ (LST) /**< Last data. */
+
+enum
+{
+#define _(f) HICN_NEW_FLAG_BIT_##f,
+ foreach_hicn_new_flag
+#undef _
+ HICN_NEW_N_FLAG_BITS,
+};
+
+enum
+{
+#define _(f) HICN_NEW_FLAG_##f = 1 << HICN_NEW_FLAG_BIT_##f,
+ foreach_hicn_new_flag
+#undef _
+};
+
+static inline int
+_get_new_header_version (const _new_header_t *new_hdr)
+{
+ return ((new_hdr->version_reserved >> 4) & 0x0F);
+}
+
+static inline void
+_set_new_header_version (_new_header_t *new_hdr)
+{
+ new_hdr->version_reserved = (0x9 << 4) & 0xF0;
+}
+
+#endif /* HICN_PROTOCOL_NEW_H */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/includes/hicn/protocol/tcp.h b/lib/includes/hicn/protocol/tcp.h
index 347682299..1731f0c24 100644
--- a/lib/includes/hicn/protocol/tcp.h
+++ b/lib/includes/hicn/protocol/tcp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -59,55 +59,55 @@ typedef struct
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct
{
- u16 reserved:4;
- u16 doff:4;
- u16 fin:1;
- u16 syn:1;
- u16 rst:1;
- u16 psh:1;
- u16 ack:1;
- u16 urg:1;
- u16 ece:1;
- u16 cwr:1;
+ u16 reserved : 4;
+ u16 doff : 4;
+ u16 fin : 1;
+ u16 syn : 1;
+ u16 rst : 1;
+ u16 psh : 1;
+ u16 ack : 1;
+ u16 urg : 1;
+ u16 ece : 1;
+ u16 cwr : 1;
};
struct
- { /* __ denotes unchanged bitfields */
- u16 timescale:4;
- u16 __doff:4;
- u16 __fin:1;
- u16 __syn:1;
- u16 __rst:1;
- u16 sig:1;
- u16 __ack:1;
- u16 man:1;
- u16 id:1;
- u16 __cwr:1;
+ { /* __ denotes unchanged bitfields */
+ u16 timescale : 4;
+ u16 __doff : 4;
+ u16 __fin : 1;
+ u16 __syn : 1;
+ u16 __rst : 1;
+ u16 sig : 1;
+ u16 __ack : 1;
+ u16 man : 1;
+ u16 id : 1;
+ u16 __cwr : 1;
};
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
struct
{
- u16 doff:4;
- u16 reserved:4;
- u16 cwr:1;
- u16 ece:1;
- u16 urg:1;
- u16 ack:1;
- u16 psh:1;
- u16 rst:1;
- u16 syn:1;
- u16 fin:1;
+ u16 doff : 4;
+ u16 reserved : 4;
+ u16 cwr : 1;
+ u16 ece : 1;
+ u16 urg : 1;
+ u16 ack : 1;
+ u16 psh : 1;
+ u16 rst : 1;
+ u16 syn : 1;
+ u16 fin : 1;
};
struct
{
- u16 __doff:4;
- u16 timescale:4;
- u16 __cwr:1;
- u16 id:1 u16 man:1;
- u16 __ack:1;
- u16 sig:1;
- u16 __rst:1;
- u16 __syn:1;
- u16 __fin:1;
+ u16 __doff : 4;
+ u16 timescale : 4;
+ u16 __cwr : 1;
+ u16 id : 1 u16 man : 1;
+ u16 __ack : 1;
+ u16 sig : 1;
+ u16 __rst : 1;
+ u16 __syn : 1;
+ u16 __fin : 1;
};
#endif
};
@@ -124,20 +124,20 @@ typedef struct
};
} _tcp_header_t;
-#define TCP_HDRLEN sizeof(_tcp_header_t)
+#define TCP_HDRLEN sizeof (_tcp_header_t)
static_assert (EXPECTED_TCP_HDRLEN == TCP_HDRLEN,
"Size of TCP struct does not match its expected size.");
/* TCP flags bit 0 first. */
-#define foreach_tcp_flag \
- _ (FIN) /**< No more data from sender. */ \
- _ (SYN) /**< Synchronize sequence numbers. */ \
- _ (RST) /**< Reset the connection. */ \
- _ (PSH) /**< Push function. */ \
- _ (ACK) /**< Ack field significant. */ \
- _ (URG) /**< Urgent pointer field significant. */ \
- _ (ECE) /**< ECN-echo. Receiver got CE packet */ \
- _ (CWR) /**< Sender reduced congestion window */
+#define foreach_tcp_flag \
+ _ (FIN) /**< No more data from sender. */ \
+ _ (SYN) /**< Synchronize sequence numbers. */ \
+ _ (RST) /**< Reset the connection. */ \
+ _ (PSH) /**< Push function. */ \
+ _ (ACK) /**< Ack field significant. */ \
+ _ (URG) /**< Urgent pointer field significant. */ \
+ _ (ECE) /**< ECN-echo. Receiver got CE packet */ \
+ _ (CWR) /**< Sender reduced congestion window */
enum
{
diff --git a/lib/includes/hicn/protocol/udp.h b/lib/includes/hicn/protocol/udp.h
index 75d1ea98c..0e0dddd2c 100644
--- a/lib/includes/hicn/protocol/udp.h
+++ b/lib/includes/hicn/protocol/udp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -29,7 +29,7 @@ typedef struct
u16 checksum;
} _udp_header_t;
-#define UDP_HDRLEN sizeof(_udp_header_t)
+#define UDP_HDRLEN sizeof (_udp_header_t)
static_assert (EXPECTED_UDP_HDRLEN == UDP_HDRLEN,
"Size of UDP struct does not match its expected size.");
diff --git a/lib/includes/hicn/strategy.h b/lib/includes/hicn/strategy.h
new file mode 100644
index 000000000..c71db451a
--- /dev/null
+++ b/lib/includes/hicn/strategy.h
@@ -0,0 +1,63 @@
+/*
+ * 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 strategy.h
+ * \brief hICN forwarding strategy
+ */
+#ifndef HICN_STRATEGY_H
+#define HICN_STRATEGY_H
+
+#include <string.h>
+
+#define foreach_strategy_type \
+ _ (UNDEFINED) \
+ _ (LOADBALANCER) \
+ _ (LOW_LATENCY) \
+ _ (RANDOM) \
+ _ (REPLICATION) \
+ _ (BESTPATH) \
+ _ (N)
+
+typedef enum
+{
+#define _(x) STRATEGY_TYPE_##x,
+ foreach_strategy_type
+#undef _
+} strategy_type_t;
+
+extern const char *strategy_str[];
+#define strategy_str(x) strategy_str[x]
+
+#define IS_VALID_STRATEGY_TYPE(x) IS_VALID_ENUM_TYPE (STRATEGY_TYPE, x)
+
+static inline strategy_type_t
+strategy_type_from_str (const char *strategy_str)
+{
+#define _(x) \
+ if (strcasecmp (strategy_str, #x) == 0) \
+ return STRATEGY_TYPE_##x; \
+ else
+ foreach_strategy_type
+#undef _
+ return STRATEGY_TYPE_UNDEFINED;
+}
+
+#define STRATEGY_TYPE_VALID(type) \
+ ((type != STRATEGY_TYPE_UNDEFINED) && (type != STRATEGY_TYPE_N))
+
+#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
+
+#endif /* HICN_STRATEGY_H */
diff --git a/lib/includes/hicn/util/array.h b/lib/includes/hicn/util/array.h
index 56cfcad8b..46d60976e 100644
--- a/lib/includes/hicn/util/array.h
+++ b/lib/includes/hicn/util/array.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,178 +23,169 @@
#include <assert.h>
#include <hicn/util/log.h>
-#include <math.h> // log2
+#include <math.h> // log2
#include <string.h> // memmove
#define BUFSIZE 1024
-typedef int(*cmp_t)(const void * x, const void * y);
-
-#define TYPEDEF_ARRAY_H(NAME, T) \
- \
-typedef struct { \
- size_t size; \
- size_t max_size_log; \
- T * elements; \
-} NAME ## _t; \
- \
-int NAME ## _initialize(NAME ## _t * array); \
- \
-int NAME ## _finalize(NAME ## _t * array); \
- \
-NAME ## _t * NAME ## _create(); \
- \
-void NAME ## _free(NAME ## _t * array); \
- \
-int NAME ## _add(NAME ## _t * array, T element); \
- \
-int NAME ## _remove_index(NAME ## _t * array, int index, T * element); \
- \
-int NAME ## _remove(NAME ## _t * array, const T search, T * element); \
- \
-int NAME ## _get(const NAME ## _t * array, const T search, T * element); \
- \
-int NAME ## _get_index(const NAME ## _t * array, int index, T * element); \
- \
-int NAME ## _get_elements(const NAME ## _t * array, T ** elements); \
- \
-size_t NAME ## _len(const NAME ## _t * array);
+typedef int (*cmp_t) (const void *x, const void *y);
+#define TYPEDEF_ARRAY_H(NAME, T) \
+ \
+ typedef struct \
+ { \
+ size_t size; \
+ size_t max_size_log; \
+ T *elements; \
+ } NAME##_t; \
+ \
+ int NAME##_initialize (NAME##_t *array); \
+ \
+ int NAME##_finalize (NAME##_t *array); \
+ \
+ NAME##_t *NAME##_create (); \
+ \
+ void NAME##_free (NAME##_t *array); \
+ \
+ int NAME##_add (NAME##_t *array, T element); \
+ \
+ int NAME##_remove_index (NAME##_t *array, int index, T *element); \
+ \
+ int NAME##_remove (NAME##_t *array, const T search, T *element); \
+ \
+ int NAME##_get (const NAME##_t *array, const T search, T *element); \
+ \
+ int NAME##_get_index (const NAME##_t *array, int index, T *element); \
+ \
+ int NAME##_get_elements (const NAME##_t *array, T **elements); \
+ \
+ size_t NAME##_len (const NAME##_t *array);
#define ARRAY_MAX_SIZE_LOG_INIT 0
-#define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \
-int \
-NAME ## _initialize(NAME ## _t * array) \
-{ \
- array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \
- array->size = 0; \
- if (array->max_size_log == 0) { \
- array->elements = NULL; \
- return 0; \
- } \
- array->elements = malloc((1 << array->max_size_log) * sizeof(T)); \
- if (!array->elements) \
- return -1; \
- return 0; \
-} \
- \
-int \
-NAME ## _finalize(NAME ## _t * array) \
-{ \
- for (unsigned i = 0; i < array->size; i++) { \
- NAME ## _remove_index(array, i, NULL); \
- } \
- return 0; \
-} \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * array = malloc(sizeof(NAME ## _t)); \
- if (!array) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(array) < 0) \
- goto ERR_INITIALIZE; \
- \
- return array; \
- \
-ERR_INITIALIZE: \
- free(array); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * array) \
-{ \
- NAME ## _finalize(array); \
- free(array->elements); \
- free(array); \
-} \
- \
-int \
-NAME ## _add(NAME ## _t * array, T element) \
-{ \
- /* Ensure sufficient space for next addition */ \
- size_t new_size_log = (array->size > 0) ? log2(array->size)+1 : 1; \
- if (new_size_log > array->max_size_log) { \
- array->max_size_log = new_size_log; \
- array->elements = realloc(array->elements, \
- (1 << new_size_log) * sizeof(T)); \
- } \
- \
- if (!array->elements) \
- goto ERR_REALLOC; \
- \
- array->elements[array->size++] = element; \
- return 0; \
- \
-ERR_REALLOC: \
- return -1; \
-} \
- \
-int \
-NAME ## _remove_index(NAME ## _t * array, int index, T * element) \
-{ \
- if (index > NAME ## _len(array)) \
- return -1; \
- if (element) \
- *element = array->elements[index]; \
- if (index < array->size) \
- memmove(array->elements + index, array->elements + index + 1, \
- array->size - index); \
- array->size--; \
- return 0; \
-} \
- \
-int \
-NAME ## _remove(NAME ## _t * array, const T search, T * element) \
-{ \
- for (unsigned i = 0; i < array->size; i++) { \
- if (CMP(search, array->elements[i]) == 0) \
- return facelet_array_remove_index(array, i, element); \
- } \
- /* Not found */ \
- if (element) \
- *element = NULL; \
- return 0; \
-} \
- \
-int \
-NAME ## _get(const NAME ## _t * array, const T search, T * element) \
-{ \
- assert(element); \
- for (unsigned i = 0; i < array->size; i++) \
- if (CMP(search, array->elements[i]) == 0) { \
- *element = array->elements[i]; \
- return 0; \
- } \
- /* Not found */ \
- *element = NULL; \
- return 0; \
-} \
- \
-int \
-NAME ## _get_index(const NAME ## _t * array, int index, T * element) \
-{ \
- assert(element); \
- *element = array->elements[index]; \
- return 0; \
-} \
- \
-int \
-NAME ## _get_elements(const NAME ## _t * array, T ** elements) \
-{ \
- *elements = array->elements; \
- return 0; \
-} \
- \
-size_t \
-NAME ## _len(const NAME ## _t * array) \
-{ \
- return array->size; \
-}
+#define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \
+ int NAME##_initialize (NAME##_t *array) \
+ { \
+ array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \
+ array->size = 0; \
+ if (array->max_size_log == 0) \
+ { \
+ array->elements = NULL; \
+ return 0; \
+ } \
+ array->elements = malloc ((1 << array->max_size_log) * sizeof (T)); \
+ if (!array->elements) \
+ return -1; \
+ return 0; \
+ } \
+ \
+ int NAME##_finalize (NAME##_t *array) \
+ { \
+ for (unsigned i = 0; i < array->size; i++) \
+ { \
+ NAME##_remove_index (array, i, NULL); \
+ } \
+ return 0; \
+ } \
+ \
+ NAME##_t *NAME##_create () \
+ { \
+ NAME##_t *array = malloc (sizeof (NAME##_t)); \
+ if (!array) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize (array) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return array; \
+ \
+ ERR_INITIALIZE: \
+ free (array); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free (NAME##_t *array) \
+ { \
+ NAME##_finalize (array); \
+ free (array->elements); \
+ free (array); \
+ } \
+ \
+ int NAME##_add (NAME##_t *array, T element) \
+ { \
+ /* Ensure sufficient space for next addition */ \
+ size_t new_size_log = (array->size > 0) ? log2 (array->size) + 1 : 1; \
+ if (new_size_log > array->max_size_log) \
+ { \
+ array->max_size_log = new_size_log; \
+ array->elements = \
+ realloc (array->elements, (1 << new_size_log) * sizeof (T)); \
+ } \
+ \
+ if (!array->elements) \
+ goto ERR_REALLOC; \
+ \
+ array->elements[array->size++] = element; \
+ return 0; \
+ \
+ ERR_REALLOC: \
+ return -1; \
+ } \
+ \
+ int NAME##_remove_index (NAME##_t *array, int index, T *element) \
+ { \
+ if (index > NAME##_len (array)) \
+ return -1; \
+ if (element) \
+ *element = array->elements[index]; \
+ if (index < array->size) \
+ memmove (array->elements + index, array->elements + index + 1, \
+ array->size - index); \
+ array->size--; \
+ return 0; \
+ } \
+ \
+ int NAME##_remove (NAME##_t *array, const T search, T *element) \
+ { \
+ for (unsigned i = 0; i < array->size; i++) \
+ { \
+ if (CMP (search, array->elements[i]) == 0) \
+ return facelet_array_remove_index (array, i, element); \
+ } \
+ /* Not found */ \
+ if (element) \
+ *element = NULL; \
+ return 0; \
+ } \
+ \
+ int NAME##_get (const NAME##_t *array, const T search, T *element) \
+ { \
+ assert (element); \
+ for (unsigned i = 0; i < array->size; i++) \
+ if (CMP (search, array->elements[i]) == 0) \
+ { \
+ *element = array->elements[i]; \
+ return 0; \
+ } \
+ /* Not found */ \
+ *element = NULL; \
+ return 0; \
+ } \
+ \
+ int NAME##_get_index (const NAME##_t *array, int index, T *element) \
+ { \
+ assert (element); \
+ *element = array->elements[index]; \
+ return 0; \
+ } \
+ \
+ int NAME##_get_elements (const NAME##_t *array, T **elements) \
+ { \
+ *elements = array->elements; \
+ return 0; \
+ } \
+ \
+ size_t NAME##_len (const NAME##_t *array) { return array->size; }
#endif /* UTIL_ARRAY_H */
diff --git a/lib/includes/hicn/util/ip_address.h b/lib/includes/hicn/util/ip_address.h
index 4facd9ad0..89a4c11e0 100644
--- a/lib/includes/hicn/util/ip_address.h
+++ b/lib/includes/hicn/util/ip_address.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,10 +20,9 @@
#ifndef UTIL_IP_ADDRESS_H
#define UTIL_IP_ADDRESS_H
-
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
-#define __bswap_constant_32(x) OSSwapInt32(x)
+#define __bswap_constant_32(x) OSSwapInt32 (x)
#include <machine/endian.h>
#else
#ifdef __ANDROID__
@@ -34,8 +33,8 @@
#include <errno.h>
#ifndef _WIN32
-#include <netinet/in.h> // struct sockadd
-#include <arpa/inet.h> // inet_ntop
+#include <netinet/in.h> // struct sockadd
+#include <arpa/inet.h>
#include <netdb.h> // struct addrinfo
#endif
#include <stdbool.h>
@@ -45,11 +44,12 @@
#include "types.h"
-#define bytes_to_bits(x) (x * 8)
-#define IPV6_ADDR_LEN 16 /* bytes */
-#define IPV4_ADDR_LEN 4 /* bytes */
-#define IPV6_ADDR_LEN_BITS bytes_to_bits(IPV6_ADDR_LEN)
-#define IPV4_ADDR_LEN_BITS bytes_to_bits(IPV4_ADDR_LEN)
+#define bytes_to_bits(x) (x * 8)
+#define IPV6_ADDR_LEN 16 /* bytes */
+#define IPV4_ADDR_LEN 4 /* bytes */
+#define IPV6_ADDR_LEN_BITS bytes_to_bits (IPV6_ADDR_LEN)
+#define IPV4_ADDR_LEN_BITS bytes_to_bits (IPV4_ADDR_LEN)
+#define MAX_IPV6_PREFIX_LEN 128
/* Presentation format */
#ifndef INET_ADDRSTRLEN
@@ -65,25 +65,34 @@
#define DUMMY_PORT 1234
-typedef union {
- struct {
- u32 pad[3];
- union {
- struct in_addr as_inaddr;
- u8 buffer[4];
- u8 as_u8[4];
- u16 as_u16[2];
- u32 as_u32;
- } v4;
- };
- union {
- struct in6_addr as_in6addr;
- u8 buffer[16];
- u8 as_u8[16];
- u16 as_u16[8];
- u32 as_u32[4];
- u64 as_u64[2];
- } v6;
+#ifndef HICN_VPP_PLUGIN
+typedef union
+{
+ struct in_addr as_inaddr;
+ u8 buffer[4];
+ u8 as_u8[4];
+ u16 as_u16[2];
+ u32 as_u32;
+} ip4_address_t;
+
+typedef union
+{
+ struct in6_addr as_in6addr;
+ u8 buffer[16];
+ u8 as_u8[16];
+ u16 as_u16[8];
+ u32 as_u32[4];
+ u64 as_u64[2];
+} ip6_address_t;
+
+typedef union
+{
+ struct
+ {
+ u32 pad[3];
+ ip4_address_t v4;
+ };
+ ip6_address_t v6;
#if 0 /* removed as prone to error due to IPv4 padding */
u8 buffer[IP_MAX_ADDR_LEN];
u8 as_u8[IP_MAX_ADDR_LEN];
@@ -93,77 +102,105 @@ typedef union {
#endif
} ip_address_t;
+#else
+
+#include <vnet/ip/ip4_packet.h> // ip4_address_t
+#include <vnet/ip/ip6_packet.h> // ip6_address_t
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+
+#include <vnet/ip/ip46_address.h>
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic pop
+#endif
+
+typedef ip46_address_t ip_address_t;
+
+#endif /* HICN_VPP_PLUGIN */
+
+#define ip_address_is_v4(ip) \
+ (((ip)->pad[0] | (ip)->pad[1] | (ip)->pad[2]) == 0)
+
#define MAXSZ_IP4_ADDRESS_ INET_ADDRSTRLEN - 1
#define MAXSZ_IP6_ADDRESS_ INET6_ADDRSTRLEN - 1
-#define MAXSZ_IP_ADDRESS_ MAXSZ_IP6_ADDRESS_
-#define MAXSZ_IP4_ADDRESS MAXSZ_IP4_ADDRESS_ + 1
-#define MAXSZ_IP6_ADDRESS MAXSZ_IP6_ADDRESS_ + 1
-#define MAXSZ_IP_ADDRESS MAXSZ_IP_ADDRESS_ + 1
+#define MAXSZ_IP_ADDRESS_ MAXSZ_IP6_ADDRESS_
+#define MAXSZ_IP4_ADDRESS MAXSZ_IP4_ADDRESS_ + 1
+#define MAXSZ_IP6_ADDRESS MAXSZ_IP6_ADDRESS_ + 1
+#define MAXSZ_IP_ADDRESS MAXSZ_IP_ADDRESS_ + 1
-typedef struct {
+typedef struct
+{
int family;
ip_address_t address;
u8 len;
} ip_prefix_t;
-#define MAXSZ_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
-#define MAXSZ_PREFIX MAXSZ_PREFIX_ + 1
+#define MAXSZ_IP_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3
+#define MAXSZ_IP_PREFIX MAXSZ_IP_PREFIX_ + 1
extern const ip_address_t IPV4_LOOPBACK;
extern const ip_address_t IPV6_LOOPBACK;
extern const ip_address_t IPV4_ANY;
extern const ip_address_t IPV6_ANY;
+
+extern const ip4_address_t IP4_ADDRESS_EMPTY;
+extern const ip6_address_t IP6_ADDRESS_EMPTY;
extern const ip_address_t IP_ADDRESS_EMPTY;
#define IP_ANY(family) (family == AF_INET) ? IPV4_ANY : IPV6_ANY
-
-#define MAX_PORT 1 << (8 * sizeof(u16))
-#define IS_VALID_PORT(x) ((x > 0) && ((int)x < MAX_PORT))
+#define MAX_PORT 1 << (8 * sizeof (u16))
+#define IS_VALID_PORT(x) ((x > 0) && ((int) x < MAX_PORT))
#define MAXSZ_PORT_ 5
-#define MAXSZ_PORT MAXSZ_PORT_ + 1
+#define MAXSZ_PORT MAXSZ_PORT_ + 1
#define IS_VALID_FAMILY(x) ((x == AF_INET) || (x == AF_INET6))
/* IP address */
-int ip_address_get_family (const char * ip_address);
+int ip_address_get_family (const char *ip_address);
int ip_address_len (int family);
-const u8 * ip_address_get_buffer(const ip_address_t * ip_address, int family);
-int ip_address_ntop (const ip_address_t * ip_address, char *dst,
- const size_t len, int family);
-int ip_address_pton (const char *ip_address_str, ip_address_t * ip_address);
-int ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address,
- int family);
-int ip_address_to_sockaddr(const ip_address_t * ip_address, struct sockaddr *sa,
- int family);
-int ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family);
-int ip_address_empty(const ip_address_t * ip);
+const u8 *ip_address_get_buffer (const ip_address_t *ip_address, int family);
+int ip_address_ntop (const ip_address_t *ip_address, char *dst,
+ const size_t len, int family);
+int ip_address_pton (const char *ip_address_str, ip_address_t *ip_address);
+int ip_address_snprintf (char *s, size_t size, const ip_address_t *ip_address,
+ int family);
+int ip_address_to_sockaddr (const ip_address_t *ip_address,
+ struct sockaddr *sa, int family);
+int ip_address_cmp (const ip_address_t *ip1, const ip_address_t *ip2,
+ int family);
+int ip_address_empty (const ip_address_t *ip);
/* Prefix */
-int ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix);
-int ip_prefix_ntop_short (const ip_prefix_t * ip_prefix, char *dst, size_t size);
-int ip_prefix_ntop (const ip_prefix_t * ip_prefix, char *dst, size_t size);
-int ip_prefix_len (const ip_prefix_t * prefix);
-bool ip_prefix_empty (const ip_prefix_t * prefix);
-int ip_prefix_to_sockaddr(const ip_prefix_t * prefix, struct sockaddr *sa);
-int ip_prefix_cmp(const ip_prefix_t * prefix1, const ip_prefix_t * prefix2);
+int ip_prefix_pton (const char *ip_address_str, ip_prefix_t *ip_prefix);
+int ip_prefix_ntop_short (const ip_prefix_t *ip_prefix, char *dst,
+ size_t size);
+int ip_prefix_ntop (const ip_prefix_t *ip_prefix, char *dst, size_t size);
+int ip_prefix_snprintf (char *s, size_t size, const ip_prefix_t *prefix);
+int ip_prefix_len (const ip_prefix_t *prefix);
+bool ip_prefix_empty (const ip_prefix_t *prefix);
+int ip_prefix_to_sockaddr (const ip_prefix_t *prefix, struct sockaddr *sa);
+int ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2);
/* URL */
#define MAXSZ_PROTO_ 8 /* inetX:// */
-#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
+#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
#define MAXSZ_URL4_ MAXSZ_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_
#define MAXSZ_URL6_ MAXSZ_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_
-#define MAXSZ_URL_ MAXSZ_URL6_
-#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
-#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
-#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
+#define MAXSZ_URL_ MAXSZ_URL6_
+#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
+#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
+#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
-int url_snprintf(char * s, size_t size, int family,
- const ip_address_t * ip_address, u16 port);
+int url_snprintf (char *s, size_t size, int family,
+ const ip_address_t *ip_address, u16 port);
#endif /* UTIL_IP_ADDRESS_H */
diff --git a/lib/includes/hicn/util/log.h b/lib/includes/hicn/util/log.h
index 6763d464f..6b35d1fef 100644
--- a/lib/includes/hicn/util/log.h
+++ b/lib/includes/hicn/util/log.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,8 +17,8 @@
#define UTIL_LOG_H
#include <stdarg.h> // va_*
-#include <stdio.h> // FILE
-#include <time.h> // time, localtime
+#include <stdio.h> // FILE
+#include <time.h> // time, localtime
#define LOG_FATAL 0
#define LOG_ERROR 1
@@ -27,43 +27,59 @@
#define LOG_DEBUG 4
#define LOG_TRACE 5
-typedef struct {
+typedef struct
+{
int log_level;
int debug;
- FILE * log_file;
+ FILE *log_file;
} log_conf_t;
-#define DEFAULT_LOG_CONF { \
- .log_level = LOG_INFO, \
- .debug = 0, \
- .log_file = NULL, \
-};
+#define DEFAULT_LOG_CONF \
+ { \
+ .log_level = LOG_INFO, \
+ .debug = 0, \
+ .log_file = NULL, \
+ };
extern log_conf_t log_conf;
-#define WITH_DEBUG(BLOCK) \
- if (log_conf.log_level >= LOG_DEBUG) \
- BLOCK
+#define WITH_ERROR(BLOCK) \
+ if (log_conf.log_level >= LOG_ERROR) \
+ BLOCK
+#define WITH_WARN(BLOCK) \
+ if (log_conf.log_level >= LOG_WARN) \
+ BLOCK
+#define WITH_INFO(BLOCK) \
+ if (log_conf.log_level >= LOG_INFO) \
+ BLOCK
+#define WITH_DEBUG(BLOCK) \
+ if (log_conf.log_level >= LOG_DEBUG) \
+ BLOCK
+#define WITH_TRACE(BLOCK) \
+ if (log_conf.log_level >= LOG_TRACE) \
+ BLOCK
-#define FATAL(fmt, ...) (_log(LOG_FATAL, fmt, ##__VA_ARGS__ ))
+#define FATAL(fmt, ...) (_log (LOG_FATAL, fmt, ##__VA_ARGS__))
#ifdef ERROR
#undef ERROR
#endif
-#define ERROR(fmt, ...) (_log(LOG_ERROR, fmt, ##__VA_ARGS__ ))
-#define WARN(fmt, ...) (_log(LOG_WARN, fmt, ##__VA_ARGS__ ))
-#define INFO(fmt, ...) (_log(LOG_INFO, fmt, ##__VA_ARGS__ ))
-#define DEBUG(fmt, ...) (_log(LOG_DEBUG, fmt, ##__VA_ARGS__ ))
-#define TRACE(fmt, ...) (_log(LOG_TRACE, fmt, ##__VA_ARGS__ ))
+#define ERROR(fmt, ...) (_log (LOG_ERROR, fmt, ##__VA_ARGS__))
+#define WARN(fmt, ...) (_log (LOG_WARN, fmt, ##__VA_ARGS__))
+#define INFO(fmt, ...) (_log (LOG_INFO, fmt, ##__VA_ARGS__))
+#define DEBUG(fmt, ...) (_log (LOG_DEBUG, fmt, ##__VA_ARGS__))
+#define TRACE(fmt, ...) (_log (LOG_TRACE, fmt, ##__VA_ARGS__))
-void _log_va(int level, const char *fmt, va_list ap);
+void _log_va (int level, const char *fmt, va_list ap);
-void _log(int level, const char *fmt, ...);
+void _log (int level, const char *fmt, ...);
-void fatal(char *fmt, ...);
+void fatal (char *fmt, ...);
+
+int loglevel_from_str (const char *loglevel);
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
-void print_trace(void);
+void print_trace (void);
#endif
#endif // UTIL_LOG_H
diff --git a/lib/includes/hicn/util/map.h b/lib/includes/hicn/util/map.h
index 01195865e..6e23f222f 100644
--- a/lib/includes/hicn/util/map.h
+++ b/lib/includes/hicn/util/map.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,231 +20,227 @@
#include "set.h"
-#define ERR_MAP_EXISTS -2
+#define ERR_MAP_EXISTS -2
#define ERR_MAP_NOT_FOUND -3
-#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \
- \
-typedef struct { \
- KEY_T key; \
- VAL_T value; \
-} NAME ## _pair_t; \
- \
-NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value); \
- \
-void NAME ## _pair_free(NAME ## _pair_t * pair); \
- \
-int NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2); \
- \
-TYPEDEF_SET_H(NAME ## _pair_set, NAME ## _pair_t *) \
- \
-typedef struct NAME ## _s { \
- NAME ## _pair_set_t pair_set; \
-} NAME ## _t; \
- \
-int NAME ## _initialize(NAME ## _t * map); \
- \
-int NAME ## _finalize(NAME ## _t * map); \
- \
-NAME ## _t * NAME ## _create(); \
- \
-void NAME ## _free(NAME ## _t * map); \
- \
-int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value); \
- \
-int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value); \
- \
-int NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value); \
- \
-void NAME ## _dump(NAME ## _t * map);
+#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \
+ \
+ typedef struct \
+ { \
+ KEY_T key; \
+ VAL_T value; \
+ } NAME##_pair_t; \
+ \
+ NAME##_pair_t *NAME##_pair_create (KEY_T key, VAL_T value); \
+ \
+ void NAME##_pair_free (NAME##_pair_t *pair); \
+ \
+ int NAME##_pair_cmp (const NAME##_pair_t *p1, const NAME##_pair_t *p2); \
+ \
+ TYPEDEF_SET_H (NAME##_pair_set, NAME##_pair_t *) \
+ \
+ typedef struct NAME##_s \
+ { \
+ NAME##_pair_set_t pair_set; \
+ } NAME##_t; \
+ \
+ int NAME##_initialize (NAME##_t *map); \
+ \
+ int NAME##_finalize (NAME##_t *map); \
+ \
+ NAME##_t *NAME##_create (); \
+ \
+ void NAME##_free (NAME##_t *map); \
+ \
+ int NAME##_add (NAME##_t *map, KEY_T key, VAL_T value); \
+ \
+ int NAME##_remove (NAME##_t *map, KEY_T key, VAL_T *value); \
+ \
+ int NAME##_get (NAME##_t *map, KEY_T key, VAL_T *value); \
+ \
+ void NAME##_dump (NAME##_t *map); \
+ \
+ int NAME##_get_key_array (NAME##_t *map, KEY_T **array); \
+ \
+ int NAME##_get_value_array (NAME##_t *map, VAL_T **array);
-
-
-
-#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \
- \
-NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value) \
-{ \
- /* Create pair */ \
- NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t)); \
- if (!pair) \
- return NULL; \
- \
- pair->key = key; \
- pair->value = value; \
- \
- return pair; \
-} \
- \
-void NAME ## _pair_free(NAME ## _pair_t * pair) \
-{ \
- free(pair); \
-} \
- \
-int \
-NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2) \
-{ \
- return (CMP(p1->key, p2->key)); \
-} \
- \
-int \
-NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) { \
- int rc; \
- rc = KEY_SNPRINTF(buf, BUFSIZE/2, (KEY_T)pair->key); \
- if (rc < 0) \
- return rc; \
- rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value); \
- return (int)rc; \
-} \
- \
-TYPEDEF_SET(NAME ## _pair_set, NAME ## _pair_t *, NAME ## _pair_cmp, NAME ## _pair_snprintf); \
- \
-int \
-NAME ## _initialize(NAME ## _t * map) \
-{ \
- return NAME ## _pair_set_initialize(&map->pair_set); \
-} \
- \
-int \
-NAME ## _finalize(NAME ## _t * map) \
-{ \
- NAME ## _pair_t ** array; \
- int n = NAME ## _pair_set_get_array(&map->pair_set, &array); \
- if (n < 0) \
- return -1; \
- for (unsigned i = 0; i < n; i++) { \
- NAME ## _pair_t * pair = array[i]; \
- NAME ## _pair_set_remove(&map->pair_set, pair, NULL); \
- NAME ## _pair_free(pair); \
- } \
- free(array); \
- return NAME ## _pair_set_finalize(&map->pair_set); \
-} \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * map = malloc(sizeof(NAME ## _t)); \
- if (!map) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(map) < 0) \
- goto ERR_INITIALIZE; \
- \
- return map; \
- \
-ERR_INITIALIZE: \
- free(map); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * map) \
-{ \
- NAME ## _finalize(map); \
- free(map); \
-} \
- \
-int \
-NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value) \
-{ \
- int rc; \
- NAME ## _pair_t * found = NULL; \
- \
- NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \
- if (!pair) \
- return -1; \
- \
- rc = NAME ## _pair_set_get(&map->pair_set, pair, &found); \
- if (rc < 0) \
- return -1; \
- if (found) { \
- NAME ## _pair_free(pair); \
- return ERR_MAP_EXISTS; \
- } \
- \
- rc = NAME ## _pair_set_add(&map->pair_set, pair); \
- if (rc < 0) { \
- NAME ## _pair_free(pair); \
- return -1; \
- } \
- return 0; \
-} \
- \
-int \
-NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value) \
-{ \
- NAME ## _pair_t * found = NULL; \
- NAME ## _pair_t search = { .key = key }; \
- int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found); \
- if (rc < 0) \
- return ERR_MAP_NOT_FOUND; \
- if (value) \
- *value = found->value; \
- NAME ## _pair_free(found); \
- return 0; \
-} \
- \
-int \
-NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value) \
-{ \
- NAME ## _pair_t * found = NULL, search = { .key = key }; \
- int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found); \
- if (rc < 0) \
- return -1; \
- if (found) \
- *value = found->value; \
- return 0; \
-} \
- \
-void \
-NAME ## _dump(NAME ## _t * map) { \
- NAME ## _pair_set_dump(&map->pair_set); \
-} \
- \
-int \
-NAME ## _get_key_array(NAME ## _t * map, KEY_T **array) { \
- NAME ## _pair_t ** pair_array; \
- int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \
- if (n < 0) \
- return -1; \
- if (!array) \
- goto END; \
- /* Allocate result array */ \
- *array = malloc(n * sizeof(KEY_T)); \
- if (!array) { \
- free(pair_array); \
- return -1; \
- } \
- /* Copy keys */ \
- for (int i = 0; i < n; i++) \
- (*array)[i] = pair_array[i]->key; \
- free(pair_array); \
-END: \
- return n; \
-} \
- \
-int \
-NAME ## _get_value_array(NAME ## _t * map, VAL_T **array) { \
- NAME ## _pair_t ** pair_array; \
- int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \
- if (n < 0) \
- return -1; \
- if (!array) \
- goto END; \
- /* Allocate result array */ \
- *array = malloc(n * sizeof(VAL_T)); \
- if (!array) { \
- free(pair_array); \
- return -1; \
- } \
- /* Copy values */ \
- for (int i = 0; i < n; i++) \
- (*array)[i] = pair_array[i]->value; \
- free(pair_array); \
-END: \
- return n; \
-}
+#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \
+ \
+ NAME##_pair_t *NAME##_pair_create (KEY_T key, VAL_T value) \
+ { \
+ /* Create pair */ \
+ NAME##_pair_t *pair = malloc (sizeof (NAME##_pair_t)); \
+ if (!pair) \
+ return NULL; \
+ \
+ pair->key = key; \
+ pair->value = value; \
+ \
+ return pair; \
+ } \
+ \
+ void NAME##_pair_free (NAME##_pair_t *pair) { free (pair); } \
+ \
+ int NAME##_pair_cmp (const NAME##_pair_t *p1, const NAME##_pair_t *p2) \
+ { \
+ return (CMP (p1->key, p2->key)); \
+ } \
+ \
+ int NAME##_pair_snprintf (char *buf, size_t size, \
+ const NAME##_pair_t *pair) \
+ { \
+ int rc; \
+ rc = KEY_SNPRINTF (buf, BUFSIZE / 2, (KEY_T) pair->key); \
+ if (rc < 0) \
+ return rc; \
+ rc = VALUE_SNPRINTF (buf + rc, BUFSIZE / 2, (VAL_T) pair->value); \
+ return (int) rc; \
+ } \
+ \
+ TYPEDEF_SET (NAME##_pair_set, NAME##_pair_t *, NAME##_pair_cmp, \
+ NAME##_pair_snprintf); \
+ \
+ int NAME##_initialize (NAME##_t *map) \
+ { \
+ return NAME##_pair_set_initialize (&map->pair_set); \
+ } \
+ \
+ int NAME##_finalize (NAME##_t *map) \
+ { \
+ NAME##_pair_t **array; \
+ int n = NAME##_pair_set_get_array (&map->pair_set, &array); \
+ if (n < 0) \
+ return -1; \
+ for (unsigned i = 0; i < n; i++) \
+ { \
+ NAME##_pair_t *pair = array[i]; \
+ NAME##_pair_set_remove (&map->pair_set, pair, NULL); \
+ NAME##_pair_free (pair); \
+ } \
+ free (array); \
+ return NAME##_pair_set_finalize (&map->pair_set); \
+ } \
+ \
+ NAME##_t *NAME##_create () \
+ { \
+ NAME##_t *map = malloc (sizeof (NAME##_t)); \
+ if (!map) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize (map) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return map; \
+ \
+ ERR_INITIALIZE: \
+ free (map); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free (NAME##_t *map) \
+ { \
+ NAME##_finalize (map); \
+ free (map); \
+ } \
+ \
+ int NAME##_add (NAME##_t *map, KEY_T key, VAL_T value) \
+ { \
+ int rc; \
+ NAME##_pair_t *found = NULL; \
+ \
+ NAME##_pair_t *pair = NAME##_pair_create (key, value); \
+ if (!pair) \
+ return -1; \
+ \
+ rc = NAME##_pair_set_get (&map->pair_set, pair, &found); \
+ if (rc < 0) \
+ return -1; \
+ if (found) \
+ { \
+ NAME##_pair_free (pair); \
+ return ERR_MAP_EXISTS; \
+ } \
+ \
+ rc = NAME##_pair_set_add (&map->pair_set, pair); \
+ if (rc < 0) \
+ { \
+ NAME##_pair_free (pair); \
+ return -1; \
+ } \
+ return 0; \
+ } \
+ \
+ int NAME##_remove (NAME##_t *map, KEY_T key, VAL_T *value) \
+ { \
+ NAME##_pair_t *found = NULL; \
+ NAME##_pair_t search = { .key = key }; \
+ int rc = NAME##_pair_set_remove (&map->pair_set, &search, &found); \
+ if (rc < 0) \
+ return ERR_MAP_NOT_FOUND; \
+ if (value) \
+ *value = found->value; \
+ NAME##_pair_free (found); \
+ return 0; \
+ } \
+ \
+ int NAME##_get (NAME##_t *map, KEY_T key, VAL_T *value) \
+ { \
+ NAME##_pair_t *found = NULL, search = { .key = key }; \
+ int rc = NAME##_pair_set_get (&map->pair_set, &search, &found); \
+ if (rc < 0) \
+ return -1; \
+ if (found) \
+ *value = found->value; \
+ return 0; \
+ } \
+ \
+ void NAME##_dump (NAME##_t *map) { NAME##_pair_set_dump (&map->pair_set); } \
+ \
+ int NAME##_get_key_array (NAME##_t *map, KEY_T **array) \
+ { \
+ NAME##_pair_t **pair_array; \
+ int n = NAME##_pair_set_get_array (&map->pair_set, &pair_array); \
+ if (n < 0) \
+ return -1; \
+ if (!array) \
+ goto END; \
+ /* Allocate result array */ \
+ *array = malloc (n * sizeof (KEY_T)); \
+ if (!array) \
+ { \
+ free (pair_array); \
+ return -1; \
+ } \
+ /* Copy keys */ \
+ for (int i = 0; i < n; i++) \
+ (*array)[i] = pair_array[i]->key; \
+ free (pair_array); \
+ END: \
+ return n; \
+ } \
+ \
+ int NAME##_get_value_array (NAME##_t *map, VAL_T **array) \
+ { \
+ NAME##_pair_t **pair_array; \
+ int n = NAME##_pair_set_get_array (&map->pair_set, &pair_array); \
+ if (n < 0) \
+ return -1; \
+ if (!array) \
+ goto END; \
+ /* Allocate result array */ \
+ *array = malloc (n * sizeof (VAL_T)); \
+ if (!array) \
+ { \
+ free (pair_array); \
+ return -1; \
+ } \
+ /* Copy values */ \
+ for (int i = 0; i < n; i++) \
+ (*array)[i] = pair_array[i]->value; \
+ free (pair_array); \
+ END: \
+ return n; \
+ }
#endif /* UTIL_MAP_H */
diff --git a/lib/includes/hicn/util/set.h b/lib/includes/hicn/util/set.h
index bc2e3caac..0a5ff6777 100644
--- a/lib/includes/hicn/util/set.h
+++ b/lib/includes/hicn/util/set.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,214 +25,196 @@
#define thread_local _Thread_local
//#endif /* ! __ANDROID__ */
-#define ERR_SET_EXISTS -2
+#define ERR_SET_EXISTS -2
#define ERR_SET_NOT_FOUND -3
/* FIXME: buffer overflow when this is too small... investigate */
#define BUFSIZE 1024
-static inline
-int
-int_cmp(const int x, const int y)
+static inline int
+int_cmp (const int x, const int y)
{
- return x - y;
+ return x - y;
}
-static inline
-int
-int_snprintf(char * buf, size_t size, int value) {
- return snprintf(buf, size, "%d", value);
+static inline int
+int_snprintf (char *buf, size_t size, int value)
+{
+ return snprintf (buf, size, "%d", value);
}
-static inline
-int
-string_snprintf(char * buf, size_t size, const char * s) {
- return snprintf(buf, size, "%s", s);
+static inline int
+string_snprintf (char *buf, size_t size, const char *s)
+{
+ return snprintf (buf, size, "%s", s);
}
-static inline
-int
-generic_snprintf(char * buf, size_t size, const void * value) {
- return snprintf(buf, BUFSIZE, "%p", value);
+static inline int
+generic_snprintf (char *buf, size_t size, const void *value)
+{
+ return snprintf (buf, BUFSIZE, "%p", value);
}
-typedef int(*cmp_t)(const void * x, const void * y);
-
-#define TYPEDEF_SET_H(NAME, T) \
- \
-typedef struct { \
- size_t size; \
- void * root; \
-} NAME ## _t; \
- \
-int NAME ## _initialize(NAME ## _t * set); \
- \
-int NAME ## _finalize(NAME ## _t * set); \
- \
-NAME ## _t * NAME ## _create(); \
- \
-void NAME ## _free(NAME ## _t * set); \
- \
-int NAME ## _add(NAME ## _t * set, const T element); \
- \
-int NAME ## _remove(NAME ## _t * set, const T search, T * element); \
- \
-int NAME ## _clear(NAME ## _t * set); \
- \
-int NAME ## _get(const NAME ## _t * set, const T search, T * element); \
- \
-int NAME ## _get_array(const NAME ## _t * set, T ** element); \
- \
-void NAME ## _dump(NAME ## _t * set);
+typedef int (*cmp_t) (const void *x, const void *y);
+#define TYPEDEF_SET_H(NAME, T) \
+ \
+ typedef struct \
+ { \
+ size_t size; \
+ void *root; \
+ } NAME##_t; \
+ \
+ int NAME##_initialize (NAME##_t *set); \
+ \
+ int NAME##_finalize (NAME##_t *set); \
+ \
+ NAME##_t *NAME##_create (); \
+ \
+ void NAME##_free (NAME##_t *set); \
+ \
+ int NAME##_add (NAME##_t *set, const T element); \
+ \
+ int NAME##_remove (NAME##_t *set, const T search, T *element); \
+ \
+ int NAME##_clear (NAME##_t *set); \
+ \
+ int NAME##_get (const NAME##_t *set, const T search, T *element); \
+ \
+ int NAME##_get_array (const NAME##_t *set, T **element); \
+ \
+ void NAME##_dump (NAME##_t *set);
-
-
-#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \
-int \
-NAME ## _initialize(NAME ## _t * set) \
-{ \
- set->root = NULL; \
- set->size = 0; \
- return 0; \
-} \
- \
-int \
-NAME ## _finalize(NAME ## _t * set) \
-{ \
- return NAME ## _clear(set); \
-} \
- \
-NAME ## _t * \
-NAME ## _create() \
-{ \
- NAME ## _t * set = malloc(sizeof(NAME ## _t)); \
- if (!set) \
- goto ERR_MALLOC; \
- \
- if (NAME ## _initialize(set) < 0) \
- goto ERR_INITIALIZE; \
- \
- return set; \
- \
-ERR_INITIALIZE: \
- free(set); \
-ERR_MALLOC: \
- return NULL; \
-} \
- \
-void \
-NAME ## _free(NAME ## _t * set) \
-{ \
- NAME ## _finalize(set); \
- free(set); \
-} \
- \
-int \
-NAME ## _add(NAME ## _t * set, const T element) \
-{ \
- T * found = tfind(element, &set->root, (cmp_t)CMP); \
- void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \
- if (!ptr) \
- return -1; \
- if (!found) \
- set->size++; \
- return 0; \
-} \
- \
-int \
-NAME ## _remove(NAME ## _t * set, const T search, T * element) \
-{ \
- T * found = tfind(search, &set->root, (cmp_t)CMP); \
- if (!found) \
- return ERR_SET_NOT_FOUND; \
- if (element) \
- *element = *found; \
- tdelete(search, &set->root, (cmp_t)CMP); \
- set->size--; \
- return 0; \
-} \
- \
-int \
-NAME ## _clear(NAME ## _t * set) \
-{ \
- T * array; \
- int n = NAME ## _get_array(set, &array); \
- if (n < 0) \
- return -1; \
- for (unsigned i = 0; i < n; i++) { \
- T element = array[i]; \
- NAME ## _remove(set, element, NULL); \
- } \
- free(array); \
- return 0; \
-} \
- \
-int \
-NAME ## _get(const NAME ## _t * set, const T search, T * element) \
-{ \
- T * found = tfind(search, &set->root, (cmp_t)CMP); \
- if (element) \
- *element = found ? *found : NULL; \
- return 0; \
-} \
- \
-static void \
-NAME ## _dump_node(const void *nodep, const VISIT which, \
- const int depth) \
-{ \
- char buf[BUFSIZE]; \
- switch (which) { \
- case preorder: \
- case endorder: \
- break; \
- case postorder: \
- case leaf: \
- SNPRINTF(buf, BUFSIZE, *(T*)nodep); \
- INFO("%s", buf); \
- break; \
- } \
-} \
- \
-void \
-NAME ## _dump(NAME ## _t * set) { \
- twalk(set->root, NAME ## _dump_node); \
-} \
- \
-thread_local \
-T * NAME ## _array_pos = NULL; \
- \
-static void \
-NAME ## _add_node_to_array(const void *nodep, const VISIT which, \
- const int depth) \
-{ \
- if (!NAME ## _array_pos) \
- return; \
- switch (which) { \
- case preorder: \
- case endorder: \
- break; \
- case postorder: \
- case leaf: \
- *NAME ## _array_pos = *(T*)nodep; \
- NAME ## _array_pos++; \
- break; \
- } \
-} \
- \
-int \
-NAME ## _get_array(const NAME ## _t * set, T ** element) \
-{ \
- if (!element) \
- goto END; \
- *element = malloc(set->size * sizeof(T)); \
- if (!*element) \
- return -1; \
- NAME ## _array_pos = *element; \
- twalk(set->root, NAME ## _add_node_to_array); \
- NAME ## _array_pos = NULL; \
-END: \
- return (int)(set->size); \
-}
+#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \
+ int NAME##_initialize (NAME##_t *set) \
+ { \
+ set->root = NULL; \
+ set->size = 0; \
+ return 0; \
+ } \
+ \
+ int NAME##_finalize (NAME##_t *set) { return NAME##_clear (set); } \
+ \
+ NAME##_t *NAME##_create () \
+ { \
+ NAME##_t *set = malloc (sizeof (NAME##_t)); \
+ if (!set) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME##_initialize (set) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return set; \
+ \
+ ERR_INITIALIZE: \
+ free (set); \
+ ERR_MALLOC: \
+ return NULL; \
+ } \
+ \
+ void NAME##_free (NAME##_t *set) \
+ { \
+ NAME##_finalize (set); \
+ free (set); \
+ } \
+ \
+ int NAME##_add (NAME##_t *set, const T element) \
+ { \
+ T *found = tfind (element, &set->root, (cmp_t) CMP); \
+ void *ptr = tsearch (element, &set->root, (cmp_t) CMP); \
+ if (!ptr) \
+ return -1; \
+ if (!found) \
+ set->size++; \
+ return 0; \
+ } \
+ \
+ int NAME##_remove (NAME##_t *set, const T search, T *element) \
+ { \
+ T *found = tfind (search, &set->root, (cmp_t) CMP); \
+ if (!found) \
+ return ERR_SET_NOT_FOUND; \
+ if (element) \
+ *element = *found; \
+ tdelete (search, &set->root, (cmp_t) CMP); \
+ set->size--; \
+ return 0; \
+ } \
+ \
+ int NAME##_clear (NAME##_t *set) \
+ { \
+ T *array; \
+ int n = NAME##_get_array (set, &array); \
+ if (n < 0) \
+ return -1; \
+ for (unsigned i = 0; i < n; i++) \
+ { \
+ T element = array[i]; \
+ NAME##_remove (set, element, NULL); \
+ } \
+ free (array); \
+ return 0; \
+ } \
+ \
+ int NAME##_get (const NAME##_t *set, const T search, T *element) \
+ { \
+ T *found = tfind (search, &set->root, (cmp_t) CMP); \
+ if (element) \
+ *element = found ? *found : NULL; \
+ return 0; \
+ } \
+ \
+ static void NAME##_dump_node (const void *nodep, const VISIT which, \
+ const int depth) \
+ { \
+ char buf[BUFSIZE]; \
+ switch (which) \
+ { \
+ case preorder: \
+ case endorder: \
+ break; \
+ case postorder: \
+ case leaf: \
+ SNPRINTF (buf, BUFSIZE, *(T *) nodep); \
+ INFO ("%s", buf); \
+ break; \
+ } \
+ } \
+ \
+ void NAME##_dump (NAME##_t *set) { twalk (set->root, NAME##_dump_node); } \
+ \
+ thread_local T *NAME##_array_pos = NULL; \
+ \
+ static void NAME##_add_node_to_array (const void *nodep, const VISIT which, \
+ const int depth) \
+ { \
+ if (!NAME##_array_pos) \
+ return; \
+ switch (which) \
+ { \
+ case preorder: \
+ case endorder: \
+ break; \
+ case postorder: \
+ case leaf: \
+ *NAME##_array_pos = *(T *) nodep; \
+ NAME##_array_pos++; \
+ break; \
+ } \
+ } \
+ \
+ int NAME##_get_array (const NAME##_t *set, T **element) \
+ { \
+ if (!element) \
+ goto END; \
+ *element = calloc (set->size, sizeof (T)); \
+ if (!*element) \
+ return -1; \
+ NAME##_array_pos = *element; \
+ twalk (set->root, NAME##_add_node_to_array); \
+ NAME##_array_pos = NULL; \
+ END: \
+ return (int) (set->size); \
+ }
#endif /* UTIL_SET_H */
diff --git a/lib/includes/hicn/util/sstrncpy.h b/lib/includes/hicn/util/sstrncpy.h
new file mode 100644
index 000000000..b316201be
--- /dev/null
+++ b/lib/includes/hicn/util/sstrncpy.h
@@ -0,0 +1,68 @@
+/*
+ * 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 UTIL_SSTRNCPY_H
+#define UTIL_SSTRNCPY_H
+
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+
+#ifdef __STDC_LIB_EXT1__
+// If safe string functions already available in the system, use them
+#elif ENABLE_SAFEC
+// If safe string functions not available and SafeC is enabled,
+// use SafeC
+#include <safe_string.h>
+#else
+// Use custom safe string functions
+typedef int errno_t;
+#define EOK 0
+
+/**
+ * @brief This function assures a null byte at the end of the buffer.
+ */
+static inline errno_t
+strcpy_s (char *dst, size_t n, const char *src)
+{
+ if (!dst || !src || !n)
+ {
+ fprintf (stderr, "[strncpy] invalid input received");
+ return EINVAL;
+ }
+
+ dst[n - 1] = 0;
+ strncpy (dst, src, n);
+
+ if (dst[n - 1] != 0)
+ {
+ fprintf (stderr, "[strncpy] '%s' has been trucated\n", src);
+ dst[n - 1] = 0;
+ return EINVAL;
+ }
+
+ return EOK;
+}
+
+static inline size_t
+strnlen_s (const char *s, size_t maxlen)
+{
+ if (s == NULL)
+ return 0;
+
+ return strnlen (s, maxlen);
+}
+
+#endif /* __STDC_LIB_EXT1__ */
+#endif /* UTIL_SSTRNCPY_H */
diff --git a/lib/includes/hicn/util/token.h b/lib/includes/hicn/util/token.h
index 43e0a77b2..c62c294bc 100644
--- a/lib/includes/hicn/util/token.h
+++ b/lib/includes/hicn/util/token.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,12 +19,12 @@
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
-#define PPCAT_NX(A, B) A ## B
+#define PPCAT_NX(A, B) A##B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
-#define PPCAT(A, B) PPCAT_NX(A, B)
+#define PPCAT(A, B) PPCAT_NX (A, B)
/* Token stringification */
@@ -37,4 +37,4 @@
/*
* Turn A into a string literal after macro-expanding it.
*/
-#define STRINGIZE(A) STRINGIZE_NX(A)
+#define STRINGIZE(A) STRINGIZE_NX (A)
diff --git a/lib/includes/hicn/util/types.h b/lib/includes/hicn/util/types.h
index 017e85b72..50c5362d3 100644
--- a/lib/includes/hicn/util/types.h
+++ b/lib/includes/hicn/util/types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,15 +25,19 @@ typedef uint32_t u32;
typedef uint64_t u64;
/* Helper for avoiding warnings about type-punning */
-#define UNION_CAST(x, destType) \
- (((union {__typeof__(x) a; destType b;})x).b)
+#define UNION_CAST(x, destType) \
+ (((union { \
+ __typeof__ (x) a; \
+ destType b; \
+ }) x) \
+ .b)
-//typedef unsigned int hash_t;
+// typedef unsigned int hash_t;
-typedef int (*cmp_t)(const void *, const void *);
+typedef int (*cmp_t) (const void *, const void *);
/* Enums */
-#define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME ## _UNDEFINED) && (x < NAME ## _N))
+#define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME##_UNDEFINED) && (x < NAME##_N))
#endif /* UTIL_TYPES */
diff --git a/lib/includes/hicn/util/win_portability.h b/lib/includes/hicn/util/win_portability.h
index 5f30cfbb2..609203afc 100644
--- a/lib/includes/hicn/util/win_portability.h
+++ b/lib/includes/hicn/util/win_portability.h
@@ -1,45 +1,45 @@
-/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-#include <hicn/util/windows/windows_Utils.h>
-#include <afunix.h>
-#include <io.h>
-#include <iphlpapi.h>
-#include <process.h>
-#include <stdio.h>
-#pragma comment(lib, "IPHLPAPI.lib")
-
-#ifndef in_port_t
-#define in_port_t uint16_t
-#endif
-
-#ifndef in_addr_t
-#define in_addr_t uint32_t
-#endif
-
-#ifndef strncasecmp
-#define strncasecmp _strnicmp
-#endif
-
-#ifndef strcasecmp
-#define strcasecmp _stricmp
-#endif
-
-#define HAVE_STRUCT_TIMESPEC
-
-#ifndef getline
-int getline(char **lineptr, size_t *n, FILE *stream);
+/*
+ * 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/util/windows/windows_Utils.h>
+#include <afunix.h>
+#include <io.h>
+#include <iphlpapi.h>
+#include <process.h>
+#include <stdio.h>
+#pragma comment(lib, "IPHLPAPI.lib")
+
+#ifndef in_port_t
+#define in_port_t uint16_t
+#endif
+
+#ifndef in_addr_t
+#define in_addr_t uint32_t
+#endif
+
+#ifndef strncasecmp
+#define strncasecmp _strnicmp
+#endif
+
+#ifndef strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+#define HAVE_STRUCT_TIMESPEC
+
+#ifndef getline
+int getline (char **lineptr, size_t *n, FILE *stream);
#endif \ No newline at end of file
diff --git a/lib/includes/hicn/util/windows/dlfcn.h b/lib/includes/hicn/util/windows/dlfcn.h
index 7775226cd..f1457964e 100644
--- a/lib/includes/hicn/util/windows/dlfcn.h
+++ b/lib/includes/hicn/util/windows/dlfcn.h
@@ -5,8 +5,8 @@
#define RTLD_GLOBAL 0x100 /* do not hide entries in this module */
#define RTLD_LOCAL 0x000 /* hide entries in this module */
-#define RTLD_LAZY 0x000 /* accept unresolved externs */
-#define RTLD_NOW 0x001 /* abort if module has unresolved externs */
+#define RTLD_LAZY 0x000 /* accept unresolved externs */
+#define RTLD_NOW 0x001 /* abort if module has unresolved externs */
/*
How to call in Windows:
@@ -16,15 +16,16 @@
*/
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
- void *dlopen (const char *filename, int flag);
- int dlclose (void *handle);
+ void *dlopen (const char *filename, int flag);
+ int dlclose (void *handle);
- void *dlsym (void *handle, const char *name);
+ void *dlsym (void *handle, const char *name);
-const char *dlerror (void);
+ const char *dlerror (void);
#ifdef __cplusplus
}
diff --git a/lib/includes/hicn/util/windows/windows_utils.h b/lib/includes/hicn/util/windows/windows_utils.h
index d24aaadbf..e15c0d752 100755..100644
--- a/lib/includes/hicn/util/windows/windows_utils.h
+++ b/lib/includes/hicn/util/windows/windows_utils.h
@@ -1,162 +1,166 @@
-/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WINDOWS_UTILS_H
-#define WINDOWS_UTILS_H
-#define WIN32_LEAN_AND_MEAN
-#define HAVE_STRUCT_TIMESPEC
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <Windows.h>
-#include <stdint.h>
-#include <io.h>
-#include <stdlib.h>
-#include <winsock2.h>
-#include <WS2tcpip.h>
-#include "dlfcn.h"
-
-#ifndef IOVEC
-#define IOVEC
-struct iovec {
- void* iov_base;
- size_t iov_len;
-};
-#endif
-
-typedef uint16_t in_port_t;
-
-#ifndef SLEEP
-#define SLEEP
-#define sleep Sleep
-#endif
-
-#ifndef USLEEP
-#define USLEEP
-void usleep(__int64 usec);
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#endif
-
-#define PARCLibrary_DISABLE_ATOMICS
-#include <BaseTsd.h>
-typedef SSIZE_T ssize_t;
-
-#ifndef __ATTRIBUTE__
-#define __ATTRIBUTE__
-#define __attribute__(A)
-#endif
-
-#ifndef RESTRICT
-#define RESTRICT
-#define restrict __restrict
-#endif
-
-#ifndef GETTIMEOFDAY
-#define GETTIMEOFDAY
-int gettimeofday(struct timeval * tp, struct timezone * tzp);
-#endif
-
-#ifndef timersub
-#define timersub(a, b, result) \
- do { \
- (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
- (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
- if ((result)->tv_usec < 0) { \
- --(result)->tv_sec; \
- (result)->tv_usec += 1000000; \
- } \
- } while (0)
-#endif // timersub
-
-#ifndef dup
-#define dup _dup
-#endif
-
-#ifndef access
-#define access _access
-#endif
-
-#ifndef __cplusplus
-
-#ifndef read
-#define read _read
-#endif
-
-#ifndef close
-#define close _close
-#endif
-
-#ifndef write
-#define write _write
-#endif
-
-#ifndef open
-#define open _open
-#endif
-
-#endif
-
-#ifndef unlink
-#define unlink _unlink
-#endif
-
-#ifndef strcasecmp
-#define strncasecmp _strnicmp
-#endif
-
-#ifndef strcasecmp
-
-#define strcasecmp _stricmp
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-#ifndef R_OK
-#define R_OK 4 /* Test for read permission. */
-#endif
-#ifndef W_OK
-#define W_OK 2 /* Test for write permission. */
-#endif
-#ifndef F_OK
-#define F_OK 0
-#endif
-
-#ifndef STDIN_FILENO
-#define STDIN_FILENO _fileno(stdin)
-#endif
-
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO _fileno(stdout)
-#endif
-
-#ifndef STDERR_FILENO
-#define STDERR_FILENO _fileno(stderr)
-#endif
-
-#endif
-
-#ifndef __bswap_constant_32
-#define __bswap_constant_32(x) \
- ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \
- | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
-#endif
-
-#ifndef bzero
-#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+/*
+ * 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 WINDOWS_UTILS_H
+#define WINDOWS_UTILS_H
+#define WIN32_LEAN_AND_MEAN
+#define HAVE_STRUCT_TIMESPEC
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <Windows.h>
+#include <stdint.h>
+#include <io.h>
+#include <stdlib.h>
+#include <winsock2.h>
+#include <WS2tcpip.h>
+#include "dlfcn.h"
+
+#ifndef IOVEC
+#define IOVEC
+struct iovec
+{
+ void *iov_base;
+ size_t iov_len;
+};
+#endif
+
+typedef uint16_t in_port_t;
+
+#ifndef SLEEP
+#define SLEEP
+#define sleep Sleep
+#endif
+
+#ifndef USLEEP
+#define USLEEP
+void usleep (__int64 usec);
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode) &S_IFMT) == S_IFDIR)
+#endif
+
+#define PARCLibrary_DISABLE_ATOMICS
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+
+#ifndef __ATTRIBUTE__
+#define __ATTRIBUTE__
+#define __attribute__(A)
+#endif
+
+#ifndef RESTRICT
+#define RESTRICT
+#define restrict __restrict
+#endif
+
+#ifndef GETTIMEOFDAY
+#define GETTIMEOFDAY
+int gettimeofday (struct timeval *tp, struct timezone *tzp);
+#endif
+
+#ifndef timersub
+#define timersub(a, b, result) \
+ do \
+ { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) \
+ { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } \
+ while (0)
+#endif // timersub
+
+#ifndef dup
+#define dup _dup
+#endif
+
+#ifndef access
+#define access _access
+#endif
+
+#ifndef __cplusplus
+
+#ifndef read
+#define read _read
+#endif
+
+#ifndef close
+#define close _close
+#endif
+
+#ifndef write
+#define write _write
+#endif
+
+#ifndef open
+#define open _open
+#endif
+
+#endif
+
+#ifndef unlink
+#define unlink _unlink
+#endif
+
+#ifndef strcasecmp
+#define strncasecmp _strnicmp
+#endif
+
+#ifndef strcasecmp
+
+#define strcasecmp _stricmp
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG(mode) (((mode) &S_IFMT) == S_IFREG)
+#endif
+#ifndef R_OK
+#define R_OK 4 /* Test for read permission. */
+#endif
+#ifndef W_OK
+#define W_OK 2 /* Test for write permission. */
+#endif
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO _fileno (stdin)
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO _fileno (stdout)
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO _fileno (stderr)
+#endif
+
+#endif
+
+#ifndef __bswap_constant_32
+#define __bswap_constant_32(x) \
+ ((((x) &0xff000000u) >> 24) | (((x) &0x00ff0000u) >> 8) | \
+ (((x) &0x0000ff00u) << 8) | (((x) &0x000000ffu) << 24))
+#endif
+
+#ifndef bzero
+#define bzero(b, len) (memset ((b), '\0', (len)), (void) 0)
#endif \ No newline at end of file
diff --git a/lib/includes/hicn/validation.h b/lib/includes/hicn/validation.h
new file mode 100644
index 000000000..05be6d306
--- /dev/null
+++ b/lib/includes/hicn/validation.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file validation.h
+ * \brief Functions for input validation
+ */
+#include <ctype.h>
+#include <hicn/util/sstrncpy.h>
+
+static inline bool
+is_number (const char *string, size_t maxlen)
+{
+ size_t len = strnlen_s (string, maxlen);
+ for (size_t i = 0; i < len; i++)
+ {
+ if (!isdigit (string[i]))
+ return false;
+ }
+ return len != 0;
+}
+
+/**
+ * A symbolic name must be at least 1 character and must begin with an alpha.
+ * The remainder must be an alphanum.
+ */
+static inline bool
+is_symbolic_name (const char *name, size_t maxlen)
+{
+ size_t len = strnlen_s (name, maxlen);
+ if (len <= 0)
+ return false;
+ if (!isalpha (name[0]))
+ return false;
+
+ for (size_t i = 1; i < len; i++)
+ {
+ if (!isalnum (name[i]) && name[i] != '_' && name[i] != '-')
+ return false;
+ }
+
+ return true;
+}
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index 2588bde8b..ef74127cc 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,53 +11,117 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+##############################################################
+# Source and Header files
+##############################################################
list(APPEND LIBHICN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/common.c
- ${CMAKE_CURRENT_SOURCE_DIR}/compat.c
- ${CMAKE_CURRENT_SOURCE_DIR}/error.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mapme.c
- ${CMAKE_CURRENT_SOURCE_DIR}/name.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ops.c
- ${CMAKE_CURRENT_SOURCE_DIR}/policy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ah.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/icmp.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv4.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/ipv6.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol/tcp.c
- ${CMAKE_CURRENT_SOURCE_DIR}/util/ip_address.c
- ${CMAKE_CURRENT_SOURCE_DIR}/util/log.c
+ common.c
+ compat.c
+ error.c
+ face.c
+ mapme.c
+ name.c
+ ops.c
+ policy.c
+ strategy.c
+ protocol/ah.c
+ protocol/icmp.c
+ protocol/ipv4.c
+ protocol/ipv6.c
+ protocol/tcp.c
+ protocol/udp.c
+ protocol/new.c
+ util/ip_address.c
+ util/log.c
)
if (WIN32)
list(APPEND LIBHICN_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/util/windows/dlfcn.c
+ util/windows/dlfcn.c
)
endif ()
-set (COMPILER_DEFINITIONS "-DWITH_MAPME")
+
+##############################################################
+# Compiler definitions
+##############################################################
+set (COMPILER_DEFINITIONS
+ PUBLIC "-DWITH_MAPME"
+ PUBLIC "-DWITH_POLICY"
+)
include(BuildMacros)
include(WindowsMacros)
-if (DISABLE_SHARED_LIBRARIES)
- build_library(${LIBHICN}
- STATIC
- SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- COMPONENT lib${LIBHICN}
- INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
- DEFINITIONS ${COMPILER_DEFINITIONS}
- HEADER_ROOT_DIR hicn
- INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+##############################################################
+# Build type
+##############################################################
+set (BUILD_TYPES "STATIC")
+
+if (NOT DISABLE_SHARED_LIBRARIES)
+ list(APPEND BUILD_TYPES
+ "SHARED"
)
-else ()
- build_library(${LIBHICN}
- SHARED STATIC
- SOURCES ${LIBHICN_SOURCE_FILES} ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- COMPONENT lib${LIBHICN}
- INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
- DEFINITIONS ${COMPILER_DEFINITIONS}
- HEADER_ROOT_DIR hicn
- INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
- LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+endif()
+
+
+##############################################################
+# Compiler Options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Link libraries
+##############################################################
+if (WIN32)
+ list(APPEND LIBRARIES
+ PRIVATE ${WSOCK32_LIBRARY}
+ PRIVATE ${WS2_32_LIBRARY}
)
endif ()
+
+
+##############################################################
+# Build library
+##############################################################
+build_library(${LIBHICN}
+ ${BUILD_TYPES}
+ SOURCES ${LIBHICN_SOURCE_FILES}
+ COMPONENT ${LIBHICN_COMPONENT}
+ INCLUDE_DIRS
+ PUBLIC
+ $<BUILD_INTERFACE:${Libhicn_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<BUILD_INTERFACE:${THIRD_PARTY_INCLUDE_DIRS}>
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
+ DEPENDS ${THIRD_PARTY_DEPENDENCIES}
+ LINK_LIBRARIES
+ PRIVATE ${WSOCK32_LIBRARY}
+ PRIVATE ${WS2_32_LIBRARY}
+ PUBLIC ${THIRD_PARTY_LIBRARIES}
+ VERSION ${CURRENT_VERSION}
+ EXPORT_NAME ${LIBHICN_COMPONENT}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
+
+##############################################################
+# Unit tests
+##############################################################
+if (${BUILD_TESTS})
+ add_subdirectory(test)
+endif()
+
+
+##############################################################
+# Cmake config files
+##############################################################
+create_cmake_config (
+ ${LIBHICN_COMPONENT}
+ INCLUDE_DIRS ${HICN_INCLUDE_DIRS}
+ VERSION ${CURRENT_VERSION}
+ COMPONENT ${LIBHICN_COMPONENT}
+ NAMESPACE hicn
+)
diff --git a/lib/src/common.c b/lib/src/common.c
index 562771e09..c4cb8bc3e 100644
--- a/lib/src/common.c
+++ b/lib/src/common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,8 +20,8 @@
*/
#include <stdlib.h>
-#include <string.h> // memset
-#include <sys/types.h> // getaddrinfo
+#include <string.h> // memset
+#include <sys/types.h> // getaddrinfo
#ifndef _WIN32
#include <sys/socket.h>
#include <netdb.h>
@@ -31,8 +31,6 @@
#include <hicn/common.h>
#include <hicn/util/log.h>
-
-
int
get_addr_family (const char *ip_address)
{
@@ -59,7 +57,8 @@ get_addr_family (const char *ip_address)
u32
cumulative_hash32 (const void *data, size_t len, u32 lastValue)
{
- // Standard FNV 32-bit prime: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ // 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;
@@ -78,7 +77,8 @@ cumulative_hash32 (const void *data, size_t len, u32 lastValue)
u32
hash32 (const void *data, size_t len)
{
- // Standard FNV 32-bit offset: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ // 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);
}
@@ -86,7 +86,8 @@ hash32 (const void *data, size_t len)
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
+ // 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;
@@ -104,13 +105,14 @@ cumulative_hash64 (const void *data, size_t len, u64 lastValue)
u64
hash64 (const void *data, size_t len)
{
- // Standard FNV 64-bit offset: see http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
+ // 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);
}
void
-hicn_packet_dump (const uint8_t * buffer, size_t len)
+hicn_packet_dump (const uint8_t *buffer, size_t len)
{
int i;
unsigned char buff[17];
diff --git a/lib/src/compat.c b/lib/src/compat.c
index 932c11d9e..cb771dbdd 100644
--- a/lib/src/compat.c
+++ b/lib/src/compat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -51,6 +51,12 @@ hicn_packet_get_format (const hicn_header_t *h, hicn_format_t *format)
else
*format = HF_INET_TCP;
break;
+ case IPPROTO_UDP:
+ if (h->v4.newhdr.flags & HICN_NEW_FLAG_SIG)
+ *format = HF_INET_UDP_AH;
+ else
+ *format = HF_INET_UDP;
+ break;
case IPPROTO_ICMP:
*format = HF_INET_ICMP;
break;
@@ -67,6 +73,12 @@ hicn_packet_get_format (const hicn_header_t *h, hicn_format_t *format)
else
*format = HF_INET6_TCP;
break;
+ case IPPROTO_UDP:
+ if (h->v6.newhdr.flags & HICN_NEW_FLAG_SIG)
+ *format = HF_INET6_UDP_AH;
+ else
+ *format = HF_INET6_UDP;
+ break;
case IPPROTO_ICMPV6:
*format = HF_INET6_ICMP;
break;
@@ -74,6 +86,12 @@ hicn_packet_get_format (const hicn_header_t *h, hicn_format_t *format)
return HICN_LIB_ERROR_NOT_HICN;
}
break;
+ case 9:
+ {
+ uint8_t ah = (HICN_NEW_FLAG_SIG & h->protocol.newhdr.flags);
+ *format = HF_NEW_AH * ah + (1 - ah) * HF_NEW;
+ break;
+ }
default:
return HICN_LIB_ERROR_NOT_HICN;
}
@@ -93,20 +111,32 @@ hicn_format_to_type (hicn_format_t format)
{
case HF_INET_TCP:
return HICN_TYPE_IPV4_TCP;
+ case HF_INET_UDP:
+ return HICN_TYPE_IPV4_UDP;
case HF_INET6_TCP:
return HICN_TYPE_IPV6_TCP;
+ case HF_INET6_UDP:
+ return HICN_TYPE_IPV6_UDP;
case HF_INET_ICMP:
return HICN_TYPE_IPV4_ICMP;
case HF_INET6_ICMP:
return HICN_TYPE_IPV6_ICMP;
+ case HF_NEW:
+ return HICN_TYPE_NEW;
case HF_INET_TCP_AH:
return HICN_TYPE_IPV4_TCP_AH;
+ case HF_INET_UDP_AH:
+ return HICN_TYPE_IPV4_UDP_AH;
case HF_INET6_TCP_AH:
return HICN_TYPE_IPV6_TCP_AH;
+ case HF_INET6_UDP_AH:
+ return HICN_TYPE_IPV6_UDP_AH;
case HF_INET_ICMP_AH:
return HICN_TYPE_IPV4_ICMP_AH;
case HF_INET6_ICMP_AH:
return HICN_TYPE_IPV6_ICMP_AH;
+ case HF_NEW_AH:
+ return HICN_TYPE_NEW_AH;
default:
break;
}
@@ -176,6 +206,8 @@ hicn_packet_get_header_length_from_format (hicn_format_t format,
*header_length += _is_ipv6 (format) * IPV6_HDRLEN;
*header_length += _is_icmp (format) * ICMP_HDRLEN;
*header_length += _is_tcp (format) * TCP_HDRLEN;
+ *header_length += _is_udp (format) * UDP_HDRLEN;
+ *header_length += _is_cmpr (format) * NEW_HDRLEN;
*header_length += _is_ah (format) * AH_HDRLEN;
return HICN_LIB_ERROR_NONE;
@@ -185,17 +217,9 @@ int
hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t *h,
size_t *header_length)
{
- hicn_packet_get_header_length_from_format (format, header_length);
- int is_ah = _is_ah (format);
- int is_ipv4 = _is_ipv4 (format);
- int is_ipv6 = _is_ipv6 (format);
- // The signature payload is expressed as number of 32 bits words
- if (is_ah && is_ipv4)
- *header_length += (h->v4ah.ah.payloadlen) << 2;
- else if (is_ah && is_ipv6)
- *header_length += (h->v6ah.ah.payloadlen) << 2;
-
- return HICN_LIB_ERROR_NONE;
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
+ header_length);
}
int
@@ -261,11 +285,6 @@ hicn_packet_set_name (hicn_format_t format, hicn_header_t *h,
{
hicn_type_t type = hicn_format_to_type (format);
-#ifndef HICN_VPP_PLUGIN
- if (name->type & HNT_IOV)
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-#endif /* HICN_VPP_PLUGIN */
-
if (is_interest)
return hicn_ops_vft[type.l1]->set_interest_name (type, &h->protocol, name);
else
@@ -325,54 +344,26 @@ int
hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *h,
ip_address_t *address, bool is_interest)
{
- int is_ipv4 = (format & HFO_INET);
- int is_ipv6 = (format & HFO_INET6) >> 1;
-
- if (is_ipv4)
- {
- address->v4.as_inaddr =
- is_interest ? h->v4.ip.saddr.as_inaddr : h->v4.ip.daddr.as_inaddr;
- }
- else if (is_ipv6)
- {
- address->v6.as_in6addr =
- is_interest ? h->v6.ip.saddr.as_in6addr : h->v6.ip.daddr.as_in6addr;
- }
+ hicn_type_t type = hicn_format_to_type (format);
+ if (is_interest)
+ return hicn_ops_vft[type.l1]->get_interest_locator (type, &h->protocol,
+ address);
else
- {
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
- return HICN_LIB_ERROR_NONE;
+ return hicn_ops_vft[type.l1]->get_data_locator (type, &h->protocol,
+ address);
}
int
hicn_packet_set_locator (hicn_format_t format, hicn_header_t *h,
const ip_address_t *address, bool is_interest)
{
- int is_ipv4 = (format & HFO_INET);
- int is_ipv6 = (format & HFO_INET6) >> 1;
-
- if (is_ipv6)
- {
- if (is_interest)
- h->v6.ip.saddr.as_in6addr = address->v6.as_in6addr;
- else
- h->v6.ip.daddr.as_in6addr = address->v6.as_in6addr;
- }
- else if (is_ipv4)
- {
- if (is_interest)
- h->v4.ip.saddr.as_inaddr = address->v4.as_inaddr;
- else
- h->v4.ip.daddr.as_inaddr = address->v4.as_inaddr;
- }
+ hicn_type_t type = hicn_format_to_type (format);
+ if (is_interest)
+ return hicn_ops_vft[type.l1]->set_interest_locator (type, &h->protocol,
+ address);
else
- {
- return HICN_LIB_ERROR_INVALID_PARAMETER;
- }
-
- return HICN_LIB_ERROR_NONE;
+ return hicn_ops_vft[type.l1]->set_data_locator (type, &h->protocol,
+ address);
}
int
@@ -392,19 +383,21 @@ hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t *h,
}
int
-hicn_packet_get_signature_gap (hicn_format_t format, const hicn_header_t *h,
- uint8_t *bytes)
+hicn_packet_get_signature_padding (hicn_format_t format,
+ const hicn_header_t *h, size_t *bytes)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature_gap (type, &h->protocol, bytes);
+ return hicn_ops_vft[type.l1]->get_signature_padding (type, &h->protocol,
+ bytes);
}
int
-hicn_packet_set_signature_gap (hicn_format_t format, hicn_header_t *h,
- uint8_t bytes)
+hicn_packet_set_signature_padding (hicn_format_t format, hicn_header_t *h,
+ size_t bytes)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_signature_gap (type, &h->protocol, bytes);
+ return hicn_ops_vft[type.l1]->set_signature_padding (type, &h->protocol,
+ bytes);
}
int
@@ -499,7 +492,30 @@ hicn_packet_set_hoplimit (hicn_header_t *h, u8 hops)
}
int
-hicn_packet_get_lifetime (const hicn_header_t *h, u32 *lifetime)
+hicn_packet_is_interest (hicn_format_t format, const hicn_header_t *h,
+ int *ret)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->is_interest (type, &h->protocol, ret);
+}
+
+int
+hicn_packet_set_interest (hicn_format_t format, hicn_header_t *h)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->mark_packet_as_interest (type, &h->protocol);
+}
+
+int
+hicn_packet_set_data (hicn_format_t format, hicn_header_t *h)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->mark_packet_as_data (type, &h->protocol);
+}
+
+int
+hicn_packet_get_lifetime (hicn_format_t format, const hicn_header_t *h,
+ u32 *lifetime)
{
hicn_type_t type = hicn_header_to_type (h);
return hicn_ops_vft[type.l1]->get_lifetime (type, &h->protocol,
@@ -507,7 +523,7 @@ hicn_packet_get_lifetime (const hicn_header_t *h, u32 *lifetime)
}
int
-hicn_packet_set_lifetime (hicn_header_t *h, u32 lifetime)
+hicn_packet_set_lifetime (hicn_format_t format, hicn_header_t *h, u32 lifetime)
{
hicn_type_t type = hicn_header_to_type (h);
return hicn_ops_vft[type.l1]->set_lifetime (type, &h->protocol,
@@ -551,59 +567,21 @@ hicn_packet_set_reserved_bits (hicn_header_t *h, const u8 reserved_bits)
}
int
-hicn_packet_get_payload_type (const hicn_header_t *h,
+hicn_packet_get_payload_type (hicn_format_t format, const hicn_header_t *h,
hicn_payload_type_t *payload_type)
{
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- *payload_type =
- ((h->v6.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
- break;
- case 4:
- *payload_type =
- ((h->v4.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- if (*payload_type == HPT_UNSPEC)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
+ hicn_type_t type = hicn_header_to_type (h);
+ return hicn_ops_vft[type.l1]->get_payload_type (type, &h->protocol,
+ payload_type);
}
int
-hicn_packet_set_payload_type (hicn_header_t *h,
+hicn_packet_set_payload_type (hicn_format_t format, hicn_header_t *h,
hicn_payload_type_t payload_type)
{
- if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- switch (HICN_IP_VERSION (h))
- {
- case 6:
- if (payload_type)
- h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_URG;
- else
- h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_URG;
- break;
- case 4:
- if (payload_type)
- h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_URG;
- else
- h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_URG;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- return HICN_LIB_ERROR_NONE;
+ hicn_type_t type = hicn_header_to_type (h);
+ return hicn_ops_vft[type.l1]->set_payload_type (type, &h->protocol,
+ payload_type);
}
int
@@ -1057,10 +1035,6 @@ int
hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest,
const hicn_name_t *name)
{
- int ret_err = hicn_packet_reset_ece (
- format, interest); // interest packet -> ece flag unset
- if (ret_err < 0)
- return HICN_LIB_ERROR_UNEXPECTED;
return hicn_packet_set_name (format, interest, name, _INTEREST);
}
@@ -1088,13 +1062,25 @@ hicn_interest_compare (const hicn_header_t *interest_1,
int
hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime)
{
- return hicn_packet_get_lifetime (interest, lifetime);
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (interest, &format);
+
+ if (rc)
+ return rc;
+
+ return hicn_packet_get_lifetime (format, interest, lifetime);
}
int
hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime)
{
- return hicn_packet_set_lifetime (interest, lifetime);
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (interest, &format);
+
+ if (rc)
+ return rc;
+
+ return hicn_packet_set_lifetime (format, interest, lifetime);
}
int
@@ -1150,10 +1136,6 @@ int
hicn_data_set_name (hicn_format_t format, hicn_header_t *data,
const hicn_name_t *name)
{
- int ret_err =
- hicn_packet_set_ece (format, data); // data packet -> ece flag set
- if (ret_err < 0)
- return HICN_LIB_ERROR_UNEXPECTED;
return hicn_packet_set_name (format, data, name, _DATA);
}
@@ -1180,13 +1162,26 @@ hicn_data_compare (const hicn_header_t *data_1, const hicn_header_t *data_2)
int
hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time)
{
- return hicn_packet_get_lifetime (data, expiry_time);
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (data, &format);
+
+ if (rc)
+ return rc;
+
+ return hicn_packet_get_lifetime (format, data, expiry_time);
}
int
hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time)
{
- return hicn_packet_set_lifetime (data, (hicn_lifetime_t) expiry_time);
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (data, &format);
+
+ if (rc)
+ return rc;
+
+ return hicn_packet_set_lifetime (format, data,
+ (hicn_lifetime_t) expiry_time);
}
int
@@ -1204,20 +1199,6 @@ hicn_data_get_payload_length (hicn_format_t format, const hicn_header_t *data,
}
int
-hicn_data_set_payload_type (hicn_header_t *data,
- hicn_payload_type_t payload_type)
-{
- return hicn_packet_set_payload_type (data, payload_type);
-}
-
-int
-hicn_data_get_payload_type (const hicn_header_t *data,
- hicn_payload_type_t *payload_type)
-{
- return hicn_packet_get_payload_type (data, payload_type);
-}
-
-int
hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label)
{
hicn_type_t type = hicn_header_to_type (data);
@@ -1256,6 +1237,20 @@ hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet)
}
int
+hicn_data_is_last (hicn_format_t format, hicn_header_t *h, int *is_last)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->is_last_data (type, &h->protocol, is_last);
+}
+
+int
+hicn_data_set_last (hicn_format_t format, hicn_header_t *h)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_last_data (type, &h->protocol);
+}
+
+int
hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet,
uint8_t **sign_buf)
{
diff --git a/lib/src/error.c b/lib/src/error.c
index ab5d6e27d..0d7c80d9b 100644
--- a/lib/src/error.c
+++ b/lib/src/error.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,7 +21,7 @@
#include <hicn/error.h>
const char *HICN_LIB_ERROR_STRING[] = {
-#define _(a,b,c) [b] = c,
+#define _(a, b, c) [b] = c,
foreach_libhicn_error
#undef _
};
diff --git a/lib/src/face.c b/lib/src/face.c
new file mode 100644
index 000000000..46b36e8cd
--- /dev/null
+++ b/lib/src/face.c
@@ -0,0 +1,451 @@
+/*
+ * 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 face.c
+ * \brief Implementation of face abstraction
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <hicn/face.h>
+#include <hicn/util/token.h>
+
+#define member_size(type, member) sizeof (((type *) 0)->member)
+
+/* Netdevice */
+
+const char *_netdevice_type_str[] = {
+#define _(x) [NETDEVICE_TYPE_##x] = STRINGIZE (x),
+ foreach_netdevice_type
+#undef _
+};
+
+netdevice_t *
+netdevice_create_from_index (u32 index)
+{
+ netdevice_t *netdevice = malloc (sizeof (netdevice_t));
+ if (!netdevice)
+ goto ERR_MALLOC;
+
+ int rc = netdevice_set_index (netdevice, index);
+ if (rc < 0)
+ goto ERR_INIT;
+
+ return netdevice;
+
+ERR_INIT:
+ free (netdevice);
+ERR_MALLOC:
+ return NULL;
+}
+
+netdevice_t *
+netdevice_create_from_name (const char *name)
+{
+ netdevice_t *netdevice = malloc (sizeof (netdevice_t));
+ if (!netdevice)
+ goto ERR_MALLOC;
+
+ int rc = netdevice_set_name (netdevice, name);
+ if (rc < 0)
+ goto ERR_INIT;
+
+ return netdevice;
+
+ERR_INIT:
+ free (netdevice);
+ERR_MALLOC:
+ return NULL;
+}
+
+/**
+ * \brief Update the index of the netdevice based on the name
+ */
+int
+netdevice_update_index (netdevice_t *netdevice)
+{
+ netdevice->index = if_nametoindex (netdevice->name);
+ if (netdevice->index == 0)
+ return -1;
+ return 0;
+}
+
+int
+netdevice_update_name (netdevice_t *netdevice)
+{
+ if (!if_indextoname (netdevice->index, netdevice->name))
+ return -1;
+ return 0;
+}
+
+void
+netdevice_free (netdevice_t *netdevice)
+{
+ free (netdevice);
+}
+
+int
+netdevice_get_index (const netdevice_t *netdevice, u32 *index)
+{
+ if (netdevice->index == 0)
+ return -1;
+ *index = netdevice->index;
+ return 0;
+}
+
+int
+netdevice_set_index (netdevice_t *netdevice, u32 index)
+{
+ netdevice->index = index;
+ return netdevice_update_name (netdevice);
+}
+
+int
+netdevice_get_name (const netdevice_t *netdevice, const char **name)
+{
+ if (netdevice->name[0] == '\0')
+ return -1;
+ *name = netdevice->name;
+ return 0;
+}
+
+int
+netdevice_set_name (netdevice_t *netdevice, const char *name)
+{
+ memset (netdevice->name, 0, sizeof (netdevice->name));
+ int rc = snprintf (netdevice->name, IFNAMSIZ, "%s", name);
+ if (rc < 0)
+ return -1;
+ if (rc >= IFNAMSIZ)
+ return -2; /* truncated */
+ return netdevice_update_index (netdevice);
+}
+
+int
+netdevice_cmp (const netdevice_t *nd1, const netdevice_t *nd2)
+{
+ return (nd1->index - nd2->index);
+}
+
+/* Face state */
+
+const char *_face_state_str[] = {
+#define _(x) [FACE_STATE_##x] = STRINGIZE (x),
+ foreach_face_state
+#undef _
+};
+
+/* Face type */
+
+const char *_face_type_str[] = {
+#define _(x) [FACE_TYPE_##x] = STRINGIZE (x),
+ foreach_face_type
+#undef _
+};
+
+face_type_t
+face_type_from_str (const char *str)
+{
+#define _(x) \
+ if (strcasecmp (str, STRINGIZE (x)) == 0) \
+ return FACE_TYPE_##x; \
+ else
+ foreach_face_type
+#undef _
+ return FACE_TYPE_UNDEFINED;
+}
+
+/* Face */
+
+int
+face_initialize (face_t *face)
+{
+ memset (face, 0, sizeof (face_t)); /* 0'ed for hash */
+ return 1;
+}
+
+int
+face_initialize_udp (face_t *face, const char *interface_name,
+ const ip_address_t *local_addr, u16 local_port,
+ const ip_address_t *remote_addr, u16 remote_port,
+ int family)
+{
+ if (!local_addr)
+ return -1;
+
+ *face = (face_t){
+ .type = FACE_TYPE_UDP,
+ .family = family,
+ .local_addr = *local_addr,
+ .local_port = local_port,
+ .remote_addr = remote_addr ? *remote_addr : IP_ADDRESS_EMPTY,
+ .remote_port = remote_port,
+ };
+
+ snprintf (face->netdevice.name, IFNAMSIZ, "%s", interface_name);
+
+ return 1;
+}
+
+int
+face_initialize_udp_sa (face_t *face, const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr)
+{
+ if (!local_addr)
+ return -1;
+
+ if (remote_addr && (local_addr->sa_family != remote_addr->sa_family))
+ return -1;
+
+ switch (local_addr->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *lsai = (struct sockaddr_in *) local_addr;
+ struct sockaddr_in *rsai = (struct sockaddr_in *) remote_addr;
+ *face = (face_t){
+ .type = FACE_TYPE_UDP,
+ .family = AF_INET,
+ .local_addr.v4.as_inaddr = lsai->sin_addr,
+ .local_port = lsai ? ntohs (lsai->sin_port) : 0,
+ .remote_addr = IP_ADDRESS_EMPTY,
+ .remote_port = rsai ? ntohs (rsai->sin_port) : 0,
+ };
+ if (rsai)
+ face->remote_addr.v4.as_inaddr = rsai->sin_addr;
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *lsai = (struct sockaddr_in6 *) local_addr;
+ struct sockaddr_in6 *rsai = (struct sockaddr_in6 *) remote_addr;
+ *face = (face_t){
+ .type = FACE_TYPE_UDP,
+ .family = AF_INET6,
+ .local_addr.v6.as_in6addr = lsai->sin6_addr,
+ .local_port = lsai ? ntohs (lsai->sin6_port) : 0,
+ .remote_addr = IP_ADDRESS_EMPTY,
+ .remote_port = rsai ? ntohs (rsai->sin6_port) : 0,
+ };
+ if (rsai)
+ face->remote_addr.v6.as_in6addr = rsai->sin6_addr;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ snprintf (face->netdevice.name, IFNAMSIZ, "%s", interface_name);
+
+ return 1;
+}
+
+face_t *
+face_create ()
+{
+ face_t *face = calloc (1, sizeof (face_t)); /* 0'ed for hash */
+ return face;
+}
+
+face_t *
+face_create_udp (const char *interface_name, const ip_address_t *local_addr,
+ u16 local_port, const ip_address_t *remote_addr,
+ u16 remote_port, int family)
+{
+ face_t *face = face_create ();
+ if (face_initialize_udp (face, interface_name, local_addr, local_port,
+ remote_addr, remote_port, family) < 0)
+ goto ERR_INIT;
+ return face;
+
+ERR_INIT:
+ free (face);
+ return NULL;
+}
+
+face_t *
+face_create_udp_sa (const char *interface_name,
+ const struct sockaddr *local_addr,
+ const struct sockaddr *remote_addr)
+{
+ face_t *face = face_create ();
+ if (face_initialize_udp_sa (face, interface_name, local_addr, remote_addr) <
+ 0)
+ goto ERR_INIT;
+ return face;
+
+ERR_INIT:
+ free (face);
+ return NULL;
+}
+
+void
+face_free (face_t *face)
+{
+ free (face);
+}
+
+/**
+ * \brief Compare two faces
+ * \param [in] f1 - First face
+ * \param [in] f2 - Second face
+ * \return whether faces are equal, ie both their types are parameters are
+ * equal.
+ *
+ * NOTE: this function implements a partial order.
+ */
+int
+face_cmp (const face_t *f1, const face_t *f2)
+{
+
+ int ret = f1->type - f2->type;
+ if (ret != 0)
+ return ret;
+
+ ret = f1->family - f2->family;
+ if (ret != 0)
+ return ret;
+
+ /*
+ * FIXME As hicn-light API might not return the netdevice, we can discard the
+ * comparison when one of the two is not set for now...
+ */
+ if ((f1->netdevice.index != 0) && (f2->netdevice.index != 0))
+ {
+ ret = netdevice_cmp (&f1->netdevice, &f2->netdevice);
+ if (ret != 0)
+ return ret;
+ }
+
+ switch (f1->type)
+ {
+ case FACE_TYPE_HICN:
+ ret = ip_address_cmp (&f1->local_addr, &f2->local_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ ret = ip_address_cmp (&f1->remote_addr, &f2->remote_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ break;
+
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ ret = ip_address_cmp (&f1->local_addr, &f2->local_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ ret = f1->local_port - f2->local_port;
+ if (ret != 0)
+ return ret;
+
+ ret = ip_address_cmp (&f1->remote_addr, &f2->remote_addr, f1->family);
+ if (ret != 0)
+ return ret;
+
+ ret = f1->remote_port - f2->remote_port;
+ if (ret != 0)
+ return ret;
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* /!\ Please update constants in header file upon changes */
+size_t
+face_snprintf (char *s, size_t size, const face_t *face)
+{
+ switch (face->type)
+ {
+ case FACE_TYPE_HICN:
+ {
+ char local[MAXSZ_IP_ADDRESS];
+ char remote[MAXSZ_IP_ADDRESS];
+ char tags[MAXSZ_POLICY_TAGS];
+
+ ip_address_snprintf (local, MAXSZ_IP_ADDRESS, &face->local_addr,
+ face->family);
+ ip_address_snprintf (remote, MAXSZ_IP_ADDRESS, &face->remote_addr,
+ face->family);
+ policy_tags_snprintf (tags, MAXSZ_POLICY_TAGS, face->tags);
+ return snprintf (s, size, "%s [%s -> %s] [%s]",
+ face_type_str (face->type), local, remote, tags);
+ }
+ case FACE_TYPE_UNDEFINED:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ {
+ char local[MAXSZ_IP_ADDRESS];
+ char remote[MAXSZ_IP_ADDRESS];
+ char tags[MAXSZ_POLICY_TAGS];
+
+ ip_address_snprintf (local, MAXSZ_IP_ADDRESS, &face->local_addr,
+ face->family);
+ ip_address_snprintf (remote, MAXSZ_IP_ADDRESS, &face->remote_addr,
+ face->family);
+ policy_tags_snprintf (tags, MAXSZ_POLICY_TAGS, face->tags);
+
+ return snprintf (s, size, "%s [%s:%d -> %s:%d] [%s]",
+ face_type_str (face->type), local, face->local_port,
+ remote, face->remote_port, tags);
+ }
+ default:
+ return -1;
+ }
+}
+
+policy_tags_t
+face_get_tags (const face_t *face)
+{
+ return face->tags;
+}
+
+int
+face_set_tags (face_t *face, policy_tags_t tags)
+{
+ face->tags = tags;
+ return 1;
+}
+
+face_protocol_t
+get_protocol (face_type_t face_type)
+{
+ switch (face_type)
+ {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ return FACE_PROTOCOL_HICN;
+
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_TCP_LISTENER:
+ return FACE_PROTOCOL_TCP;
+
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_UDP_LISTENER:
+ return FACE_PROTOCOL_UDP;
+
+ default:
+ return FACE_PROTOCOL_UNKNOWN;
+ }
+}
diff --git a/lib/src/libhicn-config.cmake.in b/lib/src/libhicn-config.cmake.in
new file mode 100644
index 000000000..1ae219280
--- /dev/null
+++ b/lib/src/libhicn-config.cmake.in
@@ -0,0 +1,12 @@
+set(Libhicn_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@")
+
+@PACKAGE_INIT@
+
+set(Libhicn_VERSION_MAJOR "@VERSION_MAJOR@")
+set(Libhicn_VERSION_MINOR "@VERSION_MINOR@")
+set(Libhicn_VERSION_PATCH "@VERSION_PATCH@")
+
+set_and_check(Libhicn_INCLUDE_DIRS "@PACKAGE_Libhicn_INCLUDE_DIRS@")
+include("${CMAKE_CURRENT_LIST_DIR}/libhicn-targets.cmake")
+
+check_required_components(Libhicn)
diff --git a/lib/src/mapme.c b/lib/src/mapme.c
index 3e7e8bc80..b8e8eaed2 100644
--- a/lib/src/mapme.c
+++ b/lib/src/mapme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,8 +26,8 @@
#include <hicn/protocol/ipv6.h>
size_t
-hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params)
+hicn_mapme_v4_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params)
{
hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf;
/* *INDENT-OFF* */
@@ -41,14 +41,14 @@ hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
.ttl = HICN_MAPME_TTL,
.protocol = IPPROTO_ICMP,
.csum = 0,
- .saddr.as_u32 = 0,
- .daddr = prefix->name.ip4,
+ .saddr.as_u32 = IPV4_LOOPBACK.v4.as_u32,
+ .daddr = prefix->name.v4,
},
.icmp_rd = {
.type = ((params->type == UPDATE) || (params->type == NOTIFICATION)) ? HICN_MAPME_ICMP_TYPE_IPV4 : HICN_MAPME_ICMP_TYPE_ACK_IPV4,
.code = HICN_MAPME_ICMP_CODE,
.csum = 0,
- .ip = prefix->name.ip4,
+ .ip = prefix->name.v4,
},
.seq = htonl(params->seq),
.len = prefix->len,
@@ -59,15 +59,15 @@ hicn_mapme_v4_create_packet (u8 * buf, const hicn_prefix_t * prefix,
}
size_t
-hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params)
+hicn_mapme_v6_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params)
{
hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf;
/* *INDENT-OFF* */
*mh = (hicn_mapme_v6_header_t) {
.ip = {
- .saddr = {{0}},
- .daddr = prefix->name.ip6,
+ .saddr = IPV6_LOOPBACK.v6,
+ .daddr = prefix->name.v6,
.version_class_flow = htonl(
(IPV6_DEFAULT_VERSION << 28) |
(IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
@@ -81,8 +81,8 @@ hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
.code = HICN_MAPME_ICMP_CODE,
.csum = 0,
.res = 0,
- .tgt = prefix->name.ip6,
- .dst = prefix->name.ip6,
+ .tgt = prefix->name.v6,
+ .dst = prefix->name.v6,
},
.seq = htonl(params->seq),
.len = prefix->len,
@@ -92,8 +92,8 @@ hicn_mapme_v6_create_packet (u8 * buf, const hicn_prefix_t * prefix,
}
size_t
-hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
- const mapme_params_t * params)
+hicn_mapme_create_packet (u8 *buf, const hicn_prefix_t *prefix,
+ const mapme_params_t *params)
{
/* We currently ignore subsequent protocol definitions */
if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6))
@@ -103,9 +103,9 @@ hicn_mapme_create_packet (u8 * buf, const hicn_prefix_t * prefix,
}
size_t
-hicn_mapme_v4_create_ack (u8 * buf, const mapme_params_t * params)
+hicn_mapme_v4_create_ack (u8 *buf, const mapme_params_t *params)
{
- ip4_address_t tmp; // tmp storage for swapping IP addresses for ACK
+ ip4_address_t tmp; // tmp storage for swapping IP addresses for ACK
hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf;
tmp = mh->ip.daddr;
@@ -119,9 +119,9 @@ hicn_mapme_v4_create_ack (u8 * buf, const mapme_params_t * params)
}
size_t
-hicn_mapme_v6_create_ack (u8 * buf, const mapme_params_t * params)
+hicn_mapme_v6_create_ack (u8 *buf, const mapme_params_t *params)
{
- ip6_address_t tmp; // tmp storage for swapping IP addresses for ACK
+ ip6_address_t tmp; // tmp storage for swapping IP addresses for ACK
hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf;
tmp = mh->ip.daddr;
@@ -135,7 +135,7 @@ hicn_mapme_v6_create_ack (u8 * buf, const mapme_params_t * params)
}
size_t
-hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params)
+hicn_mapme_create_ack (u8 *buf, const mapme_params_t *params)
{
/* We currently ignore subsequent protocol definitions */
if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6))
@@ -145,22 +145,23 @@ hicn_mapme_create_ack (u8 * buf, const mapme_params_t * params)
}
int
-hicn_mapme_v4_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params)
+hicn_mapme_v4_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params)
{
hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) packet;
/* *INDENT-OFF* */
*prefix = (hicn_prefix_t) {
.name = {
- .ip4 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
+ .v4 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
},
.len = mh->len,
};
- *params = (mapme_params_t) {
+ *params = (mapme_params_t){
.protocol = IPPROTO_IP,
- .type = (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV4) ? UPDATE : UPDATE_ACK,
+ .type =
+ (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV4) ? UPDATE : UPDATE_ACK,
.seq = ntohl (mh->seq),
};
/* *INDENT-ON* */
@@ -169,22 +170,23 @@ hicn_mapme_v4_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
}
int
-hicn_mapme_v6_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params)
+hicn_mapme_v6_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params)
{
hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) packet;
/* *INDENT-OFF* */
*prefix = (hicn_prefix_t) {
.name = {
- .ip6 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
+ .v6 = HICN_MAPME_TYPE_IS_IU (mh->icmp_rd.type) ? mh->ip.daddr : mh->ip.saddr,
},
.len = mh->len,
};
- *params = (mapme_params_t) {
+ *params = (mapme_params_t){
.protocol = IPPROTO_IPV6,
- .type = (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV6) ? UPDATE : UPDATE_ACK,
+ .type =
+ (mh->icmp_rd.type == HICN_MAPME_ICMP_TYPE_IPV6) ? UPDATE : UPDATE_ACK,
.seq = ntohl (mh->seq),
};
/* *INDENT-ON* */
@@ -193,8 +195,8 @@ hicn_mapme_v6_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
}
int
-hicn_mapme_parse_packet (const u8 * packet, hicn_prefix_t * prefix,
- mapme_params_t * params)
+hicn_mapme_parse_packet (const u8 *packet, hicn_prefix_t *prefix,
+ mapme_params_t *params)
{
switch (HICN_IP_VERSION (packet))
{
diff --git a/lib/src/name.c b/lib/src/name.c
index 54b2a76aa..3bdcbbdb4 100644
--- a/lib/src/name.c
+++ b/lib/src/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,522 +19,210 @@
*/
#ifndef _WIN32
-#include <arpa/inet.h> // inet_ptin
+#include <arpa/inet.h> // inet_ptin
#endif
#include <errno.h>
#include <stdio.h>
-#include <stdlib.h> // strtoul
-#include <string.h> // memcpy
+#include <stdlib.h> // strtoul
+#include <string.h> // memcpy
#include <hicn/common.h>
#include <hicn/error.h>
#include <hicn/name.h>
+#include <hicn/util/sstrncpy.h>
-#if ! HICN_VPP_PLUGIN
int
-hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name)
+hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name)
{
int af, rc;
- af = get_addr_family (ip_address);
-
- switch (af)
- {
- case AF_INET:
- if (name->type == HNT_UNSPEC)
- {
- name->type = HNT_CONTIGUOUS_V4;
- }
- name->len = IPV4_ADDR_LEN;
- break;
- case AF_INET6:
- if (name->type == HNT_UNSPEC)
- {
- name->type = HNT_CONTIGUOUS_V6;
- }
- name->len = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
+ memset (name, 0, sizeof (hicn_name_t));
- if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6))
- {
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+ af = get_addr_family (ip_address);
+ int v4 = (af == AF_INET);
+ u8 *dst = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) +
+ (1 - v4) * (intptr_t) (name->prefix.v6.as_u8));
+ rc = inet_pton (af, ip_address, dst);
- rc = inet_pton (af, ip_address, name->buffer);
- if (rc <= 0)
+ if (rc != 1)
{
return HICN_LIB_ERROR_UNKNOWN_ADDRESS;
}
- *(u32 *) (name->buffer + name->len) = id;
+
+ name->suffix = id;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id,
- hicn_name_t * name)
+hicn_name_create_from_ip_prefix (const ip_prefix_t *prefix, u32 id,
+ hicn_name_t *name)
{
- switch (prefix->family)
- {
- case AF_INET:
- name->type = HNT_CONTIGUOUS_V4;
- memcpy (name->buffer, prefix->address.v4.buffer,
- ip_address_len(prefix->family));
- name->len = IPV4_ADDR_LEN;
- break;
- case AF_INET6:
- name->type = HNT_CONTIGUOUS_V6;
- memcpy (name->buffer, prefix->address.v6.buffer,
- ip_address_len(prefix->family));
- name->len = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
-
- *(u32 *) (name->buffer + name->len) = id;
+ name->prefix.v6.as_u64[0] = prefix->address.v6.as_u64[0];
+ name->prefix.v6.as_u64[1] = prefix->address.v6.as_u64[1];
+ name->suffix = id;
return HICN_LIB_ERROR_NONE;
}
-u8
-hicn_name_get_length (const hicn_name_t * name)
-{
- return name->len;
-}
-
int
-hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
- bool consider_segment)
+hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2,
+ bool consider_segment)
{
- hicn_name_t *name1 = (hicn_name_t *) name_1;
- hicn_name_t *name2 = (hicn_name_t *) name_2;
-
- if ((name1->type == HNT_CONTIGUOUS_V4 && name2->type == HNT_CONTIGUOUS_V6)
- || (name1->type == HNT_CONTIGUOUS_V6
- && name2->type == HNT_CONTIGUOUS_V4))
- {
- return -1;
- }
-
- if ((name1->type == HNT_IOV_V4 && name2->type == HNT_IOV_V6) ||
- (name1->type == HNT_IOV_V6 && name2->type == HNT_IOV_V4))
- {
- return -1;
- }
-
- if ((name1->type == HNT_IOV_V4 && name2->type == HNT_CONTIGUOUS_V6) ||
- (name1->type == HNT_IOV_V6 && name2->type == HNT_CONTIGUOUS_V4))
- {
- return -1;
- }
-
- if (name1->type == HNT_UNSPEC || name2->type == HNT_UNSPEC)
- {
- return -1;
- }
-
- size_t len1 = 0, len2 = 0;
+ int ret;
+ ret = memcmp (&name_1->prefix.v6.buffer, &name_2->prefix.v6.buffer,
+ sizeof (name_1->prefix.v6));
- u8 *buffer11, *buffer12, *buffer21, *buffer22;
+ if (consider_segment)
+ ret |= !(name_1->suffix == name_2->suffix);
- switch (name1->type)
- {
- case HNT_CONTIGUOUS_V4:
- buffer11 = name1->buffer;
- buffer12 = name1->buffer + IPV4_ADDR_LEN;
- len1 = IPV4_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V6:
- buffer11 = name1->buffer;
- buffer12 = name1->buffer + IPV6_ADDR_LEN;
- len1 = IPV6_ADDR_LEN;
- break;
- case HNT_IOV_V4:
- buffer11 = name1->iov.buffers[0].iov_base;
- buffer12 = name1->iov.buffers[1].iov_base;
- len1 = IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- buffer11 = name1->iov.buffers[0].iov_base;
- buffer12 = name1->iov.buffers[1].iov_base;
- len1 = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
- switch (name2->type)
- {
- case HNT_CONTIGUOUS_V4:
- buffer21 = name2->buffer;
- buffer22 = name2->buffer + IPV4_ADDR_LEN;
- len2 = IPV4_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V6:
- buffer21 = name2->buffer;
- buffer22 = name2->buffer + IPV6_ADDR_LEN;
- len2 = IPV6_ADDR_LEN;
- break;
- case HNT_IOV_V4:
- buffer21 = name2->iov.buffers[0].iov_base;
- buffer22 = name2->iov.buffers[1].iov_base;
- len2 = IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- buffer21 = name2->iov.buffers[0].iov_base;
- buffer22 = name2->iov.buffers[1].iov_base;
- len2 = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
- // Sanity check
- if (len1 != len2)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- int ret1 = memcmp ((u8 *) buffer11, (u8 *) buffer21, len1);
-
- if (!consider_segment)
- {
- return ret1;
- }
-
- int ret2 = memcmp ((u8 *) buffer12, (u8 *) buffer22, HICN_SEGMENT_LEN);
-
- return ret1 || ret2;
+ return ret;
}
int
-hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix)
+hicn_name_hash (const hicn_name_t *name, u32 *hash, bool consider_suffix)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V4:
- *hash = hash32 (name->buffer, consider_suffix ? HICN_V4_NAME_LEN : HICN_V4_PREFIX_LEN);
- break;
- case HNT_CONTIGUOUS_V6:
- *hash = hash32 (name->buffer, consider_suffix ? HICN_V6_NAME_LEN : HICN_V6_PREFIX_LEN);
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- *hash =
- hash32 (name->iov.buffers[0].iov_base, name->iov.buffers[0].iov_len);
- if (consider_suffix)
- {
- *hash = cumulative_hash32 (name->iov.buffers[1].iov_base,
- name->iov.buffers[1].iov_len, *hash);
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+ *hash = hash32 (&name->prefix, sizeof (name->prefix));
+
+ if (consider_suffix)
+ *hash = cumulative_hash32 (&name->suffix, sizeof (name->suffix), *hash);
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_empty (hicn_name_t * name)
+hicn_name_empty (hicn_name_t *name)
{
- return name->type == HNT_UNSPEC ? 1 : 0;
+ return _is_unspec (name);
}
int
-hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src)
+hicn_name_copy (hicn_name_t *dst, const hicn_name_t *src)
{
- switch (src->type)
- {
- case HNT_CONTIGUOUS_V4:
- case HNT_CONTIGUOUS_V6:
- *dst = *src;
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- dst->type =
- src->type == HNT_IOV_V4 ? HNT_CONTIGUOUS_V4 : HNT_CONTIGUOUS_V6;
- memcpy (dst->buffer, src->iov.buffers[0].iov_base,
- src->iov.buffers[0].iov_len);
- memcpy (dst->buffer + src->iov.buffers[0].iov_len,
- src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
+ *dst = *src;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
- bool copy_suffix)
+hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *name)
{
- size_t length;
-
- switch (src->type)
- {
- case HNT_CONTIGUOUS_V4:
- if (copy_suffix)
- {
- length = HICN_V4_NAME_LEN;
- }
- else
- {
- length = IPV4_ADDR_LEN;
- }
- memcpy (dst, src->buffer, length);
- break;
- case HNT_CONTIGUOUS_V6:
- if (copy_suffix)
- {
- length = HICN_V6_NAME_LEN;
- }
- else
- {
- length = IPV6_ADDR_LEN;
- }
- memcpy (dst, src->buffer, length);
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- memcpy (dst, src->iov.buffers[0].iov_base, src->iov.buffers[0].iov_len);
- if (copy_suffix)
- {
- memcpy (dst + src->iov.buffers[0].iov_len,
- src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+ int v4 = _is_inet4 (name);
+ const u8 *src = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) +
+ (1 - v4) * (intptr_t) (name->prefix.v6.as_u8));
+ size_t size = v4 * IPV4_ADDR_LEN + (1 - v4) * IPV6_ADDR_LEN;
+ memcpy (dst, src, size);
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number)
+hicn_name_set_seq_number (hicn_name_t *name, u32 seq_number)
{
- u8 *sequence_number = NULL;
-
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- sequence_number = name->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- sequence_number = name->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- case HNT_IOV_V4:
- sequence_number = name->iov.buffers[1].iov_base;
- break;
- case HNT_UNSPEC:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- if (sequence_number)
- {
- *(u32 *) sequence_number = seq_number;
- }
- else
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
+ name->suffix = seq_number;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_to_sockaddr_address (const hicn_name_t * name,
- struct sockaddr *ip_address)
+hicn_name_to_sockaddr_address (const hicn_name_t *name,
+ struct sockaddr *ip_address)
{
struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address;
struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address;
- switch (name->type)
+ assert (!_is_unspec (name));
+
+ if (_is_inet4 (name))
+ {
+ tmp4->sin_family = AF_INET;
+ tmp4->sin_port = DUMMY_PORT;
+ memcpy (&tmp4->sin_addr, &name->prefix.v4, IPV4_ADDR_LEN);
+ }
+ else
{
- case HNT_CONTIGUOUS_V6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_scope_id = 0;
- tmp6->sin6_port = DUMMY_PORT;
- memcpy (&tmp6->sin6_addr, name->buffer, IPV6_ADDR_LEN);
- break;
- case HNT_IOV_V6:
tmp6->sin6_family = AF_INET6;
tmp6->sin6_scope_id = 0;
tmp6->sin6_port = DUMMY_PORT;
- memcpy (&tmp6->sin6_addr, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- break;
- case HNT_CONTIGUOUS_V4:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, name->buffer, IPV4_ADDR_LEN);
- break;
- case HNT_IOV_V4:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
+ memcpy (&tmp6->sin6_addr, &name->prefix.v6, IPV6_ADDR_LEN);
}
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_to_ip_prefix (const hicn_name_t * name, ip_prefix_t * prefix)
+hicn_name_to_ip_prefix (const hicn_name_t *name, ip_prefix_t *prefix)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- memcpy (&prefix->address.v6.buffer, name->buffer, IPV6_ADDR_LEN);
- prefix->family = AF_INET6;
- break;
- case HNT_IOV_V6:
- memcpy (&prefix->address.v6.buffer, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- prefix->family = AF_INET6;
- break;
- case HNT_CONTIGUOUS_V4:
- memcpy (&prefix->address.v4.buffer, name->buffer, IPV4_ADDR_LEN);
- prefix->family = AF_INET;
- break;
- case HNT_IOV_V4:
- memcpy (&prefix->address.v4.buffer, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- prefix->family = AF_INET;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ int family, rc;
+ rc = hicn_name_get_family (name, &family);
+ if (rc)
+ return rc;
+ prefix->family = family;
+ prefix->address.v6.as_u64[0] = name->prefix.v6.as_u64[0];
+ prefix->address.v6.as_u64[1] = name->prefix.v6.as_u64[1];
+ prefix->len = 128;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number)
+hicn_name_get_seq_number (const hicn_name_t *name, u32 *seq_number)
{
- const u8 *sequence_number = NULL;
-
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- sequence_number = name->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- sequence_number = name->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- case HNT_IOV_V4:
- sequence_number = name->iov.buffers[1].iov_base;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
- if (sequence_number)
- {
- *seq_number = *(u32 *) sequence_number;
- }
- else
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
-
+ *seq_number = name->suffix;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len)
+hicn_name_ntop (const hicn_name_t *src, char *dst, size_t len)
{
int offset;
- const char *rc;
- void *seg_number = NULL;
-
- switch (src->type)
- {
- case HNT_CONTIGUOUS_V6:
- rc = inet_ntop (AF_INET6, src->buffer, dst, (socklen_t)len);
- seg_number = (u8 *) src->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- rc = inet_ntop (AF_INET, src->buffer, dst, (socklen_t)len);
- seg_number = (u8 *) src->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- rc = inet_ntop (AF_INET6, src->iov.buffers[0].iov_base, dst, (socklen_t)len);
- seg_number = src->iov.buffers[1].iov_base;
- break;
- case HNT_IOV_V4:
- rc = inet_ntop (AF_INET, src->iov.buffers[0].iov_base, dst, (socklen_t)len);
- seg_number = src->iov.buffers[1].iov_base;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+ const char *rc = NULL;
+ int v4 = _is_inet4 (src);
+ const u8 *addr = (u8 *) (v4 * (intptr_t) src->prefix.v4.as_u8 +
+ (1 - v4) * (intptr_t) src->prefix.v6.as_u8);
+ int family = v4 * AF_INET + (1 - v4) * AF_INET6;
+ rc = inet_ntop (family, addr, dst, (socklen_t) len);
if (!rc)
{
- goto ERR;
+ return HICN_LIB_ERROR_UNSPECIFIED;
}
- offset = (int) strlen (dst);
+ offset = (int) strnlen_s (dst, len);
dst[offset] = '|';
- sprintf (dst + offset + 1, "%lu", (unsigned long) (*(u32 *) seg_number));
+ snprintf (dst + offset + 1, len - offset - 1, "%lu",
+ (unsigned long) (src->suffix));
return HICN_LIB_ERROR_NONE;
-
-ERR:
- return HICN_LIB_ERROR_UNSPECIFIED;
}
int
-hicn_name_pton (const char *src, hicn_name_t * dst)
+hicn_name_pton (const char *src, hicn_name_t *dst)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
}
int
-hicn_name_get_family (const hicn_name_t * name, int *family)
+hicn_name_get_family (const hicn_name_t *name, int *family)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- case HNT_IOV_V6:
- *family = AF_INET6;
- break;
- case HNT_CONTIGUOUS_V4:
- case HNT_IOV_V4:
- *family = AF_INET;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ assert (!_is_unspec (name));
+ int v4 = _is_inet4 (name);
+ *family = v4 * AF_INET + (1 - v4) * AF_INET6;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
- hicn_prefix_t * prefix)
+hicn_prefix_create_from_ip_prefix (const ip_prefix_t *ip_prefix,
+ hicn_prefix_t *prefix)
{
switch (ip_prefix->family)
{
case AF_INET:
- prefix->name.ip4.as_u32 = ip_prefix->address.v4.as_u32;
+ prefix->name.v4.as_u32 = ip_prefix->address.v4.as_u32;
break;
case AF_INET6:
- prefix->name.ip6.as_u64[0] = ip_prefix->address.v6.as_u64[0];
- prefix->name.ip6.as_u64[1] = ip_prefix->address.v6.as_u64[1];
+ prefix->name.v6.as_u64[0] = ip_prefix->address.v6.as_u64[0];
+ prefix->name.v6.as_u64[1] = ip_prefix->address.v6.as_u64[1];
break;
default:
return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
@@ -544,9 +232,6 @@ hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
return HICN_LIB_ERROR_NONE;
}
-#endif /* ! HICN_VPP_PLUGIN */
-
-
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/lib/src/ops.c b/lib/src/ops.c
index ef12e9bf0..80ffcf3c5 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -27,8 +27,10 @@
extern const hicn_ops_t hicn_ops_ipv4;
extern const hicn_ops_t hicn_ops_icmp;
+extern const hicn_ops_t hicn_ops_udp;
extern const hicn_ops_t hicn_ops_tcp;
extern const hicn_ops_t hicn_ops_ipv6;
+extern const hicn_ops_t hicn_ops_new;
extern const hicn_ops_t hicn_ops_ah;
/* Declare empty operations (terminates recursion on protocol layers) */
@@ -39,6 +41,7 @@ DECLARE_get_interest_name (none, NONE);
DECLARE_set_interest_name (none, NONE);
DECLARE_get_interest_name_suffix (none, NONE);
DECLARE_set_interest_name_suffix (none, NONE);
+DECLARE_is_interest (none, NONE);
DECLARE_mark_packet_as_interest (none, NONE);
DECLARE_mark_packet_as_data (none, NONE);
DECLARE_reset_interest_for_hash (none, NONE);
@@ -63,6 +66,8 @@ DECLARE_get_header_length (none, NONE);
DECLARE_get_current_header_length (none, NONE);
DECLARE_get_payload_length (none, NONE);
DECLARE_set_payload_length (none, NONE);
+DECLARE_get_payload_type (none, NONE);
+DECLARE_set_payload_type (none, NONE);
DECLARE_get_signature_size (none, NONE);
DECLARE_set_signature_size (none, NONE);
DECLARE_set_signature_timestamp (none, NONE);
@@ -72,8 +77,10 @@ DECLARE_get_validation_algorithm (none, NONE);
DECLARE_set_key_id (none, NONE);
DECLARE_get_key_id (none, NONE);
DECLARE_get_signature (none, NONE);
-DECLARE_get_signature_gap (none, NONE);
-DECLARE_set_signature_gap (none, NONE);
+DECLARE_get_signature_padding (none, NONE);
+DECLARE_set_signature_padding (none, NONE);
+DECLARE_is_last_data (none, NONE);
+DECLARE_set_last_data (none, NONE);
DECLARE_HICN_OPS (none);
/**
@@ -84,9 +91,11 @@ const hicn_ops_t *const hicn_ops_vft[] = {
/* 0 */ [IPPROTO_IP] = &hicn_ops_ipv4,
/* 1 */[IPPROTO_ICMP] = &hicn_ops_icmp,
/* 6 */[IPPROTO_TCP] = &hicn_ops_tcp,
+ /* 6 */[IPPROTO_UDP] = &hicn_ops_udp,
/* 41 */[IPPROTO_IPV6] = &hicn_ops_ipv6,
/* 51 */[IPPROTO_AH] = &hicn_ops_ah,
/* 58 */[IPPROTO_ICMPV6] = &hicn_ops_icmp,
+ /* 98 */[IPPROTO_ENCAP] = &hicn_ops_new,
[IPPROTO_NONE] = &hicn_ops_none,
};
diff --git a/lib/src/policy.c b/lib/src/policy.c
index 694f0ea5e..0b4850b93 100644
--- a/lib/src/policy.c
+++ b/lib/src/policy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,41 +21,56 @@
#include <stdio.h>
#include <hicn/policy.h>
-const char * policy_tag_str[] = {
- #define _(x, y) [POLICY_TAG_ ## x] = STRINGIZE(x),
- foreach_policy_tag
- #undef _
+const char *policy_tag_str[] = {
+#define _(x, y) [POLICY_TAG_##x] = STRINGIZE (x),
+ foreach_policy_tag
+#undef _
};
const char policy_tag_short_str[] = {
- #define _(x, y) [POLICY_TAG_ ## x] = y,
- foreach_policy_tag
- #undef _
+#define _(x, y) [POLICY_TAG_##x] = y,
+ foreach_policy_tag
+#undef _
};
-const char * policy_state_str[] = {
- #define _(x) [POLICY_STATE_ ## x] = STRINGIZE(x),
- foreach_policy_state
- #undef _
+const char *policy_state_str[] = {
+#define _(x) [POLICY_STATE_##x] = STRINGIZE (x),
+ foreach_policy_state
+#undef _
};
+policy_state_t
+policy_state_from_str (const char *str)
+{
+#define _(x) \
+ if (strcasecmp (str, #x) == 0) \
+ return POLICY_STATE_##x; \
+ else
+ foreach_policy_state
+#undef _
+ return POLICY_STATE_N;
+}
+
int
-policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t * tag_state)
+policy_tag_state_snprintf (char *s, size_t size,
+ const policy_tag_state_t *tag_state)
{
- char *cur = s;
- int rc;
-
- if (tag_state->disabled > 1)
- return -1;
-
- rc = snprintf(cur, s + size - cur, "%s%s", (tag_state->disabled == 1) ? "!" : "", policy_state_str[tag_state->state]);
- if (rc >= (int)(s + size - cur))
- return (int)(s + size - cur);
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
- return (int)(cur - s);
-
- return (int)(cur - s);
+ char *cur = s;
+ int rc;
+
+ if (tag_state->disabled > 1)
+ return -1;
+
+ rc = snprintf (cur, s + size - cur, "%s%s",
+ (tag_state->disabled == 1) ? "!" : "",
+ policy_state_str[tag_state->state]);
+ if (rc >= (int) (s + size - cur))
+ return (int) (s + size - cur);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ return (int) (cur - s);
+
+ return (int) (cur - s);
}
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index 13340eae1..b3d24161d 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -31,6 +31,7 @@ DECLARE_get_interest_name (ah, UNEXPECTED);
DECLARE_set_interest_name (ah, UNEXPECTED);
DECLARE_get_interest_name_suffix (ah, UNEXPECTED);
DECLARE_set_interest_name_suffix (ah, UNEXPECTED);
+DECLARE_is_interest (ah, UNEXPECTED);
DECLARE_mark_packet_as_interest (ah, UNEXPECTED);
DECLARE_mark_packet_as_data (ah, UNEXPECTED);
DECLARE_get_data_locator (ah, UNEXPECTED);
@@ -46,6 +47,10 @@ DECLARE_get_lifetime (ah, UNEXPECTED);
DECLARE_set_lifetime (ah, UNEXPECTED);
DECLARE_get_payload_length (ah, UNEXPECTED);
DECLARE_set_payload_length (ah, UNEXPECTED);
+DECLARE_get_payload_type (ah, UNEXPECTED);
+DECLARE_set_payload_type (ah, UNEXPECTED);
+DECLARE_is_last_data (ah, UNEXPECTED);
+DECLARE_set_last_data (ah, UNEXPECTED);
int
ah_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
@@ -69,6 +74,7 @@ ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
if (rc < 0)
return rc;
memset (&(h->ah.validationPayload), 0, signature_size);
+ h->ah.signaturePadding = 0;
return CHILD_OPS (reset_interest_for_hash, type, h);
}
@@ -81,6 +87,7 @@ ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
if (rc < 0)
return rc;
memset (&(h->ah.validationPayload), 0, signature_size);
+ h->ah.signaturePadding = 0;
return CHILD_OPS (reset_interest_for_hash, type, h);
}
@@ -102,7 +109,7 @@ ah_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
int
ah_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old)
+ const ip_address_t *addr_new, ip_address_t *addr_old)
{
/* Nothing to do on signature */
return HICN_LIB_ERROR_NONE;
@@ -110,7 +117,7 @@ ah_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
int
ah_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
/* Nothing to do on signature */
@@ -162,7 +169,7 @@ int
ah_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
const size_t signature_size)
{
- h->ah.payloadlen = (u8) (signature_size >> 2);
+ h->ah.payloadlen = signature_size >> 2;
return HICN_LIB_ERROR_NONE;
}
@@ -201,16 +208,17 @@ ah_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
}
int
-ah_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+ah_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, size_t padding)
{
- h->ah.signatureGap = gap;
+ h->ah.signaturePadding = padding;
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h, uint8_t *gap)
+ah_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
{
- *gap = h->ah.signatureGap;
+ *padding = h->ah.signaturePadding;
return HICN_LIB_ERROR_NONE;
}
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index 5783cf52c..0452e4fbb 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,6 +24,7 @@ DECLARE_get_interest_name (icmp, UNEXPECTED);
DECLARE_set_interest_name (icmp, UNEXPECTED);
DECLARE_get_interest_name_suffix (icmp, UNEXPECTED);
DECLARE_set_interest_name_suffix (icmp, UNEXPECTED);
+DECLARE_is_interest (icmp, UNEXPECTED);
DECLARE_mark_packet_as_interest (icmp, UNEXPECTED);
DECLARE_mark_packet_as_data (icmp, UNEXPECTED);
DECLARE_get_data_locator (icmp, UNEXPECTED);
@@ -40,7 +41,11 @@ DECLARE_set_lifetime (icmp, UNEXPECTED);
DECLARE_get_length (icmp, UNEXPECTED);
DECLARE_get_payload_length (icmp, UNEXPECTED);
DECLARE_set_payload_length (icmp, UNEXPECTED);
+DECLARE_get_payload_type (icmp, UNEXPECTED);
+DECLARE_set_payload_type (icmp, UNEXPECTED);
DECLARE_get_signature (icmp, UNEXPECTED);
+DECLARE_is_last_data (icmp, UNEXPECTED);
+DECLARE_set_last_data (icmp, UNEXPECTED);
int
icmp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
@@ -94,8 +99,7 @@ icmp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
int
icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old)
+ const ip_address_t *addr_new, ip_address_t *addr_old)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
// u16 *icmp_checksum = &(h->icmp.csum);
@@ -120,7 +124,7 @@ icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
int
icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
@@ -184,16 +188,17 @@ icmp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
}
int
-icmp_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+icmp_set_signature_padding (hicn_type_t type, hicn_protocol_t *h,
+ size_t padding)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CHILD_OPS (set_signature_padding, type, h, padding);
}
int
-icmp_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+icmp_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CHILD_OPS (get_signature_padding, type, h, padding);
}
int
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index cf50f9996..5d445f018 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -64,17 +64,17 @@ ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
int
ipv4_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ ip_address_t *ip_address)
{
- ip_address->ip4 = h->ipv4.saddr;
+ ip_address->v4 = h->ipv4.saddr;
return HICN_LIB_ERROR_NONE;
}
int
ipv4_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ const ip_address_t *ip_address)
{
- h->ipv4.saddr = ip_address->ip4;
+ h->ipv4.saddr = ip_address->v4;
return HICN_LIB_ERROR_NONE;
}
@@ -82,20 +82,16 @@ int
ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
hicn_name_t *name)
{
- name->ip4.prefix_as_ip4 = h->ipv4.daddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V4;
- name->len = HICN_V4_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_interest_name_suffix, type, h, &(name->ip4.suffix));
+ name->prefix.v4 = h->ipv4.daddr;
+ return CHILD_OPS (get_interest_name_suffix, type, h, &(name->suffix));
}
int
ipv4_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
const hicn_name_t *name)
{
- h->ipv4.daddr = name->ip4.prefix_as_ip4;
- return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip4.suffix));
+ h->ipv4.daddr = name->prefix.v4;
+ return CHILD_OPS (set_interest_name_suffix, type, h, &(name->suffix));
}
int
@@ -113,6 +109,12 @@ ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv4_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest)
+{
+ return CHILD_OPS (is_interest, type, h, is_interest);
+}
+
+int
ipv4_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
{
return CHILD_OPS (mark_packet_as_interest, type, h);
@@ -135,17 +137,17 @@ ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
int
ipv4_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ ip_address_t *ip_address)
{
- ip_address->ip4 = h->ipv4.daddr;
+ ip_address->v4 = h->ipv4.daddr;
return HICN_LIB_ERROR_NONE;
}
int
ipv4_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ const ip_address_t *ip_address)
{
- h->ipv4.daddr = ip_address->ip4;
+ h->ipv4.daddr = ip_address->v4;
return HICN_LIB_ERROR_NONE;
}
@@ -153,20 +155,16 @@ int
ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
hicn_name_t *name)
{
- name->ip4.prefix_as_ip4 = h->ipv4.saddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V4;
- name->len = HICN_V4_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_data_name_suffix, type, h, &(name->ip4.suffix));
+ name->prefix.v4 = h->ipv4.saddr;
+ return CHILD_OPS (get_data_name_suffix, type, h, &(name->suffix));
}
int
ipv4_set_data_name (hicn_type_t type, hicn_protocol_t *h,
const hicn_name_t *name)
{
- h->ipv4.saddr = name->ip4.prefix_as_ip4;
- return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip4.suffix));
+ h->ipv4.saddr = name->prefix.v4;
+ return CHILD_OPS (set_data_name_suffix, type, h, &(name->suffix));
}
int
@@ -311,16 +309,15 @@ ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
int
ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old)
+ const ip_address_t *addr_new, ip_address_t *addr_old)
{
// ASSERT(addr_old == NULL);
- addr_old->ip4 = h->ipv4.saddr;
+ addr_old->v4 = h->ipv4.saddr;
addr_old->pad[0] = 0;
addr_old->pad[1] = 0;
addr_old->pad[2] = 0;
- h->ipv4.saddr = addr_new->ip4;
+ h->ipv4.saddr = addr_new->v4;
h->ipv4.csum = 0;
h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
@@ -329,16 +326,16 @@ ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
int
ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
// ASSERT(addr_old == NULL);
- addr_old->ip4 = h->ipv4.daddr;
+ addr_old->v4 = h->ipv4.daddr;
addr_old->pad[0] = 0;
addr_old->pad[1] = 0;
addr_old->pad[2] = 0;
- h->ipv4.daddr = addr_new->ip4;
+ h->ipv4.daddr = addr_new->v4;
h->ipv4.csum = 0;
h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
@@ -408,6 +405,20 @@ ipv4_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv4_get_payload_type (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_payload_type_t *payload_type)
+{
+ return CHILD_OPS (get_payload_type, type, h, payload_type);
+}
+
+int
+ipv4_set_payload_type (hicn_type_t type, hicn_protocol_t *h,
+ hicn_payload_type_t payload_type)
+{
+ return CHILD_OPS (set_payload_type, type, h, payload_type);
+}
+
+int
ipv4_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
size_t *signature_size)
{
@@ -422,16 +433,17 @@ ipv4_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
}
int
-ipv4_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+ipv4_set_signature_padding (hicn_type_t type, hicn_protocol_t *h,
+ size_t padding)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CHILD_OPS (set_signature_padding, type, h, padding);
}
int
-ipv4_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+ipv4_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CHILD_OPS (get_signature_padding, type, h, padding);
}
int
@@ -481,6 +493,18 @@ ipv4_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
return CHILD_OPS (get_signature, type, h, signature);
}
+int
+ipv4_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last)
+{
+ return CHILD_OPS (is_last_data, type, h, is_last);
+}
+
+int
+ipv4_set_last_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (set_last_data, type, h);
+}
+
DECLARE_HICN_OPS (ipv4);
/*
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index 7ac55b2be..b3a107a13 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -33,8 +33,8 @@ ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
/* *INDENT-OFF* */
h->ipv6 = (_ipv6_header_t){
- .saddr = { { 0 } },
- .daddr = { { 0 } },
+ .saddr = IP6_ADDRESS_EMPTY,
+ .daddr = IP6_ADDRESS_EMPTY,
.version_class_flow = htonl ((IPV6_DEFAULT_VERSION << 28) |
(IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
(IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
@@ -48,17 +48,17 @@ ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
int
ipv6_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ ip_address_t *ip_address)
{
- ip_address->ip6 = h->ipv6.saddr;
+ ip_address->v6 = h->ipv6.saddr;
return HICN_LIB_ERROR_NONE;
}
int
ipv6_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ const ip_address_t *ip_address)
{
- h->ipv6.saddr = ip_address->ip6;
+ h->ipv6.saddr = ip_address->v6;
return HICN_LIB_ERROR_NONE;
}
@@ -66,20 +66,16 @@ int
ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
hicn_name_t *name)
{
- name->ip6.prefix_as_ip6 = h->ipv6.daddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V6;
- name->len = HICN_V6_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_interest_name_suffix, type, h, &(name->ip6.suffix));
+ name->prefix.v6 = h->ipv6.daddr;
+ return CHILD_OPS (get_interest_name_suffix, type, h, &(name->suffix));
}
int
ipv6_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
const hicn_name_t *name)
{
- h->ipv6.daddr = name->ip6.prefix_as_ip6;
- return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip6.suffix));
+ h->ipv6.daddr = name->prefix.v6;
+ return CHILD_OPS (set_interest_name_suffix, type, h, &(name->suffix));
}
int
@@ -97,6 +93,12 @@ ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv6_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest)
+{
+ return CHILD_OPS (is_interest, type, h, is_interest);
+}
+
+int
ipv6_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
{
return CHILD_OPS (mark_packet_as_interest, type, h);
@@ -119,17 +121,17 @@ ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
int
ipv6_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
- ip46_address_t *ip_address)
+ ip_address_t *ip_address)
{
- ip_address->ip6 = h->ipv6.daddr;
+ ip_address->v6 = h->ipv6.daddr;
return HICN_LIB_ERROR_NONE;
}
int
ipv6_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *ip_address)
+ const ip_address_t *ip_address)
{
- h->ipv6.daddr = ip_address->ip6;
+ h->ipv6.daddr = ip_address->v6;
return HICN_LIB_ERROR_NONE;
}
@@ -137,20 +139,16 @@ int
ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
hicn_name_t *name)
{
- name->ip6.prefix_as_ip6 = h->ipv6.saddr;
-#ifndef HICN_VPP_PLUGIN
- name->type = HNT_CONTIGUOUS_V6;
- name->len = HICN_V6_NAME_LEN;
-#endif /* HICN_VPP_PLUGIN */
- return CHILD_OPS (get_data_name_suffix, type, h, &(name->ip6.suffix));
+ name->prefix.v6 = h->ipv6.saddr;
+ return CHILD_OPS (get_data_name_suffix, type, h, &(name->suffix));
}
int
ipv6_set_data_name (hicn_type_t type, hicn_protocol_t *h,
const hicn_name_t *name)
{
- h->ipv6.saddr = name->ip6.prefix_as_ip6;
- return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip6.suffix));
+ h->ipv6.saddr = name->prefix.v6;
+ return CHILD_OPS (set_data_name_suffix, type, h, &(name->suffix));
}
int
@@ -281,24 +279,23 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
int
ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new,
- ip46_address_t *addr_old)
+ const ip_address_t *addr_new, ip_address_t *addr_old)
{
// ASSERT(addr_old == NULL);
- addr_old->ip6 = h->ipv6.saddr;
- h->ipv6.saddr = addr_new->ip6;
+ addr_old->v6 = h->ipv6.saddr;
+ h->ipv6.saddr = addr_new->v6;
return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old);
}
int
ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
// ASSERT(addr_old == NULL);
- addr_old->ip6 = h->ipv6.daddr;
- h->ipv6.daddr = addr_new->ip6;
+ addr_old->v6 = h->ipv6.daddr;
+ h->ipv6.daddr = addr_new->v6;
return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id,
reset_pl);
@@ -357,6 +354,20 @@ ipv6_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv6_get_payload_type (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_payload_type_t *payload_type)
+{
+ return CHILD_OPS (get_payload_type, type, h, payload_type);
+}
+
+int
+ipv6_set_payload_type (hicn_type_t type, hicn_protocol_t *h,
+ hicn_payload_type_t payload_type)
+{
+ return CHILD_OPS (set_payload_type, type, h, payload_type);
+}
+
+int
ipv6_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
size_t *signature_size)
{
@@ -371,16 +382,17 @@ ipv6_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
}
int
-ipv6_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+ipv6_set_signature_padding (hicn_type_t type, hicn_protocol_t *h,
+ size_t padding)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CHILD_OPS (set_signature_padding, type, h, padding);
}
int
-ipv6_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+ipv6_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CHILD_OPS (get_signature_padding, type, h, padding);
}
int
@@ -430,6 +442,18 @@ ipv6_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
return CHILD_OPS (get_signature, type, h, signature);
}
+int
+ipv6_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last)
+{
+ return CHILD_OPS (is_last_data, type, h, is_last);
+}
+
+int
+ipv6_set_last_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (set_last_data, type, h);
+}
+
DECLARE_HICN_OPS (ipv6);
/*
diff --git a/lib/src/protocol/new.c b/lib/src/protocol/new.c
new file mode 100644
index 000000000..8c79963ad
--- /dev/null
+++ b/lib/src/protocol/new.c
@@ -0,0 +1,441 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/ops.h>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+static int
+is_interest (u8 flags)
+{
+ return flags & HICN_NEW_FLAG_INT;
+}
+
+int
+new_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+{
+ memset (&h->newhdr, 0, sizeof (h->newhdr));
+ _set_new_header_version (&h->newhdr);
+ uint8_t ah_flag = type.l2 == IPPROTO_AH ? HICN_NEW_FLAG_SIG : 0;
+ h->newhdr.flags |= ah_flag;
+
+ return CHILD_OPS (init_packet_header, type, h);
+}
+
+int
+new_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest)
+{
+ *is_interest = (h->newhdr.flags & HICN_NEW_FLAG_INT) != 0;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
+{
+ h->newhdr.flags |= HICN_NEW_FLAG_INT;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ h->newhdr.flags &= ~HICN_NEW_FLAG_INT;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
+ ip_address_t *ip_address)
+{
+ assert (is_interest (h->newhdr.flags));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
+ const ip_address_t *ip_address)
+{
+ assert (is_interest (h->newhdr.flags));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name)
+{
+ assert (is_interest (h->newhdr.flags));
+ name->prefix = h->newhdr.prefix;
+ name->suffix = ntohl (h->newhdr.suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name)
+{
+ int rc = new_mark_packet_as_interest (type, h);
+ if (rc)
+ return rc;
+
+ assert (is_interest (h->newhdr.flags));
+ h->newhdr.prefix = name->prefix;
+ h->newhdr.suffix = htonl (name->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
+{
+ assert (is_interest (h->newhdr.flags));
+ *suffix = ntohl (h->newhdr.suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
+{
+ assert (is_interest (h->newhdr.flags));
+ h->newhdr.suffix = htonl (*suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+{
+ assert (is_interest (h->newhdr.flags));
+ return CHILD_OPS (init_packet_header, type, h);
+}
+
+int
+new_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
+ ip_address_t *ip_address)
+{
+ assert (!is_interest (h->newhdr.flags));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
+ const ip_address_t *ip_address)
+{
+ assert (!is_interest (h->newhdr.flags));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name)
+{
+ assert (!is_interest (h->newhdr.flags));
+ name->prefix = h->newhdr.prefix;
+ name->suffix = ntohl (h->newhdr.suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_name (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name)
+{
+ new_mark_packet_as_data (type, h);
+ assert (!is_interest (h->newhdr.flags));
+ h->newhdr.prefix = name->prefix;
+ h->newhdr.suffix = htonl (name->suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
+{
+ assert (!is_interest (h->newhdr.flags));
+ *suffix = ntohl (h->newhdr.suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
+{
+ assert (!is_interest (h->newhdr.flags));
+ h->newhdr.suffix = htonl (*suffix);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
+ u32 *pathlabel)
+{
+ assert (!is_interest (h->newhdr.flags));
+ *pathlabel = h->newhdr.path_label;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
+ const u32 pathlabel)
+{
+ assert (!is_interest (h->newhdr.flags));
+ h->newhdr.path_label = pathlabel;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_faceid_t face_id)
+{
+ hicn_pathlabel_t new_pl;
+ update_pathlabel (h->newhdr.path_label, face_id, &new_pl);
+ h->newhdr.path_label = new_pl;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (reset_data_for_hash, type, h);
+}
+
+int
+new_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_lifetime_t *lifetime)
+{
+ *lifetime = ntohl (h->newhdr.lifetime);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_lifetime_t lifetime)
+{
+ h->newhdr.lifetime = htonl (lifetime);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
+{
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
+{
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip_address_t *addr_new, ip_address_t *addr_old)
+{
+ assert (is_interest (h->newhdr.flags));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
+ const hicn_faceid_t face_id, u8 reset_pl)
+{
+ assert (!is_interest (h->newhdr.flags));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
+{
+ *header_length = NEW_HDRLEN + ntohs (h->newhdr.payload_length);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
+{
+ *header_length = NEW_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *header_length = NEW_HDRLEN + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *payload_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *payload_length = ntohs (h->newhdr.payload_length) - child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
+ size_t payload_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ h->newhdr.payload_length =
+ htons ((u_short) (payload_length + child_header_length));
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
+{
+ return CHILD_OPS (get_signature_size, type, h, signature_size);
+}
+
+int
+new_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
+ size_t signature_size)
+{
+ return CHILD_OPS (set_signature_size, type, h, signature_size);
+}
+
+int
+new_set_signature_padding (hicn_type_t type, hicn_protocol_t *h,
+ size_t padding)
+{
+ return CHILD_OPS (set_signature_padding, type, h, padding);
+}
+
+int
+new_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
+{
+ return CHILD_OPS (get_signature_padding, type, h, padding);
+}
+
+int
+new_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp)
+{
+ return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+new_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
+{
+ return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+new_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm)
+{
+ return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+new_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
+{
+ return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+new_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+{
+ return CHILD_OPS (set_key_id, type, h, key_id);
+}
+
+int
+new_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
+{
+ return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+}
+
+int
+new_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
+{
+ return CHILD_OPS (get_signature, type, h, signature);
+}
+
+int
+new_get_payload_type (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_payload_type_t *payload_type)
+{
+ *payload_type = ((h->newhdr.flags & HICN_NEW_FLAG_MAN) == HICN_NEW_FLAG_MAN);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_payload_type (hicn_type_t type, hicn_protocol_t *h,
+ hicn_payload_type_t payload_type)
+{
+ if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+
+ if (payload_type)
+ h->newhdr.flags |= HICN_NEW_FLAG_MAN;
+ else
+ h->newhdr.flags &= ~HICN_NEW_FLAG_MAN;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last)
+{
+ assert (!is_interest (h->newhdr.flags));
+ *is_last = h->newhdr.flags & HICN_NEW_FLAG_LST;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+new_set_last_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ assert (!is_interest (h->newhdr.flags));
+ h->newhdr.flags |= HICN_NEW_FLAG_LST;
+ return HICN_LIB_ERROR_NONE;
+}
+
+DECLARE_HICN_OPS (new);
+
+#pragma GCC diagnostic pop
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index cfeac1907..8097cfd12 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -44,7 +44,20 @@ DECLARE_get_length (tcp, UNEXPECTED);
DECLARE_get_payload_length (tcp, UNEXPECTED);
DECLARE_set_payload_length (tcp, UNEXPECTED);
-always_inline int
+static inline void
+reset_for_hash (hicn_protocol_t *h)
+{
+ h->tcp.sport = 0;
+ h->tcp.dport = 0;
+ h->tcp.seq_ack = 0;
+ h->tcp.data_offset_and_reserved = 0;
+ h->tcp.flags = 0;
+ h->tcp.window = 0;
+ h->tcp.csum = 0;
+ h->tcp.urg_ptr = 0;
+}
+
+static inline int
check_tcp_checksum (u16 csum)
{
/* As per RFC1624
@@ -92,6 +105,20 @@ tcp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
}
int
+tcp_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest)
+{
+ *is_interest = (h->tcp.flags & HICN_TCP_FLAG_ECE) == 0;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
+{
+ h->tcp.flags &= ~HICN_TCP_FLAG_ECE;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
tcp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
hicn_name_suffix_t *suffix)
{
@@ -103,15 +130,12 @@ int
tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
const hicn_name_suffix_t *suffix)
{
- h->tcp.name_suffix = htonl (*suffix);
+ int rc = tcp_mark_packet_as_interest (type, h);
+ if (rc)
+ return rc;
- return HICN_LIB_ERROR_NONE;
-}
+ h->tcp.name_suffix = htonl (*suffix);
-int
-tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
-{
- h->tcp.flags &= ~HICN_TCP_FLAG_ECE;
return HICN_LIB_ERROR_NONE;
}
@@ -125,9 +149,7 @@ tcp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
int
tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
- memset (&(h->tcp), 0, 4);
- memset (&(h->tcp.seq_ack), 0, 12);
-
+ reset_for_hash (h);
return CHILD_OPS (reset_interest_for_hash, type, h);
}
@@ -143,6 +165,10 @@ int
tcp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
const hicn_name_suffix_t *suffix)
{
+ int rc = tcp_mark_packet_as_data (type, h);
+ if (rc)
+ return rc;
+
h->tcp.name_suffix = htonl (*suffix);
return HICN_LIB_ERROR_NONE;
}
@@ -181,9 +207,7 @@ tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
int
tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
- memset (&(h->tcp), 0, 4);
- memset (&(h->tcp.seq_ack), 0, 12);
-
+ reset_for_hash (h);
return CHILD_OPS (reset_data_for_hash, type, h);
}
@@ -279,7 +303,7 @@ tcp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
int
tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old)
+ const ip_address_t *addr_new, ip_address_t *addr_old)
{
u16 *tcp_checksum = &(h->tcp.csum);
int ret = check_tcp_checksum (*tcp_checksum);
@@ -310,7 +334,7 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
int
tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
- const ip46_address_t *addr_new, ip46_address_t *addr_old,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
@@ -339,11 +363,11 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
* csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
*/
ip_csum_t csum =
- ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[0]));
+ ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->v6.as_u64[0]));
csum =
- ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[1]));
- csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[0]));
- csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[1]));
+ ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->v6.as_u64[1]));
+ csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->v6.as_u64[0]));
+ csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->v6.as_u64[1]));
csum = ip_csum_sub_even (csum, old_pl);
csum = ip_csum_add_even (csum, h->tcp.seq_ack);
@@ -389,16 +413,17 @@ tcp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
}
int
-tcp_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+tcp_set_signature_padding (hicn_type_t type, hicn_protocol_t *h,
+ size_t padding)
{
- return CHILD_OPS (set_signature_gap, type, h, gap);
+ return CHILD_OPS (set_signature_padding, type, h, padding);
}
int
-tcp_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
- uint8_t *gap)
+tcp_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
{
- return CHILD_OPS (get_signature_gap, type, h, gap);
+ return CHILD_OPS (get_signature_padding, type, h, padding);
}
int
@@ -448,6 +473,43 @@ tcp_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
return CHILD_OPS (get_signature, type, h, signature);
}
+int
+tcp_get_payload_type (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_payload_type_t *payload_type)
+{
+ *payload_type = ((h->tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_payload_type (hicn_type_t type, hicn_protocol_t *h,
+ hicn_payload_type_t payload_type)
+{
+ if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
+ return HICN_LIB_ERROR_INVALID_PARAMETER;
+
+ if (payload_type)
+ h->tcp.flags |= HICN_TCP_FLAG_URG;
+ else
+ h->tcp.flags &= ~HICN_TCP_FLAG_URG;
+
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last)
+{
+ *is_last = (h->tcp.flags & HICN_TCP_FLAG_RST) == HICN_TCP_FLAG_RST;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_last_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ h->tcp.flags |= HICN_TCP_FLAG_RST;
+ return HICN_LIB_ERROR_NONE;
+}
+
DECLARE_HICN_OPS (tcp);
/*
diff --git a/lib/src/protocol/udp.c b/lib/src/protocol/udp.c
new file mode 100644
index 000000000..ee46b8e9d
--- /dev/null
+++ b/lib/src/protocol/udp.c
@@ -0,0 +1,312 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/ops.h>
+
+#include <hicn/protocol/udp.h>
+
+DECLARE_get_interest_locator (udp, UNEXPECTED);
+DECLARE_set_interest_locator (udp, UNEXPECTED);
+DECLARE_get_interest_name (udp, UNEXPECTED);
+DECLARE_set_interest_name (udp, UNEXPECTED);
+DECLARE_get_data_locator (udp, UNEXPECTED);
+DECLARE_set_data_locator (udp, UNEXPECTED);
+DECLARE_get_data_name (udp, UNEXPECTED);
+DECLARE_set_data_name (udp, UNEXPECTED);
+DECLARE_get_payload_length (udp, UNEXPECTED);
+DECLARE_set_payload_length (udp, UNEXPECTED);
+
+int
+udp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+{
+ size_t total_header_length;
+ int rc = CHILD_OPS (get_header_length, type, h, &total_header_length);
+ if (rc < 0)
+ return rc;
+
+ /* *INDENT-OFF* */
+ h->udp = (_udp_header_t){ .src_port = 0,
+ .dst_port = 0,
+ .length = htons ((u16) total_header_length),
+ .checksum = 0 };
+ /* *INDENT-ON* */
+ return CHILD_OPS (init_packet_header, type, h);
+}
+
+int
+udp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
+{
+ return CHILD_OPS (get_interest_name_suffix, type, h, suffix);
+}
+
+int
+udp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
+{
+ return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
+}
+
+int
+udp_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest)
+{
+ return CHILD_OPS (is_interest, type, h, is_interest);
+}
+
+int
+udp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (mark_packet_as_interest, type, h);
+}
+
+int
+udp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (mark_packet_as_data, type, h);
+}
+
+int
+udp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (reset_interest_for_hash, type, h);
+}
+
+int
+udp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
+{
+ return CHILD_OPS (get_data_name_suffix, type, h, suffix);
+}
+
+int
+udp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
+{
+ return CHILD_OPS (set_data_name_suffix, type, h, suffix);
+}
+
+int
+udp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
+ u32 *pathlabel)
+{
+ return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
+}
+
+int
+udp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
+ const u32 pathlabel)
+{
+ return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
+}
+
+int
+udp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_faceid_t face_id)
+{
+ return CHILD_OPS (update_data_pathlabel, type, h, face_id);
+}
+
+int
+udp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (reset_data_for_hash, type, h);
+}
+
+int
+udp_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_lifetime_t *lifetime)
+{
+ return CHILD_OPS (get_lifetime, type, h, lifetime);
+}
+
+int
+udp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_lifetime_t lifetime)
+{
+ return CHILD_OPS (set_lifetime, type, h, lifetime);
+}
+
+int
+udp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
+{
+ return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length);
+}
+
+int
+udp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
+{
+ return CHILD_OPS (verify_checksums, type, h, partial_csum, payload_length);
+}
+
+int
+udp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip_address_t *addr_new, ip_address_t *addr_old)
+{
+ return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old);
+}
+
+int
+udp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip_address_t *addr_new, ip_address_t *addr_old,
+ const hicn_faceid_t face_id, u8 reset_pl)
+{
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id,
+ reset_pl);
+}
+
+int
+udp_get_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
+{
+ *header_length = IPV6_HDRLEN + ntohs (h->ipv6.len);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
+{
+ *header_length = UDP_HDRLEN;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
+{
+ size_t child_header_length = 0;
+ int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
+ if (rc < 0)
+ return rc;
+ *header_length = UDP_HDRLEN + child_header_length;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_get_payload_type (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_payload_type_t *payload_type)
+{
+ return CHILD_OPS (get_payload_type, type, h, payload_type);
+}
+
+int
+udp_set_payload_type (hicn_type_t type, hicn_protocol_t *h,
+ hicn_payload_type_t payload_type)
+{
+ return CHILD_OPS (set_payload_type, type, h, payload_type);
+}
+
+int
+udp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
+{
+ return CHILD_OPS (get_signature_size, type, h, signature_size);
+}
+
+int
+udp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
+ size_t signature_size)
+{
+ return CHILD_OPS (set_signature_size, type, h, signature_size);
+}
+
+int
+udp_set_signature_padding (hicn_type_t type, hicn_protocol_t *h,
+ size_t padding)
+{
+ return CHILD_OPS (set_signature_padding, type, h, padding);
+}
+
+int
+udp_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *padding)
+{
+ return CHILD_OPS (get_signature_padding, type, h, padding);
+}
+
+int
+udp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp)
+{
+ return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+udp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
+{
+ return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
+}
+
+int
+udp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm)
+{
+ return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+udp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
+{
+ return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
+}
+
+int
+udp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
+{
+ return CHILD_OPS (set_key_id, type, h, key_id);
+}
+
+int
+udp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
+{
+ return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
+}
+
+int
+udp_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
+{
+ return CHILD_OPS (get_signature, type, h, signature);
+}
+
+int
+udp_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last)
+{
+ return CHILD_OPS (is_last_data, type, h, is_last);
+}
+
+int
+udp_set_last_data (hicn_type_t type, hicn_protocol_t *h)
+{
+ return CHILD_OPS (set_last_data, type, h);
+}
+
+DECLARE_HICN_OPS (udp);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-light/src/hicn/config/controlCache.h b/lib/src/strategy.c
index c2f2402f1..3b797664a 100644
--- a/hicn-light/src/hicn/config/controlCache.h
+++ b/lib/src/strategy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,10 +13,10 @@
* limitations under the License.
*/
-#ifndef controlCache_h
-#define controlCache_h
+#include <hicn/strategy.h>
-#include <hicn/config/controlState.h>
-CommandOps *controlCache_Create(ControlState *state);
-CommandOps *controlCache_HelpCreate(ControlState *state);
-#endif // controlCache_h
+const char *strategy_str[] = {
+#define _(x) [STRATEGY_TYPE_##x] = #x,
+ foreach_strategy_type
+#undef _
+}; \ No newline at end of file
diff --git a/lib/src/test/CMakeLists.txt b/lib/src/test/CMakeLists.txt
new file mode 100644
index 000000000..3e3c025c7
--- /dev/null
+++ b/lib/src/test/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright (c) 2021-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.
+
+find_package(Threads REQUIRED)
+
+##############################################################
+# Test sources
+##############################################################
+list(APPEND TESTS_SRC
+ main.cc
+ test_name.cc
+ test_new_header.cc
+ test_udp_header.cc
+ test_validation.cc
+)
+
+##############################################################
+# Build single unit test executable and add it to test list
+##############################################################
+build_executable(lib_tests
+ NO_INSTALL
+ SOURCES ${TESTS_SRC}
+ LINK_LIBRARIES
+ PRIVATE ${LIBHICN_STATIC}
+ PRIVATE ${GTEST_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+ INCLUDE_DIRS
+ PRIVATE ${Libhicn_INCLUDE_DIRS}
+ PRIVATE ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBHICN_SHARED}
+ COMPONENT ${LIBHICN_COMPONENT}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${DEFAULT_COMPILER_OPTIONS}
+ LINK_FLAGS ${LINK_FLAGS}
+)
+
+add_test_internal(lib_tests)
diff --git a/lib/src/test/main.cc b/lib/src/test/main.cc
new file mode 100644
index 000000000..042fcd6c0
--- /dev/null
+++ b/lib/src/test/main.cc
@@ -0,0 +1,23 @@
+/*
+ * 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>
+
+int
+main (int argc, char **argv)
+{
+ ::testing::InitGoogleTest (&argc, argv);
+ return RUN_ALL_TESTS ();
+}
diff --git a/lib/src/test/test_name.cc b/lib/src/test/test_name.cc
new file mode 100644
index 000000000..207725adb
--- /dev/null
+++ b/lib/src/test/test_name.cc
@@ -0,0 +1,339 @@
+/*
+ * 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/name.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+}
+
+class NameTest : public ::testing::Test
+{
+protected:
+ const char *ipv6_prefix = "b001::abcd:1234:abcd:1234";
+ const char *ipv4_prefix = "12.13.14.15";
+ const uint32_t suffix = 12345;
+
+ NameTest () : name_{}, name4_{}, name6_{}
+ {
+ int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6);
+ EXPECT_EQ (rc, 1);
+
+ rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4);
+ EXPECT_EQ (rc, 1);
+
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (ipv6_prefix, suffix, &name6_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ }
+
+ virtual ~NameTest () {}
+
+ void
+ nameHashTest (const char *prefix)
+ {
+ // Create 2 names
+ uint32_t suffix = 13579;
+ hicn_name_t name_a, name_b;
+ int rc = hicn_name_create (prefix, suffix, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (prefix, suffix, &name_b);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // The hash should be equal, with and without considering the suffix
+ uint32_t hash_a, hash_b;
+ rc = hicn_name_hash (&name_a, &hash_a, 1);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_hash (&name_b, &hash_b, 1);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (hash_a, hash_b);
+
+ rc = hicn_name_hash (&name_a, &hash_a, 0);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_hash (&name_b, &hash_b, 0);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (hash_a, hash_b);
+
+ // Now let's change the suffix
+ rc = hicn_name_set_seq_number (&name_a, 97531);
+ // They should result equal if we do not consider the suffix
+ rc = hicn_name_hash (&name_a, &hash_a, 0);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_hash (&name_b, &hash_b, 0);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (hash_a, hash_b);
+
+ // And different if we consider it
+ rc = hicn_name_hash (&name_a, &hash_a, 1);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_hash (&name_b, &hash_b, 1);
+ EXPECT_EQ (rc, 0);
+ EXPECT_NE (hash_a, hash_b);
+ }
+
+ void
+ nameCopyTest (const char *prefix)
+ {
+ uint32_t suffix = 13579;
+ hicn_name_t name_a, name_b;
+ int rc = hicn_name_create (prefix, suffix, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_copy (&name_b, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_compare (&name_a, &name_b, 1);
+ EXPECT_EQ (rc, 0);
+ }
+
+ void
+ nameCompareTest (const char *prefix)
+ {
+ // Create 2 names
+ uint32_t suffix = 13579;
+ hicn_name_t name_a, name_b;
+ int rc = hicn_name_create (prefix, suffix, &name_a);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (prefix, suffix, &name_b);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // They should be equal, with and without considering the suffix
+ rc = hicn_name_compare (&name_a, &name_b, 1);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_compare (&name_a, &name_b, 0);
+ EXPECT_EQ (rc, 0);
+
+ // Now let's change the suffix
+ rc = hicn_name_set_seq_number (&name_a, 97531);
+ // They should result equal if we do not consider the suffix
+ rc = hicn_name_compare (&name_a, &name_b, 0);
+ EXPECT_EQ (rc, 0);
+ // And different if we consider the suffix
+ rc = hicn_name_compare (&name_a, &name_b, 1);
+ EXPECT_NE (rc, 0);
+ }
+
+ void
+ nameFromIpPrefixTest (const ip_prefix_t &ip_prefix)
+ {
+ uint32_t suffix = 54321;
+ hicn_name_t name;
+ int rc = hicn_name_create_from_ip_prefix (&ip_prefix, suffix, &name);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = memcmp (ip_prefix.address.v6.as_u8, name.prefix.v6.as_u8,
+ sizeof (name.prefix.v6));
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (suffix, name.suffix);
+ }
+
+ void
+ nameToIpPrefixTest (const char *prefix)
+ {
+ uint32_t suffix = 54321;
+ hicn_name_t name;
+ int rc = hicn_name_create (prefix, suffix, &name);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Get family
+ int family;
+ rc = hicn_name_get_family (&name, &family);
+
+ ip_prefix_t ip_prefix;
+ rc = hicn_name_to_ip_prefix (&name, &ip_prefix);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ip_prefix.family, family);
+ rc = ip_address_cmp (&ip_prefix.address, &name.prefix, AF_INET6);
+ EXPECT_EQ (rc, 0);
+ }
+
+ hicn_name_t name_, name4_, name6_;
+ ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes;
+};
+
+/**
+ * Name Initialization
+ */
+TEST_F (NameTest, NameInitialization)
+{
+ EXPECT_TRUE (_is_unspec (&name_));
+ uint32_t suffix = 12345;
+
+ // Initialize ipv6 name
+ hicn_name_t name6;
+ int rc = hicn_name_create (ipv6_prefix, suffix, &name6);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check name is correctly created
+ rc = ip_address_cmp (&name6.prefix, &ipv6_prefix_bytes, AF_INET6);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (name6.suffix, suffix);
+
+ // Initialize ipv4 name
+ hicn_name_t name4;
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check name is correctly created
+ rc = ip_address_cmp (&name4.prefix, &ipv4_prefix_bytes, AF_INET);
+ EXPECT_EQ (name4.prefix.pad[0], 0UL);
+ EXPECT_EQ (name4.prefix.pad[1], 0UL);
+ EXPECT_EQ (name4.prefix.pad[2], 0UL);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (name4.suffix, suffix);
+
+ // Try also to reuse previously initialized name
+ rc = hicn_name_create (ipv4_prefix, suffix, &name6);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check name is correctly created
+ rc = ip_address_cmp (&name6.prefix, &ipv4_prefix_bytes, AF_INET);
+ EXPECT_EQ (name6.prefix.pad[0], 0UL);
+ EXPECT_EQ (name6.prefix.pad[1], 0UL);
+ EXPECT_EQ (name6.prefix.pad[2], 0UL);
+ EXPECT_EQ (rc, 0);
+ EXPECT_EQ (name6.suffix, suffix);
+}
+
+/**
+ * Name from ip prefix
+ */
+TEST_F (NameTest, NameFromIpPrefix6)
+{
+ ip_prefix_t ip_prefix = { .family = AF_INET6, .address = {}, .len = 64 };
+
+ ip_prefix.address.v6.as_u64[0] = ipv6_prefix_bytes.v6.as_u64[0];
+ ip_prefix.address.v6.as_u64[1] = ipv6_prefix_bytes.v6.as_u64[1];
+
+ nameFromIpPrefixTest (ip_prefix);
+}
+
+TEST_F (NameTest, NameFromIpPrefix4)
+{
+ ip_prefix_t ip_prefix = { .family = AF_INET, .address = {}, .len = 64 };
+ ip_prefix.address.v4.as_u32 = ipv4_prefix_bytes.v4.as_u32;
+ ip_prefix.address.pad[0] = 0;
+ ip_prefix.address.pad[1] = 0;
+ ip_prefix.address.pad[2] = 0;
+ nameFromIpPrefixTest (ip_prefix);
+}
+
+TEST_F (NameTest, NameCompare6) { nameCompareTest (ipv6_prefix); }
+
+TEST_F (NameTest, NameCompare4) { nameCompareTest (ipv4_prefix); }
+
+TEST_F (NameTest, NameHash6) { nameHashTest (ipv6_prefix); }
+
+TEST_F (NameTest, NameHash4) { nameHashTest (ipv4_prefix); }
+
+TEST_F (NameTest, NameEmpty)
+{
+ int rc = hicn_name_empty (&name_);
+ EXPECT_EQ (rc, 1);
+
+ name_.prefix.v6 = ipv6_prefix_bytes.v6;
+ rc = hicn_name_empty (&name_);
+ EXPECT_EQ (rc, 0);
+}
+
+TEST_F (NameTest, NameCopy6) { nameCopyTest (ipv6_prefix); }
+
+TEST_F (NameTest, NameCopy4) { nameCopyTest (ipv4_prefix); }
+
+TEST_F (NameTest, NameCopyToDestination)
+{
+ ip4_address_t dst4;
+ ip6_address_t dst6;
+
+ // Copy names to destination
+ int rc = hicn_name_copy_prefix_to_destination (dst4.as_u8, &name4_);
+ EXPECT_EQ (rc, 0);
+ rc = hicn_name_copy_prefix_to_destination (dst6.as_u8, &name6_);
+ EXPECT_EQ (rc, 0);
+
+ // Check copy succeeded
+ EXPECT_TRUE (dst4.as_u32 == name4_.prefix.v4.as_u32);
+ EXPECT_TRUE (dst6.as_u64[0] == name6_.prefix.v6.as_u64[0]);
+ EXPECT_TRUE (dst6.as_u64[1] == name6_.prefix.v6.as_u64[1]);
+}
+
+TEST_F (NameTest, SetGetSuffix)
+{
+ uint32_t suffix2 = 55555, suffix_ret;
+
+ // Check if suffix is correct
+ int rc = hicn_name_get_seq_number (&name6_, &suffix_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (suffix, suffix_ret);
+
+ // Set new suffix
+ rc = hicn_name_set_seq_number (&name6_, suffix2);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check suffix was set
+ rc = hicn_name_get_seq_number (&name6_, &suffix_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (suffix2, suffix_ret);
+}
+
+TEST_F (NameTest, NameToSockAddr)
+{
+ struct sockaddr_in saddr4;
+ struct sockaddr_in6 saddr6;
+
+ int rc =
+ hicn_name_to_sockaddr_address (&name6_, (struct sockaddr *) (&saddr6));
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = memcmp (name6_.prefix.v6.as_u8, saddr6.sin6_addr.s6_addr,
+ sizeof (name6_.prefix.v6));
+ EXPECT_EQ (rc, 0);
+
+ rc = hicn_name_to_sockaddr_address (&name4_, (struct sockaddr *) (&saddr4));
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (name4_.prefix.v4.as_u32, saddr4.sin_addr.s_addr);
+}
+
+TEST_F (NameTest, NameToIpPrefix)
+{
+ nameToIpPrefixTest (ipv4_prefix);
+ nameToIpPrefixTest (ipv6_prefix);
+}
+
+TEST_F (NameTest, NameNToP)
+{
+ char dst[128];
+
+ // V6
+ int rc = hicn_name_ntop (&name6_, dst, 128);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Build expected name
+ std::stringstream expected6;
+ expected6 << ipv6_prefix << "|" << suffix;
+
+ rc = strcmp (dst, expected6.str ().c_str ());
+ EXPECT_EQ (rc, 0);
+
+ // V4
+ rc = hicn_name_ntop (&name4_, dst, 128);
+ std::stringstream expected4;
+ expected4 << ipv4_prefix << "|" << suffix;
+
+ rc = strcmp (dst, expected4.str ().c_str ());
+ EXPECT_EQ (rc, 0);
+}
diff --git a/lib/src/test/test_new_header.cc b/lib/src/test/test_new_header.cc
new file mode 100644
index 000000000..33c9e13c9
--- /dev/null
+++ b/lib/src/test/test_new_header.cc
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/name.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/protocol/new.h>
+#include <hicn/protocol/ah.h>
+#include <hicn/header.h>
+#include <hicn/compat.h>
+}
+
+class NewHeaderTest : public ::testing::Test
+{
+protected:
+ const char *ipv6_prefix = "b001::abcd:1234:abcd:1234";
+ const char *ipv4_prefix = "12.13.14.15";
+ const uint32_t suffix = 12345;
+
+ NewHeaderTest (size_t hdr_size, hicn_format_t format)
+ : buffer_ (new uint8_t[hdr_size]), header_ ((hicn_header_t *) (buffer_)),
+ format_ (format), name_{}, name4_{}, name6_{}
+ {
+ int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6);
+ EXPECT_EQ (rc, 1);
+
+ rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4);
+ EXPECT_EQ (rc, 1);
+
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (ipv6_prefix, suffix, &name6_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ }
+
+ NewHeaderTest () : NewHeaderTest (NEW_HDRLEN, HF_NEW) {}
+
+ virtual ~NewHeaderTest () { delete[] buffer_; }
+
+ void
+ checkCommon (const _new_header_t *new_hdr)
+ {
+ // Initialize header
+ int rc = hicn_packet_init_header (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check fields
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL);
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL);
+ EXPECT_EQ (new_hdr->suffix, 0UL);
+ EXPECT_EQ (new_hdr->lifetime, 0UL);
+ EXPECT_EQ (new_hdr->path_label, 0UL);
+ EXPECT_EQ (new_hdr->payload_length, 0UL);
+ EXPECT_EQ (_get_new_header_version (new_hdr), 0x9);
+ }
+
+ virtual void
+ SetUp () override
+ {
+ auto new_hdr = &header_->protocol.newhdr;
+ checkCommon (new_hdr);
+ EXPECT_EQ (new_hdr->flags, 0);
+ }
+
+ uint8_t *buffer_;
+ hicn_header_t *header_;
+ hicn_format_t format_;
+ hicn_name_t name_, name4_, name6_;
+ ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes;
+};
+
+class NewHeaderAHTest : public NewHeaderTest
+{
+protected:
+ NewHeaderAHTest () : NewHeaderTest (NEW_HDRLEN + AH_HDRLEN, HF_NEW_AH) {}
+
+ virtual void
+ SetUp () override
+ {
+ auto new_hdr = &header_->protocol.newhdr;
+ checkCommon (new_hdr);
+ EXPECT_NE (new_hdr->flags, 0);
+ }
+};
+
+/**
+ * Header Initialization
+ */
+TEST_F (NewHeaderTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (header_, &format);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HF_NEW);
+}
+
+TEST_F (NewHeaderAHTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (header_, &format);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HF_NEW_AH);
+}
+
+/**
+ * @brief Checksum functions are not required, but we keep them for
+ * compatibility.
+ */
+TEST_F (NewHeaderTest, Checksum)
+{
+ // Get format from existing packet
+ int rc = hicn_packet_compute_checksum (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderAHTest, Checksum)
+{
+ // Get format from existing packet
+ int rc = hicn_packet_compute_checksum (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN);
+}
+
+TEST_F (NewHeaderAHTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (NewHeaderTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN);
+}
+
+TEST_F (NewHeaderAHTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (NewHeaderTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (NewHeaderAHTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (NewHeaderTest, SetGetName)
+{
+ // Get v6 name and set it to new_header
+ hicn_name_t name_ret;
+ int rc = hicn_packet_set_name (format_, header_, &name6_, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_name (format_, header_, &name_ret, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_compare (&name6_, &name_ret, 1);
+ EXPECT_EQ (rc, 0);
+}
+
+TEST_F (NewHeaderTest, SetGetLocator)
+{
+ // This function does nothing but it is set for compatibility
+ ip_address_t locator;
+ memset (&locator, 0, sizeof (locator));
+ locator.v6.as_u8[15] = 1;
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_set_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ // FixMe no error raised here
+ size_t signature_size = 128;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ (void) rc;
+ // EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size);
+ // EXPECT_NE (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (NewHeaderAHTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ size_t signature_size = 128, signature_size_ret;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (signature_size, signature_size_ret);
+}
+
+TEST_F (NewHeaderTest, IsInterestIsData)
+{
+ // Mark packet as interest
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ int ret;
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 1);
+
+ // Mark packet as data
+ rc = hicn_packet_set_data (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 0);
+}
+
+TEST_F (NewHeaderTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (NewHeaderAHTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (NewHeaderTest, SetGetPayloadType)
+{
+ // Lifetime
+ hicn_payload_type_t payload_type = HPT_MANIFEST, payload_type_ret;
+ int rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+
+ payload_type = HPT_DATA;
+
+ rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+}
diff --git a/lib/src/test/test_udp_header.cc b/lib/src/test/test_udp_header.cc
new file mode 100644
index 000000000..5d9f4d1eb
--- /dev/null
+++ b/lib/src/test/test_udp_header.cc
@@ -0,0 +1,355 @@
+/*
+ * 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/name.h>
+#include <hicn/common.h>
+#include <hicn/error.h>
+#include <hicn/protocol/new.h>
+#include <hicn/protocol/ah.h>
+#include <hicn/header.h>
+#include <hicn/compat.h>
+}
+
+class UdpHeaderTest : public ::testing::Test
+{
+protected:
+ const char *ipv6_prefix = "b001::abcd:1234:abcd:1234";
+ const char *ipv4_prefix = "12.13.14.15";
+ const uint32_t suffix = 12345;
+
+ UdpHeaderTest (size_t hdr_size, hicn_format_t format)
+ : buffer_ (new uint8_t[hdr_size]), header_ ((hicn_header_t *) (buffer_)),
+ format_ (format), name_{}, name4_{}, name6_{}
+ {
+ int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6);
+ EXPECT_EQ (rc, 1);
+
+ rc = inet_pton (AF_INET, ipv4_prefix, &ipv4_prefix_bytes.v4);
+ EXPECT_EQ (rc, 1);
+
+ rc = hicn_name_create (ipv4_prefix, suffix, &name4_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_name_create (ipv6_prefix, suffix, &name6_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ }
+
+ UdpHeaderTest ()
+ : UdpHeaderTest (NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN, HF_INET6_UDP)
+ {
+ }
+
+ virtual ~UdpHeaderTest () { delete[] buffer_; }
+
+ void
+ checkCommon (const _ipv6_header_t *ip6_hdr)
+ {
+ // Initialize header
+ int rc = hicn_packet_init_header (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check fields
+ EXPECT_EQ (ip6_hdr->saddr.as_u64[0], 0UL);
+ EXPECT_EQ (ip6_hdr->saddr.as_u64[1], 0UL);
+ EXPECT_EQ (ip6_hdr->daddr.as_u64[0], 0UL);
+ EXPECT_EQ (ip6_hdr->daddr.as_u64[1], 0UL);
+ EXPECT_EQ (ip6_hdr->nxt, IPPROTO_UDP);
+
+ _udp_header_t *udp_hdr = (_udp_header_t *) (ip6_hdr + 1);
+ EXPECT_EQ (udp_hdr->src_port, 0UL);
+ EXPECT_EQ (udp_hdr->dst_port, 0UL);
+ EXPECT_EQ (udp_hdr->checksum, 0UL);
+ // EXPECT_EQ (ntohs (udp_hdr->length), NEW_HDRLEN + AH_HDRLEN);
+
+ _new_header_t *new_hdr = (_new_header_t *) (udp_hdr + 1);
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL);
+ EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL);
+ EXPECT_EQ (new_hdr->suffix, 0UL);
+ EXPECT_EQ (new_hdr->lifetime, 0UL);
+ EXPECT_EQ (new_hdr->path_label, 0UL);
+ EXPECT_EQ (new_hdr->payload_length, 0UL);
+ EXPECT_EQ (_get_new_header_version (new_hdr), 0x9);
+ }
+
+ virtual void
+ SetUp () override
+ {
+ auto ip6_hdr = &header_->protocol.ipv6;
+ checkCommon (ip6_hdr);
+ }
+
+ uint8_t *buffer_;
+ hicn_header_t *header_;
+ hicn_format_t format_;
+ hicn_name_t name_, name4_, name6_;
+ ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes;
+};
+
+class UdpHeaderAHTest : public UdpHeaderTest
+{
+protected:
+ UdpHeaderAHTest ()
+ : UdpHeaderTest (AH_HDRLEN + NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN,
+ HF_INET6_UDP_AH)
+ {
+ }
+};
+
+/**
+ * Header Initialization
+ */
+TEST_F (UdpHeaderTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (header_, &format);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HF_INET6_UDP);
+}
+
+TEST_F (UdpHeaderAHTest, GetFormat)
+{
+ // Get format from existing packet
+ hicn_format_t format;
+ int rc = hicn_packet_get_format (header_, &format);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Check it corresponds to the new header format
+ EXPECT_EQ (format, HF_INET6_UDP_AH);
+}
+
+// /**
+// * @brief Checksum functions are not required, but we keep them for
+// * compatibility.
+// */
+// TEST_F (NewHeaderTest, Checksum)
+// {
+// // Get format from existing packet
+// int rc = hicn_packet_compute_checksum (format_, header_);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+// }
+
+// TEST_F (NewHeaderAHTest, Checksum)
+// {
+// // Get format from existing packet
+// int rc = hicn_packet_compute_checksum (format_, header_);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_compute_header_checksum (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+// rc = hicn_packet_check_integrity_no_payload (format_, header_, 0);
+// EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+// }
+
+TEST_F (UdpHeaderTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN);
+}
+
+TEST_F (UdpHeaderAHTest, GetHeaderLengthFromFormat)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length_from_format (format_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (UdpHeaderTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN);
+}
+
+TEST_F (UdpHeaderAHTest, GetHeaderLength)
+{
+ // Get format from existing packet
+ std::size_t hdr_len;
+ int rc = hicn_packet_get_header_length (format_, header_, &hdr_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (hdr_len, UDP_HDRLEN + IPV6_HDRLEN + NEW_HDRLEN + AH_HDRLEN);
+}
+
+TEST_F (UdpHeaderTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (UdpHeaderAHTest, SetGetPayloadLength)
+{
+ // Get format from existing packet
+ std::size_t payload_len = 1000, payload_len_ret;
+ int rc = hicn_packet_set_payload_length (format_, header_, payload_len);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ rc = hicn_packet_get_payload_length (format_, header_, &payload_len_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (payload_len, payload_len_ret);
+}
+
+TEST_F (UdpHeaderTest, SetGetName)
+{
+ // Get v6 name and set it to new_header
+ hicn_name_t name_ret;
+
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_set_name (format_, header_, &name6_, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_name (format_, header_, &name_ret, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_name_compare (&name6_, &name_ret, 1);
+ EXPECT_EQ (rc, 0);
+}
+
+TEST_F (UdpHeaderTest, SetGetLocator)
+{
+ // This function does nothing but it is set for compatibility
+ ip_address_t locator;
+ memset (&locator, 0, sizeof (locator));
+ locator.v6.as_u8[15] = 1;
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_set_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_locator (format_, header_, &locator, 1);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (UdpHeaderTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ // FixMe no error raised here
+ size_t signature_size = 128;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ (void) rc;
+ // EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size);
+ // EXPECT_NE (rc, HICN_LIB_ERROR_NONE);
+}
+
+TEST_F (UdpHeaderAHTest, SetGetSignatureSize)
+{
+ // No AH, so we should get an error
+ size_t signature_size = 128, signature_size_ret;
+ int rc = hicn_packet_set_signature_size (format_, header_, signature_size);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ // Same for hicn_packet_get_signature_size
+ rc = hicn_packet_get_signature_size (format_, header_, &signature_size_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (signature_size, signature_size_ret);
+}
+
+TEST_F (UdpHeaderTest, IsInterestIsData)
+{
+ // Mark packet as interest
+ int rc = hicn_packet_set_interest (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ int ret;
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 1);
+
+ // Mark packet as data
+ rc = hicn_packet_set_data (format_, header_);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_is_interest (format_, header_, &ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+ EXPECT_EQ (ret, 0);
+}
+
+TEST_F (UdpHeaderTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (UdpHeaderAHTest, SetGetLifetime)
+{
+ // Lifetime
+ u32 lifetime = 20000, lifetime_ret; // 20 sec.
+ int rc = hicn_packet_set_lifetime (format_, header_, lifetime);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_lifetime (format_, header_, &lifetime_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (lifetime, lifetime_ret);
+}
+
+TEST_F (UdpHeaderTest, SetGetPayloadType)
+{
+ // Lifetime
+ hicn_payload_type_t payload_type = HPT_MANIFEST, payload_type_ret;
+ int rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+
+ payload_type = HPT_DATA;
+
+ rc = hicn_packet_set_payload_type (format_, header_, payload_type);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ rc = hicn_packet_get_payload_type (format_, header_, &payload_type_ret);
+ EXPECT_EQ (rc, HICN_LIB_ERROR_NONE);
+
+ EXPECT_EQ (payload_type, payload_type_ret);
+}
diff --git a/lib/src/test/test_validation.cc b/lib/src/test/test_validation.cc
new file mode 100644
index 000000000..091f26d65
--- /dev/null
+++ b/lib/src/test/test_validation.cc
@@ -0,0 +1,55 @@
+/*
+ * 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 <gtest/gtest.h>
+
+extern "C"
+{
+#include <hicn/validation.h>
+}
+
+static constexpr int BUF_SIZE = 10;
+
+class ValidationTest : public ::testing::Test
+{
+};
+
+TEST_F (ValidationTest, SymbolicName)
+{
+ const char symbolic_name_correct[BUF_SIZE] = "conn0";
+ const char symbolic_name_empty[BUF_SIZE] = "";
+ const char symbolic_name_wrong[BUF_SIZE] = "1conn0";
+
+ EXPECT_TRUE (is_symbolic_name (symbolic_name_correct, BUF_SIZE));
+ EXPECT_FALSE (is_symbolic_name (symbolic_name_empty, BUF_SIZE));
+ EXPECT_FALSE (is_symbolic_name (symbolic_name_wrong, BUF_SIZE));
+}
+
+TEST_F (ValidationTest, Number)
+{
+ const char number_correct[BUF_SIZE] = "123";
+ const char number_empty[BUF_SIZE] = "";
+ const char number_wrong[BUF_SIZE] = "a123";
+ const char number_wrong_2[BUF_SIZE] = "12T3";
+ const char number_wrong_3[BUF_SIZE] = "a";
+ const char number_wrong_negative[BUF_SIZE] = "-123";
+
+ EXPECT_TRUE (is_number (number_correct, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_empty, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong_2, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong_3, BUF_SIZE));
+ EXPECT_FALSE (is_number (number_wrong_negative, BUF_SIZE));
+} \ No newline at end of file
diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c
index 49916547d..412baddcf 100644
--- a/lib/src/util/ip_address.c
+++ b/lib/src/util/ip_address.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,44 +20,51 @@
#include <hicn/util/ip_address.h>
#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#ifdef __ANDROID__
-#define SWAP(x) bswap_32(x)
+#define SWAP(x) bswap_32 (x)
#else
-#define SWAP(x) __bswap_constant_32(x)
+#define SWAP(x) __bswap_constant_32 (x)
#endif
#else
#define SWAP(x) x
#endif
-
/* No htonl() with const */
const ip_address_t IPV4_LOOPBACK = {
- .v4.as_inaddr.s_addr = SWAP(INADDR_LOOPBACK),
+ .v4.as_inaddr.s_addr = SWAP (INADDR_LOOPBACK),
};
-const ip_address_t IPV6_LOOPBACK ={
- .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT,
+const ip_address_t IPV6_LOOPBACK = {
+ .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT,
};
-const ip_address_t IPV4_ANY = {
- .v4.as_inaddr.s_addr = INADDR_ANY,
+const ip_address_t IPV4_ANY = {
+ .v4.as_inaddr.s_addr = INADDR_ANY,
};
const ip_address_t IPV6_ANY = {
- .v6.as_in6addr = IN6ADDR_ANY_INIT,
+ .v6.as_in6addr = IN6ADDR_ANY_INIT,
};
-const ip_address_t IP_ADDRESS_EMPTY = {
- .v6.as_u64 = { 0 },
+const ip4_address_t IP4_ADDRESS_EMPTY = {
+ .as_u32 = 0,
+};
+
+const ip6_address_t IP6_ADDRESS_EMPTY = {
+ .as_u64 = { 0, 0 },
};
+const ip_address_t IP_ADDRESS_EMPTY = {
+ .v6.as_u64 = { 0, 0 },
+};
/* IP address */
int
-ip_address_get_family (const char * ip_address)
+ip_address_get_family (const char *ip_address)
{
struct addrinfo hint, *res = NULL;
int rc;
@@ -81,24 +88,26 @@ int
ip_address_len (int family)
{
return (family == AF_INET6) ? IPV6_ADDR_LEN :
- (family == AF_INET) ? IPV4_ADDR_LEN : 0;
+ (family == AF_INET) ? IPV4_ADDR_LEN :
+ 0;
}
int
-ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
- int family)
+ip_address_ntop (const ip_address_t *ip_address, char *dst, const size_t len,
+ int family)
{
- const char * s;
- switch(family) {
+ const char *s;
+ switch (family)
+ {
case AF_INET:
- s = inet_ntop (AF_INET, ip_address->v4.buffer, dst, (socklen_t)len);
+ s = inet_ntop (AF_INET, ip_address->v4.buffer, dst, (socklen_t) len);
break;
case AF_INET6:
- s = inet_ntop (AF_INET6, ip_address->v6.buffer, dst, (socklen_t)len);
+ s = inet_ntop (AF_INET6, ip_address->v6.buffer, dst, (socklen_t) len);
break;
default:
return -1;
- }
+ }
return (s ? 1 : -1);
}
@@ -106,14 +115,15 @@ ip_address_ntop (const ip_address_t * ip_address, char *dst, const size_t len,
* Parse ip addresses in presentation format
*/
int
-ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
+ip_address_pton (const char *ip_address_str, ip_address_t *ip_address)
{
int pton_fd;
int family;
family = ip_address_get_family (ip_address_str);
- switch (family) {
+ switch (family)
+ {
case AF_INET:
ip_address->pad[0] = 0;
ip_address->pad[1] = 0;
@@ -136,32 +146,34 @@ ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
}
int
-ip_address_snprintf(char * s, size_t size, const ip_address_t * ip_address, int family)
+ip_address_snprintf (char *s, size_t size, const ip_address_t *ip_address,
+ int family)
{
- const char * rc;
- switch(family) {
- case AF_INET:
- if (size < INET_ADDRSTRLEN)
- return -1;
- rc = inet_ntop (AF_INET, ip_address->v4.buffer, s, INET_ADDRSTRLEN);
- break;
- case AF_INET6:
- if (size < INET6_ADDRSTRLEN)
- return -1;
- rc = inet_ntop (AF_INET6, ip_address->v6.buffer, s, INET6_ADDRSTRLEN);
- break;
- default:
- return -1;
+ const char *rc;
+ switch (family)
+ {
+ case AF_INET:
+ if (size < INET_ADDRSTRLEN)
+ return -1;
+ rc = inet_ntop (AF_INET, ip_address->v4.buffer, s, INET_ADDRSTRLEN);
+ break;
+ case AF_INET6:
+ if (size < INET6_ADDRSTRLEN)
+ return -1;
+ rc = inet_ntop (AF_INET6, ip_address->v6.buffer, s, INET6_ADDRSTRLEN);
+ break;
+ default:
+ return -1;
}
- if (!rc)
- return -1;
- return (int)strlen(s);
+ if (!rc)
+ return -1;
+ return (int) strnlen_s (s, MAXSZ_IP_ADDRESS);
}
int
-ip_address_to_sockaddr(const ip_address_t * ip_address,
- struct sockaddr *sa, int family)
+ip_address_to_sockaddr (const ip_address_t *ip_address, struct sockaddr *sa,
+ int family)
{
struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sa;
struct sockaddr_in *tmp4 = (struct sockaddr_in *) sa;
@@ -187,33 +199,30 @@ ip_address_to_sockaddr(const ip_address_t * ip_address,
}
int
-ip_address_cmp(const ip_address_t * ip1, const ip_address_t * ip2, int family)
+ip_address_cmp (const ip_address_t *ip1, const ip_address_t *ip2, int family)
{
- switch(family) {
- case AF_INET:
- return memcmp(&ip1->v4, &ip2->v4, sizeof(ip1->v4));
- break;
- case AF_INET6:
- return memcmp(&ip1->v6, &ip2->v6, sizeof(ip1->v6));
- break;
- default:
- return memcmp(ip1, ip2, sizeof(ip_address_t));
+ switch (family)
+ {
+ case AF_INET:
+ return memcmp (ip1->v4.buffer, ip2->v4.buffer, sizeof (ip1->v4));
+ case AF_INET6:
+ default:
+ return memcmp (ip1->v6.buffer, ip2->v6.buffer, sizeof (ip1->v6));
}
}
int
-ip_address_empty(const ip_address_t * ip)
+ip_address_empty (const ip_address_t *ip)
{
- return (memcmp(ip, &IP_ADDRESS_EMPTY, sizeof(IP_ADDRESS_EMPTY)) == 0);
+ return (memcmp (ip->v6.buffer, &IP_ADDRESS_EMPTY.v6.buffer,
+ sizeof (IP_ADDRESS_EMPTY)) == 0);
}
-
-
/* Prefix */
/* Parse IP Prefixes in presentation format (in bits, separated by a slash) */
int
-ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
+ip_prefix_pton (const char *ip_address_str, ip_prefix_t *ip_prefix)
{
int pton_fd;
char *p;
@@ -221,29 +230,32 @@ ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
char *addr = strdup (ip_address_str);
p = strchr (addr, '/');
- if (!p) {
- ip_prefix->len = ~0; // until we get the ip address family
- } else {
- ip_prefix->len = (u8)strtoul (p + 1, &eptr, 10);
- *p = 0;
- }
+ if (!p)
+ {
+ ip_prefix->len = ~0; // until we get the ip address family
+ }
+ else
+ {
+ ip_prefix->len = (u8) strtoul (p + 1, &eptr, 10);
+ *p = 0;
+ }
ip_prefix->family = ip_address_get_family (addr);
switch (ip_prefix->family)
{
case AF_INET6:
- if (ip_prefix->len == (u8)~0)
- ip_prefix->len = IPV6_ADDR_LEN_BITS;
+ if (ip_prefix->len == (u8) ~0)
+ ip_prefix->len = IPV6_ADDR_LEN_BITS;
if (ip_prefix->len > IPV6_ADDR_LEN_BITS)
- goto ERR;
+ goto ERR;
pton_fd = inet_pton (AF_INET6, addr, &ip_prefix->address.v6.buffer);
break;
case AF_INET:
- if (ip_prefix->len == (u8)~0)
- ip_prefix->len = IPV4_ADDR_LEN_BITS;
+ if (ip_prefix->len == (u8) ~0)
+ ip_prefix->len = IPV4_ADDR_LEN_BITS;
if (ip_prefix->len > IPV4_ADDR_LEN_BITS)
- goto ERR;
+ goto ERR;
pton_fd = inet_pton (AF_INET, addr, &ip_prefix->address.v4.buffer);
break;
default:
@@ -253,9 +265,9 @@ ip_prefix_pton (const char *ip_address_str, ip_prefix_t * ip_prefix)
// 0 = not in presentation format
// < 0 = other error (use perror)
if (pton_fd <= 0)
- goto ERR;
+ goto ERR;
- free(addr);
+ free (addr);
return 1;
ERR:
free (addr);
@@ -263,129 +275,143 @@ ERR:
}
int
-ip_prefix_ntop_short(const ip_prefix_t * ip_prefix, char *dst, size_t size)
+ip_prefix_ntop_short (const ip_prefix_t *ip_prefix, char *dst, size_t size)
{
char ip_s[MAXSZ_IP_ADDRESS];
- const char * s;
- switch(ip_prefix->family) {
+ const char *s;
+ switch (ip_prefix->family)
+ {
case AF_INET:
- s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
case AF_INET6:
- s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
default:
return -1;
- }
+ }
if (!s)
- return -1;
- int rc = snprintf(dst, size, "%s", ip_s);
+ return -1;
+ int rc = snprintf (dst, size, "%s", ip_s);
if (rc >= size)
- return (int)size;
+ return (int) size;
return rc;
}
int
-ip_prefix_ntop(const ip_prefix_t * ip_prefix, char *dst, size_t size)
+ip_prefix_ntop (const ip_prefix_t *ip_prefix, char *dst, size_t size)
{
char ip_s[MAXSZ_IP_ADDRESS];
- const char * s;
- switch(ip_prefix->family) {
+ const char *s;
+ switch (ip_prefix->family)
+ {
case AF_INET:
- s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
case AF_INET6:
- s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s, MAXSZ_IP_ADDRESS);
+ s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s,
+ MAXSZ_IP_ADDRESS);
break;
default:
return -1;
- }
+ }
if (!s)
- return -1;
- int rc = snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len);
+ return -1;
+ int rc = snprintf (dst, size, "%s/%d", ip_s, ip_prefix->len);
if (rc >= size)
- return (int)size;
+ return (int) size;
return rc;
}
int
-ip_prefix_len (const ip_prefix_t * prefix)
+ip_prefix_snprintf (char *s, size_t size, const ip_prefix_t *prefix)
+{
+ return ip_prefix_ntop (prefix, s, size);
+}
+
+int
+ip_prefix_len (const ip_prefix_t *prefix)
{
- return prefix->len; // ip_address_len(&prefix->address, prefix->family);
+ return prefix->len; // ip_address_len(&prefix->address, prefix->family);
}
const u8 *
-ip_address_get_buffer(const ip_address_t * ip_address, int family)
+ip_address_get_buffer (const ip_address_t *ip_address, int family)
{
- switch(family) {
+ switch (family)
+ {
case AF_INET:
return ip_address->v4.buffer;
case AF_INET6:
return ip_address->v6.buffer;
default:
return NULL;
- }
+ }
}
bool
-ip_prefix_empty (const ip_prefix_t * prefix)
+ip_prefix_empty (const ip_prefix_t *prefix)
{
return prefix->len == 0;
}
int
-ip_prefix_to_sockaddr(const ip_prefix_t * prefix,
- struct sockaddr *sa)
+ip_prefix_to_sockaddr (const ip_prefix_t *prefix, struct sockaddr *sa)
{
- // XXX assert len == ip_address_len
- return ip_address_to_sockaddr(&prefix->address, sa, prefix->family);
+ // XXX assert len == ip_address_len
+ return ip_address_to_sockaddr (&prefix->address, sa, prefix->family);
}
int
-ip_prefix_cmp(const ip_prefix_t * prefix1, const ip_prefix_t * prefix2)
+ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2)
{
- if (prefix1->family < prefix2->family)
- return -1;
- else if (prefix1->family > prefix2->family)
- return 1;
+ if (prefix1->family < prefix2->family)
+ return -1;
+ else if (prefix1->family > prefix2->family)
+ return 1;
- if (prefix1->len < prefix2->len)
- return -1;
- else if (prefix1->len > prefix2->len)
- return 1;
+ if (prefix1->len < prefix2->len)
+ return -1;
+ else if (prefix1->len > prefix2->len)
+ return 1;
- return ip_address_cmp(&prefix1->address, &prefix2->address, prefix1->family);
+ return ip_address_cmp (&prefix1->address, &prefix2->address,
+ prefix1->family);
}
/* URL */
#define MAXSZ_PROTO_ 8 /* inetX:// */
-#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
+#define MAXSZ_PROTO MAXSZ_PROTO_ + NULLTERM
#define MAXSZ_URL4_ MAXSZ_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_
#define MAXSZ_URL6_ MAXSZ_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_
-#define MAXSZ_URL_ MAXSZ_URL6_
-#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
-#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
-#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
+#define MAXSZ_URL_ MAXSZ_URL6_
+#define MAXSZ_URL4 MAXSZ_URL4_ + NULLTERM
+#define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM
+#define MAXSZ_URL MAXSZ_URL_ + NULLTERM
int
-url_snprintf(char * s, size_t size, int family,
- const ip_address_t * ip_address, u16 port)
+url_snprintf (char *s, size_t size, int family, const ip_address_t *ip_address,
+ u16 port)
{
- char ip_address_s[MAXSZ_IP_ADDRESS];
- int rc;
+ char ip_address_s[MAXSZ_IP_ADDRESS];
+ int rc;
- /* Other address are currently not supported */
- if (!IS_VALID_FAMILY(family))
- return -1;
+ /* Other address are currently not supported */
+ if (!IS_VALID_FAMILY (family))
+ return -1;
- rc = ip_address_snprintf(ip_address_s, MAXSZ_IP_ADDRESS, ip_address, family);
- if (rc >= MAXSZ_IP_ADDRESS)
- WARN("[url_snprintf] Unexpected ip_address truncation");
- if (rc < 0)
- return rc;
+ rc =
+ ip_address_snprintf (ip_address_s, MAXSZ_IP_ADDRESS, ip_address, family);
+ if (rc >= MAXSZ_IP_ADDRESS)
+ WARN ("[url_snprintf] Unexpected ip_address truncation");
+ if (rc < 0)
+ return rc;
- return snprintf(s, size, "inet%c://%s:%d", (family == AF_INET) ? '4' : '6',
- ip_address_s, port);
+ return snprintf (s, size, "inet%c://%s:%d", (family == AF_INET) ? '4' : '6',
+ ip_address_s, port);
}
diff --git a/lib/src/util/log.c b/lib/src/util/log.c
index c1fc999ad..975762603 100644
--- a/lib/src/util/log.c
+++ b/lib/src/util/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,6 +18,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#include <strings.h>
#ifdef __ANDROID__
#include <android/log.h>
@@ -25,154 +26,177 @@
log_conf_t log_conf = DEFAULT_LOG_CONF;
-#define FMT_DATETIME "%02d-%02d-%04d %02d:%02d:%02d"
-#define FMT_DATETIME_LEN 20
-#define snprintf_nowarn(...) (snprintf(__VA_ARGS__) < 0 ? abort() : (void)0)
-
+#define FMT_DATETIME "%02d-%02d-%04d %02d:%02d:%02d"
+#define FMT_DATETIME_LEN 20
+#define snprintf_nowarn(...) (snprintf (__VA_ARGS__) < 0 ? abort () : (void) 0)
static char ts[FMT_DATETIME_LEN];
-static char *timestamp(void)
+static char *
+timestamp (void)
{
- time_t tv;
- struct tm *tm;
+ time_t tv;
+ struct tm *tm;
- time(&tv);
- tm = localtime(&tv);
+ time (&tv);
+ tm = localtime (&tv);
- snprintf_nowarn(ts, FMT_DATETIME_LEN, FMT_DATETIME, tm->tm_mday,
- tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
- tm->tm_sec);
- return ts;
+ snprintf_nowarn (ts, FMT_DATETIME_LEN, FMT_DATETIME, tm->tm_mday,
+ tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
+ tm->tm_sec);
+ return ts;
}
-void _log_va(int level, const char *fmt, va_list ap)
-{
+void
+_log_va (int level, const char *fmt, va_list ap)
+{
#if 0
if (!conf.log_system)
return;
#endif
- char *prefix;
+ char *prefix;
#ifdef __ANDROID__
- int prio = -1;
- if (level > log_conf.log_level)
- return;
-
- switch (level) {
- case LOG_FATAL:
- prio = ANDROID_LOG_FATAL;
- prefix = "FATAL: ";
- break;
- case LOG_ERROR:
- prio = ANDROID_LOG_ERROR;
- prefix = "ERROR: ";
- break;
- case LOG_WARN:
- prio = ANDROID_LOG_WARN;
- prefix = "WARNING: ";
- break;
- case LOG_INFO:
- prio = ANDROID_LOG_INFO;
- prefix = "";
- break;
- case LOG_DEBUG:
- prio = ANDROID_LOG_DEBUG;
- prefix = "DEBUG: ";
- break;
- case LOG_TRACE:
- prio = ANDROID_LOG_DEBUG;
- prefix = "TRACE: ";
- break;
- default:
- prio = ANDROID_LOG_INFO;
- prefix = "";
- break;
- }
-
- if (log_conf.log_file) {
- FILE *f = log_conf.log_file;
- fprintf(f, "%s %s", timestamp(), prefix);
- vfprintf(f, fmt, ap);
- fprintf(f, "\n");
- } else {
- __android_log_vprint(ANDROID_LOG_INFO, "HICN FACEMGR", fmt, ap);
- }
+ int prio = -1;
+ if (level > log_conf.log_level)
+ return;
+
+ switch (level)
+ {
+ case LOG_FATAL:
+ prio = ANDROID_LOG_FATAL;
+ prefix = "FATAL: ";
+ break;
+ case LOG_ERROR:
+ prio = ANDROID_LOG_ERROR;
+ prefix = "ERROR: ";
+ break;
+ case LOG_WARN:
+ prio = ANDROID_LOG_WARN;
+ prefix = "WARNING: ";
+ break;
+ case LOG_INFO:
+ prio = ANDROID_LOG_INFO;
+ prefix = "";
+ break;
+ case LOG_DEBUG:
+ prio = ANDROID_LOG_DEBUG;
+ prefix = "DEBUG: ";
+ break;
+ case LOG_TRACE:
+ prio = ANDROID_LOG_DEBUG;
+ prefix = "TRACE: ";
+ break;
+ default:
+ prio = ANDROID_LOG_INFO;
+ prefix = "";
+ break;
+ }
+
+ if (log_conf.log_file)
+ {
+ FILE *f = log_conf.log_file;
+ fprintf (f, "%s %s", timestamp (), prefix);
+ vfprintf (f, fmt, ap);
+ fprintf (f, "\n");
+ }
+ else
+ {
+ __android_log_vprint (ANDROID_LOG_INFO, "HICN FACEMGR", fmt, ap);
+ }
#else
- if (level > log_conf.log_level)
- return;
-
- switch (level) {
- case LOG_FATAL:
- prefix = "FATAL: ";
- break;
- case LOG_ERROR:
- prefix = "ERROR: ";
- break;
- case LOG_WARN:
- prefix = "WARNING: ";
- break;
- case LOG_INFO:
- prefix = "";
- break;
- case LOG_DEBUG:
- prefix = "DEBUG: ";
- break;
- case LOG_TRACE:
- prefix = "TRACE: ";
- break;
- default:
- prefix = "";
- break;
- }
- FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
- fprintf(f, "%s %s", timestamp(), prefix);
- vfprintf(f, fmt, ap);
- fprintf(f, "\n");
+ if (level > log_conf.log_level)
+ return;
+
+ switch (level)
+ {
+ case LOG_FATAL:
+ prefix = "FATAL: ";
+ break;
+ case LOG_ERROR:
+ prefix = "ERROR: ";
+ break;
+ case LOG_WARN:
+ prefix = "WARNING: ";
+ break;
+ case LOG_INFO:
+ prefix = "";
+ break;
+ case LOG_DEBUG:
+ prefix = "DEBUG: ";
+ break;
+ case LOG_TRACE:
+ prefix = "TRACE: ";
+ break;
+ default:
+ prefix = "";
+ break;
+ }
+ FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
+ fprintf (f, "%s %s", timestamp (), prefix);
+ vfprintf (f, fmt, ap);
+ fprintf (f, "\n");
#ifdef DEBUG
- fflush(f);
+ fflush (f);
#endif
#endif
}
-void _log(int level, const char *fmt, ...)
+void
+_log (int level, const char *fmt, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, fmt);
- _log_va(level, fmt, ap);
- va_end(ap);
+ va_start (ap, fmt);
+ _log_va (level, fmt, ap);
+ va_end (ap);
}
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
-void print_trace(void)
+void
+print_trace (void)
{
- void *array[32];
- size_t size;
+ void *array[32];
+ size_t size;
- size = backtrace(array, 32);
- fflush(conf.log_file);
- backtrace_symbols_fd(array, size, fileno(conf.log_file));
+ size = backtrace (array, 32);
+ fflush (conf.log_file);
+ backtrace_symbols_fd (array, size, fileno (conf.log_file));
}
#endif
-void fatal(char *fmt, ...)
+void
+fatal (char *fmt, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, fmt);
- _log_va(LOG_FATAL, fmt, ap);
- va_end(ap);
+ va_start (ap, fmt);
+ _log_va (LOG_FATAL, fmt, ap);
+ va_end (ap);
#ifdef HAVE_BACKTRACE
- print_trace();
+ print_trace ();
#endif
- exit(200);
+ exit (200);
}
+
+const char *loglevel_str[] = { "fatal", "error", "warn",
+ "info", "debug", "trace" };
+
+int
+loglevel_from_str (const char *loglevel)
+{
+ for (int i = 0; i <= LOG_TRACE; i++)
+ {
+ if (strcasecmp (loglevel, loglevel_str[i]) == 0)
+ return i;
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/lib/src/util/windows/dlfcn.c b/lib/src/util/windows/dlfcn.c
index c8173cdb0..5606074a0 100644
--- a/lib/src/util/windows/dlfcn.c
+++ b/lib/src/util/windows/dlfcn.c
@@ -1,4 +1,4 @@
-/* dlfcn.c */
+/* dlfcn.c */
#include <inttypes.h>
#include <stdio.h>
@@ -6,60 +6,68 @@
#include <string.h>
#include <windows.h>
-static struct {
- long lasterror;
- const char *err_rutin;
-} var = {
- 0,
- NULL
-};
+static struct
+{
+ long lasterror;
+ const char *err_rutin;
+} var = { 0, NULL };
-void *dlopen (const char *filename, int flags)
+void *
+dlopen (const char *filename, int flags)
{
- HINSTANCE hInst;
+ HINSTANCE hInst;
- hInst= LoadLibrary (filename);
- if (hInst==NULL) {
- var.lasterror = GetLastError ();
- var.err_rutin = "dlopen";
+ hInst = LoadLibrary (filename);
+ if (hInst == NULL)
+ {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlopen";
}
- return hInst;
+ return hInst;
}
-int dlclose (void *handle)
+int
+dlclose (void *handle)
{
- BOOL ok;
- int rc= 0;
+ BOOL ok;
+ int rc = 0;
- ok= FreeLibrary ((HINSTANCE)handle);
- if (! ok) {
- var.lasterror = GetLastError ();
- var.err_rutin = "dlclose";
- rc= -1;
+ ok = FreeLibrary ((HINSTANCE) handle);
+ if (!ok)
+ {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlclose";
+ rc = -1;
}
- return rc;
+ return rc;
}
-void *dlsym (void *handle, const char *name)
+void *
+dlsym (void *handle, const char *name)
{
- FARPROC fp;
+ FARPROC fp;
- fp= GetProcAddress ((HINSTANCE)handle, name);
- if (!fp) {
- var.lasterror = GetLastError ();
- var.err_rutin = "dlsym";
+ fp = GetProcAddress ((HINSTANCE) handle, name);
+ if (!fp)
+ {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlsym";
}
- return (void *)(intptr_t)fp;
+ return (void *) (intptr_t) fp;
}
-const char *dlerror (void)
+const char *
+dlerror (void)
{
-static char errstr [88];
+ static char errstr[88];
- if (var.lasterror) {
- sprintf (errstr, "%s error #%ld", var.err_rutin, var.lasterror);
- return errstr;
- } else {
- return NULL;
+ if (var.lasterror)
+ {
+ snprintf (errstr, 88, "%s error #%ld", var.err_rutin, var.lasterror);
+ return errstr;
+ }
+ else
+ {
+ return NULL;
}
} \ No newline at end of file
diff --git a/libtransport/.clang-format b/libtransport/.clang-format
index 513da4d69..ae46ce82d 100644
--- a/libtransport/.clang-format
+++ b/libtransport/.clang-format
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/CMakeLists.txt b/libtransport/CMakeLists.txt
index a5009f353..62c0c0788 100644
--- a/libtransport/CMakeLists.txt
+++ b/libtransport/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,29 +11,36 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+##############################################################
+# Project and cmake version
+##############################################################
# CMake 3.11 required to use FetchContent
cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
-
project(libtransport)
+
+##############################################################
+# Cmake modules
+##############################################################
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
- "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+ ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules
)
+include("${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake")
-include(DefaultConfiguration)
-include(BuildMacros)
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif ()
+##############################################################
+# C/CXX Standard
+##############################################################
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_C_STANDARD 11)
-set(TRANSPORT_ROOT_PATH "src")
+##############################################################
+# Libs and Bins names
+##############################################################
set(LIBTRANSPORT hicntransport)
-set(LIBTRANSPORT_COMPONENT libhicntransport)
+set(LIBTRANSPORT_COMPONENT lib${LIBTRANSPORT})
if ((BUILD_HICNPLUGIN OR BUILD_MEMIF_CONNECTOR) AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(__vpp__ 1)
@@ -42,19 +49,32 @@ endif ()
set(LIBTRANSPORT ${LIBTRANSPORT} CACHE INTERNAL "" FORCE)
set(LIBTRANSPORT_SHARED ${LIBTRANSPORT}.shared CACHE INTERNAL "" FORCE)
set(LIBTRANSPORT_STATIC ${LIBTRANSPORT}.static CACHE INTERNAL "" FORCE)
-set(LIBTRANSPORT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src CACHE INTERNAL "" FORCE)
-include(WindowsMacros)
-include(IosMacros)
-find_package_wrapper(Asio REQUIRED)
-find_package(OpenSSL REQUIRED)
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(Asio ${ASIO_DEFAULT_VERSION} REQUIRED)
+find_package(OpenSSL ${OPENSSL_DEFAULT_VERSION} EXACT REQUIRED)
find_package(Threads REQUIRED)
-find_package(OpenSSL REQUIRED)
-find_package(Libconfig++ REQUIRED)
+find_package(Libconfig++ ${LIBCONFIG_DEFAULT_VERSION} REQUIRED)
+add_subdirectory(third-party)
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package_wrapper(Libhicn REQUIRED)
+ include(CommonSetup)
+ find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
+
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+
+ list(APPEND HICN_LIBRARIES hicn::hicn.${LIBTYPE})
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
@@ -73,34 +93,16 @@ else()
endif()
endif()
-include(Packaging)
-
-add_subdirectory(third-party)
-
-set(LIBRARIES
- PRIVATE ${HICN_LIBRARIES}
- PRIVATE ${CMAKE_THREAD_LIBS_INIT}
- PRIVATE ${CMAKE_DL_LIBS}
- PRIVATE ${OPENSSL_LIBRARIES}
- PRIVATE ${LIBCONFIG_CPP_LIBRARIES}
- PRIVATE ${THIRD_PARTY_LIBRARIES}
-)
-# Include dirs -- Order does matter!
-list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
- ${HICN_INCLUDE_DIRS}
- ${HICNPLUGIN_INCLUDE_DIRS}
- ${CMAKE_THREADS_INCLUDE_DIRS}
- ${ASIO_INCLUDE_DIRS}
- ${WINDOWS_INCLUDE_DIRS}
- ${OPENSSL_INCLUDE_DIR}
- ${CONFIG_INCLUDE_DIRS}
- ${THIRD_PARTY_INCLUDE_DIRS}
-)
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
-list(APPEND DEPENDENCIES
- ${THIRD_PARTY_DEPENDENCIES}
-)
+##############################################################
+# Subdirectories
+##############################################################
add_subdirectory(includes/hicn/transport)
-add_subdirectory(${TRANSPORT_ROOT_PATH})
+add_subdirectory(src)
diff --git a/libtransport/cmake/Modules/Android.cmake b/libtransport/cmake/Modules/Android.cmake
deleted file mode 100644
index 78918455a..000000000
--- a/libtransport/cmake/Modules/Android.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-function (configure_android_environment)
- set(CMAKE_CXX_FLAGS " -Wall -stdlib=libc++ -DASIO_STANDALONE -pthread -isystem -lm")
-
- #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
- #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS}" PARENT_SCOPE)
-endfunction() \ No newline at end of file
diff --git a/libtransport/cmake/Modules/DefaultConfiguration.cmake b/libtransport/cmake/Modules/DefaultConfiguration.cmake
deleted file mode 100644
index 402ad86f5..000000000
--- a/libtransport/cmake/Modules/DefaultConfiguration.cmake
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# C/c++ standard
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_C_STANDARD 11)
-
-# Compilation flags
-
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
-if (NOT WIN32)
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fpermissive")
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fpermissive")
- set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -fpermissive")
-endif ()
-
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
-set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
-set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
-set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") \ No newline at end of file
diff --git a/libtransport/cmake/Modules/Ios.cmake b/libtransport/cmake/Modules/Ios.cmake
deleted file mode 100644
index 1b2aae2bf..000000000
--- a/libtransport/cmake/Modules/Ios.cmake
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-function (configure_ios_environment)
- find_host_package ( OpenSSL REQUIRED )
- include_directories(extras/iOS)
-
- find_host_package(Libhicn REQUIRED)
- include_directories(${HICN_INCLUDE_DIRS})
-endfunction() \ No newline at end of file
diff --git a/libtransport/cmake/Modules/Packaging.cmake b/libtransport/cmake/packaging.cmake
index 9ff26aecc..f7f0c27e3 100644
--- a/libtransport/cmake/Modules/Packaging.cmake
+++ b/libtransport/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -17,6 +17,11 @@
# Packages section
######################
+##############################################################
+# Get VPP version
+##############################################################
+list(GET VPP_DEFAULT_VERSION 0 VPP_VERSION)
+
set(${LIBTRANSPORT_COMPONENT}_DESCRIPTION
"Libhicn-transport provides transport services and \
socket API for applications willing to communicate \
@@ -28,7 +33,7 @@ set(${LIBTRANSPORT_COMPONENT}-dev_DESCRIPTION
CACHE STRING "Header files for developing using libhicntransport."
)
-set(${LIBTRANSPORT_COMPONENT}-devel_DESCRIPTION
+set(lib${LIBTRANSPORT}-devel_DESCRIPTION
CACHE STRING "Header files for developing using libhicntransport."
)
@@ -37,31 +42,44 @@ set(${LIBTRANSPORT_COMPONENT}-io-modules_DESCRIPTION
)
set(${LIBTRANSPORT_COMPONENT}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), libparc (>= 1.0), libconfig++9v5 (>= 1.5-0.4build1)"
+ "lib${LIBHICN} (= stable_version), libconfig++9v5 (>= 1.5-0.4build1)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBTRANSPORT_COMPONENT}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, libparc >= 1.0, libconfig >= 1.5-9.el8"
+ "lib${LIBHICN} = stable_version, libconfig >= 1.5-9.el8"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBTRANSPORT_COMPONENT}-dev_DEB_DEPENDENCIES
- "${LIBTRANSPORT_COMPONENT} (>= stable_version), libasio-dev (>= 1.10), lib${LIBHICN}-dev (>= stable_version), libparc-dev (>= 1.0), libconfig++-dev (>= 1.5-0.4build1)"
+ "${LIBTRANSPORT_COMPONENT} (= stable_version), libasio-dev (>= 1.10), lib${LIBHICN}-dev (= stable_version), libconfig++-dev (>= 1.5-0.4build1)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBTRANSPORT_COMPONENT}-dev_RPM_DEPENDENCIES
- "${LIBTRANSPORT_COMPONENT} >= stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel >= stable_version, libparc-devel >= 1.0, libconfig-devel >= 1.5-9.el8"
+ "${LIBTRANSPORT_COMPONENT} = stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel = stable_version, libconfig-devel >= 1.5-9.el8"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBTRANSPORT_COMPONENT}-io-modules_DEB_DEPENDENCIES
- "${LIBTRANSPORT_COMPONENT} (>= stable_version), libmemif (>= stable_version), vpp (>= stable_version-release), vpp (<< next_version-release), hicn-plugin (>= stable_version)"
+ "${LIBTRANSPORT_COMPONENT} (= stable_version), vpp (>= ${VPP_VERSION}), hicn-plugin (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${LIBTRANSPORT_COMPONENT}-io-modules_RPM_DEPENDENCIES
- "${LIBTRANSPORT_COMPONENT} >= stable_version, libmemif >= stable_version, vpp >= stable_version-release, vpp < next_version-release, hicn-plugin >= stable_version"
+ "${LIBTRANSPORT_COMPONENT} = stable_version, vpp >= ${VPP_VERSION}, hicn-plugin = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
+
+if (INTERNAL_ENVIRONMENT)
+ include(CheckSsl)
+ CheckSsl()
+ set(${LIBTRANSPORT_COMPONENT}_DEB_DEPENDENCIES
+ "${${LIBTRANSPORT_COMPONENT}_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY}"
+ CACHE STRING "Dependencies for deb/rpm package."
+ )
+ set(${LIBTRANSPORT_COMPONENT}-dev_DEB_DEPENDENCIES
+ "${${LIBTRANSPORT_COMPONENT}-dev_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY_DEV}"
+ CACHE STRING "Dependencies for deb/rpm package."
+ )
+endif ()
diff --git a/libtransport/includes/hicn/transport/CMakeLists.txt b/libtransport/includes/hicn/transport/CMakeLists.txt
index eb339fb5a..8b9f907b9 100644
--- a/libtransport/includes/hicn/transport/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -23,14 +23,21 @@ add_subdirectory(portability)
add_subdirectory(auth)
add_subdirectory(utils)
-set(LIBTRANSPORT_INCLUDE_DIRS
- ${CMAKE_CURRENT_SOURCE_DIR}/../.. ""
+
+##############################################################
+# Public headers directory
+##############################################################
+set(Libhicntransport_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/../..
CACHE INTERNAL
"" FORCE
)
+
+##############################################################
+# Header files to install
+##############################################################
set(LIBHICNTRANSPORT_TO_INSTALL_HEADER_FILES
- ${HEADER_FILES} ""
- CACHE INTERNAL
- "" FORCE
+ ${HEADER_FILES}
+ PARENT_SCOPE
)
diff --git a/libtransport/includes/hicn/transport/auth/CMakeLists.txt b/libtransport/includes/hicn/transport/auth/CMakeLists.txt
index 1e9fe4698..0b5ae1836 100644
--- a/libtransport/includes/hicn/transport/auth/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/auth/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -15,7 +15,6 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/common.h
${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.h
${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.h
- ${CMAKE_CURRENT_SOURCE_DIR}/identity.h
${CMAKE_CURRENT_SOURCE_DIR}/key_id.h
${CMAKE_CURRENT_SOURCE_DIR}/policies.h
${CMAKE_CURRENT_SOURCE_DIR}/signer.h
diff --git a/libtransport/includes/hicn/transport/auth/common.h b/libtransport/includes/hicn/transport/auth/common.h
index fb0e82eb7..d2282436e 100644
--- a/libtransport/includes/hicn/transport/auth/common.h
+++ b/libtransport/includes/hicn/transport/auth/common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/auth/crypto_hash.h b/libtransport/includes/hicn/transport/auth/crypto_hash.h
index 90f1627e9..3c734fee3 100644
--- a/libtransport/includes/hicn/transport/auth/crypto_hash.h
+++ b/libtransport/includes/hicn/transport/auth/crypto_hash.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -89,7 +89,7 @@ class CryptoHash {
static std::size_t getSize(CryptoHashType hash_type);
// Compare two raw buffers
- static bool compareDigest(const uint8_t *h1, const uint8_t *h2,
+ static bool compareDigest(const uint8_t *digest1, const uint8_t *digest2,
CryptoHashType hash_type);
private:
diff --git a/libtransport/includes/hicn/transport/auth/crypto_suite.h b/libtransport/includes/hicn/transport/auth/crypto_suite.h
index d0f1de395..ed21abb91 100644
--- a/libtransport/includes/hicn/transport/auth/crypto_suite.h
+++ b/libtransport/includes/hicn/transport/auth/crypto_suite.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -47,6 +47,9 @@ enum class CryptoSuite : uint8_t {
// Return the suite associated to the given NID
CryptoSuite getSuite(int nid);
+// Return the string representation of given suite
+std::string getStringSuite(CryptoSuite suite);
+
// Return the hash type associated to the given suite
CryptoHashType getHashType(CryptoSuite suite);
diff --git a/libtransport/includes/hicn/transport/auth/identity.h b/libtransport/includes/hicn/transport/auth/identity.h
deleted file mode 100644
index be072f5d3..000000000
--- a/libtransport/includes/hicn/transport/auth/identity.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <errno.h>
-#include <fcntl.h>
-#include <hicn/transport/auth/signer.h>
-#include <unistd.h>
-
-extern "C" {
-#include <openssl/pkcs12.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-}
-
-namespace transport {
-namespace auth {
-
-class Identity {
- // This class holds several information about a client, including its public
- // key.
- public:
- // Generate a new identity from the given parameters. The identity will be
- // saved in 'keystore_path' and encrypted using 'keystore_pwd'.
- Identity(const std::string &keystore_path, const std::string &keystore_pwd,
- CryptoSuite suite, unsigned int signature_len,
- unsigned int validity_days, const std::string &subject_name);
-
- // Create an identity from an already existing keystore path.
- Identity(std::string &keystore_path, std::string &keystore_pwd,
- CryptoHashType hash_type);
-
- Identity(const Identity &other);
- Identity(Identity &&other);
- ~Identity();
-
- // Return the asymmetric signer object created from the public key.
- std::shared_ptr<AsymmetricSigner> getSigner() const;
-
- // Return the key store filename.
- std::string getFilename() const;
-
- // Return the key store password.
- std::string getPassword() const;
-
- std::shared_ptr<X509> getCertificate() const;
-
- std::shared_ptr<EVP_PKEY> getPrivateKey() const;
-
- // Generate a new random identity.
- static Identity generateIdentity(const std::string &subject_name = "");
-
- private:
- static void free_key(EVP_PKEY *T) { EVP_PKEY_free(T); }
-
- std::string pwd_;
- std::string filename_;
- std::shared_ptr<AsymmetricSigner> signer_;
- std::shared_ptr<X509> cert_;
-};
-
-} // namespace auth
-} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/key_id.h b/libtransport/includes/hicn/transport/auth/key_id.h
index 3aa09336f..8723ae698 100644
--- a/libtransport/includes/hicn/transport/auth/key_id.h
+++ b/libtransport/includes/hicn/transport/auth/key_id.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/auth/policies.h b/libtransport/includes/hicn/transport/auth/policies.h
index 00464d54b..b9755595c 100644
--- a/libtransport/includes/hicn/transport/auth/policies.h
+++ b/libtransport/includes/hicn/transport/auth/policies.h
@@ -23,10 +23,10 @@ namespace auth {
* perform after verification.
*/
enum class VerificationPolicy {
+ UNKNOWN,
ABORT,
- ACCEPT,
DROP,
- UNKNOWN,
+ ACCEPT,
};
} // namespace auth
diff --git a/libtransport/includes/hicn/transport/auth/signer.h b/libtransport/includes/hicn/transport/auth/signer.h
index 405dd83cf..5a7598991 100644
--- a/libtransport/includes/hicn/transport/auth/signer.h
+++ b/libtransport/includes/hicn/transport/auth/signer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -21,18 +21,19 @@
#include <hicn/transport/errors/errors.h>
#include <hicn/transport/utils/membuf.h>
+#include <memory>
extern "C" {
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#include <openssl/pkcs12.h>
+#include <openssl/x509.h>
}
namespace transport {
namespace auth {
-class Identity;
class Signer {
// The base class from which all signer classes derive.
- friend class Identity;
public:
Signer();
@@ -47,6 +48,9 @@ class Signer {
// Return the signature.
std::vector<uint8_t> getSignature() const;
+ // Return the signature as a string
+ std::string getStringSignature() const;
+
// Return the signature size in bytes.
virtual std::size_t getSignatureSize() const;
@@ -61,6 +65,9 @@ class Signer {
// Return the hash algorithm associated to the signer.
CryptoHashType getHashType() const;
+ // Print signature to stdout
+ void display();
+
protected:
CryptoSuite suite_;
std::vector<uint8_t> signature_;
@@ -84,10 +91,17 @@ class AsymmetricSigner : public Signer {
public:
AsymmetricSigner() = default;
- // Construct an AsymmetricSigner from a key store and a given crypto suite.
+ // Create an AsymmetricSigner from a keystore file (.p12).
+ AsymmetricSigner(std::string keystore_path, std::string password);
+
+ // Construct an AsymmetricSigner from a key store and a given crypto
+ // suite.
AsymmetricSigner(CryptoSuite suite, std::shared_ptr<EVP_PKEY> key,
std::shared_ptr<EVP_PKEY> pub_key);
+ void setKey(CryptoSuite suite, std::shared_ptr<EVP_PKEY> key,
+ std::shared_ptr<EVP_PKEY> pub_key);
+
std::size_t getSignatureFieldSize() const override;
};
diff --git a/libtransport/includes/hicn/transport/auth/verifier.h b/libtransport/includes/hicn/transport/auth/verifier.h
index 6321d4ed5..677a1efe4 100644
--- a/libtransport/includes/hicn/transport/auth/verifier.h
+++ b/libtransport/includes/hicn/transport/auth/verifier.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -40,9 +40,9 @@ class Verifier {
// The VerificationFailedCallback will be called by the transport if a
// data packet (either a manifest or a content object) was not validated.
// The application decides what to do then by returning a
- // VerificationPolicy object.
+ // new VerificationPolicy.
using VerificationFailedCallback = std::function<auth::VerificationPolicy(
- const core::ContentObject &content_object, std::error_code ec)>;
+ Suffix suffix, VerificationPolicy policy)>;
// The list of VerificationPolicy that will trigger the
// VerificationFailedCallback.
@@ -96,13 +96,13 @@ class Verifier {
void getVerificationFailedCallback(
VerificationFailedCallback **verification_failed_cb);
+ // Call VerificationFailedCallback if it is set and update the packet policy.
+ void callVerificationFailedCallback(Suffix suffix,
+ VerificationPolicy &policy);
+
protected:
VerificationFailedCallback verification_failed_cb_;
std::vector<VerificationPolicy> failed_policies_;
-
- // Call VerificationFailedCallback if it is set and update the packet policy.
- void callVerificationFailedCallback(PacketPtr packet,
- VerificationPolicy &policy);
};
class VoidVerifier : public Verifier {
diff --git a/libtransport/includes/hicn/transport/core/CMakeLists.txt b/libtransport/includes/hicn/transport/core/CMakeLists.txt
index 14c795a7a..34048d93a 100644
--- a/libtransport/includes/hicn/transport/core/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/core/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/includes/hicn/transport/core/connector.h b/libtransport/includes/hicn/transport/core/connector.h
index dcf38cdc8..b671a7d89 100644
--- a/libtransport/includes/hicn/transport/core/connector.h
+++ b/libtransport/includes/hicn/transport/core/connector.h
@@ -15,6 +15,7 @@
#pragma once
+#include <glog/logging.h>
#include <hicn/transport/core/connector_stats.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/endpoint.h>
@@ -50,22 +51,21 @@ class Connector : public std::enable_shared_from_this<Connector> {
enum class Role : std::uint8_t { CONSUMER, PRODUCER };
- public:
static constexpr std::size_t queue_size = 4096;
static constexpr std::uint32_t invalid_connector = ~0;
-
-#ifdef LINUX
+ static constexpr std::uint32_t max_reconnection_reattempts = 5;
static constexpr std::uint16_t max_burst = 256;
-#endif
using Ptr = std::shared_ptr<Connector>;
- using PacketQueue = std::deque<Packet::Ptr>;
- using PacketReceivedCallback = std::function<void(
- Connector *, utils::MemBuf &, const std::error_code &)>;
+ using PacketQueue = std::deque<utils::MemBuf::Ptr>;
+ using PacketReceivedCallback =
+ std::function<void(Connector *, const std::vector<utils::MemBuf::Ptr> &,
+ const std::error_code &)>;
using PacketSentCallback =
std::function<void(Connector *, const std::error_code &)>;
using OnCloseCallback = std::function<void(Connector *)>;
- using OnReconnectCallback = std::function<void(Connector *)>;
+ using OnReconnectCallback =
+ std::function<void(Connector *, const std::error_code &)>;
using Id = std::uint64_t;
template <typename ReceiveCallback, typename SentCallback, typename OnClose,
@@ -77,7 +77,8 @@ class Connector : public std::enable_shared_from_this<Connector> {
on_close_callback_(std::forward<OnClose &&>(close_callback)),
on_reconnect_callback_(std::forward<OnReconnect &&>(on_reconnect)),
state_(State::CLOSED),
- connector_id_(invalid_connector) {}
+ connector_id_(invalid_connector),
+ connection_reattempts_(0) {}
virtual ~Connector(){};
@@ -115,7 +116,7 @@ class Connector : public std::enable_shared_from_this<Connector> {
virtual void send(Packet &packet) = 0;
- virtual void send(const uint8_t *packet, std::size_t len) = 0;
+ virtual void send(const utils::MemBuf::Ptr &buffer) = 0;
virtual void close() = 0;
@@ -206,6 +207,9 @@ class Connector : public std::enable_shared_from_this<Connector> {
// Stats
AtomicConnectorStats stats_;
+
+ // Connection attempts
+ std::uint32_t connection_reattempts_;
};
} // namespace core
diff --git a/libtransport/includes/hicn/transport/core/content_object.h b/libtransport/includes/hicn/transport/core/content_object.h
index 38baafc69..a8df1e8e3 100644
--- a/libtransport/includes/hicn/transport/core/content_object.h
+++ b/libtransport/includes/hicn/transport/core/content_object.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -31,10 +31,9 @@ class ContentObject : public Packet {
using Ptr = std::shared_ptr<ContentObject>;
using HICNContentObject = hicn_header_t;
- ContentObject(Packet::Format format = HF_INET6_TCP,
- std::size_t additional_header_size = 0);
+ ContentObject(Packet::Format format, std::size_t additional_header_size = 0);
- ContentObject(const Name &name, Packet::Format format = HF_INET6_TCP,
+ ContentObject(const Name &name, Packet::Format format,
std::size_t additional_header_size = 0);
ContentObject(const Name &name, hicn_format_t format,
@@ -42,7 +41,7 @@ class ContentObject : public Packet {
std::size_t payload_size);
template <typename... Args>
- ContentObject(CopyBufferOp op, Args &&... args)
+ ContentObject(CopyBufferOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
0) {
@@ -51,7 +50,7 @@ class ContentObject : public Packet {
}
template <typename... Args>
- ContentObject(WrapBufferOp op, Args &&... args)
+ ContentObject(WrapBufferOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
0) {
@@ -60,8 +59,12 @@ class ContentObject : public Packet {
}
template <typename... Args>
- ContentObject(CreateOp op, Args &&... args)
+ ContentObject(CreateOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
+ if (hicn_packet_set_data(format_, packet_start_) < 0) {
+ throw errors::MalformedPacketException();
+ }
+
if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
0) {
throw errors::MalformedPacketException();
@@ -96,6 +99,10 @@ class ContentObject : public Packet {
auto shared_from_this() { return utils::shared_from(this); }
+ bool isLast() const;
+
+ void setLast();
+
private:
void resetForHash() override;
};
diff --git a/libtransport/includes/hicn/transport/core/endpoint.h b/libtransport/includes/hicn/transport/core/endpoint.h
index cb6b0f562..e1fa193d7 100644
--- a/libtransport/includes/hicn/transport/core/endpoint.h
+++ b/libtransport/includes/hicn/transport/core/endpoint.h
@@ -42,14 +42,20 @@ class Endpoint {
~Endpoint() = default;
Endpoint &operator=(const Endpoint &other) {
- address_ = other.address_;
- port_ = other.port_;
+ if (this != &other) {
+ address_ = other.address_;
+ port_ = other.port_;
+ }
+
return *this;
}
Endpoint &operator=(Endpoint &&other) {
- address_ = std::move(other.address_);
- port_ = std::move(other.port_);
+ if (this != &other) {
+ address_ = std::move(other.address_);
+ port_ = std::move(other.port_);
+ }
+
return *this;
}
diff --git a/libtransport/includes/hicn/transport/core/global_object_pool.h b/libtransport/includes/hicn/transport/core/global_object_pool.h
index d7f3a9e41..f98df521f 100644
--- a/libtransport/includes/hicn/transport/core/global_object_pool.h
+++ b/libtransport/includes/hicn/transport/core/global_object_pool.h
@@ -27,9 +27,10 @@ namespace transport {
namespace core {
template <std::size_t packet_pool_size = 1024, std::size_t chunk_size = 2048>
-class PacketManager
- : public utils::Singleton<PacketManager<packet_pool_size, chunk_size>> {
- friend class utils::Singleton<PacketManager<packet_pool_size, chunk_size>>;
+class PacketManager : public utils::ThreadLocalSingleton<
+ PacketManager<packet_pool_size, chunk_size>> {
+ friend class utils::ThreadLocalSingleton<
+ PacketManager<packet_pool_size, chunk_size>>;
public:
using MemoryPool = utils::FixedBlockAllocator<chunk_size, packet_pool_size>;
@@ -71,7 +72,10 @@ class PacketManager
template <
typename PacketType, typename... Args,
typename = std::enable_if_t<std::is_base_of<Packet, PacketType>::value>>
- typename PacketType::Ptr getPacket(Args &&... args) {
+ typename PacketType::Ptr getPacket(Args &&...args) {
+ static_assert(sizeof(PacketType) + sizeof(std::shared_ptr<PacketType>) +
+ sizeof(std::max_align_t) <=
+ sizeof(PacketStorage::packet_and_shared_ptr));
PacketType *memory = nullptr;
memory = reinterpret_cast<PacketType *>(memory_pool_.allocateBlock());
@@ -98,7 +102,7 @@ class PacketManager
template <typename PacketType, typename... Args>
typename PacketType::Ptr getPacketFromExistingBuffer(uint8_t *buffer,
std::size_t length,
- Args &&... args) {
+ Args &&...args) {
auto offset = offsetof(PacketStorage, align);
auto memory = reinterpret_cast<PacketType *>(buffer - offset);
utils::STLAllocator<PacketType, MemoryPool> allocator(memory,
diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h
index a5b9cf375..b7ce3c3a0 100644
--- a/libtransport/includes/hicn/transport/core/interest.h
+++ b/libtransport/includes/hicn/transport/core/interest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -40,16 +40,15 @@ class Interest
public:
using Ptr = std::shared_ptr<Interest>;
- Interest(Packet::Format format = HF_INET6_TCP,
- std::size_t additional_header_size = 0);
+ Interest(Packet::Format format, std::size_t additional_header_size = 0);
- Interest(const Name &interest_name, Packet::Format format = HF_INET6_TCP,
+ Interest(const Name &interest_name, Packet::Format format,
std::size_t additional_header_size = 0);
Interest(MemBuf &&buffer);
template <typename... Args>
- Interest(CopyBufferOp op, Args &&... args)
+ Interest(CopyBufferOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_interest_get_name(format_, packet_start_,
name_.getStructReference()) < 0) {
@@ -58,7 +57,7 @@ class Interest
}
template <typename... Args>
- Interest(WrapBufferOp op, Args &&... args)
+ Interest(WrapBufferOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_interest_get_name(format_, packet_start_,
name_.getStructReference()) < 0) {
@@ -67,8 +66,12 @@ class Interest
}
template <typename... Args>
- Interest(CreateOp op, Args &&... args)
- : Packet(op, std::forward<Args>(args)...) {}
+ Interest(CreateOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {
+ if (hicn_packet_set_interest(format_, packet_start_) < 0) {
+ throw errors::MalformedPacketException();
+ }
+ }
/* Move constructor */
Interest(Interest &&other_interest);
diff --git a/libtransport/includes/hicn/transport/core/io_module.h b/libtransport/includes/hicn/transport/core/io_module.h
index ea3cf4e16..817d96d00 100644
--- a/libtransport/includes/hicn/transport/core/io_module.h
+++ b/libtransport/includes/hicn/transport/core/io_module.h
@@ -40,7 +40,7 @@ typedef struct {
class Connector;
-class IoModule {
+class IoModule : utils::NonCopyable {
protected:
IoModule()
: inet_address_({}),
@@ -64,15 +64,20 @@ class IoModule {
virtual bool isConnected() = 0;
virtual void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") = 0;
virtual void registerRoute(const Prefix &prefix) = 0;
+ virtual void sendMapme() {}
+
+ virtual void setForwardingStrategy(const Prefix &prefix,
+ std::string &strategy){};
virtual std::uint32_t getMtu() = 0;
- virtual bool isControlMessage(const uint8_t *message) = 0;
+ virtual bool isControlMessage(utils::MemBuf &packet_buffer) = 0;
virtual void processControlMessageReply(utils::MemBuf &packet_buffer) = 0;
@@ -89,7 +94,7 @@ class IoModule {
}
}
- virtual void send(const uint8_t *packet, std::size_t len) = 0;
+ virtual void send(const utils::MemBuf::Ptr &buffer) = 0;
void setContentStoreSize(uint32_t cs_size) {
content_store_reserved_ = cs_size;
diff --git a/libtransport/includes/hicn/transport/core/name.h b/libtransport/includes/hicn/transport/core/name.h
index 033582289..5cb4efd10 100644
--- a/libtransport/includes/hicn/transport/core/name.h
+++ b/libtransport/includes/hicn/transport/core/name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -51,7 +51,7 @@ class Name {
public:
using NameStruct = hicn_name_t;
- using Type = hicn_name_type_t;
+ enum class Type { UNDEFINED, V4, V6 };
Name();
@@ -69,6 +69,8 @@ class Name {
Name(const Name &name);
+ ~Name();
+
Name &operator=(const Name &name);
bool operator==(const Name &name) const;
@@ -91,14 +93,11 @@ class Name {
uint32_t getSuffix() const;
- std::shared_ptr<Sockaddr> getAddress() const;
-
Name &setSuffix(uint32_t seq_number);
ip_prefix_t toIpAddress() const;
- void copyToDestination(uint8_t *destination,
- bool include_suffix = false) const;
+ void copyPrefixToDestination(uint8_t *destination) const;
int getAddressFamily() const;
diff --git a/libtransport/includes/hicn/transport/core/packet.h b/libtransport/includes/hicn/transport/core/packet.h
index 269a1571a..059430f1d 100644
--- a/libtransport/includes/hicn/transport/core/packet.h
+++ b/libtransport/includes/hicn/transport/core/packet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -30,11 +30,7 @@ namespace transport {
namespace auth {
class Signer;
-class AsymmetricSigner;
-class SymmetricSigner;
class Verifier;
-class AsymmetricVerifier;
-class SymmetricVerifier;
} // namespace auth
namespace core {
@@ -51,16 +47,13 @@ namespace core {
class Packet : public utils::MemBuf,
public std::enable_shared_from_this<Packet> {
friend class auth::Signer;
- friend class auth::SymmetricSigner;
- friend class auth::AsymmetricSigner;
friend class auth::Verifier;
- friend class auth::AsymmetricVerifier;
- friend class auth::SymmetricVerifier;
public:
using Ptr = std::shared_ptr<Packet>;
using MemBufPtr = std::shared_ptr<utils::MemBuf>;
using Format = hicn_format_t;
+
static constexpr size_t default_mtu = 1500;
/**
@@ -68,146 +61,73 @@ class Packet : public utils::MemBuf,
* the eventual payload will be added by prepending the payload buffer
* to the buffer chain whose the fist buffer is the header itself.
*/
- Packet(Format format = HF_INET6_TCP, std::size_t additional_header_size = 0);
-
- /**
- * Create new IP packet using raw buffer.
- */
-
+ Packet(Format format, std::size_t additional_header_size = 0);
/* Copy buffer */
Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size);
/* Wrap buffer */
Packet(WrapBufferOp, uint8_t *buffer, std::size_t length, std::size_t size);
/* Create new using pre-allocated buffer */
Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size,
- Format format = HF_INET6_TCP, std::size_t additional_header_size = 0);
- /* Move MemBuf */
- Packet(MemBuf &&buffer);
+ Format format, std::size_t additional_header_size = 0);
+ Packet(MemBuf &&buffer);
Packet(Packet &&other);
-
- /*
- * Copy constructor and assignemnt operators.
- */
Packet(const Packet &other);
- Packet &operator=(const Packet &other);
-
- friend bool operator==(const Packet &l_packet, const Packet &r_packet);
+ // Destructor
virtual ~Packet();
- static std::size_t getHeaderSizeFromFormat(Format format,
- std::size_t signature_size = 0) {
- std::size_t header_length;
- hicn_packet_get_header_length_from_format(format, &header_length);
- int is_ah = _is_ah(format);
- return is_ah * (header_length + signature_size) + (!is_ah) * header_length;
- }
-
- static std::size_t getHeaderSizeFromBuffer(Format format,
- const uint8_t *buffer);
-
- static std::size_t getPayloadSizeFromBuffer(Format format,
- const uint8_t *buffer);
-
- static bool isInterest(const uint8_t *buffer);
-
- bool isInterest();
-
- static Format getFormatFromBuffer(const uint8_t *buffer, std::size_t length) {
- Format format = HF_UNSPEC;
- hicn_packet_get_format((const hicn_header_t *)buffer, &format);
- return format;
- }
-
- void reset() {
- clear();
- packet_start_ = reinterpret_cast<hicn_header_t *>(writableData());
- header_offset_ = 0;
- format_ = HF_UNSPEC;
- payload_type_ = PayloadType::UNSPECIFIED;
- name_.clear();
-
- if (isChained()) {
- separateChain(next(), prev());
- }
- }
-
- void setFormat(Packet::Format format = HF_INET6_TCP,
- std::size_t additional_header_size = 0);
-
- std::size_t payloadSize() const;
-
- std::size_t headerSize() const;
+ // Operators
+ Packet &operator=(const Packet &other);
+ friend bool operator==(const Packet &l_packet, const Packet &r_packet);
+ // Cast to MemBuf
std::shared_ptr<utils::MemBuf> acquireMemBufReference();
- virtual const Name &getName() const = 0;
+ // Format
+ Format getFormat() const;
+ void setFormat(Packet::Format format, std::size_t additional_header_size = 0);
+ // Name
+ virtual const Name &getName() const = 0;
virtual Name &getWritableName() = 0;
-
virtual void setName(const Name &name) = 0;
+ // Lifetime
virtual void setLifetime(uint32_t lifetime) = 0;
-
virtual uint32_t getLifetime() const = 0;
- Packet &appendPayload(const uint8_t *buffer, std::size_t length);
-
- Packet &appendPayload(std::unique_ptr<utils::MemBuf> &&payload);
-
- std::unique_ptr<utils::MemBuf> getPayload() const;
-
- Packet &updateLength(std::size_t length = 0);
-
- PayloadType getPayloadType() const;
-
- Packet &setPayloadType(PayloadType payload_type);
-
- Format getFormat() const;
-
- void dump() const;
-
- static void dump(uint8_t *buffer, std::size_t length);
-
+ // Locator
virtual void setLocator(const ip_address_t &locator) = 0;
-
virtual ip_address_t getLocator() const = 0;
- /**
- * @brief Set signature timestamp, in milliseconds.
- */
- void setSignatureTimestamp(const uint64_t &timestamp_milliseconds);
-
- uint64_t getSignatureTimestamp() const;
-
- void setValidationAlgorithm(const auth::CryptoSuite &validation_algorithm);
-
- auth::CryptoSuite getValidationAlgorithm() const;
-
- void setKeyId(const auth::KeyId &key_id);
+ // Payload type
+ PayloadType getPayloadType() const;
+ Packet &setPayloadType(PayloadType payload_type);
- auth::KeyId getKeyId() const;
+ // Payload
+ std::unique_ptr<utils::MemBuf> getPayload() const;
+ Packet &appendPayload(std::unique_ptr<utils::MemBuf> &&payload);
+ Packet &appendPayload(const uint8_t *buffer, std::size_t length);
- virtual auth::CryptoHash computeDigest(auth::CryptoHashType algorithm) const;
+ // Sizes
+ std::size_t headerSize() const;
+ std::size_t payloadSize() const;
- void setChecksum() {
- uint16_t partial_csum =
- csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0);
+ // Digest
+ auth::CryptoHash computeDigest(auth::CryptoHashType algorithm) const;
- for (utils::MemBuf *current = next(); current != this;
- current = current->next()) {
- partial_csum = csum(current->data(), current->length(), ~partial_csum);
- }
+ // Reset packet
+ void reset();
- if (hicn_packet_compute_header_checksum(format_, packet_start_,
- partial_csum) < 0) {
- throw errors::MalformedPacketException();
- }
- }
+ // Utils
+ bool isInterest();
+ Packet &updateLength(std::size_t length = 0);
+ void dump() const;
+ // TCP methods
+ void setChecksum();
bool checkIntegrity() const;
-
Packet &setSyn();
Packet &resetSyn();
bool testSyn() const;
@@ -222,53 +142,45 @@ class Packet : public utils::MemBuf,
bool testFin() const;
Packet &resetFlags();
std::string printFlags() const;
-
Packet &setSrcPort(uint16_t srcPort);
Packet &setDstPort(uint16_t dstPort);
uint16_t getSrcPort() const;
uint16_t getDstPort() const;
-
Packet &setTTL(uint8_t hops);
uint8_t getTTL() const;
+ // Authentication Header methods
+ bool hasAH() const;
+ std::vector<uint8_t> getSignature() const;
+ std::size_t getSignatureFieldSize() const;
+ std::size_t getSignatureSize() const;
+ uint64_t getSignatureTimestamp() const;
+ auth::KeyId getKeyId() const;
+ auth::CryptoSuite getValidationAlgorithm() const;
+ void setSignature(const std::vector<uint8_t> &signature);
+ void setSignatureFieldSize(std::size_t size);
+ void setSignatureSize(std::size_t size);
+ void setSignatureTimestamp(const uint64_t &timestamp_ms);
+ void setKeyId(const auth::KeyId &key_id);
+ void setValidationAlgorithm(const auth::CryptoSuite &algo);
+
+ // Static methods
+ static Format toAHFormat(const Format &format);
+ static Format getFormatFromBuffer(const uint8_t *buffer, std::size_t length);
+ static std::size_t getHeaderSizeFromFormat(Format format,
+ std::size_t signature_size = 0);
+ static std::size_t getHeaderSizeFromBuffer(Format format,
+ const uint8_t *buffer);
+ static std::size_t getPayloadSizeFromBuffer(Format format,
+ const uint8_t *buffer);
+ static bool isInterest(const uint8_t *buffer,
+ Format format = Format::HF_UNSPEC);
+ static void dump(uint8_t *buffer, std::size_t length);
+
private:
virtual void resetForHash() = 0;
- void setSignatureSize(std::size_t size_bytes);
- void setSignatureSizeGap(std::size_t size_bytes);
void prependPayload(const uint8_t **buffer, std::size_t *size);
- bool authenticationHeader() const { return _is_ah(format_); }
-
- std::size_t getSignatureSize() const {
- size_t size_bytes;
- int ret =
- hicn_packet_get_signature_size(format_, packet_start_, &size_bytes);
-
- if (ret < 0) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- return size_bytes;
- }
-
- std::size_t getSignatureSizeGap() const {
- uint8_t size_bytes;
- int ret =
- hicn_packet_get_signature_gap(format_, packet_start_, &size_bytes);
-
- if (ret < 0) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- return (size_t)size_bytes;
- }
-
- std::size_t getSignatureSizeReal() const {
- return getSignatureSize() - getSignatureSizeGap();
- }
-
- uint8_t *getSignature() const;
-
protected:
hicn_header_t *packet_start_;
std::size_t header_offset_;
diff --git a/libtransport/includes/hicn/transport/core/payload_type.h b/libtransport/includes/hicn/transport/core/payload_type.h
index 8c918f792..3a682e177 100644
--- a/libtransport/includes/hicn/transport/core/payload_type.h
+++ b/libtransport/includes/hicn/transport/core/payload_type.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/core/prefix.h b/libtransport/includes/hicn/transport/core/prefix.h
index 7ef667bc8..13401e1a8 100644
--- a/libtransport/includes/hicn/transport/core/prefix.h
+++ b/libtransport/includes/hicn/transport/core/prefix.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -35,6 +35,10 @@ class Prefix {
Prefix(const core::Name &content_name, uint16_t prefix_length);
+ bool operator<(const Prefix &prefix) const;
+
+ bool operator==(const Prefix &prefix) const;
+
std::unique_ptr<Sockaddr> toSockaddr() const;
uint16_t getPrefixLength() const;
diff --git a/libtransport/includes/hicn/transport/errors/CMakeLists.txt b/libtransport/includes/hicn/transport/errors/CMakeLists.txt
index 1d35c5b34..c8642b51b 100644
--- a/libtransport/includes/hicn/transport/errors/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/errors/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/includes/hicn/transport/errors/errors.h b/libtransport/includes/hicn/transport/errors/errors.h
index b659820fa..09ce97221 100644
--- a/libtransport/includes/hicn/transport/errors/errors.h
+++ b/libtransport/includes/hicn/transport/errors/errors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/indexing_exception.h b/libtransport/includes/hicn/transport/errors/indexing_exception.h
index 731314f0e..bdcc39aef 100644
--- a/libtransport/includes/hicn/transport/errors/indexing_exception.h
+++ b/libtransport/includes/hicn/transport/errors/indexing_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/invalid_ip_address_exception.h b/libtransport/includes/hicn/transport/errors/invalid_ip_address_exception.h
index 60226f576..26e0f98af 100644
--- a/libtransport/includes/hicn/transport/errors/invalid_ip_address_exception.h
+++ b/libtransport/includes/hicn/transport/errors/invalid_ip_address_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/malformed_ahpacket_exception.h b/libtransport/includes/hicn/transport/errors/malformed_ahpacket_exception.h
index f0cfe0b82..9b3ec7466 100644
--- a/libtransport/includes/hicn/transport/errors/malformed_ahpacket_exception.h
+++ b/libtransport/includes/hicn/transport/errors/malformed_ahpacket_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/malformed_name_exception.h b/libtransport/includes/hicn/transport/errors/malformed_name_exception.h
index 4ef45d2e8..57412cf7f 100644
--- a/libtransport/includes/hicn/transport/errors/malformed_name_exception.h
+++ b/libtransport/includes/hicn/transport/errors/malformed_name_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/malformed_packet_exception.h b/libtransport/includes/hicn/transport/errors/malformed_packet_exception.h
index ec5c97e6e..996d6a4ab 100644
--- a/libtransport/includes/hicn/transport/errors/malformed_packet_exception.h
+++ b/libtransport/includes/hicn/transport/errors/malformed_packet_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/not_implemented_exception.h b/libtransport/includes/hicn/transport/errors/not_implemented_exception.h
index e9869163d..3291fa425 100644
--- a/libtransport/includes/hicn/transport/errors/not_implemented_exception.h
+++ b/libtransport/includes/hicn/transport/errors/not_implemented_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/null_pointer_exception.h b/libtransport/includes/hicn/transport/errors/null_pointer_exception.h
index bd06485ed..7edb619b8 100644
--- a/libtransport/includes/hicn/transport/errors/null_pointer_exception.h
+++ b/libtransport/includes/hicn/transport/errors/null_pointer_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/runtime_exception.h b/libtransport/includes/hicn/transport/errors/runtime_exception.h
index ba5128a7e..498c41a7c 100644
--- a/libtransport/includes/hicn/transport/errors/runtime_exception.h
+++ b/libtransport/includes/hicn/transport/errors/runtime_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/tokenizer_exception.h b/libtransport/includes/hicn/transport/errors/tokenizer_exception.h
index 76eda838e..31f79644a 100644
--- a/libtransport/includes/hicn/transport/errors/tokenizer_exception.h
+++ b/libtransport/includes/hicn/transport/errors/tokenizer_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/errors/unexpected_manifest_exception.h b/libtransport/includes/hicn/transport/errors/unexpected_manifest_exception.h
index 6f71471e4..c8e4eadd4 100644
--- a/libtransport/includes/hicn/transport/errors/unexpected_manifest_exception.h
+++ b/libtransport/includes/hicn/transport/errors/unexpected_manifest_exception.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/http/CMakeLists.txt b/libtransport/includes/hicn/transport/http/CMakeLists.txt
index 9f4cdaf39..36a2ca5ce 100644
--- a/libtransport/includes/hicn/transport/http/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/http/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2020 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/includes/hicn/transport/http/client_connection.h b/libtransport/includes/hicn/transport/http/client_connection.h
index 7e78e9c59..d5edf6cd0 100644
--- a/libtransport/includes/hicn/transport/http/client_connection.h
+++ b/libtransport/includes/hicn/transport/http/client_connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -31,7 +31,7 @@ namespace http {
using namespace interface;
using namespace core;
-class HTTPClientConnection {
+class HTTPClientConnection : private utils::NonCopyable {
static constexpr uint32_t max_buffer_capacity = 64 * 1024;
public:
@@ -39,7 +39,7 @@ class HTTPClientConnection {
public:
virtual void onBytesReceived(std::unique_ptr<utils::MemBuf> &&buffer) = 0;
virtual void onSuccess(std::size_t bytes) = 0;
- virtual void onError(const std::error_code ec) = 0;
+ virtual void onError(const std::error_code &ec) = 0;
};
enum class RC : uint32_t { DOWNLOAD_FAILED, DOWNLOAD_SUCCESS };
diff --git a/libtransport/includes/hicn/transport/http/default_values.h b/libtransport/includes/hicn/transport/http/default_values.h
index 2d5a6b821..8cf247e19 100644
--- a/libtransport/includes/hicn/transport/http/default_values.h
+++ b/libtransport/includes/hicn/transport/http/default_values.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/http/facade.h b/libtransport/includes/hicn/transport/http/facade.h
index 8a465ce94..c886a7588 100644
--- a/libtransport/includes/hicn/transport/http/facade.h
+++ b/libtransport/includes/hicn/transport/http/facade.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/http/message.h b/libtransport/includes/hicn/transport/http/message.h
index b8756224f..a07941413 100644
--- a/libtransport/includes/hicn/transport/http/message.h
+++ b/libtransport/includes/hicn/transport/http/message.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/http/request.h b/libtransport/includes/hicn/transport/http/request.h
index b62f5b061..9939fbcaf 100644
--- a/libtransport/includes/hicn/transport/http/request.h
+++ b/libtransport/includes/hicn/transport/http/request.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/http/response.h b/libtransport/includes/hicn/transport/http/response.h
index bab41acb8..79def27cd 100644
--- a/libtransport/includes/hicn/transport/http/response.h
+++ b/libtransport/includes/hicn/transport/http/response.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
index 40623dfe1..1acaadcf0 100644
--- a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -21,6 +21,7 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/global_conf_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/statistics.h
${CMAKE_CURRENT_SOURCE_DIR}/portal.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/notification.h
)
if (${OPENSSL_VERSION} VERSION_EQUAL "1.1.1a" OR ${OPENSSL_VERSION} VERSION_GREATER "1.1.1a")
diff --git a/libtransport/includes/hicn/transport/interfaces/callbacks.h b/libtransport/includes/hicn/transport/interfaces/callbacks.h
index 22e111799..41e4fba3b 100644
--- a/libtransport/includes/hicn/transport/interfaces/callbacks.h
+++ b/libtransport/includes/hicn/transport/interfaces/callbacks.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/auth/policies.h>
+#include <hicn/transport/interfaces/notification.h>
#include <hicn/transport/interfaces/statistics.h>
#include <functional>
@@ -60,6 +61,12 @@ using ConsumerTimerCallback =
std::function<void(ConsumerSocket &, const TransportStatistics &stats)>;
/**
+ * The ConsumerTimerCallback is called when the forwarding/recovery stategy is
+ * changes.
+ */
+using StrategyCallback = std::function<void(notification::Strategy strategy)>;
+
+/**
* The ProducerContentCallback will be called by the producer socket right after
* a content has been segmented and published.
*/
diff --git a/hicn-light/src/hicn/config/controlAdd.h b/libtransport/includes/hicn/transport/interfaces/notification.h
index 7c160b5f7..a0945c3f0 100644
--- a/hicn-light/src/hicn/config/controlAdd.h
+++ b/libtransport/includes/hicn/transport/interfaces/notification.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,20 +13,19 @@
* limitations under the License.
*/
-/**
- * @file control_Add.h
- * @brief Command-line "add" node
- *
- * Implements the "add" node of the CLI tree
- *
- *
- */
+#pragma once
+
+#include <variant>
+
+namespace transport {
+namespace interface {
+namespace notification {
-#ifndef control_Add_h
-#define control_Add_h
+enum class ForwardingStrategy { BEST_PATH, REPLICATION, BOTH, NONE };
+enum class RecoveryStrategy { RECOVERY_OFF, RTX_ONLY, FEC_ONLY, RTX_AND_FEC };
-#include <hicn/config/controlState.h>
+using Strategy = std::variant<ForwardingStrategy, RecoveryStrategy>;
-CommandOps *webControlAdd_Create(ControlState *state);
-CommandOps *controlAdd_CreateHelp(ControlState *state);
-#endif // control_Add_h
+} // namespace notification
+} // namespace interface
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
index 224493f00..a67634c1e 100644
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
+++ b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
index d86744514..e197a3658 100644
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -15,7 +15,6 @@
#pragma once
-#include <hicn/transport/auth/identity.h>
#include <hicn/transport/interfaces/socket_producer.h>
namespace transport {
@@ -25,8 +24,8 @@ namespace interface {
class P2PSecureProducerSocket : public ProducerSocket {
public:
P2PSecureProducerSocket();
- P2PSecureProducerSocket(bool rtc,
- const std::shared_ptr<auth::Identity> &identity);
+ P2PSecureProducerSocket(bool rtc, std::string &keystore_path,
+ std::string &keystore_pwd);
~P2PSecureProducerSocket() = default;
};
diff --git a/libtransport/includes/hicn/transport/interfaces/portal.h b/libtransport/includes/hicn/transport/interfaces/portal.h
index 66fc84256..1a22b1f1d 100644
--- a/libtransport/includes/hicn/transport/interfaces/portal.h
+++ b/libtransport/includes/hicn/transport/interfaces/portal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,6 +19,8 @@
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/prefix.h>
+#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/noncopyable.h>
#include <functional>
@@ -28,58 +30,18 @@ namespace transport {
namespace interface {
-template <typename PrefixType>
-class BasicBindConfig {
- static_assert(std::is_same<core::Prefix, PrefixType>::value,
- "Prefix must be a Prefix type.");
-
- const uint32_t standard_cs_reserved = 5000;
-
- public:
- template <typename T>
- BasicBindConfig(T &&prefix)
- : prefix_(std::forward<T &&>(prefix)),
- content_store_reserved_(standard_cs_reserved) {}
-
- template <typename T>
- BasicBindConfig(T &&prefix, uint32_t cs_reserved)
- : prefix_(std::forward<T &&>(prefix)),
- content_store_reserved_(cs_reserved) {}
-
- TRANSPORT_ALWAYS_INLINE const PrefixType &prefix() const { return prefix_; }
-
- TRANSPORT_ALWAYS_INLINE uint32_t csReserved() const {
- return content_store_reserved_;
- }
-
- private:
- PrefixType prefix_;
- uint32_t content_store_reserved_;
-};
-
-using BindConfig = BasicBindConfig<core::Prefix>;
-
-class Portal {
+class Portal : private utils::NonCopyable {
public:
/**
- * Consumer callback is an abstract class containing two methods to be
- * implemented by a consumer application.
+ * Transport callback is an abstract class containing two methods to be
+ * implemented by a consumer/producer application.
*/
- class ConsumerCallback {
+ class TransportCallback {
public:
+ virtual void onInterest(core::Interest &i) = 0;
virtual void onContentObject(core::Interest &i, core::ContentObject &c) = 0;
virtual void onTimeout(core::Interest::Ptr &i, const core::Name &n) = 0;
- virtual void onError(std::error_code ec) = 0;
- };
-
- /**
- * Producer callback is an abstract class containing two methods to be
- * implemented by a producer application.
- */
- class ProducerCallback {
- public:
- virtual void onInterest(core::Interest &i) = 0;
- virtual void onError(std::error_code ec) = 0;
+ virtual void onError(const std::error_code &ec) = 0;
};
using OnContentObjectCallback =
@@ -89,21 +51,14 @@ class Portal {
Portal();
- Portal(asio::io_service &io_service);
+ Portal(::utils::EventThread &worker);
/**
- * Set the consumer callback.
- *
- * @param consumer_callback - The pointer to the ConsumerCallback object.
- */
- void setConsumerCallback(ConsumerCallback *consumer_callback);
-
- /**
- * Set the producer callback.
+ * Set the transport protocl callback.
*
* @param producer_callback - The pointer to the ProducerCallback object.
*/
- void setProducerCallback(ProducerCallback *producer_callback);
+ void registerTransportCallback(TransportCallback *transport_callback);
/**
* Connect the transport to the local hicn forwarder.
@@ -146,34 +101,12 @@ class Portal {
UNSET_CALLBACK);
/**
- * Register a producer name to the local forwarder and optionally set the
- * content store size in a per-face manner.
- *
- * @param config - The configuration for the local forwarder binding.
- */
- void bind(const BindConfig &config);
-
- void runEventsLoop();
-
- /**
- * Run one event and return.
- */
- void runOneEvent();
-
- /**
* Send a data packet to the local forwarder. As opposite to sendInterest, the
* ownership of the content object is not transferred to the portal.
*
* @param content_object - The data packet.
*/
void sendContentObject(core::ContentObject &content_object);
- /**
- * Stop the event loop, canceling all the pending events in the event queue.
- *
- * Beware that stopping the event loop DOES NOT disconnect the transport from
- * the local forwarder, the connector underneath will stay connected.
- */
- void stopEventsLoop();
/**
* Disconnect the transport from the local forwarder.
@@ -188,15 +121,26 @@ class Portal {
/**
* Get a reference to the io_service object.
*/
- asio::io_service &getIoService();
+ utils::EventThread &getThread();
/**
* Register a route to the local forwarder.
*/
void registerRoute(core::Prefix &prefix);
+ /**
+ * Send a MAP-Me command to traverse NATs.
+ */
+ void sendMapme();
+
+ /**
+ * Set forwarding strategy
+ */
+ void setForwardingStrategy(core::Prefix &prefix, std::string &strategy);
+
private:
- void *implementation_;
+ class Impl;
+ Impl *implementation_;
};
} // namespace interface
diff --git a/libtransport/includes/hicn/transport/interfaces/publication_options.h b/libtransport/includes/hicn/transport/interfaces/publication_options.h
index 6910e5371..03a0763f5 100644
--- a/libtransport/includes/hicn/transport/interfaces/publication_options.h
+++ b/libtransport/includes/hicn/transport/interfaces/publication_options.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
index 5e0e81b9f..e26fe5a85 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,6 +23,8 @@
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/noncopyable.h>
#define CONSUMER_FINISHED 0
#define CONSUMER_BUSY 1
@@ -45,7 +47,7 @@ using namespace core;
* It allows to retrieve an application data from one/many producers, by
* hiding all the complexity of the transport protocol used underneath.
*/
-class ConsumerSocket {
+class ConsumerSocket : private utils::NonCopyable {
public:
/**
* The ReadCallback is a class which can be used by the transport for both
@@ -124,7 +126,7 @@ class ConsumerSocket {
*
* @param ec - An error code describing the error.
*/
- virtual void readError(const std::error_code ec) noexcept = 0;
+ virtual void readError(const std::error_code &ec) noexcept = 0;
/**
* This callback will be invoked when the whole content is retrieved. The
@@ -166,7 +168,12 @@ class ConsumerSocket {
* 110, 104-117
* - RTC: Real time communication
*/
- explicit ConsumerSocket(int protocol, asio::io_service &io_service);
+ explicit ConsumerSocket(int protocol, ::utils::EventThread &worker);
+
+ /**
+ * @brief Move contructor
+ */
+ ConsumerSocket(ConsumerSocket &&other) noexcept;
/**
* @brief Destroy the consumer socket.
@@ -200,12 +207,10 @@ class ConsumerSocket {
* content retrieval succeeded. This information can be obtained from the
* error code in CONTENT_RETRIEVED callback.
*/
- int consume(const Name &name);
- int asyncConsume(const Name &name);
+ int consume(const Name &name, bool blocking = false);
/**
- * Stops the consumer socket. If several downloads are queued (using
- * asyncConsume), this call stops just the current one.
+ * Stops the consumer socket.
*/
void stop();
@@ -255,6 +260,12 @@ class ConsumerSocket {
int setSocketOption(int socket_option_key,
ConsumerTimerCallback socket_option_value);
+ int setSocketOption(int socket_option_key,
+ StrategyCallback socket_option_value);
+
+ int setSocketOption(int socket_option_key,
+ Packet::Format socket_option_value);
+
int getSocketOption(int socket_option_key, double &socket_option_value);
int getSocketOption(int socket_option_key, uint32_t &socket_option_value);
@@ -280,8 +291,14 @@ class ConsumerSocket {
ConsumerTimerCallback **socket_option_value);
int getSocketOption(int socket_option_key,
+ StrategyCallback **socket_option_value);
+
+ int getSocketOption(int socket_option_key,
interface::TransportStatistics **socket_option_value);
+ int getSocketOption(int socket_option_key,
+ Packet::Format &socket_option_value);
+
protected:
ConsumerSocket();
std::unique_ptr<implementation::ConsumerSocket> socket_;
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 f4945ac8a..04454852b 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,7 +15,10 @@
#pragma once
+extern "C" {
#include <hicn/base.h>
+#include <hicn/compat.h>
+}
#include <chrono>
#include <cstdint>
@@ -26,6 +29,16 @@ namespace interface {
namespace default_values {
+// Packet format
+// #define NEW_PACKET_FORMAT
+static constexpr hicn_format_t packet_format =
+#ifdef NEW_PACKET_FORMAT
+ HF_INET6_UDP;
+#else
+ HF_INET6_TCP;
+#endif
+
+// Parameters
static constexpr uint32_t interest_lifetime = 1001; // milliseconds
static constexpr uint32_t never_expire_time = HICN_MAX_LIFETIME;
static constexpr uint32_t content_object_expiry_time =
@@ -40,6 +53,8 @@ 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 max_unverified_delay = 2001; // milliseconds
+static constexpr uint32_t manifest_capacity = 30;
// 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 00cd44075..90f218770 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,15 +26,27 @@ namespace transport {
namespace interface {
typedef enum {
- RAAQM = 0,
- CBR = 1,
- RTC = 2,
+ UNKNOWN = 0,
+ BYTE_STREAM = 1,
+ RTC_PROD = 2,
+} ProductionProtocolAlgorithms;
+
+typedef enum {
+ RAAQM = 10,
+ CBR = 11,
+ RTC = 12,
} TransportProtocolAlgorithms;
typedef enum {
- BYTE_STREAM = 10,
- RTC_PROD = 11,
-} ProductionProtocolAlgorithms;
+ RECOVERY_OFF = 20,
+ RTX_ONLY = 21,
+ FEC_ONLY = 22,
+ DELAY_BASED = 23,
+ LOW_RATE = 24,
+ LOW_RATE_AND_BESTPATH = 25,
+ LOW_RATE_AND_REPLICATION = 26,
+ LOW_RATE_AND_ALL_FWD_STRATEGIES = 27,
+} RtcTransportRecoveryStrategies;
typedef enum {
INPUT_BUFFER_SIZE = 101,
@@ -45,6 +57,8 @@ typedef enum {
DATA_PACKET_SIZE = 106,
INTEREST_LIFETIME = 107,
CONTENT_OBJECT_EXPIRY_TIME = 108,
+ MAX_SEGMENT_SIZE = 109,
+ MAX_UNVERIFIED_TIME = 110,
MIN_WINDOW_SIZE = 111,
MAX_WINDOW_SIZE = 112,
CURRENT_WINDOW_SIZE = 113,
@@ -57,7 +71,9 @@ typedef enum {
SIGNER = 121,
VERIFIER = 122,
STATS_INTERVAL = 125,
- SUFFIX_STRATEGY = 126
+ SUFFIX_STRATEGY = 126,
+ PACKET_FORMAT = 127,
+ FEC_TYPE = 128,
} GeneralTransportOptions;
typedef enum {
@@ -87,7 +103,9 @@ typedef enum {
CONTENT_OBJECT_TO_VERIFY = 413,
VERIFICATION_FAILED = 414,
READ_CALLBACK = 415,
- STATS_SUMMARY = 416
+ STATS_SUMMARY = 416,
+ FWD_STRATEGY_CHANGE = 417,
+ REC_STRATEGY_CHANGE = 418,
} ConsumerCallbacksOptions;
typedef enum {
@@ -100,7 +118,8 @@ typedef enum {
CONTENT_OBJECT_READY = 510,
CONTENT_OBJECT_OUTPUT = 511,
CONTENT_PRODUCED = 512,
- CONTENT_OBJECT_TO_SIGN = 513
+ CONTENT_OBJECT_TO_SIGN = 513,
+ PRODUCER_CALLBACK = 514,
} ProducerCallbacksOptions;
typedef enum { OUTPUT_INTERFACE = 601 } DataLinkOptions;
@@ -116,6 +135,11 @@ typedef enum {
RSA_256 = 802,
} SignatureType;
+typedef enum {
+ RECOVERY_STRATEGY = 901,
+ AGGREGATED_DATA = 902,
+} RtcTransportOptions;
+
} // namespace interface
} // end namespace transport
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_producer.h b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
index 27b603dfe..77b89742a 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,6 +23,8 @@
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/noncopyable.h>
namespace transport {
@@ -34,12 +36,28 @@ namespace interface {
using namespace core;
-class ProducerSocket {
+class ProducerSocket : private utils::NonCopyable {
public:
+ /**
+ * @brief This class is used by the transport to notify events to the
+ * application.
+ */
+ class Callback {
+ public:
+ /**
+ * @brief This will invoked in an error occurred in the production protocol.
+ *
+ * @param ec - An error code describing the error.
+ */
+ virtual void produceError(const std::error_code &ec) noexcept = 0;
+ };
+
explicit ProducerSocket(
int protocol = ProductionProtocolAlgorithms::BYTE_STREAM);
- explicit ProducerSocket(int protocol, asio::io_service &io_service);
+ explicit ProducerSocket(int protocol, ::utils::EventThread &worker);
+
+ ProducerSocket(ProducerSocket &&other) noexcept;
virtual ~ProducerSocket();
@@ -63,21 +81,18 @@ class ProducerSocket {
uint32_t produceDatagram(const Name &content_name,
std::unique_ptr<utils::MemBuf> &&buffer);
- void asyncProduce(const Name &suffix, const uint8_t *buf, size_t buffer_size,
- bool is_last = true, uint32_t *start_offset = nullptr);
-
- void asyncProduce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t offset,
- uint32_t **last_segment = nullptr);
-
void produce(ContentObject &content_object);
- void serveForever();
+ void sendMapme();
void stop();
+ void start();
+
asio::io_service &getIoService();
+ int setSocketOption(int socket_option_key, Callback *socket_option_value);
+
int setSocketOption(int socket_option_key, uint32_t socket_option_value);
int setSocketOption(int socket_option_key,
@@ -111,6 +126,9 @@ class ProducerSocket {
int setSocketOption(int socket_option_key,
const std::string &socket_option_value);
+ int setSocketOption(int socket_option_key,
+ Packet::Format socket_option_value);
+
int getSocketOption(int socket_option_key, uint32_t &socket_option_value);
int getSocketOption(int socket_option_key, bool &socket_option_value);
@@ -138,6 +156,9 @@ class ProducerSocket {
int getSocketOption(int socket_option_key, std::string &socket_option_value);
+ int getSocketOption(int socket_option_key,
+ Packet::Format &socket_option_value);
+
protected:
ProducerSocket(bool);
std::unique_ptr<implementation::ProducerSocket> socket_;
diff --git a/libtransport/includes/hicn/transport/interfaces/statistics.h b/libtransport/includes/hicn/transport/interfaces/statistics.h
index 1ff6f3edd..4d9e1bfe2 100644
--- a/libtransport/includes/hicn/transport/interfaces/statistics.h
+++ b/libtransport/includes/hicn/transport/interfaces/statistics.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/portability/c_portability.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <cstdint>
@@ -37,6 +38,8 @@ class TransportStatistics {
static constexpr double default_alpha = 0.7;
public:
+ enum class statsAlerts : uint8_t { CONGESTION, LATENCY, LOSSES };
+
TransportStatistics(double alpha = default_alpha)
: retx_count_(0),
bytes_received_(0),
@@ -51,11 +54,15 @@ class TransportStatistics {
lost_data_(0),
definitely_lost_data_(0),
recovered_data_(0),
- status_(-1),
+ status_(0),
// avg_data_rtt_(0),
avg_pending_pkt_(0.0),
received_nacks_(0),
- received_fec_(0) {}
+ received_fec_(0),
+ in_congestion_(false),
+ residual_loss_rate_(0.0),
+ quality_score_(5),
+ alerts_(0) {}
TRANSPORT_ALWAYS_INLINE void updateRetxCount(uint64_t retx) {
retx_count_ += retx;
@@ -65,8 +72,11 @@ class TransportStatistics {
bytes_received_ += bytes;
}
- TRANSPORT_ALWAYS_INLINE void updateAverageRtt(uint64_t rtt) {
- average_rtt_ = (alpha_ * average_rtt_) + ((1. - alpha_) * double(rtt));
+ 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));
}
TRANSPORT_ALWAYS_INLINE void updateAverageWindowSize(double current_window) {
@@ -120,6 +130,26 @@ class TransportStatistics {
received_fec_ += pkt;
}
+ TRANSPORT_ALWAYS_INLINE void updateResidualLossRate(double val) {
+ residual_loss_rate_ = val;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateQualityScore(uint8_t val) {
+ quality_score_ = val;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateCongestionState(bool state) {
+ in_congestion_ = state;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void setAlert(statsAlerts x) {
+ alerts_ |= 1UL << (uint32_t)x;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void clearAlert(statsAlerts x) {
+ alerts_ &= ~(1UL << (uint32_t)x);
+ }
+
TRANSPORT_ALWAYS_INLINE uint64_t getRetxCount() const { return retx_count_; }
TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecv() const {
@@ -174,6 +204,18 @@ class TransportStatistics {
return received_fec_;
}
+ TRANSPORT_ALWAYS_INLINE double getResidualLossRate() const {
+ return residual_loss_rate_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE uint8_t getQualityScore() const {
+ return quality_score_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE bool isCongested() const { return in_congestion_; }
+
+ TRANSPORT_ALWAYS_INLINE uint32_t getAlerts() const { return alerts_; }
+
TRANSPORT_ALWAYS_INLINE void setAlpha(double val) { alpha_ = val; }
TRANSPORT_ALWAYS_INLINE void reset() {
@@ -193,6 +235,8 @@ class TransportStatistics {
avg_pending_pkt_ = 0;
received_nacks_ = 0;
received_fec_ = 0;
+ in_congestion_ = false;
+ quality_score_ = 5;
}
private:
@@ -213,6 +257,14 @@ class TransportStatistics {
double avg_pending_pkt_;
uint32_t received_nacks_;
uint32_t received_fec_;
+ bool in_congestion_;
+ double residual_loss_rate_;
+ uint8_t quality_score_;
+
+ // alerts is a bit vector used to signal to the upper layer that
+ // something bad is appening in the network, the encode is done accoding to
+ // the enum alerts;
+ uint32_t alerts_;
};
} // namespace interface
diff --git a/libtransport/includes/hicn/transport/portability/CMakeLists.txt b/libtransport/includes/hicn/transport/portability/CMakeLists.txt
index 8094c0661..7a688b1f1 100644
--- a/libtransport/includes/hicn/transport/portability/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/portability/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -14,6 +14,7 @@
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/c_portability.h
${CMAKE_CURRENT_SOURCE_DIR}/portability.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cpu.h
)
list(APPEND SOURCE_FILES
diff --git a/libtransport/includes/hicn/transport/portability/c_portability.h b/libtransport/includes/hicn/transport/portability/c_portability.h
index 2675de000..bc697d8b1 100644
--- a/libtransport/includes/hicn/transport/portability/c_portability.h
+++ b/libtransport/includes/hicn/transport/portability/c_portability.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/libtransport/includes/hicn/transport/portability/cpu.h b/libtransport/includes/hicn/transport/portability/cpu.h
new file mode 100644
index 000000000..036bf9cd9
--- /dev/null
+++ b/libtransport/includes/hicn/transport/portability/cpu.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.
+ */
+
+#pragma once
+
+#if defined(__aarch64__) && defined(__ARM_NEON) || defined(__i686__)
+#define TRANSPORT_HAVE_VEC128
+#endif
+
+#if defined(__SSE4_2__) && __GNUC__ >= 4
+#define TRANSPORT_HAVE_VEC128
+#endif
+
+#if defined(__ALTIVEC__)
+#define TRANSPORT_HAVE_VEC128
+#endif
+
+#if defined(__AVX2__)
+#define TRANSPORT_HAVE_VEC256
+#if defined(__clang__) && __clang_major__ < 4
+#undef TRANSPORT_HAVE_VEC256
+#endif
+#endif
+
+#if defined(__AVX512BITALG__)
+#define TRANSPORT_HAVE_VEC512
+#endif
diff --git a/libtransport/includes/hicn/transport/portability/portability.h b/libtransport/includes/hicn/transport/portability/portability.h
index 24ef012f7..b093f8892 100644
--- a/libtransport/includes/hicn/transport/portability/portability.h
+++ b/libtransport/includes/hicn/transport/portability/portability.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,9 +28,6 @@
namespace portability {
-constexpr bool little_endian_arch = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
-constexpr bool big_endian_arch = !little_endian_arch;
-
// Generalize warning push/pop.
#if defined(__GNUC__) || defined(__clang__)
// Clang & GCC
diff --git a/libtransport/includes/hicn/transport/portability/win_portability.h b/libtransport/includes/hicn/transport/portability/win_portability.h
index 24c7a932a..81aa828cd 100644
--- a/libtransport/includes/hicn/transport/portability/win_portability.h
+++ b/libtransport/includes/hicn/transport/portability/win_portability.h
@@ -1,44 +1,44 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Copyright 2017 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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
-#define WIN32_LEAN_AND_MEAN
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <fcntl.h>
-#include <io.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2ipdef.h>
-#include <ws2tcpip.h>
-
-#include <algorithm>
-
-#define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
-#define __ORDER_BIG_ENDIAN__ 0x44434241UL
-#define __BYTE_ORDER__ ('ABCD')
-#undef DELETE
-
-#define HAVE_STRUCT_TIMESPEC
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <fcntl.h>
+#include <io.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2ipdef.h>
+#include <ws2tcpip.h>
+
+#include <algorithm>
+
+#define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
+#define __ORDER_BIG_ENDIAN__ 0x44434241UL
+#define __BYTE_ORDER__ ('ABCD')
+#undef DELETE
+
+#define HAVE_STRUCT_TIMESPEC
#include <pthread.h> \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/CMakeLists.txt b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
index 75f727f03..bbd149e09 100644
--- a/libtransport/includes/hicn/transport/utils/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -19,6 +19,7 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/chrono_typedefs.h
${CMAKE_CURRENT_SOURCE_DIR}/branch_prediction.h
${CMAKE_CURRENT_SOURCE_DIR}/ring_buffer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_quality_score.h
${CMAKE_CURRENT_SOURCE_DIR}/literals.h
${CMAKE_CURRENT_SOURCE_DIR}/conversions.h
${CMAKE_CURRENT_SOURCE_DIR}/linux.h
diff --git a/libtransport/includes/hicn/transport/utils/array.h b/libtransport/includes/hicn/transport/utils/array.h
index 7c0ed65d8..d57bfabaf 100644
--- a/libtransport/includes/hicn/transport/utils/array.h
+++ b/libtransport/includes/hicn/transport/utils/array.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/branch_prediction.h b/libtransport/includes/hicn/transport/utils/branch_prediction.h
index 8cbfaca76..626cb1573 100644
--- a/libtransport/includes/hicn/transport/utils/branch_prediction.h
+++ b/libtransport/includes/hicn/transport/utils/branch_prediction.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/chrono_typedefs.h b/libtransport/includes/hicn/transport/utils/chrono_typedefs.h
index 8f28e763c..ddfbd00cd 100644
--- a/libtransport/includes/hicn/transport/utils/chrono_typedefs.h
+++ b/libtransport/includes/hicn/transport/utils/chrono_typedefs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,11 +17,102 @@
#include <chrono>
+namespace std {
+namespace chrono {
+namespace detail {
+
+template <typename From, typename To>
+struct posix_duration_cast;
+
+// chrono -> timespec caster
+template <typename Rep, typename Period>
+struct posix_duration_cast<std::chrono::duration<Rep, Period>,
+ struct timespec> {
+ static struct timespec cast(std::chrono::duration<Rep, Period> const &d) {
+ struct timespec tv;
+
+ std::chrono::seconds const sec =
+ std::chrono::duration_cast<std::chrono::seconds>(d);
+
+ tv.tv_sec = sec.count();
+ tv.tv_nsec =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(d - sec).count();
+
+ return tv;
+ }
+};
+
+// timespec -> chrono caster
+template <typename Rep, typename Period>
+struct posix_duration_cast<struct timespec,
+ std::chrono::duration<Rep, Period>> {
+ static std::chrono::duration<Rep, Period> cast(struct timespec const &tv) {
+ return std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
+ std::chrono::seconds(tv.tv_sec) + std::chrono::nanoseconds(tv.tv_nsec));
+ }
+};
+
+} // namespace detail
+
+// chrono -> timespec
+template <typename T, typename Rep, typename Period>
+auto duration_cast(std::chrono::duration<Rep, Period> const &d) ->
+ typename std::enable_if<std::is_same<T, struct timespec>::value,
+ struct timespec>::type {
+ return detail::posix_duration_cast<std::chrono::duration<Rep, Period>,
+ timespec>::cast(d);
+}
+
+// timespec -> chrono
+template <typename Duration>
+Duration duration_cast(struct timespec const &tv) {
+ return detail::posix_duration_cast<struct timespec, Duration>::cast(tv);
+}
+
+} // namespace chrono
+} // namespace std
+
namespace utils {
-using SteadyClock = std::chrono::steady_clock;
-using TimePoint = SteadyClock::time_point;
-using Milliseconds = std::chrono::milliseconds;
-using Microseconds = std::chrono::microseconds;
+template <typename T>
+class Time {
+ public:
+ using Clock = T;
+ using TimePoint = typename Clock::time_point;
+ using Rep = double;
+ using Seconds = std::chrono::duration<Rep>;
+ using Milliseconds = std::chrono::duration<Rep, std::milli>;
+ using Microseconds = std::chrono::duration<Rep, std::micro>;
+
+ static auto now() { return Clock::now(); }
+
+ // From epochs
+ static auto nowMs() {
+ return std::chrono::duration_cast<Milliseconds>(now().time_since_epoch());
+ }
+
+ // From epoch
+ static auto nowUs() {
+ return std::chrono::duration_cast<Microseconds>(now().time_since_epoch());
+ }
+
+ template <typename D>
+ static auto getDuration(const TimePoint &start, const TimePoint &end) {
+ return std::chrono::duration_cast<D>(end - start);
+ }
+
+ static auto getDurationS(const TimePoint &start, const TimePoint &end) {
+ return getDuration<Seconds>(start, end);
+ }
+ static auto getDurationMs(const TimePoint &start, const TimePoint &end) {
+ return getDuration<Milliseconds>(start, end);
+ }
+ static auto getDurationUs(const TimePoint &start, const TimePoint &end) {
+ return getDuration<Microseconds>(start, end);
+ }
+};
+
+using SteadyTime = Time<std::chrono::steady_clock>;
+using SystemTime = Time<std::chrono::system_clock>;
} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/conversions.h b/libtransport/includes/hicn/transport/utils/conversions.h
index 52d3e3168..812803175 100644
--- a/libtransport/includes/hicn/transport/utils/conversions.h
+++ b/libtransport/includes/hicn/transport/utils/conversions.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/daemonizator.h b/libtransport/includes/hicn/transport/utils/daemonizator.h
index 028d74865..1d0a0b309 100644
--- a/libtransport/includes/hicn/transport/utils/daemonizator.h
+++ b/libtransport/includes/hicn/transport/utils/daemonizator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/event_thread.h b/libtransport/includes/hicn/transport/utils/event_thread.h
index 15ec1d62c..2cd2f3aca 100644
--- a/libtransport/includes/hicn/transport/utils/event_thread.h
+++ b/libtransport/includes/hicn/transport/utils/event_thread.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -97,6 +97,19 @@ class EventThread {
io_service_.get().dispatch(std::forward<Func&&>(f));
}
+ template <typename Func>
+ void addAndWaitForExecution(Func&& f) {
+ auto promise = std::promise<void>();
+ auto future = promise.get_future();
+
+ asio::dispatch(io_service_.get(), [&promise, f = std::forward<Func>(f)]() {
+ f();
+ promise.set_value();
+ });
+
+ future.wait();
+ }
+
void stop() {
work_.reset();
diff --git a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
index 298b6f9d1..19b52b37e 100644
--- a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
+++ b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
@@ -1,23 +1,28 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
*/
#pragma once
#include <hicn/transport/portability/c_portability.h>
+#include <hicn/transport/utils/branch_prediction.h>
#include <hicn/transport/utils/singleton.h>
#include <hicn/transport/utils/spinlock.h>
#include <stdint.h>
#include <cassert>
#include <cstdlib>
+#include <list>
#include <memory>
namespace utils {
template <std::size_t SIZE = 512, std::size_t OBJECTS = 4096>
class FixedBlockAllocator
- : public utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>> {
- friend class utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>>;
+ : public utils::ThreadLocalSingleton<FixedBlockAllocator<SIZE, OBJECTS>> {
+ friend class utils::ThreadLocalSingleton<FixedBlockAllocator<SIZE, OBJECTS>>;
+
+ static inline const std::size_t BLOCK_SIZE = SIZE;
+ static inline const std::size_t BLOCKS_PER_POOL = OBJECTS;
public:
~FixedBlockAllocator() {
@@ -26,19 +31,19 @@ class FixedBlockAllocator
}
}
- void* allocateBlock(size_t size = SIZE) {
- assert(size <= SIZE);
+ void* allocateBlock() {
uint32_t index;
-
SpinLock::Acquire locked(lock_);
void* p_block = pop();
if (!p_block) {
- if (TRANSPORT_EXPECT_FALSE(current_pool_index_ >= max_objects_)) {
+ if (TRANSPORT_EXPECT_FALSE(current_pool_index_ >= BLOCKS_PER_POOL)) {
// Allocate new memory block
p_pools_.emplace_front(
- new typename std::aligned_storage<SIZE>::type[max_objects_]);
+ new typename std::aligned_storage<SIZE>::type[BLOCKS_PER_POOL]);
// reset current_pool_index_
current_pool_index_ = 0;
+ // Increase total block count
+ block_count_ += BLOCKS_PER_POOL;
}
auto& latest = p_pools_.front();
@@ -59,7 +64,7 @@ class FixedBlockAllocator
}
public:
- std::size_t blockSize() { return block_size_; }
+ std::size_t blockSize() { return BLOCK_SIZE; }
uint32_t blockCount() { return block_count_; }
@@ -69,20 +74,32 @@ class FixedBlockAllocator
uint32_t deallocations() { return deallocations_; }
+ void reset() {
+ p_head_ = nullptr;
+ blocks_in_use_ = 0;
+ allocations_ = 0;
+ deallocations_ = 0;
+ current_pool_index_ = 0;
+ block_count_ = BLOCKS_PER_POOL;
+
+ // Delete all memory pools but the first one
+ for (auto it = std::next(p_pools_.begin()); it != p_pools_.end();) {
+ delete[] * it;
+ it = p_pools_.erase(it);
+ }
+ }
+
private:
FixedBlockAllocator()
- : block_size_(SIZE),
- object_size_(SIZE),
- max_objects_(OBJECTS),
- p_head_(NULL),
+ : p_head_(NULL),
current_pool_index_(0),
- block_count_(0),
+ block_count_(BLOCKS_PER_POOL),
blocks_in_use_(0),
allocations_(0),
deallocations_(0) {
static_assert(SIZE >= sizeof(long*), "SIZE must be at least 8 bytes");
p_pools_.emplace_front(
- new typename std::aligned_storage<SIZE>::type[max_objects_]);
+ new typename std::aligned_storage<SIZE>::type[BLOCKS_PER_POOL]);
}
void push(void* p_memory) {
@@ -106,12 +123,6 @@ class FixedBlockAllocator
Block* p_next;
};
- static std::unique_ptr<FixedBlockAllocator> instance_;
-
- const std::size_t block_size_;
- const std::size_t object_size_;
- const std::size_t max_objects_;
-
Block* p_head_;
uint32_t current_pool_index_;
std::list<typename std::aligned_storage<SIZE>::type*> p_pools_;
@@ -123,10 +134,6 @@ class FixedBlockAllocator
SpinLock lock_;
};
-template <std::size_t A, std::size_t B>
-std::unique_ptr<FixedBlockAllocator<A, B>>
- FixedBlockAllocator<A, B>::instance_ = nullptr;
-
/**
* STL Allocator trait to be used with allocate_shared.
*/
diff --git a/libtransport/includes/hicn/transport/utils/hash.h b/libtransport/includes/hicn/transport/utils/hash.h
index 6815ca4bf..7943596e6 100644
--- a/libtransport/includes/hicn/transport/utils/hash.h
+++ b/libtransport/includes/hicn/transport/utils/hash.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/libtransport/includes/hicn/transport/utils/linux.h b/libtransport/includes/hicn/transport/utils/linux.h
index 4fbf5f01e..03d29c1db 100644
--- a/libtransport/includes/hicn/transport/utils/linux.h
+++ b/libtransport/includes/hicn/transport/utils/linux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/literals.h b/libtransport/includes/hicn/transport/utils/literals.h
index bd00e0a58..531f67362 100644
--- a/libtransport/includes/hicn/transport/utils/literals.h
+++ b/libtransport/includes/hicn/transport/utils/literals.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/log.h b/libtransport/includes/hicn/transport/utils/log.h
index 0947b755e..f4d39b6b1 100644
--- a/libtransport/includes/hicn/transport/utils/log.h
+++ b/libtransport/includes/hicn/transport/utils/log.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/move_wrapper.h b/libtransport/includes/hicn/transport/utils/move_wrapper.h
index 5dc3b461d..73389948d 100644
--- a/libtransport/includes/hicn/transport/utils/move_wrapper.h
+++ b/libtransport/includes/hicn/transport/utils/move_wrapper.h
@@ -23,6 +23,7 @@ namespace utils {
template <typename F>
struct MoveWrapper : F {
MoveWrapper(F&& f) : F(std::move(f)) {}
+ ~MoveWrapper() = default;
MoveWrapper(MoveWrapper&&) = default;
MoveWrapper& operator=(MoveWrapper&&) = default;
diff --git a/libtransport/includes/hicn/transport/utils/noncopyable.h b/libtransport/includes/hicn/transport/utils/noncopyable.h
index 83923e647..0c54d24a3 100644
--- a/libtransport/includes/hicn/transport/utils/noncopyable.h
+++ b/libtransport/includes/hicn/transport/utils/noncopyable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/object_pool.h b/libtransport/includes/hicn/transport/utils/object_pool.h
index d9b28e663..63288c655 100644
--- a/libtransport/includes/hicn/transport/utils/object_pool.h
+++ b/libtransport/includes/hicn/transport/utils/object_pool.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/utils/branch_prediction.h>
+#include <hicn/transport/utils/noncopyable.h>
#include <hicn/transport/utils/spinlock.h>
#include <deque>
@@ -25,7 +26,7 @@
namespace utils {
template <typename T>
-class ObjectPool {
+class ObjectPool : private utils::NonCopyable {
class ObjectDeleter {
public:
ObjectDeleter(ObjectPool<T> *pool = nullptr) : pool_(pool) {}
@@ -47,8 +48,20 @@ class ObjectPool {
ObjectPool() : destructor_(false) {}
- // No copies
- ObjectPool(const ObjectPool &other) = delete;
+ ObjectPool(ObjectPool &&other)
+ : object_pool_lock_(std::move(other.object_pool_lock_)),
+ object_pool_(std::move(other.object_pool_)),
+ destructor_(other.destructor_) {}
+
+ ObjectPool &operator=(ObjectPool &&other) {
+ if (this != &other) {
+ object_pool_lock_ = std::move(other.object_pool_lock_);
+ object_pool_ = std::move(other.object_pool_);
+ destructor_ = other.destructor_;
+ }
+
+ return *this;
+ }
~ObjectPool() {
destructor_ = true;
diff --git a/libtransport/includes/hicn/transport/utils/ring_buffer.h b/libtransport/includes/hicn/transport/utils/ring_buffer.h
index 52629b82b..3032032c9 100644
--- a/libtransport/includes/hicn/transport/utils/ring_buffer.h
+++ b/libtransport/includes/hicn/transport/utils/ring_buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/rtc_quality_score.h b/libtransport/includes/hicn/transport/utils/rtc_quality_score.h
new file mode 100644
index 000000000..2e8ca97d3
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/rtc_quality_score.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCQualityScore {
+ public:
+ RTCQualityScore(){};
+ ~RTCQualityScore(){};
+
+ uint8_t getQualityScore(uint64_t RTT, uint32_t loss_rate) {
+ uint32_t delay_index = getDelay(RTT);
+ uint32_t loss_index = getLossRate(loss_rate);
+ return quality_score_[loss_index][delay_index];
+ }
+
+ private:
+ // see quality score map
+ uint8_t quality_score_[7][6]{{5, 5, 5, 4, 3, 1}, {5, 4, 3, 2, 1, 1},
+ {5, 3, 2, 1, 1, 1}, {5, 2, 1, 1, 1, 1},
+ {4, 1, 1, 1, 1, 1}, {3, 1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1, 1}};
+
+ uint8_t getDelay(uint64_t RTT) {
+ uint64_t OWD = RTT / 2;
+ // we should never get a OWD of 0. so we take the first col if OWD is < 5ms
+ if (OWD < 5) return 0;
+ if (OWD < 50) return 1;
+ if (OWD < 100) return 2;
+ if (OWD < 200) return 3;
+ if (OWD < 300) return 4;
+ return 5;
+ }
+
+ uint8_t getLossRate(uint32_t loss_rate) {
+ // we use 3% as mean loss rate
+ if (loss_rate < 3) return 0;
+ if (loss_rate < 10) return 1;
+ if (loss_rate < 20) return 2;
+ if (loss_rate < 30) return 3;
+ if (loss_rate < 40) return 4;
+ if (loss_rate < 50) return 5;
+ return 6;
+ }
+};
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/utils/singleton.h b/libtransport/includes/hicn/transport/utils/singleton.h
index 4b7b19c0a..cdd8b03bf 100644
--- a/libtransport/includes/hicn/transport/utils/singleton.h
+++ b/libtransport/includes/hicn/transport/utils/singleton.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,4 +32,17 @@ class Singleton : NonCopyable {
~Singleton() {}
};
+template <typename T>
+class ThreadLocalSingleton : NonCopyable {
+ public:
+ static T& getInstance() {
+ static thread_local T instance;
+ return instance;
+ }
+
+ protected:
+ ThreadLocalSingleton() {}
+ ~ThreadLocalSingleton() {}
+};
+
} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/spinlock.h b/libtransport/includes/hicn/transport/utils/spinlock.h
index 009a94454..40fc48de3 100644
--- a/libtransport/includes/hicn/transport/utils/spinlock.h
+++ b/libtransport/includes/hicn/transport/utils/spinlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/string_tokenizer.h b/libtransport/includes/hicn/transport/utils/string_tokenizer.h
index 36630eb58..2b2b893a0 100644
--- a/libtransport/includes/hicn/transport/utils/string_tokenizer.h
+++ b/libtransport/includes/hicn/transport/utils/string_tokenizer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/string_utils.h b/libtransport/includes/hicn/transport/utils/string_utils.h
index 313c28cc6..5f9cca13b 100644
--- a/libtransport/includes/hicn/transport/utils/string_utils.h
+++ b/libtransport/includes/hicn/transport/utils/string_utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/includes/hicn/transport/utils/thread_pool.h b/libtransport/includes/hicn/transport/utils/thread_pool.h
new file mode 100644
index 000000000..e4e47209c
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/thread_pool.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.
+ */
+
+#pragma once
+
+#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/noncopyable.h>
+
+#include <thread>
+#include <vector>
+
+namespace utils {
+
+class ThreadPool : public NonCopyable {
+ public:
+ explicit ThreadPool(
+ std::size_t n_threads = std::thread::hardware_concurrency())
+ : workers_(n_threads > 0 ? n_threads : 1) {}
+
+ std::size_t getNThreads() const { return workers_.size(); }
+ EventThread &getWorker(std::size_t i) { return workers_.at(i); }
+
+ private:
+ std::vector<EventThread> workers_;
+};
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/uri.h b/libtransport/includes/hicn/transport/utils/uri.h
index 7c28e8552..30675e880 100644
--- a/libtransport/includes/hicn/transport/utils/uri.h
+++ b/libtransport/includes/hicn/transport/utils/uri.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/CMakeLists.txt b/libtransport/src/CMakeLists.txt
index 5e0cd38e7..477a21cb1 100644
--- a/libtransport/src/CMakeLists.txt
+++ b/libtransport/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,10 +11,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-include(GNUInstallDirs)
-
-set(ASIO_STANDALONE 1)
-
+##############################################################
+# Source files
+##############################################################
add_subdirectory(core)
add_subdirectory(interfaces)
add_subdirectory(protocols)
@@ -23,49 +22,131 @@ add_subdirectory(implementation)
add_subdirectory(utils)
add_subdirectory(http)
-include(Packager)
-extract_version()
-configure_file("config.h.in" "hicn/transport/config.h" @ONLY)
-install(
- FILES ${CMAKE_CURRENT_BINARY_DIR}/hicn/transport/config.h
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hicn/transport
- COMPONENT ${LIBTRANSPORT_COMPONENT}-dev
+
+##############################################################
+# Libraries to link
+##############################################################
+set(LIBRARIES
+ PRIVATE ${HICN_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+ PRIVATE ${CMAKE_DL_LIBS}
+ PRIVATE ${OPENSSL_LIBRARIES}
+ PRIVATE ${LIBCONFIG_CPP_LIBRARIES}
+ PRIVATE ${THIRD_PARTY_LIBRARIES}
)
-install(
- FILES "transport.config"
- DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
- COMPONENT ${LIBTRANSPORT_COMPONENT}
+
+##############################################################
+# Include dirs
+##############################################################
+list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
+ PRIVATE
+ ${CMAKE_THREADS_INCLUDE_DIRS}
+ ${ASIO_INCLUDE_DIRS}
+ ${WINDOWS_INCLUDE_DIRS}
+ ${LIBCONFIG_CPP_INCLUDE_DIRS}
+ ${THIRD_PARTY_INCLUDE_DIRS}
+ PUBLIC
+ ${ASIO_INCLUDE_DIRS}
+ ${OPENSSL_INCLUDE_DIR}
)
-list(APPEND COMPILER_DEFINITIONS
- "-DASIO_STANDALONE"
+list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/
+ PUBLIC
+ $<BUILD_INTERFACE:${Libhicntransport_INCLUDE_DIRS}>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
-list(INSERT LIBTRANSPORT_INTERNAL_INCLUDE_DIRS 0
- ${CMAKE_CURRENT_SOURCE_DIR}/
- ${CMAKE_CURRENT_BINARY_DIR}/
+
+##############################################################
+# Dependencies
+##############################################################
+list(APPEND DEPENDENCIES
+ ${THIRD_PARTY_DEPENDENCIES}
)
-set(LIBTRANSPORT_INCLUDE_DIRS
- ${LIBTRANSPORT_INCLUDE_DIRS}
- "" CACHE INTERNAL
- "" FORCE
+##############################################################
+# Compiler definitions
+##############################################################
+list(APPEND COMPILER_DEFINITIONS
+ PUBLIC "-DASIO_STANDALONE"
+)
+
+if (ENABLE_RELY)
+ list(APPEND COMPILER_DEFINITIONS
+ PRIVATE "-DENABLE_RELY=1"
+ )
+endif()
+
+
+##############################################################
+# Compiler options
+##############################################################
+list(APPEND COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
)
if (NOT WIN32)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
+ list(APPEND COMPILER_OPTIONS
+ PRIVATE "-pthread"
+ )
else ()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 -D_WIN32_WINDOWS=0x0400")
+ list(APPEND COMPILER_OPTIONS
+ PRIVATE "-/wd4200 -D_WIN32_WINDOWS=0x0400"
+ )
if (CMAKE_BUILD_TYPE EQUAL "RELEASE")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:\"MSVCRTD\"" )
+ list(APPEND COMPILER_OPTIONS
+ PRIVATE "/NODEFAULTLIB:\"MSVCRTD\""
+ )
endif ()
endif ()
if (${CMAKE_SYSTEM_NAME} MATCHES "Android")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -isystem -lm")
+ list(APPEND COMPILER_OPTIONS
+ PRIVATE "-stdlib=libc++"
+ PRIVATE "-isystem"
+ PRIVATE "-lm"
+ )
endif()
+
+##############################################################
+# Configuration file
+##############################################################
+configure_file("config.h.in" "hicn/transport/config.h" @ONLY)
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/hicn/transport/config.h
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hicn/transport
+ COMPONENT ${LIBTRANSPORT_COMPONENT}-dev
+)
+
+if (${CMAKE_SYSTEM_NAME} MATCHES Darwin OR ${CMAKE_SYSTEM_NAME} MATCHES Linux)
+ install(
+ FILES "transport.config"
+ DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ )
+else ()
+ install(
+ FILES "transport.config"
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/etc/hicn
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ )
+endif()
+
+
+##############################################################
+# IO Modules
+##############################################################
+add_subdirectory(io_modules)
+
+
+##############################################################
+# Build type
+##############################################################
set (BUILD_TYPES "STATIC")
if (NOT DISABLE_SHARED_LIBRARIES)
@@ -74,8 +155,10 @@ if (NOT DISABLE_SHARED_LIBRARIES)
)
endif()
-add_subdirectory(io_modules)
+##############################################################
+# Build library
+##############################################################
build_library(${LIBTRANSPORT}
${BUILD_TYPES}
SOURCES ${SOURCE_FILES} ${HEADER_FILES}
@@ -84,12 +167,29 @@ build_library(${LIBTRANSPORT}
OBJECT_LIBRARIES ${THIRD_PARTY_OBJECT_LIBRARIES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBTRANSPORT_COMPONENT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn/transport
+ INCLUDE_DIRS ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
- VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
+ VERSION ${CURRENT_VERSION}
+ EXPORT_NAME ${LIBTRANSPORT_COMPONENT}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
+
+##############################################################
+# Unit tests
+##############################################################
if (${BUILD_TESTS})
add_subdirectory(test)
endif()
+
+
+##############################################################
+# Cmake config files
+##############################################################
+create_cmake_config (
+ ${LIBTRANSPORT_COMPONENT}
+ INCLUDE_DIRS ${Libhicntransport_INCLUDE_DIRS}
+ VERSION ${CURRENT_VERSION}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ NAMESPACE hicn
+)
diff --git a/libtransport/src/auth/CMakeLists.txt b/libtransport/src/auth/CMakeLists.txt
index 699bc1050..8d3286338 100644
--- a/libtransport/src/auth/CMakeLists.txt
+++ b/libtransport/src/auth/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -14,7 +14,6 @@
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/signer.cc
${CMAKE_CURRENT_SOURCE_DIR}/verifier.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/identity.cc
${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.cc
${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.cc
)
diff --git a/libtransport/src/auth/crypto_hash.cc b/libtransport/src/auth/crypto_hash.cc
index b4b0a8b81..f60f46051 100644
--- a/libtransport/src/auth/crypto_hash.cc
+++ b/libtransport/src/auth/crypto_hash.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,8 +15,6 @@
#include <hicn/transport/auth/crypto_hash.h>
-using namespace std;
-
namespace transport {
namespace auth {
@@ -28,7 +26,7 @@ CryptoHash::CryptoHash(const CryptoHash &other)
digest_size_(other.digest_size_) {}
CryptoHash::CryptoHash(CryptoHash &&other)
- : digest_type_(move(other.digest_type_)),
+ : digest_type_(std::move(other.digest_type_)),
digest_(other.digest_),
digest_size_(other.digest_size_) {
other.reset();
@@ -43,13 +41,16 @@ CryptoHash::CryptoHash(const uint8_t *hash, size_t size,
memcpy(digest_.data(), hash, size);
}
-CryptoHash::CryptoHash(const vector<uint8_t> &hash, CryptoHashType hash_type)
+CryptoHash::CryptoHash(const std::vector<uint8_t> &hash,
+ CryptoHashType hash_type)
: CryptoHash(hash.data(), hash.size(), hash_type) {}
CryptoHash &CryptoHash::operator=(const CryptoHash &other) {
- digest_type_ = other.digest_type_;
- digest_ = other.digest_;
- digest_size_ = other.digest_size_;
+ if (this != &other) {
+ digest_type_ = other.digest_type_;
+ digest_ = other.digest_;
+ digest_size_ = other.digest_size_;
+ }
return *this;
}
@@ -68,7 +69,7 @@ void CryptoHash::computeDigest(const uint8_t *buffer, size_t len) {
(*hash_evp)(), nullptr);
}
-void CryptoHash::computeDigest(const vector<uint8_t> &buffer) {
+void CryptoHash::computeDigest(const std::vector<uint8_t> &buffer) {
computeDigest(buffer.data(), buffer.size());
}
@@ -102,15 +103,15 @@ void CryptoHash::computeDigest(const utils::MemBuf *buffer) {
EVP_MD_CTX_free(mcdtx);
}
-vector<uint8_t> CryptoHash::getDigest() const { return digest_; }
+std::vector<uint8_t> CryptoHash::getDigest() const { return digest_; }
-string CryptoHash::getStringDigest() const {
- stringstream string_digest;
+std::string CryptoHash::getStringDigest() const {
+ std::stringstream string_digest;
- string_digest << hex << setfill('0');
+ string_digest << std::hex << std::setfill('0');
for (auto byte : digest_) {
- string_digest << hex << setw(2) << static_cast<int>(byte);
+ string_digest << std::hex << std::setw(2) << static_cast<int>(byte);
}
return string_digest.str();
@@ -130,23 +131,23 @@ void CryptoHash::setType(CryptoHashType hash_type) {
void CryptoHash::display() {
switch (digest_type_) {
case CryptoHashType::SHA256:
- cout << "SHA256";
+ std::cout << "SHA256";
break;
case CryptoHashType::SHA512:
- cout << "SHA512";
+ std::cout << "SHA512";
break;
case CryptoHashType::BLAKE2S256:
- cout << "BLAKE2s256";
+ std::cout << "BLAKE2s256";
break;
case CryptoHashType::BLAKE2B512:
- cout << "BLAKE2b512";
+ std::cout << "BLAKE2b512";
break;
default:
- cout << "UNKNOWN";
+ std::cout << "UNKNOWN";
break;
}
- cout << ": " << getStringDigest() << endl;
+ std::cout << ": " << getStringDigest() << std::endl;
}
void CryptoHash::reset() {
@@ -159,19 +160,14 @@ CryptoHashEVP CryptoHash::getEVP(CryptoHashType hash_type) {
switch (hash_type) {
case CryptoHashType::SHA256:
return &EVP_sha256;
- break;
case CryptoHashType::SHA512:
return &EVP_sha512;
- break;
case CryptoHashType::BLAKE2S256:
return &EVP_blake2s256;
- break;
case CryptoHashType::BLAKE2B512:
return &EVP_blake2b512;
- break;
default:
return nullptr;
- break;
}
}
diff --git a/libtransport/src/auth/crypto_suite.cc b/libtransport/src/auth/crypto_suite.cc
index 7e898ef09..44de85212 100644
--- a/libtransport/src/auth/crypto_suite.cc
+++ b/libtransport/src/auth/crypto_suite.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,31 +22,61 @@ CryptoSuite getSuite(int nid) {
switch (nid) {
case NID_ecdsa_with_SHA256:
return CryptoSuite::ECDSA_SHA256;
- break;
case NID_ecdsa_with_SHA512:
return CryptoSuite::ECDSA_SHA512;
- break;
case NID_sha256WithRSAEncryption:
return CryptoSuite::RSA_SHA256;
- break;
case NID_sha512WithRSAEncryption:
return CryptoSuite::RSA_SHA512;
- break;
case NID_hmacWithSHA256:
return CryptoSuite::HMAC_SHA256;
- break;
case NID_hmacWithSHA512:
return CryptoSuite::HMAC_SHA512;
- break;
case NID_dsa_with_SHA256:
return CryptoSuite::DSA_SHA256;
- break;
case NID_dsa_with_SHA512:
return CryptoSuite::DSA_SHA512;
- break;
default:
return CryptoSuite::UNKNOWN;
- break;
+ }
+}
+
+std::string getStringSuite(CryptoSuite suite) {
+ switch (suite) {
+ case CryptoSuite::ECDSA_BLAKE2B512:
+ return "ECDSA_BLAKE2B512";
+ case CryptoSuite::ECDSA_BLAKE2S256:
+ return "ECDSA_BLAKE2S256";
+ case CryptoSuite::ECDSA_SHA256:
+ return "ECDSA_SHA256";
+ case CryptoSuite::ECDSA_SHA512:
+ return "ECDSA_SHA512";
+ case CryptoSuite::RSA_BLAKE2B512:
+ return "RSA_BLAKE2B512";
+ case CryptoSuite::RSA_BLAKE2S256:
+ return "RSA_BLAKE2S256";
+ case CryptoSuite::RSA_SHA256:
+ return "RSA_SHA256";
+ case CryptoSuite::RSA_SHA512:
+ return "RSA_SHA512";
+ case CryptoSuite::HMAC_BLAKE2B512:
+ return "HMAC_BLAKE2B512";
+ case CryptoSuite::HMAC_BLAKE2S256:
+ return "HMAC_BLAKE2S256";
+ case CryptoSuite::HMAC_SHA256:
+ return "HMAC_SHA256";
+ case CryptoSuite::HMAC_SHA512:
+ return "HMAC_SHA512";
+ case CryptoSuite::DSA_BLAKE2B512:
+ return "DSA_BLAKE2B512";
+ case CryptoSuite::DSA_BLAKE2S256:
+ return "DSA_BLAKE2S256";
+ case CryptoSuite::DSA_SHA256:
+ return "DSA_SHA256";
+ case CryptoSuite::DSA_SHA512:
+ return "DSA_SHA512";
+ default:
+ return "UNKNOWN";
}
}
diff --git a/libtransport/src/auth/identity.cc b/libtransport/src/auth/identity.cc
deleted file mode 100644
index f56532033..000000000
--- a/libtransport/src/auth/identity.cc
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/auth/identity.h>
-
-using namespace std;
-
-// function needed to create the a certificate
-static bool _addRandomSerial(X509 *cert) {
- unsigned long serial = 0;
- unsigned char serial_bytes[sizeof(serial)];
-
- // Construct random positive serial number.
- RAND_bytes(serial_bytes, sizeof(serial_bytes));
- serial_bytes[0] &= 0x7F;
- serial = 0;
- for (size_t i = 0; i < sizeof(serial_bytes); i++) {
- serial = (256 * serial) + serial_bytes[i];
- }
- ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
- return true;
-}
-
-static bool _addValidityPeriod(X509 *cert, size_t validityDays) {
- // Set the validity from now for the specified number of days.
- X509_gmtime_adj(X509_get_notBefore(cert), (long)0);
- X509_gmtime_adj(X509_get_notAfter(cert), (long)(60 * 60 * 24 * validityDays));
- return true;
-}
-
-static bool _addSubjectName(X509 *cert, const char *subjectname) {
- // Set up the simple subject name and issuer name for the certificate.
- X509_NAME *name = X509_get_subject_name(cert);
-
- if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
- (unsigned char *)subjectname, -1, -1, 0)) {
- if (X509_set_issuer_name(cert, name)) {
- return true;
- }
- }
- return false;
-}
-static bool _addCertificateExtensionWithContext(X509 *cert, int nid,
- const char *value) {
- X509_EXTENSION *extension;
- X509V3_CTX context;
-
- X509V3_set_ctx_nodb(&context);
- X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0);
- extension = X509V3_EXT_conf_nid(NULL, &context, nid, value);
- if (extension == NULL) {
- return false;
- }
- X509_add_ext(cert, extension, -1);
- X509_EXTENSION_free(extension);
- return true;
-}
-static bool _addCertificateExtension(X509 *cert, int nid, const char *value) {
- X509_EXTENSION *extension = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
- if (extension == NULL) {
- return false;
- }
- X509_add_ext(cert, extension, -1);
- X509_EXTENSION_free(extension);
- return true;
-}
-
-static bool _addExtensions(X509 *cert) {
- // Add the necessary extensions.
- if (_addCertificateExtension(cert, NID_basic_constraints,
- "critical,CA:FALSE") == true) {
- if (_addCertificateExtension(
- cert, NID_key_usage,
- "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,"
- "keyAgreement") == true) {
- if (_addCertificateExtension(cert, NID_ext_key_usage, "clientAuth") ==
- true) {
- return true;
- }
- }
- }
- return false;
-}
-static bool _addKeyIdentifier(X509 *cert) {
- unsigned char spkid[SHA256_DIGEST_LENGTH];
- char spkid_hex[1 + 2 * SHA256_DIGEST_LENGTH];
- if (ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(),
- X509_get_X509_PUBKEY(cert), spkid, NULL)) {
- for (int i = 0; i < 32; i++) {
- snprintf(&spkid_hex[2 * i], 3, "%02X", (unsigned)spkid[i]);
- }
- if (_addCertificateExtension(cert, NID_subject_key_identifier, spkid_hex) ==
- true) {
- if (_addCertificateExtensionWithContext(
- cert, NID_authority_key_identifier, "keyid:always") == true) {
- return true;
- }
- }
- }
- return false;
-}
-
-namespace transport {
-namespace auth {
-
-Identity::Identity(const string &keystore_path, const string &keystore_pwd,
- CryptoSuite suite, unsigned int signature_len,
- unsigned int validity_days, const string &subject_name)
- : cert_(X509_new(), ::X509_free) {
- // create the file and complete it.
- // first we create the certificate
-
- // to create the cert we will need a private key
-
- std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
-
- if (suite == CryptoSuite::RSA_SHA512 || suite == CryptoSuite::RSA_SHA256) {
- RSA *rsa = RSA_new();
- BIGNUM *pub_exp;
-
- pub_exp = BN_new();
-
- BN_set_word(pub_exp, RSA_F4);
- if (1 != RSA_generate_key_ex(rsa, signature_len, pub_exp, NULL))
- throw errors::RuntimeException("can't generate the key");
- if (1 != EVP_PKEY_set1_RSA(privateKey.get(), rsa))
- throw errors::RuntimeException("can't generate the key");
- } else if (suite == CryptoSuite::ECDSA_SHA256) {
- int curve_params;
- switch (signature_len) {
- case 160u:
- curve_params = NID_secp160k1;
- break;
- case 192u:
- curve_params = NID_secp192k1;
- break;
- case 224u:
- curve_params = NID_secp224k1;
- break;
- case 256u:
- curve_params = NID_secp256k1;
- break;
- default:
- curve_params = -1;
- break;
- }
- if (curve_params == -1)
- throw errors::RuntimeException("can't generate the key");
- EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve_params);
- if (ec_key == NULL)
- throw errors::RuntimeException("can't create ecdsa key from curve");
- EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
- if (EC_KEY_generate_key(ec_key) == 0)
- throw errors::RuntimeException("can't generate the ecdsa key");
- if (EVP_PKEY_set1_EC_KEY(privateKey.get(), ec_key) == 0)
- throw errors::RuntimeException("can't generate the ecdsa key");
- } else if (suite == CryptoSuite::DSA_SHA256) {
- DSA *dsa = DSA_new();
- unsigned char buffer[32];
- if (RAND_bytes(buffer, sizeof(buffer)) != 1) {
- throw errors::RuntimeException("can't generate the key");
- }
- if (DSA_generate_parameters_ex(dsa, signature_len, buffer, sizeof(buffer),
- NULL, NULL, NULL) != 1)
- throw errors::RuntimeException("can't generate the key");
- if (DSA_generate_key(dsa) != 1)
- throw errors::RuntimeException("can't generate the key");
- if (EVP_PKEY_set1_DSA(privateKey.get(), dsa) != 1)
- throw errors::RuntimeException("can't generate the key");
- }
- bool success = true;
- success = success && (X509_set_version(cert_.get(), 2) == 1); // 2 => X509v3
- success = success && _addRandomSerial(cert_.get());
- success = success && _addValidityPeriod(cert_.get(), validity_days);
- success = success && (X509_set_pubkey(cert_.get(), privateKey.get()) == 1);
- success = success && _addSubjectName(cert_.get(), subject_name.c_str());
- success = success && _addExtensions(cert_.get());
- success =
- success && (X509_sign(cert_.get(), privateKey.get(), EVP_sha256()) != 0);
- success = success && _addKeyIdentifier(cert_.get());
- if (!success) {
- throw errors::RuntimeException("error while creating the certificate");
- }
- // the certificate is created. We create the pkcs12 object to write the p12
- // file
- PKCS12 *p12 = PKCS12_create(
- keystore_pwd.c_str(), "ccnxuser", privateKey.get(), cert_.get(), NULL, 0,
- 0, 0 /*default iter*/, PKCS12_DEFAULT_ITER /*mac_iter*/, 0);
- filename_ = keystore_path;
- int fp = open(filename_.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0600);
- if (fp == -1) throw errors::RuntimeException("impossible to create the file");
- FILE *fp_f = fdopen(fp, "wb");
- if (fp_f == NULL)
- throw errors::RuntimeException("impossible to create the file");
- i2d_PKCS12_fp(fp_f, p12);
- fclose(fp_f);
- close(fp);
- std::shared_ptr<EVP_PKEY> publickey(X509_get_pubkey(cert_.get()),
- EVP_PKEY_free);
- signer_ = std::shared_ptr<AsymmetricSigner>(
- new AsymmetricSigner(suite, privateKey, publickey));
- signer_->signature_len_ = signature_len;
-}
-
-Identity::Identity(string &keystore_path, string &keystore_pwd,
- CryptoHashType hash_type)
- : cert_(X509_new(), ::X509_free) {
- filename_ = keystore_path;
- pwd_ = keystore_path;
- // get the key and certificate by first opening the keystore file
- FILE *p12file = fopen(keystore_path.c_str(), "r");
- if (p12file == NULL)
- throw errors::RuntimeException("impossible open keystore");
- PKCS12 *p12 = d2i_PKCS12_fp(p12file, NULL);
- EVP_PKEY *privatekey;
- EVP_PKEY *publickey;
- X509 *cert = cert_.get();
- // now we parse the file to get the first key and certificate
- if (1 != PKCS12_parse(p12, keystore_pwd.c_str(), &privatekey, &cert, NULL))
- throw errors::RuntimeException("impossible to get the private key");
- publickey = X509_get_pubkey(cert);
- // to have the cryptosuite we use the nid number that is used to identify the
- // suite.
- CryptoSuite suite = getSuite(X509_get_signature_nid(cert));
- signer_ = std::shared_ptr<AsymmetricSigner>(new AsymmetricSigner(
- suite, std::shared_ptr<EVP_PKEY>(privatekey, EVP_PKEY_free),
- std::shared_ptr<EVP_PKEY>(publickey, EVP_PKEY_free)));
- PKCS12_free(p12);
-}
-
-Identity::Identity(const Identity &other) {
- pwd_ = other.pwd_;
- filename_ = other.filename_;
- signer_ = other.signer_;
- cert_ = other.cert_;
-}
-
-Identity::Identity(Identity &&other) {
- signer_ = std::move(other.signer_);
- other.signer_.reset();
- cert_ = std::move(other.cert_);
- other.cert_.reset();
- pwd_ = other.pwd_;
- other.pwd_ = "";
- filename_ = other.filename_;
- other.filename_ = "";
- signer_ = other.signer_;
- other.signer_ = nullptr;
-}
-
-Identity::~Identity() {}
-
-shared_ptr<AsymmetricSigner> Identity::getSigner() const { return signer_; }
-
-string Identity::getFilename() const { return filename_; }
-
-std::shared_ptr<X509> Identity::getCertificate() const { return cert_; }
-std::shared_ptr<EVP_PKEY> Identity::getPrivateKey() const {
- return signer_->key_;
-}
-
-string Identity::getPassword() const { return pwd_; }
-
-Identity Identity::generateIdentity(const string &subject_name) {
- string keystore_name = "keystore";
- string keystore_password = "password";
- size_t key_length = 1024;
- unsigned int validity_days = 30;
- CryptoSuite suite = CryptoSuite::RSA_SHA256;
-
- return Identity(keystore_name, keystore_password, suite,
- (unsigned int)key_length, validity_days, subject_name);
-}
-
-} // namespace auth
-} // namespace transport
diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc
index 884e850ca..e74e2f1b8 100644
--- a/libtransport/src/auth/signer.cc
+++ b/libtransport/src/auth/signer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -13,9 +13,9 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/auth/signer.h>
-
-using namespace std;
+#include <hicn/transport/utils/chrono_typedefs.h>
namespace transport {
namespace auth {
@@ -29,31 +29,29 @@ Signer::Signer()
Signer::~Signer() {}
void Signer::signPacket(PacketPtr packet) {
- assert(key_ != nullptr);
+ DCHECK(key_ != nullptr);
core::Packet::Format format = packet->getFormat();
- if (!packet->authenticationHeader()) {
+ if (!packet->hasAH()) {
throw errors::MalformedAHPacketException();
}
// Set signature size
size_t signature_field_len = getSignatureFieldSize();
- packet->setSignatureSize(signature_field_len);
- packet->setSignatureSizeGap(0u);
+ packet->setSignatureFieldSize(signature_field_len);
+ packet->updateLength(); // update IP payload length
// Copy IP+TCP / ICMP header before zeroing them
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
// Fill in the hICN AH header
- auto now = chrono::duration_cast<chrono::milliseconds>(
- chrono::system_clock::now().time_since_epoch())
- .count();
+ auto now = utils::SteadyTime::nowMs().count();
packet->setSignatureTimestamp(now);
packet->setValidationAlgorithm(suite_);
// Set key ID
- vector<uint8_t> key_id = key_id_.getDigest();
+ std::vector<uint8_t> key_id = key_id_.getDigest();
packet->setKeyId({key_id.data(), key_id.size()});
// Reset fields to compute the packet hash
@@ -61,22 +59,22 @@ void Signer::signPacket(PacketPtr packet) {
// Compute the signature and put it in the packet
signBuffer(packet);
- hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
+ packet->setSignature(signature_);
+ packet->setSignatureSize(signature_len_);
- // Set the gap between the signature field size and the signature real size.
- packet->setSignatureSizeGap(signature_field_len - signature_len_);
- memcpy(packet->getSignature(), signature_.data(), signature_len_);
+ // Restore header
+ hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
}
void Signer::signBuffer(const std::vector<uint8_t> &buffer) {
- assert(key_ != nullptr);
+ DCHECK(key_ != nullptr);
CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
if (hash_evp == nullptr) {
throw errors::RuntimeException("Unknown hash type");
}
- shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+ std::shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
if (mdctx == nullptr) {
throw errors::RuntimeException("Digest context allocation failed");
@@ -106,7 +104,7 @@ void Signer::signBuffer(const std::vector<uint8_t> &buffer) {
}
void Signer::signBuffer(const utils::MemBuf *buffer) {
- assert(key_ != nullptr);
+ DCHECK(key_ != nullptr);
CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
if (hash_evp == nullptr) {
@@ -114,7 +112,7 @@ void Signer::signBuffer(const utils::MemBuf *buffer) {
}
const utils::MemBuf *p = buffer;
- shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+ std::shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
if (mdctx == nullptr) {
throw errors::RuntimeException("Digest context allocation failed");
@@ -147,7 +145,18 @@ void Signer::signBuffer(const utils::MemBuf *buffer) {
signature_.resize(signature_len_);
}
-vector<uint8_t> Signer::getSignature() const { return signature_; }
+std::vector<uint8_t> Signer::getSignature() const { return signature_; }
+
+std::string Signer::getStringSignature() const {
+ std::stringstream string_sig;
+ string_sig << std::hex << std::setfill('0');
+
+ for (auto byte : signature_) {
+ string_sig << std::hex << std::setw(2) << static_cast<int>(byte);
+ }
+
+ return string_sig.str();
+}
size_t Signer::getSignatureSize() const { return signature_len_; }
@@ -159,36 +168,75 @@ size_t Signer::getSignatureFieldSize() const {
return (signature_len_ + 4) - (signature_len_ % 4);
}
+CryptoSuite Signer::getSuite() const { return suite_; }
+
CryptoHashType Signer::getHashType() const {
return ::transport::auth::getHashType(suite_);
}
-CryptoSuite Signer::getSuite() const { return suite_; }
+void Signer::display() {
+ std::cout << getStringSuite(suite_) << ": " << getStringSignature()
+ << std::endl;
+}
// ---------------------------------------------------------
// Void Signer
// ---------------------------------------------------------
-void VoidSigner::signPacket(PacketPtr packet){};
+void VoidSigner::signPacket(PacketPtr packet) {}
-void VoidSigner::signBuffer(const std::vector<uint8_t> &buffer){};
+void VoidSigner::signBuffer(const std::vector<uint8_t> &buffer) {}
-void VoidSigner::signBuffer(const utils::MemBuf *buffer){};
+void VoidSigner::signBuffer(const utils::MemBuf *buffer) {}
// ---------------------------------------------------------
// Asymmetric Signer
// ---------------------------------------------------------
-AsymmetricSigner::AsymmetricSigner(CryptoSuite suite, shared_ptr<EVP_PKEY> key,
- shared_ptr<EVP_PKEY> pub_key) {
+AsymmetricSigner::AsymmetricSigner(CryptoSuite suite,
+ std::shared_ptr<EVP_PKEY> key,
+ std::shared_ptr<EVP_PKEY> pub_key) {
+ setKey(suite, key, pub_key);
+}
+
+AsymmetricSigner::AsymmetricSigner(std::string keystore_path,
+ std::string password) {
+ FILE *p12file = fopen(keystore_path.c_str(), "r");
+
+ if (p12file == nullptr) {
+ throw errors::RuntimeException("failed to read keystore");
+ }
+
+ std::unique_ptr<PKCS12, decltype(&PKCS12_free)> p12(
+ d2i_PKCS12_fp(p12file, nullptr), &PKCS12_free);
+ X509 *cert_raw;
+ EVP_PKEY *key_raw;
+
+ if (PKCS12_parse(p12.get(), password.c_str(), &key_raw, &cert_raw, nullptr) !=
+ 1) {
+ fclose(p12file);
+ throw errors::RuntimeException("failed to parse keystore");
+ }
+
+ std::shared_ptr<EVP_PKEY> key(key_raw, EVP_PKEY_free);
+ std::shared_ptr<EVP_PKEY> pub_key(X509_get_pubkey(cert_raw), EVP_PKEY_free);
+
+ setKey(transport::auth::getSuite(X509_get_signature_nid(cert_raw)), key,
+ pub_key);
+
+ fclose(p12file);
+}
+
+void AsymmetricSigner::setKey(CryptoSuite suite, std::shared_ptr<EVP_PKEY> key,
+ std::shared_ptr<EVP_PKEY> pub_key) {
suite_ = suite;
key_ = key;
- key_id_ = CryptoHash(getHashType());
+ signature_len_ = EVP_PKEY_size(key.get());
+ signature_.resize(signature_len_);
- vector<uint8_t> pbk(i2d_PublicKey(pub_key.get(), nullptr));
+ 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);
- signature_len_ = EVP_PKEY_size(key.get());
- signature_.resize(signature_len_);
+ key_id_ = CryptoHash(getHashType());
key_id_.computeDigest(pbk_ptr, len);
}
@@ -205,9 +253,10 @@ size_t AsymmetricSigner::getSignatureFieldSize() const {
// ---------------------------------------------------------
// Symmetric Signer
// ---------------------------------------------------------
-SymmetricSigner::SymmetricSigner(CryptoSuite suite, const string &passphrase) {
+SymmetricSigner::SymmetricSigner(CryptoSuite suite,
+ const std::string &passphrase) {
suite_ = suite;
- key_ = shared_ptr<EVP_PKEY>(
+ key_ = std::shared_ptr<EVP_PKEY>(
EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr,
(const unsigned char *)passphrase.c_str(),
passphrase.size()),
diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc
index c9ac1650f..0c35437f3 100644
--- a/libtransport/src/auth/verifier.cc
+++ b/libtransport/src/auth/verifier.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -16,12 +16,10 @@
#include <hicn/transport/auth/verifier.h>
#include <protocols/errors.h>
-using namespace std;
-
namespace transport {
namespace auth {
-const vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
+const std::vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
VerificationPolicy::DROP,
VerificationPolicy::ABORT,
};
@@ -38,24 +36,21 @@ Verifier::~Verifier() {}
bool Verifier::verifyPacket(PacketPtr packet) {
core::Packet::Format format = packet->getFormat();
- if (!packet->authenticationHeader()) {
+ if (!packet->hasAH()) {
throw errors::MalformedAHPacketException();
}
// Get crypto suite, hash type, signature length
CryptoSuite suite = packet->getValidationAlgorithm();
CryptoHashType hash_type = getHashType(suite);
- size_t signature_len = packet->getSignatureSizeReal();
// Copy IP+TCP / ICMP header before zeroing them
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
- packet->setSignatureSizeGap(0u);
// Retrieve packet signature
- uint8_t *packet_signature = packet->getSignature();
- vector<uint8_t> signature_raw(packet_signature,
- packet_signature + signature_len);
+ std::vector<uint8_t> signature_raw = packet->getSignature();
+ signature_raw.resize(packet->getSignatureSize());
// Reset fields that are not used to compute signature
packet->resetForHash();
@@ -66,12 +61,14 @@ bool Verifier::verifyPacket(PacketPtr packet) {
// Restore header
hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
- packet->setSignatureSizeGap(packet->getSignatureSize() - signature_len);
+ packet->setSignature(signature_raw);
+ packet->setSignatureSize(signature_raw.size());
return valid_packet;
}
-Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets) {
+Verifier::PolicyMap Verifier::verifyPackets(
+ const std::vector<PacketPtr> &packets) {
PolicyMap policies;
for (const auto &packet : packets) {
@@ -82,8 +79,8 @@ Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets) {
policy = VerificationPolicy::ACCEPT;
}
+ callVerificationFailedCallback(suffix, policy);
policies[suffix] = policy;
- callVerificationFailedCallback(packet, policy);
}
return policies;
@@ -105,14 +102,15 @@ Verifier::PolicyMap Verifier::verifyHashes(const SuffixMap &packet_map,
}
}
+ callVerificationFailedCallback(packet_hash.first, policy);
policies[packet_hash.first] = policy;
}
return policies;
}
-Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets,
- const SuffixMap &suffix_map) {
+Verifier::PolicyMap Verifier::verifyPackets(
+ const std::vector<PacketPtr> &packets, const SuffixMap &suffix_map) {
PolicyMap policies;
for (const auto &packet : packets) {
@@ -130,8 +128,8 @@ Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets,
}
}
+ callVerificationFailedCallback(suffix, policy);
policies[suffix] = policy;
- callVerificationFailedCallback(packet, policy);
}
return policies;
@@ -139,7 +137,7 @@ Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets,
void Verifier::setVerificationFailedCallback(
VerificationFailedCallback verfication_failed_cb,
- const vector<VerificationPolicy> &failed_policies) {
+ const std::vector<VerificationPolicy> &failed_policies) {
verification_failed_cb_ = verfication_failed_cb;
failed_policies_ = failed_policies;
}
@@ -149,7 +147,7 @@ void Verifier::getVerificationFailedCallback(
*verfication_failed_cb = &verification_failed_cb_;
}
-void Verifier::callVerificationFailedCallback(PacketPtr packet,
+void Verifier::callVerificationFailedCallback(Suffix suffix,
VerificationPolicy &policy) {
if (verification_failed_cb_ == interface::VOID_HANDLER) {
return;
@@ -157,10 +155,7 @@ void Verifier::callVerificationFailedCallback(PacketPtr packet,
if (find(failed_policies_.begin(), failed_policies_.end(), policy) !=
failed_policies_.end()) {
- policy = verification_failed_cb_(
- static_cast<const core::ContentObject &>(*packet),
- make_error_code(
- protocol::protocol_error::signature_verification_failed));
+ policy = verification_failed_cb_(suffix, policy);
}
}
@@ -169,71 +164,75 @@ void Verifier::callVerificationFailedCallback(PacketPtr packet,
// ---------------------------------------------------------
bool VoidVerifier::verifyPacket(PacketPtr packet) { return true; }
-bool VoidVerifier::verifyBuffer(const vector<uint8_t> &buffer,
- const vector<uint8_t> &signature,
+bool VoidVerifier::verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
CryptoHashType hash_type) {
return true;
}
bool VoidVerifier::verifyBuffer(const utils::MemBuf *buffer,
- const vector<uint8_t> &signature,
+ const std::vector<uint8_t> &signature,
CryptoHashType hash_type) {
return true;
}
Verifier::PolicyMap VoidVerifier::verifyPackets(
- const vector<PacketPtr> &packets) {
+ const std::vector<PacketPtr> &packets) {
PolicyMap policies;
for (const auto &packet : packets) {
- policies[packet->getName().getSuffix()] = VerificationPolicy::ACCEPT;
+ auth::Suffix suffix = packet->getName().getSuffix();
+ VerificationPolicy policy = VerificationPolicy::ACCEPT;
+ callVerificationFailedCallback(suffix, policy);
+ policies[suffix] = policy;
}
return policies;
}
Verifier::PolicyMap VoidVerifier::verifyPackets(
- const vector<PacketPtr> &packets, const SuffixMap &suffix_map) {
+ const std::vector<PacketPtr> &packets, const SuffixMap &suffix_map) {
return verifyPackets(packets);
}
// ---------------------------------------------------------
// Asymmetric Verifier
// ---------------------------------------------------------
-AsymmetricVerifier::AsymmetricVerifier(shared_ptr<EVP_PKEY> key) {
+AsymmetricVerifier::AsymmetricVerifier(std::shared_ptr<EVP_PKEY> key) {
setKey(key);
}
-AsymmetricVerifier::AsymmetricVerifier(const string &cert_path) {
+AsymmetricVerifier::AsymmetricVerifier(const std::string &cert_path) {
useCertificate(cert_path);
}
-AsymmetricVerifier::AsymmetricVerifier(shared_ptr<X509> cert) {
+AsymmetricVerifier::AsymmetricVerifier(std::shared_ptr<X509> cert) {
useCertificate(cert);
}
-void AsymmetricVerifier::setKey(shared_ptr<EVP_PKEY> key) { key_ = key; };
+void AsymmetricVerifier::setKey(std::shared_ptr<EVP_PKEY> key) { key_ = key; };
-void AsymmetricVerifier::useCertificate(const string &cert_path) {
+void AsymmetricVerifier::useCertificate(const std::string &cert_path) {
FILE *certf = fopen(cert_path.c_str(), "rb");
if (certf == nullptr) {
throw errors::RuntimeException("Certificate not found");
}
- shared_ptr<X509> cert = shared_ptr<X509>(
+ std::shared_ptr<X509> cert = std::shared_ptr<X509>(
PEM_read_X509(certf, nullptr, nullptr, nullptr), ::X509_free);
useCertificate(cert);
fclose(certf);
}
-void AsymmetricVerifier::useCertificate(shared_ptr<X509> cert) {
- key_ = shared_ptr<EVP_PKEY>(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
+void AsymmetricVerifier::useCertificate(std::shared_ptr<X509> cert) {
+ key_ =
+ std::shared_ptr<EVP_PKEY>(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
}
-bool AsymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
- const vector<uint8_t> &signature,
+bool AsymmetricVerifier::verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
CryptoHashType hash_type) {
CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
@@ -241,7 +240,7 @@ bool AsymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
throw errors::RuntimeException("Unknown hash type");
}
- shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+ std::shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
if (mdctx == nullptr) {
throw errors::RuntimeException("Digest context allocation failed");
@@ -261,7 +260,7 @@ bool AsymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
}
bool AsymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
- const vector<uint8_t> &signature,
+ const std::vector<uint8_t> &signature,
CryptoHashType hash_type) {
CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
@@ -270,7 +269,7 @@ bool AsymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
}
const utils::MemBuf *p = buffer;
- shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+ std::shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
if (mdctx == nullptr) {
throw errors::RuntimeException("Digest context allocation failed");
@@ -296,21 +295,21 @@ bool AsymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
// ---------------------------------------------------------
// Symmetric Verifier
// ---------------------------------------------------------
-SymmetricVerifier::SymmetricVerifier(const string &passphrase) {
+SymmetricVerifier::SymmetricVerifier(const std::string &passphrase) {
setPassphrase(passphrase);
}
// Create and set a symmetric key from a passphrase.
-void SymmetricVerifier::setPassphrase(const string &passphrase) {
- key_ = shared_ptr<EVP_PKEY>(
+void SymmetricVerifier::setPassphrase(const std::string &passphrase) {
+ key_ = std::shared_ptr<EVP_PKEY>(
EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr,
(const unsigned char *)passphrase.c_str(),
passphrase.size()),
EVP_PKEY_free);
}
-bool SymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
- const vector<uint8_t> &signature,
+bool SymmetricVerifier::verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
CryptoHashType hash_type) {
CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
@@ -318,9 +317,9 @@ bool SymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
throw errors::RuntimeException("Unknown hash type");
}
- vector<uint8_t> signature_bis(signature.size());
+ std::vector<uint8_t> signature_bis(signature.size());
size_t signature_bis_len;
- shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+ std::shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
if (mdctx == nullptr) {
throw errors::RuntimeException("Digest context allocation failed");
@@ -344,7 +343,7 @@ bool SymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
}
bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
- const vector<uint8_t> &signature,
+ const std::vector<uint8_t> &signature,
CryptoHashType hash_type) {
CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
@@ -353,9 +352,9 @@ bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
}
const utils::MemBuf *p = buffer;
- vector<uint8_t> signature_bis(signature.size());
+ std::vector<uint8_t> signature_bis(signature.size());
size_t signature_bis_len;
- shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+ std::shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
if (mdctx == nullptr) {
throw errors::RuntimeException("Digest context allocation failed");
diff --git a/libtransport/src/config.h.in b/libtransport/src/config.h.in
index 73a326a84..231a370aa 100644
--- a/libtransport/src/config.h.in
+++ b/libtransport/src/config.h.in
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,13 +19,12 @@
#define HICNTRANSPORT_VERSION_MAJOR "@VERSION_MAJOR@"
#define HICNTRANSPORT_VERSION_MINOR "@VERSION_MINOR@"
-#define HICNTRANSPORT_VERSION_REVISION "@VERSION_REVISION@"
+#define HICNTRANSPORT_VERSION_PATCH "@VERSION_PATCH@"
#ifndef ASIO_STANDALONE
#cmakedefine ASIO_STANDALONE
#endif
#define RAAQM_CONFIG_PATH "@raaqm_config_path@"
-#define ENABLE_RELY @ENABLE_RELY@
#cmakedefine __vpp__
diff --git a/libtransport/src/core/CMakeLists.txt b/libtransport/src/core/CMakeLists.txt
index e442bb863..b9b024d60 100644
--- a/libtransport/src/core/CMakeLists.txt
+++ b/libtransport/src/core/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -22,6 +22,9 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/errors.h
${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.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
)
list(APPEND SOURCE_FILES
@@ -36,7 +39,21 @@ list(APPEND SOURCE_FILES
${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
)
+if (NOT ${CMAKE_SYSTEM_NAME} MATCHES Android)
+ if (UNIX AND NOT APPLE)
+ list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.cc
+ )
+
+ list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.h
+ )
+ endif()
+endif()
+
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
diff --git a/libtransport/src/core/content_object.cc b/libtransport/src/core/content_object.cc
index 411494fdf..643e0388e 100644
--- a/libtransport/src/core/content_object.cc
+++ b/libtransport/src/core/content_object.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -35,6 +35,11 @@ namespace core {
ContentObject::ContentObject(const Name &name, Packet::Format format,
std::size_t additional_header_size)
: Packet(format, additional_header_size) {
+ if (TRANSPORT_EXPECT_FALSE(hicn_packet_set_data(format_, packet_start_) <
+ 0)) {
+ throw errors::MalformedPacketException();
+ }
+
if (TRANSPORT_EXPECT_FALSE(
hicn_data_set_name(format, packet_start_, &name.name_) < 0)) {
throw errors::RuntimeException("Error filling the packet name.");
@@ -47,15 +52,20 @@ ContentObject::ContentObject(const Name &name, Packet::Format format,
}
}
-#ifdef __ANDROID__
ContentObject::ContentObject(hicn_format_t format,
std::size_t additional_header_size)
- : ContentObject(Name("0::0|0"), format, additional_header_size) {}
+ : ContentObject(
+#ifdef __ANDROID__
+ Name("0::0|0"),
#else
-ContentObject::ContentObject(hicn_format_t format,
- std::size_t additional_header_size)
- : ContentObject(Packet::base_name, format, additional_header_size) {}
+ Packet::base_name,
#endif
+ format, additional_header_size) {
+ if (TRANSPORT_EXPECT_FALSE(hicn_packet_set_data(format_, packet_start_) <
+ 0)) {
+ throw errors::MalformedPacketException();
+ }
+}
ContentObject::ContentObject(const Name &name, hicn_format_t format,
std::size_t additional_header_size,
@@ -167,6 +177,23 @@ void ContentObject::resetForHash() {
}
}
+bool ContentObject::isLast() const {
+ int is_last = 0;
+ if (hicn_data_is_last(format_, packet_start_, &is_last) < 0) {
+ throw errors::RuntimeException(
+ "Impossible to get last data flag from packet header.");
+ }
+
+ return is_last;
+}
+
+void ContentObject::setLast() {
+ if (hicn_data_set_last(format_, packet_start_) < 0) {
+ throw errors::RuntimeException(
+ "Impossible to set last data flag to packet header.");
+ }
+}
+
} // end namespace core
} // end namespace transport
diff --git a/libtransport/src/core/errors.cc b/libtransport/src/core/errors.cc
index 82647a60b..68fd7bf38 100644
--- a/libtransport/src/core/errors.cc
+++ b/libtransport/src/core/errors.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -39,6 +39,15 @@ std::string core_category_impl::message(int ev) const {
case core_error::configuration_not_applied: {
return "Configuration was not applied due to wrong parameters.";
}
+ case core_error::send_failed: {
+ return "Error sending data to socket.";
+ }
+ case core_error::send_buffer_allocation_failed: {
+ return "Error allocating buffers to send data.";
+ }
+ case core_error::receive_failed: {
+ return "Error receiving data from socket.";
+ }
default: {
return "Unknown core error";
}
diff --git a/libtransport/src/core/errors.h b/libtransport/src/core/errors.h
index a46f1dbcd..4532e6dc5 100644
--- a/libtransport/src/core/errors.h
+++ b/libtransport/src/core/errors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -36,7 +36,10 @@ const std::error_category& core_category();
enum class core_error {
success = 0,
configuration_parse_failed,
- configuration_not_applied
+ configuration_not_applied,
+ send_failed,
+ send_buffer_allocation_failed,
+ receive_failed
};
/**
diff --git a/libtransport/src/core/facade.h b/libtransport/src/core/facade.h
index 199081271..1ad4437e2 100644
--- a/libtransport/src/core/facade.h
+++ b/libtransport/src/core/facade.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/core/global_workers.h b/libtransport/src/core/global_workers.h
new file mode 100644
index 000000000..1ac254188
--- /dev/null
+++ b/libtransport/src/core/global_workers.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/utils/singleton.h>
+#include <hicn/transport/utils/thread_pool.h>
+
+#include <atomic>
+#include <mutex>
+
+namespace transport {
+namespace core {
+
+class GlobalWorkers : public utils::Singleton<GlobalWorkers> {
+ public:
+ friend class utils::Singleton<GlobalWorkers>;
+
+ ::utils::EventThread& getWorker() {
+ return thread_pool_.getWorker(counter_++ % thread_pool_.getNThreads());
+ }
+
+ private:
+ GlobalWorkers() : counter_(0), thread_pool_() {}
+
+ std::atomic_uint16_t counter_;
+ ::utils::ThreadPool thread_pool_;
+};
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/interest.cc b/libtransport/src/core/interest.cc
index 9d868ced0..b7719b3ed 100644
--- a/libtransport/src/core/interest.cc
+++ b/libtransport/src/core/interest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -34,6 +34,10 @@ namespace core {
Interest::Interest(const Name &interest_name, Packet::Format format,
std::size_t additional_header_size)
: Packet(format, additional_header_size) {
+ if (hicn_packet_set_interest(format_, packet_start_) < 0) {
+ throw errors::MalformedPacketException();
+ }
+
if (hicn_interest_set_name(format_, packet_start_,
interest_name.getConstStructReference()) < 0) {
throw errors::MalformedPacketException();
@@ -45,13 +49,18 @@ Interest::Interest(const Name &interest_name, Packet::Format format,
}
}
-#ifdef __ANDROID__
Interest::Interest(hicn_format_t format, std::size_t additional_header_size)
- : Interest(Name("0::0|0"), format, additional_header_size) {}
+ : Interest(
+#ifdef __ANDROID__
+ Name("0::0|0"),
#else
-Interest::Interest(hicn_format_t format, std::size_t additional_header_size)
- : Interest(base_name, format, additional_header_size) {}
+ base_name,
#endif
+ format, additional_header_size) {
+ if (hicn_packet_set_interest(format_, packet_start_) < 0) {
+ throw errors::MalformedPacketException();
+ }
+}
Interest::Interest(MemBuf &&buffer) : Packet(std::move(buffer)) {
if (hicn_interest_get_name(format_, packet_start_,
diff --git a/libtransport/src/core/io_module.cc b/libtransport/src/core/io_module.cc
index a751eabf5..69e4e8bcf 100644
--- a/libtransport/src/core/io_module.cc
+++ b/libtransport/src/core/io_module.cc
@@ -19,8 +19,10 @@
#include <glog/logging.h>
#include <hicn/transport/core/io_module.h>
+#include <iostream>
+
#ifdef ANDROID
-#include <io_modules/udp/hicn_forwarder_module.h>
+#include <io_modules/hicn-light-ng/hicn_forwarder_module.h>
#elif _WIN32
#include <hicn/util/windows/windows_utils.h>
#endif
@@ -55,8 +57,9 @@ IoModule *IoModule::load(const char *module_name) {
if (!creator) {
if ((error = dlerror()) != 0) {
LOG(ERROR) << error;
- return 0;
}
+
+ return 0;
}
// create object and return it
@@ -85,4 +88,4 @@ bool IoModule::unload(IoModule *module) {
}
} // namespace core
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/core/local_connector.cc b/libtransport/src/core/local_connector.cc
index 50dadc677..f27be2e5c 100644
--- a/libtransport/src/core/local_connector.cc
+++ b/libtransport/src/core/local_connector.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -32,13 +32,17 @@ void LocalConnector::send(Packet &packet) {
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, p{packet.shared_from_this()}]() mutable {
- receive_callback_(this, *p, std::make_error_code(std::errc(0)));
+ 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 uint8_t *packet, std::size_t len) {
+void LocalConnector::send(const utils::MemBuf::Ptr &buffer) {
throw errors::NotImplementedException();
}
diff --git a/libtransport/src/core/local_connector.h b/libtransport/src/core/local_connector.h
index 0e2d8f676..eede89e74 100644
--- a/libtransport/src/core/local_connector.h
+++ b/libtransport/src/core/local_connector.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -42,7 +42,7 @@ class LocalConnector : public Connector {
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
void close() override;
diff --git a/libtransport/src/core/manifest.cc b/libtransport/src/core/manifest.cc
index 3f890f3d0..da2689426 100644
--- a/libtransport/src/core/manifest.cc
+++ b/libtransport/src/core/manifest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/core/manifest.h b/libtransport/src/core/manifest.h
index 9b25ebd67..5bdbfc6ff 100644
--- a/libtransport/src/core/manifest.h
+++ b/libtransport/src/core/manifest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#pragma once
#include <core/manifest_format.h>
+#include <glog/logging.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/name.h>
@@ -40,17 +41,20 @@ class Manifest : public Base {
using Encoder = typename FormatTraits::Encoder;
using Decoder = typename FormatTraits::Decoder;
- Manifest(std::size_t signature_size = 0)
- : Base(HF_INET6_TCP_AH, signature_size),
+ 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);
}
- Manifest(const core::Name &name, std::size_t signature_size = 0)
- : Base(name, HF_INET6_TCP_AH, signature_size),
+ 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);
}
@@ -62,6 +66,11 @@ class Manifest : public Base {
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) {
@@ -78,24 +87,27 @@ class Manifest : public Base {
Manifest &decode() {
Manifest::decoder_.decode();
- manifest_type_ = decoder_.getManifestType();
+ manifest_type_ = decoder_.getType();
+ manifest_transport_type_ = decoder_.getTransportType();
hash_algorithm_ = decoder_.getHashAlgorithm();
- is_last_ = decoder_.getIsFinalManifest();
+ is_last_ = decoder_.getIsLast();
return static_cast<ManifestImpl &>(*this).decodeImpl();
}
- static std::size_t getManifestHeaderSize() {
- return Encoder::getManifestHeaderSize();
+ static std::size_t manifestHeaderSize(
+ interface::ProductionProtocolAlgorithms transport_type =
+ interface::ProductionProtocolAlgorithms::UNKNOWN) {
+ return Encoder::manifestHeaderSize(transport_type);
}
- static std::size_t getManifestEntrySize() {
- return Encoder::getManifestEntrySize();
+ static std::size_t manifestEntrySize() {
+ return Encoder::manifestEntrySize();
}
- Manifest &setManifestType(ManifestType type) {
+ Manifest &setType(ManifestType type) {
manifest_type_ = type;
- encoder_.setManifestType(manifest_type_);
+ encoder_.setType(manifest_type_);
return *this;
}
@@ -105,31 +117,46 @@ class Manifest : public Base {
return *this;
}
- auth::CryptoHashType getHashAlgorithm() { return hash_algorithm_; }
+ auth::CryptoHashType getHashAlgorithm() const { return hash_algorithm_; }
- ManifestType getManifestType() const { return manifest_type_; }
+ ManifestType getType() const { return manifest_type_; }
+
+ interface::ProductionProtocolAlgorithms getTransportType() const {
+ return manifest_transport_type_;
+ }
- bool isFinalManifest() const { return is_last_; }
+ bool getIsLast() const { return is_last_; }
Manifest &setVersion(ManifestVersion version) {
encoder_.setVersion(version);
return *this;
}
- Manifest &setFinalBlockNumber(std::uint32_t final_block_number) {
- encoder_.setFinalBlockNumber(final_block_number);
+ Manifest &setParamsBytestream(const ParamsBytestream &params) {
+ manifest_transport_type_ =
+ interface::ProductionProtocolAlgorithms::BYTE_STREAM;
+ encoder_.setParamsBytestream(params);
return *this;
}
- uint32_t getFinalBlockNumber() const {
- return decoder_.getFinalBlockNumber();
+ 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 &setFinalManifest(bool is_final_manifest) {
- encoder_.setIsFinalManifest(is_final_manifest);
- is_last_ = is_final_manifest;
+ Manifest &setIsLast(bool is_last) {
+ encoder_.setIsLast(is_last);
+ is_last_ = is_last;
return *this;
}
@@ -141,6 +168,7 @@ class Manifest : public Base {
protected:
ManifestType manifest_type_;
+ interface::ProductionProtocolAlgorithms manifest_transport_type_;
auth::CryptoHashType hash_algorithm_;
bool is_last_;
diff --git a/libtransport/src/core/manifest_format.h b/libtransport/src/core/manifest_format.h
index 90d221f5e..38f26067e 100644
--- a/libtransport/src/core/manifest_format.h
+++ b/libtransport/src/core/manifest_format.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,6 +17,7 @@
#include <hicn/transport/auth/crypto_hash.h>
#include <hicn/transport/core/name.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
#include <cinttypes>
#include <type_traits>
@@ -26,15 +27,6 @@ namespace transport {
namespace core {
-enum class ManifestFields : uint8_t {
- VERSION,
- HASH_ALGORITHM,
- SEGMENT_CALCULATION_STRATEGY,
- FINAL_MANIFEST,
- NAME_HASH_LIST,
- BASE_NAME
-};
-
enum class ManifestVersion : uint8_t {
VERSION_1 = 1,
};
@@ -45,18 +37,24 @@ enum class ManifestType : uint8_t {
FLIC_MANIFEST = 3,
};
-/**
- * INCREMENTAL: Manifests will be received inline with the data with no specific
- * assumption regarding the manifest capacity. Consumers can send interests
- * using a +1 heuristic.
- *
- * MANIFEST_CAPACITY_BASED: manifests with capacity N have a suffix multiple of
- * N+1: 0, N+1, 2(N+1) etc. Contents have a suffix incremented by 1 except when
- * it conflicts with a manifest: 1, 2, ..., N, N+2, N+3, ..., 2N+1, 2N+3
- */
-enum class NextSegmentCalculationStrategy : uint8_t {
- INCREMENTAL = 1,
- MANIFEST_CAPACITY_BASED = 2,
+struct ParamsRTC {
+ std::uint64_t timestamp;
+ std::uint32_t prod_rate;
+ std::uint32_t prod_seg;
+ std::uint32_t support_fec;
+
+ bool operator==(const ParamsRTC &other) const {
+ return (timestamp == other.timestamp && prod_rate == other.prod_rate &&
+ prod_seg == other.prod_seg && support_fec == other.support_fec);
+ }
+};
+
+struct ParamsBytestream {
+ std::uint32_t final_segment;
+
+ bool operator==(const ParamsBytestream &other) const {
+ return (final_segment == other.final_segment);
+ }
};
template <typename T>
@@ -84,24 +82,14 @@ class ManifestEncoder {
return static_cast<Implementation &>(*this).clearImpl();
}
- ManifestEncoder &setManifestType(ManifestType type) {
- return static_cast<Implementation &>(*this).setManifestTypeImpl(type);
+ ManifestEncoder &setType(ManifestType type) {
+ return static_cast<Implementation &>(*this).setTypeImpl(type);
}
ManifestEncoder &setHashAlgorithm(auth::CryptoHashType hash) {
return static_cast<Implementation &>(*this).setHashAlgorithmImpl(hash);
}
- ManifestEncoder &setFinalChunkNumber(uint32_t final_chunk) {
- return static_cast<Implementation &>(*this).setFinalChunkImpl(final_chunk);
- }
-
- ManifestEncoder &setNextSegmentCalculationStrategy(
- NextSegmentCalculationStrategy strategy) {
- return static_cast<Implementation &>(*this)
- .setNextSegmentCalculationStrategyImpl(strategy);
- }
-
template <
typename T,
typename = std::enable_if_t<std::is_same<
@@ -116,8 +104,8 @@ class ManifestEncoder {
suffix, std::forward<Hash &&>(hash));
}
- ManifestEncoder &setIsFinalManifest(bool is_last) {
- return static_cast<Implementation &>(*this).setIsFinalManifestImpl(is_last);
+ ManifestEncoder &setIsLast(bool is_last) {
+ return static_cast<Implementation &>(*this).setIsLastImpl(is_last);
}
ManifestEncoder &setVersion(ManifestVersion version) {
@@ -133,17 +121,22 @@ class ManifestEncoder {
return static_cast<Implementation &>(*this).updateImpl();
}
- ManifestEncoder &setFinalBlockNumber(std::uint32_t final_block_number) {
- return static_cast<Implementation &>(*this).setFinalBlockNumberImpl(
- final_block_number);
+ ManifestEncoder &setParamsBytestream(const ParamsBytestream &params) {
+ return static_cast<Implementation &>(*this).setParamsBytestreamImpl(params);
+ }
+
+ ManifestEncoder &setParamsRTC(const ParamsRTC &params) {
+ return static_cast<Implementation &>(*this).setParamsRTCImpl(params);
}
- static std::size_t getManifestHeaderSize() {
- return Implementation::getManifestHeaderSizeImpl();
+ static std::size_t manifestHeaderSize(
+ interface::ProductionProtocolAlgorithms transport_type =
+ interface::ProductionProtocolAlgorithms::UNKNOWN) {
+ return Implementation::manifestHeaderSizeImpl(transport_type);
}
- static std::size_t getManifestEntrySize() {
- return Implementation::getManifestEntrySizeImpl();
+ static std::size_t manifestEntrySize() {
+ return Implementation::manifestEntrySizeImpl();
}
};
@@ -158,21 +151,16 @@ class ManifestDecoder {
void decode() { static_cast<Implementation &>(*this).decodeImpl(); }
- ManifestType getManifestType() const {
- return static_cast<const Implementation &>(*this).getManifestTypeImpl();
- }
-
- auth::CryptoHashType getHashAlgorithm() const {
- return static_cast<const Implementation &>(*this).getHashAlgorithmImpl();
+ ManifestType getType() const {
+ return static_cast<const Implementation &>(*this).getTypeImpl();
}
- uint32_t getFinalChunkNumber() const {
- return static_cast<const Implementation &>(*this).getFinalChunkImpl();
+ interface::ProductionProtocolAlgorithms getTransportType() const {
+ return static_cast<const Implementation &>(*this).getTransportTypeImpl();
}
- NextSegmentCalculationStrategy getNextSegmentCalculationStrategy() const {
- return static_cast<const Implementation &>(*this)
- .getNextSegmentCalculationStrategyImpl();
+ auth::CryptoHashType getHashAlgorithm() const {
+ return static_cast<const Implementation &>(*this).getHashAlgorithmImpl();
}
core::Name getBaseName() const {
@@ -183,8 +171,8 @@ class ManifestDecoder {
return static_cast<Implementation &>(*this).getSuffixHashListImpl();
}
- bool getIsFinalManifest() const {
- return static_cast<const Implementation &>(*this).getIsFinalManifestImpl();
+ bool getIsLast() const {
+ return static_cast<const Implementation &>(*this).getIsLastImpl();
}
ManifestVersion getVersion() const {
@@ -196,8 +184,12 @@ class ManifestDecoder {
.estimateSerializedLengthImpl(number_of_entries);
}
- uint32_t getFinalBlockNumber() const {
- return static_cast<const Implementation &>(*this).getFinalBlockNumberImpl();
+ ParamsBytestream getParamsBytestream() const {
+ return static_cast<const Implementation &>(*this).getParamsBytestreamImpl();
+ }
+
+ ParamsRTC getParamsRTC() const {
+ return static_cast<const Implementation &>(*this).getParamsRTCImpl();
}
};
diff --git a/libtransport/src/core/manifest_format_fixed.cc b/libtransport/src/core/manifest_format_fixed.cc
index 11d4a56cb..4c8a5e031 100644
--- a/libtransport/src/core/manifest_format_fixed.cc
+++ b/libtransport/src/core/manifest_format_fixed.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -27,164 +27,288 @@ FixedManifestEncoder::FixedManifestEncoder(Packet &packet,
bool clear)
: packet_(packet),
max_size_(Packet::default_mtu - packet_.headerSize()),
- manifest_header_(reinterpret_cast<ManifestHeader *>(
- packet_.writableData() + packet_.headerSize())),
- manifest_entries_(
- reinterpret_cast<ManifestEntry *>(manifest_header_ + 1)),
- current_entry_(0),
- signature_size_(signature_size) {
+ 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());
+ manifest_entry_meta_ =
+ reinterpret_cast<ManifestEntryMeta *>(manifest_meta_ + 1);
+
if (clear) {
- *manifest_header_ = {0};
+ *manifest_meta_ = {0};
+ *manifest_entry_meta_ = {0};
}
}
FixedManifestEncoder::~FixedManifestEncoder() {}
FixedManifestEncoder &FixedManifestEncoder::encodeImpl() {
- packet_.append(sizeof(ManifestHeader) +
- manifest_header_->number_of_entries * sizeof(ManifestEntry));
+ if (encoded_) {
+ return *this;
+ }
+
+ manifest_meta_->transport_type = static_cast<uint8_t>(transport_type_);
+ manifest_entry_meta_->nb_entries = manifest_entries_.size();
+
+ packet_.append(FixedManifestEncoder::manifestHeaderSizeImpl());
packet_.updateLength();
+
+ switch (transport_type_) {
+ case interface::ProductionProtocolAlgorithms::BYTE_STREAM:
+ packet_.appendPayload(
+ reinterpret_cast<const uint8_t *>(&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);
+ break;
+ default:
+ break;
+ }
+
+ packet_.appendPayload(
+ reinterpret_cast<const uint8_t *>(manifest_entries_.data()),
+ manifest_entries_.size() * FixedManifestEncoder::manifestEntrySizeImpl());
+
+ if (TRANSPORT_EXPECT_FALSE(packet_.payloadSize() <
+ estimateSerializedLengthImpl())) {
+ throw errors::RuntimeException("Error encoding the manifest");
+ }
+
+ encoded_ = true;
return *this;
}
FixedManifestEncoder &FixedManifestEncoder::clearImpl() {
- packet_.trimEnd(sizeof(ManifestHeader) +
- manifest_header_->number_of_entries * sizeof(ManifestEntry));
- current_entry_ = 0;
- *manifest_header_ = {0};
+ if (encoded_) {
+ packet_.trimEnd(FixedManifestEncoder::manifestHeaderSizeImpl() +
+ manifest_entries_.size() *
+ FixedManifestEncoder::manifestEntrySizeImpl());
+ }
+
+ transport_type_ = interface::ProductionProtocolAlgorithms::UNKNOWN;
+ encoded_ = false;
+ params_bytestream_ = {0};
+ params_rtc_ = {0};
+ *manifest_meta_ = {0};
+ *manifest_entry_meta_ = {0};
+ manifest_entries_.clear();
+
return *this;
}
-FixedManifestEncoder &FixedManifestEncoder::setHashAlgorithmImpl(
- auth::CryptoHashType algorithm) {
- manifest_header_->hash_algorithm = static_cast<uint8_t>(algorithm);
+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;
}
-FixedManifestEncoder &FixedManifestEncoder::setManifestTypeImpl(
+FixedManifestEncoder &FixedManifestEncoder::setTypeImpl(
ManifestType manifest_type) {
- manifest_header_->manifest_type = static_cast<uint8_t>(manifest_type);
+ manifest_meta_->type = static_cast<uint8_t>(manifest_type);
+ return *this;
+}
+
+FixedManifestEncoder &FixedManifestEncoder::setHashAlgorithmImpl(
+ auth::CryptoHashType algorithm) {
+ manifest_meta_->hash_algorithm = static_cast<uint8_t>(algorithm);
return *this;
}
-FixedManifestEncoder &
-FixedManifestEncoder::setNextSegmentCalculationStrategyImpl(
- NextSegmentCalculationStrategy strategy) {
- manifest_header_->next_segment_strategy = static_cast<uint8_t>(strategy);
+FixedManifestEncoder &FixedManifestEncoder::setIsLastImpl(bool is_last) {
+ manifest_meta_->is_last = static_cast<uint8_t>(is_last);
return *this;
}
FixedManifestEncoder &FixedManifestEncoder::setBaseNameImpl(
const core::Name &base_name) {
- base_name.copyToDestination(
- reinterpret_cast<uint8_t *>(&manifest_header_->prefix[0]), false);
- manifest_header_->flags.ipv6 =
+ manifest_entry_meta_->is_ipv6 =
base_name.getAddressFamily() == AF_INET6 ? 1_U8 : 0_U8;
+ base_name.copyPrefixToDestination(
+ reinterpret_cast<uint8_t *>(&manifest_entry_meta_->prefix[0]));
return *this;
}
-FixedManifestEncoder &FixedManifestEncoder::addSuffixAndHashImpl(
- uint32_t suffix, const auth::CryptoHash &hash) {
- auto _hash = hash.getDigest();
- addSuffixHashBytes(suffix, _hash.data(), _hash.size());
+FixedManifestEncoder &FixedManifestEncoder::setParamsBytestreamImpl(
+ const ParamsBytestream &params) {
+ transport_type_ = interface::ProductionProtocolAlgorithms::BYTE_STREAM;
+ params_bytestream_ = TransportParamsBytestream{
+ .final_segment = params.final_segment,
+ };
return *this;
}
-void FixedManifestEncoder::addSuffixHashBytes(uint32_t suffix,
- const uint8_t *hash,
- std::size_t length) {
- manifest_entries_[current_entry_].suffix = htonl(suffix);
- // std::copy(hash, hash + length,
- // manifest_entries_[current_entry_].hash);
- std::memcpy(
- reinterpret_cast<uint8_t *>(manifest_entries_[current_entry_].hash), hash,
- length);
+FixedManifestEncoder &FixedManifestEncoder::setParamsRTCImpl(
+ const ParamsRTC &params) {
+ transport_type_ = interface::ProductionProtocolAlgorithms::RTC_PROD;
+ params_rtc_ = TransportParamsRTC{
+ .timestamp = params.timestamp,
+ .prod_rate = params.prod_rate,
+ .prod_seg = params.prod_seg,
+ .support_fec = params.support_fec,
+ };
+ return *this;
+}
- manifest_header_->number_of_entries++;
- current_entry_++;
+FixedManifestEncoder &FixedManifestEncoder::addSuffixAndHashImpl(
+ uint32_t suffix, const auth::CryptoHash &hash) {
+ std::vector<uint8_t> _hash = hash.getDigest();
+
+ manifest_entries_.push_back(ManifestEntry{
+ .suffix = htonl(suffix),
+ .hash = {0},
+ });
+
+ std::memcpy(reinterpret_cast<uint8_t *>(manifest_entries_.back().hash),
+ _hash.data(), _hash.size());
if (TRANSPORT_EXPECT_FALSE(estimateSerializedLengthImpl() > max_size_)) {
throw errors::RuntimeException("Manifest size exceeded the packet MTU!");
}
-}
-
-FixedManifestEncoder &FixedManifestEncoder::setIsFinalManifestImpl(
- bool is_last) {
- manifest_header_->flags.is_last = static_cast<uint8_t>(is_last);
- return *this;
-}
-FixedManifestEncoder &FixedManifestEncoder::setVersionImpl(
- ManifestVersion version) {
- manifest_header_->version = static_cast<uint8_t>(version);
return *this;
}
std::size_t FixedManifestEncoder::estimateSerializedLengthImpl(
std::size_t additional_entries) {
- return sizeof(ManifestHeader) +
- (manifest_header_->number_of_entries + additional_entries) *
- sizeof(ManifestEntry);
+ return FixedManifestEncoder::manifestHeaderSizeImpl(transport_type_) +
+ (manifest_entries_.size() + additional_entries) *
+ FixedManifestEncoder::manifestEntrySizeImpl();
}
-FixedManifestEncoder &FixedManifestEncoder::updateImpl() {
- max_size_ = Packet::default_mtu - packet_.headerSize() - signature_size_;
- return *this;
-}
-
-FixedManifestEncoder &FixedManifestEncoder::setFinalBlockNumberImpl(
- std::uint32_t final_block_number) {
- manifest_header_->final_block_number = htonl(final_block_number);
- 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;
+ }
-std::size_t FixedManifestEncoder::getManifestHeaderSizeImpl() {
- return sizeof(ManifestHeader);
+ return MANIFEST_META_SIZE + MANIFEST_ENTRY_META_SIZE + params_size;
}
-std::size_t FixedManifestEncoder::getManifestEntrySizeImpl() {
- return sizeof(ManifestEntry);
+std::size_t FixedManifestEncoder::manifestEntrySizeImpl() {
+ return MANIFEST_ENTRY_SIZE;
}
FixedManifestDecoder::FixedManifestDecoder(Packet &packet)
- : packet_(packet),
- manifest_header_(reinterpret_cast<ManifestHeader *>(
- packet_.getPayload()->writableData())),
- manifest_entries_(reinterpret_cast<ManifestEntry *>(
- packet_.getPayload()->writableData() + sizeof(ManifestHeader))) {}
+ : packet_(packet), decoded_(false) {
+ manifest_meta_ =
+ reinterpret_cast<ManifestMeta *>(packet_.getPayload()->writableData());
+ manifest_entry_meta_ =
+ reinterpret_cast<ManifestEntryMeta *>(manifest_meta_ + 1);
+ transport_type_ = getTransportTypeImpl();
+
+ switch (transport_type_) {
+ case interface::ProductionProtocolAlgorithms::BYTE_STREAM:
+ params_bytestream_ = reinterpret_cast<TransportParamsBytestream *>(
+ manifest_entry_meta_ + 1);
+ manifest_entries_ =
+ reinterpret_cast<ManifestEntry *>(params_bytestream_ + 1);
+ break;
+ case interface::ProductionProtocolAlgorithms::RTC_PROD:
+ params_rtc_ =
+ reinterpret_cast<TransportParamsRTC *>(manifest_entry_meta_ + 1);
+ manifest_entries_ = reinterpret_cast<ManifestEntry *>(params_rtc_ + 1);
+ break;
+ default:
+ manifest_entries_ =
+ 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 < sizeof(ManifestHeader) ||
+ if (packet_size <
+ FixedManifestEncoder::manifestHeaderSizeImpl(transport_type_) ||
packet_size < estimateSerializedLengthImpl()) {
throw errors::RuntimeException(
"The packet does not match expected manifest size.");
}
+
+ decoded_ = true;
+}
+
+FixedManifestDecoder &FixedManifestDecoder::clearImpl() {
+ decoded_ = false;
+ return *this;
}
-FixedManifestDecoder &FixedManifestDecoder::clearImpl() { return *this; }
+ManifestType FixedManifestDecoder::getTypeImpl() const {
+ return static_cast<ManifestType>(manifest_meta_->type);
+}
-ManifestType FixedManifestDecoder::getManifestTypeImpl() const {
- return static_cast<ManifestType>(manifest_header_->manifest_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);
}
auth::CryptoHashType FixedManifestDecoder::getHashAlgorithmImpl() const {
- return static_cast<auth::CryptoHashType>(manifest_header_->hash_algorithm);
+ return static_cast<auth::CryptoHashType>(manifest_meta_->hash_algorithm);
}
-NextSegmentCalculationStrategy
-FixedManifestDecoder::getNextSegmentCalculationStrategyImpl() const {
- return static_cast<NextSegmentCalculationStrategy>(
- manifest_header_->next_segment_strategy);
+bool FixedManifestDecoder::getIsLastImpl() const {
+ return static_cast<bool>(manifest_meta_->is_last);
+}
+
+core::Name FixedManifestDecoder::getBaseNameImpl() const {
+ if (static_cast<bool>(manifest_entry_meta_->is_ipv6)) {
+ return core::Name(
+ AF_INET6, reinterpret_cast<uint8_t *>(&manifest_entry_meta_->prefix));
+ } else {
+ return core::Name(
+ AF_INET, reinterpret_cast<uint8_t *>(&manifest_entry_meta_->prefix));
+ }
+}
+
+ParamsBytestream FixedManifestDecoder::getParamsBytestreamImpl() const {
+ return ParamsBytestream{
+ .final_segment = params_bytestream_->final_segment,
+ };
+}
+
+ParamsRTC FixedManifestDecoder::getParamsRTCImpl() const {
+ return ParamsRTC{
+ .timestamp = params_rtc_->timestamp,
+ .prod_rate = params_rtc_->prod_rate,
+ .prod_seg = params_rtc_->prod_seg,
+ .support_fec = params_rtc_->support_fec,
+ };
}
typename Fixed::SuffixList FixedManifestDecoder::getSuffixHashListImpl() {
typename Fixed::SuffixList hash_list;
- for (int i = 0; i < manifest_header_->number_of_entries; i++) {
+ 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 *>(
@@ -194,33 +318,11 @@ typename Fixed::SuffixList FixedManifestDecoder::getSuffixHashListImpl() {
return hash_list;
}
-core::Name FixedManifestDecoder::getBaseNameImpl() const {
- if (static_cast<bool>(manifest_header_->flags.ipv6)) {
- return core::Name(AF_INET6,
- reinterpret_cast<uint8_t *>(&manifest_header_->prefix));
- } else {
- return core::Name(AF_INET,
- reinterpret_cast<uint8_t *>(&manifest_header_->prefix));
- }
-}
-
-bool FixedManifestDecoder::getIsFinalManifestImpl() const {
- return static_cast<bool>(manifest_header_->flags.is_last);
-}
-
-ManifestVersion FixedManifestDecoder::getVersionImpl() const {
- return static_cast<ManifestVersion>(manifest_header_->version);
-}
-
std::size_t FixedManifestDecoder::estimateSerializedLengthImpl(
std::size_t additional_entries) const {
- return sizeof(ManifestHeader) +
- (additional_entries + manifest_header_->number_of_entries) *
- sizeof(ManifestEntry);
-}
-
-uint32_t FixedManifestDecoder::getFinalBlockNumberImpl() const {
- return ntohl(manifest_header_->final_block_number);
+ return FixedManifestEncoder::manifestHeaderSizeImpl(transport_type_) +
+ (manifest_entry_meta_->nb_entries + additional_entries) *
+ FixedManifestEncoder::manifestEntrySizeImpl();
}
} // end namespace core
diff --git a/libtransport/src/core/manifest_format_fixed.h b/libtransport/src/core/manifest_format_fixed.h
index 56ad4ef6d..ade4bf02c 100644
--- a/libtransport/src/core/manifest_format_fixed.h
+++ b/libtransport/src/core/manifest_format_fixed.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,26 +24,74 @@ namespace transport {
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| MType |HashAlg|NextStr| Flags |NumberOfEntries|
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | Final Block Number |
-// +---------------------------------------------------------------|
-// | |
-// + +
-// | |
-// + Prefix +
-// | |
-// + +
-// | |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | Suffix |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | Hash Value |
-// | |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// Manifest Metadata:
+// 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 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+// Manifest Entry Metadata:
+// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Nb entries |I| Reserved |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |
+// + +
+// | |
+// + Prefix +
+// | |
+// + +
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+// Manifest Transport Parameters - Bytestream:
+// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Final Segment |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+// Manifest Transport Parameters - RTC:
+// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |
+// + Timestamp +
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Production Rate |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Current Segment |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |F| |
+// + Reserved for future parameters +
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+// Manifest Entry:
+// 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
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Packet Suffix |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |
+// + +
+// | |
+// + +
+// | |
+// + +
+// | |
+// + Packet Digest +
+// | |
+// + +
+// | |
+// + +
+// | |
+// + +
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class FixedManifestEncoder;
class FixedManifestDecoder;
@@ -58,28 +106,47 @@ struct Fixed {
using SuffixList = std::list<std::pair<uint32_t, uint8_t *>>;
};
-struct Flags {
- std::uint8_t ipv6 : 1;
- std::uint8_t is_last : 1;
- std::uint8_t unused : 6;
+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 hash_algorithm;
+ std::uint8_t is_last;
};
+static_assert(sizeof(ManifestMeta) == MANIFEST_META_SIZE);
-struct ManifestEntry {
- std::uint32_t suffix;
- std::uint32_t hash[8];
+const size_t MANIFEST_ENTRY_META_SIZE = 20;
+struct __attribute__((__packed__)) ManifestEntryMeta {
+ std::uint8_t nb_entries;
+ std::uint8_t is_ipv6;
+ std::uint16_t unused;
+ std::uint32_t prefix[4];
};
+static_assert(sizeof(ManifestEntryMeta) == MANIFEST_ENTRY_META_SIZE);
-struct ManifestHeader {
- std::uint8_t version : 4;
- std::uint8_t manifest_type : 4;
- std::uint8_t hash_algorithm : 4;
- std::uint8_t next_segment_strategy : 4;
- Flags flags;
- std::uint8_t number_of_entries;
- std::uint32_t final_block_number;
- std::uint32_t prefix[4];
- ManifestEntry entries[0];
+const size_t MANIFEST_PARAMS_BYTESTREAM_SIZE = 4;
+struct __attribute__((__packed__)) TransportParamsBytestream {
+ std::uint32_t final_segment;
+};
+static_assert(sizeof(TransportParamsBytestream) ==
+ MANIFEST_PARAMS_BYTESTREAM_SIZE);
+
+const size_t MANIFEST_PARAMS_RTC_SIZE = 20;
+struct __attribute__((__packed__)) TransportParamsRTC {
+ std::uint64_t timestamp;
+ std::uint32_t prod_rate;
+ std::uint32_t prod_seg;
+ std::uint32_t support_fec;
+};
+static_assert(sizeof(TransportParamsRTC) == MANIFEST_PARAMS_RTC_SIZE);
+
+const size_t MANIFEST_ENTRY_SIZE = 36;
+struct __attribute__((__packed__)) ManifestEntry {
+ std::uint32_t suffix;
+ std::uint32_t hash[8];
};
+static_assert(sizeof(ManifestEntry) == MANIFEST_ENTRY_SIZE);
static const constexpr std::uint8_t manifest_version = 1;
@@ -91,46 +158,48 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
~FixedManifestEncoder();
FixedManifestEncoder &encodeImpl();
-
FixedManifestEncoder &clearImpl();
+ FixedManifestEncoder &updateImpl();
- FixedManifestEncoder &setManifestTypeImpl(ManifestType manifest_type);
-
+ // ManifestMeta
+ FixedManifestEncoder &setVersionImpl(ManifestVersion version);
+ FixedManifestEncoder &setTypeImpl(ManifestType manifest_type);
FixedManifestEncoder &setHashAlgorithmImpl(Fixed::HashType algorithm);
+ FixedManifestEncoder &setIsLastImpl(bool is_last);
- FixedManifestEncoder &setNextSegmentCalculationStrategyImpl(
- NextSegmentCalculationStrategy strategy);
-
+ // ManifestEntryMeta
FixedManifestEncoder &setBaseNameImpl(const core::Name &base_name);
+ // TransportParams
+ FixedManifestEncoder &setParamsBytestreamImpl(const ParamsBytestream &params);
+ FixedManifestEncoder &setParamsRTCImpl(const ParamsRTC &params);
+
+ // ManifestEntry
FixedManifestEncoder &addSuffixAndHashImpl(uint32_t suffix,
const Fixed::Hash &hash);
- FixedManifestEncoder &setIsFinalManifestImpl(bool is_last);
-
- FixedManifestEncoder &setVersionImpl(ManifestVersion version);
-
std::size_t estimateSerializedLengthImpl(std::size_t additional_entries = 0);
- FixedManifestEncoder &updateImpl();
-
- FixedManifestEncoder &setFinalBlockNumberImpl(
- std::uint32_t final_block_number);
-
- static std::size_t getManifestHeaderSizeImpl();
-
- static std::size_t getManifestEntrySizeImpl();
+ static std::size_t manifestHeaderSizeImpl(
+ interface::ProductionProtocolAlgorithms transport_type =
+ interface::ProductionProtocolAlgorithms::UNKNOWN);
+ static std::size_t manifestEntrySizeImpl();
private:
- void addSuffixHashBytes(uint32_t suffix, const uint8_t *hash,
- std::size_t length);
-
Packet &packet_;
std::size_t max_size_;
- ManifestHeader *manifest_header_;
- ManifestEntry *manifest_entries_;
- std::size_t current_entry_;
std::size_t signature_size_;
+ interface::ProductionProtocolAlgorithms transport_type_;
+ bool encoded_;
+
+ // Manifest Header
+ ManifestMeta *manifest_meta_;
+ ManifestEntryMeta *manifest_entry_meta_;
+ TransportParamsBytestream params_bytestream_;
+ TransportParamsRTC params_rtc_;
+
+ // Manifest Entries
+ std::vector<ManifestEntry> manifest_entries_;
};
class FixedManifestDecoder : public ManifestDecoder<FixedManifestDecoder> {
@@ -140,31 +209,40 @@ class FixedManifestDecoder : public ManifestDecoder<FixedManifestDecoder> {
~FixedManifestDecoder();
void decodeImpl();
-
FixedManifestDecoder &clearImpl();
- ManifestType getManifestTypeImpl() const;
-
+ // ManifestMeta
+ ManifestVersion getVersionImpl() const;
+ ManifestType getTypeImpl() const;
+ interface::ProductionProtocolAlgorithms getTransportTypeImpl() const;
Fixed::HashType getHashAlgorithmImpl() const;
+ bool getIsLastImpl() const;
- NextSegmentCalculationStrategy getNextSegmentCalculationStrategyImpl() const;
-
- typename Fixed::SuffixList getSuffixHashListImpl();
-
+ // ManifestEntryMeta
core::Name getBaseNameImpl() const;
- bool getIsFinalManifestImpl() const;
+ // TransportParams
+ ParamsBytestream getParamsBytestreamImpl() const;
+ ParamsRTC getParamsRTCImpl() const;
+
+ // ManifestEntry
+ typename Fixed::SuffixList getSuffixHashListImpl();
std::size_t estimateSerializedLengthImpl(
std::size_t additional_entries = 0) const;
- ManifestVersion getVersionImpl() const;
-
- uint32_t getFinalBlockNumberImpl() const;
-
private:
Packet &packet_;
- ManifestHeader *manifest_header_;
+ interface::ProductionProtocolAlgorithms transport_type_;
+ bool decoded_;
+
+ // Manifest Header
+ ManifestMeta *manifest_meta_;
+ ManifestEntryMeta *manifest_entry_meta_;
+ TransportParamsBytestream *params_bytestream_;
+ TransportParamsRTC *params_rtc_;
+
+ // Manifest Entries
ManifestEntry *manifest_entries_;
};
diff --git a/libtransport/src/core/manifest_inline.h b/libtransport/src/core/manifest_inline.h
index a487ccfe3..ca48a4a79 100644
--- a/libtransport/src/core/manifest_inline.h
+++ b/libtransport/src/core/manifest_inline.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -40,25 +40,26 @@ class ManifestInline
public:
ManifestInline() : ManifestBase() {}
- ManifestInline(const core::Name &name, std::size_t signature_size = 0)
- : ManifestBase(name, signature_size) {}
+ 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(
- const core::Name &manifest_name, ManifestVersion version,
- ManifestType type, HashType algorithm, bool is_last,
- const Name &base_name, NextSegmentCalculationStrategy strategy,
- std::size_t signature_size) {
- auto manifest = new ManifestInline(manifest_name, signature_size);
+ 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->setManifestType(type);
- manifest->setHashAlgorithm(algorithm);
- manifest->setFinalManifest(is_last);
+ manifest->setType(type);
+ manifest->setHashAlgorithm(hash_algo);
+ manifest->setIsLast(is_last);
manifest->setBaseName(base_name);
- manifest->setNextSegmentCalculationStrategy(strategy);
-
return manifest;
}
@@ -69,8 +70,6 @@ class ManifestInline
ManifestInline &decodeImpl() {
base_name_ = ManifestBase::decoder_.getBaseName();
- next_segment_strategy_ =
- ManifestBase::decoder_.getNextSegmentCalculationStrategy();
suffix_hash_map_ = ManifestBase::decoder_.getSuffixHashList();
return *this;
@@ -96,18 +95,6 @@ class ManifestInline
// Call this function only after the decode function!
const SuffixList &getSuffixList() { return suffix_hash_map_; }
- ManifestInline &setNextSegmentCalculationStrategy(
- NextSegmentCalculationStrategy strategy) {
- next_segment_strategy_ = strategy;
- ManifestBase::encoder_.setNextSegmentCalculationStrategy(
- next_segment_strategy_);
- return *this;
- }
-
- NextSegmentCalculationStrategy getNextSegmentCalculationStrategy() {
- return next_segment_strategy_;
- }
-
// Convert several manifests into a single map from suffixes to packet hashes.
// All manifests must have been decoded beforehand.
static std::unordered_map<Suffix, Hash> getSuffixMap(
@@ -134,7 +121,6 @@ class ManifestInline
private:
core::Name base_name_;
- NextSegmentCalculationStrategy next_segment_strategy_;
SuffixList suffix_hash_map_;
};
diff --git a/libtransport/src/core/memif_connector.cc b/libtransport/src/core/memif_connector.cc
new file mode 100644
index 000000000..fb38a6e23
--- /dev/null
+++ b/libtransport/src/core/memif_connector.cc
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/errors.h>
+#include <core/memif_connector.h>
+#include <glog/logging.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <sys/epoll.h>
+
+#include <cstdlib>
+
+/* sstrncpy */
+#include <hicn/util/sstrncpy.h>
+
+#define CANCEL_TIMER 1
+
+namespace transport {
+
+namespace core {
+
+MemifConnector::MemifConnector(PacketReceivedCallback &&receive_callback,
+ PacketSentCallback &&packet_sent,
+ OnCloseCallback &&close_callback,
+ OnReconnectCallback &&on_reconnect,
+ asio::io_service &io_service,
+ std::string app_name)
+ : Connector(std::move(receive_callback), std::move(packet_sent),
+ std::move(close_callback), std::move(on_reconnect)),
+ event_reactor_(),
+ memif_worker_(std::bind(&MemifConnector::threadMain, this)),
+ timer_set_(false),
+ send_timer_(event_reactor_),
+ disconnect_timer_(event_reactor_),
+ io_service_(io_service),
+ work_(asio::make_work_guard(io_service_)),
+ memif_connection_({0}),
+ tx_buf_counter_(0),
+ is_reconnection_(false),
+ data_available_(false),
+ app_name_(app_name),
+ socket_filename_(""),
+ buffer_size_(kbuf_size),
+ log2_ring_size_(klog2_ring_size),
+ max_memif_bufs_(1 << klog2_ring_size) {}
+
+MemifConnector::~MemifConnector() { close(); }
+
+void MemifConnector::connect(uint32_t memif_id, long memif_mode,
+ const std::string &socket_filename,
+ std::size_t buffer_size,
+ std::size_t log2_ring_size) {
+ state_ = State::CONNECTING;
+
+ memif_id_ = memif_id;
+ socket_filename_ = socket_filename;
+ buffer_size_ = buffer_size;
+ log2_ring_size_ = log2_ring_size;
+ max_memif_bufs_ = 1 << log2_ring_size;
+ createMemif(memif_id, memif_mode);
+}
+
+int MemifConnector::createMemif(uint32_t index, uint8_t is_master) {
+ int err = MEMIF_ERR_SUCCESS;
+
+ memif_socket_args_t socket_args;
+ memif_conn_args_t args;
+ memset(&socket_args, 0, sizeof(memif_socket_args_t));
+ memset(&args, 0, sizeof(memif_conn_args_t));
+
+ // Setup memif socket first
+
+ int rc = strcpy_s(socket_args.path, sizeof(socket_args.path) - 1,
+ socket_filename_.c_str());
+ if (rc != EOK) {
+ std::string error = "Provided socket path is larger than " +
+ std::to_string(sizeof(socket_args.path)) + " bytes.";
+ throw errors::RuntimeException(error);
+ }
+
+ rc = strcpy_s(socket_args.app_name, sizeof(socket_args.app_name) - 1,
+ app_name_.c_str());
+ if (rc != EOK) {
+ std::string error = "Provided app_name is larger than " +
+ std::to_string(sizeof(socket_args.app_name)) +
+ " bytes.";
+ throw errors::RuntimeException(error);
+ }
+
+ socket_args.on_control_fd_update = controlFdUpdate;
+ socket_args.alloc = nullptr;
+ socket_args.realloc = nullptr;
+ socket_args.free = nullptr;
+
+ err = memif_create_socket(&args.socket, &socket_args, this);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ throw errors::RuntimeException(memif_strerror(err));
+ }
+
+ // Setup memif connection using provided memif_socket_handle_t
+ args.is_master = is_master;
+ args.log2_ring_size = log2_ring_size_;
+ args.buffer_size = buffer_size_;
+ args.num_s2m_rings = 1;
+ args.num_m2s_rings = 1;
+ strcpy_s((char *)args.interface_name, sizeof(args.interface_name), IF_NAME);
+ args.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
+ args.interface_id = index;
+ err = memif_create(&memif_connection_.conn, &args, onConnect, onDisconnect,
+ onInterrupt, this);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ throw errors::RuntimeException(memif_strerror(err));
+ }
+
+ memif_connection_.index = (uint16_t)index;
+ memif_connection_.tx_qid = 0;
+ /* alloc memif buffers */
+ memif_connection_.rx_buf_num = 0;
+ memif_connection_.rx_bufs = static_cast<memif_buffer_t *>(
+ malloc(sizeof(memif_buffer_t) * max_memif_bufs_));
+ memif_connection_.tx_buf_num = 0;
+ memif_connection_.tx_bufs = static_cast<memif_buffer_t *>(
+ malloc(sizeof(memif_buffer_t) * max_memif_bufs_));
+
+ return 0;
+}
+
+int MemifConnector::deleteMemif() {
+ if (memif_connection_.rx_bufs) {
+ free(memif_connection_.rx_bufs);
+ }
+
+ memif_connection_.rx_bufs = nullptr;
+ memif_connection_.rx_buf_num = 0;
+
+ if (memif_connection_.tx_bufs) {
+ free(memif_connection_.tx_bufs);
+ }
+
+ memif_connection_.tx_bufs = nullptr;
+ memif_connection_.tx_buf_num = 0;
+
+ int err;
+ /* disconenct then delete memif connection */
+ err = memif_delete(&memif_connection_.conn);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ LOG(ERROR) << "memif_delete: " << memif_strerror(err);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(memif_connection_.conn != nullptr)) {
+ LOG(ERROR) << "memif delete fail";
+ }
+
+ state_ = State::CLOSED;
+
+ return 0;
+}
+
+int MemifConnector::controlFdUpdate(memif_fd_event_t fde, void *private_ctx) {
+ auto self = reinterpret_cast<MemifConnector *>(private_ctx);
+ uint32_t evt = 0;
+
+ /* convert memif event definitions to epoll events */
+ auto events = fde.type;
+ auto fd = fde.fd;
+
+ if (events & MEMIF_FD_EVENT_ERROR) {
+ LOG(ERROR) << "memif fd event: Error";
+ return -1;
+ }
+
+ if (events & MEMIF_FD_EVENT_DEL) {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "memif fd event: DEL fd " << fd;
+ return self->event_reactor_.delFileDescriptor(fd);
+ }
+
+ if (events & MEMIF_FD_EVENT_MOD) {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "memif fd event: MOD fd " << fd;
+ return self->event_reactor_.modFileDescriptor(fd, evt);
+ }
+
+ if (events & MEMIF_FD_EVENT_READ) {
+ evt |= EPOLLIN;
+ }
+
+ if (events & MEMIF_FD_EVENT_WRITE) {
+ evt |= EPOLLOUT;
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "memif fd event: ADD fd " << fd;
+ return self->event_reactor_.addFileDescriptor(
+ fd, evt, [fde](const utils::Event &evt) -> int {
+ int event = 0;
+ int memif_err = 0;
+
+ if (evt.events & EPOLLIN) {
+ event |= MEMIF_FD_EVENT_READ;
+ }
+
+ if (evt.events & EPOLLOUT) {
+ event |= MEMIF_FD_EVENT_WRITE;
+ }
+
+ if (evt.events & EPOLLERR) {
+ event |= MEMIF_FD_EVENT_ERROR;
+ }
+
+ memif_err = memif_control_fd_handler(fde.private_ctx,
+ memif_fd_event_type_t(event));
+
+ if (TRANSPORT_EXPECT_FALSE(memif_err != MEMIF_ERR_SUCCESS)) {
+ LOG(ERROR) << "memif_control_fd_handler: "
+ << memif_strerror(memif_err);
+ }
+
+ return 0;
+ });
+}
+
+uint16_t MemifConnector::bufferAlloc(long n, uint16_t qid,
+ std::error_code &ec) {
+ int err;
+ uint16_t r = 0;
+ /* set data pointer to shared memory and set buffer_len to shared mmeory
+ * buffer len */
+ err = memif_buffer_alloc(memif_connection_.conn, qid,
+ memif_connection_.tx_bufs, n, &r, buffer_size_);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ ec = make_error_code(core_error::send_buffer_allocation_failed);
+ }
+
+ memif_connection_.tx_buf_num += r;
+ return r;
+}
+
+uint16_t MemifConnector::txBurst(uint16_t qid, std::error_code &ec) {
+ int err = MEMIF_ERR_SUCCESS;
+ ec = make_error_code(core_error::success);
+ uint16_t tx = 0;
+
+ /* inform peer memif interface about data in shared memory buffers */
+ /* mark memif buffers as free */
+ err = memif_tx_burst(memif_connection_.conn, qid, memif_connection_.tx_bufs,
+ memif_connection_.tx_buf_num, &tx);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ ec = make_error_code(core_error::send_failed);
+ }
+
+ memif_connection_.tx_buf_num -= tx;
+ return tx;
+}
+
+void MemifConnector::scheduleSend(std::uint64_t delay) {
+ if (!timer_set_) {
+ timer_set_ = true;
+ send_timer_.expiresFromNow(std::chrono::microseconds(delay));
+ send_timer_.asyncWait(
+ std::bind(&MemifConnector::sendCallback, this, std::placeholders::_1));
+ }
+}
+
+void MemifConnector::sendCallback(const std::error_code &ec) {
+ timer_set_ = false;
+
+ if (TRANSPORT_EXPECT_TRUE(!ec && state_ == State::CONNECTED)) {
+ doSend();
+ }
+}
+
+/* informs user about connected status. private_ctx is used by user to identify
+ connection (multiple connections WIP) */
+int MemifConnector::onConnect(memif_conn_handle_t conn, void *private_ctx) {
+ auto self = reinterpret_cast<MemifConnector *>(private_ctx);
+ self->state_ = State::CONNECTED;
+ memif_refill_queue(conn, 0, -1, 0);
+
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Memif " << self->app_name_ << " connected";
+
+ // We are connected. Notify higher layers.
+ self->io_service_.post([self]() {
+ self->on_reconnect_callback_(self, make_error_code(core_error::success));
+ });
+
+ self->doSend();
+
+ return 0;
+}
+
+/* informs user about disconnected status. private_ctx is used by user to
+ identify connection (multiple connections WIP) */
+int MemifConnector::onDisconnect(memif_conn_handle_t conn, void *private_ctx) {
+ MemifConnector *connector = (MemifConnector *)private_ctx;
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Memif " << connector->app_name_ << " disconnected";
+ return 0;
+}
+
+void MemifConnector::threadMain() { event_reactor_.runEventLoop(200); }
+
+int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
+ uint16_t qid) {
+ MemifConnector *connector = (MemifConnector *)private_ctx;
+
+ Details &c = connector->memif_connection_;
+ std::weak_ptr<MemifConnector> self = connector->shared_from_this();
+ std::vector<::utils::MemBuf::Ptr> v;
+ std::error_code ec = make_error_code(core_error::success);
+
+ int err = MEMIF_ERR_SUCCESS, ret_val;
+ uint16_t rx = 0;
+
+ do {
+ err = memif_rx_burst(conn, qid, c.rx_bufs, max_burst, &rx);
+ ret_val = err;
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS &&
+ err != MEMIF_ERR_NOBUF)) {
+ ec = make_error_code(core_error::receive_failed);
+ LOG(ERROR) << "memif_rx_burst: " << memif_strerror(err);
+ goto error;
+ }
+
+ c.rx_buf_num += rx;
+
+ if (TRANSPORT_EXPECT_FALSE(connector->io_service_.stopped())) {
+ LOG(ERROR) << "socket stopped: ignoring " << rx << " packets";
+ goto error;
+ }
+
+ std::size_t packet_length;
+ v.reserve(rx);
+ for (int i = 0; i < rx; i++) {
+ auto buffer = connector->getRawBuffer();
+ packet_length = (c.rx_bufs + i)->len;
+ std::memcpy(buffer.first, (c.rx_bufs + i)->data, packet_length);
+ auto packet = connector->getPacketFromBuffer(buffer.first, packet_length);
+ v.emplace_back(std::move(packet));
+ }
+
+ /* mark memif buffers and shared memory buffers as free */
+ /* free processed buffers */
+
+ err = memif_refill_queue(conn, qid, rx, 0);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
+ }
+
+ c.rx_buf_num -= rx;
+
+ } while (ret_val == MEMIF_ERR_NOBUF);
+
+ connector->io_service_.post([self, buffers = std::move(v)]() {
+ if (auto c = self.lock()) {
+ c->receive_callback_(c.get(), buffers,
+ std::make_error_code(std::errc(0)));
+ }
+ });
+
+ return 0;
+
+error:
+ err = memif_refill_queue(c.conn, qid, rx, 0);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
+ }
+ c.rx_buf_num -= rx;
+
+ connector->io_service_.post([self, ec]() {
+ if (auto c = self.lock()) {
+ c->receive_callback_(c.get(), {}, ec);
+ }
+ });
+
+ return 0;
+}
+
+void MemifConnector::close() {
+ if (state_ != State::CLOSED) {
+ disconnect_timer_.expiresFromNow(std::chrono::microseconds(50));
+ disconnect_timer_.asyncWait([this](const std::error_code &ec) {
+ deleteMemif();
+ event_reactor_.stop();
+ });
+ }
+
+ if (memif_worker_.joinable()) {
+ memif_worker_.join();
+ }
+}
+
+void MemifConnector::send(Packet &packet) { send(packet.shared_from_this()); }
+
+void MemifConnector::send(const utils::MemBuf::Ptr &buffer) {
+ {
+ utils::SpinLock::Acquire locked(write_msgs_lock_);
+ output_buffer_.push_back(buffer);
+ }
+#if CANCEL_TIMER
+ scheduleSend(50);
+#endif
+}
+
+int MemifConnector::doSend() {
+ std::size_t max = 0;
+ std::size_t size = 0;
+ std::error_code ec = make_error_code(core_error::success);
+ int ret = 0;
+ uint64_t delay = 50; // microseconds
+
+ utils::SpinLock::Acquire locked(write_msgs_lock_);
+
+ // Check if there are pending buffers to send
+ if (memif_connection_.tx_buf_num > 0) {
+ ret = txBurst(memif_connection_.tx_qid, ec);
+ if (TRANSPORT_EXPECT_FALSE(ec.operator bool())) {
+ delay = 200;
+ goto done;
+ }
+ }
+
+ // Continue trying to send buffers in output_buffer_
+ size = output_buffer_.size();
+ max = size < max_burst ? size : max_burst;
+
+ ret = bufferAlloc(max, memif_connection_.tx_qid, ec);
+ if (TRANSPORT_EXPECT_FALSE(ec.operator bool() && ret == 0)) {
+ delay = 200;
+ goto done;
+ }
+
+ // Fill allocated buffers and remove them from output_buffer_
+ for (uint16_t i = 0; i < ret; i++) {
+ auto packet = output_buffer_.front().get();
+ const utils::MemBuf *current = packet;
+ std::size_t offset = 0;
+ uint8_t *shared_buffer =
+ reinterpret_cast<uint8_t *>(memif_connection_.tx_bufs[i].data);
+ do {
+ std::memcpy(shared_buffer + offset, current->data(), current->length());
+ offset += current->length();
+ current = current->next();
+ } while (current != packet);
+
+ memif_connection_.tx_bufs[i].len = uint32_t(offset);
+ output_buffer_.pop_front();
+ }
+
+ // Try to send them
+ ret = txBurst(memif_connection_.tx_qid, ec);
+ if (TRANSPORT_EXPECT_FALSE(ec.operator bool())) {
+ LOG(ERROR) << "Tx burst failed " << ec.message();
+ delay = 200;
+ goto done;
+ }
+
+done:
+ memif_refill_queue(memif_connection_.conn, memif_connection_.tx_qid, ret, 0);
+
+ // If there are still packets to send, schedule another send
+ if (memif_connection_.tx_buf_num > 0 || !output_buffer_.empty()) {
+ scheduleSend(delay);
+ }
+
+ // If error, signal to upper layers
+ if (ec.operator bool()) {
+ std::weak_ptr<MemifConnector> self = shared_from_this();
+ io_service_.post([self, ec]() {
+ if (auto c = self.lock()) {
+ c->sent_callback_(c.get(), ec);
+ }
+ });
+ }
+
+ return 0;
+}
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/io_modules/memif/memif_connector.h b/libtransport/src/core/memif_connector.h
index 0a189f893..d36be4616 100644
--- a/libtransport/src/io_modules/memif/memif_connector.h
+++ b/libtransport/src/core/memif_connector.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,27 +25,48 @@
#include <utils/fd_deadline_timer.h>
#include <deque>
+#include <future>
#include <mutex>
#include <thread>
+extern "C" {
+#include <libmemif.h>
+};
+
#define _Static_assert static_assert
namespace transport {
namespace core {
-typedef struct memif_connection memif_connection_t;
-
#define APP_NAME "libtransport"
#define IF_NAME "vpp_connection"
-#define MEMIF_BUF_SIZE 2048
-#define MEMIF_LOG2_RING_SIZE 13
-#define MAX_MEMIF_BUFS (1 << MEMIF_LOG2_RING_SIZE)
-
class MemifConnector : public Connector {
- using memif_conn_handle_t = void *;
+ static inline std::size_t kbuf_size = 2048;
+ static inline std::size_t klog2_ring_size = 13;
+
using PacketRing = utils::CircularFifo<utils::MemBuf::Ptr, queue_size>;
+ struct Details {
+ // index
+ uint16_t index;
+ // memif conenction handle
+ memif_conn_handle_t conn;
+ // transmit queue id
+ uint16_t tx_qid;
+ // tx buffers
+ memif_buffer_t *tx_bufs;
+ // allocated tx buffers counter
+ // number of tx buffers pointing to shared memory
+ uint16_t tx_buf_num;
+ // rx buffers
+ memif_buffer_t *rx_bufs;
+ // allocated rx buffers counter
+ // number of rx buffers pointing to shared memory
+ uint16_t rx_buf_num;
+ // interface ip address
+ uint8_t ip_addr[4];
+ };
public:
MemifConnector(PacketReceivedCallback &&receive_callback,
@@ -59,11 +80,14 @@ class MemifConnector : public Connector {
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
void close() override;
- void connect(uint32_t memif_id, long memif_mode);
+ void connect(uint32_t memif_id, long memif_mode,
+ const std::string &socket_filename,
+ std::size_t buffer_size = kbuf_size,
+ std::size_t log2_ring_size = klog2_ring_size);
TRANSPORT_ALWAYS_INLINE uint32_t getMemifId() { return memif_id_; };
@@ -72,13 +96,13 @@ class MemifConnector : public Connector {
int doSend();
- int createMemif(uint32_t index, uint8_t mode, char *s);
+ int createMemif(uint32_t index, uint8_t is_master);
uint32_t getMemifConfiguration();
int deleteMemif();
- static int controlFdUpdate(int fd, uint8_t events, void *private_ctx);
+ static int controlFdUpdate(memif_fd_event_t fde, void *private_ctx);
static int onConnect(memif_conn_handle_t conn, void *private_ctx);
@@ -89,27 +113,26 @@ class MemifConnector : public Connector {
void threadMain();
- int txBurst(uint16_t qid);
+ uint16_t txBurst(uint16_t qid, std::error_code &ec);
+
+ uint16_t bufferAlloc(long n, uint16_t qid, std::error_code &ec);
- int bufferAlloc(long n, uint16_t qid);
+ void scheduleSend(std::uint64_t delay);
void sendCallback(const std::error_code &ec);
- void processInputBuffer(std::uint16_t total_packets);
+ auto shared_from_this() { return utils::shared_from(this); }
private:
- static utils::EpollEventReactor main_event_reactor_;
- static std::unique_ptr<std::thread> main_worker_;
-
int epfd;
- std::unique_ptr<std::thread> memif_worker_;
utils::EpollEventReactor event_reactor_;
+ std::thread memif_worker_;
std::atomic_bool timer_set_;
- std::unique_ptr<utils::FdDeadlineTimer> send_timer_;
- std::unique_ptr<utils::FdDeadlineTimer> disconnect_timer_;
+ utils::FdDeadlineTimer send_timer_;
+ utils::FdDeadlineTimer disconnect_timer_;
asio::io_service &io_service_;
asio::executor_work_guard<asio::io_context::executor_type> work_;
- std::unique_ptr<memif_connection_t> memif_connection_;
+ Details memif_connection_;
uint16_t tx_buf_counter_;
PacketRing input_buffer_;
@@ -121,8 +144,9 @@ class MemifConnector : public Connector {
uint16_t transmission_index_;
utils::SpinLock write_msgs_lock_;
std::string socket_filename_;
-
- static std::once_flag flag_;
+ std::size_t buffer_size_;
+ std::size_t log2_ring_size_;
+ std::size_t max_memif_bufs_;
};
} // end namespace core
diff --git a/libtransport/src/core/name.cc b/libtransport/src/core/name.cc
index 795c8a697..98091eea5 100644
--- a/libtransport/src/core/name.cc
+++ b/libtransport/src/core/name.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,30 +26,28 @@ namespace core {
Name::Name() { name_ = {}; }
+/**
+ * XXX This function does not use the name API provided by libhicn
+ */
Name::Name(int family, const uint8_t *ip_address, std::uint32_t suffix)
: name_({}) {
- name_.type = HNT_UNSPEC;
std::size_t length;
uint8_t *dst = NULL;
if (family == AF_INET) {
- dst = name_.ip4.prefix_as_u8;
+ dst = name_.prefix.v4.as_u8;
length = IPV4_ADDR_LEN;
- name_.type = HNT_CONTIGUOUS_V4;
} else if (family == AF_INET6) {
- dst = name_.ip6.prefix_as_u8;
+ dst = name_.prefix.v6.as_u8;
length = IPV6_ADDR_LEN;
- name_.type = HNT_CONTIGUOUS_V6;
} else {
throw errors::RuntimeException("Specified name family does not exist.");
}
std::memcpy(dst, ip_address, length);
- *reinterpret_cast<std::uint32_t *>(dst + length) = suffix;
+ name_.suffix = suffix;
}
-
Name::Name(const char *name, uint32_t segment) {
- name_.type = HNT_UNSPEC;
if (hicn_name_create(name, segment, &name_) < 0) {
throw errors::InvalidIpAddressException();
}
@@ -59,7 +57,6 @@ Name::Name(const std::string &uri, uint32_t segment)
: Name(uri.c_str(), segment) {}
Name::Name(const std::string &uri) {
- name_.type = HNT_UNSPEC;
utils::StringTokenizer tokenizer(uri, "|");
std::string ip_address;
std::string seq_number;
@@ -80,9 +77,13 @@ Name::Name(const std::string &uri) {
Name::Name(const Name &name) { this->name_ = name.name_; }
+Name::~Name() {}
+
Name &Name::operator=(const Name &name) {
- if (hicn_name_copy(&this->name_, &name.name_) < 0) {
- throw errors::MalformedNameException();
+ if (this != &name) {
+ if (hicn_name_copy(&this->name_, &name.name_) < 0) {
+ throw errors::MalformedNameException();
+ }
}
return *this;
@@ -129,9 +130,13 @@ uint32_t Name::getHash32(bool consider_suffix) const {
return hash;
}
-void Name::clear() { name_.type = HNT_UNSPEC; };
+void Name::clear() { std::memset(&name_, 0, sizeof(name_)); };
-Name::Type Name::getType() const { return name_.type; }
+Name::Type Name::getType() const {
+ int family;
+ hicn_name_get_family(&name_, &family);
+ return family == AF_INET ? Name::Type::V4 : Name::Type::V6;
+}
uint32_t Name::getSuffix() const {
uint32_t ret = 0;
@@ -151,29 +156,6 @@ Name &Name::setSuffix(uint32_t seq_number) {
return *this;
}
-std::shared_ptr<Sockaddr> Name::getAddress() const {
- Sockaddr *ret = nullptr;
-
- switch (name_.type) {
- case HNT_CONTIGUOUS_V4:
- case HNT_IOV_V4:
- ret = (Sockaddr *)new Sockaddr4;
- break;
- case HNT_CONTIGUOUS_V6:
- case HNT_IOV_V6:
- ret = (Sockaddr *)new Sockaddr6;
- break;
- default:
- throw errors::MalformedNameException();
- }
-
- if (hicn_name_to_sockaddr_address((hicn_name_t *)&name_, ret) < 0) {
- throw errors::MalformedNameException();
- }
-
- return std::shared_ptr<Sockaddr>(ret);
-}
-
ip_prefix_t Name::toIpAddress() const {
ip_prefix_t ret;
std::memset(&ret, 0, sizeof(ret));
@@ -195,8 +177,8 @@ int Name::getAddressFamily() const {
return ret;
}
-void Name::copyToDestination(uint8_t *destination, bool include_suffix) const {
- if (hicn_name_copy_to_destination(destination, &name_, include_suffix) < 0) {
+void Name::copyPrefixToDestination(uint8_t *destination) const {
+ if (hicn_name_copy_prefix_to_destination(destination, &name_) < 0) {
throw errors::RuntimeException(
"Impossibe to copy the name into the "
"provided destination");
diff --git a/libtransport/src/core/packet.cc b/libtransport/src/core/packet.cc
index 51337201f..df27444af 100644
--- a/libtransport/src/core/packet.cc
+++ b/libtransport/src/core/packet.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -41,13 +41,6 @@ Packet::Packet(Format format, std::size_t additional_header_size)
setFormat(format_, additional_header_size);
}
-Packet::Packet(MemBuf &&buffer)
- : utils::MemBuf(std::move(buffer)),
- packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
- header_offset_(0),
- format_(getFormatFromBuffer(data(), length())),
- payload_type_(PayloadType::UNSPECIFIED) {}
-
Packet::Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size)
: utils::MemBuf(COPY_BUFFER, buffer, size),
packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
@@ -74,11 +67,11 @@ Packet::Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size,
setFormat(format_, additional_header_size);
}
-Packet::Packet(const Packet &other)
- : utils::MemBuf(other),
+Packet::Packet(MemBuf &&buffer)
+ : utils::MemBuf(std::move(buffer)),
packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
- header_offset_(other.header_offset_),
- format_(other.format_),
+ header_offset_(0),
+ format_(getFormatFromBuffer(data(), length())),
payload_type_(PayloadType::UNSPECIFIED) {}
Packet::Packet(Packet &&other)
@@ -92,6 +85,13 @@ Packet::Packet(Packet &&other)
other.header_offset_ = 0;
}
+Packet::Packet(const Packet &other)
+ : utils::MemBuf(other),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(other.header_offset_),
+ format_(other.format_),
+ payload_type_(PayloadType::UNSPECIFIED) {}
+
Packet::~Packet() {}
Packet &Packet::operator=(const Packet &other) {
@@ -103,29 +103,19 @@ Packet &Packet::operator=(const Packet &other) {
return *this;
}
-std::size_t Packet::getHeaderSizeFromBuffer(Format format,
- const uint8_t *buffer) {
- size_t header_length;
-
- if (hicn_packet_get_header_length(format, (hicn_header_t *)buffer,
- &header_length) < 0) {
- throw errors::MalformedPacketException();
- }
-
- return header_length;
+std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() {
+ return std::static_pointer_cast<utils::MemBuf>(shared_from_this());
}
-bool Packet::isInterest(const uint8_t *buffer) {
- bool is_interest = false;
-
- if (TRANSPORT_EXPECT_FALSE(hicn_packet_test_ece(HF_INET6_TCP,
- (const hicn_header_t *)buffer,
- &is_interest) < 0)) {
- throw errors::RuntimeException(
- "Impossible to retrieve ece flag from packet");
+Packet::Format Packet::getFormat() const {
+ // We check packet start because after a movement it will result in a nullptr
+ if (format_ == HF_UNSPEC && length()) {
+ if (hicn_packet_get_format(packet_start_, &format_) < 0) {
+ LOG(ERROR) << "Unexpected packet format HF_UNSPEC.";
+ }
}
- return !is_interest;
+ return format_;
}
void Packet::setFormat(Packet::Format format,
@@ -136,47 +126,43 @@ void Packet::setFormat(Packet::Format format,
}
auto header_size = getHeaderSizeFromFormat(format_);
- assert(header_size <= tailroom());
+ DCHECK(header_size <= tailroom());
append(header_size);
- assert(additional_header_size <= tailroom());
+ DCHECK(additional_header_size <= tailroom());
append(additional_header_size);
header_offset_ = length();
}
-bool Packet::isInterest() { return Packet::isInterest(data()); }
+PayloadType Packet::getPayloadType() const {
+ if (payload_type_ == PayloadType::UNSPECIFIED) {
+ hicn_payload_type_t ret;
-std::size_t Packet::getPayloadSizeFromBuffer(Format format,
- const uint8_t *buffer) {
- std::size_t payload_length;
- if (TRANSPORT_EXPECT_FALSE(
- hicn_packet_get_payload_length(format, (hicn_header_t *)buffer,
- &payload_length) < 0)) {
- throw errors::MalformedPacketException();
+ if (hicn_packet_get_payload_type(format_, packet_start_, &ret) < 0) {
+ throw errors::RuntimeException("Impossible to retrieve payload type.");
+ }
+
+ payload_type_ = (PayloadType)ret;
}
- return payload_length;
+ return payload_type_;
}
-std::size_t Packet::payloadSize() const {
- std::size_t ret = 0;
-
- if (length()) {
- ret = getPayloadSizeFromBuffer(format_,
- reinterpret_cast<uint8_t *>(packet_start_));
+Packet &Packet::setPayloadType(PayloadType payload_type) {
+ if (hicn_packet_set_payload_type(format_, packet_start_,
+ hicn_payload_type_t(payload_type)) < 0) {
+ throw errors::RuntimeException("Error setting payload type of the packet.");
}
- return ret;
+ payload_type_ = payload_type;
+ return *this;
}
-std::size_t Packet::headerSize() const {
- if (header_offset_ == 0 && length()) {
- const_cast<Packet *>(this)->header_offset_ = getHeaderSizeFromBuffer(
- format_, reinterpret_cast<uint8_t *>(packet_start_));
- }
-
- return header_offset_;
+std::unique_ptr<utils::MemBuf> Packet::getPayload() const {
+ auto ret = clone();
+ ret->trimStart(headerSize());
+ return ret;
}
Packet &Packet::appendPayload(std::unique_ptr<utils::MemBuf> &&payload) {
@@ -196,12 +182,56 @@ Packet &Packet::appendPayload(const uint8_t *buffer, std::size_t length) {
return *this;
}
-std::unique_ptr<utils::MemBuf> Packet::getPayload() const {
- auto ret = clone();
- ret->trimStart(headerSize());
+std::size_t Packet::headerSize() const {
+ if (header_offset_ == 0 && length()) {
+ const_cast<Packet *>(this)->header_offset_ = getHeaderSizeFromBuffer(
+ format_, reinterpret_cast<uint8_t *>(packet_start_));
+ }
+
+ return header_offset_;
+}
+
+std::size_t Packet::payloadSize() const {
+ std::size_t ret = 0;
+
+ if (length()) {
+ ret = getPayloadSizeFromBuffer(format_,
+ reinterpret_cast<uint8_t *>(packet_start_));
+ }
+
return ret;
}
+auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const {
+ auth::CryptoHash hash;
+ hash.setType(algorithm);
+
+ // Copy IP+TCP/ICMP header before zeroing them
+ hicn_header_t header_copy;
+ hicn_packet_copy_header(format_, packet_start_, &header_copy, false);
+ const_cast<Packet *>(this)->resetForHash();
+
+ hash.computeDigest(this);
+ hicn_packet_copy_header(format_, &header_copy, packet_start_, false);
+
+ return hash;
+}
+
+void Packet::reset() {
+ clear();
+ packet_start_ = reinterpret_cast<hicn_header_t *>(writableData());
+ header_offset_ = 0;
+ format_ = HF_UNSPEC;
+ payload_type_ = PayloadType::UNSPECIFIED;
+ name_.clear();
+
+ if (isChained()) {
+ separateChain(next(), prev());
+ }
+}
+
+bool Packet::isInterest() { return Packet::isInterest(data(), format_); }
+
Packet &Packet::updateLength(std::size_t length) {
std::size_t total_length = length;
@@ -221,47 +251,6 @@ Packet &Packet::updateLength(std::size_t length) {
return *this;
}
-PayloadType Packet::getPayloadType() const {
- if (payload_type_ == PayloadType::UNSPECIFIED) {
- hicn_payload_type_t ret;
- if (hicn_packet_get_payload_type(packet_start_, &ret) < 0) {
- throw errors::RuntimeException("Impossible to retrieve payload type.");
- }
-
- payload_type_ = (PayloadType)ret;
- }
-
- return payload_type_;
-}
-
-Packet &Packet::setPayloadType(PayloadType payload_type) {
- if (hicn_packet_set_payload_type(packet_start_,
- hicn_payload_type_t(payload_type)) < 0) {
- throw errors::RuntimeException("Error setting payload type of the packet.");
- }
-
- payload_type_ = payload_type;
-
- return *this;
-}
-
-Packet::Format Packet::getFormat() const {
- /**
- * We check packet start because after a movement it will result in a nullptr
- */
- if (format_ == HF_UNSPEC && length()) {
- if (hicn_packet_get_format(packet_start_, &format_) < 0) {
- LOG(ERROR) << "Unexpected packet format HF_UNSPEC.";
- }
- }
-
- return format_;
-}
-
-std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() {
- return std::static_pointer_cast<utils::MemBuf>(shared_from_this());
-}
-
void Packet::dump() const {
LOG(INFO) << "HEADER -- Length: " << headerSize();
LOG(INFO) << "PAYLOAD -- Length: " << payloadSize();
@@ -274,180 +263,42 @@ void Packet::dump() const {
} while (current != this);
}
-void Packet::dump(uint8_t *buffer, std::size_t length) {
- hicn_packet_dump(buffer, length);
-}
-
-void Packet::setSignatureSize(std::size_t size_bytes) {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- int ret = hicn_packet_set_signature_size(format_, packet_start_, size_bytes);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error setting signature size.");
- }
-}
-
-void Packet::setSignatureSizeGap(std::size_t size_bytes) {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- int ret = hicn_packet_set_signature_gap(format_, packet_start_,
- (uint8_t)size_bytes);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error setting signature size.");
- }
-}
-
-uint8_t *Packet::getSignature() const {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- uint8_t *signature;
- int ret = hicn_packet_get_signature(format_, packet_start_, &signature);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error getting signature.");
- }
-
- return signature;
-}
-
-void Packet::setSignatureTimestamp(const uint64_t &timestamp) {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- int ret =
- hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error setting the signature timestamp.");
- }
-}
-
-uint64_t Packet::getSignatureTimestamp() const {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- uint64_t return_value;
- int ret = hicn_packet_get_signature_timestamp(format_, packet_start_,
- &return_value);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error getting the signature timestamp.");
- }
-
- return return_value;
-}
-
-void Packet::setValidationAlgorithm(
- const auth::CryptoSuite &validation_algorithm) {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- int ret = hicn_packet_set_validation_algorithm(format_, packet_start_,
- uint8_t(validation_algorithm));
-
- if (ret < 0) {
- throw errors::RuntimeException("Error setting the validation algorithm.");
- }
-}
-
-auth::CryptoSuite Packet::getValidationAlgorithm() const {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- uint8_t return_value;
- int ret = hicn_packet_get_validation_algorithm(format_, packet_start_,
- &return_value);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error getting the validation algorithm.");
- }
-
- return auth::CryptoSuite(return_value);
-}
-
-void Packet::setKeyId(const auth::KeyId &key_id) {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
-
- int ret = hicn_packet_set_key_id(format_, packet_start_, key_id.first);
-
- if (ret < 0) {
- throw errors::RuntimeException("Error setting the key id.");
- }
-}
-
-auth::KeyId Packet::getKeyId() const {
- if (!authenticationHeader()) {
- throw errors::RuntimeException("Packet without Authentication Header.");
- }
+void Packet::setChecksum() {
+ if (_is_tcp(format_)) {
+ uint16_t partial_csum =
+ csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0);
- auth::KeyId return_value;
- int ret = hicn_packet_get_key_id(format_, packet_start_, &return_value.first,
- &return_value.second);
+ for (utils::MemBuf *current = next(); current != this;
+ current = current->next()) {
+ partial_csum = csum(current->data(), current->length(), ~partial_csum);
+ }
- if (ret < 0) {
- throw errors::RuntimeException("Error getting the validation algorithm.");
+ if (hicn_packet_compute_header_checksum(format_, packet_start_,
+ partial_csum) < 0) {
+ throw errors::MalformedPacketException();
+ }
}
-
- return return_value;
-}
-
-auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const {
- auth::CryptoHash hash;
- hash.setType(algorithm);
-
- // Copy IP+TCP/ICMP header before zeroing them
- hicn_header_t header_copy;
-
- hicn_packet_copy_header(format_, packet_start_, &header_copy, false);
-
- const_cast<Packet *>(this)->resetForHash();
-
- hash.computeDigest(this);
- hicn_packet_copy_header(format_, &header_copy, packet_start_, false);
-
- return hash;
}
bool Packet::checkIntegrity() const {
- uint16_t partial_csum =
- csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0);
+ if (_is_tcp(format_)) {
+ uint16_t partial_csum =
+ csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0);
- for (const utils::MemBuf *current = next(); current != this;
- current = current->next()) {
- partial_csum = csum(current->data(), current->length(), ~partial_csum);
- }
+ for (const utils::MemBuf *current = next(); current != this;
+ current = current->next()) {
+ partial_csum = csum(current->data(), current->length(), ~partial_csum);
+ }
- if (hicn_packet_check_integrity_no_payload(format_, packet_start_,
- partial_csum) < 0) {
- return false;
+ if (hicn_packet_check_integrity_no_payload(format_, packet_start_,
+ partial_csum) < 0) {
+ return false;
+ }
}
return true;
}
-void Packet::prependPayload(const uint8_t **buffer, std::size_t *size) {
- auto last = prev();
- auto to_copy = std::min(*size, last->tailroom());
- std::memcpy(last->writableTail(), *buffer, to_copy);
- last->append(to_copy);
- *size -= to_copy;
- *buffer += to_copy;
-}
-
Packet &Packet::setSyn() {
if (hicn_packet_set_syn(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error setting syn bit in the packet.");
@@ -553,29 +404,23 @@ Packet &Packet::resetFlags() {
resetAck();
resetRst();
resetFin();
-
return *this;
}
std::string Packet::printFlags() const {
std::string flags;
-
if (testSyn()) {
flags += "S";
}
-
if (testAck()) {
flags += "A";
}
-
if (testRst()) {
flags += "R";
}
-
if (testFin()) {
flags += "F";
}
-
return flags;
}
@@ -634,6 +479,245 @@ uint8_t Packet::getTTL() const {
return hops;
}
+bool Packet::hasAH() const { return _is_ah(format_); }
+
+std::vector<uint8_t> Packet::getSignature() const {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ uint8_t *signature;
+ int ret = hicn_packet_get_signature(format_, packet_start_, &signature);
+
+ if (ret < 0) {
+ throw errors::RuntimeException("Error getting signature.");
+ }
+
+ return std::vector<uint8_t>(signature, signature + getSignatureFieldSize());
+}
+
+std::size_t Packet::getSignatureFieldSize() const {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ size_t field_size;
+ int ret = hicn_packet_get_signature_size(format_, packet_start_, &field_size);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error reading signature field size");
+ }
+ return field_size;
+}
+
+std::size_t Packet::getSignatureSize() const {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ size_t padding;
+ int ret = hicn_packet_get_signature_padding(format_, packet_start_, &padding);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error reading signature padding");
+ }
+
+ size_t size = getSignatureFieldSize() - padding;
+ if (size < 0) {
+ throw errors::RuntimeException("Error reading signature size");
+ }
+
+ return size;
+}
+
+uint64_t Packet::getSignatureTimestamp() const {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ uint64_t timestamp;
+ int ret =
+ hicn_packet_get_signature_timestamp(format_, packet_start_, &timestamp);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error getting the signature timestamp.");
+ }
+ return timestamp;
+}
+
+auth::KeyId Packet::getKeyId() const {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ auth::KeyId key_id;
+ int ret = hicn_packet_get_key_id(format_, packet_start_, &key_id.first,
+ &key_id.second);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error getting the validation algorithm.");
+ }
+ return key_id;
+}
+
+auth::CryptoSuite Packet::getValidationAlgorithm() const {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ uint8_t return_value;
+ int ret = hicn_packet_get_validation_algorithm(format_, packet_start_,
+ &return_value);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error getting the validation algorithm.");
+ }
+ return auth::CryptoSuite(return_value);
+}
+
+void Packet::setSignature(const std::vector<uint8_t> &signature) {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ uint8_t *signature_field;
+ int ret = hicn_packet_get_signature(format_, packet_start_, &signature_field);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error getting signature.");
+ }
+ memcpy(signature_field, signature.data(), signature.size());
+}
+
+void Packet::setSignatureFieldSize(std::size_t size) {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ int ret = hicn_packet_set_signature_size(format_, packet_start_, size);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error setting signature size.");
+ }
+}
+
+void Packet::setSignatureSize(std::size_t size) {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ size_t padding = getSignatureFieldSize() - size;
+ if (padding < 0) {
+ throw errors::RuntimeException("Error setting signature padding.");
+ }
+
+ int ret = hicn_packet_set_signature_padding(format_, packet_start_, padding);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error setting signature padding.");
+ }
+}
+
+void Packet::setSignatureTimestamp(const uint64_t &timestamp) {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ int ret =
+ hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error setting the signature timestamp.");
+ }
+}
+
+void Packet::setKeyId(const auth::KeyId &key_id) {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ int ret = hicn_packet_set_key_id(format_, packet_start_, key_id.first);
+ if (ret < 0) {
+ throw errors::RuntimeException("Error setting the key id.");
+ }
+}
+
+void Packet::setValidationAlgorithm(
+ const auth::CryptoSuite &validation_algorithm) {
+ if (!hasAH()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ int ret = hicn_packet_set_validation_algorithm(format_, packet_start_,
+ uint8_t(validation_algorithm));
+ if (ret < 0) {
+ throw errors::RuntimeException("Error setting the validation algorithm.");
+ }
+}
+
+Packet::Format Packet::toAHFormat(const Format &format) {
+ return hicn_get_ah_format(format);
+}
+
+Packet::Format Packet::getFormatFromBuffer(const uint8_t *buffer,
+ std::size_t /* length */) {
+ Packet::Format format = HF_UNSPEC;
+ hicn_packet_get_format((const hicn_header_t *)buffer, &format);
+ return format;
+}
+
+std::size_t Packet::getHeaderSizeFromFormat(Format format,
+ std::size_t signature_size) {
+ std::size_t header_length;
+ hicn_packet_get_header_length_from_format(format, &header_length);
+ int is_ah = _is_ah(format);
+ return is_ah * (header_length + signature_size) + (!is_ah) * header_length;
+}
+
+std::size_t Packet::getHeaderSizeFromBuffer(Format format,
+ const uint8_t *buffer) {
+ size_t header_length;
+
+ if (hicn_packet_get_header_length(format, (hicn_header_t *)buffer,
+ &header_length) < 0) {
+ throw errors::MalformedPacketException();
+ }
+
+ return header_length;
+}
+
+std::size_t Packet::getPayloadSizeFromBuffer(Format format,
+ const uint8_t *buffer) {
+ std::size_t payload_length;
+ if (TRANSPORT_EXPECT_FALSE(
+ hicn_packet_get_payload_length(format, (hicn_header_t *)buffer,
+ &payload_length) < 0)) {
+ throw errors::MalformedPacketException();
+ }
+
+ return payload_length;
+}
+
+bool Packet::isInterest(const uint8_t *buffer, Format format) {
+ int is_interest = 0;
+
+ if (TRANSPORT_EXPECT_FALSE(format == Format::HF_UNSPEC)) {
+ format = getFormatFromBuffer(buffer, /* Unused length */ 128);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(
+ hicn_packet_is_interest(format, (const hicn_header_t *)buffer,
+ &is_interest) < 0)) {
+ throw errors::RuntimeException("Error reading ece flag from packet");
+ }
+
+ return is_interest;
+}
+
+void Packet::dump(uint8_t *buffer, std::size_t length) {
+ hicn_packet_dump(buffer, length);
+}
+
+void Packet::prependPayload(const uint8_t **buffer, std::size_t *size) {
+ auto last = prev();
+ auto to_copy = std::min(*size, last->tailroom());
+ std::memcpy(last->writableTail(), *buffer, to_copy);
+ last->append(to_copy);
+ *size -= to_copy;
+ *buffer += to_copy;
+}
+
} // end namespace core
} // end namespace transport
diff --git a/libtransport/src/core/pending_interest.cc b/libtransport/src/core/pending_interest.cc
deleted file mode 100644
index fbe98cab5..000000000
--- a/libtransport/src/core/pending_interest.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/pending_interest.h>
-
-namespace transport {
-
-namespace core {
-
-PendingInterest::PendingInterest()
- : interest_(nullptr, nullptr),
- timer_(),
- on_content_object_callback_(),
- on_interest_timeout_callback_() {}
-
-PendingInterest::PendingInterest(Interest::Ptr &&interest,
- std::unique_ptr<asio::steady_timer> &&timer)
- : interest_(std::move(interest)),
- timer_(std::move(timer)),
- on_content_object_callback_(),
- on_interest_timeout_callback_() {}
-
-PendingInterest::PendingInterest(
- Interest::Ptr &&interest, OnContentObjectCallback &&on_content_object,
- OnInterestTimeoutCallback &&on_interest_timeout,
- std::unique_ptr<asio::steady_timer> &&timer)
- : interest_(std::move(interest)),
- timer_(std::move(timer)),
- on_content_object_callback_(std::move(on_content_object)),
- on_interest_timeout_callback_(std::move(on_interest_timeout)) {}
-
-PendingInterest::~PendingInterest() {}
-
-void PendingInterest::cancelTimer() { timer_->cancel(); }
-
-void PendingInterest::setInterest(Interest::Ptr &&interest) {
- interest_ = std::move(interest);
-}
-
-Interest::Ptr &&PendingInterest::getInterest() { return std::move(interest_); }
-
-const OnContentObjectCallback &PendingInterest::getOnDataCallback() const {
- return on_content_object_callback_;
-}
-
-void PendingInterest::setOnContentObjectCallback(
- OnContentObjectCallback &&on_content_object) {
- PendingInterest::on_content_object_callback_ = on_content_object;
-}
-
-const OnInterestTimeoutCallback &PendingInterest::getOnTimeoutCallback() const {
- return on_interest_timeout_callback_;
-}
-
-void PendingInterest::setOnTimeoutCallback(
- OnInterestTimeoutCallback &&on_interest_timeout) {
- PendingInterest::on_interest_timeout_callback_ = on_interest_timeout;
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/pending_interest.h b/libtransport/src/core/pending_interest.h
index 99a8bd327..f8a4ba10e 100644
--- a/libtransport/src/core/pending_interest.h
+++ b/libtransport/src/core/pending_interest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -48,19 +48,17 @@ class PendingInterest {
// on_content_object_callback_(),
// on_interest_timeout_callback_() {}
- PendingInterest(Interest::Ptr &&interest,
- std::unique_ptr<asio::steady_timer> &&timer)
- : interest_(std::move(interest)),
- timer_(std::move(timer)),
+ PendingInterest(asio::io_service &io_service, const Interest::Ptr &interest)
+ : interest_(interest),
+ timer_(io_service),
on_content_object_callback_(),
on_interest_timeout_callback_() {}
- PendingInterest(Interest::Ptr &&interest,
+ PendingInterest(asio::io_service &io_service, const Interest::Ptr &interest,
OnContentObjectCallback &&on_content_object,
- OnInterestTimeoutCallback &&on_interest_timeout,
- std::unique_ptr<asio::steady_timer> &&timer)
- : interest_(std::move(interest)),
- timer_(std::move(timer)),
+ OnInterestTimeoutCallback &&on_interest_timeout)
+ : interest_(interest),
+ timer_(io_service),
on_content_object_callback_(std::move(on_content_object)),
on_interest_timeout_callback_(std::move(on_interest_timeout)) {}
@@ -68,12 +66,12 @@ class PendingInterest {
template <typename Handler>
TRANSPORT_ALWAYS_INLINE void startCountdown(Handler &&cb) {
- timer_->expires_from_now(
+ timer_.expires_from_now(
std::chrono::milliseconds(interest_->getLifetime()));
- timer_->async_wait(std::forward<Handler &&>(cb));
+ timer_.async_wait(std::forward<Handler &&>(cb));
}
- TRANSPORT_ALWAYS_INLINE void cancelTimer() { timer_->cancel(); }
+ TRANSPORT_ALWAYS_INLINE void cancelTimer() { timer_.cancel(); }
TRANSPORT_ALWAYS_INLINE Interest::Ptr &&getInterest() {
return std::move(interest_);
@@ -105,7 +103,7 @@ class PendingInterest {
private:
Interest::Ptr interest_;
- std::unique_ptr<asio::steady_timer> timer_;
+ asio::steady_timer timer_;
OnContentObjectCallback on_content_object_callback_;
OnInterestTimeoutCallback on_interest_timeout_callback_;
};
diff --git a/libtransport/src/core/portal.cc b/libtransport/src/core/portal.cc
index c4c0cf8ba..d8e8d78ea 100644
--- a/libtransport/src/core/portal.cc
+++ b/libtransport/src/core/portal.cc
@@ -30,11 +30,11 @@ namespace core {
#ifdef ANDROID
static const constexpr char default_module[] = "";
#elif defined(MACINTOSH)
-static const constexpr char default_module[] = "hicnlight_module.dylib";
+static const constexpr char default_module[] = "hicnlightng_module.dylib";
#elif defined(LINUX)
-static const constexpr char default_module[] = "hicnlight_module.so";
+static const constexpr char default_module[] = "hicnlightng_module.so";
#elif defined(WINDOWS)
-static const constexpr char default_module[] = "hicnlight_module.lib";
+static const constexpr char default_module[] = "hicnlightng_module.lib";
#endif
IoModuleConfiguration Portal::conf_;
@@ -57,7 +57,7 @@ std::string Portal::defaultIoModule() {
void Portal::getModuleConfiguration(ConfigurationObject& object,
std::error_code& ec) {
- assert(object.getKey() == io_module_section);
+ DCHECK(object.getKey() == io_module_section);
auto conf = dynamic_cast<const IoModuleConfiguration&>(object);
conf = conf_;
@@ -103,7 +103,7 @@ std::string getIoModulePath(const std::string& name,
void Portal::setModuleConfiguration(const ConfigurationObject& object,
std::error_code& ec) {
- assert(object.getKey() == io_module_section);
+ DCHECK(object.getKey() == io_module_section);
const IoModuleConfiguration& conf =
dynamic_cast<const IoModuleConfiguration&>(object);
diff --git a/libtransport/src/core/portal.h b/libtransport/src/core/portal.h
index f6a9ce85b..aae4c573e 100644
--- a/libtransport/src/core/portal.h
+++ b/libtransport/src/core/portal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,6 +15,7 @@
#pragma once
+#include <core/global_workers.h>
#include <core/pending_interest.h>
#include <glog/logging.h>
#include <hicn/transport/config.h>
@@ -28,6 +29,7 @@
#include <hicn/transport/interfaces/global_conf_interface.h>
#include <hicn/transport/interfaces/portal.h>
#include <hicn/transport/portability/portability.h>
+#include <hicn/transport/utils/event_thread.h>
#include <hicn/transport/utils/fixed_block_allocator.h>
#include <future>
@@ -54,11 +56,11 @@ class HandlerMemory {
HandlerMemory(const HandlerMemory &) = delete;
HandlerMemory &operator=(const HandlerMemory &) = delete;
- TRANSPORT_ALWAYS_INLINE void *allocate(std::size_t size) {
+ void *allocate(std::size_t size) {
return utils::FixedBlockAllocator<128, 8192>::getInstance().allocateBlock();
}
- TRANSPORT_ALWAYS_INLINE void deallocate(void *pointer) {
+ void deallocate(void *pointer) {
utils::FixedBlockAllocator<128, 8192>::getInstance().deallocateBlock(
pointer);
}
@@ -69,13 +71,9 @@ class HandlerMemory {
HandlerMemory(const HandlerMemory &) = delete;
HandlerMemory &operator=(const HandlerMemory &) = delete;
- TRANSPORT_ALWAYS_INLINE void *allocate(std::size_t size) {
- return ::operator new(size);
- }
+ void *allocate(std::size_t size) { return ::operator new(size); }
- TRANSPORT_ALWAYS_INLINE void deallocate(void *pointer) {
- ::operator delete(pointer);
- }
+ void deallocate(void *pointer) { ::operator delete(pointer); }
#endif
};
@@ -92,21 +90,19 @@ class HandlerAllocator {
HandlerAllocator(const HandlerAllocator<U> &other) noexcept
: memory_(other.memory_) {}
- TRANSPORT_ALWAYS_INLINE bool operator==(
- const HandlerAllocator &other) const noexcept {
+ bool operator==(const HandlerAllocator &other) const noexcept {
return &memory_ == &other.memory_;
}
- TRANSPORT_ALWAYS_INLINE bool operator!=(
- const HandlerAllocator &other) const noexcept {
+ bool operator!=(const HandlerAllocator &other) const noexcept {
return &memory_ != &other.memory_;
}
- TRANSPORT_ALWAYS_INLINE T *allocate(std::size_t n) const {
+ T *allocate(std::size_t n) const {
return static_cast<T *>(memory_.allocate(sizeof(T) * n));
}
- TRANSPORT_ALWAYS_INLINE void deallocate(T *p, std::size_t /*n*/) const {
+ void deallocate(T *p, std::size_t /*n*/) const {
return memory_.deallocate(p);
}
@@ -135,7 +131,7 @@ class CustomAllocatorHandler {
}
template <typename... Args>
- void operator()(Args &&... args) {
+ void operator()(Args &&...args) {
handler_(std::forward<Args>(args)...);
}
@@ -151,49 +147,16 @@ inline CustomAllocatorHandler<Handler> makeCustomAllocatorHandler(
return CustomAllocatorHandler<Handler>(m, h);
}
-class Pool {
- public:
- Pool(asio::io_service &io_service) : io_service_(io_service) {
- increasePendingInterestPool();
- }
-
- TRANSPORT_ALWAYS_INLINE void increasePendingInterestPool() {
- // Create pool of pending interests to reuse
- for (uint32_t i = 0; i < pit_size; i++) {
- pending_interests_pool_.add(new PendingInterest(
- Interest::Ptr(nullptr),
- std::make_unique<asio::steady_timer>(io_service_)));
- }
- }
- PendingInterest::Ptr getPendingInterest() {
- auto res = pending_interests_pool_.get();
- while (TRANSPORT_EXPECT_FALSE(!res.first)) {
- increasePendingInterestPool();
- res = pending_interests_pool_.get();
- }
-
- return std::move(res.second);
- }
-
- private:
- utils::ObjectPool<PendingInterest> pending_interests_pool_;
- asio::io_service &io_service_;
-};
-
} // namespace portal_details
class PortalConfiguration;
-using PendingInterestHashTable =
- std::unordered_map<uint32_t, PendingInterest::Ptr>;
-
-using interface::BindConfig;
+using PendingInterestHashTable = std::unordered_map<uint32_t, PendingInterest>;
/**
* Portal is a opaque class which is used for sending/receiving interest/data
- * packets over multiple kind of connector. The connector itself is defined by
- * the template ForwarderInt, which is resolved at compile time. It is then not
- * possible to decide at runtime what the connector will be.
+ * packets over multiple kind of io_modules. The io_module itself is an external
+ * module loaded at runtime.
*
* The tasks performed by portal are the following:
* - Sending/Receiving Interest packets
@@ -210,22 +173,16 @@ using interface::BindConfig;
* users of this class.
*/
-class Portal {
- public:
- using ConsumerCallback = interface::Portal::ConsumerCallback;
- using ProducerCallback = interface::Portal::ProducerCallback;
-
- friend class PortalConfiguration;
-
- Portal() : Portal(internal_io_service_) {}
+class Portal : public ::utils::NonCopyable,
+ public std::enable_shared_from_this<Portal> {
+ private:
+ Portal() : Portal(GlobalWorkers::getInstance().getWorker()) {}
- Portal(asio::io_service &io_service)
+ Portal(::utils::EventThread &worker)
: io_module_(nullptr, [](IoModule *module) { IoModule::unload(module); }),
- io_service_(io_service),
- packet_pool_(io_service),
+ worker_(worker),
app_name_("libtransport_application"),
- consumer_callback_(nullptr),
- producer_callback_(nullptr),
+ transport_callback_(nullptr),
is_consumer_(false) {
/**
* This workaroung allows to initialize memory for packet buffers *before*
@@ -235,58 +192,105 @@ class Portal {
*/
PacketManager<>::getInstance();
}
+
+ public:
+ using TransportCallback = interface::Portal::TransportCallback;
+ friend class PortalConfiguration;
+
+ static std::shared_ptr<Portal> createShared() {
+ return std::shared_ptr<Portal>(new Portal());
+ }
+
+ static std::shared_ptr<Portal> createShared(::utils::EventThread &worker) {
+ return std::shared_ptr<Portal>(new Portal(worker));
+ }
+
+ bool isConnected() const { return io_module_.get() != nullptr; }
+
/**
- * Set the consumer callback.
+ * Set the transport callback. Must be called from the same worker thread.
*
- * @param consumer_callback - The pointer to the ConsumerCallback object.
+ * @param consumer_callback - The pointer to the TransportCallback object.
*/
- void setConsumerCallback(ConsumerCallback *consumer_callback) {
- consumer_callback_ = consumer_callback;
+ void registerTransportCallback(TransportCallback *transport_callback) {
+ DCHECK(std::this_thread::get_id() == worker_.getThreadId());
+ transport_callback_ = transport_callback;
}
/**
- * Set the producer callback.
- *
- * @param producer_callback - The pointer to the ProducerCallback object.
+ * Unset the consumer callback. Must be called from the same worker thread.
*/
- void setProducerCallback(ProducerCallback *producer_callback) {
- producer_callback_ = producer_callback;
+ void unregisterTransportCallback() {
+ DCHECK(std::this_thread::get_id() == worker_.getThreadId());
+ transport_callback_ = nullptr;
}
/**
- * Specify the output interface to use. This method will be useful in a future
- * scenario where the library will be able to forward packets without
+ * Specify the output interface to use. This method will be useful in a
+ * future scenario where the library will be able to forward packets without
* connecting to a local forwarder. Now it is not used.
*
* @param output_interface - The output interface to use for
* forwarding/receiving packets.
*/
- TRANSPORT_ALWAYS_INLINE void setOutputInterface(
- const std::string &output_interface) {
- io_module_->setOutputInterface(output_interface);
+ void setOutputInterface(const std::string &output_interface) {
+ if (io_module_) {
+ io_module_->setOutputInterface(output_interface);
+ }
}
/**
* Connect the transport to the local hicn forwarder.
*
- * @param is_consumer - Boolean specifying if the application on top of portal
- * is a consumer or a producer.
+ * @param is_consumer - Boolean specifying if the application on top of
+ * portal is a consumer or a producer.
*/
- TRANSPORT_ALWAYS_INLINE void connect(bool is_consumer = true) {
- if (!io_module_) {
- pending_interest_hash_table_.reserve(portal_details::pit_size);
- io_module_.reset(IoModule::load(io_module_path_.c_str()));
-
- CHECK(io_module_);
-
- io_module_->init(std::bind(&Portal::processIncomingMessages, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3),
- std::bind(&Portal::setLocalRoutes, this), io_service_,
- app_name_);
- io_module_->connect(is_consumer);
- is_consumer_ = is_consumer;
+ void connect(bool is_consumer = true) {
+ if (isConnected()) {
+ return;
}
+
+ worker_.addAndWaitForExecution([this, is_consumer]() {
+ if (!io_module_) {
+ pending_interest_hash_table_.reserve(portal_details::pit_size);
+ io_module_.reset(IoModule::load(io_module_path_.c_str()));
+
+ CHECK(io_module_);
+
+ std::weak_ptr<Portal> self(shared_from_this());
+
+ io_module_->init(
+ [self](Connector *c, const std::vector<utils::MemBuf::Ptr> &buffers,
+ const std::error_code &ec) {
+ if (auto ptr = self.lock()) {
+ ptr->processIncomingMessages(c, buffers, ec);
+ }
+ },
+ [self](Connector *c, const std::error_code &ec) {
+ if (!ec) {
+ return;
+ }
+ auto ptr = self.lock();
+ if (ptr && ptr->transport_callback_) {
+ ptr->transport_callback_->onError(ec);
+ }
+ },
+ [self](Connector *c, const std::error_code &ec) {
+ auto ptr = self.lock();
+ if (ptr) {
+ if (ec && ptr->transport_callback_) {
+ ptr->transport_callback_->onError(ec);
+ return;
+ }
+ ptr->setLocalRoutes();
+ }
+ },
+ worker_.getIoService(), app_name_);
+
+ io_module_->connect(is_consumer);
+ is_consumer_ = is_consumer;
+ }
+ });
}
/**
@@ -295,18 +299,13 @@ class Portal {
~Portal() { killConnection(); }
/**
- * Compute name hash
- */
- TRANSPORT_ALWAYS_INLINE uint32_t getHash(const Name &name) {
- return name.getHash32(false) + name.getSuffix();
- }
-
- /**
* Check if there is already a pending interest for a given name.
*
* @param name - The interest name.
*/
- TRANSPORT_ALWAYS_INLINE bool interestIsPending(const Name &name) {
+ bool interestIsPending(const Name &name) {
+ DCHECK(std::this_thread::get_id() == worker_.getThreadId());
+
auto it = pending_interest_hash_table_.find(getHash(name));
if (it != pending_interest_hash_table_.end()) {
return true;
@@ -321,19 +320,21 @@ class Portal {
* @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_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.
*/
- TRANSPORT_ALWAYS_INLINE void sendInterest(
+ void sendInterest(
Interest::Ptr &&interest,
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);
@@ -346,35 +347,42 @@ class Portal {
uint32_t counter = 0;
// Set timers
do {
- auto pending_interest = packet_pool_.getPendingInterest();
- pending_interest->setInterest(interest);
+ if (suffix) {
+ hash = initial_hash + *suffix;
+ seq = *suffix;
+ suffix++;
+ }
+
+ 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;
+ }
+
pending_interest->setOnContentObjectCallback(
std::move(on_content_object_callback));
pending_interest->setOnTimeoutCallback(
std::move(on_interest_timeout_callback));
+ auto self = weak_from_this();
pending_interest->startCountdown(
portal_details::makeCustomAllocatorHandler(
async_callback_memory_,
- std::bind(&Portal::timerHandler, this, std::placeholders::_1,
- hash, seq)));
+ [self, hash, seq](const std::error_code &ec) {
+ if (TRANSPORT_EXPECT_FALSE(ec.operator bool())) {
+ return;
+ }
- auto it = pending_interest_hash_table_.find(hash);
- if (it != pending_interest_hash_table_.end()) {
- it->second->cancelTimer();
-
- // Get reference to interest packet in order to have it destroyed.
- auto _int = it->second->getInterest();
- it->second = std::move(pending_interest);
- } else {
- pending_interest_hash_table_[hash] = std::move(pending_interest);
- }
-
- if (suffix) {
- hash = initial_hash + *suffix;
- seq = *suffix;
- suffix++;
- }
+ if (auto ptr = self.lock()) {
+ ptr->timerHandler(hash, seq);
+ }
+ }));
} while (counter++ < n_suffixes);
}
@@ -385,214 +393,174 @@ class Portal {
* @param ec - Error code which says whether the timer expired or has been
* canceled upon data packet reception.
*
- * @param hash - The index of the interest in the pending interest hash table.
+ * @param hash - The index of the interest in the pending interest hash
+ * table.
*/
- TRANSPORT_ALWAYS_INLINE void timerHandler(const std::error_code &ec,
- uint32_t hash, uint32_t seq) {
- bool is_stopped = io_service_.stopped();
- if (TRANSPORT_EXPECT_FALSE(is_stopped)) {
- return;
- }
+ void timerHandler(uint32_t hash, uint32_t seq) {
+ PendingInterestHashTable::iterator it =
+ pending_interest_hash_table_.find(hash);
+ if (it != pending_interest_hash_table_.end()) {
+ PendingInterest &pend_interest = it->second;
+ auto _int = pend_interest.getInterest();
+ auto callback = pend_interest.getOnTimeoutCallback();
+ pending_interest_hash_table_.erase(it);
+ Name &name = const_cast<Name &>(_int->getName());
+ name.setSuffix(seq);
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- PendingInterestHashTable::iterator it =
- pending_interest_hash_table_.find(hash);
- if (it != pending_interest_hash_table_.end()) {
- PendingInterest::Ptr ptr = std::move(it->second);
- pending_interest_hash_table_.erase(it);
- auto _int = ptr->getInterest();
- Name &name = const_cast<Name &>(_int->getName());
- name.setSuffix(seq);
-
- if (ptr->getOnTimeoutCallback() != UNSET_CALLBACK) {
- ptr->on_interest_timeout_callback_(_int, name);
- } else if (consumer_callback_) {
- consumer_callback_->onTimeout(_int, name);
- }
+ if (callback != UNSET_CALLBACK) {
+ callback(_int, name);
+ } else if (transport_callback_) {
+ transport_callback_->onTimeout(_int, name);
}
}
}
/**
- * Register a producer name to the local forwarder and optionally set the
- * content store size in a per-face manner.
- *
- * @param config - The configuration for the local forwarder binding.
- */
- TRANSPORT_ALWAYS_INLINE void bind(const BindConfig &config) {
- assert(io_module_);
- io_module_->setContentStoreSize(config.csReserved());
- served_namespaces_.push_back(config.prefix());
- setLocalRoutes();
- }
-
- /**
- * Start the event loop. This function blocks here and calls the callback set
- * by the application upon interest/data received or timeout.
- */
- TRANSPORT_ALWAYS_INLINE void runEventsLoop() {
- if (io_service_.stopped()) {
- io_service_.reset(); // ensure that run()/poll() will do some work
- }
-
- io_service_.run();
- }
-
- /**
- * Run one event and return.
- */
- TRANSPORT_ALWAYS_INLINE void runOneEvent() {
- if (io_service_.stopped()) {
- io_service_.reset(); // ensure that run()/poll() will do some work
- }
-
- io_service_.run_one();
- }
-
- /**
- * Send a data packet to the local forwarder. As opposite to sendInterest, the
- * ownership of the content object is not transferred to the portal.
+ * Send a data packet to the local forwarder.
*
* @param content_object - The data packet.
*/
- TRANSPORT_ALWAYS_INLINE void sendContentObject(
- ContentObject &content_object) {
+ void sendContentObject(ContentObject &content_object) {
+ DCHECK(io_module_);
+ DCHECK(std::this_thread::get_id() == worker_.getThreadId());
+
io_module_->send(content_object);
}
/**
- * Stop the event loop, canceling all the pending events in the event queue.
- *
- * Beware that stopping the event loop DOES NOT disconnect the transport from
- * the local forwarder, the connector underneath will stay connected.
+ * Disconnect the transport from the local forwarder.
*/
- TRANSPORT_ALWAYS_INLINE void stopEventsLoop() {
- if (!io_service_.stopped()) {
- io_service_.dispatch([this]() {
- clear();
- io_service_.stop();
- });
+ void killConnection() {
+ if (TRANSPORT_EXPECT_TRUE(io_module_ != nullptr)) {
+ io_module_->closeConnection();
}
}
/**
- * Disconnect the transport from the local forwarder.
+ * Clear the pending interest hash table.
*/
- TRANSPORT_ALWAYS_INLINE void killConnection() {
- io_module_->closeConnection();
+ void clear() {
+ worker_.tryRunHandlerNow([self{shared_from_this()}]() { self->doClear(); });
}
/**
- * Clear the pending interest hash table.
+ * Get a reference to the io_service object.
*/
- TRANSPORT_ALWAYS_INLINE void clear() {
- if (!io_service_.stopped()) {
- io_service_.dispatch(std::bind(&Portal::doClear, this));
- } else {
- doClear();
- }
- }
+ utils::EventThread &getThread() { return worker_; }
/**
- * Remove one pending interest.
+ * Register a route to the local forwarder.
*/
- TRANSPORT_ALWAYS_INLINE void clearOne(const Name &name) {
- if (!io_service_.stopped()) {
- io_service_.dispatch(std::bind(&Portal::doClearOne, this, name));
- } else {
- doClearOne(name);
- }
+ void registerRoute(const Prefix &prefix) {
+ std::weak_ptr<Portal> self = shared_from_this();
+ worker_.tryRunHandlerNow([self, prefix]() {
+ if (auto ptr = self.lock()) {
+ auto ret = ptr->served_namespaces_.insert(prefix);
+ if (ret.second && ptr->io_module_ && ptr->io_module_->isConnected()) {
+ ptr->io_module_->registerRoute(prefix);
+ }
+ }
+ });
}
/**
- * Get a reference to the io_service object.
+ * Send a MAP-Me update to traverse NATs.
*/
- TRANSPORT_ALWAYS_INLINE asio::io_service &getIoService() {
- return io_service_;
+ TRANSPORT_ALWAYS_INLINE void sendMapme() {
+ if (io_module_->isConnected()) {
+ io_module_->sendMapme();
+ }
}
/**
- * Register a route to the local forwarder.
+ * set forwarding strategy
*/
- TRANSPORT_ALWAYS_INLINE void registerRoute(Prefix &prefix) {
- served_namespaces_.push_back(prefix);
+ TRANSPORT_ALWAYS_INLINE void setForwardingStrategy(Prefix &prefix,
+ std::string &strategy) {
if (io_module_->isConnected()) {
- io_module_->registerRoute(prefix);
+ io_module_->setForwardingStrategy(prefix, strategy);
}
}
/**
* Check if the transport is connected to a forwarder or not
*/
- TRANSPORT_ALWAYS_INLINE bool isConnectedToFwd() {
+ bool isConnectedToFwd() {
std::string mod = io_module_path_.substr(0, io_module_path_.find("."));
if (mod == "forwarder_module") return false;
return true;
}
+ auto &getServedNamespaces() { return served_namespaces_; }
+
private:
/**
- * Clear the pending interest hash table.
+ * Compute name hash
*/
- TRANSPORT_ALWAYS_INLINE void doClear() {
- for (auto &pend_interest : pending_interest_hash_table_) {
- pend_interest.second->cancelTimer();
-
- // Get interest packet from pending interest and do nothing with it. It
- // will get destroyed as it goes out of scope.
- auto _int = pend_interest.second->getInterest();
- }
-
- pending_interest_hash_table_.clear();
+ uint32_t getHash(const Name &name) {
+ return name.getHash32(false) + name.getSuffix();
}
/**
- * Remove one pending interest.
+ * Clear the pending interest hash table.
*/
- TRANSPORT_ALWAYS_INLINE void doClearOne(const Name &name) {
- auto it = pending_interest_hash_table_.find(getHash(name));
-
- if (it != pending_interest_hash_table_.end()) {
- it->second->cancelTimer();
-
- // Get interest packet from pending interest and do nothing with it. It
- // will get destroyed as it goes out of scope.
- auto _int = it->second->getInterest();
-
- pending_interest_hash_table_.erase(it);
+ void doClear() {
+ for (auto &pend_interest : pending_interest_hash_table_) {
+ pend_interest.second.cancelTimer();
}
+
+ pending_interest_hash_table_.clear();
}
/**
- * Callback called by the underlying connector upon reception of a packet from
- * the local forwarder.
+ * Callback called by the underlying connector upon reception of a packet
+ * from the local forwarder.
*
* @param packet_buffer - The bytes of the packet.
*/
- TRANSPORT_ALWAYS_INLINE void processIncomingMessages(
- Connector *c, utils::MemBuf &buffer, const std::error_code &ec) {
- bool is_stopped = io_service_.stopped();
- if (TRANSPORT_EXPECT_FALSE(is_stopped)) {
+ void processIncomingMessages(Connector *c,
+ const std::vector<utils::MemBuf::Ptr> &buffers,
+ const std::error_code &ec) {
+ if (!transport_callback_) {
return;
}
- if (TRANSPORT_EXPECT_FALSE(io_module_->isControlMessage(buffer.data()))) {
- processControlMessage(buffer);
+ if (TRANSPORT_EXPECT_FALSE(ec.operator bool())) {
+ // Error receiving from underlying infra.
+ if (transport_callback_) {
+ transport_callback_->onError(ec);
+ }
+
return;
}
- // The buffer is a base class for an interest or a content object
- Packet &packet_buffer = static_cast<Packet &>(buffer);
+ for (auto &buffer_ptr : buffers) {
+ auto &buffer = *buffer_ptr;
+
+ if (TRANSPORT_EXPECT_FALSE(io_module_->isControlMessage(buffer))) {
+ processControlMessage(buffer);
+ return;
+ }
- auto format = packet_buffer.getFormat();
- if (TRANSPORT_EXPECT_TRUE(_is_tcp(format))) {
- if (is_consumer_) {
- processContentObject(static_cast<ContentObject &>(packet_buffer));
+ auto format = Packet::getFormatFromBuffer(buffer.data(), buffer.length());
+ if (TRANSPORT_EXPECT_TRUE(_is_cmpr(format) || _is_tcp(format))) {
+ // The buffer is a base class for an interest or a content object
+ Packet &packet_buffer = static_cast<Packet &>(buffer);
+ if (is_consumer_ && !packet_buffer.isInterest()) {
+ processContentObject(static_cast<ContentObject &>(packet_buffer));
+ } else if (!is_consumer_ && packet_buffer.isInterest()) {
+ processInterest(static_cast<Interest &>(packet_buffer));
+ } else {
+ auto packet_type =
+ packet_buffer.isInterest() ? "Interest" : "ContentObject";
+ auto socket_type = is_consumer_ ? "consumer " : "producer ";
+ LOG(ERROR) << "Received a " << packet_type << " packet with name "
+ << packet_buffer.getName() << " in a " << socket_type
+ << " transport. Ignoring it.";
+ }
} else {
- processInterest(static_cast<Interest &>(packet_buffer));
+ LOG(ERROR) << "Received not supported packet. Ignoring it.";
}
- } else {
- LOG(ERROR) << "Received not supported packet. Ignoring it.";
}
}
@@ -601,19 +569,21 @@ class Portal {
* It register the prefixes in the served_namespaces_ list to the local
* forwarder.
*/
- TRANSPORT_ALWAYS_INLINE void setLocalRoutes() {
+ void setLocalRoutes() {
+ DCHECK(io_module_);
+ DCHECK(io_module_->isConnected());
+ DCHECK(std::this_thread::get_id() == worker_.getThreadId());
+
for (auto &prefix : served_namespaces_) {
- if (io_module_->isConnected()) {
- io_module_->registerRoute(prefix);
- }
+ io_module_->registerRoute(prefix);
}
}
- TRANSPORT_ALWAYS_INLINE void processInterest(Interest &interest) {
+ void processInterest(Interest &interest) {
// Interest for a producer
DLOG_IF(INFO, VLOG_IS_ON(3)) << "processInterest " << interest.getName();
- if (TRANSPORT_EXPECT_TRUE(producer_callback_ != nullptr)) {
- producer_callback_->onInterest(interest);
+ if (TRANSPORT_EXPECT_TRUE(transport_callback_ != nullptr)) {
+ transport_callback_->onInterest(interest);
}
}
@@ -625,8 +595,7 @@ class Portal {
*
* @param content_object - The data packet
*/
- TRANSPORT_ALWAYS_INLINE void processContentObject(
- ContentObject &content_object) {
+ void processContentObject(ContentObject &content_object) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "processContentObject " << content_object.getName();
uint32_t hash = getHash(content_object.getName());
@@ -635,15 +604,16 @@ class Portal {
if (it != pending_interest_hash_table_.end()) {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Found pending interest.";
- PendingInterest::Ptr interest_ptr = std::move(it->second);
+ PendingInterest &pend_interest = it->second;
+ pend_interest.cancelTimer();
+ auto _int = pend_interest.getInterest();
+ auto callback = pend_interest.getOnDataCallback();
pending_interest_hash_table_.erase(it);
- interest_ptr->cancelTimer();
- auto _int = interest_ptr->getInterest();
- if (interest_ptr->getOnDataCallback() != UNSET_CALLBACK) {
- interest_ptr->on_content_object_callback_(*_int, content_object);
- } else if (consumer_callback_) {
- consumer_callback_->onContentObject(*_int, content_object);
+ 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))
@@ -652,12 +622,11 @@ class Portal {
}
/**
- * Process a control message. Control messages are different depending on the
- * connector, then the forwarder_interface will do the job of understanding
- * them.
+ * Process a control message. Control messages are different depending on
+ * the connector, then the forwarder_interface will do the job of
+ * understanding them.
*/
- TRANSPORT_ALWAYS_INLINE void processControlMessage(
- utils::MemBuf &packet_buffer) {
+ void processControlMessage(utils::MemBuf &packet_buffer) {
io_module_->processControlMessageReply(packet_buffer);
}
@@ -665,17 +634,14 @@ class Portal {
portal_details::HandlerMemory async_callback_memory_;
std::unique_ptr<IoModule, void (*)(IoModule *)> io_module_;
- asio::io_service &io_service_;
- asio::io_service internal_io_service_;
- portal_details::Pool packet_pool_;
+ ::utils::EventThread &worker_;
std::string app_name_;
PendingInterestHashTable pending_interest_hash_table_;
- std::list<Prefix> served_namespaces_;
+ std::set<Prefix> served_namespaces_;
- ConsumerCallback *consumer_callback_;
- ProducerCallback *producer_callback_;
+ TransportCallback *transport_callback_;
bool is_consumer_;
diff --git a/libtransport/src/core/prefix.cc b/libtransport/src/core/prefix.cc
index d598cff75..4c1e191e9 100644
--- a/libtransport/src/core/prefix.cc
+++ b/libtransport/src/core/prefix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -99,6 +99,14 @@ void Prefix::buildPrefix(std::string &prefix, uint16_t prefix_length,
ip_prefix_.family = family;
}
+bool Prefix::operator<(const Prefix &other) const {
+ return ip_prefix_cmp(&ip_prefix_, &other.ip_prefix_) < 0;
+}
+
+bool Prefix::operator==(const Prefix &other) const {
+ return ip_prefix_cmp(&ip_prefix_, &other.ip_prefix_) == 0;
+}
+
std::unique_ptr<Sockaddr> Prefix::toSockaddr() const {
Sockaddr *ret = nullptr;
@@ -211,8 +219,6 @@ Name Prefix::getName(const core::Name &mask, const core::Name &components,
}
}
- // if (this->contains(name_ip))
- // throw errors::RuntimeException("Mask overrides the prefix");
return Name(ip_prefix_.family, (uint8_t *)&name_ip);
}
@@ -279,8 +285,6 @@ Prefix &Prefix::setNetwork(std::string &network) {
}
Name Prefix::makeRandomName() const {
- srand((unsigned int)time(nullptr));
-
if (ip_prefix_.family == AF_INET6) {
std::default_random_engine eng((std::random_device())());
std::uniform_int_distribution<uint32_t> idis(
diff --git a/libtransport/src/core/tcp_socket_connector.cc b/libtransport/src/core/tcp_socket_connector.cc
index a30264271..7758e2cf2 100644
--- a/libtransport/src/core/tcp_socket_connector.cc
+++ b/libtransport/src/core/tcp_socket_connector.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -85,8 +85,10 @@ void TcpSocketConnector::send(const uint8_t *packet, std::size_t len,
const PacketSentCallback &packet_sent) {
if (packet_sent != 0) {
asio::async_write(socket_, asio::buffer(packet, len),
- [packet_sent](std::error_code ec,
- std::size_t /*length*/) { packet_sent(); });
+ [packet_sent](const std::error_code &ec)
+ std::size_t /*length*/) {
+ packet_sent();
+ });
} else {
if (state_ == ConnectorState::CONNECTED) {
asio::write(socket_, asio::buffer(packet, len));
@@ -151,7 +153,7 @@ void TcpSocketConnector::doWrite() {
asio::async_write(
socket_, std::move(array),
- [this, packet_store = std::move(packet_store)](std::error_code ec,
+ [this, packet_store = std::move(packet_store)](const std::error_code &ec,
std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
if (!output_buffer_.empty()) {
@@ -172,7 +174,7 @@ void TcpSocketConnector::doReadBody(std::size_t body_length) {
asio::async_read(
socket_, asio::buffer(read_msg_->writableTail(), body_length),
asio::transfer_exactly(body_length),
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
read_msg_->append(length);
if (TRANSPORT_EXPECT_TRUE(!ec)) {
receive_callback_(std::move(read_msg_));
@@ -195,7 +197,7 @@ void TcpSocketConnector::doReadHeader() {
asio::buffer(read_msg_->writableData(),
NetworkMessage::fixed_header_length),
asio::transfer_exactly(NetworkMessage::fixed_header_length),
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
read_msg_->append(NetworkMessage::fixed_header_length);
std::size_t body_length = 0;
@@ -235,7 +237,7 @@ void TcpSocketConnector::tryReconnect() {
void TcpSocketConnector::doConnect() {
asio::async_connect(
socket_, endpoint_iterator_,
- [this](std::error_code ec, tcp::resolver::iterator) {
+ [this](const std::error_code &ec, tcp::resolver::iterator) {
if (!ec) {
timer_.cancel();
state_ = ConnectorState::CONNECTED;
diff --git a/libtransport/src/core/tcp_socket_connector.h b/libtransport/src/core/tcp_socket_connector.h
index 21db8301e..2901a5c9d 100644
--- a/libtransport/src/core/tcp_socket_connector.h
+++ b/libtransport/src/core/tcp_socket_connector.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/core/udp_connector.cc b/libtransport/src/core/udp_connector.cc
new file mode 100644
index 000000000..ee0c7ea9c
--- /dev/null
+++ b/libtransport/src/core/udp_connector.cc
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#include <core/errors.h>
+#include <core/udp_connector.h>
+#include <glog/logging.h>
+#include <hicn/transport/utils/branch_prediction.h>
+
+#include <iostream>
+#include <thread>
+#include <vector>
+
+namespace transport {
+namespace core {
+
+UdpTunnelConnector::~UdpTunnelConnector() {}
+
+void UdpTunnelConnector::connect(const std::string &hostname, uint16_t port,
+ const std::string &bind_address,
+ uint16_t bind_port) {
+ if (state_ == State::CLOSED) {
+ state_ = State::CONNECTING;
+
+ asio::ip::udp::resolver::query query(asio::ip::udp::v4(), hostname,
+ std::to_string(port));
+
+ endpoint_iterator_ = resolver_.resolve(query);
+ remote_endpoint_send_ = *endpoint_iterator_;
+ socket_->open(remote_endpoint_send_.protocol());
+
+ if (!bind_address.empty() && bind_port != 0) {
+ using namespace asio::ip;
+
+ auto address = address::from_string(bind_address);
+ if (address.is_v6()) {
+ std::error_code ec;
+ socket_->set_option(asio::ip::v6_only(false), ec);
+ // Call succeeds only on dual stack systems.
+ }
+
+ socket_->bind(udp::endpoint(address, bind_port));
+ }
+
+ remote_endpoint_ = Endpoint(remote_endpoint_send_);
+ local_endpoint_ = Endpoint(socket_->local_endpoint());
+
+ auto self = shared_from_this();
+ doConnect(self);
+ }
+}
+
+void UdpTunnelConnector::send(Packet &packet) {
+ send(packet.shared_from_this());
+}
+
+void UdpTunnelConnector::send(const utils::MemBuf::Ptr &buffer) {
+ auto self = shared_from_this();
+ io_service_.post([self, pkt{buffer}]() {
+ bool write_in_progress = !self->output_buffer_.empty();
+ self->output_buffer_.push_back(std::move(pkt));
+ if (TRANSPORT_EXPECT_TRUE(self->state_ == State::CONNECTED)) {
+ if (!write_in_progress) {
+ self->doSendPacket(self);
+ }
+ } else {
+ self->data_available_ = true;
+ }
+ });
+}
+
+void UdpTunnelConnector::close() {
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "UDPTunnelConnector::close";
+ state_ = State::CLOSED;
+ bool is_socket_owned = socket_.use_count() == 1;
+ if (is_socket_owned) {
+ // Here we use a shared ptr to keep the object alive until we call the close
+ // function
+ auto self = shared_from_this();
+ io_service_.dispatch([this, self]() {
+ socket_->close();
+ // on_close_callback_(shared_from_this());
+ });
+ }
+}
+
+void UdpTunnelConnector::doSendPacket(
+ const std::shared_ptr<UdpTunnelConnector> &self) {
+#ifdef LINUX
+ send_timer_.expires_from_now(std::chrono::microseconds(50));
+ send_timer_.async_wait([self](const std::error_code &ec) {
+ if (ec) {
+ return;
+ }
+
+ self->writeHandler();
+ });
+#else
+ auto packet = output_buffer_.front().get();
+ auto array = std::vector<asio::const_buffer>();
+
+ const ::utils::MemBuf *current = packet;
+ do {
+ array.push_back(asio::const_buffer(current->data(), current->length()));
+ current = current->next();
+ } while (current != packet);
+
+ socket_->async_send_to(
+ std::move(array), remote_endpoint_send_,
+ [this, self](const std::error_code &ec, std::size_t length) {
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ sent_callback_(this, make_error_code(core_error::success));
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::operation_canceled)) {
+ // The connection has been closed by the application.
+ return;
+ } else {
+ sendFailed();
+ sent_callback_(this, ec);
+ }
+
+ output_buffer_.pop_front();
+ if (!output_buffer_.empty()) {
+ doSendPacket(self);
+ }
+ });
+#endif
+}
+
+void UdpTunnelConnector::retryConnection() {
+ // The connection was refused. In this case let's retry to reconnect.
+ connection_reattempts_++;
+ LOG(ERROR) << "Error in UDP: Connection refused. Retrying...";
+ state_ = State::CONNECTING;
+ timer_.expires_from_now(std::chrono::milliseconds(500));
+ std::weak_ptr<UdpTunnelConnector> self = shared_from_this();
+ timer_.async_wait([self, this](const std::error_code &ec) {
+ if (ec) {
+ }
+ if (auto ptr = self.lock()) {
+ doConnect(ptr);
+ }
+ });
+ return;
+}
+
+#ifdef LINUX
+void UdpTunnelConnector::writeHandler() {
+ if (TRANSPORT_EXPECT_FALSE(state_ != State::CONNECTED)) {
+ return;
+ }
+
+ auto len = std::min(output_buffer_.size(), std::size_t(Connector::max_burst));
+
+ if (len) {
+ int m = 0;
+ for (auto &p : output_buffer_) {
+ auto packet = p.get();
+ ::utils::MemBuf *current = packet;
+ int b = 0;
+ do {
+ // array.push_back(asio::const_buffer(current->data(),
+ // current->length()));
+ tx_iovecs_[m][b].iov_base = current->writableData();
+ tx_iovecs_[m][b].iov_len = current->length();
+ current = current->next();
+ b++;
+ } while (current != packet);
+
+ tx_msgs_[m].msg_hdr.msg_iov = tx_iovecs_[m];
+ tx_msgs_[m].msg_hdr.msg_iovlen = b;
+ tx_msgs_[m].msg_hdr.msg_name = remote_endpoint_send_.data();
+ tx_msgs_[m].msg_hdr.msg_namelen = remote_endpoint_send_.size();
+ m++;
+
+ if (--len == 0) {
+ break;
+ }
+ }
+
+ int retval = sendmmsg(socket_->native_handle(), tx_msgs_, m, MSG_DONTWAIT);
+ if (retval > 0) {
+ while (retval--) {
+ output_buffer_.pop_front();
+ }
+ } else if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ LOG(ERROR) << "Error sending messages: " << strerror(errno);
+ sent_callback_(this, make_error_code(core_error::send_failed));
+ return;
+ }
+ }
+
+ if (!output_buffer_.empty()) {
+ send_timer_.expires_from_now(std::chrono::microseconds(50));
+ std::weak_ptr<UdpTunnelConnector> self = shared_from_this();
+ send_timer_.async_wait([self](const std::error_code &ec) {
+ if (ec) {
+ return;
+ }
+ if (auto ptr = self.lock()) {
+ ptr->writeHandler();
+ }
+ });
+ }
+}
+
+void UdpTunnelConnector::readHandler(const std::error_code &ec) {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
+
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ if (current_position_ == 0) {
+ for (int i = 0; i < max_burst; i++) {
+ auto read_buffer = getRawBuffer();
+ rx_iovecs_[i][0].iov_base = read_buffer.first;
+ rx_iovecs_[i][0].iov_len = read_buffer.second;
+ rx_msgs_[i].msg_hdr.msg_iov = rx_iovecs_[i];
+ rx_msgs_[i].msg_hdr.msg_iovlen = 1;
+ }
+ }
+
+ int res = recvmmsg(socket_->native_handle(), rx_msgs_ + current_position_,
+ max_burst - current_position_, MSG_DONTWAIT, nullptr);
+ if (res < 0) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ // Try again later
+ return;
+ }
+
+ if (errno == ECONNREFUSED &&
+ connection_reattempts_ < max_reconnection_reattempts) {
+ retryConnection();
+ return;
+ }
+
+ LOG(ERROR) << "Error receiving messages! " << strerror(errno) << " "
+ << res;
+ std::vector<utils::MemBuf::Ptr> v;
+ auto ec = make_error_code(core_error::receive_failed);
+
+ receive_callback_(this, v, ec);
+ return;
+ }
+
+ std::vector<utils::MemBuf::Ptr> v;
+ v.reserve(res);
+ for (int i = 0; i < res; i++) {
+ auto packet = getPacketFromBuffer(
+ reinterpret_cast<uint8_t *>(
+ rx_msgs_[current_position_].msg_hdr.msg_iov[0].iov_base),
+ rx_msgs_[current_position_].msg_len);
+ receiveSuccess(*packet);
+ v.push_back(std::move(packet));
+ ++current_position_;
+ }
+
+ receive_callback_(this, v, make_error_code(core_error::success));
+
+ doRecvPacket();
+ } else {
+ LOG(ERROR) << "Error in UDP: Receiving packets from a not "
+ "connected socket.";
+ }
+ } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
+ LOG(ERROR) << "The connection has been closed by the application.";
+ return;
+ } else {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ // receive_callback_(this, *read_msg_, ec);
+ LOG(ERROR) << "Error in UDP connector: " << ec.value() << " "
+ << ec.message();
+ } else {
+ LOG(ERROR) << "Error in connector while not connected. " << ec.value()
+ << " " << ec.message();
+ }
+ }
+}
+#endif
+
+void UdpTunnelConnector::doRecvPacket() {
+ std::weak_ptr<UdpTunnelConnector> self = shared_from_this();
+#ifdef LINUX
+ if (state_ == State::CONNECTED) {
+#if ((ASIO_VERSION / 100 % 1000) < 11)
+ socket_->async_receive(asio::null_buffers(),
+#else
+ socket_->async_wait(asio::ip::tcp::socket::wait_read,
+#endif
+ [self](const std::error_code &ec) {
+ if (ec) {
+ LOG(ERROR)
+ << "Error in UDP connector: " << ec.value()
+ << " " << ec.message();
+ return;
+ }
+ if (auto ptr = self.lock()) {
+ ptr->readHandler(ec);
+ }
+ });
+ }
+#else
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
+ read_msg_ = getRawBuffer();
+ socket_->async_receive_from(
+ asio::buffer(read_msg_.first, read_msg_.second), remote_endpoint_recv_,
+ [this, self](const std::error_code &ec, std::size_t length) {
+ if (auto ptr = self.lock()) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "UdpTunnelConnector received packet length=" << length;
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ auto packet = getPacketFromBuffer(read_msg_.first, length);
+ receiveSuccess(*packet);
+ std::vector<utils::MemBuf::Ptr> v{std::move(packet)};
+ receive_callback_(this, v, make_error_code(core_error::success));
+ doRecvPacket();
+ } else {
+ LOG(ERROR) << "Error in UDP: Receiving packets from a not "
+ "connected socket.";
+ }
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::operation_canceled)) {
+ LOG(ERROR) << "The connection has been closed by the application.";
+ return;
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::connection_refused)) {
+ if (connection_reattempts_ < max_reconnection_reattempts) {
+ retryConnection();
+ }
+ } else {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ LOG(ERROR) << "Error in UDP connector: " << ec.value()
+ << ec.message();
+ } else {
+ LOG(ERROR) << "Error while not connected";
+ }
+ }
+ }
+ });
+#endif
+}
+
+void UdpTunnelConnector::doConnect(
+ std::shared_ptr<UdpTunnelConnector> &self_shared) {
+ std::weak_ptr<UdpTunnelConnector> self = self_shared;
+ asio::async_connect(*socket_, endpoint_iterator_,
+ [this, self](const std::error_code &ec,
+ asio::ip::udp::resolver::iterator) {
+ if (auto ptr = self.lock()) {
+ if (!ec) {
+ state_ = State::CONNECTED;
+ doRecvPacket();
+
+ if (data_available_) {
+ data_available_ = false;
+ doSendPacket(ptr);
+ }
+
+ on_reconnect_callback_(
+ this, make_error_code(core_error::success));
+ } else {
+ LOG(ERROR) << "UDP Connection failed!!!";
+ retryConnection();
+ }
+ }
+ });
+}
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel.h b/libtransport/src/core/udp_connector.h
index 4f044f93f..65821852d 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel.h
+++ b/libtransport/src/core/udp_connector.h
@@ -1,13 +1,13 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
*/
#pragma once
+#include <core/errors.h>
#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/portability/platform.h>
-#include <io_modules/forwarder/errors.h>
#include <iostream>
#include <memory>
@@ -30,16 +30,15 @@ class UdpTunnelConnector : public Connector {
: Connector(receive_callback, packet_sent, on_close_callback,
on_reconnect),
io_service_(io_service),
- strand_(std::make_shared<asio::io_service::strand>(io_service_)),
socket_(std::make_shared<asio::ip::udp::socket>(io_service_)),
resolver_(io_service_),
timer_(io_service_),
#ifdef LINUX
send_timer_(io_service_),
- tx_iovecs_{0},
- tx_msgs_{0},
- rx_iovecs_{0},
- rx_msgs_{0},
+ tx_iovecs_{},
+ tx_msgs_{},
+ rx_iovecs_{},
+ rx_msgs_{},
current_position_(0),
#else
read_msg_(nullptr, 0),
@@ -61,17 +60,16 @@ class UdpTunnelConnector : public Connector {
#else
io_service_((asio::io_context &)(socket->get_executor().context())),
#endif
- strand_(strand),
socket_(socket),
resolver_(io_service_),
remote_endpoint_send_(std::forward<EndpointType &&>(remote_endpoint)),
timer_(io_service_),
#ifdef LINUX
send_timer_(io_service_),
- tx_iovecs_{0},
- tx_msgs_{0},
- rx_iovecs_{0},
- rx_msgs_{0},
+ tx_iovecs_{},
+ tx_msgs_{},
+ rx_iovecs_{},
+ rx_msgs_{},
current_position_(0),
#else
read_msg_(nullptr, 0),
@@ -88,7 +86,7 @@ class UdpTunnelConnector : public Connector {
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
void close() override;
@@ -99,26 +97,27 @@ class UdpTunnelConnector : public Connector {
auto shared_from_this() { return utils::shared_from(this); }
private:
- void doConnect();
+ void retryConnection();
+ void doConnect(std::shared_ptr<UdpTunnelConnector> &self);
void doRecvPacket();
- void doRecvPacket(utils::MemBuf &buffer) {
- receive_callback_(this, buffer, make_error_code(forwarder_error::success));
+ void doRecvPacket(utils::MemBuf::Ptr &buffer) {
+ std::vector<utils::MemBuf::Ptr> v{std::move(buffer)};
+ receive_callback_(this, v, make_error_code(core_error::success));
}
#ifdef LINUX
- void readHandler(std::error_code ec);
- void writeHandler(std::error_code ec);
+ void readHandler(const std::error_code &ec);
+ void writeHandler();
#endif
void setConnected() { state_ = State::CONNECTED; }
- void doSendPacket();
+ void doSendPacket(const std::shared_ptr<UdpTunnelConnector> &self);
void doClose();
private:
asio::io_service &io_service_;
- std::shared_ptr<asio::io_service::strand> strand_;
std::shared_ptr<asio::ip::udp::socket> socket_;
asio::ip::udp::resolver resolver_;
asio::ip::udp::resolver::iterator endpoint_iterator_;
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc b/libtransport/src/core/udp_listener.cc
index d047cc568..c67673392 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc
+++ b/libtransport/src/core/udp_listener.cc
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
*/
+#include <core/udp_connector.h>
+#include <core/udp_listener.h>
#include <glog/logging.h>
#include <hicn/transport/utils/hash.h>
-#include <io_modules/forwarder/udp_tunnel.h>
-#include <io_modules/forwarder/udp_tunnel_listener.h>
#ifndef LINUX
namespace std {
@@ -35,7 +35,7 @@ void UdpTunnelListener::close() {
}
#ifdef LINUX
-void UdpTunnelListener::readHandler(std::error_code ec) {
+void UdpTunnelListener::readHandler(const std::error_code &ec) {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
if (TRANSPORT_EXPECT_TRUE(!ec)) {
@@ -102,7 +102,8 @@ void UdpTunnelListener::readHandler(std::error_code ec) {
std::make_shared<UdpTunnelConnector>(
socket_, strand_, receive_callback_,
[](Connector *, const std::error_code &) {}, [](Connector *) {},
- [](Connector *) {}, std::move(remote_endpoint_)));
+ [](Connector *, const std::error_code &) {},
+ std::move(remote_endpoint_)));
connector = ret.first;
connector->second->setConnectorId(connector_id);
}
@@ -112,7 +113,7 @@ void UdpTunnelListener::readHandler(std::error_code ec) {
*/
UdpTunnelConnector *c =
dynamic_cast<UdpTunnelConnector *>(connector->second.get());
- c->doRecvPacket(*packet);
+ c->doRecvPacket(packet);
++current_position_;
}
@@ -141,7 +142,7 @@ void UdpTunnelListener::doRecvPacket() {
read_msg_ = Connector::getRawBuffer();
socket_->async_receive_from(
asio::buffer(read_msg_.first, read_msg_.second), remote_endpoint_,
- [this](std::error_code ec, std::size_t length) {
+ [this](const std::error_code &ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
auto packet = Connector::getPacketFromBuffer(read_msg_.first, length);
auto connector_id =
@@ -153,7 +154,8 @@ void UdpTunnelListener::doRecvPacket() {
connector_id, std::make_shared<UdpTunnelConnector>(
socket_, strand_, receive_callback_,
[](Connector *, const std::error_code &) {},
- [](Connector *) {}, [](Connector *) {},
+ [](Connector *) {},
+ [](Connector *, const std::error_code &) {},
std::move(remote_endpoint_)));
connector = ret.first;
connector->second->setConnectorId(connector_id);
@@ -161,7 +163,7 @@ void UdpTunnelListener::doRecvPacket() {
UdpTunnelConnector *c =
dynamic_cast<UdpTunnelConnector *>(connector->second.get());
- c->doRecvPacket(*packet);
+ c->doRecvPacket(packet);
doRecvPacket();
} else if (ec.value() ==
static_cast<int>(std::errc::operation_canceled)) {
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h b/libtransport/src/core/udp_listener.h
index 5d197dcb0..813520309 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h
+++ b/libtransport/src/core/udp_listener.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
*/
#pragma once
@@ -44,8 +44,8 @@ class UdpTunnelListener
#ifndef LINUX
read_msg_(nullptr, 0)
#else
- iovecs_{0},
- msgs_{0},
+ iovecs_{},
+ msgs_{},
current_position_(0)
#endif
{
@@ -83,7 +83,7 @@ class UdpTunnelListener
private:
void doRecvPacket();
- void readHandler(std::error_code ec);
+ void readHandler(const std::error_code &ec);
asio::io_service &io_service_;
std::shared_ptr<asio::io_service::strand> strand_;
diff --git a/libtransport/src/http/CMakeLists.txt b/libtransport/src/http/CMakeLists.txt
index 2407faea3..0060f8714 100644
--- a/libtransport/src/http/CMakeLists.txt
+++ b/libtransport/src/http/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/src/http/client_connection.cc b/libtransport/src/http/client_connection.cc
index b4ab7cbc3..05fa3e335 100644
--- a/libtransport/src/http/client_connection.cc
+++ b/libtransport/src/http/client_connection.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -77,9 +77,7 @@ class HTTPClientConnection::Implementation
auto end = std::chrono::steady_clock::now();
LOG(INFO) << method_map[method].c_str() << " " << url.c_str() << " ["
<< name_.str() << "] duration: "
- << std::chrono::duration_cast<std::chrono::microseconds>(end -
- start)
- .count()
+ << utils::SteadyTime::getDurationUs(start, end).count()
<< " [usec] " << size << " [bytes]";
};
@@ -106,7 +104,7 @@ class HTTPClientConnection::Implementation
HTTPClientConnection &setTimeout(const std::chrono::seconds &timeout) {
timer_->cancel();
timer_->expires_from_now(timeout);
- timer_->async_wait([this](std::error_code ec) {
+ timer_->async_wait([this](const std::error_code &ec) {
if (!ec) {
consumer_.stop();
}
@@ -147,18 +145,14 @@ class HTTPClientConnection::Implementation
name_ << ipv6_first_word << ":";
- for (uint16_t *word = (uint16_t *)&locator_hash;
- std::size_t(word) <
- (std::size_t(&locator_hash) + sizeof(locator_hash));
- word++) {
- name_ << ":" << std::hex << *word;
+ uint16_t *word = (uint16_t *)(&locator_hash);
+ for (std::size_t i = 0; i < sizeof(locator_hash) / 2; i++) {
+ name_ << ":" << std::hex << word[i];
}
- for (uint16_t *word = (uint16_t *)&request_hash;
- std::size_t(word) <
- (std::size_t(&request_hash) + sizeof(request_hash));
- word++) {
- name_ << ":" << std::hex << *word;
+ word = (uint16_t *)(&request_hash);
+ for (std::size_t i = 0; i < sizeof(request_hash) / 2; i++) {
+ name_ << ":" << std::hex << word[i];
}
name_ << "|0";
@@ -199,7 +193,7 @@ class HTTPClientConnection::Implementation
}
}
- void readError(const std::error_code ec) noexcept override {
+ void readError(const std::error_code &ec) noexcept override {
LOG(ERROR) << "Error " << ec.message() << " during download of "
<< current_url_.c_str();
if (read_bytes_callback_) {
diff --git a/libtransport/src/http/request.cc b/libtransport/src/http/request.cc
index 29118fd88..ad726741a 100644
--- a/libtransport/src/http/request.cc
+++ b/libtransport/src/http/request.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/http/response.cc b/libtransport/src/http/response.cc
index c665fbc5f..727e2c755 100644
--- a/libtransport/src/http/response.cc
+++ b/libtransport/src/http/response.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/implementation/CMakeLists.txt b/libtransport/src/implementation/CMakeLists.txt
index daf899d06..1f2a33a4c 100644
--- a/libtransport/src/implementation/CMakeLists.txt
+++ b/libtransport/src/implementation/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.cc b/libtransport/src/implementation/p2psecure_socket_consumer.cc
index 4b14da5d2..6b67a5487 100644
--- a/libtransport/src/implementation/p2psecure_socket_consumer.cc
+++ b/libtransport/src/implementation/p2psecure_socket_consumer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -44,7 +44,7 @@ int readOld(BIO *b, char *buf, int size) {
if (!socket->something_to_read_) {
if (!socket->transport_protocol_->isRunning()) {
socket->network_name_.setSuffix(socket->random_suffix_);
- socket->ConsumerSocket::asyncConsume(socket->network_name_);
+ socket->ConsumerSocket::consume(socket->network_name_);
}
if (!socket->something_to_read_) socket->cv_.wait(lck);
@@ -312,36 +312,6 @@ int P2PSecureConsumerSocket::consume(const Name &name) {
return tls_consumer_->consume((prefix->mapName(name)));
}
-int P2PSecureConsumerSocket::asyncConsume(const Name &name) {
- if (transport_protocol_->isRunning()) {
- return CONSUMER_BUSY;
- }
-
- if (handshake() != 1) {
- throw errors::RuntimeException("Unable to perform client handshake");
- } else {
- 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_ != NULL)
- return tls_consumer_->asyncConsume((prefix->mapName(name)),
- std::move(payload_));
- else
- return tls_consumer_->asyncConsume((prefix->mapName(name)));
-}
-
void P2PSecureConsumerSocket::registerPrefix(const Prefix &producer_namespace) {
producer_namespace_ = producer_namespace;
}
@@ -385,7 +355,7 @@ void P2PSecureConsumerSocket::readBufferAvailable(
cv_.notify_one();
}
-void P2PSecureConsumerSocket::readError(const std::error_code ec) noexcept {};
+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_);
diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.h b/libtransport/src/implementation/p2psecure_socket_consumer.h
index a35a50352..a5e69f611 100644
--- a/libtransport/src/implementation/p2psecure_socket_consumer.h
+++ b/libtransport/src/implementation/p2psecure_socket_consumer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -48,8 +48,6 @@ class P2PSecureConsumerSocket : public ConsumerSocket,
int consume(const Name &name) override;
- int asyncConsume(const Name &name) override;
-
void registerPrefix(const Prefix &producer_namespace);
int setSocketOption(
@@ -120,7 +118,7 @@ class P2PSecureConsumerSocket : public ConsumerSocket,
virtual void readBufferAvailable(
std::unique_ptr<utils::MemBuf> &&buffer) noexcept override;
- virtual void readError(const std::error_code ec) noexcept override;
+ virtual void readError(const std::error_code &ec) noexcept override;
virtual void readSuccess(std::size_t total_size) noexcept override;
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.cc b/libtransport/src/implementation/p2psecure_socket_producer.cc
index 3748001fc..ee78ea53b 100644
--- a/libtransport/src/implementation/p2psecure_socket_producer.cc
+++ b/libtransport/src/implementation/p2psecure_socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -20,6 +20,7 @@
#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>
@@ -41,7 +42,7 @@ P2PSecureProducerSocket::P2PSecureProducerSocket(
P2PSecureProducerSocket::P2PSecureProducerSocket(
interface::ProducerSocket *producer_socket, bool rtc,
- const std::shared_ptr<auth::Identity> &identity)
+ std::string &keystore_path, std::string &keystore_pwd)
: ProducerSocket(producer_socket,
ProductionProtocolAlgorithms::BYTE_STREAM),
rtc_(rtc),
@@ -50,8 +51,16 @@ P2PSecureProducerSocket::P2PSecureProducerSocket(
map_producers(),
list_producers() {
/* Setup SSL context (identity and parameter to use TLS 1.3) */
- cert_509_ = identity->getCertificate().get();
- pkey_rsa_ = identity->getPrivateKey().get();
+ 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. */
@@ -133,15 +142,15 @@ uint32_t P2PSecureProducerSocket::produceDatagram(
// TODO
throw errors::NotImplementedException();
- if (!rtc_) {
- throw errors::RuntimeException(
- "RTC must be the transport protocol to start the production of current "
- "data. Aborting.");
- }
+ // 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_);
+ // std::unique_lock<std::mutex> lck(mtx_);
- if (list_producers.empty()) cv_.wait(lck);
+ // if (list_producers.empty()) cv_.wait(lck);
// TODO
// for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
@@ -151,7 +160,7 @@ uint32_t P2PSecureProducerSocket::produceDatagram(
// rtc_producer->produce(utils::MemBuf::copyBuffer(buffer, buffer_size));
// }
- return 0;
+ // return 0;
}
uint32_t P2PSecureProducerSocket::produceStream(
@@ -197,44 +206,6 @@ uint32_t P2PSecureProducerSocket::produceStream(const Name &content_name,
return segments;
}
-// void P2PSecureProducerSocket::asyncProduce(const Name &content_name,
-// const uint8_t *buf,
-// size_t buffer_size, bool is_last,
-// uint32_t *start_offset) {
-// if (rtc_) {
-// throw errors::RuntimeException(
-// "RTC transport protocol is not compatible with the production of "
-// "current data. Aborting.");
-// }
-
-// std::unique_lock<std::mutex> lck(mtx_);
-// if (list_producers.empty()) cv_.wait(lck);
-
-// for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
-// {
-// (*it)->asyncProduce(content_name, buf, buffer_size, is_last,
-// start_offset);
-// }
-// }
-
-void P2PSecureProducerSocket::asyncProduce(
- Name content_name, std::unique_ptr<utils::MemBuf> &&buffer, bool is_last,
- uint32_t offset, uint32_t **last_segment) {
- if (rtc_) {
- throw errors::RuntimeException(
- "RTC transport protocol is not compatible with the production of "
- "current data. Aborting.");
- }
-
- std::unique_lock<std::mutex> lck(mtx_);
- if (list_producers.empty()) cv_.wait(lck);
-
- for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) {
- (*it)->asyncProduce(content_name, buffer->clone(), is_last, offset,
- last_segment);
- }
-}
-
/* Redefinition of socket options to avoid name hiding */
int P2PSecureProducerSocket::setSocketOption(
int socket_option_key, ProducerInterestCallback socket_option_value) {
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.h b/libtransport/src/implementation/p2psecure_socket_producer.h
index f94347258..00f407a75 100644
--- a/libtransport/src/implementation/p2psecure_socket_producer.h
+++ b/libtransport/src/implementation/p2psecure_socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,7 +15,6 @@
#pragma once
-#include <hicn/transport/auth/identity.h>
#include <hicn/transport/auth/signer.h>
#include <implementation/socket_producer.h>
// #include <implementation/tls_rtc_socket_producer.h>
@@ -38,9 +37,9 @@ class P2PSecureProducerSocket : public ProducerSocket {
public:
explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket);
- explicit P2PSecureProducerSocket(
- interface::ProducerSocket *producer_socket, bool rtc,
- const std::shared_ptr<auth::Identity> &identity);
+ explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket,
+ bool rtc, std::string &keystore_path,
+ std::string &keystore_pwd);
~P2PSecureProducerSocket();
@@ -56,10 +55,6 @@ class P2PSecureProducerSocket : public ProducerSocket {
bool is_last = true,
uint32_t start_offset = 0) override;
- void asyncProduce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t offset,
- uint32_t **last_segment = nullptr) override;
-
int setSocketOption(int socket_option_key,
ProducerInterestCallback socket_option_value) override;
diff --git a/libtransport/src/implementation/socket.cc b/libtransport/src/implementation/socket.cc
index 2e21f2bc3..95941da07 100644
--- a/libtransport/src/implementation/socket.cc
+++ b/libtransport/src/implementation/socket.cc
@@ -14,13 +14,42 @@
*/
#include <core/global_configuration.h>
+#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <implementation/socket.h>
namespace transport {
namespace implementation {
Socket::Socket(std::shared_ptr<core::Portal> &&portal)
- : portal_(std::move(portal)), is_async_(false) {}
+ : portal_(std::move(portal)),
+ is_async_(false),
+ packet_format_(interface::default_values::packet_format) {}
+
+int Socket::setSocketOption(int socket_option_key,
+ hicn_format_t packet_format) {
+ switch (socket_option_key) {
+ case interface::GeneralTransportOptions::PACKET_FORMAT:
+ packet_format_ = packet_format;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_SET;
+ }
+
+ return SOCKET_OPTION_SET;
+}
+
+int Socket::getSocketOption(int socket_option_key,
+ hicn_format_t &packet_format) {
+ switch (socket_option_key) {
+ case interface::GeneralTransportOptions::PACKET_FORMAT:
+ packet_format = packet_format_;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ }
+
+ return SOCKET_OPTION_GET;
+}
} // namespace implementation
} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/implementation/socket.h b/libtransport/src/implementation/socket.h
index cf22c03e1..11c9a704d 100644
--- a/libtransport/src/implementation/socket.h
+++ b/libtransport/src/implementation/socket.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -38,7 +38,26 @@ class Socket {
virtual void connect() = 0;
virtual bool isRunning() = 0;
- virtual asio::io_service &getIoService() { return portal_->getIoService(); }
+ virtual asio::io_service &getIoService() {
+ return portal_->getThread().getIoService();
+ }
+
+ int setSocketOption(int socket_option_key, hicn_format_t packet_format);
+ int getSocketOption(int socket_option_key, hicn_format_t &packet_format);
+
+ int getSocketOption(int socket_option_key,
+ std::shared_ptr<core::Portal> &socket_option_value) {
+ switch (socket_option_key) {
+ case interface::GeneralTransportOptions::PORTAL:
+ socket_option_value = portal_;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ ;
+ }
+
+ return SOCKET_OPTION_GET;
+ }
protected:
Socket(std::shared_ptr<core::Portal> &&portal);
@@ -48,6 +67,7 @@ class Socket {
protected:
std::shared_ptr<core::Portal> portal_;
bool is_async_;
+ hicn_format_t packet_format_;
};
} // namespace implementation
diff --git a/libtransport/src/implementation/socket_consumer.h b/libtransport/src/implementation/socket_consumer.h
index e0981af7f..ebdac7f93 100644
--- a/libtransport/src/implementation/socket_consumer.h
+++ b/libtransport/src/implementation/socket_consumer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -20,6 +20,7 @@
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/statistics.h>
#include <hicn/transport/utils/event_thread.h>
+#include <implementation/socket.h>
#include <protocols/cbr.h>
#include <protocols/raaqm.h>
#include <protocols/rtc/rtc.h>
@@ -38,7 +39,6 @@ class ConsumerSocket : public Socket {
std::shared_ptr<core::Portal> &&portal)
: Socket(std::move(portal)),
consumer_interface_(consumer),
- async_downloader_(),
interest_lifetime_(default_values::interest_lifetime),
min_window_size_(default_values::min_window_size),
max_window_size_(default_values::max_window_size),
@@ -56,6 +56,7 @@ class ConsumerSocket : public Socket {
rate_estimation_observer_(nullptr),
rate_estimation_batching_parameter_(default_values::batch),
rate_estimation_choice_(0),
+ max_unverified_delay_(default_values::max_unverified_delay),
verifier_(std::make_shared<auth::VoidVerifier>()),
verify_signature_(false),
reset_window_(false),
@@ -64,41 +65,42 @@ class ConsumerSocket : public Socket {
on_interest_satisfied_(VOID_HANDLER),
on_content_object_input_(VOID_HANDLER),
stats_summary_(VOID_HANDLER),
+ on_fwd_strategy_(VOID_HANDLER),
+ on_rec_strategy_(VOID_HANDLER),
read_callback_(nullptr),
timer_interval_milliseconds_(0),
+ recovery_strategy_(RtcTransportRecoveryStrategies::RTX_ONLY),
+ aggregated_data_(false),
+ fec_setting_(""),
guard_raaqm_params_() {
switch (protocol) {
case TransportProtocolAlgorithms::CBR:
transport_protocol_ =
- std::make_unique<protocol::CbrTransportProtocol>(this);
+ std::make_shared<protocol::CbrTransportProtocol>(this);
break;
case TransportProtocolAlgorithms::RTC:
transport_protocol_ =
- std::make_unique<protocol::rtc::RTCTransportProtocol>(this);
+ std::make_shared<protocol::rtc::RTCTransportProtocol>(this);
break;
case TransportProtocolAlgorithms::RAAQM:
default:
transport_protocol_ =
- std::make_unique<protocol::RaaqmTransportProtocol>(this);
+ std::make_shared<protocol::RaaqmTransportProtocol>(this);
break;
}
}
public:
ConsumerSocket(interface::ConsumerSocket *consumer, int protocol)
- : ConsumerSocket(consumer, protocol, std::make_shared<core::Portal>()) {}
+ : ConsumerSocket(consumer, protocol, core::Portal::createShared()) {}
ConsumerSocket(interface::ConsumerSocket *consumer, int protocol,
- asio::io_service &io_service)
- : ConsumerSocket(consumer, protocol,
- std::make_shared<core::Portal>(io_service)) {
+ ::utils::EventThread &worker)
+ : ConsumerSocket(consumer, protocol, core::Portal::createShared(worker)) {
is_async_ = true;
}
- ~ConsumerSocket() {
- stop();
- async_downloader_.stop();
- }
+ ~ConsumerSocket() { stop(); }
interface::ConsumerSocket *getInterface() {
return consumer_interface_;
@@ -122,18 +124,6 @@ class ConsumerSocket : public Socket {
transport_protocol_->start();
- return is_async_ ? CONSUMER_RUNNING : CONSUMER_FINISHED;
- }
-
- virtual int asyncConsume(const Name &name) {
- if (!async_downloader_.stopped()) {
- async_downloader_.add([this, name]() {
- network_name_ = std::move(name);
- network_name_.setSuffix(0);
- transport_protocol_->start();
- });
- }
-
return CONSUMER_RUNNING;
}
@@ -149,6 +139,9 @@ class ConsumerSocket : public Socket {
}
}
+ using Socket::getSocketOption;
+ using Socket::setSocketOption;
+
virtual int setSocketOption(int socket_option_key,
ReadCallback *socket_option_value) {
// Reschedule the function on the io_service to avoid race condition in
@@ -245,6 +238,10 @@ class ConsumerSocket : public Socket {
interest_lifetime_ = socket_option_value;
break;
+ case GeneralTransportOptions::MAX_UNVERIFIED_TIME:
+ max_unverified_delay_ = socket_option_value;
+ break;
+
case RateEstimationOptions::RATE_ESTIMATION_BATCH_PARAMETER:
if (socket_option_value > 0) {
rate_estimation_batching_parameter_ = socket_option_value;
@@ -265,6 +262,11 @@ class ConsumerSocket : public Socket {
timer_interval_milliseconds_ = socket_option_value;
break;
+ case RtcTransportOptions::RECOVERY_STRATEGY:
+ recovery_strategy_ =
+ (RtcTransportRecoveryStrategies)socket_option_value;
+ break;
+
default:
return SOCKET_OPTION_NOT_SET;
}
@@ -328,6 +330,11 @@ class ConsumerSocket : public Socket {
result = SOCKET_OPTION_SET;
break;
+ case RtcTransportOptions::AGGREGATED_DATA:
+ aggregated_data_ = socket_option_value;
+ result = SOCKET_OPTION_SET;
+ break;
+
default:
return result;
}
@@ -406,36 +413,37 @@ class ConsumerSocket : public Socket {
int setSocketOption(
int socket_option_key,
const std::shared_ptr<auth::Verifier> &socket_option_value) {
- int result = SOCKET_OPTION_NOT_SET;
if (!transport_protocol_->isRunning()) {
switch (socket_option_key) {
case GeneralTransportOptions::VERIFIER:
verifier_.reset();
verifier_ = socket_option_value;
- result = SOCKET_OPTION_SET;
break;
default:
- return result;
+ return SOCKET_OPTION_NOT_SET;
}
}
-
- return result;
+ return SOCKET_OPTION_SET;
}
int setSocketOption(int socket_option_key,
const std::string &socket_option_value) {
int result = SOCKET_OPTION_NOT_SET;
- if (!transport_protocol_->isRunning()) {
- switch (socket_option_key) {
- case DataLinkOptions::OUTPUT_INTERFACE:
+ switch (socket_option_key) {
+ case DataLinkOptions::OUTPUT_INTERFACE:
+ if (!transport_protocol_->isRunning()) {
output_interface_ = socket_option_value;
portal_->setOutputInterface(output_interface_);
result = SOCKET_OPTION_SET;
- break;
+ }
+ break;
+ case GeneralTransportOptions::FEC_TYPE:
+ fec_setting_ = socket_option_value;
+ result = SOCKET_OPTION_SET;
+ break;
- default:
- return result;
- }
+ default:
+ return result;
}
return result;
}
@@ -461,6 +469,29 @@ class ConsumerSocket : public Socket {
});
}
+ int setSocketOption(int socket_option_key,
+ StrategyCallback socket_option_value) {
+ // Reschedule the function on the io_service to avoid race condition in
+ // case setSocketOption is called while the io_service is running.
+ return rescheduleOnIOService(
+ socket_option_key, socket_option_value,
+ [this](int socket_option_key,
+ StrategyCallback socket_option_value) -> int {
+ switch (socket_option_key) {
+ case ConsumerCallbacksOptions::FWD_STRATEGY_CHANGE:
+ on_fwd_strategy_ = socket_option_value;
+ break;
+ case ConsumerCallbacksOptions::REC_STRATEGY_CHANGE:
+ on_rec_strategy_ = socket_option_value;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_SET;
+ }
+
+ return SOCKET_OPTION_SET;
+ });
+ }
+
int getSocketOption(int socket_option_key, double &socket_option_value) {
utils::SpinLock::Acquire locked(guard_raaqm_params_);
switch (socket_option_key) {
@@ -516,6 +547,10 @@ class ConsumerSocket : public Socket {
socket_option_value = interest_lifetime_;
break;
+ case GeneralTransportOptions::MAX_UNVERIFIED_TIME:
+ socket_option_value = max_unverified_delay_;
+ break;
+
case RaaqmTransportOptions::SAMPLE_NUMBER:
socket_option_value = sample_number_;
break;
@@ -532,6 +567,10 @@ class ConsumerSocket : public Socket {
socket_option_value = timer_interval_milliseconds_;
break;
+ case RtcTransportOptions::RECOVERY_STRATEGY:
+ socket_option_value = recovery_strategy_;
+ break;
+
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -553,6 +592,10 @@ class ConsumerSocket : public Socket {
socket_option_value = reset_window_;
break;
+ case RtcTransportOptions::AGGREGATED_DATA:
+ socket_option_value = aggregated_data_;
+ break;
+
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -628,20 +671,6 @@ class ConsumerSocket : public Socket {
}
int getSocketOption(int socket_option_key,
- std::shared_ptr<core::Portal> &socket_option_value) {
- switch (socket_option_key) {
- case PORTAL:
- socket_option_value = portal_;
- break;
-
- default:
- return SOCKET_OPTION_NOT_GET;
- }
-
- return SOCKET_OPTION_GET;
- }
-
- int getSocketOption(int socket_option_key,
IcnObserver **socket_option_value) {
utils::SpinLock::Acquire locked(guard_raaqm_params_);
switch (socket_option_key) {
@@ -665,7 +694,6 @@ class ConsumerSocket : public Socket {
default:
return SOCKET_OPTION_NOT_GET;
}
-
return SOCKET_OPTION_GET;
}
@@ -674,6 +702,9 @@ class ConsumerSocket : public Socket {
case DataLinkOptions::OUTPUT_INTERFACE:
socket_option_value = output_interface_;
break;
+ case GeneralTransportOptions::FEC_TYPE:
+ socket_option_value = fec_setting_;
+ break;
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -714,6 +745,29 @@ class ConsumerSocket : public Socket {
});
}
+ int getSocketOption(int socket_option_key,
+ StrategyCallback **socket_option_value) {
+ // Reschedule the function on the io_service to avoid race condition in
+ // case setSocketOption is called while the io_service is running.
+ return rescheduleOnIOService(
+ socket_option_key, socket_option_value,
+ [this](int socket_option_key,
+ StrategyCallback **socket_option_value) -> int {
+ switch (socket_option_key) {
+ case ConsumerCallbacksOptions::FWD_STRATEGY_CHANGE:
+ *socket_option_value = &on_fwd_strategy_;
+ break;
+ case ConsumerCallbacksOptions::REC_STRATEGY_CHANGE:
+ *socket_option_value = &on_rec_strategy_;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ }
+
+ return SOCKET_OPTION_GET;
+ });
+ }
+
protected:
template <typename Lambda, typename arg2>
int rescheduleOnIOService(int socket_option_key, arg2 socket_option_value,
@@ -726,9 +780,9 @@ class ConsumerSocket : public Socket {
/* Condition variable for the wait */
std::condition_variable cv;
bool done = false;
- portal_->getIoService().dispatch([&socket_option_key,
- &socket_option_value, &mtx, &cv,
- &result, &done, &func]() {
+ portal_->getThread().tryRunHandlerNow([&socket_option_key,
+ &socket_option_value, &mtx, &cv,
+ &result, &done, &func]() {
std::unique_lock<std::mutex> lck(mtx);
done = true;
result = func(socket_option_key, socket_option_value);
@@ -748,8 +802,6 @@ class ConsumerSocket : public Socket {
protected:
interface::ConsumerSocket *consumer_interface_;
- utils::EventThread async_downloader_;
-
// No need to protect from multiple accesses in the async consumer
// The parameter is accessible only with a getSocketOption and
// set from the consume
@@ -776,6 +828,7 @@ class ConsumerSocket : public Socket {
int rate_estimation_choice_;
// Verification parameters
+ int max_unverified_delay_;
std::shared_ptr<auth::Verifier> verifier_;
transport::auth::KeyId *key_id_;
std::atomic_bool verify_signature_;
@@ -787,17 +840,26 @@ class ConsumerSocket : public Socket {
ConsumerInterestCallback on_interest_satisfied_;
ConsumerContentObjectCallback on_content_object_input_;
ConsumerTimerCallback stats_summary_;
+ StrategyCallback on_fwd_strategy_;
+ StrategyCallback on_rec_strategy_;
ReadCallback *read_callback_;
uint32_t timer_interval_milliseconds_;
// Transport protocol
- std::unique_ptr<protocol::TransportProtocol> transport_protocol_;
+ std::shared_ptr<protocol::TransportProtocol> transport_protocol_;
// Statistic
TransportStatistics stats_;
+ // RTC protocol
+ RtcTransportRecoveryStrategies recovery_strategy_;
+ bool aggregated_data_;
+
+ // FEC setting
+ std::string fec_setting_;
+
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 9daf79b9d..37151d497 100644
--- a/libtransport/src/implementation/socket_producer.h
+++ b/libtransport/src/implementation/socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -40,6 +40,7 @@ namespace implementation {
using namespace core;
using namespace interface;
+using ProducerCallback = interface::ProducerSocket::Callback;
class ProducerSocket : public Socket {
private:
@@ -48,11 +49,14 @@ class ProducerSocket : public Socket {
: Socket(std::move(portal)),
producer_interface_(producer_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),
- async_thread_(),
- making_manifest_(false),
+ making_manifest_(default_values::manifest_capacity),
hash_algorithm_(auth::CryptoHashType::SHA256),
- suffix_strategy_(core::NextSegmentCalculationStrategy::INCREMENTAL),
+ signer_(std::make_shared<auth::VoidSigner>()),
+ suffix_strategy_(std::make_shared<utils::IncrementalSuffixStrategy>(0)),
+ aggregated_data_(false),
+ fec_setting_(""),
on_interest_input_(VOID_HANDLER),
on_interest_dropped_input_buffer_(VOID_HANDLER),
on_interest_inserted_input_buffer_(VOID_HANDLER),
@@ -63,29 +67,30 @@ class ProducerSocket : public Socket {
on_content_object_in_output_buffer_(VOID_HANDLER),
on_content_object_output_(VOID_HANDLER),
on_content_object_evicted_from_output_buffer_(VOID_HANDLER),
- on_content_produced_(VOID_HANDLER) {
+ on_content_produced_(VOID_HANDLER),
+ application_callback_(nullptr) {
switch (protocol) {
case ProductionProtocolAlgorithms::RTC_PROD:
production_protocol_ =
- std::make_unique<protocol::RTCProductionProtocol>(this);
+ std::make_shared<protocol::RTCProductionProtocol>(this);
break;
case ProductionProtocolAlgorithms::BYTE_STREAM:
default:
production_protocol_ =
- std::make_unique<protocol::ByteStreamProductionProtocol>(this);
+ std::make_shared<protocol::ByteStreamProductionProtocol>(this);
break;
}
}
public:
ProducerSocket(interface::ProducerSocket *producer, int protocol)
- : ProducerSocket(producer, protocol, std::make_shared<core::Portal>()) {}
+ : ProducerSocket(producer, protocol, core::Portal::createShared()) {
+ is_async_ = true;
+ }
ProducerSocket(interface::ProducerSocket *producer, int protocol,
- asio::io_service &io_service)
- : ProducerSocket(producer, protocol,
- std::make_shared<core::Portal>(io_service)) {
- is_async_ = true;
+ ::utils::EventThread &worker)
+ : ProducerSocket(producer, protocol, core::Portal::createShared(worker)) {
}
virtual ~ProducerSocket() {}
@@ -98,31 +103,9 @@ class ProducerSocket : public Socket {
producer_interface_ = producer_socket;
}
- void connect() override {
- portal_->connect(false);
- production_protocol_->start();
- }
-
- bool isRunning() override { return !production_protocol_->isRunning(); };
+ void connect() override { portal_->connect(false); }
- virtual void asyncProduce(Name content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t offset,
- uint32_t **last_segment = nullptr) {
- if (!async_thread_.stopped()) {
- auto a = buffer.release();
- async_thread_.add([this, content_name, a, is_last, offset,
- last_segment]() {
- auto buf = std::unique_ptr<utils::MemBuf>(a);
- if (last_segment != NULL) {
- **last_segment = offset + produceStream(content_name, std::move(buf),
- is_last, offset);
- } else {
- produceStream(content_name, std::move(buf), is_last, offset);
- }
- });
- }
- }
+ bool isRunning() override { return production_protocol_->isRunning(); };
virtual uint32_t produceStream(const Name &content_name,
std::unique_ptr<utils::MemBuf> &&buffer,
@@ -156,12 +139,38 @@ class ProducerSocket : public Socket {
production_protocol_->produce(content_object);
}
+ void sendMapme() { production_protocol_->sendMapme(); }
+
void registerPrefix(const Prefix &producer_namespace) {
- production_protocol_->registerNamespaceWithNetwork(producer_namespace);
+ portal_->registerRoute(producer_namespace);
}
+ void start() { production_protocol_->start(); }
void stop() { production_protocol_->stop(); }
+ using Socket::getSocketOption;
+ using Socket::setSocketOption;
+
+ virtual int setSocketOption(int socket_option_key,
+ ProducerCallback *socket_option_value) {
+ // Reschedule the function on the io_service to avoid race condition in
+ // case setSocketOption is called while the io_service is running.
+ return rescheduleOnIOService(
+ socket_option_key, socket_option_value,
+ [this](int socket_option_key,
+ ProducerCallback *socket_option_value) -> int {
+ switch (socket_option_key) {
+ case ProducerCallbacksOptions::PRODUCER_CALLBACK:
+ application_callback_ = socket_option_value;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_SET;
+ }
+
+ return SOCKET_OPTION_SET;
+ });
+ }
+
virtual int setSocketOption(int socket_option_key,
uint32_t socket_option_value) {
switch (socket_option_key) {
@@ -172,6 +181,17 @@ class ProducerSocket : public Socket {
}
break;
+ case GeneralTransportOptions::MAKE_MANIFEST:
+ making_manifest_ = socket_option_value;
+ break;
+
+ case GeneralTransportOptions::MAX_SEGMENT_SIZE:
+ if (socket_option_value <= default_values::max_content_object_size &&
+ socket_option_value > 0) {
+ max_segment_size_ = socket_option_value;
+ }
+ break;
+
case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
production_protocol_->setOutputBufferSize(socket_option_value);
break;
@@ -260,8 +280,8 @@ class ProducerSocket : public Socket {
virtual int setSocketOption(int socket_option_key, bool socket_option_value) {
switch (socket_option_key) {
- case GeneralTransportOptions::MAKE_MANIFEST:
- making_manifest_ = socket_option_value;
+ case RtcTransportOptions::AGGREGATED_DATA:
+ aggregated_data_ = socket_option_value;
break;
default:
@@ -385,7 +405,7 @@ class ProducerSocket : public Socket {
virtual int setSocketOption(
int socket_option_key,
- core::NextSegmentCalculationStrategy socket_option_value) {
+ const std::shared_ptr<utils::SuffixStrategy> &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::SUFFIX_STRATEGY:
suffix_strategy_ = socket_option_value;
@@ -413,9 +433,33 @@ class ProducerSocket : public Socket {
return SOCKET_OPTION_SET;
}
+ int getSocketOption(int socket_option_key,
+ ProducerCallback **socket_option_value) {
+ // Reschedule the function on the io_service to avoid race condition in
+ // case setSocketOption is called while the io_service is running.
+ return rescheduleOnIOService(
+ socket_option_key, socket_option_value,
+ [this](int socket_option_key,
+ ProducerCallback **socket_option_value) -> int {
+ switch (socket_option_key) {
+ case ProducerCallbacksOptions::PRODUCER_CALLBACK:
+ *socket_option_value = application_callback_;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ }
+
+ return SOCKET_OPTION_GET;
+ });
+ }
+
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_;
+ break;
+
case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
socket_option_value = production_protocol_->getOutputBufferSize();
break;
@@ -424,6 +468,10 @@ class ProducerSocket : public Socket {
socket_option_value = (uint32_t)data_packet_size_;
break;
+ case GeneralTransportOptions::MAX_SEGMENT_SIZE:
+ socket_option_value = (uint32_t)max_segment_size_;
+ break;
+
case GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME:
socket_option_value = content_object_expiry_time_;
break;
@@ -438,14 +486,14 @@ class ProducerSocket : public Socket {
virtual int getSocketOption(int socket_option_key,
bool &socket_option_value) {
switch (socket_option_key) {
- case GeneralTransportOptions::MAKE_MANIFEST:
- socket_option_value = making_manifest_;
- break;
-
case GeneralTransportOptions::ASYNC_MODE:
socket_option_value = is_async_;
break;
+ case RtcTransportOptions::AGGREGATED_DATA:
+ socket_option_value = aggregated_data_;
+ break;
+
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -547,21 +595,6 @@ class ProducerSocket : public Socket {
});
}
- virtual int getSocketOption(
- int socket_option_key,
- std::shared_ptr<core::Portal> &socket_option_value) {
- switch (socket_option_key) {
- case PORTAL:
- socket_option_value = portal_;
- break;
- default:
- return SOCKET_OPTION_NOT_GET;
- ;
- }
-
- return SOCKET_OPTION_GET;
- }
-
virtual int getSocketOption(int socket_option_key,
auth::CryptoHashType &socket_option_value) {
switch (socket_option_key) {
@@ -577,7 +610,7 @@ class ProducerSocket : public Socket {
virtual int getSocketOption(
int socket_option_key,
- core::NextSegmentCalculationStrategy &socket_option_value) {
+ std::shared_ptr<utils::SuffixStrategy> &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::SUFFIX_STRATEGY:
socket_option_value = suffix_strategy_;
@@ -603,9 +636,31 @@ class ProducerSocket : public Socket {
return SOCKET_OPTION_GET;
}
+ int getSocketOption(int socket_option_key, std::string &socket_option_value) {
+ switch (socket_option_key) {
+ case GeneralTransportOptions::FEC_TYPE:
+ socket_option_value = fec_setting_;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ }
+
+ return SOCKET_OPTION_GET;
+ }
+
virtual int setSocketOption(int socket_option_key,
const std::string &socket_option_value) {
- return SOCKET_OPTION_NOT_SET;
+ int result = SOCKET_OPTION_NOT_SET;
+ switch (socket_option_key) {
+ case GeneralTransportOptions::FEC_TYPE:
+ fec_setting_ = socket_option_value;
+ result = SOCKET_OPTION_SET;
+ break;
+
+ default:
+ return result;
+ }
+ return result;
}
// If the thread calling lambda_func is not the same of io_service, this
@@ -623,9 +678,9 @@ class ProducerSocket : public Socket {
std::condition_variable cv;
bool done = false;
- portal_->getIoService().dispatch([&socket_option_key,
- &socket_option_value, &mtx, &cv,
- &result, &done, &func]() {
+ portal_->getThread().tryRunHandlerNow([&socket_option_key,
+ &socket_option_value, &mtx, &cv,
+ &result, &done, &func]() {
std::unique_lock<std::mutex> lck(mtx);
done = true;
result = func(socket_option_key, socket_option_value);
@@ -655,9 +710,9 @@ class ProducerSocket : public Socket {
/* Condition variable for the wait */
std::condition_variable cv;
bool done = false;
- portal_->getIoService().dispatch([&socket_option_key,
- &socket_option_value, &mtx, &cv,
- &result, &done, &func]() {
+ portal_->getThread().tryRunHandlerNow([&socket_option_key,
+ &socket_option_value, &mtx, &cv,
+ &result, &done, &func]() {
std::unique_lock<std::mutex> lck(mtx);
done = true;
result = func(socket_option_key, socket_option_value);
@@ -677,20 +732,24 @@ class ProducerSocket : public Socket {
// Threads
protected:
interface::ProducerSocket *producer_interface_;
- asio::io_service io_service_;
std::atomic<size_t> data_packet_size_;
+ std::atomic<size_t> max_segment_size_;
std::atomic<uint32_t> content_object_expiry_time_;
- utils::EventThread async_thread_;
-
- std::atomic<bool> making_manifest_;
+ std::atomic<uint32_t> making_manifest_;
std::atomic<auth::CryptoHashType> hash_algorithm_;
std::atomic<auth::CryptoSuite> crypto_suite_;
utils::SpinLock signer_lock_;
std::shared_ptr<auth::Signer> signer_;
- core::NextSegmentCalculationStrategy suffix_strategy_;
+ std::shared_ptr<utils::SuffixStrategy> suffix_strategy_;
+
+ std::shared_ptr<protocol::ProductionProtocol> production_protocol_;
- std::unique_ptr<protocol::ProductionProtocol> production_protocol_;
+ // RTC transport
+ bool aggregated_data_;
+
+ // FEC setting
+ std::string fec_setting_;
// callbacks
ProducerInterestCallback on_interest_input_;
@@ -706,6 +765,8 @@ class ProducerSocket : public Socket {
ProducerContentObjectCallback on_content_object_evicted_from_output_buffer_;
ProducerContentCallback on_content_produced_;
+
+ ProducerCallback *application_callback_;
};
} // namespace implementation
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.cc b/libtransport/src/implementation/tls_rtc_socket_producer.cc
index db62b10c1..06d613ef0 100644
--- a/libtransport/src/implementation/tls_rtc_socket_producer.cc
+++ b/libtransport/src/implementation/tls_rtc_socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -90,11 +90,11 @@ int TLSRTCProducerSocket::writeOld(BIO *b, const char *buf, int num) {
socket = (TLSRTCProducerSocket *)BIO_get_data(b);
if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) {
- bool making_manifest = socket->parent_->making_manifest_;
+ uint32_t making_manifest = socket->parent_->making_manifest_;
socket->tls_chunks_--;
socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- false);
+ 0U);
socket->parent_->ProducerSocket::produce(
socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0, 0);
socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.h b/libtransport/src/implementation/tls_rtc_socket_producer.h
index 92c657afc..f6dc425e4 100644
--- a/libtransport/src/implementation/tls_rtc_socket_producer.h
+++ b/libtransport/src/implementation/tls_rtc_socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/implementation/tls_socket_consumer.cc b/libtransport/src/implementation/tls_socket_consumer.cc
index 65472b41d..b368c4b88 100644
--- a/libtransport/src/implementation/tls_socket_consumer.cc
+++ b/libtransport/src/implementation/tls_socket_consumer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -43,7 +43,7 @@ int readOldTLS(BIO *b, char *buf, int size) {
if (!socket->something_to_read_) {
if (!socket->transport_protocol_->isRunning()) {
socket->network_name_.setSuffix(socket->random_suffix_);
- socket->ConsumerSocket::asyncConsume(socket->network_name_);
+ socket->ConsumerSocket::consume(socket->network_name_);
}
if (!socket->something_to_read_) socket->cv_.wait(lck);
@@ -284,31 +284,6 @@ int TLSConsumerSocket::download_content(const Name &name) {
return CONSUMER_FINISHED;
}
-int TLSConsumerSocket::asyncConsume(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 asyncConsume(name);
-}
-
-int TLSConsumerSocket::asyncConsume(const Name &name) {
- if ((SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) {
- throw errors::RuntimeException("Handshake not performed");
- }
-
- if (!async_downloader_tls_.stopped()) {
- async_downloader_tls_.add([this, name]() { download_content(name); });
- }
-
- return CONSUMER_RUNNING;
-}
-
void TLSConsumerSocket::registerPrefix(const Prefix &producer_namespace) {
producer_namespace_ = producer_namespace;
}
@@ -353,7 +328,7 @@ void TLSConsumerSocket::readBufferAvailable(
cv_.notify_one();
}
-void TLSConsumerSocket::readError(const std::error_code ec) noexcept {}
+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_);
diff --git a/libtransport/src/implementation/tls_socket_consumer.h b/libtransport/src/implementation/tls_socket_consumer.h
index be08ec47d..a74f1ee10 100644
--- a/libtransport/src/implementation/tls_socket_consumer.h
+++ b/libtransport/src/implementation/tls_socket_consumer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -47,9 +47,6 @@ class TLSConsumerSocket : public ConsumerSocket,
int consume(const Name &name, std::unique_ptr<utils::MemBuf> &&buffer);
int consume(const Name &name) override;
- int asyncConsume(const Name &name, std::unique_ptr<utils::MemBuf> &&buffer);
- int asyncConsume(const Name &name) override;
-
void registerPrefix(const Prefix &producer_namespace);
int setSocketOption(
@@ -100,7 +97,7 @@ class TLSConsumerSocket : public ConsumerSocket,
virtual void readBufferAvailable(
std::unique_ptr<utils::MemBuf> &&buffer) noexcept override;
- virtual void readError(const std::error_code ec) noexcept override;
+ virtual void readError(const std::error_code &ec) noexcept override;
virtual void readSuccess(std::size_t total_size) noexcept override;
diff --git a/libtransport/src/implementation/tls_socket_producer.cc b/libtransport/src/implementation/tls_socket_producer.cc
index 3992ca45c..47f3b43a6 100644
--- a/libtransport/src/implementation/tls_socket_producer.cc
+++ b/libtransport/src/implementation/tls_socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -99,12 +99,12 @@ int TLSProducerSocket::writeOld(BIO *b, const char *buf, int num) {
socket = (TLSProducerSocket *)BIO_get_data(b);
if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) {
- bool making_manifest = socket->parent_->making_manifest_;
+ uint32_t making_manifest = socket->parent_->making_manifest_;
//! socket->tls_chunks_ corresponds to is_last
socket->tls_chunks_--;
socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- false);
+ 0U);
socket->parent_->ProducerSocket::produceStream(
socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0,
socket->last_segment_);
@@ -358,7 +358,7 @@ uint32_t TLSProducerSocket::produceStream(
}
size_t buf_size = buffer->length();
- name_ = production_protocol_->getNamespaces().front().mapName(content_name);
+ name_ = portal_->getServedNamespaces().begin()->mapName(content_name);
tls_chunks_ = to_call_oncontentproduced_ =
(int)ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH);
@@ -394,8 +394,7 @@ int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
<< "On addHicnKeyIdCb, for the prefix registration.";
if (ext_type == 100) {
- auto &prefix =
- socket->parent_->production_protocol_->getNamespaces().front();
+ 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();
diff --git a/libtransport/src/implementation/tls_socket_producer.h b/libtransport/src/implementation/tls_socket_producer.h
index a542a4d9f..0e958b321 100644
--- a/libtransport/src/implementation/tls_socket_producer.h
+++ b/libtransport/src/implementation/tls_socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/CMakeLists.txt b/libtransport/src/interfaces/CMakeLists.txt
index 7ec024fec..0a0603ac8 100644
--- a/libtransport/src/interfaces/CMakeLists.txt
+++ b/libtransport/src/interfaces/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/src/interfaces/callbacks.cc b/libtransport/src/interfaces/callbacks.cc
index 6869ac3f7..776b4cbe7 100644
--- a/libtransport/src/interfaces/callbacks.cc
+++ b/libtransport/src/interfaces/callbacks.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/p2psecure_socket_consumer.cc b/libtransport/src/interfaces/p2psecure_socket_consumer.cc
index e473a1e2e..e329a50f1 100644
--- a/libtransport/src/interfaces/p2psecure_socket_consumer.cc
+++ b/libtransport/src/interfaces/p2psecure_socket_consumer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/p2psecure_socket_producer.cc b/libtransport/src/interfaces/p2psecure_socket_producer.cc
index 10d8a1367..5f98302d0 100644
--- a/libtransport/src/interfaces/p2psecure_socket_producer.cc
+++ b/libtransport/src/interfaces/p2psecure_socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,10 +23,11 @@ P2PSecureProducerSocket::P2PSecureProducerSocket() {
socket_ = std::make_unique<implementation::P2PSecureProducerSocket>(this);
}
-P2PSecureProducerSocket::P2PSecureProducerSocket(
- bool rtc, const std::shared_ptr<auth::Identity> &identity) {
- socket_ = std::make_unique<implementation::P2PSecureProducerSocket>(this, rtc,
- identity);
+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
diff --git a/libtransport/src/interfaces/portal.cc b/libtransport/src/interfaces/portal.cc
index 9db0621f6..84634a282 100644
--- a/libtransport/src/interfaces/portal.cc
+++ b/libtransport/src/interfaces/portal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -13,83 +13,106 @@
* limitations under the License.
*/
+#include <core/portal.h>
#include <hicn/transport/interfaces/portal.h>
-#include <implementation/socket.h>
namespace transport {
namespace interface {
-Portal::Portal() { implementation_ = new core::Portal(); }
+class Portal::Impl {
+ public:
+ Impl() : portal_(core::Portal::createShared()) {}
+ Impl(::utils::EventThread &worker)
+ : portal_(core::Portal::createShared(worker)) {}
-Portal::Portal(asio::io_service &io_service) {
- implementation_ = new core::Portal(io_service);
-}
+ void registerTransportCallback(TransportCallback *transport_callback) {
+ portal_->registerTransportCallback(transport_callback);
+ }
+
+ void connect(bool is_consumer) { portal_->connect(is_consumer); }
+
+ bool interestIsPending(const core::Name &name) {
+ return portal_->interestIsPending(name);
+ }
+
+ void sendInterest(core::Interest::Ptr &&interest,
+ OnContentObjectCallback &&on_content_object_callback,
+ OnInterestTimeoutCallback &&on_interest_timeout_callback) {
+ portal_->sendInterest(std::move(interest),
+ std::move(on_content_object_callback),
+ std::move(on_interest_timeout_callback));
+ }
+
+ void sendContentObject(core::ContentObject &content_object) {
+ portal_->sendContentObject(content_object);
+ }
+
+ void killConnection() { portal_->killConnection(); }
+
+ void clear() { portal_->clear(); }
-Portal::~Portal() { delete reinterpret_cast<core::Portal *>(implementation_); }
+ utils::EventThread &getThread() { return portal_->getThread(); }
-void Portal::setConsumerCallback(ConsumerCallback *consumer_callback) {
- reinterpret_cast<core::Portal *>(implementation_)
- ->setConsumerCallback(consumer_callback);
+ void registerRoute(core::Prefix &prefix) { portal_->registerRoute(prefix); }
+
+ void sendMapme() { portal_->sendMapme(); }
+
+ void setForwardingStrategy(core::Prefix &prefix, std::string &strategy) {
+ portal_->setForwardingStrategy(prefix, strategy);
+ }
+
+ private:
+ std::shared_ptr<core::Portal> portal_;
+};
+
+Portal::Portal() { implementation_ = new Impl(); }
+
+Portal::Portal(::utils::EventThread &worker) {
+ implementation_ = new Impl(worker);
}
-void Portal::setProducerCallback(ProducerCallback *producer_callback) {
- reinterpret_cast<core::Portal *>(implementation_)
- ->setProducerCallback(producer_callback);
+Portal::~Portal() { delete implementation_; }
+
+void Portal::registerTransportCallback(TransportCallback *transport_callback) {
+ implementation_->registerTransportCallback(transport_callback);
}
void Portal::connect(bool is_consumer) {
- reinterpret_cast<core::Portal *>(implementation_)->connect(is_consumer);
+ implementation_->connect(is_consumer);
}
bool Portal::interestIsPending(const core::Name &name) {
- return reinterpret_cast<core::Portal *>(implementation_)
- ->interestIsPending(name);
+ return implementation_->interestIsPending(name);
}
void Portal::sendInterest(
core::Interest::Ptr &&interest,
OnContentObjectCallback &&on_content_object_callback,
OnInterestTimeoutCallback &&on_interest_timeout_callback) {
- reinterpret_cast<core::Portal *>(implementation_)
- ->sendInterest(std::move(interest), std::move(on_content_object_callback),
- std::move(on_interest_timeout_callback));
-}
-
-void Portal::bind(const BindConfig &config) {
- reinterpret_cast<core::Portal *>(implementation_)->bind(config);
-}
-
-void Portal::runEventsLoop() {
- reinterpret_cast<core::Portal *>(implementation_)->runEventsLoop();
-}
-
-void Portal::runOneEvent() {
- reinterpret_cast<core::Portal *>(implementation_)->runOneEvent();
+ implementation_->sendInterest(std::move(interest),
+ std::move(on_content_object_callback),
+ std::move(on_interest_timeout_callback));
}
void Portal::sendContentObject(core::ContentObject &content_object) {
- reinterpret_cast<core::Portal *>(implementation_)
- ->sendContentObject(content_object);
+ implementation_->sendContentObject(content_object);
}
-void Portal::stopEventsLoop() {
- reinterpret_cast<core::Portal *>(implementation_)->stopEventsLoop();
-}
+void Portal::killConnection() { implementation_->killConnection(); }
-void Portal::killConnection() {
- reinterpret_cast<core::Portal *>(implementation_)->killConnection();
-}
+void Portal::clear() { implementation_->clear(); }
-void Portal::clear() {
- reinterpret_cast<core::Portal *>(implementation_)->clear();
-}
+utils::EventThread &Portal::getThread() { return implementation_->getThread(); }
-asio::io_service &Portal::getIoService() {
- return reinterpret_cast<core::Portal *>(implementation_)->getIoService();
+void Portal::registerRoute(core::Prefix &prefix) {
+ implementation_->registerRoute(prefix);
}
-void Portal::registerRoute(core::Prefix &prefix) {
- reinterpret_cast<core::Portal *>(implementation_)->registerRoute(prefix);
+void Portal::sendMapme() { implementation_->sendMapme(); }
+
+void Portal::setForwardingStrategy(core::Prefix &prefix,
+ std::string &strategy) {
+ implementation_->setForwardingStrategy(prefix, strategy);
}
} // namespace interface
diff --git a/libtransport/src/interfaces/socket_consumer.cc b/libtransport/src/interfaces/socket_consumer.cc
index 4eee73cab..747dc0974 100644
--- a/libtransport/src/interfaces/socket_consumer.cc
+++ b/libtransport/src/interfaces/socket_consumer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,23 +23,28 @@ ConsumerSocket::ConsumerSocket(int protocol) {
socket_ = std::make_unique<implementation::ConsumerSocket>(this, protocol);
}
-ConsumerSocket::ConsumerSocket(int protocol, asio::io_service &io_service) {
- socket_ = std::make_unique<implementation::ConsumerSocket>(this, protocol,
- io_service);
+ConsumerSocket::ConsumerSocket(int protocol, ::utils::EventThread &worker) {
+ socket_ =
+ std::make_unique<implementation::ConsumerSocket>(this, protocol, worker);
}
ConsumerSocket::ConsumerSocket() {}
-ConsumerSocket::~ConsumerSocket() { socket_->stop(); }
+ConsumerSocket::ConsumerSocket(ConsumerSocket &&other) noexcept
+ : socket_(std::move(other.socket_)) {}
+
+ConsumerSocket::~ConsumerSocket() {
+ if (socket_) {
+ socket_->stop();
+ }
+}
void ConsumerSocket::connect() { socket_->connect(); }
bool ConsumerSocket::isRunning() { return socket_->isRunning(); }
-int ConsumerSocket::consume(const Name &name) { return socket_->consume(name); }
-
-int ConsumerSocket::asyncConsume(const Name &name) {
- return socket_->asyncConsume(name);
+int ConsumerSocket::consume(const Name &name, bool blocking) {
+ return socket_->consume(name);
}
void ConsumerSocket::stop() { socket_->stop(); }
@@ -111,6 +116,16 @@ int ConsumerSocket::setSocketOption(int socket_option_key,
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
+int ConsumerSocket::setSocketOption(int socket_option_key,
+ StrategyCallback socket_option_value) {
+ return socket_->setSocketOption(socket_option_key, socket_option_value);
+}
+
+int ConsumerSocket::setSocketOption(int socket_option_key,
+ Packet::Format socket_option_value) {
+ return socket_->setSocketOption(socket_option_key, socket_option_value);
+}
+
int ConsumerSocket::getSocketOption(int socket_option_key,
double &socket_option_value) {
return socket_->getSocketOption(socket_option_key, socket_option_value);
@@ -169,6 +184,16 @@ int ConsumerSocket::getSocketOption(
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
+int ConsumerSocket::getSocketOption(int socket_option_key,
+ StrategyCallback **socket_option_value) {
+ return socket_->getSocketOption(socket_option_key, socket_option_value);
+}
+
+int ConsumerSocket::getSocketOption(int socket_option_key,
+ Packet::Format &socket_option_value) {
+ return socket_->getSocketOption(socket_option_key, socket_option_value);
+}
+
} // namespace interface
} // namespace transport
diff --git a/libtransport/src/interfaces/socket_producer.cc b/libtransport/src/interfaces/socket_producer.cc
index b04947dfd..10613c0e1 100644
--- a/libtransport/src/interfaces/socket_producer.cc
+++ b/libtransport/src/interfaces/socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -33,14 +33,21 @@ ProducerSocket::ProducerSocket(int protocol) {
socket_ = std::make_unique<implementation::ProducerSocket>(this, protocol);
}
-ProducerSocket::ProducerSocket(int protocol, asio::io_service &io_service) {
- socket_ = std::make_unique<implementation::ProducerSocket>(this, protocol,
- io_service);
+ProducerSocket::ProducerSocket(int protocol, ::utils::EventThread &worker) {
+ socket_ =
+ std::make_unique<implementation::ProducerSocket>(this, protocol, worker);
}
+ProducerSocket::ProducerSocket(ProducerSocket &&other) noexcept
+ : socket_(std::move(other.socket_)) {}
+
ProducerSocket::ProducerSocket(bool) {}
-ProducerSocket::~ProducerSocket() { socket_->stop(); }
+ProducerSocket::~ProducerSocket() {
+ if (socket_) {
+ socket_->stop();
+ }
+}
void ProducerSocket::connect() { socket_->connect(); }
@@ -76,18 +83,14 @@ void ProducerSocket::produce(ContentObject &content_object) {
return socket_->produce(content_object);
}
-void ProducerSocket::asyncProduce(Name content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t offset,
- uint32_t **last_segment) {
- return socket_->asyncProduce(content_name, std::move(buffer), is_last, offset,
- last_segment);
-}
+void ProducerSocket::sendMapme() { return socket_->sendMapme(); }
void ProducerSocket::registerPrefix(const Prefix &producer_namespace) {
return socket_->registerPrefix(producer_namespace);
}
+void ProducerSocket::start() { return socket_->start(); }
+
void ProducerSocket::stop() { return socket_->stop(); }
asio::io_service &ProducerSocket::getIoService() {
@@ -95,6 +98,11 @@ asio::io_service &ProducerSocket::getIoService() {
};
int ProducerSocket::setSocketOption(int socket_option_key,
+ Callback *socket_option_value) {
+ return socket_->setSocketOption(socket_option_key, socket_option_value);
+}
+
+int ProducerSocket::setSocketOption(int socket_option_key,
uint32_t socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
@@ -140,9 +148,14 @@ int ProducerSocket::setSocketOption(
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);
+}
+
int ProducerSocket::getSocketOption(int socket_option_key,
uint32_t &socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
+ return socket_->getSocketOption(socket_option_key, socket_option_value);
}
int ProducerSocket::setSocketOption(int socket_option_key,
@@ -181,6 +194,11 @@ int ProducerSocket::getSocketOption(
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);
+}
+
} // namespace interface
} // namespace transport
diff --git a/libtransport/src/interfaces/tls_rtc_socket_producer.cc b/libtransport/src/interfaces/tls_rtc_socket_producer.cc
index 7326fcbcb..6bf1b011c 100644
--- a/libtransport/src/interfaces/tls_rtc_socket_producer.cc
+++ b/libtransport/src/interfaces/tls_rtc_socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/tls_rtc_socket_producer.h b/libtransport/src/interfaces/tls_rtc_socket_producer.h
index 3ea84095b..b8b6ec298 100644
--- a/libtransport/src/interfaces/tls_rtc_socket_producer.h
+++ b/libtransport/src/interfaces/tls_rtc_socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/tls_socket_consumer.cc b/libtransport/src/interfaces/tls_socket_consumer.cc
index 6c1c535b5..24060d1d8 100644
--- a/libtransport/src/interfaces/tls_socket_consumer.cc
+++ b/libtransport/src/interfaces/tls_socket_consumer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/tls_socket_consumer.h b/libtransport/src/interfaces/tls_socket_consumer.h
index 845a9181f..242dc91a5 100644
--- a/libtransport/src/interfaces/tls_socket_consumer.h
+++ b/libtransport/src/interfaces/tls_socket_consumer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/tls_socket_producer.cc b/libtransport/src/interfaces/tls_socket_producer.cc
index 037702f72..b2b9e723a 100644
--- a/libtransport/src/interfaces/tls_socket_producer.cc
+++ b/libtransport/src/interfaces/tls_socket_producer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/interfaces/tls_socket_producer.h b/libtransport/src/interfaces/tls_socket_producer.h
index 3c662176a..9b31cb483 100644
--- a/libtransport/src/interfaces/tls_socket_producer.h
+++ b/libtransport/src/interfaces/tls_socket_producer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/io_modules/CMakeLists.txt b/libtransport/src/io_modules/CMakeLists.txt
index 29aec236a..f4143de04 100644
--- a/libtransport/src/io_modules/CMakeLists.txt
+++ b/libtransport/src/io_modules/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,25 +11,69 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+
+##############################################################
+# Android case: no submodules
+##############################################################
if (${CMAKE_SYSTEM_NAME} MATCHES Android)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/udp/hicn_forwarder_module.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/udp/udp_socket_connector.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn-light-ng/hicn_forwarder_module.cc
)
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/udp/hicn_forwarder_module.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udp/udp_socket_connector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn-light-ng/hicn_forwarder_module.h
+ )
+
+ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE)
+
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+
+ list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
+ else()
+ if (DISABLE_SHARED_LIBRARIES)
+ if (WIN32)
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
+ else ()
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC} log)
+ endif ()
+ list(APPEND DEPENDENCIES
+ ${LIBHICNCTRL_STATIC}
+ )
+ else()
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_SHARED})
+ list(APPEND DEPENDENCIES
+ ${LIBHICNCTRL_SHARED}
+ )
+ endif()
+ endif()
+
+ list(APPEND LIBRARIES
+ PRIVATE ${LIBHICNCTRL_LIBRARIES}
+ )
+
+ list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
+ PUBLIC
+ $<BUILD_INTERFACE:${LIBHICNCTRL_INCLUDE_DIRS}>
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+ set(LIBRARIES ${LIBRARIES} PARENT_SCOPE)
+ set(LIBTRANSPORT_INTERNAL_INCLUDE_DIRS ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} PARENT_SCOPE)
else()
- add_subdirectory(udp)
+##############################################################
+# Compile submodules
+##############################################################
+ add_subdirectory(hicn-light-ng)
add_subdirectory(loopback)
add_subdirectory(forwarder)
if (__vpp__)
add_subdirectory(memif)
endif()
-endif() \ No newline at end of file
+endif()
diff --git a/libtransport/src/io_modules/forwarder/CMakeLists.txt b/libtransport/src/io_modules/forwarder/CMakeLists.txt
index a1d0c5db5..3922316d3 100644
--- a/libtransport/src/io_modules/forwarder/CMakeLists.txt
+++ b/libtransport/src/io_modules/forwarder/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -17,8 +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}/udp_tunnel_listener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel.h
${CMAKE_CURRENT_SOURCE_DIR}/global_counter.h
)
@@ -26,16 +24,13 @@ list(APPEND MODULE_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/errors.cc
${CMAKE_CURRENT_SOURCE_DIR}/forwarder_module.cc
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel_listener.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel.cc
)
build_module(forwarder_module
- SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBTRANSPORT_COMPONENT}-io-modules
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ INCLUDE_DIRS ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${Libhicn_INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
diff --git a/libtransport/src/io_modules/forwarder/errors.cc b/libtransport/src/io_modules/forwarder/errors.cc
index b5f131499..6e93d0453 100644
--- a/libtransport/src/io_modules/forwarder/errors.cc
+++ b/libtransport/src/io_modules/forwarder/errors.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
*/
#include <io_modules/forwarder/errors.h>
diff --git a/libtransport/src/io_modules/forwarder/forwarder.cc b/libtransport/src/io_modules/forwarder/forwarder.cc
index 0546cb8b3..3ae5bf397 100644
--- a/libtransport/src/io_modules/forwarder/forwarder.cc
+++ b/libtransport/src/io_modules/forwarder/forwarder.cc
@@ -15,11 +15,11 @@
#include <core/global_configuration.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>
-#include <io_modules/forwarder/udp_tunnel.h>
-#include <io_modules/forwarder/udp_tunnel_listener.h>
namespace transport {
@@ -89,11 +89,12 @@ void Forwarder::initConnectors() {
Connector::Id Forwarder::registerLocalConnector(
asio::io_service &io_service,
Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback) {
utils::SpinLock::Acquire locked(connector_lock_);
auto id = GlobalCounter<Connector::Id>::getInstance().getNext();
auto connector = std::make_shared<LocalConnector>(
- io_service, receive_callback, nullptr, nullptr, reconnect_callback);
+ io_service, receive_callback, sent_callback, nullptr, reconnect_callback);
connector->setConnectorId(id);
local_connectors_.emplace(id, std::move(connector));
return id;
@@ -105,6 +106,7 @@ Forwarder &Forwarder::deleteConnector(Connector::Id id) {
if (it != local_connectors_.end()) {
it->second->close();
local_connectors_.erase(it);
+ } else {
}
return *this;
@@ -120,9 +122,9 @@ Connector::Ptr Forwarder::getConnector(Connector::Id id) {
return nullptr;
}
-void Forwarder::onPacketFromListener(Connector *connector,
- utils::MemBuf &packet_buffer,
- const std::error_code &ec) {
+void Forwarder::onPacketFromListener(
+ Connector *connector, const std::vector<utils::MemBuf::Ptr> &packets,
+ const std::error_code &ec) {
// Create connector
connector->setReceiveCallback(
std::bind(&Forwarder::onPacketReceived, this, std::placeholders::_1,
@@ -135,37 +137,47 @@ void Forwarder::onPacketFromListener(Connector *connector,
remote_connectors_.emplace(connector->getConnectorId(),
connector->shared_from_this());
}
+
// TODO Check if control packet or not. For the moment it is not.
- onPacketReceived(connector, packet_buffer, ec);
+ onPacketReceived(connector, packets, ec);
}
void Forwarder::onPacketReceived(Connector *connector,
- utils::MemBuf &packet_buffer,
+ const std::vector<utils::MemBuf::Ptr> &packets,
const std::error_code &ec) {
- // Figure out the type of packet we received
- bool is_interest = Packet::isInterest(packet_buffer.data());
-
- Packet *packet = nullptr;
- if (is_interest) {
- packet = static_cast<Interest *>(&packet_buffer);
- } else {
- packet = static_cast<ContentObject *>(&packet_buffer);
+ if (ec) {
+ LOG(ERROR) << "Error receiving packet: " << ec.message();
+ return;
}
- 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);
+ 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 {
- LOG(ERROR) << "Error sending packet to local connector. is_interest = "
- << is_interest << " - is_producer = " << is_producer;
+ 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;
+ }
}
- }
- // 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) {
diff --git a/libtransport/src/io_modules/forwarder/forwarder.h b/libtransport/src/io_modules/forwarder/forwarder.h
index 5b564bb5e..38b4260b3 100644
--- a/libtransport/src/io_modules/forwarder/forwarder.h
+++ b/libtransport/src/io_modules/forwarder/forwarder.h
@@ -15,13 +15,13 @@
#pragma once
+#include <core/udp_listener.h>
#include <hicn/transport/core/io_module.h>
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/utils/event_thread.h>
#include <hicn/transport/utils/singleton.h>
#include <hicn/transport/utils/spinlock.h>
#include <io_modules/forwarder/configuration.h>
-#include <io_modules/forwarder/udp_tunnel_listener.h>
#include <atomic>
#include <libconfig.h++>
@@ -31,9 +31,8 @@ namespace transport {
namespace core {
-class Forwarder : public utils::Singleton<Forwarder> {
+class Forwarder {
static constexpr char forwarder_config_section[] = "forwarder";
- friend class utils::Singleton<Forwarder>;
public:
Forwarder();
@@ -47,6 +46,7 @@ class Forwarder : public utils::Singleton<Forwarder> {
Connector::Id registerLocalConnector(
asio::io_service &io_service,
Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback);
Forwarder &deleteConnector(Connector::Id id);
@@ -58,9 +58,11 @@ class Forwarder : public utils::Singleton<Forwarder> {
void stop();
private:
- void onPacketFromListener(Connector *connector, utils::MemBuf &packet_buffer,
+ void onPacketFromListener(Connector *connector,
+ const std::vector<utils::MemBuf::Ptr> &packets,
const std::error_code &ec);
- void onPacketReceived(Connector *connector, utils::MemBuf &packet_buffer,
+ void onPacketReceived(Connector *connector,
+ const std::vector<utils::MemBuf::Ptr> &packets,
const std::error_code &ec);
void onPacketSent(Connector *connector, const std::error_code &ec);
void onConnectorClosed(Connector *connector);
@@ -86,5 +88,20 @@ class Forwarder : public utils::Singleton<Forwarder> {
Configuration config_;
};
+class ForwarderGlobal : public ::utils::Singleton<ForwarderGlobal> {
+ friend class utils::Singleton<ForwarderGlobal>;
+
+ public:
+ ~ForwarderGlobal() {}
+ std::shared_ptr<Forwarder> &getReference() { return forwarder_; }
+
+ private:
+ ForwarderGlobal() : forwarder_(std::make_shared<Forwarder>()) {}
+
+ private:
+ std::shared_ptr<Forwarder> forwarder_;
+};
+
} // namespace core
-} // namespace transport \ No newline at end of file
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.cc b/libtransport/src/io_modules/forwarder/forwarder_module.cc
index 4f95b9ca0..0ced84ab4 100644
--- a/libtransport/src/io_modules/forwarder/forwarder_module.cc
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -25,11 +25,10 @@ ForwarderModule::ForwarderModule()
: IoModule(),
name_(""),
connector_id_(Connector::invalid_connector),
- forwarder_(Forwarder::getInstance()) {}
+ forwarder_ptr_(ForwarderGlobal::getInstance().getReference()),
+ forwarder_(*forwarder_ptr_) {}
-ForwarderModule::~ForwarderModule() {
- forwarder_.deleteConnector(connector_id_);
-}
+ForwarderModule::~ForwarderModule() {}
bool ForwarderModule::isConnected() { return true; }
@@ -42,7 +41,7 @@ void ForwarderModule::send(Packet &packet) {
// local_faces_.at(1 - local_id_).onPacket(packet);
}
-void ForwarderModule::send(const uint8_t *packet, std::size_t len) {
+void ForwarderModule::send(const utils::MemBuf::Ptr &buffer) {
// not supported
throw errors::NotImplementedException();
}
@@ -58,11 +57,13 @@ void ForwarderModule::closeConnection() {
}
void ForwarderModule::init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name) {
connector_id_ = forwarder_.registerLocalConnector(
- io_service, std::move(receive_callback), std::move(reconnect_callback));
+ io_service, std::move(receive_callback), std::move(sent_callback),
+ std::move(reconnect_callback));
name_ = app_name;
}
@@ -78,7 +79,9 @@ void ForwarderModule::connect(bool is_consumer) {
std::uint32_t ForwarderModule::getMtu() { return interface_mtu; }
-bool ForwarderModule::isControlMessage(const uint8_t *message) { return false; }
+bool ForwarderModule::isControlMessage(utils::MemBuf &packet_buffer) {
+ return false;
+}
extern "C" IoModule *create_module(void) { return new ForwarderModule(); }
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.h b/libtransport/src/io_modules/forwarder/forwarder_module.h
index 58bfb7996..52a12b67e 100644
--- a/libtransport/src/io_modules/forwarder/forwarder_module.h
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.h
@@ -38,11 +38,12 @@ class ForwarderModule : public IoModule {
void connect(bool is_consumer) override;
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
bool isConnected() override;
void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
@@ -51,15 +52,19 @@ class ForwarderModule : public IoModule {
std::uint32_t getMtu() override;
- bool isControlMessage(const uint8_t *message) override;
+ bool isControlMessage(utils::MemBuf &packet_buffer) override;
void processControlMessageReply(utils::MemBuf &packet_buffer) override;
void closeConnection() override;
private:
+ static void initForwarder();
+
+ private:
std::string name_;
Connector::Id connector_id_;
+ std::shared_ptr<Forwarder> forwarder_ptr_;
Forwarder &forwarder_;
};
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel.cc b/libtransport/src/io_modules/forwarder/udp_tunnel.cc
deleted file mode 100644
index bf6a69b92..000000000
--- a/libtransport/src/io_modules/forwarder/udp_tunnel.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- */
-
-#include <glog/logging.h>
-#include <hicn/transport/utils/branch_prediction.h>
-#include <io_modules/forwarder/errors.h>
-#include <io_modules/forwarder/udp_tunnel.h>
-
-#include <iostream>
-#include <thread>
-#include <vector>
-
-namespace transport {
-namespace core {
-
-UdpTunnelConnector::~UdpTunnelConnector() {}
-
-void UdpTunnelConnector::connect(const std::string &hostname, uint16_t port,
- const std::string &bind_address,
- uint16_t bind_port) {
- if (state_ == State::CLOSED) {
- state_ = State::CONNECTING;
- endpoint_iterator_ = resolver_.resolve({hostname, std::to_string(port)});
- remote_endpoint_send_ = *endpoint_iterator_;
- socket_->open(remote_endpoint_send_.protocol());
-
- if (!bind_address.empty() && bind_port != 0) {
- using namespace asio::ip;
- socket_->bind(
- udp::endpoint(address::from_string(bind_address), bind_port));
- }
-
- state_ = State::CONNECTED;
-
- remote_endpoint_ = Endpoint(remote_endpoint_send_);
- local_endpoint_ = Endpoint(socket_->local_endpoint());
-
- doRecvPacket();
-
-#ifdef LINUX
- send_timer_.expires_from_now(std::chrono::microseconds(50));
- send_timer_.async_wait(std::bind(&UdpTunnelConnector::writeHandler, this,
- std::placeholders::_1));
-#endif
- }
-}
-
-void UdpTunnelConnector::send(Packet &packet) {
- strand_->post([this, pkt{packet.shared_from_this()}]() {
- bool write_in_progress = !output_buffer_.empty();
- output_buffer_.push_back(std::move(pkt));
- if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
- if (!write_in_progress) {
- doSendPacket();
- }
- } else {
- data_available_ = true;
- }
- });
-}
-
-void UdpTunnelConnector::send(const uint8_t *packet, std::size_t len) {}
-
-void UdpTunnelConnector::close() {
- DLOG_IF(INFO, VLOG_IS_ON(2)) << "UDPTunnelConnector::close";
- state_ = State::CLOSED;
- bool is_socket_owned = socket_.use_count() == 1;
- if (is_socket_owned) {
- io_service_.dispatch([this]() {
- this->socket_->close();
- // on_close_callback_(shared_from_this());
- });
- }
-}
-
-void UdpTunnelConnector::doSendPacket() {
-#ifdef LINUX
- send_timer_.expires_from_now(std::chrono::microseconds(50));
- send_timer_.async_wait(std::bind(&UdpTunnelConnector::writeHandler, this,
- std::placeholders::_1));
-#else
- auto packet = output_buffer_.front().get();
- auto array = std::vector<asio::const_buffer>();
-
- const ::utils::MemBuf *current = packet;
- do {
- array.push_back(asio::const_buffer(current->data(), current->length()));
- current = current->next();
- } while (current != packet);
-
- socket_->async_send_to(
- std::move(array), remote_endpoint_send_,
- strand_->wrap([this](std::error_code ec, std::size_t length) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- sent_callback_(this, make_error_code(forwarder_error::success));
- } else if (ec.value() ==
- static_cast<int>(std::errc::operation_canceled)) {
- // The connection has been closed by the application.
- return;
- } else {
- sendFailed();
- sent_callback_(this, ec);
- }
-
- output_buffer_.pop_front();
- if (!output_buffer_.empty()) {
- doSendPacket();
- }
- }));
-#endif
-}
-
-#ifdef LINUX
-void UdpTunnelConnector::writeHandler(std::error_code ec) {
- if (TRANSPORT_EXPECT_FALSE(state_ != State::CONNECTED)) {
- return;
- }
-
- auto len = std::min(output_buffer_.size(), std::size_t(Connector::max_burst));
-
- if (len) {
- int m = 0;
- for (auto &p : output_buffer_) {
- auto packet = p.get();
- ::utils::MemBuf *current = packet;
- int b = 0;
- do {
- // array.push_back(asio::const_buffer(current->data(),
- // current->length()));
- tx_iovecs_[m][b].iov_base = current->writableData();
- tx_iovecs_[m][b].iov_len = current->length();
- current = current->next();
- b++;
- } while (current != packet);
-
- tx_msgs_[m].msg_hdr.msg_iov = tx_iovecs_[m];
- tx_msgs_[m].msg_hdr.msg_iovlen = b;
- tx_msgs_[m].msg_hdr.msg_name = remote_endpoint_send_.data();
- tx_msgs_[m].msg_hdr.msg_namelen = remote_endpoint_send_.size();
- m++;
-
- if (--len == 0) {
- break;
- }
- }
-
- int retval = sendmmsg(socket_->native_handle(), tx_msgs_, m, MSG_DONTWAIT);
- if (retval > 0) {
- while (retval--) {
- output_buffer_.pop_front();
- }
- } else if (retval != EWOULDBLOCK && retval != EAGAIN) {
- LOG(ERROR) << "Error sending messages! " << strerror(errno)
- << " << retval";
- return;
- }
- }
-
- if (!output_buffer_.empty()) {
- send_timer_.expires_from_now(std::chrono::microseconds(50));
- send_timer_.async_wait(std::bind(&UdpTunnelConnector::writeHandler, this,
- std::placeholders::_1));
- }
-}
-
-void UdpTunnelConnector::readHandler(std::error_code ec) {
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
-
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
- if (current_position_ == 0) {
- for (int i = 0; i < max_burst; i++) {
- auto read_buffer = getRawBuffer();
- rx_iovecs_[i][0].iov_base = read_buffer.first;
- rx_iovecs_[i][0].iov_len = read_buffer.second;
- rx_msgs_[i].msg_hdr.msg_iov = rx_iovecs_[i];
- rx_msgs_[i].msg_hdr.msg_iovlen = 1;
- }
- }
-
- int res = recvmmsg(socket_->native_handle(), rx_msgs_ + current_position_,
- max_burst - current_position_, MSG_DONTWAIT, nullptr);
- if (res < 0) {
- LOG(ERROR) << "Error receiving messages! " << strerror(errno) << " "
- << res;
- return;
- }
-
- for (int i = 0; i < res; i++) {
- auto packet = getPacketFromBuffer(
- reinterpret_cast<uint8_t *>(
- rx_msgs_[current_position_].msg_hdr.msg_iov[0].iov_base),
- rx_msgs_[current_position_].msg_len);
- receiveSuccess(*packet);
- receive_callback_(this, *packet,
- make_error_code(forwarder_error::success));
- ++current_position_;
- }
-
- doRecvPacket();
- } else {
- LOG(ERROR)
- << "Error in UDP: Receiving packets from a not connected socket.";
- }
- } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
- LOG(ERROR) << "The connection has been closed by the application.";
- return;
- } else {
- if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
- // receive_callback_(this, *read_msg_, ec);
- LOG(ERROR) << "Error in UDP connector: " << ec.value() << " "
- << ec.message();
- } else {
- LOG(ERROR) << "Error in connector while not connected. " << ec.value()
- << " " << ec.message();
- }
- }
-}
-#endif
-
-void UdpTunnelConnector::doRecvPacket() {
-#ifdef LINUX
- if (state_ == State::CONNECTED) {
-#if ((ASIO_VERSION / 100 % 1000) < 11)
- socket_->async_receive(asio::null_buffers(),
-#else
- socket_->async_wait(asio::ip::tcp::socket::wait_read,
-#endif
- std::bind(&UdpTunnelConnector::readHandler, this,
- std::placeholders::_1));
- }
-#else
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
- read_msg_ = getRawBuffer();
- socket_->async_receive_from(
- asio::buffer(read_msg_.first, read_msg_.second), remote_endpoint_recv_,
- [this](std::error_code ec, std::size_t length) {
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "UdpTunnelConnector received packet length=" << length;
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
- auto packet = getPacketFromBuffer(read_msg_.first, length);
- receiveSuccess(*packet);
- receive_callback_(this, *packet,
- make_error_code(forwarder_error::success));
- doRecvPacket();
- } else {
- LOG(ERROR) << "Error in UDP: Receiving packets from a not "
- "connected socket.";
- }
- } else if (ec.value() ==
- static_cast<int>(std::errc::operation_canceled)) {
- LOG(ERROR) << "The connection has been closed by the application.";
- return;
- } else {
- if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
- LOG(ERROR) << "Error in UDP connector: " << ec.value()
- << ec.message();
- } else {
- LOG(ERROR) << "Error while not connected";
- }
- }
- });
-#endif
-}
-
-void UdpTunnelConnector::doConnect() {
- asio::async_connect(
- *socket_, endpoint_iterator_,
- [this](std::error_code ec, asio::ip::udp::resolver::iterator) {
- if (!ec) {
- state_ = State::CONNECTED;
- doRecvPacket();
-
- if (data_available_) {
- data_available_ = false;
- doSendPacket();
- }
- } else {
- LOG(ERROR) << "UDP Connection failed!!!";
- timer_.expires_from_now(std::chrono::milliseconds(500));
- timer_.async_wait(std::bind(&UdpTunnelConnector::doConnect, this));
- }
- });
-}
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/io_modules/hicn-light-ng/CMakeLists.txt b/libtransport/src/io_modules/hicn-light-ng/CMakeLists.txt
new file mode 100644
index 000000000..325a8bd1d
--- /dev/null
+++ b/libtransport/src/io_modules/hicn-light-ng/CMakeLists.txt
@@ -0,0 +1,62 @@
+# Copyright (c) 2021-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.
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE)
+
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+
+ list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
+else()
+ if (DISABLE_SHARED_LIBRARIES)
+ if (WIN32)
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
+ else ()
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC} log)
+ endif ()
+ list(APPEND DEPENDENCIES
+ ${LIBHICNCTRL_STATIC}
+ )
+ else()
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_SHARED})
+ list(APPEND DEPENDENCIES
+ ${LIBHICNCTRL_SHARED}
+ )
+ endif()
+endif()
+
+list(APPEND MODULE_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.h
+)
+
+list(APPEND MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.cc
+)
+
+build_module(hicnlightng_module
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ LINK_LIBRARIES PRIVATE ${LIBHICNCTRL_LIBRARIES}
+ INCLUDE_DIRS
+ PRIVATE
+ ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ ${Libhicnctrl_INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
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
new file mode 100644
index 000000000..f67bd9447
--- /dev/null
+++ b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc
@@ -0,0 +1,264 @@
+/*
+ * 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/udp_connector.h>
+#include <io_modules/hicn-light-ng/hicn_forwarder_module.h>
+
+extern "C" {
+#include <hicn/ctrl/hicn-light-ng.h>
+}
+
+namespace transport {
+
+namespace core {
+
+HicnForwarderModule::HicnForwarderModule()
+ : IoModule(), connector_(nullptr), seq_(0) {}
+
+HicnForwarderModule::~HicnForwarderModule() {}
+
+void HicnForwarderModule::connect(bool is_consumer) {
+ connector_->connect("localhost", 9695);
+ connector_->setRole(is_consumer ? Connector::Role::CONSUMER
+ : Connector::Role::PRODUCER);
+}
+
+bool HicnForwarderModule::isConnected() { return connector_->isConnected(); }
+
+void HicnForwarderModule::send(Packet &packet) {
+ IoModule::send(packet);
+ packet.setChecksum();
+ connector_->send(packet);
+}
+
+void HicnForwarderModule::send(const utils::MemBuf::Ptr &packet) {
+ counters_.tx_packets++;
+ counters_.tx_bytes += packet->length();
+
+ // Perfect forwarding
+ connector_->send(packet);
+}
+
+void HicnForwarderModule::registerRoute(const Prefix &prefix) {
+ auto command = createCommandRoute(prefix.toSockaddr(),
+ (uint8_t)prefix.getPrefixLength());
+ if (!command) {
+ // TODO error
+ return;
+ }
+ send(command);
+}
+
+void HicnForwarderModule::sendMapme() {
+ auto command = createCommandMapmeSendUpdate();
+ if (!command) {
+ // TODO error
+ return;
+ }
+ send(command);
+}
+
+void HicnForwarderModule::setForwardingStrategy(const Prefix &prefix,
+ std::string &strategy) {
+ auto command = createCommandSetForwardingStrategy(
+ prefix.toSockaddr(), (uint8_t)prefix.getPrefixLength(), strategy);
+ if (!command) {
+ // TODO error
+ return;
+ }
+ send(command);
+}
+
+void HicnForwarderModule::closeConnection() {
+ auto command = createCommandDeleteConnection();
+ if (!command) {
+ // TODO error
+ return;
+ }
+
+ connector_->setSentCallback([](Connector *c, const std::error_code &ec) {
+ if (!ec) {
+ c->close();
+ }
+ });
+
+ send(command);
+}
+
+void HicnForwarderModule::init(
+ Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_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)));
+ }
+}
+
+void HicnForwarderModule::processControlMessageReply(
+ utils::MemBuf &packet_buffer) {
+ if (packet_buffer.data()[0] == NACK_LIGHT) {
+ throw errors::RuntimeException(
+ "Received Nack message from hicn light forwarder.");
+ }
+}
+
+std::uint32_t HicnForwarderModule::getMtu() { return interface_mtu; }
+
+bool HicnForwarderModule::isControlMessage(utils::MemBuf &packet_buffer) {
+ return packet_buffer.data()[0] == ACK_LIGHT ||
+ packet_buffer.data()[0] == NACK_LIGHT;
+}
+
+/**
+ * @return A valid msg_route_add_t structure if the command was successful, or
+ * with .command_id == COMMAND_TYPE_UNDEFINED in case of error.
+ */
+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 command = reinterpret_cast<msg_route_add_t *>(ret->writableData());
+ ret->append(sizeof(msg_route_add_t));
+ std::memset(command, 0, sizeof(*command));
+
+ if (!IS_VALID_FAMILY(addr->sa_family)) return nullptr;
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .cost = 1,
+ .family = (uint8_t)addr->sa_family,
+ .len = prefix_length,
+ },
+ };
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ command->payload.address.v4.as_inaddr =
+ ((sockaddr_in *)addr.get())->sin_addr;
+ break;
+ case AF_INET6:
+ command->payload.address.v6.as_in6addr =
+ ((sockaddr_in6 *)addr.get())->sin6_addr;
+ break;
+ }
+ snprintf(command->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ "SELF");
+
+ return ret;
+}
+
+utils::MemBuf::Ptr HicnForwarderModule::createCommandDeleteConnection() {
+ utils::MemBuf::Ptr ret =
+ utils::MemBuf::create(sizeof(msg_connection_remove_t));
+ auto command =
+ reinterpret_cast<msg_connection_remove_t *>(ret->writableData());
+ ret->append(sizeof(msg_connection_remove_t));
+ std::memset(command, 0, sizeof(*command));
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ };
+
+ snprintf(command->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ "SELF");
+
+ return ret;
+}
+
+utils::MemBuf::Ptr HicnForwarderModule::createCommandMapmeSendUpdate() {
+ utils::MemBuf::Ptr ret =
+ utils::MemBuf::create(sizeof(msg_mapme_send_update_t));
+ auto command =
+ reinterpret_cast<msg_mapme_send_update_t *>(ret->writableData());
+ ret->append(sizeof(msg_mapme_send_update_t));
+ std::memset(command, 0, sizeof(*command));
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_SEND_UPDATE,
+ .length = 1,
+ .seq_num = seq_++,
+ },
+ };
+
+ return ret;
+}
+
+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 command = reinterpret_cast<msg_strategy_set_t *>(ret->writableData());
+ ret->append(sizeof(msg_strategy_set_t));
+ std::memset(command, 0, sizeof(*command));
+
+ if (!IS_VALID_FAMILY(addr->sa_family)) return nullptr;
+
+ strategy_type_t strategy_type = strategy_type_from_str(strategy.c_str());
+ if (strategy_type == STRATEGY_TYPE_UNDEFINED) return nullptr;
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STRATEGY_SET,
+ .length = 1,
+ .seq_num = seq_++,
+ },
+ .payload =
+ {
+ .family = (uint8_t)addr->sa_family,
+ .len = (uint8_t)prefix_len,
+ .type = (uint8_t)strategy_type,
+ },
+ };
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ command->payload.address.v4.as_inaddr =
+ ((sockaddr_in *)addr.get())->sin_addr;
+ break;
+ case AF_INET6:
+ command->payload.address.v6.as_in6addr =
+ ((sockaddr_in6 *)addr.get())->sin6_addr;
+ break;
+ }
+
+ return ret;
+}
+
+extern "C" IoModule *create_module(void) { return new HicnForwarderModule(); }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/udp/hicn_forwarder_module.h b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h
index 845db73bf..0bf82757d 100644
--- a/libtransport/src/io_modules/udp/hicn_forwarder_module.h
+++ b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -18,15 +18,17 @@
#include <hicn/transport/core/io_module.h>
#include <hicn/transport/core/prefix.h>
+extern "C" {
+#include <hicn/ctrl/hicn-light-ng.h>
+}
+
namespace transport {
namespace core {
-class UdpSocketConnector;
+class UdpTunnelConnector;
class HicnForwarderModule : public IoModule {
- static constexpr uint8_t ack_code = 0xc2;
- static constexpr uint8_t nack_code = 0xc3;
static constexpr std::uint16_t interface_mtu = 1500;
public:
@@ -56,27 +58,45 @@ class HicnForwarderModule : public IoModule {
void connect(bool is_consumer) override;
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
bool isConnected() override;
void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
void registerRoute(const Prefix &prefix) override;
+ void sendMapme() override;
+
+ void setForwardingStrategy(const Prefix &prefix,
+ std::string &strategy) override;
+
std::uint32_t getMtu() override;
- bool isControlMessage(const uint8_t *message) override;
+ bool isControlMessage(utils::MemBuf &packet_buffer) override;
void processControlMessageReply(utils::MemBuf &packet_buffer) override;
void closeConnection() override;
private:
- UdpSocketConnector *connector_;
+ utils::MemBuf::Ptr createCommandRoute(std::unique_ptr<sockaddr> &&addr,
+ uint8_t prefix_length);
+ utils::MemBuf::Ptr createCommandDeleteConnection();
+ utils::MemBuf::Ptr createCommandMapmeSendUpdate();
+ utils::MemBuf::Ptr createCommandSetForwardingStrategy(
+ std::unique_ptr<sockaddr> &&addr, uint32_t prefix_len,
+ std::string strategy);
+
+ private:
+ std::shared_ptr<UdpTunnelConnector> connector_;
+
+ /* Sequence number used for sending control messages */
+ uint32_t seq_;
};
extern "C" IoModule *create_module(void);
diff --git a/libtransport/src/io_modules/loopback/CMakeLists.txt b/libtransport/src/io_modules/loopback/CMakeLists.txt
index b5ae0b7f7..817effb3b 100644
--- a/libtransport/src/io_modules/loopback/CMakeLists.txt
+++ b/libtransport/src/io_modules/loopback/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -20,11 +20,11 @@ list(APPEND MODULE_SOURCE_FILES
)
build_module(loopback_module
- SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBTRANSPORT_COMPONENT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ INCLUDE_DIRS
+ PRIVATE ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${Libhicn_INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
diff --git a/libtransport/src/io_modules/loopback/local_face.cc b/libtransport/src/io_modules/loopback/local_face.cc
index b73444330..7ef3f1a59 100644
--- a/libtransport/src/io_modules/loopback/local_face.cc
+++ b/libtransport/src/io_modules/loopback/local_face.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/io_modules/loopback/local_face.h b/libtransport/src/io_modules/loopback/local_face.h
index 1f4101447..f54f38afa 100644
--- a/libtransport/src/io_modules/loopback/local_face.h
+++ b/libtransport/src/io_modules/loopback/local_face.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/io_modules/loopback/loopback_module.cc b/libtransport/src/io_modules/loopback/loopback_module.cc
index f7dd5e7b0..5b7ed5f61 100644
--- a/libtransport/src/io_modules/loopback/loopback_module.cc
+++ b/libtransport/src/io_modules/loopback/loopback_module.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -41,7 +41,7 @@ void LoopbackModule::send(Packet &packet) {
local_faces_.at(1 - local_id_)->send(packet);
}
-void LoopbackModule::send(const uint8_t *packet, std::size_t len) {
+void LoopbackModule::send(const utils::MemBuf::Ptr &buffer) {
// not supported
throw errors::NotImplementedException();
}
@@ -57,6 +57,7 @@ void LoopbackModule::closeConnection() {
}
void LoopbackModule::init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name) {
@@ -64,8 +65,9 @@ void LoopbackModule::init(Connector::PacketReceivedCallback &&receive_callback,
local_id_ = global_counter_++;
local_faces_.emplace(
local_faces_.begin() + local_id_,
- new LocalConnector(io_service, std::move(receive_callback), nullptr,
- nullptr, std::move(reconnect_callback)));
+ new LocalConnector(io_service, std::move(receive_callback),
+ std::move(sent_callback), nullptr,
+ std::move(reconnect_callback)));
}
}
@@ -75,7 +77,9 @@ void LoopbackModule::processControlMessageReply(utils::MemBuf &packet_buffer) {
std::uint32_t LoopbackModule::getMtu() { return interface_mtu; }
-bool LoopbackModule::isControlMessage(const uint8_t *message) { return false; }
+bool LoopbackModule::isControlMessage(utils::MemBuf &packet_buffer) {
+ return false;
+}
extern "C" IoModule *create_module(void) { return new LoopbackModule(); }
diff --git a/libtransport/src/io_modules/loopback/loopback_module.h b/libtransport/src/io_modules/loopback/loopback_module.h
index 219fa8841..2779ae7e3 100644
--- a/libtransport/src/io_modules/loopback/loopback_module.h
+++ b/libtransport/src/io_modules/loopback/loopback_module.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -36,11 +36,12 @@ class LoopbackModule : public IoModule {
void connect(bool is_consumer) override;
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
bool isConnected() override;
void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
@@ -49,7 +50,7 @@ class LoopbackModule : public IoModule {
std::uint32_t getMtu() override;
- bool isControlMessage(const uint8_t *message) override;
+ bool isControlMessage(utils::MemBuf &packet_buffer) override;
void processControlMessageReply(utils::MemBuf &packet_buffer) override;
diff --git a/libtransport/src/io_modules/memif/CMakeLists.txt b/libtransport/src/io_modules/memif/CMakeLists.txt
index fc1c1f135..134ac1db6 100644
--- a/libtransport/src/io_modules/memif/CMakeLists.txt
+++ b/libtransport/src/io_modules/memif/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,18 +11,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-find_package(Vpp REQUIRED)
-find_package(Libmemif REQUIRED)
+
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(Vpp ${VPP_DEFAULT_VERSION} EXACT REQUIRED)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(HicnPlugin REQUIRED)
- find_package(SafeVapi REQUIRED)
+ find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
+ find_package(SafeVapi ${CURRENT_VERSION} REQUIRED)
else()
list(APPEND DEPENDENCIES
${SAFE_VAPI_SHARED}
)
endif()
+list(APPEND DEPENDENCIES
+ ${MEMIF_THIRD_PARTY_DEPENDENCIES}
+)
+
+##############################################################
+# Sources
+##############################################################
list(APPEND MODULE_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.h
${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.h
@@ -32,23 +42,23 @@ list(APPEND MODULE_HEADER_FILES
list(APPEND MODULE_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.c
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.cc
${CMAKE_CURRENT_SOURCE_DIR}/memif_vapi.c
${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_module.cc
)
build_module(memif_module
- SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBTRANSPORT_COMPONENT}-io-modules
- LINK_LIBRARIES ${LIBMEMIF_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
+ OBJECT_LIBRARIES ${MEMIF_THIRD_PARTY_OBJECT_LIBRARIES}
+ LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
INCLUDE_DIRS
- ${LIBTRANSPORT_INCLUDE_DIRS}
- ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- ${VPP_INCLUDE_DIRS}
- ${LIBMEMIF_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
+ PUBLIC
+ ${MEMIF_THIRD_PARTY_INCLUDE_DIRS}
+ ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ ${VPP_INCLUDE_DIRS}
+ ${LIBMEMIF_INCLUDE_DIRS}
+ ${SAFE_VAPI_INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS} ${MARCH_COMPILER_OPTIONS}
)
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.c b/libtransport/src/io_modules/memif/hicn_vapi.c
index 6d78026ab..753679f54 100644
--- a/libtransport/src/io_modules/memif/hicn_vapi.c
+++ b/libtransport/src/io_modules/memif/hicn_vapi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -27,8 +27,6 @@
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vnet/ip/format.h>
-#include <vnet/ip/ip4_packet.h>
-#include <vnet/ip/ip6_packet.h>
#include <vpp_plugins/hicn/error.h>
#include <vppinfra/error.h>
@@ -46,9 +44,6 @@ u8 *format_vl_api_address_union(u8 *s, va_list *args) { return NULL; }
/*********************************************************************************/
-DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-DEFINE_VAPI_MSG_IDS_IP_API_JSON
-
static vapi_error_e register_prod_app_cb(
vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
vapi_payload_hicn_api_register_prod_app_reply *reply) {
@@ -78,7 +73,7 @@ int hicn_vapi_register_prod_app(vapi_ctx_t ctx,
vapi_msg_hicn_api_register_prod_app *msg =
vapi_alloc_hicn_api_register_prod_app(ctx);
- if (ip46_address_is_ip4((ip46_address_t *)&input_params->prefix->address)) {
+ if (ip_address_is_v4((ip_address_t *)&input_params->prefix->address)) {
memcpy(&msg->payload.prefix.address.un.ip4, &input_params->prefix->address,
sizeof(ip4_address_t));
msg->payload.prefix.address.af = ADDRESS_IP4;
@@ -190,7 +185,7 @@ int hicn_vapi_register_route(vapi_ctx_t ctx,
vapi_msg_ip_route_add_del *msg = vapi_alloc_ip_route_add_del(ctx, 1);
msg->payload.is_add = 1;
- if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ if (ip_address_is_v4((ip_address_t *)(input_params->prod_addr))) {
memcpy(&msg->payload.route.prefix.address.un.ip4,
&input_params->prefix->address.v4, sizeof(ip4_address_t));
msg->payload.route.prefix.address.af = ADDRESS_IP4;
@@ -204,7 +199,7 @@ int hicn_vapi_register_route(vapi_ctx_t ctx,
msg->payload.route.paths[0].sw_if_index = ~0;
msg->payload.route.paths[0].table_id = 0;
- if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ if (ip_address_is_v4((ip_address_t *)(input_params->prod_addr))) {
memcpy(&(msg->payload.route.paths[0].nh.address.ip4),
input_params->prod_addr->v4.as_u8, sizeof(ip4_address_t));
msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
@@ -214,7 +209,7 @@ int hicn_vapi_register_route(vapi_ctx_t ctx,
msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
}
- msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
+ msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL;
msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
int ret = vapi_ip_route_add_del(ctx, msg, reigster_route_cb, NULL);
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.h b/libtransport/src/io_modules/memif/hicn_vapi.h
index e94c97749..967179f68 100644
--- a/libtransport/src/io_modules/memif/hicn_vapi.h
+++ b/libtransport/src/io_modules/memif/hicn_vapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/io_modules/memif/memif_connector.cc b/libtransport/src/io_modules/memif/memif_connector.cc
deleted file mode 100644
index 68ad52b63..000000000
--- a/libtransport/src/io_modules/memif/memif_connector.cc
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <glog/logging.h>
-#include <hicn/transport/errors/not_implemented_exception.h>
-#include <io_modules/memif/memif_connector.h>
-#include <sys/epoll.h>
-
-#include <cstdlib>
-
-extern "C" {
-#include <memif/libmemif.h>
-};
-
-#define CANCEL_TIMER 1
-
-namespace transport {
-
-namespace core {
-
-struct memif_connection {
- uint16_t index;
- /* memif conenction handle */
- memif_conn_handle_t conn;
- /* transmit queue id */
- uint16_t tx_qid;
- /* tx buffers */
- memif_buffer_t *tx_bufs;
- /* allocated tx buffers counter */
- /* number of tx buffers pointing to shared memory */
- uint16_t tx_buf_num;
- /* rx buffers */
- memif_buffer_t *rx_bufs;
- /* allcoated rx buffers counter */
- /* number of rx buffers pointing to shared memory */
- uint16_t rx_buf_num;
- /* interface ip address */
- uint8_t ip_addr[4];
-};
-
-std::once_flag MemifConnector::flag_;
-utils::EpollEventReactor MemifConnector::main_event_reactor_;
-
-MemifConnector::MemifConnector(PacketReceivedCallback &&receive_callback,
- PacketSentCallback &&packet_sent,
- OnCloseCallback &&close_callback,
- OnReconnectCallback &&on_reconnect,
- asio::io_service &io_service,
- std::string app_name)
- : Connector(std::move(receive_callback), std::move(packet_sent),
- std::move(close_callback), std::move(on_reconnect)),
- memif_worker_(nullptr),
- timer_set_(false),
- send_timer_(std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
- disconnect_timer_(
- std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
- io_service_(io_service),
- work_(asio::make_work_guard(io_service_)),
- memif_connection_(std::make_unique<memif_connection_t>()),
- tx_buf_counter_(0),
- is_reconnection_(false),
- data_available_(false),
- app_name_(app_name),
- socket_filename_("") {
- std::call_once(MemifConnector::flag_, &MemifConnector::init, this);
-}
-
-MemifConnector::~MemifConnector() { close(); }
-
-void MemifConnector::init() {
- /* initialize memory interface */
- int err = memif_init(controlFdUpdate, const_cast<char *>(app_name_.c_str()),
- nullptr, nullptr, nullptr);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_init: " << memif_strerror(err);
- }
-}
-
-void MemifConnector::connect(uint32_t memif_id, long memif_mode) {
- state_ = State::CONNECTING;
-
- memif_id_ = memif_id;
- socket_filename_ = "/run/vpp/memif.sock";
-
- createMemif(memif_id, memif_mode, nullptr);
-
- while (state_ != State::CONNECTED) {
- MemifConnector::main_event_reactor_.runOneEvent();
- }
-
- int err;
-
- /* get interrupt queue id */
- int fd = -1;
- err = memif_get_queue_efd(memif_connection_->conn, 0, &fd);
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_get_queue_efd: " << memif_strerror(err);
- return;
- }
-
- // Remove fd from main epoll
- main_event_reactor_.delFileDescriptor(fd);
-
- // Add fd to epoll of instance
- event_reactor_.addFileDescriptor(
- fd, EPOLLIN, [this](const utils::Event &evt) -> int {
- return onInterrupt(memif_connection_->conn, this, 0);
- });
-
- memif_worker_ = std::make_unique<std::thread>(
- std::bind(&MemifConnector::threadMain, this));
-}
-
-int MemifConnector::createMemif(uint32_t index, uint8_t mode, char *s) {
- memif_connection_t *c = memif_connection_.get();
-
- /* setting memif connection arguments */
- memif_conn_args_t args;
- memset(&args, 0, sizeof(args));
-
- args.is_master = mode;
- args.log2_ring_size = MEMIF_LOG2_RING_SIZE;
- args.buffer_size = MEMIF_BUF_SIZE;
- args.num_s2m_rings = 1;
- args.num_m2s_rings = 1;
- strncpy((char *)args.interface_name, IF_NAME, strlen(IF_NAME) + 1);
- args.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
-
- int err;
-
- err = memif_create_socket(&args.socket, socket_filename_.c_str(), nullptr);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- throw errors::RuntimeException(memif_strerror(err));
- }
-
- args.interface_id = index;
- /* last argument for memif_create (void * private_ctx) is used by user
- to identify connection. this context is returned with callbacks */
-
- /* default interrupt */
- if (s == nullptr) {
- err = memif_create(&c->conn, &args, onConnect, onDisconnect, onInterrupt,
- this);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- throw errors::RuntimeException(memif_strerror(err));
- }
- }
-
- c->index = (uint16_t)index;
- c->tx_qid = 0;
- /* alloc memif buffers */
- c->rx_buf_num = 0;
- c->rx_bufs = static_cast<memif_buffer_t *>(
- malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
- c->tx_buf_num = 0;
- c->tx_bufs = static_cast<memif_buffer_t *>(
- malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
-
- // memif_set_rx_mode (c->conn, MEMIF_RX_MODE_POLLING, 0);
-
- return 0;
-}
-
-int MemifConnector::deleteMemif() {
- memif_connection_t *c = memif_connection_.get();
-
- if (c->rx_bufs) {
- free(c->rx_bufs);
- }
-
- c->rx_bufs = nullptr;
- c->rx_buf_num = 0;
-
- if (c->tx_bufs) {
- free(c->tx_bufs);
- }
-
- c->tx_bufs = nullptr;
- c->tx_buf_num = 0;
-
- int err;
- /* disconenct then delete memif connection */
- err = memif_delete(&c->conn);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_delete: " << memif_strerror(err);
- }
-
- if (TRANSPORT_EXPECT_FALSE(c->conn != nullptr)) {
- LOG(ERROR) << "memif delete fail";
- }
-
- return 0;
-}
-
-int MemifConnector::controlFdUpdate(int fd, uint8_t events, void *private_ctx) {
- /* convert memif event definitions to epoll events */
- if (events & MEMIF_FD_EVENT_DEL) {
- return MemifConnector::main_event_reactor_.delFileDescriptor(fd);
- }
-
- uint32_t evt = 0;
-
- if (events & MEMIF_FD_EVENT_READ) {
- evt |= EPOLLIN;
- }
-
- if (events & MEMIF_FD_EVENT_WRITE) {
- evt |= EPOLLOUT;
- }
-
- if (events & MEMIF_FD_EVENT_MOD) {
- return MemifConnector::main_event_reactor_.modFileDescriptor(fd, evt);
- }
-
- return MemifConnector::main_event_reactor_.addFileDescriptor(
- fd, evt, [](const utils::Event &evt) -> int {
- uint32_t event = 0;
- int memif_err = 0;
-
- if (evt.events & EPOLLIN) {
- event |= MEMIF_FD_EVENT_READ;
- }
-
- if (evt.events & EPOLLOUT) {
- event |= MEMIF_FD_EVENT_WRITE;
- }
-
- if (evt.events & EPOLLERR) {
- event |= MEMIF_FD_EVENT_ERROR;
- }
-
- memif_err = memif_control_fd_handler(evt.data.fd, event);
-
- if (TRANSPORT_EXPECT_FALSE(memif_err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_control_fd_handler: "
- << memif_strerror(memif_err);
- }
-
- return 0;
- });
-}
-
-int MemifConnector::bufferAlloc(long n, uint16_t qid) {
- memif_connection_t *c = memif_connection_.get();
- int err;
- uint16_t r;
- /* set data pointer to shared memory and set buffer_len to shared mmeory
- * buffer len */
- err = memif_buffer_alloc(c->conn, qid, c->tx_bufs, n, &r, 2000);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_buffer_alloc: " << memif_strerror(err);
- return -1;
- }
-
- c->tx_buf_num += r;
- return r;
-}
-
-int MemifConnector::txBurst(uint16_t qid) {
- memif_connection_t *c = memif_connection_.get();
- int err;
- uint16_t r;
- /* inform peer memif interface about data in shared memory buffers */
- /* mark memif buffers as free */
- err = memif_tx_burst(c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_tx_burst: " << memif_strerror(err);
- }
-
- // err = memif_refill_queue(c->conn, qid, r, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_tx_burst: " << memif_strerror(err);
- c->tx_buf_num -= r;
- return -1;
- }
-
- c->tx_buf_num -= r;
- return 0;
-}
-
-void MemifConnector::sendCallback(const std::error_code &ec) {
- timer_set_ = false;
-
- if (TRANSPORT_EXPECT_TRUE(!ec && state_ == State::CONNECTED)) {
- doSend();
- }
-}
-
-void MemifConnector::processInputBuffer(std::uint16_t total_packets) {
- utils::MemBuf::Ptr ptr;
-
- for (; total_packets > 0; total_packets--) {
- if (input_buffer_.pop(ptr)) {
- receive_callback_(this, *ptr, std::make_error_code(std::errc(0)));
- }
- }
-}
-
-/* informs user about connected status. private_ctx is used by user to identify
- connection (multiple connections WIP) */
-int MemifConnector::onConnect(memif_conn_handle_t conn, void *private_ctx) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
- connector->state_ = State::CONNECTED;
- memif_refill_queue(conn, 0, -1, 0);
-
- return 0;
-}
-
-/* informs user about disconnected status. private_ctx is used by user to
- identify connection (multiple connections WIP) */
-int MemifConnector::onDisconnect(memif_conn_handle_t conn, void *private_ctx) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
- connector->state_ = State::CLOSED;
- return 0;
-}
-
-void MemifConnector::threadMain() { event_reactor_.runEventLoop(1000); }
-
-int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
- uint16_t qid) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
-
- memif_connection_t *c = connector->memif_connection_.get();
- int err = MEMIF_ERR_SUCCESS, ret_val;
- uint16_t total_packets = 0;
- uint16_t rx;
-
- do {
- err = memif_rx_burst(conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
- ret_val = err;
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS &&
- err != MEMIF_ERR_NOBUF)) {
- LOG(ERROR) << "memif_rx_burst: " << memif_strerror(err);
- goto error;
- }
-
- c->rx_buf_num += rx;
-
- if (TRANSPORT_EXPECT_FALSE(connector->io_service_.stopped())) {
- LOG(ERROR) << "socket stopped: ignoring " << rx << " packets";
- goto error;
- }
-
- std::size_t packet_length;
- for (int i = 0; i < rx; i++) {
- auto buffer = connector->getRawBuffer();
- packet_length = (c->rx_bufs + i)->len;
- std::memcpy(buffer.first, (c->rx_bufs + i)->data, packet_length);
- auto packet = connector->getPacketFromBuffer(buffer.first, packet_length);
-
- if (!connector->input_buffer_.push(std::move(packet))) {
- LOG(ERROR) << "Error pushing packet. Ring buffer full.";
-
- // TODO Here we should consider the possibility to signal the congestion
- // to the application, that would react properly (e.g. slow down
- // message)
- }
- }
-
- /* mark memif buffers and shared memory buffers as free */
- /* free processed buffers */
-
- err = memif_refill_queue(conn, qid, rx, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
- }
-
- c->rx_buf_num -= rx;
- total_packets += rx;
-
- } while (ret_val == MEMIF_ERR_NOBUF);
-
- connector->io_service_.post(
- std::bind(&MemifConnector::processInputBuffer, connector, total_packets));
-
- return 0;
-
-error:
- err = memif_refill_queue(c->conn, qid, rx, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
- }
- c->rx_buf_num -= rx;
-
- return 0;
-}
-
-void MemifConnector::close() {
- if (state_ != State::CLOSED) {
- disconnect_timer_->expiresFromNow(std::chrono::microseconds(50));
- disconnect_timer_->asyncWait([this](const std::error_code &ec) {
- deleteMemif();
- event_reactor_.stop();
- });
-
- if (memif_worker_ && memif_worker_->joinable()) {
- memif_worker_->join();
- }
- }
-}
-
-void MemifConnector::send(Packet &packet) {
- {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- output_buffer_.push_back(packet.shared_from_this());
- }
-#if CANCEL_TIMER
- if (!timer_set_) {
- timer_set_ = true;
- send_timer_->expiresFromNow(std::chrono::microseconds(50));
- send_timer_->asyncWait(
- std::bind(&MemifConnector::sendCallback, this, std::placeholders::_1));
- }
-#endif
-}
-
-int MemifConnector::doSend() {
- std::size_t max = 0;
- int32_t n = 0;
- std::size_t size = 0;
-
- {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- size = output_buffer_.size();
- }
-
- do {
- max = size < MAX_MEMIF_BUFS ? size : MAX_MEMIF_BUFS;
- n = bufferAlloc(max, memif_connection_->tx_qid);
-
- if (TRANSPORT_EXPECT_FALSE(n < 0)) {
- LOG(ERROR) << "Error allocating buffers.";
- return -1;
- }
-
- for (uint16_t i = 0; i < n; i++) {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
-
- auto packet = output_buffer_.front().get();
- const utils::MemBuf *current = packet;
- std::size_t offset = 0;
- uint8_t *shared_buffer =
- reinterpret_cast<uint8_t *>(memif_connection_->tx_bufs[i].data);
- do {
- std::memcpy(shared_buffer + offset, current->data(), current->length());
- offset += current->length();
- current = current->next();
- } while (current != packet);
-
- memif_connection_->tx_bufs[i].len = uint32_t(offset);
-
- output_buffer_.pop_front();
- }
-
- txBurst(memif_connection_->tx_qid);
-
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- size = output_buffer_.size();
- } while (size > 0);
-
- return 0;
-}
-
-void MemifConnector::send(const uint8_t *packet, std::size_t len) {
- throw errors::NotImplementedException();
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/memif/memif_vapi.c b/libtransport/src/io_modules/memif/memif_vapi.c
index b3da2b012..54e2c3134 100644
--- a/libtransport/src/io_modules/memif/memif_vapi.c
+++ b/libtransport/src/io_modules/memif/memif_vapi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,8 +22,6 @@
#include <vapi/vapi_safe.h>
#include <vppinfra/clib.h>
-DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
-
static vapi_error_e memif_details_cb(vapi_ctx_t ctx, void *callback_ctx,
vapi_error_e rv, bool is_last,
vapi_payload_memif_details *reply) {
@@ -45,6 +43,9 @@ static vapi_error_e memif_details_cb(vapi_ctx_t ctx, void *callback_ctx,
int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id) {
vapi_lock();
vapi_msg_memif_dump *msg = vapi_alloc_memif_dump(ctx);
+
+ // Initialize memif id to 0
+ *memif_id = 0;
int ret = vapi_memif_dump(ctx, msg, memif_details_cb, memif_id);
vapi_unlock();
return ret;
diff --git a/libtransport/src/io_modules/memif/memif_vapi.h b/libtransport/src/io_modules/memif/memif_vapi.h
index bcf06ed43..f5f0639e7 100644
--- a/libtransport/src/io_modules/memif/memif_vapi.h
+++ b/libtransport/src/io_modules/memif/memif_vapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -44,6 +44,10 @@ typedef struct memif_output_params_s {
int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id);
+int memif_vapi_create_socket(vapi_ctx_t ctx,
+ memif_create_params_t *input_params,
+ memif_output_params_t *output_params);
+
int memif_vapi_create_memif(vapi_ctx_t ctx, memif_create_params_t *input_params,
memif_output_params_t *output_params);
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
index 44c8376df..65260077a 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,16 +13,16 @@
* limitations under the License.
*/
+#include <core/memif_connector.h>
#include <glog/logging.h>
#include <hicn/transport/config.h>
#include <hicn/transport/errors/not_implemented_exception.h>
#include <io_modules/memif/hicn_vapi.h>
-#include <io_modules/memif/memif_connector.h>
#include <io_modules/memif/memif_vapi.h>
#include <io_modules/memif/vpp_forwarder_module.h>
extern "C" {
-#include <memif/libmemif.h>
+#include <libmemif.h>
};
typedef enum { MASTER = 0, SLAVE = 1 } memif_role_t;
@@ -39,21 +39,24 @@ namespace core {
VPPForwarderModule::VPPForwarderModule()
: IoModule(),
connector_(nullptr),
+ memif_id_(0),
sw_if_index_(~0),
face_id1_(~0),
face_id2_(~0),
is_consumer_(false) {}
-VPPForwarderModule::~VPPForwarderModule() { delete connector_; }
+VPPForwarderModule::~VPPForwarderModule() {}
void VPPForwarderModule::init(
Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service, const std::string &app_name) {
if (!connector_) {
- connector_ =
- new MemifConnector(std::move(receive_callback), 0, 0,
- std::move(reconnect_callback), io_service, app_name);
+ connector_ = std::make_unique<MemifConnector>(
+ std::move(receive_callback), std::move(sent_callback),
+ Connector::OnCloseCallback(0), std::move(reconnect_callback),
+ io_service, app_name);
}
}
@@ -62,7 +65,7 @@ void VPPForwarderModule::processControlMessageReply(
throw errors::NotImplementedException();
}
-bool VPPForwarderModule::isControlMessage(const uint8_t *message) {
+bool VPPForwarderModule::isControlMessage(utils::MemBuf &packet_buffer) {
return false;
}
@@ -73,12 +76,12 @@ void VPPForwarderModule::send(Packet &packet) {
connector_->send(packet);
}
-void VPPForwarderModule::send(const uint8_t *packet, std::size_t len) {
+void VPPForwarderModule::send(const utils::MemBuf::Ptr &buffer) {
counters_.tx_packets++;
- counters_.tx_bytes += len;
+ counters_.tx_bytes += buffer->length();
// Perfect forwarding
- connector_->send(packet, len);
+ connector_->send(buffer);
}
std::uint32_t VPPForwarderModule::getMtu() { return interface_mtu; }
@@ -170,7 +173,8 @@ void VPPForwarderModule::connect(bool is_consumer) {
consumerConnection();
}
- connector_->connect(memif_id_, 0);
+ connector_->connect(memif_id_, 0 /* is_master = false */,
+ memif_socket_filename);
connector_->setRole(is_consumer_ ? Connector::Role::CONSUMER
: Connector::Role::PRODUCER);
}
@@ -207,7 +211,8 @@ void VPPForwarderModule::registerRoute(const Prefix &prefix) {
throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
}
- inet6_address_ = *output.prod_addr;
+ std::memcpy(inet6_address_.v6.as_u8, output.prod_addr->v6.as_u8,
+ sizeof(inet6_address_));
face_id1_ = output.face_id;
} else {
@@ -228,8 +233,6 @@ void VPPForwarderModule::registerRoute(const Prefix &prefix) {
void VPPForwarderModule::closeConnection() {
if (VPPForwarderModule::sock_) {
- connector_->close();
-
if (is_consumer_) {
hicn_del_face_app_input_params params;
params.face_id = face_id1_;
@@ -242,6 +245,8 @@ void VPPForwarderModule::closeConnection() {
hicn_vapi_face_prod_del(VPPForwarderModule::sock_, &params);
}
+ connector_->close();
+
if (sw_if_index_ != uint32_t(~0)) {
int ret =
memif_vapi_delete_memif(VPPForwarderModule::sock_, sw_if_index_);
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.h b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
index 8c4114fed..162ee0ca5 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.h
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,7 +32,8 @@ namespace core {
class MemifConnector;
class VPPForwarderModule : public IoModule {
- static constexpr std::uint16_t interface_mtu = 1500;
+ static inline std::uint16_t interface_mtu = 1500;
+ static inline std::string const memif_socket_filename = "/run/vpp/memif.sock";
public:
VPPForwarderModule();
@@ -41,11 +42,12 @@ class VPPForwarderModule : public IoModule {
void connect(bool is_consumer) override;
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
bool isConnected() override;
void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
@@ -54,7 +56,7 @@ class VPPForwarderModule : public IoModule {
std::uint32_t getMtu() override;
- bool isControlMessage(const uint8_t *message) override;
+ bool isControlMessage(utils::MemBuf &packet_buffer) override;
void processControlMessageReply(utils::MemBuf &packet_buffer) override;
@@ -66,7 +68,7 @@ class VPPForwarderModule : public IoModule {
void producerConnection();
private:
- MemifConnector *connector_;
+ std::shared_ptr<MemifConnector> connector_;
uint32_t memif_id_;
uint32_t sw_if_index_;
// A consumer socket in vpp has two faces (ipv4 and ipv6)
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc b/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
deleted file mode 100644
index 62efdc3a5..000000000
--- a/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/raw_socket_connector.h>
-#include <hicn/transport/utils/conversions.h>
-#include <net/if.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#define MY_DEST_MAC0 0x0a
-#define MY_DEST_MAC1 0x7b
-#define MY_DEST_MAC2 0x7c
-#define MY_DEST_MAC3 0x1c
-#define MY_DEST_MAC4 0x4a
-#define MY_DEST_MAC5 0x14
-
-namespace transport {
-
-namespace core {
-
-RawSocketConnector::RawSocketConnector(
- PacketReceivedCallback &&receive_callback,
- OnReconnect &&on_reconnect_callback, asio::io_service &io_service,
- std::string app_name)
- : Connector(std::move(receive_callback), std::move(on_reconnect_callback)),
- io_service_(io_service),
- socket_(io_service_, raw_protocol(PF_PACKET, SOCK_RAW)),
- // resolver_(io_service_),
- timer_(io_service_),
- read_msg_(packet_pool_.makePtr(nullptr)),
- data_available_(false),
- app_name_(app_name) {
- memset(&link_layer_address_, 0, sizeof(link_layer_address_));
-}
-
-RawSocketConnector::~RawSocketConnector() {}
-
-void RawSocketConnector::connect(const std::string &interface_name,
- const std::string &mac_address_str) {
- state_ = ConnectorState::CONNECTING;
- memset(&ethernet_header_, 0, sizeof(ethernet_header_));
- struct ifreq ifr;
- struct ifreq if_mac;
- uint8_t mac_address[6];
-
- utils::convertStringToMacAddress(mac_address_str, mac_address);
-
- // Get interface mac address
- int fd = static_cast<int>(socket_.native_handle());
-
- /* Get the index of the interface to send on */
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, interface_name.c_str(), interface_name.size());
-
- // if (ioctl(fd, SIOCGIFINDEX, &if_idx) < 0) {
- // perror("SIOCGIFINDEX");
- // }
-
- /* Get the MAC address of the interface to send on */
- memset(&if_mac, 0, sizeof(struct ifreq));
- strncpy(if_mac.ifr_name, interface_name.c_str(), interface_name.size());
- if (ioctl(fd, SIOCGIFHWADDR, &if_mac) < 0) {
- perror("SIOCGIFHWADDR");
- throw errors::RuntimeException("Interface does not exist");
- }
-
- /* Ethernet header */
- for (int i = 0; i < 6; i++) {
- ethernet_header_.ether_shost[i] =
- ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[i];
- ethernet_header_.ether_dhost[i] = mac_address[i];
- }
-
- /* Ethertype field */
- ethernet_header_.ether_type = htons(ETH_P_IPV6);
-
- strcpy(ifr.ifr_name, interface_name.c_str());
-
- if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) {
- memcpy(link_layer_address_.sll_addr, ifr.ifr_hwaddr.sa_data, 6);
- }
-
- // memset(&ifr, 0, sizeof(ifr));
- // ioctl(fd, SIOCGIFFLAGS, &ifr);
- // ifr.ifr_flags |= IFF_PROMISC;
- // ioctl(fd, SIOCSIFFLAGS, &ifr);
-
- link_layer_address_.sll_family = AF_PACKET;
- link_layer_address_.sll_protocol = htons(ETH_P_ALL);
- link_layer_address_.sll_ifindex = if_nametoindex(interface_name.c_str());
- link_layer_address_.sll_hatype = 1;
- link_layer_address_.sll_halen = 6;
-
- // startConnectionTimer();
- doConnect();
- doRecvPacket();
-}
-
-void RawSocketConnector::send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent) {
- if (packet_sent != 0) {
- socket_.async_send(
- asio::buffer(packet, len),
- [packet_sent](std::error_code ec, std::size_t /*length*/) {
- packet_sent();
- });
- } else {
- if (state_ == ConnectorState::CONNECTED) {
- socket_.send(asio::buffer(packet, len));
- }
- }
-}
-
-void RawSocketConnector::send(const Packet::MemBufPtr &packet) {
- io_service_.post([this, packet]() {
- bool write_in_progress = !output_buffer_.empty();
- output_buffer_.push_back(std::move(packet));
- if (TRANSPORT_EXPECT_TRUE(state_ == ConnectorState::CONNECTED)) {
- if (!write_in_progress) {
- doSendPacket();
- } else {
- // Tell the handle connect it has data to write
- data_available_ = true;
- }
- }
- });
-}
-
-void RawSocketConnector::close() {
- io_service_.post([this]() { socket_.close(); });
-}
-
-void RawSocketConnector::doSendPacket() {
- auto packet = output_buffer_.front().get();
- auto array = std::vector<asio::const_buffer>();
-
- const utils::MemBuf *current = packet;
- do {
- array.push_back(asio::const_buffer(current->data(), current->length()));
- current = current->next();
- } while (current != packet);
-
- socket_.async_send(
- std::move(array),
- [this /*, packet*/](std::error_code ec, std::size_t bytes_transferred) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- output_buffer_.pop_front();
- if (!output_buffer_.empty()) {
- doSendPacket();
- }
- } else {
- LOG(ERROR) << ec.value() << " " << ec.message();
- }
- });
-}
-
-void RawSocketConnector::doRecvPacket() {
- read_msg_ = getPacket();
- socket_.async_receive(
- asio::buffer(read_msg_->writableData(), packet_size),
- [this](std::error_code ec, std::size_t bytes_transferred) mutable {
- if (!ec) {
- // Ignore packets that are not for us
- uint8_t *dst_mac_address = const_cast<uint8_t *>(read_msg_->data());
- if (!std::memcmp(dst_mac_address, ethernet_header_.ether_shost,
- ETHER_ADDR_LEN)) {
- read_msg_->append(bytes_transferred);
- read_msg_->trimStart(sizeof(struct ether_header));
- receive_callback_(std::move(read_msg_));
- }
- } else {
- LOG(ERROR) << ec.value() << " " << ec.message();
- }
- doRecvPacket();
- });
-}
-
-void RawSocketConnector::doConnect() {
- state_ = ConnectorState::CONNECTED;
- socket_.bind(raw_endpoint(&link_layer_address_, sizeof(link_layer_address_)));
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_connector.h b/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
deleted file mode 100644
index 06892b3d8..000000000
--- a/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <core/connector.h>
-#include <hicn/transport/config.h>
-#include <hicn/transport/core/asio_wrapper.h>
-#include <hicn/transport/core/name.h>
-#include <linux/if_packet.h>
-#include <net/ethernet.h>
-#include <sys/socket.h>
-
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-using asio::generic::raw_protocol;
-using raw_endpoint = asio::generic::basic_endpoint<raw_protocol>;
-
-class RawSocketConnector : public Connector {
- public:
- RawSocketConnector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&reconnect_callback,
- asio::io_service &io_service,
- std::string app_name = "Libtransport");
-
- ~RawSocketConnector() override;
-
- void send(const Packet::MemBufPtr &packet) override;
-
- void send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent = 0) override;
-
- void close() override;
-
- void connect(const std::string &interface_name,
- const std::string &mac_address_str);
-
- private:
- void doConnect();
-
- void doRecvPacket();
-
- void doSendPacket();
-
- private:
- asio::io_service &io_service_;
- raw_protocol::socket socket_;
-
- struct ether_header ethernet_header_;
-
- struct sockaddr_ll link_layer_address_;
-
- asio::steady_timer timer_;
-
- utils::ObjectPool<utils::MemBuf>::Ptr read_msg_;
-
- bool data_available_;
- std::string app_name_;
-};
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_interface.cc b/libtransport/src/io_modules/raw_socket/raw_socket_interface.cc
deleted file mode 100644
index dcf489f59..000000000
--- a/libtransport/src/io_modules/raw_socket/raw_socket_interface.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/raw_socket_interface.h>
-#include <hicn/transport/utils/linux.h>
-
-#include <fstream>
-
-namespace transport {
-
-namespace core {
-
-static std::string config_folder_path = "/etc/transport/interface.conf.d";
-
-RawSocketInterface::RawSocketInterface(RawSocketConnector &connector)
- : ForwarderInterface<RawSocketInterface, RawSocketConnector>(connector) {}
-
-RawSocketInterface::~RawSocketInterface() {}
-
-void RawSocketInterface::connect(bool is_consumer) {
- std::string complete_filename =
- config_folder_path + std::string("/") + output_interface_;
-
- std::ifstream is(complete_filename);
- std::string interface;
-
- if (is) {
- is >> remote_mac_address_;
- }
-
- // Get interface ip address
- struct sockaddr_in6 address = {0};
- utils::retrieveInterfaceAddress(output_interface_, &address);
-
- std::memcpy(&inet6_address_.v6.as_u8, &address.sin6_addr,
- sizeof(address.sin6_addr));
- connector_.connect(output_interface_, remote_mac_address_);
-}
-
-void RawSocketInterface::registerRoute(Prefix &prefix) { return; }
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_interface.h b/libtransport/src/io_modules/raw_socket/raw_socket_interface.h
deleted file mode 100644
index 7036cac7e..000000000
--- a/libtransport/src/io_modules/raw_socket/raw_socket_interface.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <core/forwarder_interface.h>
-#include <core/raw_socket_connector.h>
-#include <hicn/transport/core/prefix.h>
-
-#include <atomic>
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-class RawSocketInterface
- : public ForwarderInterface<RawSocketInterface, RawSocketConnector> {
- public:
- typedef RawSocketConnector ConnectorType;
-
- RawSocketInterface(RawSocketConnector &connector);
-
- ~RawSocketInterface();
-
- void connect(bool is_consumer);
-
- void registerRoute(Prefix &prefix);
-
- std::uint16_t getMtu() { return interface_mtu; }
-
- TRANSPORT_ALWAYS_INLINE static bool isControlMessageImpl(
- const uint8_t *message) {
- return false;
- }
-
- TRANSPORT_ALWAYS_INLINE void processControlMessageReplyImpl(
- Packet::MemBufPtr &&packet_buffer) {}
-
- TRANSPORT_ALWAYS_INLINE void closeConnection(){};
-
- private:
- static constexpr std::uint16_t interface_mtu = 1500;
- std::string remote_mac_address_;
-};
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/io_modules/udp/CMakeLists.txt b/libtransport/src/io_modules/udp/CMakeLists.txt
deleted file mode 100644
index b9c19d063..000000000
--- a/libtransport/src/io_modules/udp/CMakeLists.txt
+++ /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.
-
-list(APPEND MODULE_HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.h
-)
-
-list(APPEND MODULE_SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.cc
-)
-
-build_module(hicnlight_module
- SHARED
- SOURCES ${MODULE_SOURCE_FILES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${LIBTRANSPORT_COMPONENT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
-)
diff --git a/libtransport/src/io_modules/udp/hicn_forwarder_module.cc b/libtransport/src/io_modules/udp/hicn_forwarder_module.cc
deleted file mode 100644
index ba08dd8c0..000000000
--- a/libtransport/src/io_modules/udp/hicn_forwarder_module.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <io_modules/udp/hicn_forwarder_module.h>
-#include <io_modules/udp/udp_socket_connector.h>
-
-union AddressLight {
- uint32_t ipv4;
- struct in6_addr ipv6;
-};
-
-typedef struct {
- uint8_t message_type;
- uint8_t command_id;
- uint16_t length;
- uint32_t seq_num;
-} CommandHeader;
-
-typedef struct {
- uint8_t message_type;
- uint8_t command_id;
- uint16_t length;
- uint32_t seq_num;
- char symbolic_or_connid[16];
- union AddressLight address;
- uint16_t cost;
- uint8_t address_type;
- uint8_t len;
-} RouteToSelfCommand;
-
-typedef struct {
- uint8_t message_type;
- uint8_t command_id;
- uint16_t length;
- uint32_t seq_num;
- char symbolic_or_connid[16];
-} DeleteSelfConnectionCommand;
-
-namespace {
-static constexpr uint8_t addr_inet = 1;
-static constexpr uint8_t addr_inet6 = 2;
-static constexpr uint8_t add_route_command = 3;
-static constexpr uint8_t delete_connection_command = 5;
-static constexpr uint8_t request_light = 0xc0;
-static constexpr char identifier[] = "SELF";
-
-void fillCommandHeader(CommandHeader *header) {
- // Allocate and fill the header
- header->message_type = request_light;
- header->length = 1;
-}
-
-RouteToSelfCommand createCommandRoute(std::unique_ptr<sockaddr> &&addr,
- uint8_t prefix_length) {
- RouteToSelfCommand command = {0};
-
- // check and set IP address
- if (addr->sa_family == AF_INET) {
- command.address_type = addr_inet;
- command.address.ipv4 = ((sockaddr_in *)addr.get())->sin_addr.s_addr;
- } else if (addr->sa_family == AF_INET6) {
- command.address_type = addr_inet6;
- command.address.ipv6 = ((sockaddr_in6 *)addr.get())->sin6_addr;
- }
-
- // Fill remaining payload fields
-#ifndef _WIN32
- strcpy(command.symbolic_or_connid, identifier);
-#else
- strcpy_s(command.symbolic_or_connid, 16, identifier);
-#endif
- command.cost = 1;
- command.len = (uint8_t)prefix_length;
-
- // Allocate and fill the header
- command.command_id = add_route_command;
- fillCommandHeader((CommandHeader *)&command);
-
- return command;
-}
-
-DeleteSelfConnectionCommand createCommandDeleteConnection() {
- DeleteSelfConnectionCommand command = {0};
- fillCommandHeader((CommandHeader *)&command);
- command.command_id = delete_connection_command;
-
-#ifndef _WIN32
- strcpy(command.symbolic_or_connid, identifier);
-#else
- strcpy_s(command.symbolic_or_connid, 16, identifier);
-#endif
-
- return command;
-}
-
-} // namespace
-
-namespace transport {
-
-namespace core {
-
-HicnForwarderModule::HicnForwarderModule() : IoModule(), connector_(nullptr) {}
-
-HicnForwarderModule::~HicnForwarderModule() {}
-
-void HicnForwarderModule::connect(bool is_consumer) {
- connector_->connect();
- connector_->setRole(is_consumer ? Connector::Role::CONSUMER
- : Connector::Role::PRODUCER);
-}
-
-bool HicnForwarderModule::isConnected() { return connector_->isConnected(); }
-
-void HicnForwarderModule::send(Packet &packet) {
- IoModule::send(packet);
- packet.setChecksum();
- connector_->send(packet);
-}
-
-void HicnForwarderModule::send(const uint8_t *packet, std::size_t len) {
- counters_.tx_packets++;
- counters_.tx_bytes += len;
-
- // Perfect forwarding
- connector_->send(packet, len);
-}
-
-void HicnForwarderModule::registerRoute(const Prefix &prefix) {
- auto command = createCommandRoute(prefix.toSockaddr(),
- (uint8_t)prefix.getPrefixLength());
- send((uint8_t *)&command, sizeof(RouteToSelfCommand));
-}
-
-void HicnForwarderModule::closeConnection() {
- auto command = createCommandDeleteConnection();
- send((uint8_t *)&command, sizeof(DeleteSelfConnectionCommand));
- connector_->close();
-}
-
-void HicnForwarderModule::init(
- Connector::PacketReceivedCallback &&receive_callback,
- Connector::OnReconnectCallback &&reconnect_callback,
- asio::io_service &io_service, const std::string &app_name) {
- if (!connector_) {
- connector_ = new UdpSocketConnector(std::move(receive_callback), nullptr,
- nullptr, std::move(reconnect_callback),
- io_service, app_name);
- }
-}
-
-void HicnForwarderModule::processControlMessageReply(
- utils::MemBuf &packet_buffer) {
- if (packet_buffer.data()[0] == nack_code) {
- throw errors::RuntimeException(
- "Received Nack message from hicn light forwarder.");
- }
-}
-
-std::uint32_t HicnForwarderModule::getMtu() { return interface_mtu; }
-
-bool HicnForwarderModule::isControlMessage(const uint8_t *message) {
- return message[0] == ack_code || message[0] == nack_code;
-}
-
-extern "C" IoModule *create_module(void) { return new HicnForwarderModule(); }
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/io_modules/udp/udp_socket_connector.cc b/libtransport/src/io_modules/udp/udp_socket_connector.cc
deleted file mode 100644
index 1412d8c07..000000000
--- a/libtransport/src/io_modules/udp/udp_socket_connector.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef _WIN32
-#include <hicn/transport/portability/win_portability.h>
-#endif
-
-#include <glog/logging.h>
-#include <hicn/transport/errors/errors.h>
-#include <hicn/transport/utils/object_pool.h>
-#include <io_modules/udp/udp_socket_connector.h>
-
-#include <thread>
-#include <vector>
-
-namespace transport {
-
-namespace core {
-
-UdpSocketConnector::UdpSocketConnector(
- PacketReceivedCallback &&receive_callback, PacketSentCallback &&packet_sent,
- OnCloseCallback &&close_callback, OnReconnectCallback &&on_reconnect,
- asio::io_service &io_service, std::string app_name)
- : Connector(std::move(receive_callback), std::move(packet_sent),
- std::move(close_callback), std::move(on_reconnect)),
- io_service_(io_service),
- socket_(io_service_),
- resolver_(io_service_),
- connection_timer_(io_service_),
- read_msg_(std::make_pair(nullptr, 0)),
- is_reconnection_(false),
- data_available_(false),
- app_name_(app_name) {}
-
-UdpSocketConnector::~UdpSocketConnector() {}
-
-void UdpSocketConnector::connect(std::string ip_address, std::string port) {
- endpoint_iterator_ = resolver_.resolve(
- {ip_address, port, asio::ip::resolver_query_base::numeric_service});
-
- state_ = Connector::State::CONNECTING;
- doConnect();
-}
-
-void UdpSocketConnector::send(const uint8_t *packet, std::size_t len) {
- socket_.async_send(asio::buffer(packet, len),
- [this](std::error_code ec, std::size_t /*length*/) {
- if (sent_callback_) {
- sent_callback_(this, ec);
- }
- });
-}
-
-void UdpSocketConnector::send(Packet &packet) {
- io_service_.post([this, _packet{packet.shared_from_this()}]() {
- bool write_in_progress = !output_buffer_.empty();
- output_buffer_.push_back(std::move(_packet));
- if (TRANSPORT_EXPECT_TRUE(state_ == Connector::State::CONNECTED)) {
- if (!write_in_progress) {
- doWrite();
- }
- } else {
- // Tell the handle connect it has data to write
- data_available_ = true;
- }
- });
-}
-
-void UdpSocketConnector::close() {
- if (io_service_.stopped()) {
- doClose();
- } else {
- io_service_.dispatch(std::bind(&UdpSocketConnector::doClose, this));
- }
-}
-
-void UdpSocketConnector::doClose() {
- if (state_ != Connector::State::CLOSED) {
- state_ = Connector::State::CLOSED;
- if (socket_.is_open()) {
- socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
- socket_.close();
- }
- }
-}
-
-void UdpSocketConnector::doWrite() {
- auto packet = output_buffer_.front().get();
- auto array = std::vector<asio::const_buffer>();
-
- const utils::MemBuf *current = packet;
- do {
- array.push_back(asio::const_buffer(current->data(), current->length()));
- current = current->next();
- } while (current != packet);
-
- socket_.async_send(std::move(array), [this](std::error_code ec,
- std::size_t length) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- output_buffer_.pop_front();
- if (!output_buffer_.empty()) {
- doWrite();
- }
- } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
- // The connection has been closed by the application.
- return;
- } else {
- LOG(ERROR) << ec.value() << " " << ec.message();
- tryReconnect();
- }
- });
-}
-
-void UdpSocketConnector::doRead() {
- read_msg_ = getRawBuffer();
- socket_.async_receive(
- asio::buffer(read_msg_.first, read_msg_.second),
- [this](std::error_code ec, std::size_t length) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- auto packet = getPacketFromBuffer(read_msg_.first, length);
- receive_callback_(this, *packet, std::make_error_code(std::errc(0)));
- doRead();
- } else if (ec.value() ==
- static_cast<int>(std::errc::operation_canceled)) {
- // The connection has been closed by the application.
- return;
- } else {
- LOG(ERROR) << ec.value() << " " << ec.message();
- tryReconnect();
- }
- });
-}
-
-void UdpSocketConnector::tryReconnect() {
- if (state_ == Connector::State::CONNECTED) {
- LOG(ERROR) << "Connection lost. Trying to reconnect...";
- state_ = Connector::State::CONNECTING;
- is_reconnection_ = true;
- io_service_.post([this]() {
- if (socket_.is_open()) {
- socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
- socket_.close();
- }
-
- doConnect();
- startConnectionTimer();
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- });
- }
-}
-
-void UdpSocketConnector::doConnect() {
- asio::async_connect(
- socket_, endpoint_iterator_,
- [this](std::error_code ec, udp::resolver::iterator) {
- if (!ec) {
- connection_timer_.cancel();
- state_ = Connector::State::CONNECTED;
- doRead();
-
- if (data_available_) {
- data_available_ = false;
- doWrite();
- }
-
- if (is_reconnection_) {
- is_reconnection_ = false;
- }
-
- on_reconnect_callback_(this);
- } else {
- doConnect();
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- }
- });
-}
-
-bool UdpSocketConnector::checkConnected() {
- return state_ == Connector::State::CONNECTED;
-}
-
-void UdpSocketConnector::startConnectionTimer() {
- connection_timer_.expires_from_now(std::chrono::seconds(60));
- connection_timer_.async_wait(std::bind(&UdpSocketConnector::handleDeadline,
- this, std::placeholders::_1));
-}
-
-void UdpSocketConnector::handleDeadline(const std::error_code &ec) {
- if (!ec) {
- io_service_.post([this]() {
- socket_.close();
- LOG(ERROR) << "Error connecting. Is the forwarder running?";
- });
- }
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/udp/udp_socket_connector.h b/libtransport/src/io_modules/udp/udp_socket_connector.h
deleted file mode 100644
index c483e14aa..000000000
--- a/libtransport/src/io_modules/udp/udp_socket_connector.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-#include <hicn/transport/core/asio_wrapper.h>
-#include <hicn/transport/core/connector.h>
-#include <hicn/transport/core/content_object.h>
-#include <hicn/transport/core/global_object_pool.h>
-#include <hicn/transport/core/interest.h>
-#include <hicn/transport/core/name.h>
-#include <hicn/transport/core/packet.h>
-#include <hicn/transport/utils/branch_prediction.h>
-
-#include <deque>
-
-namespace transport {
-namespace core {
-
-using asio::ip::udp;
-
-class UdpSocketConnector : public Connector {
- public:
- UdpSocketConnector(PacketReceivedCallback &&receive_callback,
- PacketSentCallback &&packet_sent,
- OnCloseCallback &&close_callback,
- OnReconnectCallback &&on_reconnect,
- asio::io_service &io_service,
- std::string app_name = "Libtransport");
-
- ~UdpSocketConnector() override;
-
- void send(Packet &packet) override;
-
- void send(const uint8_t *packet, std::size_t len) override;
-
- void close() override;
-
- void connect(std::string ip_address = "127.0.0.1", std::string port = "9695");
-
- private:
- void doConnect();
-
- void doRead();
-
- void doWrite();
-
- void doClose();
-
- bool checkConnected();
-
- private:
- void handleDeadline(const std::error_code &ec);
-
- void startConnectionTimer();
-
- void tryReconnect();
-
- asio::io_service &io_service_;
- asio::ip::udp::socket socket_;
- asio::ip::udp::resolver resolver_;
- asio::ip::udp::resolver::iterator endpoint_iterator_;
- asio::steady_timer connection_timer_;
-
- std::pair<uint8_t *, std::size_t> read_msg_;
-
- bool is_reconnection_;
- bool data_available_;
-
- std::string app_name_;
-};
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/libhicntransport-config.cmake.in b/libtransport/src/libhicntransport-config.cmake.in
new file mode 100644
index 000000000..9b8c51962
--- /dev/null
+++ b/libtransport/src/libhicntransport-config.cmake.in
@@ -0,0 +1,8 @@
+@PACKAGE_INIT@
+
+set(Libhicntransport_VERSION_MAJOR "@VERSION_MAJOR@")
+set(Libhicntransport_VERSION_MINOR "@VERSION_MINOR@")
+set(Libhicntransport_VERSION_PATCH "@VERSION_PATCH@")
+
+set_and_check(Libhicntransport_INCLUDE_DIRS "@PACKAGE_Libhicntransport_INCLUDE_DIRS@")
+include("${CMAKE_CURRENT_LIST_DIR}/libhicntransport-targets.cmake")
diff --git a/libtransport/src/protocols/CMakeLists.txt b/libtransport/src/protocols/CMakeLists.txt
index b763e95e2..51879a9ed 100644
--- a/libtransport/src/protocols/CMakeLists.txt
+++ b/libtransport/src/protocols/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -52,9 +52,15 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/errors.cc
)
-set(RAAQM_CONFIG_INSTALL_PREFIX
- ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
-)
+if (${CMAKE_SYSTEM_NAME} MATCHES Darwin OR ${CMAKE_SYSTEM_NAME} MATCHES Linux)
+ set(RAAQM_CONFIG_INSTALL_PREFIX
+ ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
+ )
+else()
+ set(RAAQM_CONFIG_INSTALL_PREFIX
+ ${CMAKE_INSTALL_PREFIX}/etc/hicn
+ )
+endif()
set(raaqm_config_path
${RAAQM_CONFIG_INSTALL_PREFIX}/consumer.conf
@@ -67,7 +73,7 @@ set(TRANSPORT_CONFIG
install(
FILES ${TRANSPORT_CONFIG}
- DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
+ DESTINATION ${RAAQM_CONFIG_INSTALL_PREFIX}
COMPONENT ${LIBTRANSPORT_COMPONENT}
)
diff --git a/libtransport/src/protocols/byte_stream_reassembly.cc b/libtransport/src/protocols/byte_stream_reassembly.cc
index ac36d4e61..3278595b7 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.cc
+++ b/libtransport/src/protocols/byte_stream_reassembly.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/byte_stream_reassembly.h b/libtransport/src/protocols/byte_stream_reassembly.h
index 278740bd3..bfcac3181 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.h
+++ b/libtransport/src/protocols/byte_stream_reassembly.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/cbr.cc b/libtransport/src/protocols/cbr.cc
index 1548cc68d..446ea8b99 100644
--- a/libtransport/src/protocols/cbr.cc
+++ b/libtransport/src/protocols/cbr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -37,11 +37,11 @@ void CbrTransportProtocol::afterDataUnsatisfied(uint64_t segment) {}
void CbrTransportProtocol::afterContentReception(
const Interest &interest, const ContentObject &content_object) {
auto segment = content_object.getName().getSuffix();
- auto now = utils::SteadyClock::now();
- auto rtt = std::chrono::duration_cast<utils::Microseconds>(
- now - interest_timepoints_[segment & mask]);
+ auto now = utils::SteadyTime::Clock::now();
+ auto rtt = utils::SteadyTime::getDurationMs(
+ interest_timepoints_[segment & mask], now);
// Update stats
- updateStats(segment, rtt.count(), now);
+ updateStats(segment, rtt, now);
}
} // end namespace protocol
diff --git a/libtransport/src/protocols/cbr.h b/libtransport/src/protocols/cbr.h
index 41cdbc98c..c178dbf60 100644
--- a/libtransport/src/protocols/cbr.h
+++ b/libtransport/src/protocols/cbr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/congestion_window_protocol.h b/libtransport/src/protocols/congestion_window_protocol.h
index 36ac6eb17..f9ff208cc 100644
--- a/libtransport/src/protocols/congestion_window_protocol.h
+++ b/libtransport/src/protocols/congestion_window_protocol.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/data_processing_events.h b/libtransport/src/protocols/data_processing_events.h
index 28732502b..182de3ed8 100644
--- a/libtransport/src/protocols/data_processing_events.h
+++ b/libtransport/src/protocols/data_processing_events.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/datagram_reassembly.cc b/libtransport/src/protocols/datagram_reassembly.cc
index 069873a52..3a32c81f5 100644
--- a/libtransport/src/protocols/datagram_reassembly.cc
+++ b/libtransport/src/protocols/datagram_reassembly.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/datagram_reassembly.h b/libtransport/src/protocols/datagram_reassembly.h
index de294df06..0def32dd2 100644
--- a/libtransport/src/protocols/datagram_reassembly.h
+++ b/libtransport/src/protocols/datagram_reassembly.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/errors.cc b/libtransport/src/protocols/errors.cc
index 183fcc574..a7dd26e16 100644
--- a/libtransport/src/protocols/errors.cc
+++ b/libtransport/src/protocols/errors.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/errors.h b/libtransport/src/protocols/errors.h
index 58dadae5a..33d5fbee4 100644
--- a/libtransport/src/protocols/errors.h
+++ b/libtransport/src/protocols/errors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/fec/CMakeLists.txt b/libtransport/src/protocols/fec/CMakeLists.txt
index 6d61ae043..8ae0a7360 100644
--- a/libtransport/src/protocols/fec/CMakeLists.txt
+++ b/libtransport/src/protocols/fec/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
diff --git a/libtransport/src/protocols/fec/fec.cc b/libtransport/src/protocols/fec/fec.cc
index 16a04cb98..912e7a40f 100644
--- a/libtransport/src/protocols/fec/fec.cc
+++ b/libtransport/src/protocols/fec/fec.cc
@@ -44,6 +44,7 @@
#include "fec.h"
+#include <assert.h>
#include <hicn/transport/portability/platform.h>
#include <stdio.h>
#include <stdlib.h>
@@ -60,72 +61,6 @@
#endif
/*
- * compatibility stuff
- */
-#ifdef MSDOS /* but also for others, e.g. sun... */
-#define NEED_BCOPY
-#define bcmp(a, b, n) memcmp(a, b, n)
-#endif
-
-#ifdef ANDROID
-#define bcmp(a, b, n) memcmp(a, b, n)
-#endif
-
-#ifdef NEED_BCOPY
-#define bcopy(s, d, siz) memcpy((d), (s), (siz))
-#define bzero(d, siz) memset((d), '\0', (siz))
-#endif
-
-/*
- * stuff used for testing purposes only
- */
-
-#ifdef TEST
-#define DEB(x)
-#define DDB(x) x
-#define DEBUG 0 /* minimal debugging */
-#ifdef MSDOS
-#include <time.h>
-struct timeval {
- unsigned long ticks;
-};
-#define gettimeofday(x, dummy) \
- { (x)->ticks = clock(); }
-#define DIFF_T(a, b) (1 + 1000000 * (a.ticks - b.ticks) / CLOCKS_PER_SEC)
-typedef unsigned long u_long;
-typedef unsigned short u_short;
-#else /* typically, unix systems */
-#include <sys/time.h>
-#define DIFF_T(a, b) \
- (1 + 1000000 * (a.tv_sec - b.tv_sec) + (a.tv_usec - b.tv_usec))
-#endif
-
-#define TICK(t) \
- { \
- struct timeval x; \
- gettimeofday(&x, NULL); \
- t = x.tv_usec + 1000000 * (x.tv_sec & 0xff); \
- }
-#define TOCK(t) \
- { \
- u_long t1; \
- TICK(t1); \
- if (t1 < t) \
- t = 256000000 + t1 - t; \
- else \
- t = t1 - t; \
- if (t == 0) t = 1; \
- }
-
-u_long ticks[10]; /* vars for timekeeping */
-#else
-#define DEB(x)
-#define DDB(x)
-#define TICK(x)
-#define TOCK(x)
-#endif /* TEST */
-
-/*
* You should not need to change anything beyond this point.
* The first part of the file implements linear algebra in GF.
*
@@ -402,31 +337,17 @@ static void matmul(gf *a, gf *b, gf *c, int n, int k, int m) {
}
}
-#ifdef DEBUGG
-/*
- * returns 1 if the square matrix is identiy
- * (only for test)
- */
-static int is_identity(gf *m, int k) {
- int row, col;
- for (row = 0; row < k; row++)
- for (col = 0; col < k; col++)
- if ((row == col && *m != 1) || (row != col && *m != 0))
- return 0;
- else
- m++;
- return 1;
-}
-#endif /* debug */
-
/*
* invert_mat() takes a matrix and produces its inverse
* k is the size of the matrix.
* (Gauss-Jordan, adapted from Numerical Recipes in C)
* Return non-zero if singular.
*/
-DEB(int pivloops = 0; int pivswaps = 0; /* diagnostic */)
+int pivloops = 0;
+int pivswaps = 0; /* diagnostic */
static int invert_mat(gf *src, int k) {
+ assert(k > 0);
+
gf c, *p;
int irow, icol, row, col, i, ix;
@@ -436,9 +357,9 @@ static int invert_mat(gf *src, int k) {
int *ipiv = (int *)my_malloc(k * sizeof(int), "ipiv");
gf *id_row = NEW_GF_MATRIX(1, k);
gf *temp_row = NEW_GF_MATRIX(1, k);
-
- bzero(id_row, k * sizeof(gf));
- DEB(pivloops = 0; pivswaps = 0; /* diagnostic */)
+ memset(id_row, '\0', k * sizeof(gf));
+ pivloops = 0;
+ pivswaps = 0; /* diagnostic */
/*
* ipiv marks elements already used as pivots.
*/
@@ -459,7 +380,7 @@ static int invert_mat(gf *src, int k) {
for (row = 0; row < k; row++) {
if (ipiv[row] != 1) {
for (ix = 0; ix < k; ix++) {
- DEB(pivloops++;)
+ pivloops++;
if (ipiv[ix] == 0) {
if (src[row * k + ix] != 0) {
irow = row;
@@ -497,12 +418,9 @@ static int invert_mat(gf *src, int k) {
fprintf(stderr, "singular matrix 2\n");
goto fail;
}
- if (c != 1) { /* otherwhise this is a NOP */
- /*
- * this is done often , but optimizing is not so
- * fruitful, at least in the obvious ways (unrolling)
- */
- DEB(pivswaps++;)
+
+ if (c != 1) {
+ pivswaps++;
c = inverse[c];
pivot_row[icol] = 1;
for (ix = 0; ix < k; ix++) pivot_row[ix] = gf_mul(c, pivot_row[ix]);
@@ -515,7 +433,7 @@ static int invert_mat(gf *src, int k) {
* we can optimize the addmul).
*/
id_row[icol] = 1;
- if (bcmp(pivot_row, id_row, k * sizeof(gf)) != 0) {
+ if (memcmp(pivot_row, id_row, k * sizeof(gf)) != 0) {
for (p = src, ix = 0; ix < k; ix++, p += k) {
if (ix != icol) {
c = p[icol];
@@ -560,6 +478,8 @@ fail:
*/
int invert_vdm(gf *src, int k) {
+ assert(k > 0);
+
int i, j, row, col;
gf *b, *c, *p;
gf t, xx;
@@ -614,14 +534,8 @@ int invert_vdm(gf *src, int k) {
static int fec_initialized = 0;
static void init_fec() {
- TICK(ticks[0]);
generate_gf();
- TOCK(ticks[0]);
- DDB(fprintf(stderr, "generate_gf took %ldus\n", ticks[0]);)
- TICK(ticks[0]);
init_mul_table();
- TOCK(ticks[0]);
- DDB(fprintf(stderr, "init_mul_table took %ldus\n", ticks[0]);)
fec_initialized = 1;
}
@@ -680,19 +594,14 @@ struct fec_parms *fec_new(int k, int n) {
* k*k vandermonde matrix, multiply right the bottom n-k rows
* by the inverse, and construct the identity matrix at the top.
*/
- TICK(ticks[3]);
invert_vdm(tmp_m, k); /* much faster than invert_mat */
matmul(tmp_m + k * k, tmp_m, retval->enc_matrix + k * k, n - k, k, k);
/*
* the upper matrix is I so do not bother with a slow multiply
*/
- bzero(retval->enc_matrix, k * k * sizeof(gf));
+ memset(retval->enc_matrix, '\0', k * k * sizeof(gf));
for (p = retval->enc_matrix, col = 0; col < k; col++, p += k + 1) *p = 1;
free(tmp_m);
- TOCK(ticks[3]);
-
- DDB(fprintf(stderr, "--- %ld us to build encoding matrix\n", ticks[3]);)
- DEB(pr_matrix(retval->enc_matrix, n, k, "encoding_matrix");)
return retval;
}
@@ -708,10 +617,10 @@ void fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz) {
if (GF_BITS > 8) sz /= 2;
if (index < k)
- bcopy(src[index], fec, sz * sizeof(gf));
+ memcpy(fec, src[index], sz * sizeof(gf));
else if (index < code->n) {
p = &(code->enc_matrix[index * k]);
- bzero(fec, sz * sizeof(gf));
+ memset(fec, '\0', sz * sizeof(gf));
for (i = 0; i < k; i++) addmul(fec, src[i], p[i], sz);
} else
fprintf(stderr, "Invalid index %d (max %d)\n", index, code->n - 1);
@@ -733,22 +642,13 @@ static int shuffle(gf *pkt[], int index[], int k) {
int c = index[i];
if (index[c] == c) {
- DEB(fprintf(stderr, "\nshuffle, error at %d\n", i);)
+ fprintf(stderr, "\nshuffle, error at %d\n", i);
return 1;
}
SWAP(index[i], index[c], int);
SWAP(pkt[i], pkt[c], gf *);
}
}
- DEB(/* just test that it works... */
- for (i = 0; i < k; i++) {
- if (index[i] < k && index[i] != i) {
- fprintf(stderr, "shuffle: after\n");
- for (i = 0; i < k; i++) fprintf(stderr, "%3d ", index[i]);
- fprintf(stderr, "\n");
- return 1;
- }
- })
return 0;
}
@@ -757,20 +657,16 @@ static int shuffle(gf *pkt[], int index[], int k) {
* indexes. The matrix must be already allocated as
* a vector of k*k elements, in row-major order
*/
-static gf *build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[]) {
+static gf *build_decode_matrix(struct fec_parms *code, int index[]) {
int i, k = code->k;
gf *p, *matrix = NEW_GF_MATRIX(k, k);
- TICK(ticks[9]);
for (i = 0, p = matrix; i < k; i++, p += k) {
-#if 1 /* this is simply an optimization, not very useful indeed */
if (index[i] < k) {
- bzero(p, k * sizeof(gf));
+ memset(p, '\0', k * sizeof(gf));
p[i] = 1;
- } else
-#endif
- if (index[i] < code->n)
- bcopy(&(code->enc_matrix[index[i] * k]), p, k * sizeof(gf));
+ } else if (index[i] < code->n)
+ memcpy(p, &(code->enc_matrix[index[i] * k]), k * sizeof(gf));
else {
fprintf(stderr, "decode: invalid index %d (max %d)\n", index[i],
code->n - 1);
@@ -778,12 +674,10 @@ static gf *build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[]) {
return NULL;
}
}
- TICK(ticks[9]);
if (invert_mat(matrix, k)) {
free(matrix);
matrix = NULL;
}
- TOCK(ticks[9]);
return matrix;
}
@@ -800,39 +694,29 @@ static gf *build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[]) {
*/
int fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz) {
gf *m_dec;
- gf **new_pkt;
+ gf **new_pkt = nullptr;
int row, col, k = code->k;
+ int i = 0;
if (GF_BITS > 8) sz /= 2;
if (shuffle(pkt, index, k)) /* error if true */
return 1;
- m_dec = build_decode_matrix(code, pkt, index);
+ m_dec = build_decode_matrix(code, index);
if (m_dec == NULL) return 1; /* error */
/*
* do the actual decoding
*/
- new_pkt = (gf **)my_malloc(k * sizeof(gf *), "new pkt pointers");
+ new_pkt = pkt + k;
for (row = 0; row < k; row++) {
if (index[row] >= k) {
- new_pkt[row] = (gf *)my_malloc(sz * sizeof(gf), "new pkt buffer");
- bzero(new_pkt[row], sz * sizeof(gf));
+ memset(new_pkt[i], '\0', sz * sizeof(gf));
for (col = 0; col < k; col++)
- addmul(new_pkt[row], pkt[col], m_dec[row * k + col], sz);
- }
- }
- /*
- * move pkts to their final destination
- */
- for (row = 0; row < k; row++) {
- if (index[row] >= k) {
- bcopy(new_pkt[row], pkt[row], sz * sizeof(gf));
- free(new_pkt[row]);
+ addmul(new_pkt[i], pkt[col], m_dec[row * k + col], sz);
+ i++;
}
}
- free(new_pkt);
free(m_dec);
-
return 0;
}
diff --git a/libtransport/src/protocols/fec/rely.cc b/libtransport/src/protocols/fec/rely.cc
index 7a30a62e2..d4d98a90b 100644
--- a/libtransport/src/protocols/fec/rely.cc
+++ b/libtransport/src/protocols/fec/rely.cc
@@ -23,38 +23,39 @@ namespace transport {
namespace protocol {
namespace fec {
-RelyEncoder::RelyEncoder(uint32_t k, uint32_t n, uint32_t seq_offset)
+RelyEncoder::RelyEncoder(uint32_t k, uint32_t n, uint32_t /* seq_offset */)
: RelyBase(k, n) {
configure(kmtu, ktimeout, kmax_stream_size);
set_repair_trigger(k_, n_ - k_, n_ - k_);
}
void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
- uint32_t offset) {
+ uint32_t offset, uint32_t metadata) {
// Get pointer to payload, leaving space to insert FEC header.
// TODO Check if this additional header is really needed.
- auto data = content_object.writableData() + offset - sizeof(fec_header);
- auto length = content_object.length() - offset + sizeof(fec_header);
+ auto data = content_object.writableData() + offset - sizeof(fec_metadata);
+ auto length = content_object.length() - offset + sizeof(fec_metadata);
// Check packet length does not exceed maximum length supported by the
// encoder (otherwise segmentation would take place).
- assert(length < max_packet_bytes());
+ DCHECK(length < max_packet_bytes());
DLOG_IF(INFO, VLOG_IS_ON(4))
- << "Encoding packet of length " << length - sizeof(fec_header);
+ << "Encoding packet of length " << length - sizeof(fec_metadata);
- // Get the suffix. With rely we need to write it in the fec_header in order to
- // be able to recognize the seq number upon recovery.
+ // Get the suffix. With rely we need to write it in the fec_metadata in order
+ // to be able to recognize the seq number upon recovery.
auto suffix = content_object.getName().getSuffix();
DLOG_IF(INFO, VLOG_IS_ON(4)) << "Producing packet " << suffix
<< " (index == " << current_index_ << ")";
- // Consume payload. Add fec_header in front before feeding payload to encoder,
- // and copy original content of packet
- fec_header *h = reinterpret_cast<fec_header *>(data);
- fec_header copy = *h;
+ // Consume payload. Add fec_metadata in front before feeding payload to
+ // encoder, and copy original content of packet
+ fec_metadata *h = reinterpret_cast<fec_metadata *>(data);
+ fec_metadata copy = *h;
h->setSeqNumberBase(suffix);
+ h->setMetadataBase(metadata);
auto packets = consume(data, length, getCurrentTime());
- assert(packets == 1);
+ DCHECK(packets == 1);
// Update packet counter
current_index_ += packets;
@@ -62,7 +63,7 @@ void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
// Restore original packet content and increment data pointer to the correct
// position
*h = copy;
- data += sizeof(fec_header);
+ data += sizeof(fec_metadata);
// Check position of this packet inside N size block
auto i = current_index_ % n_;
@@ -74,24 +75,24 @@ void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
// TODO Optimize it by copying only the RELY header
// Be sure encoder can produce
- assert(can_produce());
+ DCHECK(can_produce());
// Check new payload size and make sure it fits in packet buffer
auto new_payload_size = produce_bytes();
int difference = new_payload_size - length;
- assert(difference > 0);
- assert(content_object.ensureCapacity(difference));
+ DCHECK(difference > 0);
+ DCHECK(content_object.ensureCapacity(difference));
// Update length
DLOG_IF(INFO, VLOG_IS_ON(4)) << "The packet length will be incremented by "
- << difference + sizeof(fec_header);
- content_object.append(difference + sizeof(fec_header));
+ << difference + sizeof(fec_metadata);
+ content_object.append(difference + sizeof(fec_metadata));
content_object.updateLength();
// Make sure we got a source packet, otherwise we would put a repair symbol
// in a source packet
- assert(rely::packet_is_systematic(produce_data()));
+ DCHECK(rely::packet_is_systematic(produce_data()));
// Copy rely packet replacing old source packet.
std::memcpy(data, produce_data(), new_payload_size);
@@ -111,7 +112,7 @@ void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
while (can_produce()) {
// The current index MUST be k_, because we enforce n - k repair to be
// produced after k sources
- assert(current_index_ == k_);
+ DCHECK(current_index_ == k_);
buffer packet;
if (!buffer_callback_) {
@@ -130,7 +131,7 @@ void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
std::memcpy(packet->writableData(), produce_data(), produce_bytes());
// Push symbol in repair_packets
- packets_.emplace_back(0, std::move(packet));
+ packets_.emplace_back(0, metadata, std::move(packet));
// Advance the encoder
produce_next();
@@ -143,7 +144,7 @@ void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
// If we have generated repair symbols, let's notify caller via the installed
// callback
if (packets_.size()) {
- assert(packets_.size() == n_ - k_);
+ DCHECK(packets_.size() == n_ - k_);
fec_callback_(packets_);
packets_.clear();
current_index_ = 0;
@@ -156,7 +157,7 @@ RelyDecoder::RelyDecoder(uint32_t k, uint32_t n, uint32_t seq_offset)
}
void RelyDecoder::onDataPacket(core::ContentObject &content_object,
- uint32_t offset) {
+ uint32_t offset, uint32_t metadata) {
// Adjust pointers to point to packet payload
auto data = content_object.writableData() + offset;
auto size = content_object.length() - offset;
@@ -164,30 +165,38 @@ void RelyDecoder::onDataPacket(core::ContentObject &content_object,
// Pass payload to decoder
consume(data, size, getCurrentTime());
+ producePackets();
+}
+
+void RelyDecoder::producePackets() {
// Drain decoder if possible
while (can_produce()) {
- // Get size of decoded packet
- auto size = produce_bytes();
-
- // Get buffer to copy packet in
- auto packet = core::PacketManager<>::getInstance().getMemBuf();
+ auto fec_header_size = sizeof(fec_metadata);
+ auto payload_size = produce_bytes() - sizeof(fec_metadata);
- // Copy buffer
- packet->append(size);
- std::memcpy(packet->writableData(), produce_data(), size);
+ buffer packet;
+ if (!buffer_callback_) {
+ packet = core::PacketManager<>::getInstance().getMemBuf();
+ packet->append(payload_size);
+ } else {
+ packet = buffer_callback_(payload_size);
+ }
// Read seq number
- fec_header *h = reinterpret_cast<fec_header *>(packet->writableData());
+ const fec_metadata *h =
+ reinterpret_cast<const fec_metadata *>(produce_data());
uint32_t index = h->getSeqNumberBase();
+ uint32_t metadata = h->getMetadataBase();
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "The index written in the packet is " << index;
- // Remove FEC header
- packet->trimStart(sizeof(fec_header));
+ // Copy payload
+ std::memcpy(packet->writableData(), produce_data() + fec_header_size,
+ payload_size);
// Save packet in buffer
- packets_.emplace_back(index, std::move(packet));
+ packets_.emplace_back(index, metadata, std::move(packet));
// Advance to next packet
produce_next();
@@ -198,8 +207,28 @@ void RelyDecoder::onDataPacket(core::ContentObject &content_object,
fec_callback_(packets_);
packets_.clear();
}
+
+ flushOutOfOrder();
+}
+
+void RelyDecoder::flushOutOfOrder() {
+ if (flush_timer_ == nullptr) return;
+ flush_timer_->cancel();
+
+ if (has_upcoming_flush()) {
+ flush_timer_->expires_from_now(std::chrono::milliseconds(
+ std::max((int64_t)0, upcoming_flush(getCurrentTime()))));
+
+ flush_timer_->async_wait([this](const std::error_code &ec) {
+ if (ec) return;
+ if (has_upcoming_flush()) {
+ flush(getCurrentTime());
+ producePackets();
+ }
+ });
+ }
}
} // namespace fec
} // namespace protocol
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/protocols/fec/rely.h b/libtransport/src/protocols/fec/rely.h
index bfbdb30bc..001a26002 100644
--- a/libtransport/src/protocols/fec/rely.h
+++ b/libtransport/src/protocols/fec/rely.h
@@ -33,8 +33,12 @@ namespace fec {
* @brief Table of used codes.
*/
#define foreach_rely_fec_type \
+ _(Rely, 1, 2) \
_(Rely, 1, 3) \
+ _(Rely, 1, 4) \
_(Rely, 2, 3) \
+ _(Rely, 2, 6) \
+ _(Rely, 3, 9) \
_(Rely, 4, 5) \
_(Rely, 4, 6) \
_(Rely, 4, 7) \
@@ -74,11 +78,17 @@ class RelyBase : public virtual FECBase {
* decoding operations. It may be removed once we know the meaning of the
* fields in the rely header.
*/
- struct fec_header {
- uint32_t seq_number;
-
+ class fec_metadata {
+ public:
void setSeqNumberBase(uint32_t suffix) { seq_number = htonl(suffix); }
- uint32_t getSeqNumberBase() { return ntohl(seq_number); }
+ uint32_t getSeqNumberBase() const { return ntohl(seq_number); }
+
+ void setMetadataBase(uint32_t value) { metadata = htonl(value); }
+ uint32_t getMetadataBase() const { return ntohl(metadata); }
+
+ private:
+ uint32_t seq_number;
+ uint32_t metadata;
};
/**
@@ -112,21 +122,20 @@ class RelyBase : public virtual FECBase {
#if RELY_DEBUG
return time_++;
#else
- auto _time = utils::SteadyClock::now().time_since_epoch();
- auto time = std::chrono::duration_cast<utils::Milliseconds>(_time).count();
- return time;
+ return utils::SteadyTime::nowMs().count();
#endif
}
- protected:
uint32_t k_;
uint32_t n_;
+
std::uint32_t seq_offset_;
+
/**
* @brief Vector of packets to be passed to caller callbacks. For encoder it
* will contain the repair packets, for decoder the recovered sources.
*/
- std::vector<std::pair<uint32_t, buffer>> packets_;
+ BufferArray packets_;
/**
* @brief Current index to be used for local packet count.
@@ -142,50 +151,54 @@ class RelyBase : public virtual FECBase {
* @brief The Rely Encoder implementation.
*
*/
-class RelyEncoder : private RelyBase,
- private rely::encoder,
- public ProducerFEC {
+class RelyEncoder : RelyBase, rely::encoder, public ProducerFEC {
public:
RelyEncoder(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
/**
* Producers will call this function when they produce a data packet.
*/
- void onPacketProduced(core::ContentObject &content_object,
- uint32_t offset) override;
+ void onPacketProduced(core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata = FECBase::INVALID_METADATA) override;
/**
* @brief Get the fec header size, if added to source packets
*/
std::size_t getFecHeaderSize() override {
- return header_bytes() + sizeof(fec_header) + 4;
+ return header_bytes() + sizeof(fec_metadata) + 4;
}
- void reset() override {}
+ void reset() override {
+ // Nothing to do here
+ }
};
-class RelyDecoder : private RelyBase,
- private rely::decoder,
- public ConsumerFEC {
+class RelyDecoder : RelyBase, rely::decoder, public ConsumerFEC {
public:
RelyDecoder(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
/**
* Consumers will call this function when they receive a data packet
*/
- void onDataPacket(core::ContentObject &content_object,
- uint32_t offset) override;
+ void onDataPacket(core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata = FECBase::INVALID_METADATA) override;
/**
* @brief Get the fec header size, if added to source packets
*/
std::size_t getFecHeaderSize() override {
- return header_bytes() + sizeof(fec_header);
+ return header_bytes() + sizeof(fec_metadata);
+ }
+
+ void reset() override {
+ // Nothing to do here
}
- void reset() override {}
+ private:
+ void producePackets();
+ void flushOutOfOrder();
};
} // namespace fec
} // namespace protocol
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/protocols/fec/rs.cc b/libtransport/src/protocols/fec/rs.cc
index 2c23d515d..9c0a3d4fb 100644
--- a/libtransport/src/protocols/fec/rs.cc
+++ b/libtransport/src/protocols/fec/rs.cc
@@ -46,23 +46,26 @@ bool BlockCode::addRepairSymbol(const fec::buffer &packet, uint32_t i,
to_decode_ = true;
DLOG_IF(INFO, VLOG_IS_ON(4)) << "Adding symbol of size " << packet->length();
return addSymbol(packet, i, offset,
- packet->length() - sizeof(fec_header) - offset);
+ packet->length() - sizeof(fec_header) - offset,
+ FECBase::INVALID_METADATA);
}
bool BlockCode::addSourceSymbol(const fec::buffer &packet, uint32_t i,
- uint32_t offset) {
+ uint32_t offset, uint32_t metadata) {
DLOG_IF(INFO, VLOG_IS_ON(4)) << "Adding source symbol of size "
<< packet->length() << ", offset " << offset;
- return addSymbol(packet, i, offset, packet->length() - offset);
+ return addSymbol(packet, i, offset, packet->length() - offset, metadata);
}
bool BlockCode::addSymbol(const fec::buffer &packet, uint32_t i,
- uint32_t offset, std::size_t size) {
+ uint32_t offset, std::size_t size,
+ uint32_t metadata) {
if (size > max_buffer_size_) {
max_buffer_size_ = size;
}
- operator[](current_block_size_++) = std::make_tuple(i, packet, offset);
+ operator[](current_block_size_) = RSBufferInfo(offset, i, metadata, packet);
+ current_block_size_++;
if (current_block_size_ >= k_) {
if (to_decode_) {
@@ -80,12 +83,13 @@ bool BlockCode::addSymbol(const fec::buffer &packet, uint32_t i,
void BlockCode::encode() {
gf *data[n_];
- uint32_t base = std::get<0>(operator[](0));
+ uint32_t base = operator[](0).getIndex();
// Set packet length in first 2 bytes
for (uint32_t i = 0; i < k_; i++) {
- auto &packet = std::get<1>(operator[](i));
- auto offset = std::get<2>(operator[](i));
+ auto &packet = operator[](i).getBuffer();
+ auto offset = operator[](i).getOffset();
+ auto metadata_base = operator[](i).getMetadata();
auto ret =
packet->ensureCapacityAndFillUnused(max_buffer_size_ + offset, 0);
@@ -98,10 +102,11 @@ void BlockCode::encode() {
// Buffers should hold 2 *after* the padding, in order to be
// able to set the length for the encoding operation.
// packet->trimStart(offset);
- uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData() +
- max_buffer_size_ + offset);
+ fec_metadata *metadata = reinterpret_cast<fec_metadata *>(
+ packet->writableData() + max_buffer_size_ + offset);
auto buffer_length = packet->length() - offset;
- *length = htons(buffer_length);
+ metadata->setPacketLength(buffer_length);
+ metadata->setMetadataBase(metadata_base);
DLOG_IF(INFO, VLOG_IS_ON(4)) << "Current buffer size: " << packet->length();
@@ -109,7 +114,7 @@ void BlockCode::encode() {
}
// Finish to fill source block with the buffers to hold the repair symbols
- auto length = max_buffer_size_ + sizeof(fec_header) + LEN_SIZE_BYTES;
+ auto length = max_buffer_size_ + sizeof(fec_header) + METADATA_BYTES;
for (uint32_t i = k_; i < n_; i++) {
buffer packet;
if (!params_.buffer_callback_) {
@@ -133,19 +138,20 @@ void BlockCode::encode() {
DLOG_IF(INFO, VLOG_IS_ON(4)) << "Current symbol size: " << packet->length();
data[i] = packet->writableData();
- operator[](i) = std::make_tuple(i, std::move(packet), uint32_t(0));
+ operator[](i) = RSBufferInfo(uint32_t(0), i, FECBase::INVALID_METADATA,
+ std::move(packet));
}
// Generate repair symbols and put them in corresponding buffers
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_ + LEN_SIZE_BYTES);
+ fec_encode(code_, data, data[i], i, max_buffer_size_ + METADATA_BYTES);
}
// Re-include header in repair packets
for (uint32_t i = k_; i < n_; i++) {
- auto &packet = std::get<1>(operator[](i));
+ auto &packet = operator[](i).getBuffer();
packet->prepend(sizeof(fec_header));
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Produced repair symbol of size = " << packet->length();
@@ -153,16 +159,31 @@ void BlockCode::encode() {
}
void BlockCode::decode() {
- gf *data[k_];
+ gf *data[n_];
uint32_t index[k_];
+ buffer aux_fec_packets[n_ - k_];
+ // FEC packet number k0
+ uint32_t k0 = 0;
+
+ // Reorder block by index with in-place sorting
+ for (uint32_t i = 0; i < k_;) {
+ uint32_t idx = operator[](i).getIndex();
+ if (idx >= k_ || idx == i) {
+ i++;
+ } else {
+ std::swap(operator[](i), operator[](idx));
+ }
+ }
for (uint32_t i = 0; i < k_; i++) {
- auto &packet = std::get<1>(operator[](i));
- index[i] = std::get<0>(operator[](i));
- auto offset = std::get<2>(operator[](i));
+ auto &packet = operator[](i).getBuffer();
+ index[i] = operator[](i).getIndex();
+ auto offset = operator[](i).getOffset();
+ auto metadata_base = operator[](i).getMetadata();
sorted_index_[i] = index[i];
if (index[i] < k_) {
+ operator[](i).setReceived();
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "DECODE SOURCE - index " << index[i]
<< " - Current buffer size: " << packet->length();
@@ -173,49 +194,51 @@ void BlockCode::decode() {
// able to set the length for the encoding operation
packet->trimStart(offset);
packet->ensureCapacityAndFillUnused(max_buffer_size_, 0);
- uint16_t *length = reinterpret_cast<uint16_t *>(
- packet->writableData() + max_buffer_size_ - LEN_SIZE_BYTES);
-
- *length = htons(packet->length());
+ fec_metadata *metadata = reinterpret_cast<fec_metadata *>(
+ packet->writableData() + max_buffer_size_ - METADATA_BYTES);
+ metadata->setPacketLength(packet->length());
+ metadata->setMetadataBase(metadata_base);
} else {
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "DECODE SYMBOL - index " << index[i]
<< " - Current buffer size: " << packet->length();
packet->trimStart(sizeof(fec_header) + offset);
+ aux_fec_packets[k0] = core::PacketManager<>::getInstance().getMemBuf();
+ data[k_ + k0] = aux_fec_packets[k0]->writableData();
+ k0++;
}
-
data[i] = packet->writableData();
}
-
// We decode the source block
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_);
// Find the index in the block for recovered packets
- for (uint32_t i = 0; i < k_; i++) {
- if (index[i] != i) {
- for (uint32_t j = 0; j < k_; j++)
- if (sorted_index_[j] == uint32_t(index[i])) {
- sorted_index_[j] = i;
- }
- }
- }
-
- // Reorder block by index with in-place sorting
- for (uint32_t i = 0; i < k_; i++) {
- for (uint32_t j = sorted_index_[i]; j != i; j = sorted_index_[i]) {
- std::swap(sorted_index_[j], sorted_index_[i]);
- std::swap(operator[](j), operator[](i));
+ for (uint32_t i = 0, j = 0; i < k_; i++) {
+ if (index[i] >= k_) {
+ operator[](i).setBuffer(aux_fec_packets[j++]);
+ operator[](i).setIndex(i);
}
}
// Adjust length according to the one written in the source packet
for (uint32_t i = 0; i < k_; i++) {
- auto &packet = std::get<1>(operator[](i));
- uint16_t *length = reinterpret_cast<uint16_t *>(
- packet->writableData() + max_buffer_size_ - LEN_SIZE_BYTES);
- packet->setLength(ntohs(*length));
+ auto &packet = operator[](i).getBuffer();
+ fec_metadata *metadata = reinterpret_cast<fec_metadata *>(
+ packet->writableData() + max_buffer_size_ - METADATA_BYTES);
+ // Adjust buffer length
+ packet->setLength(metadata->getPacketLength());
+ // Adjust metadata
+ operator[](i).setMetadata(metadata->getMetadataBase());
+
+ // reset the point to the beginning of the packets for all received packets
+ if (operator[](i).getReceived()) {
+ auto &packet = operator[](i).getBuffer();
+ auto offset = operator[](i).getOffset();
+ packet->prepend(offset);
+ }
}
}
@@ -252,12 +275,11 @@ RSEncoder::RSEncoder(uint32_t k, uint32_t n, uint32_t seq_offset)
source_block_(k_, n_, seq_offset_, current_code_, *this) {}
void RSEncoder::consume(const fec::buffer &packet, uint32_t index,
- uint32_t offset) {
- if (!source_block_.addSourceSymbol(packet, index, offset)) {
- std::vector<std::pair<uint32_t, buffer>> repair_packets;
+ uint32_t offset, uint32_t metadata) {
+ if (!source_block_.addSourceSymbol(packet, index, offset, metadata)) {
+ fec::BufferArray repair_packets;
for (uint32_t i = k_; i < n_; i++) {
- repair_packets.emplace_back(std::move(std::get<0>(source_block_[i])),
- std::move(std::get<1>(source_block_[i])));
+ repair_packets.emplace_back(std::move(source_block_[i]));
}
fec_callback_(repair_packets);
@@ -265,9 +287,9 @@ void RSEncoder::consume(const fec::buffer &packet, uint32_t index,
}
void RSEncoder::onPacketProduced(core::ContentObject &content_object,
- uint32_t offset) {
+ uint32_t offset, uint32_t metadata) {
consume(content_object.shared_from_this(),
- content_object.getName().getSuffix(), offset);
+ content_object.getName().getSuffix(), offset, metadata);
}
RSDecoder::RSDecoder(uint32_t k, uint32_t n, uint32_t seq_offset)
@@ -276,10 +298,15 @@ RSDecoder::RSDecoder(uint32_t k, uint32_t n, uint32_t seq_offset)
void RSDecoder::recoverPackets(SourceBlocks::iterator &src_block_it) {
DLOG_IF(INFO, VLOG_IS_ON(4)) << "recoverPackets for " << k_;
auto &src_block = src_block_it->second;
- std::vector<std::pair<uint32_t, buffer>> source_packets(k_);
+ auto base_index = src_block_it->first;
+ BufferArray source_packets(k_);
+
+ // Iterate over packets in the block and adjust indexed accordingly. This must
+ // be done because indexes are from 0 to (n - k - 1), but we need indexes from
+ // base_index to base_index + (n - k - 1)
for (uint32_t i = 0; i < src_block.getK(); i++) {
- source_packets[i] = std::make_pair(src_block_it->first + i,
- std::move(std::get<1>(src_block[i])));
+ src_block[i].setIndex(base_index + src_block[i].getIndex());
+ source_packets[i] = FECBufferInfo(std::move(src_block[i]));
}
setProcessed(src_block_it->first);
@@ -296,9 +323,9 @@ void RSDecoder::recoverPackets(SourceBlocks::iterator &src_block_it) {
}
void RSDecoder::consumeSource(const fec::buffer &packet, uint32_t index,
- uint32_t offset) {
+ uint32_t offset, uint32_t metadata) {
// Normalize index
- assert(index >= seq_offset_);
+ DCHECK(index >= seq_offset_);
auto i = (index - seq_offset_) % n_;
// Get base
@@ -324,16 +351,19 @@ void RSDecoder::consumeSource(const fec::buffer &packet, uint32_t index,
// protocol that may come in the future.
auto it = src_blocks_.find(base);
if (it != src_blocks_.end()) {
- auto ret = it->second.addSourceSymbol(packet, i, offset);
+ auto ret = it->second.addSourceSymbol(packet, i, offset, metadata);
if (!ret) {
recoverPackets(it);
}
} else {
DLOG_IF(INFO, VLOG_IS_ON(4)) << "Adding to parked source packets";
- auto ret = parked_packets_.emplace(
- base, std::vector<std::pair<buffer, uint32_t>>());
- ret.first->second.emplace_back(packet, i);
+ auto ret = parked_packets_.emplace(base, BufferInfoArray());
+ ret.first->second.emplace_back(offset, i, metadata, packet);
+ /**
+ * If we reached k source packets, we do not have any missing packet to
+ * recover via FEC. Delete the block.
+ */
if (ret.first->second.size() >= k_) {
setProcessed(ret.first->first);
parked_packets_.erase(ret.first);
@@ -356,8 +386,8 @@ void RSDecoder::consumeRepair(const fec::buffer &packet, uint32_t offset) {
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Decoder consume called for repair symbol. BASE = " << base
- << ", index = " << base + i << " and i = " << i << ". K=" << k
- << ", N=" << n;
+ << ", index = " << base + i << " and i = " << (int)i << ". K=" << (int)k
+ << ", N=" << (int)n;
// check if a source block already exist for this symbol
auto it = src_blocks_.find(base);
@@ -380,8 +410,9 @@ void RSDecoder::consumeRepair(const fec::buffer &packet, uint32_t offset) {
auto it2 = parked_packets_.find(base);
if (it2 != parked_packets_.end()) {
for (auto &packet_index : it2->second) {
- auto ret = it->second.addSourceSymbol(packet_index.first,
- packet_index.second, offset);
+ auto ret = it->second.addSourceSymbol(
+ packet_index.getBuffer(), packet_index.getIndex(),
+ packet_index.getOffset(), packet_index.getMetadata());
if (!ret) {
recoverPackets(it);
// Finish to delete packets in same source block that were
@@ -399,7 +430,7 @@ void RSDecoder::consumeRepair(const fec::buffer &packet, uint32_t offset) {
}
void RSDecoder::onDataPacket(core::ContentObject &content_object,
- uint32_t offset) {
+ uint32_t offset, uint32_t metadata) {
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Calling fec for data packet " << content_object.getName()
<< ". Offset: " << offset;
@@ -409,7 +440,7 @@ void RSDecoder::onDataPacket(core::ContentObject &content_object,
if (isSymbol(suffix)) {
consumeRepair(content_object.shared_from_this(), offset);
} else {
- consumeSource(content_object.shared_from_this(), suffix, offset);
+ consumeSource(content_object.shared_from_this(), suffix, offset, metadata);
}
}
diff --git a/libtransport/src/protocols/fec/rs.h b/libtransport/src/protocols/fec/rs.h
index e159ad9f7..034c32bdc 100644
--- a/libtransport/src/protocols/fec/rs.h
+++ b/libtransport/src/protocols/fec/rs.h
@@ -34,10 +34,28 @@ namespace protocol {
namespace fec {
#define foreach_rs_fec_type \
+ _(RS, 1, 2) \
_(RS, 1, 3) \
+ _(RS, 1, 4) \
+ _(RS, 2, 3) \
+ _(RS, 2, 4) \
+ _(RS, 2, 5) \
+ _(RS, 2, 6) \
+ _(RS, 3, 6) \
+ _(RS, 3, 7) \
+ _(RS, 3, 8) \
+ _(RS, 3, 9) \
+ _(RS, 3, 10) \
+ _(RS, 3, 11) \
+ _(RS, 3, 12) \
_(RS, 4, 5) \
_(RS, 4, 6) \
_(RS, 4, 7) \
+ _(RS, 4, 8) \
+ _(RS, 4, 9) \
+ _(RS, 4, 10) \
+ _(RS, 4, 11) \
+ _(RS, 4, 12) \
_(RS, 6, 10) \
_(RS, 8, 10) \
_(RS, 8, 11) \
@@ -45,6 +63,8 @@ namespace fec {
_(RS, 8, 14) \
_(RS, 8, 16) \
_(RS, 8, 32) \
+ _(RS, 10, 20) \
+ _(RS, 10, 25) \
_(RS, 10, 30) \
_(RS, 10, 40) \
_(RS, 10, 60) \
@@ -56,12 +76,24 @@ namespace fec {
_(RS, 16, 27) \
_(RS, 17, 21) \
_(RS, 17, 34) \
+ _(RS, 20, 45) \
+ _(RS, 20, 50) \
+ _(RS, 20, 60) \
+ _(RS, 20, 70) \
+ _(RS, 30, 70) \
+ _(RS, 30, 75) \
+ _(RS, 30, 85) \
+ _(RS, 30, 95) \
_(RS, 32, 36) \
_(RS, 32, 41) \
_(RS, 32, 46) \
_(RS, 32, 54) \
_(RS, 34, 42) \
_(RS, 35, 70) \
+ _(RS, 40, 95) \
+ _(RS, 40, 100) \
+ _(RS, 40, 110) \
+ _(RS, 40, 120) \
_(RS, 52, 62)
static const constexpr uint16_t MAX_SOURCE_BLOCK_SIZE = 128;
@@ -73,9 +105,24 @@ static const constexpr uint16_t MAX_SOURCE_BLOCK_SIZE = 128;
* std::array allows to be constructed in place, saving the allocation at the
* price os knowing in advance its size.
*/
-using Packets = std::array<std::tuple</* index */ uint32_t, /* buffer */ buffer,
- uint32_t /* offset */>,
- MAX_SOURCE_BLOCK_SIZE>;
+class RSBufferInfo : public FECBufferInfo {
+ public:
+ RSBufferInfo() : FECBufferInfo() {}
+
+ RSBufferInfo(uint32_t offset, uint32_t index, uint32_t metadata,
+ buffer buffer)
+ : FECBufferInfo(index, metadata, buffer), offset_(offset) {}
+
+ uint32_t getOffset() { return offset_; }
+ RSBufferInfo &setOffset(uint32_t offset) {
+ offset_ = offset;
+ return *this;
+ }
+
+ private:
+ uint32_t offset_ = 0;
+};
+using Packets = std::array<RSBufferInfo, MAX_SOURCE_BLOCK_SIZE>;
/**
* FEC Header, prepended to symbol packets.
@@ -123,10 +170,32 @@ class rs;
*/
class BlockCode : public Packets {
/**
+ * @brief Metadata to include when encoding the buffers. This does not need to
+ * be sent over the network, but just to be included in the FEC protected
+ * bytes.
+ *
+ */
+ class __attribute__((__packed__)) fec_metadata {
+ public:
+ void setPacketLength(uint16_t length) { packet_length = htons(length); }
+ uint32_t getPacketLength() { return ntohs(packet_length); }
+
+ void setMetadataBase(uint32_t value) { metadata = htonl(value); }
+ uint32_t getMetadataBase() { return ntohl(metadata); }
+
+ private:
+ uint16_t packet_length; /* Used to get the real size of the packet after we
+ pad it */
+ uint32_t
+ metadata; /* Caller may specify an integer for storing additional
+ metadata that can be used when recovering the packet. */
+ };
+
+ /**
* For variable length packet we need to prepend to the padded payload the
* real length of the packet. This is *not* sent over the network.
*/
- static constexpr std::size_t LEN_SIZE_BYTES = 2;
+ static constexpr std::size_t METADATA_BYTES = sizeof(fec_metadata);
public:
BlockCode(uint32_t k, uint32_t n, uint32_t seq_offset, struct fec_parms *code,
@@ -142,7 +211,8 @@ class BlockCode : public Packets {
* Add a source symbol to the source block.
*/
bool addSourceSymbol(const fec::buffer &packet, uint32_t i,
- uint32_t offset = 0);
+ uint32_t offset = 0,
+ uint32_t metadata = FECBase::INVALID_METADATA);
/**
* Get current length of source block.
@@ -169,7 +239,7 @@ class BlockCode : public Packets {
* Add symbol to source block
**/
bool addSymbol(const fec::buffer &packet, uint32_t i, uint32_t offset,
- std::size_t size);
+ std::size_t size, uint32_t metadata);
/**
* Starting from k source symbols, get the n - k repair symbols
@@ -310,10 +380,11 @@ class RSEncoder : public rs, public ProducerFEC {
/**
* Always consume source symbols.
*/
- void consume(const fec::buffer &packet, uint32_t index, uint32_t offset = 0);
+ void consume(const fec::buffer &packet, uint32_t index, uint32_t offset = 0,
+ uint32_t metadata = FECBase::INVALID_METADATA);
- void onPacketProduced(core::ContentObject &content_object,
- uint32_t offset) override;
+ void onPacketProduced(core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata = FECBase::INVALID_METADATA) override;
/**
* @brief Get the fec header size, if added to source packets
@@ -348,8 +419,8 @@ class RSDecoder : public rs, public ConsumerFEC {
/**
* Consume source symbol
*/
- void consumeSource(const fec::buffer &packet, uint32_t i,
- uint32_t offset = 0);
+ void consumeSource(const fec::buffer &packet, uint32_t i, uint32_t offset = 0,
+ uint32_t metadata = FECBase::INVALID_METADATA);
/**
* Consume repair symbol
@@ -359,8 +430,8 @@ class RSDecoder : public rs, public ConsumerFEC {
/**
* Consumers will call this function when they receive a data packet
*/
- void onDataPacket(core::ContentObject &content_object,
- uint32_t offset) override;
+ void onDataPacket(core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata = FECBase::INVALID_METADATA) override;
/**
* @brief Get the fec header size, if added to source packets
@@ -398,8 +469,8 @@ class RSDecoder : public rs, public ConsumerFEC {
* not make any sense to build the source block, since we received all the
* source packet of the block.
*/
- std::unordered_map<uint32_t, std::vector<std::pair<buffer, uint32_t>>>
- parked_packets_;
+ using BufferInfoArray = std::vector<RSBufferInfo>;
+ std::unordered_map<uint32_t, BufferInfoArray> parked_packets_;
};
} // namespace fec
diff --git a/libtransport/src/protocols/fec_base.h b/libtransport/src/protocols/fec_base.h
index a1929d85e..bda3ee756 100644
--- a/libtransport/src/protocols/fec_base.h
+++ b/libtransport/src/protocols/fec_base.h
@@ -15,6 +15,7 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/errors/not_implemented_exception.h>
@@ -25,12 +26,67 @@ namespace protocol {
namespace fec {
-using buffer = typename utils::MemBuf::Ptr;
-using BufferArray = std::vector<std::pair<uint32_t, buffer>>;
+using buffer = utils::MemBuf::Ptr;
+
+class FECBufferInfo {
+ public:
+ FECBufferInfo()
+ : index_(~0), metadata_(~0), received_(false), buffer_(nullptr) {}
+
+ template <typename T>
+ FECBufferInfo(uint32_t index, uint32_t metadata, T &&buffer)
+ : index_(index),
+ metadata_(metadata),
+ received_(false),
+ buffer_(std::forward<T>(buffer)) {}
+
+ // Getters
+ uint32_t getIndex() const { return index_; }
+
+ uint32_t getMetadata() const { return metadata_; }
+
+ bool getReceived() const { return received_; }
+
+ buffer &getBuffer() { return buffer_; }
+
+ // Setters
+ void setReceived() { received_ = true; }
+
+ FECBufferInfo &setIndex(uint32_t index) {
+ index_ = index;
+ return *this;
+ }
+
+ FECBufferInfo &setMetadata(uint32_t metadata) {
+ metadata_ = metadata;
+ return *this;
+ }
+
+ FECBufferInfo &setBuffer(buffer &buffer) {
+ buffer_ = buffer;
+ return *this;
+ }
+
+ FECBufferInfo &setBuffer(buffer &&buffer) {
+ buffer_ = std::move(buffer);
+ return *this;
+ }
+
+ private:
+ uint32_t index_;
+ uint32_t metadata_;
+ bool received_;
+ buffer buffer_;
+};
+
+using BufferArray = typename std::vector<FECBufferInfo>;
class FECBase {
public:
- virtual ~FECBase() = default;
+ static inline uint32_t INVALID_METADATA = ~0;
+ static inline uint32_t INVALID_INDEX = ~0;
+
+ virtual ~FECBase() {}
/**
* Callback to be called after the encode or the decode operations. In the
* former case it will contain the symbols, while in the latter the sources.
@@ -64,11 +120,21 @@ class FECBase {
buffer_callback_ = buffer_callback;
}
+ /**
+ * Creates the timer to flush packets. So far needed only if using Rely and
+ * want to avoid expired packets blocked by missing pkts to wait for a new
+ * packet to arrive and trigger the flush
+ */
+ void setIOService(asio::io_service &io_service) {
+ flush_timer_ = std::make_unique<asio::steady_timer>(io_service);
+ }
+
virtual void reset() = 0;
protected:
PacketsReady fec_callback_{0};
BufferRequested buffer_callback_{0};
+ std::unique_ptr<asio::steady_timer> flush_timer_;
};
/**
@@ -80,8 +146,9 @@ class ProducerFEC : public virtual FECBase {
/**
* Producers will call this function upon production of a new packet.
*/
- virtual void onPacketProduced(core::ContentObject &content_object,
- uint32_t offset) = 0;
+ virtual void onPacketProduced(
+ core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata = FECBase::INVALID_METADATA) = 0;
};
/**
@@ -95,9 +162,10 @@ class ConsumerFEC : public virtual FECBase {
* Consumers will call this function when they receive a data packet
*/
virtual void onDataPacket(core::ContentObject &content_object,
- uint32_t offset) = 0;
+ uint32_t offset,
+ uint32_t metadata = FECBase::INVALID_METADATA) = 0;
};
} // namespace fec
} // namespace protocol
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/protocols/incremental_indexer_bytestream.cc b/libtransport/src/protocols/incremental_indexer_bytestream.cc
index cc302a98a..b94f229e5 100644
--- a/libtransport/src/protocols/incremental_indexer_bytestream.cc
+++ b/libtransport/src/protocols/incremental_indexer_bytestream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -29,9 +29,9 @@ void IncrementalIndexer::onContentObject(core::Interest &interest,
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Received content " << content_object.getName();
- assert(reassembly_);
+ DCHECK(reassembly_);
- if (TRANSPORT_EXPECT_FALSE(content_object.testRst())) {
+ if (TRANSPORT_EXPECT_FALSE(content_object.isLast())) {
final_suffix_ = content_object.getName().getSuffix();
}
diff --git a/libtransport/src/protocols/incremental_indexer_bytestream.h b/libtransport/src/protocols/incremental_indexer_bytestream.h
index c6a669629..422e49ecd 100644
--- a/libtransport/src/protocols/incremental_indexer_bytestream.h
+++ b/libtransport/src/protocols/incremental_indexer_bytestream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -62,7 +62,7 @@ class IncrementalIndexer : public Indexer {
next_reassembly_suffix_ = first_suffix_;
}
- virtual uint32_t checkNextSuffix() override {
+ virtual uint32_t checkNextSuffix() const override {
return next_download_suffix_ <= final_suffix_ ? next_download_suffix_
: Indexer::invalid_index;
}
@@ -76,7 +76,7 @@ class IncrementalIndexer : public Indexer {
first_suffix_ = suffix;
}
- uint32_t getFirstSuffix() override { return first_suffix_; }
+ uint32_t getFirstSuffix() const override { return first_suffix_; }
virtual uint32_t jumpToIndex(uint32_t index) override {
next_download_suffix_ = index;
@@ -95,14 +95,14 @@ class IncrementalIndexer : public Indexer {
return final_suffix_ != Indexer::invalid_index;
}
- virtual uint32_t getFinalSuffix() override { return final_suffix_; }
+ virtual uint32_t getFinalSuffix() const override { return final_suffix_; }
void enableFec(fec::FECType fec_type) override {}
void disableFec() override {}
void setNFec(uint32_t n_fec) override {}
- virtual uint32_t getNFec() override { return 0; }
+ virtual uint32_t getNFec() const override { return 0; }
virtual void onContentObject(core::Interest &interest,
core::ContentObject &content_object,
diff --git a/libtransport/src/protocols/index_manager_bytestream.cc b/libtransport/src/protocols/index_manager_bytestream.cc
index c78dc634d..952f36e0e 100644
--- a/libtransport/src/protocols/index_manager_bytestream.cc
+++ b/libtransport/src/protocols/index_manager_bytestream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/index_manager_bytestream.h b/libtransport/src/protocols/index_manager_bytestream.h
index e14c8845b..7ea31dfa5 100644
--- a/libtransport/src/protocols/index_manager_bytestream.h
+++ b/libtransport/src/protocols/index_manager_bytestream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -40,7 +40,9 @@ class IndexManager : public IncrementalIndexer {
indexer_->setFirstSuffix(suffix);
}
- uint32_t getFirstSuffix() override { return indexer_->getFirstSuffix(); }
+ uint32_t getFirstSuffix() const override {
+ return indexer_->getFirstSuffix();
+ }
uint32_t getNextReassemblySegment() override {
return indexer_->getNextReassemblySegment();
@@ -50,22 +52,26 @@ class IndexManager : public IncrementalIndexer {
return indexer_->isFinalSuffixDiscovered();
}
- uint32_t getFinalSuffix() override { return indexer_->getFinalSuffix(); }
+ uint32_t getFinalSuffix() const override {
+ return indexer_->getFinalSuffix();
+ }
uint32_t jumpToIndex(uint32_t index) override {
return indexer_->jumpToIndex(index);
}
void setNFec(uint32_t n_fec) override { return indexer_->setNFec(n_fec); }
- uint32_t getNFec() override { return indexer_->getNFec(); }
+ uint32_t getNFec() const override { return indexer_->getNFec(); }
void enableFec(fec::FECType fec_type) override {
return indexer_->enableFec(fec_type);
}
- double getFecOverhead() override { return indexer_->getFecOverhead(); }
+ double getFecOverhead() const override { return indexer_->getFecOverhead(); }
- double getMaxFecOverhead() override { return indexer_->getMaxFecOverhead(); }
+ double getMaxFecOverhead() const override {
+ return indexer_->getMaxFecOverhead();
+ }
void disableFec() override { return indexer_->disableFec(); }
diff --git a/libtransport/src/protocols/indexer.cc b/libtransport/src/protocols/indexer.cc
index 8d4cf04d7..41465755b 100644
--- a/libtransport/src/protocols/indexer.cc
+++ b/libtransport/src/protocols/indexer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,10 +14,10 @@
*/
#include <implementation/socket_consumer.h>
+#include <protocols/errors.h>
#include <protocols/indexer.h>
namespace transport {
-
namespace protocol {
using namespace interface;
@@ -36,6 +36,35 @@ void Indexer::setVerifier() {
}
}
-} // end namespace protocol
+void Indexer::applyPolicy(core::Interest &interest,
+ core::ContentObject &content_object, bool reassembly,
+ auth::VerificationPolicy policy) const {
+ DCHECK(reassembly_ != nullptr);
+
+ switch (policy) {
+ case auth::VerificationPolicy::ACCEPT: {
+ if (reassembly) {
+ reassembly_->reassemble(content_object);
+ }
+ break;
+ }
+ case auth::VerificationPolicy::UNKNOWN:
+ if (reassembly && reassembly_->reassembleUnverified()) {
+ reassembly_->reassemble(content_object);
+ }
+ break;
+ case auth::VerificationPolicy::DROP:
+ transport_->onPacketDropped(
+ interest, content_object,
+ make_error_code(protocol_error::verification_failed));
+ break;
+ case auth::VerificationPolicy::ABORT: {
+ transport_->onContentReassembled(
+ make_error_code(protocol_error::session_aborted));
+ break;
+ }
+ }
+}
+} // end namespace protocol
} // end namespace transport
diff --git a/libtransport/src/protocols/indexer.h b/libtransport/src/protocols/indexer.h
index 7e3a52fb0..1bacb13aa 100644
--- a/libtransport/src/protocols/indexer.h
+++ b/libtransport/src/protocols/indexer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,6 +15,7 @@
#pragma once
+#include <hicn/transport/auth/policies.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <protocols/fec_utils.h>
@@ -44,7 +45,7 @@ class Indexer {
/**
* Suffix getters
*/
- virtual uint32_t checkNextSuffix() = 0;
+ virtual uint32_t checkNextSuffix() const = 0;
virtual uint32_t getNextSuffix() = 0;
virtual uint32_t getNextReassemblySegment() = 0;
@@ -52,24 +53,24 @@ class Indexer {
* Set first suffix from where to start.
*/
virtual void setFirstSuffix(uint32_t suffix) = 0;
- virtual uint32_t getFirstSuffix() = 0;
+ virtual uint32_t getFirstSuffix() const = 0;
/**
* Functions to set/enable/disable fec
*/
virtual void setNFec(uint32_t n_fec) = 0;
- virtual uint32_t getNFec() = 0;
+ virtual uint32_t getNFec() const = 0;
virtual void enableFec(fec::FECType fec_type) = 0;
virtual void disableFec() = 0;
virtual bool isFec(uint32_t index) { return false; }
- virtual double getFecOverhead() { return 0.0; }
- virtual double getMaxFecOverhead() { return 0.0; }
+ virtual double getFecOverhead() const { return 0.0; }
+ virtual double getMaxFecOverhead() const { return 0.0; }
/**
* Final suffix helpers.
*/
virtual bool isFinalSuffixDiscovered() = 0;
- virtual uint32_t getFinalSuffix() = 0;
+ virtual uint32_t getFinalSuffix() const = 0;
/**
* Set reassembly protocol
@@ -84,9 +85,15 @@ class Indexer {
virtual void setVerifier();
/**
+ * Apply a verification policy
+ */
+ virtual void applyPolicy(core::Interest &interest,
+ core::ContentObject &content_object, bool reassembly,
+ auth::VerificationPolicy policy) const;
+ /**
* Jump to suffix. This may be useful if, for any protocol dependent
- * mechanism, we need to suddenly change current suffix. This does not modify
- * the way suffixes re incremented/decremented (that's part of the
+ * mechanism, we need to suddenly change current suffix. This does not
+ * modify the way suffixes re incremented/decremented (that's part of the
* implementation).
*/
virtual uint32_t jumpToIndex(uint32_t index) = 0;
@@ -108,6 +115,7 @@ class Indexer {
TransportProtocol *transport_;
Reassembly *reassembly_;
std::shared_ptr<auth::Verifier> verifier_;
+ auth::CryptoHashType manifest_hash_type_;
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
index 168aa57af..b5ab8184f 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
+++ b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -31,8 +31,7 @@ ManifestIncrementalIndexer::ManifestIncrementalIndexer(
implementation::ConsumerSocket *icn_socket, TransportProtocol *transport)
: IncrementalIndexer(icn_socket, transport),
suffix_strategy_(utils::SuffixStrategyFactory::getSuffixStrategy(
- NextSegmentCalculationStrategy::INCREMENTAL, next_download_suffix_,
- 0)) {}
+ utils::NextSuffixStrategy::INCREMENTAL, next_download_suffix_)) {}
void ManifestIncrementalIndexer::onContentObject(
core::Interest &interest, core::ContentObject &content_object,
@@ -59,12 +58,7 @@ void ManifestIncrementalIndexer::onContentObject(
void ManifestIncrementalIndexer::onUntrustedManifest(
core::Interest &interest, core::ContentObject &content_object,
bool reassembly) {
- auto manifest =
- std::make_unique<ContentObjectManifest>(std::move(content_object));
-
- auth::VerificationPolicy policy = verifier_->verifyPackets(manifest.get());
-
- manifest->decode();
+ auth::VerificationPolicy policy = verifier_->verifyPackets(&content_object);
if (policy != auth::VerificationPolicy::ACCEPT) {
transport_->onContentReassembled(
@@ -72,6 +66,10 @@ void ManifestIncrementalIndexer::onUntrustedManifest(
return;
}
+ auto manifest =
+ std::make_unique<ContentObjectManifest>(std::move(content_object));
+ manifest->decode();
+
processTrustedManifest(interest, std::move(manifest), reassembly);
}
@@ -83,9 +81,10 @@ void ManifestIncrementalIndexer::processTrustedManifest(
throw errors::RuntimeException("Received manifest with unknown version.");
}
- switch (manifest->getManifestType()) {
+ switch (manifest->getType()) {
case core::ManifestType::INLINE_MANIFEST: {
- suffix_strategy_->setFinalSuffix(manifest->getFinalBlockNumber());
+ suffix_strategy_->setFinalSuffix(
+ manifest->getParamsBytestream().final_segment);
// The packets to verify with the received manifest
std::vector<auth::PacketPtr> packets;
@@ -162,45 +161,15 @@ void ManifestIncrementalIndexer::onUntrustedContentObject(
applyPolicy(interest, content_object, reassembly, policy);
}
-void ManifestIncrementalIndexer::applyPolicy(
- core::Interest &interest, core::ContentObject &content_object,
- bool reassembly, auth::VerificationPolicy policy) {
- assert(reassembly_);
- switch (policy) {
- case auth::VerificationPolicy::ACCEPT: {
- if (reassembly && !reassembly_->reassembleUnverified()) {
- reassembly_->reassemble(content_object);
- }
- break;
- }
- case auth::VerificationPolicy::DROP: {
- transport_->onPacketDropped(
- interest, content_object,
- make_error_code(protocol_error::verification_failed));
- break;
- }
- case auth::VerificationPolicy::ABORT: {
- transport_->onContentReassembled(
- make_error_code(protocol_error::session_aborted));
- break;
- }
- case auth::VerificationPolicy::UNKNOWN: {
- if (reassembly && reassembly_->reassembleUnverified()) {
- reassembly_->reassemble(content_object);
- }
- }
- }
-}
-
-uint32_t ManifestIncrementalIndexer::checkNextSuffix() {
- return suffix_strategy_->getNextSuffix();
+uint32_t ManifestIncrementalIndexer::checkNextSuffix() const {
+ return suffix_strategy_->checkNextSuffix();
}
uint32_t ManifestIncrementalIndexer::getNextSuffix() {
auto ret = suffix_strategy_->getNextSuffix();
if (ret <= suffix_strategy_->getFinalSuffix() &&
- ret != utils::SuffixStrategy::INVALID_SUFFIX) {
+ ret != utils::SuffixStrategy::MAX_SUFFIX) {
suffix_queue_.push(ret);
return ret;
}
@@ -208,7 +177,7 @@ uint32_t ManifestIncrementalIndexer::getNextSuffix() {
return Indexer::invalid_index;
}
-uint32_t ManifestIncrementalIndexer::getFinalSuffix() {
+uint32_t ManifestIncrementalIndexer::getFinalSuffix() const {
return suffix_strategy_->getFinalSuffix();
}
diff --git a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
index d8cf5892f..12876f35c 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
+++ b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -39,8 +39,7 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
ManifestIncrementalIndexer(IncrementalIndexer &&indexer)
: IncrementalIndexer(std::move(indexer)),
suffix_strategy_(utils::SuffixStrategyFactory::getSuffixStrategy(
- core::NextSegmentCalculationStrategy::INCREMENTAL,
- next_download_suffix_, 0)) {
+ utils::NextSuffixStrategy::INCREMENTAL, next_download_suffix_)) {
for (uint32_t i = first_suffix_; i < next_download_suffix_; i++) {
suffix_queue_.push(i);
}
@@ -54,7 +53,7 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
core::ContentObject &content_object,
bool reassembly) override;
- uint32_t checkNextSuffix() override;
+ uint32_t checkNextSuffix() const override;
uint32_t getNextSuffix() override;
@@ -62,7 +61,7 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
bool isFinalSuffixDiscovered() override;
- uint32_t getFinalSuffix() override;
+ uint32_t getFinalSuffix() const override;
protected:
std::unique_ptr<utils::SuffixStrategy> suffix_strategy_;
@@ -82,9 +81,6 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
void onUntrustedContentObject(core::Interest &interest,
core::ContentObject &content_object,
bool reassembly);
- void applyPolicy(core::Interest &interest,
- core::ContentObject &content_object, bool reassembly,
- auth::VerificationPolicy policy);
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/prod_protocol_bytestream.cc b/libtransport/src/protocols/prod_protocol_bytestream.cc
index f659cb37c..2a3ec07e1 100644
--- a/libtransport/src/protocols/prod_protocol_bytestream.cc
+++ b/libtransport/src/protocols/prod_protocol_bytestream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -29,12 +29,7 @@ ByteStreamProductionProtocol::ByteStreamProductionProtocol(
implementation::ProducerSocket *icn_socket)
: ProductionProtocol(icn_socket) {}
-ByteStreamProductionProtocol::~ByteStreamProductionProtocol() {
- stop();
- if (listening_thread_.joinable()) {
- listening_thread_.join();
- }
-}
+ByteStreamProductionProtocol::~ByteStreamProductionProtocol() { stop(); }
uint32_t ByteStreamProductionProtocol::produceDatagram(
const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) {
@@ -68,16 +63,16 @@ uint32_t ByteStreamProductionProtocol::produceStream(
return 0;
}
- Name name(content_name);
-
- // Get the atomic variables to ensure they keep the same value
- // during the production
-
// Total size of the data packet
uint32_t data_packet_size;
socket_->getSocketOption(GeneralTransportOptions::DATA_PACKET_SIZE,
data_packet_size);
+ // Maximum size of a segment
+ uint32_t max_segment_size;
+ socket_->getSocketOption(GeneralTransportOptions::MAX_SEGMENT_SIZE,
+ max_segment_size);
+
// Expiry time
uint32_t content_object_expiry_time;
socket_->getSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
@@ -88,106 +83,90 @@ uint32_t ByteStreamProductionProtocol::produceStream(
socket_->getSocketOption(GeneralTransportOptions::HASH_ALGORITHM, hash_algo);
// Suffix calculation strategy
- core::NextSegmentCalculationStrategy _suffix_strategy;
+ std::shared_ptr<utils::SuffixStrategy> suffix_strategy;
socket_->getSocketOption(GeneralTransportOptions::SUFFIX_STRATEGY,
- _suffix_strategy);
- auto suffix_strategy = utils::SuffixStrategyFactory::getSuffixStrategy(
- _suffix_strategy, start_offset);
+ suffix_strategy);
+ suffix_strategy->reset(start_offset);
- auto buffer_size = buffer->length();
+ // Default format
+ core::Packet::Format default_format;
+ socket_->getSocketOption(GeneralTransportOptions::PACKET_FORMAT,
+ default_format);
+
+ Name name(content_name);
+ size_t buffer_size = buffer->length();
+ size_t signature_length = signer_->getSignatureFieldSize();
+ uint32_t final_block_number = start_offset;
+
+ // Content-related
+ core::Packet::Format content_format;
+ uint32_t content_header_size;
+ uint64_t content_free_space;
+ uint32_t nb_segments;
int bytes_segmented = 0;
- std::size_t header_size;
- std::size_t manifest_header_size = 0;
- std::size_t signature_length = 0;
- std::uint32_t final_block_number = start_offset;
- uint64_t free_space_for_content = 0;
- core::Packet::Format format;
+ // Manifest-related
+ core::Packet::Format manifest_format;
+ uint32_t manifest_header_size;
+ uint64_t manifest_free_space;
+ uint32_t nb_manifests;
std::shared_ptr<core::ContentObjectManifest> manifest;
+ uint32_t manifest_capacity = making_manifest_;
bool is_last_manifest = false;
-
- // TODO Manifest may still be used for indexing
- if (making_manifest_ && !signer_) {
- LOG(FATAL) << "Making manifests without setting producer identity.";
- }
-
- core::Packet::Format hf_format = core::Packet::Format::HF_UNSPEC;
- core::Packet::Format hf_format_ah = core::Packet::Format::HF_UNSPEC;
-
- if (name.getType() == HNT_CONTIGUOUS_V4 || name.getType() == HNT_IOV_V4) {
- hf_format = core::Packet::Format::HF_INET_TCP;
- hf_format_ah = core::Packet::Format::HF_INET_TCP_AH;
- } else if (name.getType() == HNT_CONTIGUOUS_V6 ||
- name.getType() == HNT_IOV_V6) {
- hf_format = core::Packet::Format::HF_INET6_TCP;
- hf_format_ah = core::Packet::Format::HF_INET6_TCP_AH;
- } else {
- throw errors::RuntimeException("Unknown name format.");
- }
-
- format = hf_format;
- if (making_manifest_) {
- manifest_header_size = core::Packet::getHeaderSizeFromFormat(
- signer_ ? hf_format_ah : hf_format,
- signer_ ? signer_->getSignatureFieldSize() : 0);
- } else if (signer_) {
- format = hf_format_ah;
- signature_length = signer_->getSignatureFieldSize();
+ ParamsBytestream transport_params;
+
+ manifest_format = Packet::toAHFormat(default_format);
+ content_format =
+ !making_manifest_ ? 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_free_space =
+ std::min(max_segment_size, data_packet_size - content_header_size);
+ manifest_free_space =
+ std::min(max_segment_size, data_packet_size - manifest_header_size);
+
+ // Compute the number of segments the data will be split into
+ nb_segments =
+ uint32_t(std::ceil(double(buffer_size) / double(content_free_space)));
+ if (content_free_space * nb_segments < buffer_size) {
+ nb_segments++;
}
- header_size = core::Packet::getHeaderSizeFromFormat(format, signature_length);
- free_space_for_content = data_packet_size - header_size;
- uint32_t number_of_segments =
- uint32_t(std::ceil(double(buffer_size) / double(free_space_for_content)));
- if (free_space_for_content * number_of_segments < buffer_size) {
- number_of_segments++;
- }
-
- // TODO allocate space for all the headers
if (making_manifest_) {
- uint32_t segment_in_manifest = static_cast<uint32_t>(
- std::floor(double(data_packet_size - manifest_header_size -
- ContentObjectManifest::getManifestHeaderSize()) /
- ContentObjectManifest::getManifestEntrySize()) -
- 1.0);
- uint32_t number_of_manifests = static_cast<uint32_t>(
- std::ceil(float(number_of_segments) / segment_in_manifest));
- final_block_number += number_of_segments + number_of_manifests - 1;
+ 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_format,
name.setSuffix(suffix_strategy->getNextManifestSuffix()),
core::ManifestVersion::VERSION_1, core::ManifestType::INLINE_MANIFEST,
- hash_algo, is_last_manifest, name, _suffix_strategy,
- signer_ ? signer_->getSignatureFieldSize() : 0));
- manifest->setLifetime(content_object_expiry_time);
+ is_last_manifest, name, hash_algo, signature_length));
- if (is_last) {
- manifest->setFinalBlockNumber(final_block_number);
- } else {
- manifest->setFinalBlockNumber(utils::SuffixStrategy::INVALID_SUFFIX);
- }
+ manifest->setLifetime(content_object_expiry_time);
+ manifest->setParamsBytestream(transport_params);
}
- for (unsigned int packaged_segments = 0;
- packaged_segments < number_of_segments; packaged_segments++) {
+ auto self = shared_from_this();
+ for (unsigned int packaged_segments = 0; packaged_segments < nb_segments;
+ packaged_segments++) {
if (making_manifest_) {
- if (manifest->estimateManifestSize(2) >
- data_packet_size - manifest_header_size) {
+ if (manifest->estimateManifestSize(1) > manifest_free_space) {
manifest->encode();
-
- // If identity set, sign manifest
- if (signer_) {
- signer_->signPacket(manifest.get());
- }
+ signer_->signPacket(manifest.get());
// Send the current manifest
- passContentObjectToCallbacks(manifest);
-
+ passContentObjectToCallbacks(manifest, self);
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest->getName();
// Send content objects stored in the queue
while (!content_queue_.empty()) {
- passContentObjectToCallbacks(content_queue_.front());
+ passContentObjectToCallbacks(content_queue_.front(), self);
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Send content " << content_queue_.front()->getName();
content_queue_.pop();
@@ -195,86 +174,84 @@ 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
+ // safely release this reference.
manifest.reset(ContentObjectManifest::createManifest(
+ manifest_format,
name.setSuffix(suffix_strategy->getNextManifestSuffix()),
core::ManifestVersion::VERSION_1,
- core::ManifestType::INLINE_MANIFEST, hash_algo, is_last_manifest,
- name, _suffix_strategy,
- signer_ ? signer_->getSignatureFieldSize() : 0));
+ core::ManifestType::INLINE_MANIFEST, is_last_manifest, name,
+ hash_algo, signature_length));
manifest->setLifetime(content_object_expiry_time);
- manifest->setFinalBlockNumber(
- is_last ? final_block_number
- : utils::SuffixStrategy::INVALID_SUFFIX);
+ manifest->setParamsBytestream(transport_params);
}
}
- auto content_suffix = suffix_strategy->getNextContentSuffix();
+ // Create content object
+ uint32_t content_suffix = suffix_strategy->getNextContentSuffix();
auto content_object = std::make_shared<ContentObject>(
- name.setSuffix(content_suffix), format,
- signer_ && !making_manifest_ ? signer_->getSignatureFieldSize() : 0);
+ name.setSuffix(content_suffix), content_format,
+ !making_manifest_ ? signature_length : 0);
content_object->setLifetime(content_object_expiry_time);
auto b = buffer->cloneOne();
- b->trimStart(free_space_for_content * packaged_segments);
+ b->trimStart(content_free_space * packaged_segments);
b->trimEnd(b->length());
- if (TRANSPORT_EXPECT_FALSE(packaged_segments == number_of_segments - 1)) {
+ // Segment the input data
+ if (TRANSPORT_EXPECT_FALSE(packaged_segments == nb_segments - 1)) {
b->append(buffer_size - bytes_segmented);
bytes_segmented += (int)(buffer_size - bytes_segmented);
if (is_last && making_manifest_) {
is_last_manifest = true;
} else if (is_last) {
- content_object->setRst();
+ content_object->setLast();
}
} else {
- b->append(free_space_for_content);
- bytes_segmented += (int)(free_space_for_content);
+ b->append(content_free_space);
+ bytes_segmented += (int)(content_free_space);
}
+ // Set the segmented data as payload
content_object->appendPayload(std::move(b));
+ // Either we sign the content object or we save its hash into the current
+ // manifest
if (making_manifest_) {
- using namespace std::chrono_literals;
auth::CryptoHash hash = content_object->computeDigest(hash_algo);
manifest->addSuffixHash(content_suffix, hash);
content_queue_.push(content_object);
} else {
- if (signer_) {
- signer_->signPacket(content_object.get());
- }
- passContentObjectToCallbacks(content_object);
+ signer_->signPacket(content_object.get());
+ passContentObjectToCallbacks(content_object, self);
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Send content " << content_object->getName();
}
}
+ // We send the manifest that hasn't been fully filled yet
if (making_manifest_) {
if (is_last_manifest) {
- manifest->setFinalManifest(is_last_manifest);
+ manifest->setIsLast(is_last_manifest);
}
manifest->encode();
+ signer_->signPacket(manifest.get());
- if (signer_) {
- signer_->signPacket(manifest.get());
- }
-
- passContentObjectToCallbacks(manifest);
+ passContentObjectToCallbacks(manifest, self);
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest->getName();
while (!content_queue_.empty()) {
- passContentObjectToCallbacks(content_queue_.front());
+ passContentObjectToCallbacks(content_queue_.front(), self);
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Send content " << content_queue_.front()->getName();
content_queue_.pop();
}
}
- portal_->getIoService().post([this]() {
+ portal_->getThread().add([this, self]() {
std::shared_ptr<ContentObject> co;
while (object_queue_for_callbacks_.pop(co)) {
if (*on_new_segment_) {
@@ -296,7 +273,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
}
});
- portal_->getIoService().dispatch([this, buffer_size]() {
+ portal_->getThread().add([this, buffer_size, self]() {
if (*on_content_produced_) {
on_content_produced_->operator()(*socket_->getInterface(),
std::make_error_code(std::errc(0)),
@@ -307,9 +284,10 @@ uint32_t ByteStreamProductionProtocol::produceStream(
return suffix_strategy->getTotalCount();
}
-void ByteStreamProductionProtocol::scheduleSendBurst() {
- portal_->getIoService().post([this]() {
- std::shared_ptr<ContentObject> co;
+void ByteStreamProductionProtocol::scheduleSendBurst(
+ const std::shared_ptr<ByteStreamProductionProtocol> &self) {
+ portal_->getThread().add([this, self]() {
+ ContentObject::Ptr co;
for (uint32_t i = 0; i < burst_size; i++) {
if (object_queue_for_callbacks_.pop(co)) {
@@ -321,11 +299,15 @@ void ByteStreamProductionProtocol::scheduleSendBurst() {
on_content_object_to_sign_->operator()(*socket_->getInterface(), *co);
}
+ output_buffer_.insert(co);
+
if (*on_content_object_in_output_buffer_) {
on_content_object_in_output_buffer_->operator()(
*socket_->getInterface(), *co);
}
+ portal_->sendContentObject(*co);
+
if (*on_content_object_output_) {
on_content_object_output_->operator()(*socket_->getInterface(), *co);
}
@@ -337,13 +319,12 @@ void ByteStreamProductionProtocol::scheduleSendBurst() {
}
void ByteStreamProductionProtocol::passContentObjectToCallbacks(
- const std::shared_ptr<ContentObject> &content_object) {
- output_buffer_.insert(content_object);
- portal_->sendContentObject(*content_object);
+ const std::shared_ptr<ContentObject> &content_object,
+ const std::shared_ptr<ByteStreamProductionProtocol> &self) {
object_queue_for_callbacks_.push(std::move(content_object));
if (object_queue_for_callbacks_.size() >= burst_size) {
- scheduleSendBurst();
+ scheduleSendBurst(self);
}
}
@@ -376,7 +357,5 @@ void ByteStreamProductionProtocol::onInterest(Interest &interest) {
}
}
-void ByteStreamProductionProtocol::onError(std::error_code ec) {}
-
} // namespace protocol
} // end namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_bytestream.h b/libtransport/src/protocols/prod_protocol_bytestream.h
index cf36b90a5..809ad8d5c 100644
--- a/libtransport/src/protocols/prod_protocol_bytestream.h
+++ b/libtransport/src/protocols/prod_protocol_bytestream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -50,16 +50,19 @@ class ByteStreamProductionProtocol : public ProductionProtocol {
uint32_t produceDatagram(const Name &content_name, const uint8_t *buffer,
size_t buffer_size) override;
+ auto shared_from_this() { return utils::shared_from(this); }
+
protected:
// Consumer Callback
// void reset() override;
void onInterest(core::Interest &i) override;
- void onError(std::error_code ec) override;
private:
void passContentObjectToCallbacks(
- const std::shared_ptr<ContentObject> &content_object);
- void scheduleSendBurst();
+ const std::shared_ptr<ContentObject> &content_object,
+ const std::shared_ptr<ByteStreamProductionProtocol> &self);
+ void scheduleSendBurst(
+ const std::shared_ptr<ByteStreamProductionProtocol> &self);
private:
// While manifests are being built, contents are stored in a queue
diff --git a/libtransport/src/protocols/prod_protocol_rtc.cc b/libtransport/src/protocols/prod_protocol_rtc.cc
index cdc882d81..242abd30d 100644
--- a/libtransport/src/protocols/prod_protocol_rtc.cc
+++ b/libtransport/src/protocols/prod_protocol_rtc.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,9 +13,11 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/core/global_object_pool.h>
#include <implementation/socket_producer.h>
#include <protocols/prod_protocol_rtc.h>
+#include <protocols/rtc/probe_handler.h>
#include <protocols/rtc/rtc_consts.h>
#include <stdlib.h>
#include <time.h>
@@ -38,71 +40,89 @@ RTCProductionProtocol::RTCProductionProtocol(
bytes_production_rate_(0),
packets_production_rate_(0),
fec_packets_production_rate_(0),
- last_round_(std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count()),
+ 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) {
- srand((unsigned int)time(NULL));
- prod_label_ = rand() % 256;
+ on_consumer_in_sync_(nullptr),
+ pending_fec_pace_(false),
+ max_len_(0),
+ queue_len_(0),
+ data_aggregation_(true),
+ data_aggregation_timer_switch_(false) {
+ 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_->getIoService());
- round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
+ round_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
+ fec_pacing_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
+ app_packets_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
setOutputBufferSize(10000);
- scheduleRoundTimer();
+}
+
+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);
+
+ // Default format
+ core::Packet::Format default_format;
+ socket_->getSocketOption(interface::GeneralTransportOptions::PACKET_FORMAT,
+ default_format);
// FEC
using namespace std::placeholders;
enableFEC(std::bind(&RTCProductionProtocol::onFecPackets, this, _1),
std::bind(&RTCProductionProtocol::getBuffer, this, _1));
-}
-RTCProductionProtocol::~RTCProductionProtocol() {}
+ // Aggregated data
+ socket_->getSocketOption(interface::RtcTransportOptions::AGGREGATED_DATA,
+ data_aggregation_);
-void RTCProductionProtocol::registerNamespaceWithNetwork(
- const Prefix &producer_namespace) {
- ProductionProtocol::registerNamespaceWithNetwork(producer_namespace);
-
- flow_name_ = producer_namespace.getName();
- auto family = flow_name_.getAddressFamily();
-
- switch (family) {
- case AF_INET6:
- data_header_size_ =
- signer_ && !making_manifest_
- ? (uint32_t)Packet::getHeaderSizeFromFormat(
- HF_INET6_TCP_AH, signer_->getSignatureFieldSize())
- : (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET6_TCP);
- ;
- break;
- case AF_INET:
- data_header_size_ =
- signer_ && !making_manifest_
- ? (uint32_t)Packet::getHeaderSizeFromFormat(
- HF_INET_TCP_AH, signer_->getSignatureFieldSize())
- : (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET_TCP);
- break;
- default:
- throw errors::RuntimeException("Unknown name format.");
- }
+ size_t signature_size = signer->getSignatureFieldSize();
+ data_header_format_ = {
+ !making_manifest ? Packet::toAHFormat(default_format) : default_format,
+ !making_manifest ? 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};
+
+ // Schedule round timer
+ scheduleRoundTimer();
}
void RTCProductionProtocol::scheduleRoundTimer() {
round_timer_->expires_from_now(
std::chrono::milliseconds(rtc::PRODUCER_STATS_INTERVAL));
- round_timer_->async_wait([this](std::error_code ec) {
+ std::weak_ptr<RTCProductionProtocol> self = shared_from_this();
+ round_timer_->async_wait([self](const std::error_code &ec) {
if (ec) return;
- updateStats();
+
+ auto sp = self.lock();
+ if (sp && sp->isRunning()) {
+ sp->updateStats();
+ }
});
}
void RTCProductionProtocol::updateStats() {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint64_t duration = now - last_round_;
if (duration == 0) duration = 1;
double per_second = rtc::MILLI_IN_A_SEC / duration;
@@ -125,11 +145,12 @@ void RTCProductionProtocol::updateStats() {
if (max_packet_production_ < rtc::WIN_MIN)
max_packet_production_ = rtc::WIN_MIN;
- if (packets_production_rate_ != 0) {
- allow_delayed_nacks_ = false;
- } else if (prev_packets_production_rate == 0) {
- // at least 2 rounds with production rate = 0
+ if (packets_production_rate_ <= rtc::MIN_PRODUCTION_RATE ||
+ prev_packets_production_rate <= rtc::MIN_PRODUCTION_RATE) {
allow_delayed_nacks_ = true;
+ } else {
+ // at least 2 rounds with enough packets
+ allow_delayed_nacks_ = false;
}
// check if the production rate is decreased. if yes send nacks if needed
@@ -170,42 +191,237 @@ uint32_t RTCProductionProtocol::produceDatagram(
socket_->getSocketOption(interface::GeneralTransportOptions::DATA_PACKET_SIZE,
data_packet_size);
- if (TRANSPORT_EXPECT_FALSE((buffer_size + data_header_size_ +
- rtc::DATA_HEADER_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)) {
return 0;
}
+ if (!data_aggregation_) {
+ // if data aggregation is off emptyQueue will always return doing nothing
+ emptyQueue();
+
+ sendManifest(content_name);
+
+ // create content object
+ auto content_object =
+ core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ data_header_format_.first, data_header_format_.second);
+
+ // add rtc header to the payload
+ struct rtc::data_packet_t header;
+ content_object->appendPayload((const uint8_t *)&header,
+ rtc::DATA_HEADER_SIZE);
+ content_object->appendPayload(buffer->data(), buffer->length());
+
+ // schedule actual sending on internal thread
+ portal_->getThread().tryRunHandlerNow(
+ [this, content_object{std::move(content_object)},
+ content_name]() mutable {
+ produceInternal(std::move(content_object), content_name);
+ });
+ } else {
+ // XXX here we assume that all the packets that we push to the queue have
+ // the same name
+ auto app_pkt = utils::MemBuf::copyBuffer(buffer->data(), buffer->length());
+ addPacketToQueue(std::move(app_pkt));
+ }
+
+ return 1;
+}
+
+void RTCProductionProtocol::addPacketToQueue(
+ std::unique_ptr<utils::MemBuf> &&buffer) {
+ std::size_t buffer_size = buffer->length();
+ if ((queue_len_ + buffer_size) > rtc::MAX_RTC_PAYLOAD_SIZE) {
+ emptyQueue(); // this should guaranty that the generated packet will never
+ // be larger than an MTU
+ }
+
+ waiting_app_packets_.push(std::move(buffer));
+ if (max_len_ < buffer_size) max_len_ = buffer_size;
+ queue_len_ += buffer_size;
+
+ if (waiting_app_packets_.size() >= rtc::MAX_AGGREGATED_PACKETS) {
+ emptyQueue();
+ }
+
+ if (waiting_app_packets_.size() >= 1 && !data_aggregation_timer_switch_) {
+ data_aggregation_timer_switch_ = true;
+ app_packets_timer_->expires_from_now(
+ std::chrono::milliseconds(rtc::AGGREGATED_PACKETS_TIMER));
+ std::weak_ptr<RTCProductionProtocol> self = shared_from_this();
+ app_packets_timer_->async_wait([self](const std::error_code &ec) {
+ if (ec) return;
+
+ auto ptr = self.lock();
+ if (ptr && ptr->isRunning()) {
+ if (!ptr->data_aggregation_timer_switch_) return;
+ ptr->emptyQueue();
+ }
+ });
+ }
+}
+
+void RTCProductionProtocol::emptyQueue() {
+ if (waiting_app_packets_.size() == 0) return; // queue is empty
+
+ Name n(flow_name_);
+
+ // cancel timer is scheduled
+ if (data_aggregation_timer_switch_) {
+ data_aggregation_timer_switch_ = false;
+ app_packets_timer_->cancel();
+ }
+
+ // send a manifest beforehand if the hash buffer if full
+ sendManifest(n);
+
+ // create content object
auto content_object =
core::PacketManager<>::getInstance().getPacket<ContentObject>(
- signer_ ? Format::HF_INET6_TCP_AH : Format::HF_INET6_TCP,
- signer_ ? signer_->getSignatureFieldSize() : 0);
+ data_header_format_.first, data_header_format_.second);
+
// add rtc header to the payload
struct rtc::data_packet_t header;
content_object->appendPayload((const uint8_t *)&header,
rtc::DATA_HEADER_SIZE);
- content_object->appendPayload(buffer->data(), buffer->length());
- // schedule actual sending on internal thread
- portal_->getIoService().dispatch([this,
- content_object{std::move(content_object)},
- content_name]() mutable {
- produceInternal(std::move(content_object), content_name);
+ // init aggregated header
+ rtc::AggrPktHeader hdr(
+ (uint8_t *)(content_object->getPayload()->data() + rtc::DATA_HEADER_SIZE),
+ max_len_, waiting_app_packets_.size());
+ uint32_t header_size = hdr.getHeaderLen();
+ content_object->append(header_size); // leave space for the aggregated header
+
+ uint8_t index = 0;
+ while (waiting_app_packets_.size() != 0) {
+ std::unique_ptr<utils::MemBuf> pkt =
+ std::move(waiting_app_packets_.front());
+ waiting_app_packets_.pop();
+ // XXX for the moment we have a single name, so this works, otherwise we
+ // need to do something else
+ hdr.addPacketToHeader(index, pkt->length());
+ // append packet
+ content_object->appendPayload(pkt->data(), pkt->length());
+ index++;
+ }
+
+ // reset queue values
+ max_len_ = 0;
+ queue_len_ = 0;
+
+ // the packet is ready we need to send it
+ portal_->getThread().tryRunHandlerNow(
+ [this, content_object{std::move(content_object)}, n]() mutable {
+ produceInternal(std::move(content_object), n);
+ });
+}
+
+void RTCProductionProtocol::sendManifest(const Name &name) {
+ if (!making_manifest_) {
+ 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_;
+
+ // If there is not enough hashes to fill a manifest, return early
+ if (manifest_entries_.size() < manifest_capacity) {
+ return;
+ }
+
+ // Create a new manifest
+ std::shared_ptr<core::ContentObjectManifest> manifest =
+ createManifest(manifest_name.setSuffix(current_seg_));
+
+ // Fill the manifest with packet hashes that were previously saved
+ uint32_t nb_entries;
+ for (nb_entries = 0; nb_entries < manifest_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_entries_.pop();
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Sending manifest " << manifest->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 {
+ produceInternal(std::move(content_object), manifest_name);
+ });
+}
+
+std::shared_ptr<core::ContentObjectManifest>
+RTCProductionProtocol::createManifest(const Name &content_name) const {
+ Name name(content_name);
+
+ auth::CryptoHashType hash_algo;
+ socket_->getSocketOption(interface::GeneralTransportOptions::HASH_ALGORITHM,
+ hash_algo);
+
+ 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));
+
+ // Set connection parameters
+ manifest->setParamsRTC(ParamsRTC{
+ .timestamp = now,
+ .prod_rate = bytes_production_rate_,
+ .prod_seg = current_seg_,
+ .support_fec = false,
});
- return 1;
+ return manifest;
}
void RTCProductionProtocol::produceInternal(
std::shared_ptr<ContentObject> &&content_object, const Name &content_name,
bool fec) {
+ uint64_t now = utils::SteadyTime::nowMs().count();
+
+ if (fec && (now - last_produced_data_ts_) < rtc::FEC_PACING_TIME) {
+ paced_fec_packets_.push(std::pair<uint64_t, ContentObject::Ptr>(
+ now, std::move(content_object)));
+ postponeFecPacket();
+ } else {
+ // need to check if there are FEC packets waiting to be sent
+ flushFecPkts(current_seg_);
+ producePktInternal(std::move(content_object), content_name, fec);
+ }
+}
+
+void RTCProductionProtocol::producePktInternal(
+ std::shared_ptr<ContentObject> &&content_object, const Name &content_name,
+ bool fec) {
+ bool is_manifest = content_object->getPayloadType() == PayloadType::MANIFEST;
+ uint64_t now = utils::SteadyTime::nowMs().count();
+
// set rtc header
- struct rtc::data_packet_t *data_pkt =
- (struct rtc::data_packet_t *)content_object->getPayload()->data();
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- data_pkt->setTimestamp(now);
- data_pkt->setProductionRate(bytes_production_rate_);
+ if (!is_manifest) {
+ struct rtc::data_packet_t *data_pkt =
+ (struct rtc::data_packet_t *)content_object->getPayload()->data();
+ data_pkt->setTimestamp(now);
+ data_pkt->setProductionRate(bytes_production_rate_);
+ }
// set hicn stuff
Name n(content_name);
@@ -213,11 +429,6 @@ void RTCProductionProtocol::produceInternal(
content_object->setLifetime(500); // XXX this should be set by the APP
content_object->setPathLabel(prod_label_);
- // sign packet
- if (signer_) {
- signer_->signPacket(content_object.get());
- }
-
// update stats
if (!fec) {
produced_bytes_ +=
@@ -227,7 +438,7 @@ void RTCProductionProtocol::produceInternal(
produced_fec_packets_++;
}
- if (produced_packets_ >= max_packet_production_) {
+ if (!data_aggregation_ && produced_packets_ >= max_packet_production_) {
// in this case all the pending interests may be used to accomodate the
// sudden increase in the production rate. calling the updateStats we will
// notify all the clients
@@ -240,8 +451,12 @@ void RTCProductionProtocol::produceInternal(
// pass packet to FEC encoder
if (fec_encoder_ && !fec) {
- fec_encoder_->onPacketProduced(
- *content_object, content_object->headerSize() + rtc::DATA_HEADER_SIZE);
+ uint32_t offset =
+ is_manifest ? content_object->headerSize()
+ : content_object->headerSize() + rtc::DATA_HEADER_SIZE;
+ uint32_t metadata = static_cast<uint32_t>(content_object->getPayloadType());
+
+ fec_encoder_->onPacketProduced(*content_object, offset, metadata);
}
output_buffer_.insert(content_object);
@@ -253,7 +468,7 @@ void RTCProductionProtocol::produceInternal(
auto seq_it = seqs_map_.find(current_seg_);
if (seq_it != seqs_map_.end()) {
- portal_->sendContentObject(*content_object);
+ sendContentObject(content_object, false, fec);
}
if (*on_content_object_output_) {
@@ -264,6 +479,8 @@ void RTCProductionProtocol::produceInternal(
// remove interests from the interest cache if it exists
removeFromInterestQueue(current_seg_);
+ if (!fec) last_produced_data_ts_ = now;
+
// Update current segment
current_seg_ = (current_seg_ + 1) % rtc::MIN_PROBE_SEQ;
@@ -277,6 +494,55 @@ void RTCProductionProtocol::produceInternal(
}
}
+void RTCProductionProtocol::flushFecPkts(uint32_t current_seq_num) {
+ // Currently we immediately send all the pending fec packets
+ // A pacing policy may be helpful, but we do not want to delay too much
+ // the packets at this moment.
+ while (paced_fec_packets_.size() > 0) {
+ producePktInternal(std::move(paced_fec_packets_.front().second), flow_name_,
+ true);
+ paced_fec_packets_.pop();
+ }
+ fec_pacing_timer_->cancel();
+ pending_fec_pace_ = false;
+ postponeFecPacket();
+}
+
+void RTCProductionProtocol::postponeFecPacket() {
+ if (paced_fec_packets_.size() == 0) return;
+ if (pending_fec_pace_) {
+ return;
+ }
+
+ uint64_t produced_time = paced_fec_packets_.front().first;
+ uint64_t now = utils::SteadyTime::nowMs().count();
+
+ uint64_t wait_time = 0;
+ if ((produced_time + rtc::FEC_PACING_TIME) > now)
+ wait_time = produced_time + rtc::FEC_PACING_TIME - now;
+
+ fec_pacing_timer_->expires_from_now(std::chrono::milliseconds(wait_time));
+ pending_fec_pace_ = true;
+
+ std::weak_ptr<RTCProductionProtocol> self = shared_from_this();
+ fec_pacing_timer_->async_wait([self](const std::error_code &ec) {
+ if (ec) return;
+
+ auto sp = self.lock();
+ if (sp && sp->isRunning()) {
+ if (!sp->pending_fec_pace_) return;
+
+ if (sp->paced_fec_packets_.size() > 0) {
+ sp->producePktInternal(std::move(sp->paced_fec_packets_.front().second),
+ sp->flow_name_, true);
+ sp->paced_fec_packets_.pop();
+ }
+ sp->pending_fec_pace_ = false;
+ sp->postponeFecPacket();
+ }
+ });
+}
+
void RTCProductionProtocol::onInterest(Interest &interest) {
if (*on_interest_input_) {
on_interest_input_->operator()(*socket_->getInterface(), interest);
@@ -284,7 +550,7 @@ void RTCProductionProtocol::onInterest(Interest &interest) {
auto suffix = interest.firstSuffix();
// numberOfSuffixes returns only the prefixes in the payalod
- // we add + 1 to count anche the seq in the name
+ // 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_;
@@ -293,6 +559,7 @@ void RTCProductionProtocol::onInterest(Interest &interest) {
if (i > 0) {
name.setSuffix(*(suffix + (i - 1)));
}
+
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received interest " << name;
const std::shared_ptr<ContentObject> content_object =
@@ -312,7 +579,7 @@ void RTCProductionProtocol::onInterest(Interest &interest) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Send content %u (onInterest) " << content_object->getName();
content_object->setPathLabel(cache_label_);
- portal_->sendContentObject(*content_object);
+ sendContentObject(content_object);
} else {
if (*on_interest_process_) {
on_interest_process_->operator()(*socket_->getInterface(), interest);
@@ -332,14 +599,19 @@ void RTCProductionProtocol::processInterest(uint32_t interest_seg,
consumer_in_sync_ = false;
}
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
- if (interest_seg > rtc::MIN_PROBE_SEQ) {
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received probe " << interest_seg;
- sendNack(interest_seg);
- return;
+ switch (rtc::ProbeHandler::getProbeType(interest_seg)) {
+ case rtc::ProbeType::INIT:
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received init probe " << interest_seg;
+ sendManifestProbe(interest_seg);
+ return;
+ case rtc::ProbeType::RTT:
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received RTT probe " << interest_seg;
+ sendNack(interest_seg);
+ return;
+ default:
+ break;
}
// if the production rate 0 use delayed nacks
@@ -349,7 +621,7 @@ void RTCProductionProtocol::processInterest(uint32_t interest_seg,
next_timer = timers_map_.begin()->first;
}
- uint64_t expiration = now + rtc::SENTINEL_TIMER_INTERVAL;
+ 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
@@ -369,8 +641,8 @@ void RTCProductionProtocol::processInterest(uint32_t interest_seg,
}
if (queue_timer_on_) {
- // the producer is producing. Send nacks to packets that will expire before
- // the data production and remove the timer
+ // 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();
@@ -387,8 +659,8 @@ void RTCProductionProtocol::processInterest(uint32_t interest_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
+ // 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;
@@ -401,13 +673,18 @@ void RTCProductionProtocol::processInterest(uint32_t interest_seg,
}
}
-void RTCProductionProtocol::onError(std::error_code ec) {}
-
void RTCProductionProtocol::scheduleQueueTimer(uint64_t wait) {
interests_queue_timer_->expires_from_now(std::chrono::milliseconds(wait));
- interests_queue_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
- interestQueueTimer();
+ 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();
+ }
});
}
@@ -450,9 +727,7 @@ void RTCProductionProtocol::sendNacksForPendingInterests() {
if (packets_production_rate_ != 0)
packet_gap = ceil(rtc::MILLI_IN_A_SEC / (double)packets_production_rate_);
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
for (auto it = seqs_map_.begin(); it != seqs_map_.end(); it++) {
if (it->first > current_seg_) {
@@ -486,9 +761,7 @@ void RTCProductionProtocol::removeFromInterestQueue(uint32_t interest_seg) {
}
void RTCProductionProtocol::interestQueueTimer() {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ 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;
@@ -511,20 +784,37 @@ void RTCProductionProtocol::interestQueueTimer() {
}
}
+void RTCProductionProtocol::sendManifestProbe(uint32_t sequence) {
+ Name manifest_name(flow_name_);
+ manifest_name.setSuffix(sequence);
+
+ std::shared_ptr<core::ContentObjectManifest> manifest_probe =
+ createManifest(manifest_name);
+
+ manifest_probe->setLifetime(0);
+ manifest_probe->setPathLabel(prod_label_);
+ manifest_probe->encode();
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ *manifest_probe);
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send init probe " << sequence;
+ sendContentObject(manifest_probe, true, false);
+}
+
void RTCProductionProtocol::sendNack(uint32_t sequence) {
auto nack = core::PacketManager<>::getInstance().getPacket<ContentObject>(
- signer_ ? Format::HF_INET6_TCP_AH : Format::HF_INET6_TCP,
- signer_ ? signer_->getSignatureFieldSize() : 0);
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ nack_header_format_.first, nack_header_format_.second);
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint32_t next_packet = current_seg_;
uint32_t prod_rate = bytes_production_rate_;
struct rtc::nack_packet_t header;
header.setTimestamp(now);
header.setProductionRate(prod_rate);
- header.setProductionSegement(next_packet);
+ header.setProductionSegment(next_packet);
nack->appendPayload((const uint8_t *)&header, rtc::NACK_HEADER_SIZE);
Name n(flow_name_);
@@ -533,14 +823,16 @@ void RTCProductionProtocol::sendNack(uint32_t sequence) {
nack->setLifetime(0);
nack->setPathLabel(prod_label_);
- if (signer_) {
- signer_->signPacket(nack.get());
- }
-
if (!consumer_in_sync_ && on_consumer_in_sync_ &&
- sequence < rtc::MIN_PROBE_SEQ && sequence > next_packet) {
+ rtc::ProbeHandler::getProbeType(sequence) == rtc::ProbeType::NOT_PROBE &&
+ sequence > next_packet) {
consumer_in_sync_ = true;
- auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
+ 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);
}
@@ -550,16 +842,37 @@ void RTCProductionProtocol::sendNack(uint32_t sequence) {
}
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send nack " << sequence;
- portal_->sendContentObject(*nack);
+ sendContentObject(nack, true, false);
}
-void RTCProductionProtocol::onFecPackets(
- std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
+void RTCProductionProtocol::sendContentObject(
+ std::shared_ptr<ContentObject> content_object, bool nack, bool fec) {
+ bool is_ah = _is_ah(content_object->getFormat());
+
+ // Compute signature
+ if (is_ah) {
+ signer_->signPacket(content_object.get());
+ }
+
+ portal_->sendContentObject(*content_object);
+
+ // Compute and save data packet digest
+ if (making_manifest_ && !is_ah) {
+ auth::CryptoHashType hash_algo;
+ socket_->getSocketOption(interface::GeneralTransportOptions::HASH_ALGORITHM,
+ hash_algo);
+ manifest_entries_.push({content_object->getName().getSuffix(),
+ content_object->computeDigest(hash_algo)});
+ }
+}
+
+void RTCProductionProtocol::onFecPackets(fec::BufferArray &packets) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Produced " << packets.size() << " FEC packets";
+
for (auto &packet : packets) {
auto content_object =
- std::static_pointer_cast<ContentObject>(packet.second);
+ std::static_pointer_cast<ContentObject>(packet.getBuffer());
content_object->prepend(content_object->headerSize() +
rtc::DATA_HEADER_SIZE);
pending_fec_packets_.push(std::move(content_object));
@@ -569,19 +882,21 @@ void RTCProductionProtocol::onFecPackets(
fec::buffer RTCProductionProtocol::getBuffer(std::size_t size) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Asked buffer for FEC symbol of size " << size;
+
auto ret = core::PacketManager<>::getInstance().getPacket<ContentObject>(
- signer_ ? Format::HF_INET6_TCP_AH : Format::HF_INET6_TCP,
- signer_ ? signer_->getSignatureFieldSize() : 0);
+ fec_header_format_.first, fec_header_format_.second);
+
ret->updateLength(rtc::DATA_HEADER_SIZE + size);
ret->append(rtc::DATA_HEADER_SIZE + size);
ret->trimStart(ret->headerSize() + rtc::DATA_HEADER_SIZE);
+
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Responding with buffer of length " << ret->length();
- assert(ret->length() >= size);
+ DCHECK(ret->length() >= size);
return ret;
}
} // namespace protocol
-} // end namespace transport
+} // namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_rtc.h b/libtransport/src/protocols/prod_protocol_rtc.h
index 96ad5673d..7f50a2505 100644
--- a/libtransport/src/protocols/prod_protocol_rtc.h
+++ b/libtransport/src/protocols/prod_protocol_rtc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,6 +32,7 @@ class RTCProductionProtocol : public ProductionProtocol {
using ProductionProtocol::start;
using ProductionProtocol::stop;
+ void setProducerParam() override;
void produce(ContentObject &content_object) override;
uint32_t produceStream(const Name &content_name,
@@ -49,21 +50,31 @@ class RTCProductionProtocol : public ProductionProtocol {
buffer, buffer_size, buffer_size));
}
- void registerNamespaceWithNetwork(const Prefix &producer_namespace) override;
-
void setConsumerInSyncCallback(
interface::ProducerInterestCallback &&callback) {
on_consumer_in_sync_ = std::move(callback);
}
+ auto shared_from_this() { return utils::shared_from(this); }
+
private:
// packet handlers
void onInterest(Interest &interest) override;
- void onError(std::error_code ec) override;
+ void onError(const std::error_code &ec) override{};
void processInterest(uint32_t interest_seg, uint32_t lifetime);
+ void producePktInternal(std::shared_ptr<ContentObject> &&content_object,
+ const Name &content_name, bool fec = false);
void produceInternal(std::shared_ptr<ContentObject> &&content_object,
const Name &content_name, bool fec = false);
void sendNack(uint32_t sequence);
+ void sendContentObject(std::shared_ptr<ContentObject> content_object,
+ bool nac = false, bool fec = false);
+
+ // manifests
+ void sendManifestProbe(uint32_t sequence);
+ void sendManifest(const Name &content_name);
+ std::shared_ptr<core::ContentObjectManifest> createManifest(
+ const Name &name) const;
// stats
void updateStats();
@@ -77,15 +88,25 @@ class RTCProductionProtocol : public ProductionProtocol {
void interestQueueTimer();
// FEC functions
- void onFecPackets(std::vector<std::pair<uint32_t, fec::buffer>> &packets);
+ void onFecPackets(fec::BufferArray &packets);
fec::buffer getBuffer(std::size_t size);
+ void postponeFecPacket();
+ void dispatchFecPacket();
+ void flushFecPkts(uint32_t current_seq_num);
+ // aggregated data functions
+ void emptyQueue();
+ void addPacketToQueue(std::unique_ptr<utils::MemBuf> &&buffer);
core::Name flow_name_;
- uint32_t current_seg_; // seq id of the next packet produced
- uint32_t prod_label_; // path lable of the producer
- uint32_t cache_label_; // path lable for content from the producer cache
- uint16_t data_header_size_; // hicn data header size
+ std::pair<core::Packet::Format, size_t> data_header_format_;
+ std::pair<core::Packet::Format, size_t> manifest_header_format_;
+ std::pair<core::Packet::Format, size_t> fec_header_format_;
+ std::pair<core::Packet::Format, size_t> nack_header_format_;
+
+ uint32_t current_seg_; // seq id of the next packet produced
+ uint32_t prod_label_; // path label of the producer
+ uint32_t cache_label_; // path label for content from the producer cache
uint32_t produced_bytes_; // bytes produced in the last round
uint32_t produced_packets_; // packet produed in the last round
@@ -98,7 +119,11 @@ class RTCProductionProtocol : public ProductionProtocol {
uint32_t packets_production_rate_; // pps
uint32_t fec_packets_production_rate_; // pps
+ uint64_t last_produced_data_ts_; // ms
+
std::unique_ptr<asio::steady_timer> round_timer_;
+ std::unique_ptr<asio::steady_timer> fec_pacing_timer_;
+
uint64_t last_round_;
// delayed nacks are used by the producer to avoid to send too
@@ -131,6 +156,21 @@ class RTCProductionProtocol : public ProductionProtocol {
// 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_;
+ bool pending_fec_pace_;
+
+ // Save application packets if they are small
+ std::queue<std::unique_ptr<utils::MemBuf>> waiting_app_packets_;
+ uint16_t max_len_; // len of the largest packet
+ uint16_t queue_len_; // total size of all packet in the queue
+ bool data_aggregation_; // turns on/off data aggregation
+ // timer to check the queue len
+ std::unique_ptr<asio::steady_timer> app_packets_timer_;
+ bool data_aggregation_timer_switch_; // bool to check if the timer is on
+
+ // Manifest
+ std::queue<std::pair<uint32_t, auth::CryptoHash>>
+ manifest_entries_; // map a packet suffix to a packet hash
};
} // namespace protocol
diff --git a/libtransport/src/protocols/production_protocol.cc b/libtransport/src/protocols/production_protocol.cc
index 6b317d47d..8b781e38a 100644
--- a/libtransport/src/protocols/production_protocol.cc
+++ b/libtransport/src/protocols/production_protocol.cc
@@ -24,8 +24,8 @@ using namespace interface;
ProductionProtocol::ProductionProtocol(
implementation::ProducerSocket *icn_socket)
- : socket_(icn_socket),
- is_running_(false),
+ : Protocol(),
+ socket_(icn_socket),
fec_encoder_(nullptr),
on_interest_input_(VOID_HANDLER),
on_interest_dropped_input_buffer_(VOID_HANDLER),
@@ -38,101 +38,92 @@ ProductionProtocol::ProductionProtocol(
on_content_object_output_(VOID_HANDLER),
on_content_object_evicted_from_output_buffer_(VOID_HANDLER),
on_content_produced_(VOID_HANDLER),
+ producer_callback_(VOID_HANDLER),
fec_type_(fec::FECType::UNKNOWN) {
socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
// TODO add statistics for producer
// socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
}
-ProductionProtocol::~ProductionProtocol() {
- if (!is_async_ && is_running_) {
- stop();
- }
+ProductionProtocol::~ProductionProtocol() {}
- if (listening_thread_.joinable()) {
- listening_thread_.join();
+int ProductionProtocol::start() {
+ if (isRunning()) {
+ return -1;
}
-}
-int ProductionProtocol::start() {
- socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
- &on_interest_input_);
- socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_DROP,
- &on_interest_dropped_input_buffer_);
- socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_PASS,
- &on_interest_inserted_input_buffer_);
- socket_->getSocketOption(ProducerCallbacksOptions::CACHE_HIT,
- &on_interest_satisfied_output_buffer_);
- socket_->getSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- &on_interest_process_);
- socket_->getSocketOption(ProducerCallbacksOptions::NEW_CONTENT_OBJECT,
- &on_new_segment_);
- socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_READY,
- &on_content_object_in_output_buffer_);
- socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_OUTPUT,
- &on_content_object_output_);
- socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN,
- &on_content_object_to_sign_);
- socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED,
- &on_content_produced_);
-
- socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
- socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer_);
- socket_->getSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- making_manifest_);
-
- bool first = true;
-
- for (core::Prefix &producer_namespace : served_namespaces_) {
- if (first) {
- core::BindConfig bind_config(producer_namespace, 1000);
- portal_->bind(bind_config);
- portal_->setProducerCallback(this);
- first = !first;
- } else {
- portal_->registerRoute(producer_namespace);
+ portal_->getThread().addAndWaitForExecution([this]() {
+ socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
+ &on_interest_input_);
+ socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_DROP,
+ &on_interest_dropped_input_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_PASS,
+ &on_interest_inserted_input_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CACHE_HIT,
+ &on_interest_satisfied_output_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ &on_interest_process_);
+ socket_->getSocketOption(ProducerCallbacksOptions::NEW_CONTENT_OBJECT,
+ &on_new_segment_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_READY,
+ &on_content_object_in_output_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_OUTPUT,
+ &on_content_object_output_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN,
+ &on_content_object_to_sign_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED,
+ &on_content_produced_);
+ socket_->getSocketOption(ProducerCallbacksOptions::PRODUCER_CALLBACK,
+ &producer_callback_);
+
+ socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+ socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer_);
+ socket_->getSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
+ making_manifest_);
+
+ std::string fec_type_str = "";
+ socket_->getSocketOption(GeneralTransportOptions::FEC_TYPE, fec_type_str);
+ if (fec_type_str != "") {
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_type_str.c_str());
}
- }
- is_running_ = true;
+ portal_->registerTransportCallback(this);
+ setProducerParam();
- if (!is_async_) {
- listening_thread_ = std::thread([this]() { portal_->runEventsLoop(); });
- }
+ setRunning();
+ });
return 0;
}
-void ProductionProtocol::stop() {
- is_running_ = false;
-
- if (!is_async_) {
- portal_->stopEventsLoop();
- } else {
- portal_->clear();
- }
-}
-
void ProductionProtocol::produce(ContentObject &content_object) {
- if (*on_content_object_in_output_buffer_) {
- on_content_object_in_output_buffer_->operator()(*socket_->getInterface(),
- content_object);
- }
+ auto content_object_ptr = content_object.shared_from_this();
+ portal_->getThread().add([this, co = std::move(content_object_ptr)]() {
+ if (*on_content_object_in_output_buffer_) {
+ on_content_object_in_output_buffer_->operator()(*socket_->getInterface(),
+ *co);
+ }
- output_buffer_.insert(std::static_pointer_cast<ContentObject>(
- content_object.shared_from_this()));
+ output_buffer_.insert(co);
- 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(), *co);
+ }
- portal_->sendContentObject(content_object);
+ portal_->sendContentObject(*co);
+ });
}
-void ProductionProtocol::registerNamespaceWithNetwork(
- const Prefix &producer_namespace) {
- served_namespaces_.push_back(producer_namespace);
+void ProductionProtocol::sendMapme() { portal_->sendMapme(); }
+
+void ProductionProtocol::onError(const std::error_code &ec) {
+ // Stop production protocol
+ stop();
+
+ // Call error callback
+ if (producer_callback_) {
+ producer_callback_->produceError(ec);
+ }
}
} // namespace protocol
diff --git a/libtransport/src/protocols/production_protocol.h b/libtransport/src/protocols/production_protocol.h
index 7366311eb..8e10d2f40 100644
--- a/libtransport/src/protocols/production_protocol.h
+++ b/libtransport/src/protocols/production_protocol.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,6 +22,7 @@
#include <implementation/socket.h>
#include <protocols/fec_base.h>
#include <protocols/fec_utils.h>
+#include <protocols/protocol.h>
#include <utils/content_store.h>
#include <atomic>
@@ -33,17 +34,20 @@ namespace protocol {
using namespace core;
-class ProductionProtocol : public Portal::ProducerCallback {
+class ProductionProtocol
+ : public Protocol,
+ public std::enable_shared_from_this<ProductionProtocol> {
public:
ProductionProtocol(implementation::ProducerSocket *icn_socket);
virtual ~ProductionProtocol();
- bool isRunning() { return is_running_; }
-
virtual int start();
- virtual void stop();
+ using Protocol::stop;
+
+ virtual void setProducerParam(){};
virtual void produce(ContentObject &content_object);
+ virtual void sendMapme();
virtual uint32_t produceStream(const Name &content_name,
std::unique_ptr<utils::MemBuf> &&buffer,
bool is_last = true,
@@ -61,20 +65,18 @@ class ProductionProtocol : public Portal::ProducerCallback {
void setOutputBufferSize(std::size_t size) { output_buffer_.setLimit(size); }
std::size_t getOutputBufferSize() { return output_buffer_.getLimit(); }
- virtual void registerNamespaceWithNetwork(const Prefix &producer_namespace);
- const std::list<Prefix> &getNamespaces() const { return served_namespaces_; }
-
protected:
// Producer callback
virtual void onInterest(core::Interest &i) override = 0;
- virtual void onError(std::error_code ec) override{};
+ virtual void onError(const std::error_code &ec) override;
template <typename FECHandler, typename AllocatorHandler>
void enableFEC(FECHandler &&fec_handler,
AllocatorHandler &&allocator_handler) {
if (!fec_encoder_) {
// Try to get FEC from environment
- if (const char *fec_str = std::getenv("TRANSPORT_FEC_TYPE")) {
+ const char *fec_str = std::getenv("TRANSPORT_FEC_TYPE");
+ if (fec_str && (fec_type_ == fec::FECType::UNKNOWN)) {
LOG(INFO) << "Using FEC " << fec_str;
fec_type_ = fec::FECUtils::fecTypeFromString(fec_str);
}
@@ -95,11 +97,6 @@ class ProductionProtocol : public Portal::ProducerCallback {
// Thread pool responsible for IO operations (send data / receive interests)
std::vector<utils::EventThread> io_threads_;
-
- // TODO remove this thread
- std::thread listening_thread_;
- std::shared_ptr<Portal> portal_;
- std::atomic<bool> is_running_;
interface::ProductionStatistics *stats_;
std::unique_ptr<fec::ProducerFEC> fec_encoder_;
@@ -119,15 +116,14 @@ class ProductionProtocol : public Portal::ProducerCallback {
interface::ProducerContentCallback *on_content_produced_;
+ interface::ProducerSocket::Callback *producer_callback_;
+
// Output buffer
utils::ContentStore output_buffer_;
- // List ot routes served by current producer protocol
- std::list<Prefix> served_namespaces_;
-
// Signature and manifest
std::shared_ptr<auth::Signer> signer_;
- bool making_manifest_;
+ uint32_t making_manifest_;
bool is_async_;
fec::FECType fec_type_;
diff --git a/libtransport/src/protocols/protocol.h b/libtransport/src/protocols/protocol.h
new file mode 100644
index 000000000..a9f929db9
--- /dev/null
+++ b/libtransport/src/protocols/protocol.h
@@ -0,0 +1,73 @@
+/*
+ * 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/portal.h>
+#include <hicn/transport/errors/runtime_exception.h>
+#include <hicn/transport/utils/noncopyable.h>
+
+#include <random>
+
+namespace transport {
+
+namespace protocol {
+
+class Protocol : public core::Portal::TransportCallback, utils::NonCopyable {
+ public:
+ virtual void stop() {
+ portal_->getThread().addAndWaitForExecution([this]() {
+ unSetRunning();
+ portal_->unregisterTransportCallback();
+ portal_->clear();
+ });
+ }
+
+ virtual void onInterest(core::Interest &i) {
+ throw errors::RuntimeException("Not implemented");
+ }
+
+ virtual void onContentObject(core::Interest &i, core::ContentObject &c) {
+ throw errors::RuntimeException("Not implemented");
+ }
+
+ virtual void onTimeout(core::Interest::Ptr &i, const core::Name &n) {
+ throw errors::RuntimeException("Not implemented");
+ }
+
+ virtual void onError(const std::error_code &ec) {
+ throw errors::RuntimeException("Not implemented");
+ }
+
+ bool isRunning() { return is_running_; }
+ void setRunning() { is_running_ = true; }
+ void unSetRunning() { is_running_ = false; }
+
+ protected:
+ Protocol() : portal_(nullptr), is_running_(false), gen_(rd_()) {}
+ virtual ~Protocol() {}
+
+ protected:
+ std::shared_ptr<core::Portal> portal_;
+ std::atomic_bool is_running_;
+
+ // Random engine
+ std::random_device rd_;
+ std::mt19937 gen_;
+};
+
+} // namespace protocol
+
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/raaqm.cc b/libtransport/src/protocols/raaqm.cc
index 1247af400..131367d78 100644
--- a/libtransport/src/protocols/raaqm.cc
+++ b/libtransport/src/protocols/raaqm.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -36,8 +36,9 @@ RaaqmTransportProtocol::RaaqmTransportProtocol(
current_window_size_(1),
interests_in_flight_(0),
cur_path_(nullptr),
- t0_(utils::SteadyClock::now()),
+ t0_(utils::SteadyTime::Clock::now()),
rate_estimator_(nullptr),
+ dis_(0, 1.0),
schedule_interests_(true) {
init();
}
@@ -60,7 +61,7 @@ void RaaqmTransportProtocol::reset() {
// Reset protocol variables
interests_in_flight_ = 0;
- t0_ = utils::SteadyClock::now();
+ t0_ = utils::SteadyTime::Clock::now();
// Optionally reset congestion window
bool reset_window;
@@ -389,6 +390,8 @@ void RaaqmTransportProtocol::sendInterest(
uint32_t len) {
interests_in_flight_++;
interest_retransmissions_[interest_name.getSuffix() & mask]++;
+ interest_timepoints_[interest_name.getSuffix() & mask] =
+ utils::SteadyTime::Clock::now();
TransportProtocol::sendInterest(interest_name, additional_suffixes, len);
}
@@ -477,7 +480,7 @@ void RaaqmTransportProtocol::scheduleNextInterests() {
}
}
-void RaaqmTransportProtocol::onContentReassembled(std::error_code ec) {
+void RaaqmTransportProtocol::onContentReassembled(const std::error_code &ec) {
rate_estimator_->onDownloadFinished();
TransportProtocol::onContentReassembled(ec);
schedule_interests_ = false;
@@ -487,18 +490,18 @@ void RaaqmTransportProtocol::updateRtt(uint64_t segment) {
if (TRANSPORT_EXPECT_FALSE(!cur_path_)) {
throw std::runtime_error("RAAQM ERROR: no current path found, exit");
} else {
- auto now = utils::SteadyClock::now();
- utils::Microseconds rtt = std::chrono::duration_cast<utils::Microseconds>(
- now - interest_timepoints_[segment & mask]);
+ auto now = utils::SteadyTime::Clock::now();
+ utils::SteadyTime::Milliseconds rtt = utils::SteadyTime::getDurationMs(
+ interest_timepoints_[segment & mask], now);
// Update stats
- updateStats((uint32_t)segment, rtt.count(), now);
+ updateStats((uint32_t)segment, rtt, now);
if (rate_estimator_) {
- rate_estimator_->onRttUpdate((double)rtt.count());
+ rate_estimator_->onRttUpdate(rtt);
}
- cur_path_->insertNewRtt(rtt.count(), now);
+ cur_path_->insertNewRtt(rtt, now);
cur_path_->smoothTimer();
if (cur_path_->newPropagationDelayAvailable()) {
@@ -510,27 +513,27 @@ void RaaqmTransportProtocol::updateRtt(uint64_t segment) {
void RaaqmTransportProtocol::RAAQM() {
if (!cur_path_) {
throw errors::RuntimeException("ERROR: no current path found, exit");
- exit(EXIT_FAILURE);
} else {
// Change drop probability according to RTT statistics
cur_path_->updateDropProb();
- double coin = ((double)rand() / (RAND_MAX));
+ double coin = dis_(gen_);
if (coin <= cur_path_->getDropProb()) {
decreaseWindow();
}
}
}
-void RaaqmTransportProtocol::updateStats(uint32_t suffix, uint64_t rtt,
- utils::TimePoint &now) {
+void RaaqmTransportProtocol::updateStats(
+ uint32_t suffix, const utils::SteadyTime::Milliseconds &rtt,
+ utils::SteadyTime::TimePoint &now) {
// Update RTT statistics
stats_->updateAverageRtt(rtt);
stats_->updateAverageWindowSize(current_window_size_);
// Call statistics callback
if (*stats_summary_) {
- auto dt = std::chrono::duration_cast<utils::Milliseconds>(now - t0_);
+ auto dt = utils::SteadyTime::getDurationMs(t0_, now);
uint32_t timer_interval_milliseconds = 0;
socket_->getSocketOption(GeneralTransportOptions::STATS_INTERVAL,
diff --git a/libtransport/src/protocols/raaqm.h b/libtransport/src/protocols/raaqm.h
index ffbb30d3a..ec344c23a 100644
--- a/libtransport/src/protocols/raaqm.h
+++ b/libtransport/src/protocols/raaqm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,6 +23,7 @@
#include <protocols/transport_protocol.h>
#include <queue>
+#include <random>
#include <vector>
namespace transport {
@@ -55,8 +56,9 @@ class RaaqmTransportProtocol : public TransportProtocol,
const ContentObject &content_object);
virtual void afterDataUnsatisfied(uint64_t segment);
- virtual void updateStats(uint32_t suffix, uint64_t rtt,
- utils::TimePoint &now);
+ virtual void updateStats(uint32_t suffix,
+ const utils::SteadyTime::Milliseconds &rtt,
+ utils::SteadyTime::TimePoint &now);
private:
void init();
@@ -73,7 +75,7 @@ class RaaqmTransportProtocol : public TransportProtocol,
*additional_suffixes = nullptr,
uint32_t len = 0) override;
- void onContentReassembled(std::error_code ec) override;
+ void onContentReassembled(const std::error_code &ec) override;
void updateRtt(uint64_t segment);
void RAAQM();
void updatePathTable(const ContentObject &content_object);
@@ -81,13 +83,15 @@ class RaaqmTransportProtocol : public TransportProtocol,
void checkForStalePaths();
void printRtt();
+ auto shared_from_this() { return utils::shared_from(this); }
+
protected:
// Congestion window management
double current_window_size_;
// Protocol management
uint64_t interests_in_flight_;
std::array<std::uint32_t, buffer_size> interest_retransmissions_;
- std::array<utils::TimePoint, buffer_size> interest_timepoints_;
+ std::array<utils::SteadyTime::TimePoint, buffer_size> interest_timepoints_;
std::queue<uint32_t> interest_to_retransmit_;
private:
@@ -102,13 +106,16 @@ class RaaqmTransportProtocol : public TransportProtocol,
PathTable path_table_;
// TimePoints for statistic
- utils::TimePoint t0_;
+ utils::SteadyTime::TimePoint t0_;
bool set_interest_filter_;
// for rate-estimation at packet level
IcnRateEstimator *rate_estimator_;
+ // Real distribution
+ std::uniform_real_distribution<> dis_;
+
// params for autotuning
bool raaqm_autotune_;
double default_beta_;
diff --git a/libtransport/src/protocols/raaqm_data_path.cc b/libtransport/src/protocols/raaqm_data_path.cc
index f2c21b9ef..d06fee918 100644
--- a/libtransport/src/protocols/raaqm_data_path.cc
+++ b/libtransport/src/protocols/raaqm_data_path.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -23,16 +23,18 @@ namespace protocol {
RaaqmDataPath::RaaqmDataPath(double drop_factor,
double minimum_drop_probability,
unsigned new_timer, unsigned int samples,
- uint64_t new_rtt, uint64_t new_rtt_min,
- uint64_t new_rtt_max, unsigned new_pd)
+ const utils::SteadyTime::Milliseconds &new_rtt,
+ const utils::SteadyTime::Milliseconds &new_rtt_min,
+ const utils::SteadyTime::Milliseconds &new_rtt_max,
+ unsigned new_pd)
: drop_factor_(drop_factor),
minimum_drop_probability_(minimum_drop_probability),
timer_(new_timer),
samples_(samples),
- rtt_(new_rtt),
- rtt_min_(new_rtt_min),
- rtt_max_(new_rtt_max),
+ rtt_(new_rtt.count()),
+ rtt_min_(new_rtt_min.count()),
+ rtt_max_(new_rtt_max.count()),
prop_delay_(new_pd),
new_prop_delay_(false),
drop_prob_(0),
@@ -43,14 +45,15 @@ RaaqmDataPath::RaaqmDataPath(double drop_factor,
raw_data_bytes_received_(0),
last_raw_data_bytes_received_(0),
rtt_samples_(samples_),
- last_received_pkt_(utils::SteadyClock::now()),
+ last_received_pkt_(utils::SteadyTime::Clock::now()),
average_rtt_(0),
alpha_(ALPHA) {}
-RaaqmDataPath &RaaqmDataPath::insertNewRtt(uint64_t new_rtt,
- const utils::TimePoint &now) {
- rtt_ = new_rtt;
- rtt_samples_.pushBack(new_rtt);
+RaaqmDataPath &RaaqmDataPath::insertNewRtt(
+ const utils::SteadyTime::Milliseconds &new_rtt,
+ const utils::SteadyTime::TimePoint &now) {
+ rtt_ = new_rtt.count();
+ rtt_samples_.pushBack(rtt_);
rtt_max_ = rtt_samples_.rBegin();
rtt_min_ = rtt_samples_.begin();
@@ -143,10 +146,8 @@ unsigned int RaaqmDataPath::getPropagationDelay() {
}
bool RaaqmDataPath::isStale() {
- utils::TimePoint now = utils::SteadyClock::now();
- auto time =
- std::chrono::duration_cast<utils::Microseconds>(now - last_received_pkt_)
- .count();
+ utils::SteadyTime::TimePoint now = utils::SteadyTime::Clock::now();
+ auto time = utils::SteadyTime::getDurationUs(last_received_pkt_, now).count();
if (time > 2000000) {
return true;
}
diff --git a/libtransport/src/protocols/raaqm_data_path.h b/libtransport/src/protocols/raaqm_data_path.h
index c0b53a690..b6f7c5ac1 100644
--- a/libtransport/src/protocols/raaqm_data_path.h
+++ b/libtransport/src/protocols/raaqm_data_path.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -34,8 +34,13 @@ class RaaqmDataPath {
public:
RaaqmDataPath(double drop_factor, double minimum_drop_probability,
unsigned new_timer, unsigned int samples,
- uint64_t new_rtt = 1000, uint64_t new_rtt_min = 1000,
- uint64_t new_rtt_max = 1000, unsigned new_pd = UINT_MAX);
+ const utils::SteadyTime::Milliseconds &new_rtt =
+ utils::SteadyTime::Milliseconds(1000),
+ const utils::SteadyTime::Milliseconds &new_rtt_min =
+ utils::SteadyTime::Milliseconds(1000),
+ const utils::SteadyTime::Milliseconds &new_rtt_max =
+ utils::SteadyTime::Milliseconds(1000),
+ unsigned new_pd = UINT_MAX);
public:
/*
@@ -44,7 +49,8 @@ class RaaqmDataPath {
* max of RTT.
* @param new_rtt is the value of the new RTT
*/
- RaaqmDataPath &insertNewRtt(uint64_t new_rtt, const utils::TimePoint &now);
+ RaaqmDataPath &insertNewRtt(const utils::SteadyTime::Milliseconds &new_rtt,
+ const utils::SteadyTime::TimePoint &now);
/**
* @brief Update the path statistics
@@ -214,7 +220,7 @@ class RaaqmDataPath {
/**
* Time of the last call to the path reporter method
*/
- utils::TimePoint last_received_pkt_;
+ utils::SteadyTime::TimePoint last_received_pkt_;
double average_rtt_;
double alpha_;
diff --git a/libtransport/src/protocols/rate_estimation.cc b/libtransport/src/protocols/rate_estimation.cc
index 2337e18be..d834b53e6 100644
--- a/libtransport/src/protocols/rate_estimation.cc
+++ b/libtransport/src/protocols/rate_estimation.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -14,6 +14,7 @@
*/
#include <glog/logging.h>
+#include <hicn/transport/errors/runtime_exception.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <protocols/rate_estimation.h>
@@ -92,8 +93,8 @@ InterRttEstimator::InterRttEstimator(double alpha_arg) {
this->win_current_ = 1.0;
pthread_mutex_init(&(this->mutex_), NULL);
- this->start_time_ = std::chrono::steady_clock::now();
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->start_time_ = utils::SteadyTime::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
InterRttEstimator::~InterRttEstimator() {
@@ -105,33 +106,35 @@ InterRttEstimator::~InterRttEstimator() {
pthread_mutex_destroy(&(this->mutex_));
}
-void InterRttEstimator::onRttUpdate(double rtt) {
+void InterRttEstimator::onRttUpdate(
+ const utils::SteadyTime::Milliseconds &rtt) {
pthread_mutex_lock(&(this->mutex_));
- this->rtt_ = rtt;
+ this->rtt_ = rtt.count();
this->number_of_packets_++;
- this->avg_rtt_ += rtt;
+ this->avg_rtt_ += this->rtt_;
pthread_mutex_unlock(&(this->mutex_));
if (!thread_is_running_) {
my_th_ = (pthread_t *)malloc(sizeof(pthread_t));
if (!my_th_) {
- LOG(ERROR) << "Error allocating thread.";
- my_th_ = NULL;
+ throw errors::RuntimeException("Error allocating thread.");
}
- if (/*int err = */ pthread_create(my_th_, NULL, transport::protocol::Timer,
- (void *)this)) {
- LOG(ERROR) << "Error creating the thread";
+
+ if (pthread_create(my_th_, NULL, transport::protocol::Timer,
+ (void *)this)) {
+ free(my_th_);
my_th_ = NULL;
+ throw errors::RuntimeException("Error allocating thread.");
}
+
thread_is_running_ = true;
}
}
void InterRttEstimator::onWindowIncrease(double win_current) {
- TimePoint end = std::chrono::steady_clock::now();
+ auto end = utils::SteadyTime::now();
auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->begin_batch_)
- .count();
+ utils::SteadyTime::getDurationUs(this->begin_batch_, end).count();
pthread_mutex_lock(&(this->mutex_));
this->avg_win_ += this->win_current_ * delay;
@@ -139,14 +142,13 @@ void InterRttEstimator::onWindowIncrease(double win_current) {
this->win_change_ += delay;
pthread_mutex_unlock(&(this->mutex_));
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
void InterRttEstimator::onWindowDecrease(double win_current) {
- TimePoint end = std::chrono::steady_clock::now();
+ auto end = utils::SteadyTime::now();
auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->begin_batch_)
- .count();
+ utils::SteadyTime::getDurationUs(this->begin_batch_, end).count();
pthread_mutex_lock(&(this->mutex_));
this->avg_win_ += this->win_current_ * delay;
@@ -154,25 +156,24 @@ void InterRttEstimator::onWindowDecrease(double win_current) {
this->win_change_ += delay;
pthread_mutex_unlock(&(this->mutex_));
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
ALaTcpEstimator::ALaTcpEstimator() {
this->estimation_ = 0.0;
this->observer_ = NULL;
- this->start_time_ = std::chrono::steady_clock::now();
+ this->start_time_ = utils::SteadyTime::now();
this->totalSize_ = 0.0;
}
void ALaTcpEstimator::onStart() {
this->totalSize_ = 0.0;
- this->start_time_ = std::chrono::steady_clock::now();
+ this->start_time_ = utils::SteadyTime::now();
}
void ALaTcpEstimator::onDownloadFinished() {
- TimePoint end = std::chrono::steady_clock::now();
- auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->start_time_).count();
+ auto end = utils::SteadyTime::now();
+ auto delay = utils::SteadyTime::getDurationUs(this->start_time_, end).count();
this->estimation_ = this->totalSize_ * 8 * 1000000 / delay;
if (observer_) {
observer_->notifyStats(this->estimation_);
@@ -192,22 +193,21 @@ SimpleEstimator::SimpleEstimator(double alphaArg, int batching_param) {
this->number_of_packets_ = 0;
this->base_alpha_ = alphaArg;
this->alpha_ = alphaArg;
- this->start_time_ = std::chrono::steady_clock::now();
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->start_time_ = utils::SteadyTime::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
void SimpleEstimator::onStart() {
this->estimated_ = false;
this->number_of_packets_ = 0;
this->total_size_ = 0.0;
- this->start_time_ = std::chrono::steady_clock::now();
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->start_time_ = utils::SteadyTime::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
void SimpleEstimator::onDownloadFinished() {
- TimePoint end = std::chrono::steady_clock::now();
- auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->start_time_).count();
+ auto end = utils::SteadyTime::now();
+ auto delay = utils::SteadyTime::getDurationUs(this->start_time_, end).count();
if (observer_) {
observer_->notifyDownloadTime((double)delay);
}
@@ -229,8 +229,7 @@ void SimpleEstimator::onDownloadFinished() {
} else {
if (this->number_of_packets_ >=
(int)(75.0 * (double)this->batching_param_ / 100.0)) {
- delay = std::chrono::duration_cast<Microseconds>(end - this->begin_batch_)
- .count();
+ delay = utils::SteadyTime::getDurationUs(this->begin_batch_, end).count();
// Assuming all packets carry max_packet_size_ bytes of data
// (8*max_packet_size_ bits); 1000000 factor to convert us to seconds
if (this->estimation_) {
@@ -249,22 +248,21 @@ void SimpleEstimator::onDownloadFinished() {
}
this->number_of_packets_ = 0;
this->total_size_ = 0.0;
- this->start_time_ = std::chrono::steady_clock::now();
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->start_time_ = utils::SteadyTime::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
void SimpleEstimator::onDataReceived(int packet_size) {
this->total_size_ += packet_size;
}
-void SimpleEstimator::onRttUpdate(double rtt) {
+void SimpleEstimator::onRttUpdate(const utils::SteadyTime::Milliseconds &rtt) {
this->number_of_packets_++;
if (this->number_of_packets_ == this->batching_param_) {
- TimePoint end = std::chrono::steady_clock::now();
+ auto end = utils::SteadyTime::now();
auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->begin_batch_)
- .count();
+ utils::SteadyTime::getDurationUs(this->begin_batch_, end).count();
// Assuming all packets carry max_packet_size_ bytes of data
// (8*max_packet_size_ bits); 1000000 factor to convert us to seconds
if (this->estimation_) {
@@ -280,7 +278,7 @@ void SimpleEstimator::onRttUpdate(double rtt) {
this->alpha_ = this->base_alpha_;
this->number_of_packets_ = 0;
this->total_size_ = 0.0;
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
}
@@ -297,13 +295,14 @@ BatchingPacketsEstimator::BatchingPacketsEstimator(double alpha_arg,
this->max_packet_size_ = 0;
this->estimation_ = 0.0;
this->win_current_ = 1.0;
- this->begin_batch_ = std::chrono::steady_clock::now();
- this->start_time_ = std::chrono::steady_clock::now();
+ this->begin_batch_ = utils::SteadyTime::now();
+ this->start_time_ = utils::SteadyTime::now();
}
-void BatchingPacketsEstimator::onRttUpdate(double rtt) {
+void BatchingPacketsEstimator::onRttUpdate(
+ const utils::SteadyTime::Milliseconds &rtt) {
this->number_of_packets_++;
- this->avg_rtt_ += rtt;
+ this->avg_rtt_ += rtt.count();
if (number_of_packets_ == this->batching_param_) {
if (estimation_ == 0) {
@@ -329,25 +328,23 @@ void BatchingPacketsEstimator::onRttUpdate(double rtt) {
}
void BatchingPacketsEstimator::onWindowIncrease(double win_current) {
- TimePoint end = std::chrono::steady_clock::now();
+ auto end = utils::SteadyTime::now();
auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->begin_batch_)
- .count();
+ utils::SteadyTime::getDurationUs(this->begin_batch_, end).count();
this->avg_win_ += this->win_current_ * delay;
this->win_current_ = win_current;
this->win_change_ += delay;
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
void BatchingPacketsEstimator::onWindowDecrease(double win_current) {
- TimePoint end = std::chrono::steady_clock::now();
+ auto end = utils::SteadyTime::now();
auto delay =
- std::chrono::duration_cast<Microseconds>(end - this->begin_batch_)
- .count();
+ utils::SteadyTime::getDurationUs(this->begin_batch_, end).count();
this->avg_win_ += this->win_current_ * delay;
this->win_current_ = win_current;
this->win_change_ += delay;
- this->begin_batch_ = std::chrono::steady_clock::now();
+ this->begin_batch_ = utils::SteadyTime::now();
}
} // end namespace protocol
diff --git a/libtransport/src/protocols/rate_estimation.h b/libtransport/src/protocols/rate_estimation.h
index 42ae74194..b71de12e4 100644
--- a/libtransport/src/protocols/rate_estimation.h
+++ b/libtransport/src/protocols/rate_estimation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/interfaces/statistics.h>
+#include <hicn/transport/utils/noncopyable.h>
#include <protocols/raaqm_data_path.h>
#include <chrono>
@@ -24,16 +25,13 @@ namespace transport {
namespace protocol {
-class IcnRateEstimator {
+class IcnRateEstimator : utils::NonCopyable {
public:
- using TimePoint = std::chrono::steady_clock::time_point;
- using Microseconds = std::chrono::microseconds;
-
IcnRateEstimator(){};
virtual ~IcnRateEstimator(){};
- virtual void onRttUpdate(double rtt){};
+ virtual void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt){};
virtual void onDataReceived(int packetSize){};
@@ -48,9 +46,10 @@ class IcnRateEstimator {
virtual void setObserver(interface::IcnObserver *observer) {
this->observer_ = observer;
};
+
interface::IcnObserver *observer_;
- TimePoint start_time_;
- TimePoint begin_batch_;
+ utils::SteadyTime::TimePoint start_time_;
+ utils::SteadyTime::TimePoint begin_batch_;
double base_alpha_;
double alpha_;
double estimation_;
@@ -67,7 +66,7 @@ class InterRttEstimator : public IcnRateEstimator {
~InterRttEstimator();
- void onRttUpdate(double rtt);
+ void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt);
void onDataReceived(int packet_size) {
if (packet_size > this->max_packet_size_) {
@@ -102,7 +101,7 @@ class BatchingPacketsEstimator : public IcnRateEstimator {
public:
BatchingPacketsEstimator(double alpha_arg, int batchingParam);
- void onRttUpdate(double rtt);
+ void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt);
void onDataReceived(int packet_size) {
if (packet_size > this->max_packet_size_) {
@@ -149,7 +148,7 @@ class SimpleEstimator : public IcnRateEstimator {
public:
SimpleEstimator(double alpha, int batching_param);
- void onRttUpdate(double rtt);
+ void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt);
void onDataReceived(int packet_size);
diff --git a/libtransport/src/protocols/reassembly.cc b/libtransport/src/protocols/reassembly.cc
index ce24fce1b..065458f7e 100644
--- a/libtransport/src/protocols/reassembly.cc
+++ b/libtransport/src/protocols/reassembly.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/protocols/reassembly.h b/libtransport/src/protocols/reassembly.h
index e072ad123..b0879201d 100644
--- a/libtransport/src/protocols/reassembly.h
+++ b/libtransport/src/protocols/reassembly.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -36,7 +36,7 @@ class Reassembly {
public:
class ContentReassembledCallback {
public:
- virtual void onContentReassembled(std::error_code ec) = 0;
+ virtual void onContentReassembled(const std::error_code &ec) = 0;
};
Reassembly(implementation::ConsumerSocket *icn_socket,
@@ -47,12 +47,12 @@ class Reassembly {
virtual ~Reassembly() = default;
/**
- * Hanle reassembly of content object.
+ * Handle reassembly of content object.
*/
virtual void reassemble(core::ContentObject &content_object) = 0;
/**
- * Hanle reassembly of content object.
+ * Handle reassembly of content object.
*/
virtual void reassemble(utils::MemBuf &buffer, uint32_t suffix) = 0;
diff --git a/libtransport/src/protocols/rtc/CMakeLists.txt b/libtransport/src/protocols/rtc/CMakeLists.txt
index 873b345d0..be8e0189c 100644
--- a/libtransport/src/protocols/rtc/CMakeLists.txt
+++ b/libtransport/src/protocols/rtc/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -16,22 +16,43 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rtc.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_consts.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_forwarding_strategy.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_indexer.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_packet.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_congestion_detection.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_iat.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_queue.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_reassembly.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_recovery_strategy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_delay.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_fec_only.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_low_rate.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_recovery_off.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_rtx_only.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_verifier.h
)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_forwarding_strategy.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_congestion_detection.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_iat.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_queue.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_reassembly.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_recovery_strategy.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_delay.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_fec_only.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_low_rate.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_recovery_off.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rs_rtx_only.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_verifier.cc
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/protocols/rtc/probe_handler.cc b/libtransport/src/protocols/rtc/probe_handler.cc
index abaca6ad9..abb234757 100644
--- a/libtransport/src/protocols/rtc/probe_handler.cc
+++ b/libtransport/src/protocols/rtc/probe_handler.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <protocols/rtc/probe_handler.h>
#include <protocols/rtc/rtc_consts.h>
@@ -27,6 +28,7 @@ ProbeHandler::ProbeHandler(SendProbeCallback &&send_callback,
: probe_interval_(0),
max_probes_(0),
sent_probes_(0),
+ recv_probes_(0),
probe_timer_(std::make_unique<asio::steady_timer>(io_service)),
rand_eng_((std::random_device())()),
distr_(MIN_RTT_PROBE_SEQ, MAX_RTT_PROBE_SEQ),
@@ -39,17 +41,25 @@ uint64_t ProbeHandler::getRtt(uint32_t seq) {
if (it == pending_probes_.end()) return 0;
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint64_t rtt = now - it->second;
if (rtt < 1) rtt = 1;
pending_probes_.erase(it);
+ recv_probes_++;
return rtt;
}
+double ProbeHandler::getProbeLossRate() {
+ return 1.0 - ((double)recv_probes_ / (double)sent_probes_);
+}
+
+void ProbeHandler::setSuffixRange(uint32_t min, uint32_t max) {
+ assert(min <= max && min >= MIN_PROBE_SEQ);
+ distr_ = std::uniform_int_distribution<uint32_t>(min, max);
+}
+
void ProbeHandler::setProbes(uint32_t probe_interval, uint32_t max_probes) {
stopProbes();
probe_interval_ = probe_interval;
@@ -60,6 +70,7 @@ void ProbeHandler::stopProbes() {
probe_interval_ = 0;
max_probes_ = 0;
sent_probes_ = 0;
+ recv_probes_ = 0;
probe_timer_->cancel();
}
@@ -67,9 +78,7 @@ void ProbeHandler::sendProbes() {
if (probe_interval_ == 0) return;
if (max_probes_ != 0 && sent_probes_ >= max_probes_) return;
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint32_t seq = distr_(rand_eng_);
pending_probes_.insert(std::pair<uint32_t, uint64_t>(seq, now));
@@ -92,14 +101,25 @@ void ProbeHandler::sendProbes() {
std::weak_ptr<ProbeHandler> self(shared_from_this());
probe_timer_->expires_from_now(std::chrono::microseconds(probe_interval_));
- probe_timer_->async_wait([self](std::error_code ec) {
+ probe_timer_->async_wait([self](const std::error_code &ec) {
if (ec) return;
- if (auto s = self.lock()) {
+ auto s = self.lock();
+ if (s) {
s->sendProbes();
}
});
}
+ProbeType ProbeHandler::getProbeType(uint32_t seq) {
+ if (MIN_INIT_PROBE_SEQ <= seq && seq <= MAX_INIT_PROBE_SEQ) {
+ return ProbeType::INIT;
+ }
+ if (MIN_RTT_PROBE_SEQ <= seq && seq <= MAX_RTT_PROBE_SEQ) {
+ return ProbeType::RTT;
+ }
+ return ProbeType::NOT_PROBE;
+}
+
} // namespace rtc
} // namespace protocol
diff --git a/libtransport/src/protocols/rtc/probe_handler.h b/libtransport/src/protocols/rtc/probe_handler.h
index e34b23df0..2de908176 100644
--- a/libtransport/src/protocols/rtc/probe_handler.h
+++ b/libtransport/src/protocols/rtc/probe_handler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -26,6 +26,12 @@ namespace protocol {
namespace rtc {
+enum class ProbeType {
+ NOT_PROBE,
+ INIT,
+ RTT,
+};
+
class ProbeHandler : public std::enable_shared_from_this<ProbeHandler> {
public:
using SendProbeCallback = std::function<void(uint32_t)>;
@@ -35,31 +41,39 @@ class ProbeHandler : public std::enable_shared_from_this<ProbeHandler> {
~ProbeHandler();
- // if the function returns 0 the probe is not valaid
+ // If the function returns 0 the probe is not valid.
uint64_t getRtt(uint32_t seq);
- // reset the probes parameters. it stop the current probing.
- // to restar call sendProbes.
- // probe_interval = 0 means that no event will be scheduled
- // max_probe = 0 means no limit to the number of probe to send
+ // this function may return a residual loss rate higher than the real one if
+ // we don't wait enough time for the probes to come back
+ double getProbeLossRate();
+
+ // Set the probe suffix range [min, max]
+ void setSuffixRange(uint32_t min, uint32_t max);
+
+ // Reset the probes parameters and stops the current probing.
+ // probe_interval = 0 means that no event will be scheduled.
+ // max_probe = 0 means no limit to the number of probe to send.
void setProbes(uint32_t probe_interval, uint32_t max_probes);
- // stop to schedule probes
void stopProbes();
void sendProbes();
+ static ProbeType getProbeType(uint32_t seq);
+
private:
uint32_t probe_interval_; // us
uint32_t max_probes_; // packets
uint32_t sent_probes_; // packets
+ uint32_t recv_probes_; // packets
std::unique_ptr<asio::steady_timer> probe_timer_;
- // map from seqnumber to timestamp
+ // Map from packet suffixes to timestamp
std::unordered_map<uint32_t, uint64_t> pending_probes_;
- // random generator
+ // Random generator
std::default_random_engine rand_eng_;
std::uniform_int_distribution<uint32_t> distr_;
diff --git a/libtransport/src/protocols/rtc/rtc.cc b/libtransport/src/protocols/rtc/rtc.cc
index 0cb4cda1d..df6522471 100644
--- a/libtransport/src/protocols/rtc/rtc.cc
+++ b/libtransport/src/protocols/rtc/rtc.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,7 +22,7 @@
#include <protocols/rtc/rtc.h>
#include <protocols/rtc/rtc_consts.h>
#include <protocols/rtc/rtc_indexer.h>
-#include <protocols/rtc/rtc_rc_queue.h>
+#include <protocols/rtc/rtc_rc_congestion_detection.h>
#include <algorithm>
@@ -37,13 +37,15 @@ using namespace interface;
RTCTransportProtocol::RTCTransportProtocol(
implementation::ConsumerSocket *icn_socket)
: TransportProtocol(icn_socket, new RtcIndexer<>(icn_socket, this),
- new DatagramReassembly(icn_socket, this)),
+ new RtcReassembly(icn_socket, this)),
number_(0) {
icn_socket->getSocketOption(PORTAL, portal_);
- round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
+ round_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
scheduler_timer_ =
- std::make_unique<asio::steady_timer>(portal_->getIoService());
- pacing_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
+ pacing_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
}
RTCTransportProtocol::~RTCTransportProtocol() {}
@@ -61,25 +63,52 @@ std::size_t RTCTransportProtocol::transportHeaderLength() {
// private
void RTCTransportProtocol::initParams() {
TransportProtocol::reset();
+ fwd_strategy_.setCallback(on_fwd_strategy_);
- rc_ = std::make_shared<RTCRateControlQueue>();
+ std::weak_ptr<RTCTransportProtocol> self = shared_from_this();
+
+ std::shared_ptr<auth::Verifier> verifier;
+ socket_->getSocketOption(GeneralTransportOptions::VERIFIER, verifier);
+
+ uint32_t max_unverified_delay;
+ socket_->getSocketOption(GeneralTransportOptions::MAX_UNVERIFIED_TIME,
+ max_unverified_delay);
+
+ rc_ = std::make_shared<RTCRateControlCongestionDetection>();
ldr_ = std::make_shared<RTCLossDetectionAndRecovery>(
- indexer_verifier_.get(),
- std::bind(&RTCTransportProtocol::sendRtxInterest, this,
- std::placeholders::_1),
- portal_->getIoService());
+ indexer_verifier_.get(), portal_->getThread().getIoService(),
+ interface::RtcTransportRecoveryStrategies::RTX_ONLY,
+ [self](uint32_t seq) {
+ auto ptr = self.lock();
+ if (ptr && ptr->isRunning()) {
+ ptr->sendRtxInterest(seq);
+ }
+ },
+ on_rec_strategy_);
+ verifier_ = std::make_shared<RTCVerifier>(verifier, max_unverified_delay);
state_ = std::make_shared<RTCState>(
indexer_verifier_.get(),
- std::bind(&RTCTransportProtocol::sendProbeInterest, this,
- std::placeholders::_1),
- std::bind(&RTCTransportProtocol::discoveredRtt, this),
- portal_->getIoService());
+ [self](uint32_t seq) {
+ auto ptr = self.lock();
+ if (ptr && ptr->isRunning()) {
+ ptr->sendProbeInterest(seq);
+ }
+ },
+ [self]() {
+ auto ptr = self.lock();
+ if (ptr && ptr->isRunning()) {
+ ptr->discoveredRtt();
+ }
+ },
+ portal_->getThread().getIoService());
+ state_->initParams();
rc_->setState(state_);
- // TODO: for the moment we keep the congestion control disabled
- // rc_->tunrOnRateControl();
- ldr_->setState(state_);
+ rc_->turnOnRateControl();
+ ldr_->setState(state_.get());
+ ldr_->setRateControl(rc_.get());
+ verifier_->setState(state_);
// protocol state
start_send_interest_ = false;
@@ -102,6 +131,10 @@ void RTCTransportProtocol::initParams() {
}
#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));
+ }
#endif
max_sent_int_ =
@@ -131,6 +164,7 @@ void RTCTransportProtocol::initParams() {
indexer_verifier_->setNFec(0);
ldr_->setFecParams(fec::FECUtils::getBlockSymbols(fec_type_),
fec::FECUtils::getSourceSymbols(fec_type_));
+ fec_decoder_->setIOService(portal_->getThread().getIoService());
} else {
indexer_verifier_->disableFec();
}
@@ -162,61 +196,97 @@ void RTCTransportProtocol::inactiveProducer() {
void RTCTransportProtocol::newRound() {
round_timer_->expires_from_now(std::chrono::milliseconds(ROUND_LEN));
- // TODO pass weak_ptr here
- round_timer_->async_wait([this, n{number_}](std::error_code ec) {
- if (ec) return;
- if (n != number_) {
+ std::weak_ptr<RTCTransportProtocol> self = shared_from_this();
+ round_timer_->async_wait([self](const std::error_code &ec) {
+ if (ec) {
return;
}
+ auto ptr = self.lock();
+
+ if (!ptr || !ptr->isRunning()) {
+ return;
+ }
+
+ auto &state = ptr->state_;
+
// saving counters that will be reset on new round
- uint32_t sent_retx = state_->getSentRtxInRound();
- uint32_t received_bytes = state_->getReceivedBytesInRound();
- uint32_t sent_interest = state_->getSentInterestInRound();
- uint32_t lost_data = state_->getLostData();
- uint32_t definitely_lost = state_->getDefinitelyLostPackets();
- uint32_t recovered_losses = state_->getRecoveredLosses();
- uint32_t received_nacks = state_->getReceivedNacksInRound();
- uint32_t received_fec = state_->getReceivedFecPackets();
-
- bool in_sync = (current_state_ == SyncState::in_sync);
- ldr_->onNewRound(in_sync);
- state_->onNewRound((double)ROUND_LEN, in_sync);
- rc_->onNewRound((double)ROUND_LEN);
+ uint32_t sent_retx = state->getSentRtxInRound();
+ uint32_t received_bytes =
+ (state->getReceivedBytesInRound() + // data packets received
+ state->getReceivedFecBytesInRound()); // fec packets received
+ uint32_t sent_interest = state->getSentInterestInRound();
+ uint32_t lost_data = state->getLostData();
+ uint32_t definitely_lost = state->getDefinitelyLostPackets();
+ uint32_t recovered_losses = state->getRecoveredLosses();
+ uint32_t received_nacks = state->getReceivedNacksInRound();
+ uint32_t received_fec = state->getReceivedFecPackets();
+
+ bool in_sync = (ptr->current_state_ == SyncState::in_sync);
+ ptr->ldr_->onNewRound(in_sync);
+ ptr->state_->onNewRound((double)ROUND_LEN, in_sync);
+ ptr->rc_->onNewRound((double)ROUND_LEN);
// update sync state if needed
- if (current_state_ == SyncState::in_sync) {
- double cache_rate = state_->getPacketFromCacheRatio();
+ if (ptr->current_state_ == SyncState::in_sync) {
+ double cache_rate = state->getPacketFromCacheRatio();
if (cache_rate > MAX_DATA_FROM_CACHE) {
- current_state_ = SyncState::catch_up;
+ ptr->current_state_ = SyncState::catch_up;
}
} else {
- double target_rate = state_->getProducerRate() * PRODUCTION_RATE_FRACTION;
- double received_rate = state_->getReceivedRate();
- uint32_t round_without_nacks = state_->getRoundsWithoutNacks();
- double cache_ratio = state_->getPacketFromCacheRatio();
+ double target_rate = state->getProducerRate() * PRODUCTION_RATE_FRACTION;
+ double received_rate =
+ state->getReceivedRate() + state->getRecoveredFecRate();
+ uint32_t round_without_nacks = state->getRoundsWithoutNacks();
+ double cache_ratio = state->getPacketFromCacheRatio();
if (round_without_nacks >= ROUNDS_IN_SYNC_BEFORE_SWITCH &&
received_rate >= target_rate && cache_ratio < MAX_DATA_FROM_CACHE) {
- current_state_ = SyncState::in_sync;
+ ptr->current_state_ = SyncState::in_sync;
}
}
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Calling updateSyncWindow in newRound function";
- updateSyncWindow();
+ ptr->updateSyncWindow();
- sendStatsToApp(sent_retx, received_bytes, sent_interest, lost_data,
- definitely_lost, recovered_losses, received_nacks,
- received_fec);
- newRound();
+ ptr->sendStatsToApp(sent_retx, received_bytes, sent_interest, lost_data,
+ definitely_lost, recovered_losses, received_nacks,
+ received_fec);
+ ptr->fwd_strategy_.checkStrategy();
+ ptr->newRound();
});
}
void RTCTransportProtocol::discoveredRtt() {
start_send_interest_ = true;
- ldr_->turnOnRTX();
+ uint32_t strategy;
+ socket_->getSocketOption(RtcTransportOptions::RECOVERY_STRATEGY, strategy);
+ ldr_->changeRecoveryStrategy(
+ (interface::RtcTransportRecoveryStrategies)strategy);
+ ldr_->turnOnRecovery();
ldr_->onNewRound(false);
+
+ // set forwarding strategy switch if selected
+ 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);
+ }
+
updateSyncWindow();
}
@@ -244,7 +314,7 @@ void RTCTransportProtocol::computeMaxSyncWindow() {
(production_rate * lifetime_ms * INTEREST_LIFETIME_REDUCTION_FACTOR) /
packet_size);
- max_sync_win_ = std::min(max_sync_win_, rc_->getCongesionWindow());
+ max_sync_win_ = std::min(max_sync_win_, rc_->getCongestionWindow());
}
void RTCTransportProtocol::updateSyncWindow() {
@@ -259,25 +329,14 @@ void RTCTransportProtocol::updateSyncWindow() {
}
double prod_rate = state_->getProducerRate();
- double rtt = (double)state_->getRTT() / MILLI_IN_A_SEC;
+ double rtt = (double)state_->getMinRTT() / MILLI_IN_A_SEC;
double packet_size = state_->getAveragePacketSize();
// if some of the info are not available do not update the current win
if (prod_rate != 0.0 && rtt != 0.0 && packet_size != 0.0) {
- double fec_interest_overhead = (double)state_->getPendingFecPackets() /
- (double)(state_->getPendingInterestNumber() -
- state_->getPendingFecPackets());
-
- double fec_overhead =
- std::max(indexer_verifier_->getFecOverhead(), fec_interest_overhead);
-
- prod_rate += (prod_rate * fec_overhead);
-
current_sync_win_ = (uint32_t)ceil(prod_rate * rtt / packet_size);
uint32_t buffer = PRODUCER_BUFFER_MS;
- if (rtt > 150)
- buffer = buffer * 2; // if the RTT is too large we increase the
- // the size of the buffer
+
current_sync_win_ +=
ceil(prod_rate * (buffer / MILLI_IN_A_SEC) / packet_size);
@@ -285,8 +344,17 @@ void RTCTransportProtocol::updateSyncWindow() {
current_sync_win_ = current_sync_win_ * CATCH_UP_WIN_INCREMENT;
}
+ uint32_t min_win = WIN_MIN;
+ bool aggregated_data_on;
+ socket_->getSocketOption(RtcTransportOptions::AGGREGATED_DATA,
+ aggregated_data_on);
+ if (aggregated_data_on) {
+ min_win = WIN_MIN_WITH_AGGREGARED_DATA;
+ min_win += (min_win * (1 - (std::max(0.3, rtt) - rtt) / 0.3));
+ }
+
current_sync_win_ = std::min(current_sync_win_, max_sync_win_);
- current_sync_win_ = std::max(current_sync_win_, WIN_MIN);
+ current_sync_win_ = std::max(current_sync_win_, min_win);
}
scheduleNextInterests();
@@ -322,7 +390,7 @@ void RTCTransportProtocol::sendProbeInterest(uint32_t seq) {
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
&interest_name);
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "send probe " << seq;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send probe " << seq;
interest_name->setSuffix(seq);
sendInterest(*interest_name);
}
@@ -330,13 +398,18 @@ void RTCTransportProtocol::sendProbeInterest(uint32_t seq) {
void RTCTransportProtocol::scheduleNextInterests() {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Schedule next interests";
- if (!isRunning() && !is_first_) return;
+ if (!isRunning() && !is_first_) {
+ return;
+ }
- if (pacing_timer_on_) return; // wait pacing timer for the next send
+ if (pacing_timer_on_) {
+ return; // wait pacing timer for the next send
+ }
- if (!start_send_interest_)
+ if (!start_send_interest_) {
return; // RTT discovering phase is not finished so
// do not start to send interests
+ }
if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Inactive producer.";
@@ -352,7 +425,7 @@ void RTCTransportProtocol::scheduleNextInterests() {
&interest_name);
uint32_t next_seg = 0;
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "send interest " << next_seg;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send interest " << next_seg;
interest_name->setSuffix(next_seg);
if (portal_->interestIsPending(*interest_name)) {
@@ -370,28 +443,37 @@ void RTCTransportProtocol::scheduleNextInterests() {
<< " -- current_sync_win_: " << current_sync_win_;
uint32_t pending = state_->getPendingInterestNumber();
- if (pending >= current_sync_win_) return; // no space in the window
+ uint32_t pending_fec = state_->getPendingFecPackets();
+
+ if ((pending - pending_fec) >= current_sync_win_)
+ return; // no space in the window
- if ((current_sync_win_ - pending) < max_aggregated_interest_) {
+ // XXX double check if aggregated interests are still working here
+ if ((current_sync_win_ - (pending - pending_fec)) <
+ max_aggregated_interest_) {
if (scheduler_timer_on_) return; // timer already scheduled
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint64_t time = now - last_interest_sent_time_;
if (time < WAIT_FOR_INTEREST_BATCH) {
uint64_t next = WAIT_FOR_INTEREST_BATCH - time;
scheduler_timer_on_ = true;
scheduler_timer_->expires_from_now(std::chrono::milliseconds(next));
- scheduler_timer_->async_wait([this](std::error_code ec) {
+
+ std::weak_ptr<RTCTransportProtocol> self = shared_from_this();
+ scheduler_timer_->async_wait([self](const std::error_code &ec) {
if (ec) return;
- if (!scheduler_timer_on_) return;
- scheduler_timer_on_ = false;
- scheduleNextInterests();
+ auto ptr = self.lock();
+ if (ptr && ptr->isRunning()) {
+ if (!ptr->scheduler_timer_on_) return;
+
+ ptr->scheduler_timer_on_ = false;
+ ptr->scheduleNextInterests();
+ }
});
- return; // whait for the timer
+ return; // wait for the timer
}
}
@@ -403,7 +485,7 @@ void RTCTransportProtocol::scheduleNextInterests() {
indexer_verifier_->jumpToIndex(state_->getLastSeqNacked() + 1);
}
- // skipe received packets
+ // skip received packets
if (indexer_verifier_->checkNextSuffix() <=
state_->getHighestSeqReceivedInOrder()) {
indexer_verifier_->jumpToIndex(state_->getHighestSeqReceivedInOrder() + 1);
@@ -417,7 +499,8 @@ void RTCTransportProtocol::scheduleNextInterests() {
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
std::array<uint32_t, MAX_AGGREGATED_INTEREST> additional_suffixes;
- while ((state_->getPendingInterestNumber() < current_sync_win_) &&
+ while (((state_->getPendingInterestNumber() -
+ state_->getPendingFecPackets()) < current_sync_win_) &&
(sent_interests < max_sent_int_)) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "In while loop. Window size: " << current_sync_win_;
@@ -428,19 +511,20 @@ void RTCTransportProtocol::scheduleNextInterests() {
// send the packet only if:
// 1) it is not pending yet (not true for rtx)
- // 2) the packet is not received or lost
+ // 2) the packet is not received or def lost
// 3) is not in the rtx list
// 4) is fec and is not in order (!= last sent + 1)
+ PacketState packet_state = state_->getPacketState(next_seg);
if (portal_->interestIsPending(*name) ||
- state_->isReceivedOrLost(next_seg) != PacketState::UNKNOWN ||
- ldr_->isRtx(next_seg) ||
+ packet_state == PacketState::RECEIVED ||
+ packet_state == PacketState::DEFINITELY_LOST || ldr_->isRtx(next_seg) ||
(indexer_verifier_->isFec(next_seg) &&
next_seg != last_interest_sent_seq_ + 1)) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "skip interest " << next_seg << " because: pending "
- << portal_->interestIsPending(*name) << ", recv "
- << (state_->isReceivedOrLost(next_seg) != PacketState::UNKNOWN)
- << ", rtx " << (ldr_->isRtx(next_seg)) << ", is old fec "
+ << portal_->interestIsPending(*name) << ", recv or lost"
+ << (int)packet_state << ", rtx " << (ldr_->isRtx(next_seg))
+ << ", is old fec "
<< ((indexer_verifier_->isFec(next_seg) &&
next_seg != last_interest_sent_seq_ + 1));
continue;
@@ -462,10 +546,7 @@ void RTCTransportProtocol::scheduleNextInterests() {
sent_packets++;
sent_interests++;
sendInterest(interest_name, &additional_suffixes, aggregated_counter - 1);
- last_interest_sent_time_ =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ last_interest_sent_time_ = utils::SteadyTime::nowMs().count();
aggregated_counter = 0;
}
}
@@ -473,25 +554,29 @@ void RTCTransportProtocol::scheduleNextInterests() {
// exiting the while we may have some pending interest to send
if (aggregated_counter != 0) {
sent_packets++;
- last_interest_sent_time_ =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ last_interest_sent_time_ = utils::SteadyTime::nowMs().count();
sendInterest(interest_name, &additional_suffixes, aggregated_counter - 1);
}
- if (state_->getPendingInterestNumber() < current_sync_win_) {
+ if ((state_->getPendingInterestNumber() - state_->getPendingFecPackets()) <
+ current_sync_win_) {
// we still have space in the window but we already sent too many packets
// wait PACING_WAIT to avoid drops in the kernel
pacing_timer_on_ = true;
pacing_timer_->expires_from_now(std::chrono::microseconds(PACING_WAIT));
- scheduler_timer_->async_wait([this](std::error_code ec) {
+
+ std::weak_ptr<RTCTransportProtocol> self = shared_from_this();
+ scheduler_timer_->async_wait([self](const std::error_code &ec) {
if (ec) return;
- if (!pacing_timer_on_) return;
- pacing_timer_on_ = false;
- scheduleNextInterests();
+ auto ptr = self.lock();
+ if (ptr && ptr->isRunning()) {
+ if (!ptr->pacing_timer_on_) return;
+
+ ptr->pacing_timer_on_ = false;
+ ptr->scheduleNextInterests();
+ }
});
}
}
@@ -500,13 +585,13 @@ void RTCTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
const Name &name) {
uint32_t segment_number = name.getSuffix();
- if (segment_number >= MIN_PROBE_SEQ) {
+ if (ProbeHandler::getProbeType(segment_number) != ProbeType::NOT_PROBE) {
// this is a timeout on a probe, do nothing
return;
}
- PacketState state = state_->isReceivedOrLost(segment_number);
- if (state != PacketState::UNKNOWN) {
+ PacketState state = state_->getPacketState(segment_number);
+ if (state == PacketState::RECEIVED || state == PacketState::DEFINITELY_LOST) {
// we may recover a packets using fec, ignore this timer
return;
}
@@ -524,13 +609,18 @@ void RTCTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "handle timeout for packet " << segment_number << " using rtx";
if (ldr_->isRtxOn()) {
- ldr_->onTimeout(segment_number);
- if (indexer_verifier_->isFec(segment_number))
+ if (indexer_verifier_->isFec(segment_number)) {
+ // if this is a fec packet we do not recover it with rtx so we consider
+ // the packet to be lost
+ ldr_->onTimeout(segment_number, true);
state_->onTimeout(segment_number, true);
- else
+ } else {
+ ldr_->onTimeout(segment_number, false);
state_->onTimeout(segment_number, false);
+ }
} else {
// in this case we wil never recover the timeout
+ ldr_->onTimeout(segment_number, true);
state_->onTimeout(segment_number, true);
}
scheduleNextInterests();
@@ -559,7 +649,7 @@ void RTCTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
void RTCTransportProtocol::onNack(const ContentObject &content_object) {
struct nack_packet_t *nack =
(struct nack_packet_t *)content_object.getPayload()->data();
- uint32_t production_seg = nack->getProductionSegement();
+ uint32_t production_seg = nack->getProductionSegment();
uint32_t nack_segment = content_object.getName().getSuffix();
bool is_rtx = ldr_->isRtx(nack_segment);
@@ -592,6 +682,8 @@ void RTCTransportProtocol::onNack(const ContentObject &content_object) {
// remove the nack is it exists
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
@@ -618,11 +710,9 @@ void RTCTransportProtocol::onProbe(const ContentObject &content_object) {
bool valid = state_->onProbePacketReceived(content_object);
if (!valid) return;
- struct nack_packet_t *probe =
- (struct nack_packet_t *)content_object.getPayload()->data();
- uint32_t production_seg = probe->getProductionSegement();
+ uint32_t production_seg = RTCState::getProbeParams(content_object).prod_seg;
- // as for the nacks set next_segment
+ // As for the nacks set next_segment
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "on probe next seg = " << indexer_verifier_->checkNextSuffix()
<< ", jump to " << production_seg;
@@ -636,12 +726,39 @@ void RTCTransportProtocol::onContentObjectReceived(
Interest &interest, ContentObject &content_object, std::error_code &ec) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Received content object of size: " << content_object.payloadSize();
- uint32_t payload_size = content_object.payloadSize();
+
uint32_t segment_number = content_object.getName().getSuffix();
+ PayloadType payload_type = content_object.getPayloadType();
+ PacketState state;
+
+ ContentObject *content_ptr = &content_object;
+ ContentObject::Ptr manifest_ptr = nullptr;
+
+ bool is_probe =
+ ProbeHandler::getProbeType(segment_number) != ProbeType::NOT_PROBE;
+ bool is_nack = !is_probe && content_object.payloadSize() == NACK_HEADER_SIZE;
+ bool is_fec = indexer_verifier_->isFec(segment_number);
+ bool is_manifest =
+ !is_probe && !is_nack && !is_fec && payload_type == PayloadType::MANIFEST;
+ bool is_data =
+ !is_probe && !is_nack && !is_fec && payload_type == PayloadType::DATA;
+ bool compute_stats = is_data || is_manifest;
ec = make_error_code(protocol_error::not_reassemblable);
- if (segment_number >= MIN_PROBE_SEQ) {
+ // A helper function to process manifests or data packets received
+ auto onDataPacketReceived = [this](ContentObject &content_object,
+ bool compute_stats) {
+ ldr_->onDataPacketReceived(content_object);
+ rc_->onDataPacketReceived(content_object, compute_stats);
+ updateSyncWindow();
+ };
+
+ // First verify the packet signature and apply the corresponding policy
+ auth::VerificationPolicy policy = verifier_->verify(content_object, is_fec);
+ indexer_verifier_->applyPolicy(interest, content_object, false, policy);
+
+ if (is_probe) {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received probe " << segment_number;
if (*on_content_object_input_) {
(*on_content_object_input_)(*socket_->getInterface(), content_object);
@@ -650,7 +767,7 @@ void RTCTransportProtocol::onContentObjectReceived(
return;
}
- if (payload_size == NACK_HEADER_SIZE) {
+ if (is_nack) {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received nack " << segment_number;
if (*on_content_object_input_) {
(*on_content_object_input_)(*socket_->getInterface(), content_object);
@@ -659,57 +776,122 @@ void RTCTransportProtocol::onContentObjectReceived(
return;
}
+ // content_ptr will point either to the input data packet or to a manifest
+ // whose FEC header has been removed
+ if (is_manifest) {
+ manifest_ptr = removeFecHeader(content_object);
+ if (manifest_ptr) {
+ content_ptr = manifest_ptr.get();
+ }
+ }
+
+ // From there, the packet is either a FEC, a manifest or a data packet.
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received content " << segment_number;
- bool compute_stats = true;
+ // Do not count timed out packets in stats
auto tn_it = timeouts_or_nacks_.find(segment_number);
if (tn_it != timeouts_or_nacks_.end()) {
compute_stats = false;
timeouts_or_nacks_.erase(tn_it);
}
- if (ldr_->isRtx(segment_number)) {
+
+ // Do not count retransmissions or losses in stats
+ if (ldr_->isRtx(segment_number) ||
+ ldr_->isPossibleLossWithNoRtx(segment_number)) {
compute_stats = false;
}
- // check if the packet was already received
- PacketState state = state_->isReceivedOrLost(segment_number);
+ // Fetch packet state
+ state = state_->getPacketState(segment_number);
- if (state != PacketState::RECEIVED) {
- // send packet to decoder
- if (fec_decoder_) {
- DLOG_IF(INFO, VLOG_IS_ON(4))
- << "send packet " << segment_number << " to FEC decoder";
- fec_decoder_->onDataPacket(
- content_object, content_object.headerSize() + rtc::DATA_HEADER_SIZE);
- }
- if (!indexer_verifier_->isFec(segment_number)) {
- // the packet may be alredy sent to the ap by the decoder, check again if
- // it is already received
- state = state_->isReceivedOrLost(segment_number);
- if (state != PacketState::RECEIVED) {
- DLOG_IF(INFO, VLOG_IS_ON(4)) << "Received content " << segment_number;
+ // Check if the packet is a retransmission
+ if (ldr_->isRtx(segment_number) && state != PacketState::RECEIVED) {
+ if (is_data || is_manifest) {
+ state_->onPacketRecoveredRtx(segment_number);
- state_->onDataPacketReceived(content_object, compute_stats);
+ if (*on_content_object_input_) {
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ }
- if (*on_content_object_input_) {
- (*on_content_object_input_)(*socket_->getInterface(), content_object);
- }
- ec = make_error_code(protocol_error::success);
+ if (is_manifest) {
+ processManifest(interest, *content_ptr);
}
- } else {
- DLOG_IF(INFO, VLOG_IS_ON(4)) << "Received fec " << segment_number;
- state_->onFecPacketReceived(content_object);
+
+ ec = is_manifest ? make_error_code(protocol_error::not_reassemblable)
+ : make_error_code(protocol_error::success);
+
+ // The packet is considered received, return early
+ onDataPacketReceived(*content_ptr, compute_stats);
+ return;
}
- } else {
+
+ if (is_fec) {
+ state_->onFecPacketRecoveredRtx(segment_number);
+ }
+ }
+
+ // Fetch packet state again; it may have changed
+ state = state_->getPacketState(segment_number);
+
+ // Check if the packet was already received
+ if (state == PacketState::RECEIVED || state == PacketState::TO_BE_RECEIVED) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Received duplicated content " << segment_number << ", drop it";
ec = make_error_code(protocol_error::duplicated_content);
+ onDataPacketReceived(*content_ptr, compute_stats);
+ return;
}
- ldr_->onDataPacketReceived(content_object);
- rc_->onDataPacketReceived(content_object);
+ if (!is_fec) {
+ state_->dataToBeReceived(segment_number);
+ }
- updateSyncWindow();
+ // Send packet to FEC decoder
+ if (fec_decoder_) {
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Send packet " << segment_number << " to FEC decoder";
+
+ uint32_t offset = is_manifest
+ ? content_object.headerSize()
+ : content_object.headerSize() + rtc::DATA_HEADER_SIZE;
+ uint32_t metadata = static_cast<uint32_t>(content_object.getPayloadType());
+
+ fec_decoder_->onDataPacket(content_object, offset, metadata);
+ }
+
+ // We can return early if FEC
+ if (is_fec) {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Received FEC " << segment_number;
+ state_->onFecPacketReceived(content_object);
+ onDataPacketReceived(*content_ptr, compute_stats);
+ return;
+ }
+
+ // The packet may have been already sent to the app by the decoder, check
+ // again if it is already received
+ state = state_->getPacketState(
+ segment_number); // state == RECEIVED or TO_BE_RECEIVED
+
+ if (state != PacketState::RECEIVED) {
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << (is_manifest ? "Received manifest " : "Received data ")
+ << segment_number;
+
+ if (is_manifest) {
+ processManifest(interest, *content_ptr);
+ }
+
+ state_->onDataPacketReceived(*content_ptr, compute_stats);
+
+ if (*on_content_object_input_) {
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ }
+
+ ec = is_manifest ? make_error_code(protocol_error::not_reassemblable)
+ : make_error_code(protocol_error::success);
+ }
+
+ onDataPacketReceived(*content_ptr, compute_stats);
}
void RTCTransportProtocol::sendStatsToApp(
@@ -729,33 +911,149 @@ void RTCTransportProtocol::sendStatsToApp(
stats_->updateReceivedNacks(received_nacks);
stats_->updateReceivedFEC(received_fec);
- stats_->updateAverageWindowSize(current_sync_win_);
- stats_->updateLossRatio(state_->getLossRate());
- stats_->updateAverageRtt(state_->getRTT());
+ stats_->updateAverageWindowSize(state_->getPendingInterestNumber());
+ stats_->updateLossRatio(state_->getPerSecondLossRate());
+ uint64_t rtt = state_->getAvgRTT();
+ stats_->updateAverageRtt(utils::SteadyTime::Milliseconds(rtt));
+
stats_->updateQueuingDelay(state_->getQueuing());
stats_->updateLostData(lost_data);
stats_->updateDefinitelyLostData(definitely_lost);
stats_->updateRecoveredData(recovered_losses);
stats_->updateCCState((unsigned int)current_state_ ? 1 : 0);
(*stats_summary_)(*socket_->getInterface(), *stats_);
+ bool in_congestion = rc_->inCongestionState();
+ stats_->updateCongestionState(in_congestion);
+ double residual_losses = state_->getResidualLossRate();
+ stats_->updateResidualLossRate(residual_losses);
+ stats_->updateQualityScore(state_->getQualityScore());
+
+ // set alerts
+ if (rtt > MAX_RTT)
+ stats_->setAlert(interface::TransportStatistics::statsAlerts::LATENCY);
+ else
+ stats_->clearAlert(interface::TransportStatistics::statsAlerts::LATENCY);
+
+ if (in_congestion)
+ stats_->setAlert(interface::TransportStatistics::statsAlerts::CONGESTION);
+ else
+ stats_->clearAlert(
+ interface::TransportStatistics::statsAlerts::CONGESTION);
+
+ if (residual_losses > MAX_RESIDUAL_LOSSES)
+ stats_->setAlert(interface::TransportStatistics::statsAlerts::LOSSES);
+ else
+ stats_->clearAlert(interface::TransportStatistics::statsAlerts::LOSSES);
}
}
-void RTCTransportProtocol::onFecPackets(
- std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
+void RTCTransportProtocol::onFecPackets(fec::BufferArray &packets) {
+ Packet::Format format;
+ socket_->getSocketOption(interface::GeneralTransportOptions::PACKET_FORMAT,
+ format);
+
+ Name *name = nullptr;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
+
for (auto &packet : packets) {
- PacketState state = state_->isReceivedOrLost(packet.first);
- if (state != PacketState::RECEIVED) {
- state_->onPacketRecoveredFec(packet.first);
- ldr_->onPacketRecoveredFec(packet.first);
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "Recovered packet " << packet.first << " through FEC.";
- reassembly_->reassemble(*packet.second, packet.first);
- } else {
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "Packet" << packet.first << "already received.";
+ uint32_t seq_number = packet.getIndex();
+ uint32_t metadata = packet.getMetadata();
+ fec::buffer buffer = packet.getBuffer();
+
+ PayloadType payload_type = static_cast<PayloadType>(metadata);
+ switch (payload_type) {
+ case PayloadType::DATA:
+ case PayloadType::MANIFEST:
+ break;
+ case PayloadType::UNSPECIFIED:
+ default:
+ payload_type = PayloadType::DATA;
+ break;
}
+
+ switch (state_->getPacketState(seq_number)) {
+ case PacketState::RECEIVED:
+ case PacketState::TO_BE_RECEIVED: {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Packet " << seq_number << " already received";
+ break;
+ }
+ default: {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Recovered packet " << seq_number << " through FEC";
+
+ if (payload_type == PayloadType::MANIFEST) {
+ name->setSuffix(seq_number);
+
+ auto interest =
+ core::PacketManager<>::getInstance().getPacket<Interest>(format);
+ interest->setName(*name);
+
+ auto content_object = toContentObject(
+ *name, format, payload_type, buffer->data(), buffer->length());
+
+ processManifest(*interest, *content_object);
+ }
+
+ state_->onPacketRecoveredFec(seq_number, buffer->length());
+ ldr_->onPacketRecoveredFec(seq_number);
+
+ if (payload_type == PayloadType::DATA) {
+ verifier_->onDataRecoveredFec(seq_number);
+ reassembly_->reassemble(*buffer, seq_number);
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+void RTCTransportProtocol::processManifest(Interest &interest,
+ ContentObject &manifest) {
+ auth::VerificationPolicy policy = verifier_->processManifest(manifest);
+ indexer_verifier_->applyPolicy(interest, manifest, false, policy);
+}
+
+ContentObject::Ptr RTCTransportProtocol::removeFecHeader(
+ const ContentObject &content_object) {
+ if (!fec_decoder_ || !fec_decoder_->getFecHeaderSize()) {
+ return nullptr;
}
+
+ size_t fec_header_size = fec_decoder_->getFecHeaderSize();
+ const uint8_t *payload =
+ content_object.data() + content_object.headerSize() + fec_header_size;
+ size_t payload_size = content_object.payloadSize() - fec_header_size;
+
+ ContentObject::Ptr co =
+ toContentObject(content_object.getName(), content_object.getFormat(),
+ content_object.getPayloadType(), payload, payload_size);
+
+ return co;
+}
+
+ContentObject::Ptr RTCTransportProtocol::toContentObject(
+ const Name &name, Packet::Format format, PayloadType payload_type,
+ const uint8_t *payload, std::size_t payload_size,
+ std::size_t additional_header_size) {
+ // Recreate ContentObject
+ ContentObject::Ptr co =
+ core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ format, additional_header_size);
+ co->updateLength(payload_size);
+ co->append(payload_size);
+ co->trimStart(co->headerSize());
+
+ // Copy payload
+ std::memcpy(co->writableData(), payload, payload_size);
+
+ // Restore network headers and some fields
+ co->prepend(co->headerSize());
+ co->setName(name);
+ co->setPayloadType(payload_type);
+
+ return co;
}
} // end namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc.h b/libtransport/src/protocols/rtc/rtc.h
index e6431264d..37706eb1c 100644
--- a/libtransport/src/protocols/rtc/rtc.h
+++ b/libtransport/src/protocols/rtc/rtc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -15,10 +15,12 @@
#pragma once
-#include <protocols/datagram_reassembly.h>
+#include <protocols/rtc/rtc_forwarding_strategy.h>
#include <protocols/rtc/rtc_ldr.h>
#include <protocols/rtc/rtc_rc.h>
+#include <protocols/rtc/rtc_reassembly.h>
#include <protocols/rtc/rtc_state.h>
+#include <protocols/rtc/rtc_verifier.h>
#include <protocols/transport_protocol.h>
#include <unordered_set>
@@ -44,6 +46,8 @@ class RTCTransportProtocol : public TransportProtocol {
std::size_t transportHeaderLength() override;
+ auto shared_from_this() { return utils::shared_from(this); }
+
private:
enum class SyncState { catch_up = 0, in_sync = 1, last };
@@ -76,6 +80,7 @@ class RTCTransportProtocol : public TransportProtocol {
void onPacketDropped(Interest &interest, ContentObject &content_object,
const std::error_code &reason) override {}
void onReassemblyFailed(std::uint32_t missing_segment) override {}
+ void processManifest(Interest &interest, ContentObject &manifest);
// interaction with app functions
void sendStatsToApp(uint32_t retx_count, uint32_t received_bytes,
@@ -84,11 +89,20 @@ class RTCTransportProtocol : public TransportProtocol {
uint32_t received_nacks, uint32_t received_fec);
// FEC functions
- void onFecPackets(std::vector<std::pair<uint32_t, fec::buffer>> &packets);
+ void onFecPackets(fec::BufferArray &packets);
+
+ // Utils
+ ContentObject::Ptr removeFecHeader(const ContentObject &content_object);
+ ContentObject::Ptr toContentObject(const Name &name, Packet::Format format,
+ PayloadType payload_type,
+ const uint8_t *payload,
+ std::size_t payload_size,
+ std::size_t additional_header_size = 0);
// protocol state
bool start_send_interest_;
SyncState current_state_;
+
// cwin vars
uint32_t current_sync_win_;
uint32_t max_sync_win_;
@@ -120,6 +134,10 @@ class RTCTransportProtocol : public TransportProtocol {
std::shared_ptr<RTCState> state_;
std::shared_ptr<RTCRateControl> rc_;
std::shared_ptr<RTCLossDetectionAndRecovery> ldr_;
+ std::shared_ptr<RTCVerifier> verifier_;
+
+ // forwarding strategy selection
+ RTCForwardingStrategy fwd_strategy_;
uint32_t number_;
};
diff --git a/libtransport/src/protocols/rtc/rtc_consts.h b/libtransport/src/protocols/rtc/rtc_consts.h
index d04bc1b1f..03efd8e84 100644
--- a/libtransport/src/protocols/rtc/rtc_consts.h
+++ b/libtransport/src/protocols/rtc/rtc_consts.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -45,22 +45,22 @@ const uint32_t MAX_INTERESTS_IN_BATCH = 5; // number of seq numbers per
const uint32_t WAIT_FOR_INTEREST_BATCH = 20; // msec. timer that we wait to try
// to aggregate interest in the
// same packet
-const uint32_t MAX_PACING_BATCH = 5;
-// number of interest that we can send inside
-// the loop before they get dropped by the
-// kernel.
+const uint32_t MAX_PACING_BATCH = 5; // number of interest that we can send
+ // inside the loop before they get dropped
+ // by the kernel.
const uint32_t PACING_WAIT = 1000; // usec to wait betwing two pacing batch. As
// for MAX_PACING_BATCH this value was
// computed during tests
const uint32_t MAX_RTX_IN_BATCH = 10; // max rtx to send in loop
// packet const
-const uint32_t HICN_HEADER_SIZE = 40 + 20; // IPv6 + TCP bytes
const uint32_t RTC_INTEREST_LIFETIME = 2000;
// probes sequence range
const uint32_t MIN_PROBE_SEQ = 0xefffffff;
-const uint32_t MIN_RTT_PROBE_SEQ = MIN_PROBE_SEQ;
+const uint32_t MIN_INIT_PROBE_SEQ = MIN_PROBE_SEQ;
+const uint32_t MAX_INIT_PROBE_SEQ = 0xf7ffffff - 1;
+const uint32_t MIN_RTT_PROBE_SEQ = MAX_INIT_PROBE_SEQ + 1;
const uint32_t MAX_RTT_PROBE_SEQ = 0xffffffff - 1;
// RTT_PROBE_INTERVAL will be used during the section while
// INIT_RTT_PROBE_INTERVAL is used at the beginning to
@@ -78,15 +78,16 @@ const uint32_t INIT_RTT_MIN_PROBES_TO_RECV = 5; // ms
const uint32_t MAX_PENDING_PROBES = 10;
// congestion
-const double MAX_QUEUING_DELAY = 100.0; // ms
+const double MAX_QUEUING_DELAY = 50.0; // ms
// data from cache
const double MAX_DATA_FROM_CACHE = 0.25; // 25%
// window const
-const uint32_t INITIAL_WIN = 5; // pkts
-const uint32_t INITIAL_WIN_MAX = 1000000; // pkts
-const uint32_t WIN_MIN = 5; // pkts
+const uint32_t INITIAL_WIN = 5; // pkts
+const uint32_t INITIAL_WIN_MAX = 1000000; // pkts
+const uint32_t WIN_MIN = 5; // pkts
+const uint32_t WIN_MIN_WITH_AGGREGARED_DATA = 10; // pkts
const double CATCH_UP_WIN_INCREMENT = 1.2;
// used in rate control
const double WIN_DECREASE_FACTOR = 0.5;
@@ -105,10 +106,8 @@ const double MOVING_AVG_ALPHA = 0.8;
const double MILLI_IN_A_SEC = 1000.0;
const double MICRO_IN_A_SEC = 1000000.0;
-
-const double MAX_CACHED_PACKETS = 262144; // 2^18
- // about 50 sec of traffic at 50Mbps
- // with 1200 bytes packets
+const uint32_t ROUNDS_PER_SEC = (uint32_t)(MILLI_IN_A_SEC / ROUND_LEN);
+const uint32_t ROUNDS_PER_MIN = (uint32_t)ROUNDS_PER_SEC * 60;
const uint32_t MAX_ROUND_WHIOUT_PACKETS =
(20 * MILLI_IN_A_SEC) / ROUND_LEN; // 20 sec in rounds;
@@ -120,12 +119,24 @@ 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;
// used by producer
const uint32_t PRODUCER_STATS_INTERVAL = 200; // ms
-const uint32_t MIN_PRODUCTION_RATE = 10; // pps
- // min prod rate
- // set running several test
+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
+const uint16_t MAX_RTC_PAYLOAD_SIZE = 1200; // bytes
+const uint16_t MAX_AGGREGATED_PACKETS = 5; // pkt
+const uint32_t AGGREGATED_PACKETS_TIMER = 2; // ms
+
+// alert thresholds
+const uint32_t MAX_RTT = 200; // ms
+const double MAX_RESIDUAL_LOSSES = 0.05; // %
} // namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.cc b/libtransport/src/protocols/rtc/rtc_data_path.cc
index c098088a3..b3abf5ea8 100644
--- a/libtransport/src/protocols/rtc/rtc_data_path.cc
+++ b/libtransport/src/protocols/rtc/rtc_data_path.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -13,14 +13,17 @@
* limitations under the License.
*/
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <protocols/rtc/rtc_data_path.h>
#include <stdlib.h>
#include <algorithm>
#include <cfloat>
#include <chrono>
+#include <cmath>
#define MAX_ROUNDS_WITHOUT_PKTS 10 // 2sec
+#define AVG_RTT_TIME 1000 // (ms) 1sec
namespace transport {
@@ -32,6 +35,8 @@ RTCDataPath::RTCDataPath(uint32_t path_id)
: path_id_(path_id),
min_rtt(UINT_MAX),
prev_min_rtt(UINT_MAX),
+ max_rtt(0),
+ prev_max_rtt(0),
min_owd(INT_MAX), // this is computed like in LEDBAT, so it is not the
// real OWD, but the measured one, that depends on the
// clock of sender and receiver. the only meaningful
@@ -46,20 +51,46 @@ RTCDataPath::RTCDataPath(uint32_t path_id)
largest_recv_seq_(0),
largest_recv_seq_time_(0),
avg_inter_arrival_(DBL_MAX),
+ rtt_sum_(0),
+ last_avg_rtt_compute_(0),
+ rtt_samples_(0),
+ avg_rtt_(0.0),
received_nacks_(false),
- received_packets_(false),
+ received_packets_(0),
rounds_without_packets_(0),
last_received_data_packet_(0),
- RTT_history_(HISTORY_LEN),
+ min_RTT_history_(HISTORY_LEN),
+ max_RTT_history_(HISTORY_LEN),
OWD_history_(HISTORY_LEN){};
-void RTCDataPath::insertRttSample(uint64_t rtt) {
- // for the rtt we only keep track of the min one
+void RTCDataPath::insertRttSample(
+ const utils::SteadyTime::Milliseconds& rtt_milliseconds, bool is_probe) {
+ // compute min rtt
+ uint64_t rtt = rtt_milliseconds.count();
if (rtt < min_rtt) min_rtt = rtt;
- last_received_data_packet_ =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+
+ uint64_t now = utils::SteadyTime::nowMs().count();
+ last_received_data_packet_ = now;
+
+ // compute avg rtt
+ if (is_probe) {
+ // max rtt is computed only on probes to avoid to take into account the
+ // production time at the server
+ if (rtt > max_rtt) max_rtt = rtt;
+
+ rtt_sum_ += rtt;
+ rtt_samples_++;
+ }
+
+ if ((now - last_avg_rtt_compute_) >= AVG_RTT_TIME) {
+ // compute a new avg rtt
+ // if rtt_samples_ = 0 keep the same rtt
+ if (rtt_samples_ != 0) avg_rtt_ = (double)rtt_sum_ / (double)rtt_samples_;
+
+ rtt_sum_ = 0;
+ rtt_samples_ = 0;
+ last_avg_rtt_compute_ = now;
+ }
}
void RTCDataPath::insertOwdSample(int64_t owd) {
@@ -87,15 +118,13 @@ void RTCDataPath::insertOwdSample(int64_t owd) {
// owd is computed only for valid data packets so we count only
// this for decide if we recevie traffic or not
- received_packets_ = true;
+ received_packets_++;
}
void RTCDataPath::computeInterArrivalGap(uint32_t segment_number) {
// got packet in sequence, compute gap
if (largest_recv_seq_ == (segment_number - 1)) {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint64_t delta = now - largest_recv_seq_time_;
largest_recv_seq_ = segment_number;
largest_recv_seq_time_ = now;
@@ -110,10 +139,7 @@ void RTCDataPath::computeInterArrivalGap(uint32_t segment_number) {
// ooo packet, update the stasts if needed
if (largest_recv_seq_ <= segment_number) {
largest_recv_seq_ = segment_number;
- largest_recv_seq_time_ =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ largest_recv_seq_time_ = utils::SteadyTime::nowMs().count();
}
}
@@ -146,10 +172,20 @@ void RTCDataPath::roundEnd() {
min_rtt = prev_min_rtt;
}
+ // same for max_rtt
+ if (max_rtt != 0) {
+ prev_max_rtt = max_rtt;
+ } else {
+ max_rtt = prev_max_rtt;
+ }
+
if (min_rtt == 0) min_rtt = 1;
+ if (max_rtt == 0) max_rtt = 1;
- RTT_history_.pushBack(min_rtt);
+ min_RTT_history_.pushBack(min_rtt);
+ max_RTT_history_.pushBack(max_rtt);
min_rtt = UINT_MAX;
+ max_rtt = 0;
// do the same for min owd
if (min_owd != INT_MAX) {
@@ -163,32 +199,47 @@ void RTCDataPath::roundEnd() {
min_owd = INT_MAX;
}
- if (!received_packets_)
+ if (received_packets_ == 0)
rounds_without_packets_++;
else
rounds_without_packets_ = 0;
- received_packets_ = false;
+ received_packets_ = 0;
}
uint32_t RTCDataPath::getPathId() { return path_id_; }
-double RTCDataPath::getQueuingDealy() { return queuing_delay; }
+double RTCDataPath::getQueuingDealy() {
+ if (queuing_delay == DBL_MAX) return 0;
+ return queuing_delay;
+}
uint64_t RTCDataPath::getMinRtt() {
- if (RTT_history_.size() != 0) return RTT_history_.begin();
+ if (min_RTT_history_.size() != 0) return min_RTT_history_.begin();
+ return 0;
+}
+
+uint64_t RTCDataPath::getAvgRtt() { return std::round(avg_rtt_); }
+
+uint64_t RTCDataPath::getMaxRtt() {
+ if (max_RTT_history_.size() != 0) return max_RTT_history_.begin();
return 0;
}
int64_t RTCDataPath::getMinOwd() {
if (OWD_history_.size() != 0) return OWD_history_.begin();
- return 0;
+ return INT_MAX;
}
double RTCDataPath::getJitter() { return jitter_; }
uint64_t RTCDataPath::getLastPacketTS() { return last_received_data_packet_; }
-void RTCDataPath::clearRtt() { RTT_history_.clear(); }
+uint32_t RTCDataPath::getPacketsLastRound() { return received_packets_; }
+
+void RTCDataPath::clearRtt() {
+ min_RTT_history_.clear();
+ max_RTT_history_.clear();
+}
} // end namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.h b/libtransport/src/protocols/rtc/rtc_data_path.h
index c5c37fc0d..5afbbb87f 100644
--- a/libtransport/src/protocols/rtc/rtc_data_path.h
+++ b/libtransport/src/protocols/rtc/rtc_data_path.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,7 +15,9 @@
#pragma once
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <stdint.h>
+#include <utils/max_filter.h>
#include <utils/min_filter.h>
#include <climits>
@@ -34,19 +36,23 @@ class RTCDataPath {
RTCDataPath(uint32_t path_id);
public:
- void insertRttSample(uint64_t rtt);
+ void insertRttSample(const utils::SteadyTime::Milliseconds &rtt,
+ bool is_probe);
void insertOwdSample(int64_t owd);
void computeInterArrivalGap(uint32_t segment_number);
void receivedNack();
uint32_t getPathId();
uint64_t getMinRtt();
+ uint64_t getAvgRtt();
+ uint64_t getMaxRtt();
double getQueuingDealy();
double getInterArrivalGap();
double getJitter();
bool isActive();
bool pathToProducer();
uint64_t getLastPacketTS();
+ uint32_t getPacketsLastRound();
void clearRtt();
@@ -60,6 +66,9 @@ class RTCDataPath {
uint64_t min_rtt;
uint64_t prev_min_rtt;
+ uint64_t max_rtt;
+ uint64_t prev_max_rtt;
+
int64_t min_owd;
int64_t prev_min_owd;
@@ -74,19 +83,26 @@ class RTCDataPath {
uint64_t largest_recv_seq_time_;
double avg_inter_arrival_;
+ // compute the avg rtt over one sec
+ uint64_t rtt_sum_;
+ uint64_t last_avg_rtt_compute_;
+ uint32_t rtt_samples_;
+ double avg_rtt_;
+
// flags to check if a path is active
// we considere a path active if it reaches a producer
//(not a cache) --aka we got at least one nack on this path--
// and if we receives packets
bool received_nacks_;
- bool received_packets_;
- uint8_t rounds_without_packets_; // if we don't get any packet
+ uint32_t received_packets_;
+ uint32_t rounds_without_packets_; // if we don't get any packet
// for MAX_ROUNDS_WITHOUT_PKTS
// we consider the path inactive
uint64_t last_received_data_packet_; // timestamp for the last data received
// on this path
- utils::MinFilter<uint64_t> RTT_history_;
+ utils::MinFilter<uint64_t> min_RTT_history_;
+ utils::MaxFilter<uint64_t> max_RTT_history_;
utils::MinFilter<int64_t> OWD_history_;
};
diff --git a/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc
new file mode 100644
index 000000000..9503eed3e
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc
@@ -0,0 +1,155 @@
+/*
+ * 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/notification.h>
+#include <protocols/rtc/rtc_forwarding_strategy.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+using namespace transport::interface;
+
+RTCForwardingStrategy::RTCForwardingStrategy()
+ : init_(false),
+ forwarder_set_(false),
+ selected_strategy_(NONE),
+ current_strategy_(NONE),
+ rounds_since_last_set_(0),
+ portal_(nullptr),
+ state_(nullptr) {}
+
+RTCForwardingStrategy::~RTCForwardingStrategy() {}
+
+void RTCForwardingStrategy::setCallback(interface::StrategyCallback* callback) {
+ callback_ = callback;
+}
+
+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;
+}
+
+void RTCForwardingStrategy::checkStrategy() {
+ if (*callback_) {
+ strategy_t used_strategy = selected_strategy_;
+ if (used_strategy == BOTH) used_strategy = current_strategy_;
+ assert(used_strategy == BEST_PATH || used_strategy == REPLICATION ||
+ used_strategy == NONE);
+
+ notification::ForwardingStrategy strategy =
+ notification::ForwardingStrategy::NONE;
+ switch (used_strategy) {
+ case BEST_PATH:
+ strategy = notification::ForwardingStrategy::BEST_PATH;
+ break;
+ case REPLICATION:
+ strategy = notification::ForwardingStrategy::REPLICATION;
+ break;
+ default:
+ break;
+ }
+
+ (*callback_)(strategy);
+ }
+
+ if (!init_) return;
+
+ if (selected_strategy_ == NONE) return;
+
+ if (selected_strategy_ == BEST_PATH) {
+ checkStrategyBestPath();
+ return;
+ }
+
+ if (selected_strategy_ == REPLICATION) {
+ checkStrategyReplication();
+ return;
+ }
+
+ checkStrategyBoth();
+}
+
+void RTCForwardingStrategy::checkStrategyBestPath() {
+ if (!forwarder_set_) {
+ setStrategy(BEST_PATH);
+ forwarder_set_ = true;
+ return;
+ }
+
+ 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;
+ }
+
+ // try to switch path
+ setStrategy(BEST_PATH);
+}
+
+void RTCForwardingStrategy::checkStrategyReplication() {
+ if (!forwarder_set_) {
+ setStrategy(REPLICATION);
+ forwarder_set_ = true;
+ return;
+ }
+
+ // here we have nothing to do for the moment
+ return;
+}
+
+void RTCForwardingStrategy::checkStrategyBoth() {
+ if (!forwarder_set_) {
+ setStrategy(current_strategy_);
+ forwarder_set_ = true;
+ return;
+ }
+
+ checkStrategyBestPath();
+
+ // TODO
+ // for the moment we use only best path.
+ // but 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
+}
+
+void RTCForwardingStrategy::setStrategy(strategy_t strategy) {
+ rounds_since_last_set_ = 0;
+ current_strategy_ = strategy;
+ portal_->setForwardingStrategy(prefix_,
+ string_strategies_[current_strategy_]);
+}
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h
new file mode 100644
index 000000000..821b28051
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h
@@ -0,0 +1,78 @@
+/*
+ * 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/portal.h>
+#include <hicn/transport/interfaces/callbacks.h>
+#include <protocols/rtc/rtc_state.h>
+
+#include <array>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCForwardingStrategy {
+ public:
+ enum strategy_t {
+ BEST_PATH,
+ REPLICATION,
+ BOTH,
+ NONE,
+ };
+
+ RTCForwardingStrategy();
+ ~RTCForwardingStrategy();
+
+ void initFwdStrategy(std::shared_ptr<core::Portal> portal,
+ core::Prefix& prefix, RTCState* state,
+ strategy_t strategy);
+
+ void checkStrategy();
+ void setCallback(interface::StrategyCallback* callback);
+
+ private:
+ void checkStrategyBestPath();
+ void checkStrategyReplication();
+ void checkStrategyBoth();
+
+ void setStrategy(strategy_t strategy);
+
+ std::array<std::string, 4> string_strategies_ = {"bestpath", "replication",
+ "both", "none"};
+
+ bool init_; // true if all val are initializes
+ bool forwarder_set_; // true if the strategy is been set at least
+ // once
+ strategy_t selected_strategy_; // this is the strategy selected using socket
+ // options. this can also be equal to BOTH
+ strategy_t current_strategy_; // if both strategies can be used this
+ // indicates the one that is currently in use
+ // that can be only replication or best path
+ uint32_t rounds_since_last_set_;
+ core::Prefix prefix_;
+ std::shared_ptr<core::Portal> portal_;
+ RTCState* state_;
+ interface::StrategyCallback* callback_;
+};
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_indexer.h b/libtransport/src/protocols/rtc/rtc_indexer.h
index 4aee242bb..cda156b22 100644
--- a/libtransport/src/protocols/rtc/rtc_indexer.h
+++ b/libtransport/src/protocols/rtc/rtc_indexer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,8 +18,10 @@
#include <protocols/errors.h>
#include <protocols/fec_utils.h>
#include <protocols/indexer.h>
+#include <protocols/rtc/probe_handler.h>
#include <protocols/rtc/rtc_consts.h>
#include <protocols/transport_protocol.h>
+#include <utils/suffix_strategy.h>
#include <deque>
@@ -54,7 +56,7 @@ class RtcIndexer : public Indexer {
n_fec_ = 0;
}
- uint32_t checkNextSuffix() override { return next_suffix_; }
+ uint32_t checkNextSuffix() const override { return next_suffix_; }
uint32_t getNextSuffix() override {
if (isFec(next_suffix_)) {
@@ -77,7 +79,7 @@ class RtcIndexer : public Indexer {
first_suffix_ = suffix % LIMIT;
}
- uint32_t getFirstSuffix() override { return first_suffix_; }
+ uint32_t getFirstSuffix() const override { return first_suffix_; }
uint32_t jumpToIndex(uint32_t index) override {
next_suffix_ = index % LIMIT;
@@ -87,30 +89,8 @@ class RtcIndexer : public Indexer {
void onContentObject(core::Interest &interest,
core::ContentObject &content_object,
bool reassembly) override {
- setVerifier();
- auto ret = verifier_->verifyPackets(&content_object);
-
- switch (ret) {
- case auth::VerificationPolicy::ACCEPT: {
- if (reassembly) {
- reassembly_->reassemble(content_object);
- }
- break;
- }
-
- case auth::VerificationPolicy::UNKNOWN:
- case auth::VerificationPolicy::DROP: {
- transport_->onPacketDropped(
- interest, content_object,
- make_error_code(protocol_error::verification_failed));
- break;
- }
-
- case auth::VerificationPolicy::ABORT: {
- transport_->onContentReassembled(
- make_error_code(protocol_error::session_aborted));
- break;
- }
+ if (reassembly) {
+ reassembly_->reassemble(content_object);
}
}
@@ -120,13 +100,12 @@ class RtcIndexer : public Indexer {
uint32_t getNextReassemblySegment() override {
throw errors::RuntimeException(
"Get reassembly segment called on rtc indexer. RTC indexer does not "
- "provide "
- "reassembly.");
+ "provide reassembly.");
}
bool isFinalSuffixDiscovered() override { return true; }
- uint32_t getFinalSuffix() override { return LIMIT; }
+ uint32_t getFinalSuffix() const override { return LIMIT; }
void enableFec(fec::FECType fec_type) override { fec_type_ = fec_type; }
@@ -137,13 +116,13 @@ class RtcIndexer : public Indexer {
n_current_fec_ = n_fec_;
}
- uint32_t getNFec() override { return n_fec_; }
+ uint32_t getNFec() const override { return n_fec_; }
bool isFec(uint32_t index) override {
return isFec(fec_type_, index, first_suffix_);
}
- double getFecOverhead() override {
+ double getFecOverhead() const override {
if (fec_type_ == fec::FECType::UNKNOWN) {
return 0;
}
@@ -152,7 +131,7 @@ class RtcIndexer : public Indexer {
return (double)n_fec_ / k;
}
- double getMaxFecOverhead() override {
+ double getMaxFecOverhead() const override {
if (fec_type_ == fec::FECType::UNKNOWN) {
return 0;
}
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.cc b/libtransport/src/protocols/rtc/rtc_ldr.cc
index f0de48871..1ca1cf48d 100644
--- a/libtransport/src/protocols/rtc/rtc_ldr.cc
+++ b/libtransport/src/protocols/rtc/rtc_ldr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,12 @@
#include <glog/logging.h>
#include <protocols/rtc/rtc_consts.h>
#include <protocols/rtc/rtc_ldr.h>
+#include <protocols/rtc/rtc_rs_delay.h>
+#include <protocols/rtc/rtc_rs_fec_only.h>
+#include <protocols/rtc/rtc_rs_low_rate.h>
+#include <protocols/rtc/rtc_rs_recovery_off.h>
+#include <protocols/rtc/rtc_rs_rtx_only.h>
+#include <protocols/rtc/rtc_state.h>
#include <algorithm>
#include <unordered_set>
@@ -27,146 +33,115 @@ namespace protocol {
namespace rtc {
RTCLossDetectionAndRecovery::RTCLossDetectionAndRecovery(
- Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service)
- : rtx_on_(false),
- fec_on_(false),
- next_rtx_timer_(MAX_TIMER_RTX),
- last_event_(0),
- sentinel_timer_interval_(MAX_TIMER_RTX),
- indexer_(indexer),
- send_rtx_callback_(std::move(callback)) {
- timer_ = std::make_unique<asio::steady_timer>(io_service);
- sentinel_timer_ = std::make_unique<asio::steady_timer>(io_service);
+ Indexer *indexer, asio::io_service &io_service,
+ 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, external_callback);
+ } else if (type == interface::RtcTransportRecoveryStrategies::DELAY_BASED) {
+ rs_ = std::make_shared<RecoveryStrategyDelayBased>(
+ indexer, std::move(callback), io_service, external_callback);
+ } else if (type == interface::RtcTransportRecoveryStrategies::FEC_ONLY) {
+ rs_ = std::make_shared<RecoveryStrategyFecOnly>(
+ indexer, std::move(callback), io_service, external_callback);
+ } else if (type == interface::RtcTransportRecoveryStrategies::LOW_RATE ||
+ type == interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_BESTPATH ||
+ type == interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_REPLICATION ||
+ type == interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_ALL_FWD_STRATEGIES) {
+ rs_ = std::make_shared<RecoveryStrategyLowRate>(
+ indexer, std::move(callback), io_service, external_callback);
+ } else {
+ // default
+ rs_type_ = interface::RtcTransportRecoveryStrategies::RTX_ONLY;
+ rs_ = std::make_shared<RecoveryStrategyRtxOnly>(
+ indexer, std::move(callback), io_service, external_callback);
+ }
}
RTCLossDetectionAndRecovery::~RTCLossDetectionAndRecovery() {}
-void RTCLossDetectionAndRecovery::turnOnRTX() {
- rtx_on_ = true;
- scheduleSentinelTimer(state_->getRTT() * CATCH_UP_RTT_INCREMENT);
-}
-
-void RTCLossDetectionAndRecovery::turnOffRTX() {
- rtx_on_ = false;
- clear();
-}
-
-uint32_t RTCLossDetectionAndRecovery::computeFecPacketsToAsk(bool in_sync) {
- uint32_t current_fec = indexer_->getNFec();
- double current_loss_rate = state_->getLossRate();
- double last_loss_rate = state_->getLastRoundLossRate();
-
- // when in sync ask for fec only if there are losses for 2 rounds
- if (in_sync && current_fec == 0 &&
- (current_loss_rate == 0 || last_loss_rate == 0))
- return 0;
-
- double loss_rate = state_->getMaxLossRate() * 1.5;
-
- if (!in_sync && loss_rate == 0) loss_rate = 0.05;
- if (loss_rate > 0.5) loss_rate = 0.5;
-
- double exp_losses = (double)k_ * loss_rate;
- uint32_t fec_to_ask = ceil(exp_losses / (1 - loss_rate));
-
- if (fec_to_ask > (n_ - k_)) fec_to_ask = n_ - k_;
-
- return fec_to_ask;
+void RTCLossDetectionAndRecovery::changeRecoveryStrategy(
+ interface::RtcTransportRecoveryStrategies type) {
+ if (type == rs_type_) return;
+
+ rs_type_ = type;
+ if (type == interface::RtcTransportRecoveryStrategies::RECOVERY_OFF) {
+ rs_ =
+ std::make_shared<RecoveryStrategyRecoveryOff>(std::move(*(rs_.get())));
+ } else if (type == interface::RtcTransportRecoveryStrategies::DELAY_BASED) {
+ rs_ = std::make_shared<RecoveryStrategyDelayBased>(std::move(*(rs_.get())));
+ } else if (type == interface::RtcTransportRecoveryStrategies::FEC_ONLY) {
+ rs_ = std::make_shared<RecoveryStrategyFecOnly>(std::move(*(rs_.get())));
+ } else if (type == interface::RtcTransportRecoveryStrategies::LOW_RATE ||
+ type == interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_BESTPATH ||
+ type == interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_REPLICATION ||
+ type == interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_ALL_FWD_STRATEGIES) {
+ rs_ = std::make_shared<RecoveryStrategyLowRate>(std::move(*(rs_.get())));
+ } else {
+ // default
+ rs_ = std::make_shared<RecoveryStrategyRtxOnly>(std::move(*(rs_.get())));
+ }
}
void RTCLossDetectionAndRecovery::onNewRound(bool in_sync) {
- uint64_t rtt = state_->getRTT();
- if (!fec_on_ && rtt >= 100) {
- // turn on fec, here we may have no info so ask for all packets
- fec_on_ = true;
- turnOffRTX();
- indexer_->setNFec(computeFecPacketsToAsk(in_sync));
- return;
- }
-
- if (fec_on_ && rtt > 80) {
- // keep using fec, maybe update it
- indexer_->setNFec(computeFecPacketsToAsk(in_sync));
- return;
- }
-
- if ((fec_on_ && rtt <= 80) || (!rtx_on_ && rtt <= 100)) {
- // turn on rtx
- fec_on_ = false;
- indexer_->setNFec(0);
- turnOnRTX();
- return;
- }
+ rs_->incRoundId();
+ rs_->onNewRound(in_sync);
}
-void RTCLossDetectionAndRecovery::onTimeout(uint32_t seq) {
- // always add timeouts to the RTX list to avoid to send the same packet as if
- // it was not a rtx
- addToRetransmissions(seq, seq + 1);
- last_event_ = getNow();
+void RTCLossDetectionAndRecovery::onTimeout(uint32_t seq, bool lost) {
+ if (!lost) {
+ detectLoss(seq, seq + 1);
+ } else {
+ rs_->onLostTimeout(seq);
+ }
}
void RTCLossDetectionAndRecovery::onPacketRecoveredFec(uint32_t seq) {
- // if an RTX is scheduled for a packet recovered using FEC delete it
- deleteRtx(seq);
- recover_with_fec_.erase(seq);
+ rs_->receivedPacket(seq);
}
void RTCLossDetectionAndRecovery::onDataPacketReceived(
const core::ContentObject &content_object) {
- last_event_ = getNow();
-
uint32_t seq = content_object.getName().getSuffix();
- if (deleteRtx(seq)) {
- state_->onPacketRecoveredRtx(seq);
- } else {
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "received data. add from "
- << state_->getHighestSeqReceivedInOrder() + 1 << " to " << seq;
- addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1, seq);
- }
+ bool is_rtx = rs_->isRtx(seq);
+ rs_->receivedPacket(seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "received data. add from "
+ << rs_->getState()->getHighestSeqReceivedInOrder() + 1 << " to " << seq;
+ if (!is_rtx)
+ detectLoss(rs_->getState()->getHighestSeqReceivedInOrder() + 1, seq);
}
void RTCLossDetectionAndRecovery::onNackPacketReceived(
const core::ContentObject &nack) {
- last_event_ = getNow();
-
- uint32_t seq = nack.getName().getSuffix();
-
struct nack_packet_t *nack_pkt =
(struct nack_packet_t *)nack.getPayload()->data();
- uint32_t production_seq = nack_pkt->getProductionSegement();
+ uint32_t production_seq = nack_pkt->getProductionSegment();
+ uint32_t seq = nack.getName().getSuffix();
- if (production_seq > seq) {
- // this is a past nack, all data before productionSeq are lost. if
- // productionSeq > state_->getHighestSeqReceivedInOrder() is impossible to
- // recover any packet. If this is not the case we can try to recover the
- // packets between state_->getHighestSeqReceivedInOrder() and productionSeq.
- // e.g.: the client receives packets 8 10 11 9 where 9 is a nack with
- // productionSeq = 14. 9 is lost but we can try to recover packets 12 13 and
- // 14 that are not arrived yet
- deleteRtx(seq);
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "received past nack. add from "
- << state_->getHighestSeqReceivedInOrder() + 1
- << " to " << production_seq;
- addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
- production_seq);
- } else {
- // future nack. here there should be a gap between the last data received
- // and this packet and is it possible to recover the packets between the
- // last received data and the production seq. we should not use the seq
- // number of the nack since we know that is too early to ask for this seq
- // number
- // e.g.: // e.g.: the client receives packets 10 11 12 20 where 20 is a nack
- // with productionSeq = 18. this says that all the packets between 12 and 18
- // may got lost and we should ask them
- deleteRtx(seq);
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "received futrue nack. add from "
- << state_->getHighestSeqReceivedInOrder() + 1
- << " to " << production_seq;
- addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
- production_seq);
- }
+ // received a nack. we can try to recover all data packets between the last
+ // received data and the production seq in the nack. this is similar to the
+ // recption of a probe
+ // e.g.: the client receives packets 10 11 12 20 where 20 is a nack
+ // with productionSeq = 18. this says that all the packets between 12 and 18
+ // may got lost and we should ask them
+
+ rs_->receivedPacket(seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "received nack. add from "
+ << rs_->getState()->getHighestSeqReceivedInOrder() + 1 << " to "
+ << production_seq;
+ detectLoss(rs_->getState()->getHighestSeqReceivedInOrder() + 1,
+ production_seq);
}
void RTCLossDetectionAndRecovery::onProbePacketReceived(
@@ -174,336 +149,38 @@ void RTCLossDetectionAndRecovery::onProbePacketReceived(
// we don't log the reception of a probe packet for the sentinel timer because
// probes are not taken into account into the sync window. we use them as
// future nacks to detect possible packets lost
- struct nack_packet_t *probe_pkt =
- (struct nack_packet_t *)probe.getPayload()->data();
- uint32_t production_seq = probe_pkt->getProductionSegement();
+
+ uint32_t production_seq = RTCState::getProbeParams(probe).prod_seg;
+
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "received probe. add from "
- << state_->getHighestSeqReceivedInOrder() + 1 << " to " << production_seq;
+ << rs_->getState()->getHighestSeqReceivedInOrder() + 1 << " to "
+ << production_seq;
- addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
- production_seq);
+ detectLoss(rs_->getState()->getHighestSeqReceivedInOrder() + 1,
+ production_seq);
}
-void RTCLossDetectionAndRecovery::clear() {
- rtx_state_.clear();
- rtx_timers_.clear();
- sentinel_timer_->cancel();
- if (next_rtx_timer_ != MAX_TIMER_RTX) {
- next_rtx_timer_ = MAX_TIMER_RTX;
- timer_->cancel();
- }
-}
+void RTCLossDetectionAndRecovery::detectLoss(uint32_t start, uint32_t stop) {
+ if (start >= stop) return;
-void RTCLossDetectionAndRecovery::addToRetransmissions(uint32_t start,
- uint32_t stop) {
// skip nacked packets
- if (start <= state_->getLastSeqNacked()) {
- start = state_->getLastSeqNacked() + 1;
+ if (start <= rs_->getState()->getLastSeqNacked()) {
+ start = rs_->getState()->getLastSeqNacked() + 1;
}
// skip received or lost packets
- if (start <= state_->getHighestSeqReceivedInOrder()) {
- start = state_->getHighestSeqReceivedInOrder() + 1;
+ if (start <= rs_->getState()->getHighestSeqReceivedInOrder()) {
+ start = rs_->getState()->getHighestSeqReceivedInOrder() + 1;
}
for (uint32_t seq = start; seq < stop; seq++) {
- if (state_->isReceivedOrLost(seq) == PacketState::UNKNOWN) {
- if (rtx_on_) {
- if (!indexer_->isFec(seq)) {
- // handle it with rtx
- if (!isRtx(seq)) {
- state_->onLossDetected(seq);
- rtxState state;
- state.first_send_ = state_->getInterestSentTime(seq);
- if (state.first_send_ == 0) // this interest was never sent before
- state.first_send_ = getNow();
- state.next_send_ = computeNextSend(seq, true);
- state.rtx_count_ = 0;
- DLOG_IF(INFO, VLOG_IS_ON(4))
- << "Add " << seq << " to retransmissions. next rtx is %lu "
- << state.next_send_ - getNow();
- rtx_state_.insert(std::pair<uint32_t, rtxState>(seq, state));
- rtx_timers_.insert(
- std::pair<uint64_t, uint32_t>(state.next_send_, seq));
- }
- } else {
- // is fec, do not send it
- auto it = recover_with_fec_.find(seq);
- if (it == recover_with_fec_.end()) {
- state_->onLossDetected(seq);
- recover_with_fec_.insert(seq);
- }
- }
- } else {
- // keep track of losses but recover with FEC
- auto it = recover_with_fec_.find(seq);
- if (it == recover_with_fec_.end()) {
- state_->onLossDetected(seq);
- recover_with_fec_.insert(seq);
- }
- }
- }
- }
- scheduleNextRtx();
-}
-
-uint64_t RTCLossDetectionAndRecovery::computeNextSend(uint32_t seq,
- bool new_rtx) {
- uint64_t now = getNow();
- if (new_rtx) {
- // for the new rtx we wait one estimated IAT after the loss detection. this
- // is bacause, assuming that packets arrive with a constant IAT, we should
- // get a new packet every IAT
- double prod_rate = state_->getProducerRate();
- uint32_t estimated_iat = SENTINEL_TIMER_INTERVAL;
- uint32_t jitter = 0;
-
- if (prod_rate != 0) {
- double packet_size = state_->getAveragePacketSize();
- estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
- jitter = ceil(state_->getJitter());
- }
-
- uint32_t wait = estimated_iat + jitter;
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "first rtx for " << seq << " in " << wait
- << " ms, rtt = " << state_->getRTT() << " ait = " << estimated_iat
- << " jttr = " << jitter;
-
- return now + wait;
- } else {
- // wait one RTT
- // however if the IAT is larger than the RTT, wait one IAT
- uint32_t wait = SENTINEL_TIMER_INTERVAL;
-
- double prod_rate = state_->getProducerRate();
- if (prod_rate == 0) {
- return now + SENTINEL_TIMER_INTERVAL;
- }
-
- double packet_size = state_->getAveragePacketSize();
- uint32_t estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
-
- uint64_t rtt = state_->getRTT();
- if (rtt == 0) rtt = SENTINEL_TIMER_INTERVAL;
- wait = rtt;
-
- if (estimated_iat > rtt) wait = estimated_iat;
-
- 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_->getRTT() << " ait = " << estimated_iat
- << " jttr = " << jitter << " queue = " << queue;
-
- return now + wait;
- }
-}
-
-void RTCLossDetectionAndRecovery::retransmit() {
- if (rtx_timers_.size() == 0) return;
-
- uint64_t now = getNow();
-
- auto it = rtx_timers_.begin();
- std::unordered_set<uint32_t> lost_pkt;
- uint32_t sent_counter = 0;
- while (it != rtx_timers_.end() && it->first <= now &&
- sent_counter < MAX_RTX_IN_BATCH) {
- uint32_t seq = it->second;
- auto rtx_it =
- rtx_state_.find(seq); // this should always return a valid iter
- if (rtx_it->second.rtx_count_ >= RTC_MAX_RTX ||
- (now - rtx_it->second.first_send_) >= RTC_MAX_AGE ||
- seq < state_->getLastSeqNacked()) {
- // max rtx reached or packet too old or packet nacked, this packet is lost
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "packet " << seq << " lost because 1) max rtx: "
- << (rtx_it->second.rtx_count_ >= RTC_MAX_RTX) << " 2) max age: "
- << ((now - rtx_it->second.first_send_) >= RTC_MAX_AGE)
- << " 3) nacked: " << (seq < state_->getLastSeqNacked());
- lost_pkt.insert(seq);
- it++;
- } else {
- // resend the packet
- state_->onRetransmission(seq);
- double prod_rate = state_->getProducerRate();
- if (prod_rate != 0) rtx_it->second.rtx_count_++;
- rtx_it->second.next_send_ = computeNextSend(seq, false);
- it = rtx_timers_.erase(it);
- rtx_timers_.insert(
- std::pair<uint64_t, uint32_t>(rtx_it->second.next_send_, seq));
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "send rtx for sequence " << seq << ", next send in "
- << (rtx_it->second.next_send_ - now);
- send_rtx_callback_(seq);
- sent_counter++;
- }
- }
-
- // remove packets if needed
- for (auto lost_it = lost_pkt.begin(); lost_it != lost_pkt.end(); lost_it++) {
- uint32_t seq = *lost_it;
- state_->onPacketLost(seq);
- deleteRtx(seq);
- }
-}
-
-void RTCLossDetectionAndRecovery::scheduleNextRtx() {
- if (rtx_timers_.size() == 0) {
- // all the rtx were removed, reset timer
- next_rtx_timer_ = MAX_TIMER_RTX;
- return;
- }
-
- // check if timer is alreay set
- if (next_rtx_timer_ != MAX_TIMER_RTX) {
- // a new check for rtx is already scheduled
- if (next_rtx_timer_ > rtx_timers_.begin()->first) {
- // we need to re-schedule it
- timer_->cancel();
- } else {
- // wait for the next timer
- return;
- }
- }
-
- // set a new timer
- next_rtx_timer_ = rtx_timers_.begin()->first;
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- uint64_t wait = 1;
- if (next_rtx_timer_ != MAX_TIMER_RTX && next_rtx_timer_ > now)
- wait = next_rtx_timer_ - now;
-
- std::weak_ptr<RTCLossDetectionAndRecovery> self(shared_from_this());
- timer_->expires_from_now(std::chrono::milliseconds(wait));
- timer_->async_wait([self](std::error_code ec) {
- if (ec) return;
- if (auto s = self.lock()) {
- s->retransmit();
- s->next_rtx_timer_ = MAX_TIMER_RTX;
- s->scheduleNextRtx();
- }
- });
-}
-
-bool RTCLossDetectionAndRecovery::deleteRtx(uint32_t seq) {
- auto it_rtx = rtx_state_.find(seq);
- if (it_rtx == rtx_state_.end()) return false; // rtx not found
-
- uint64_t ts = it_rtx->second.next_send_;
- auto it_timers = rtx_timers_.find(ts);
- while (it_timers != rtx_timers_.end() && it_timers->first == ts) {
- if (it_timers->second == seq) {
- rtx_timers_.erase(it_timers);
- break;
- }
- it_timers++;
- }
-
- bool lost = it_rtx->second.rtx_count_ > 0;
- rtx_state_.erase(it_rtx);
-
- return lost;
-}
-
-void RTCLossDetectionAndRecovery::scheduleSentinelTimer(
- uint64_t expires_from_now) {
- std::weak_ptr<RTCLossDetectionAndRecovery> self(shared_from_this());
- sentinel_timer_->expires_from_now(
- std::chrono::milliseconds(expires_from_now));
- sentinel_timer_->async_wait([self](std::error_code ec) {
- if (ec) return;
- if (auto s = self.lock()) {
- s->sentinelTimer();
- }
- });
-}
-
-void RTCLossDetectionAndRecovery::sentinelTimer() {
- uint64_t now = getNow();
-
- bool expired = false;
- bool sent = false;
- if ((now - last_event_) >= sentinel_timer_interval_) {
- // at least a sentinel_timer_interval_ elapsed since last event
- expired = true;
- if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) {
- // this happens at the beginning (or if the producer stops for some
- // reason) we need to keep sending interest 0 until we get an answer
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "sentinel timer: the producer is not active, send packet 0";
- state_->onRetransmission(0);
- send_rtx_callback_(0);
- } else {
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "sentinel timer: the producer is active, "
- "send the 10 oldest packets";
- sent = true;
- uint32_t rtx = 0;
- auto it = state_->getPendingInterestsMapBegin();
- auto end = state_->getPendingInterestsMapEnd();
- while (it != end && rtx < MAX_RTX_WITH_SENTINEL) {
- uint32_t seq = it->first;
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "sentinel timer, add " << seq << " to the rtx list";
- addToRetransmissions(seq, seq + 1);
- rtx++;
- it++;
- }
- }
- } else {
- // sentinel timer did not expire because we registered at least one event
- }
-
- uint32_t next_timer;
- double prod_rate = state_->getProducerRate();
- if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive()) || prod_rate == 0) {
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "next timer in " << SENTINEL_TIMER_INTERVAL;
- next_timer = SENTINEL_TIMER_INTERVAL;
- } else {
- double prod_rate = state_->getProducerRate();
- double packet_size = state_->getAveragePacketSize();
- uint32_t estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
- uint32_t jitter = ceil(state_->getJitter());
-
- // try to reduce the number of timers if the estimated IAT is too small
- next_timer = std::max((estimated_iat + jitter) * 20, (uint32_t)1);
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "next sentinel in " << next_timer
- << " ms, rate: " << ((prod_rate * 8.0) / 1000000.0)
- << ", iat: " << estimated_iat << ", jitter: " << jitter;
-
- if (!expired) {
- // discount the amout of time that is already passed
- uint32_t discount = now - last_event_;
- if (next_timer > discount) {
- next_timer = next_timer - discount;
- } else {
- // in this case we trigger the timer in 1 ms
- next_timer = 1;
+ if (rs_->getState()->getPacketState(seq) == PacketState::UNKNOWN) {
+ if (rs_->lossDetected(seq)) {
+ rs_->getState()->onLossDetected(seq);
}
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "timer after discout: " << next_timer;
- } else if (sent) {
- // wait at least one producer stats interval + owd to check if the
- // production rate is reducing.
- uint32_t min_wait = PRODUCER_STATS_INTERVAL + ceil(state_->getQueuing());
- next_timer = std::max(next_timer, min_wait);
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "wait for updates from prod, next timer: " << next_timer;
}
}
-
- scheduleSentinelTimer(next_timer);
}
} // namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.h b/libtransport/src/protocols/rtc/rtc_ldr.h
index 1b9f9afd6..e7f8ce5db 100644
--- a/libtransport/src/protocols/rtc/rtc_ldr.h
+++ b/libtransport/src/protocols/rtc/rtc_ldr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -15,16 +15,14 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
+// RtcTransportRecoveryStrategies
#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/name.h>
-#include <protocols/indexer.h>
-#include <protocols/rtc/rtc_consts.h>
-#include <protocols/rtc/rtc_state.h>
+#include <protocols/rtc/rtc_recovery_strategy.h>
#include <functional>
-#include <map>
-#include <unordered_map>
namespace transport {
@@ -34,91 +32,45 @@ namespace rtc {
class RTCLossDetectionAndRecovery
: public std::enable_shared_from_this<RTCLossDetectionAndRecovery> {
- struct rtx_state_ {
- uint64_t first_send_;
- uint64_t next_send_;
- uint32_t rtx_count_;
- };
-
- using rtxState = struct rtx_state_;
- using SendRtxCallback = std::function<void(uint32_t)>;
-
public:
- RTCLossDetectionAndRecovery(Indexer *indexer, SendRtxCallback &&callback,
- asio::io_service &io_service);
+ RTCLossDetectionAndRecovery(Indexer *indexer, asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies type,
+ RecoveryStrategy::SendRtxCallback &&callback,
+ interface::StrategyCallback *external_callback);
~RTCLossDetectionAndRecovery();
- void setState(std::shared_ptr<RTCState> state) { state_ = state; }
- void setFecParams(uint32_t n, uint32_t k) {
- n_ = n;
- k_ = k;
+ void setState(RTCState *state) { rs_->setState(state); }
+ void setRateControl(RTCRateControl *rateControl) {
+ rs_->setRateControl(rateControl);
}
- void turnOnRTX();
- void turnOffRTX();
- bool isRtxOn() { return rtx_on_; }
+
+ void setFecParams(uint32_t n, uint32_t k) { rs_->setFecParams(n, k); }
+
+ void turnOnRecovery() { rs_->tunrOnRecovery(); }
+ bool isRtxOn() { return rs_->isRtxOn(); }
+
+ void changeRecoveryStrategy(interface::RtcTransportRecoveryStrategies type);
void onNewRound(bool in_sync);
- void onTimeout(uint32_t seq);
+ void onTimeout(uint32_t seq, bool lost);
void onPacketRecoveredFec(uint32_t seq);
void onDataPacketReceived(const core::ContentObject &content_object);
void onNackPacketReceived(const core::ContentObject &nack);
void onProbePacketReceived(const core::ContentObject &probe);
- void clear();
+ void clear() { rs_->clear(); }
- bool isRtx(uint32_t seq) {
- if (rtx_state_.find(seq) != rtx_state_.end()) return true;
- return false;
+ bool isRtx(uint32_t seq) { return rs_->isRtx(seq); }
+ bool isPossibleLossWithNoRtx(uint32_t seq) {
+ return rs_->isPossibleLossWithNoRtx(seq);
}
private:
- void addToRetransmissions(uint32_t start, uint32_t stop);
- uint64_t computeNextSend(uint32_t seq, bool new_rtx);
- void retransmit();
- void scheduleNextRtx();
- bool deleteRtx(uint32_t seq);
- void scheduleSentinelTimer(uint64_t expires_from_now);
- void sentinelTimer();
- uint32_t computeFecPacketsToAsk(bool in_sync);
-
- uint64_t getNow() {
- using namespace std::chrono;
- uint64_t now =
- duration_cast<milliseconds>(steady_clock::now().time_since_epoch())
- .count();
- return now;
- }
-
- // this map keeps track of the retransmitted interest, ordered from the oldest
- // to the newest one. the state contains the timer of the first send of the
- // interest (from pendingIntetests_), the timer of the next send (key of the
- // multimap) and the number of rtx
- std::map<uint32_t, rtxState> rtx_state_;
- // this map stored the rtx by timer. The key is the time at which the rtx
- // should be sent, and the val is the interest seq number
- std::multimap<uint64_t, uint32_t> rtx_timers_;
-
- // lost packets that will be recovered with fec
- std::unordered_set<uint32_t> recover_with_fec_;
-
- bool rtx_on_;
- bool fec_on_;
- uint64_t next_rtx_timer_;
- uint64_t last_event_;
- uint64_t sentinel_timer_interval_;
-
- // fec params
- uint32_t n_;
- uint32_t k_;
-
- std::unique_ptr<asio::steady_timer> timer_;
- std::unique_ptr<asio::steady_timer> sentinel_timer_;
- std::shared_ptr<RTCState> state_;
-
- Indexer *indexer_;
+ void detectLoss(uint32_t start, uint32_t stop);
- SendRtxCallback send_rtx_callback_;
+ interface::RtcTransportRecoveryStrategies rs_type_;
+ std::shared_ptr<RecoveryStrategy> rs_;
};
} // end namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_packet.h b/libtransport/src/protocols/rtc/rtc_packet.h
index 7dc2f82c3..391aedfc6 100644
--- a/libtransport/src/protocols/rtc/rtc_packet.h
+++ b/libtransport/src/protocols/rtc/rtc_packet.h
@@ -24,6 +24,27 @@
* +-----------------------------------------+
*/
+/* aggregated packets
+ * +---------------------------------+
+ * |c| #pkts | len1 | len2 | .... |
+ * +----------------------------------
+ *
+ * +---------------------------------+
+ * |c| #pkts | resv | len 1 |
+ * +----------------------------------
+ *
+ * aggregated packets header.
+ * header position. just after the data packet header
+ *
+ * c: 1 bit: 0 8bit encoding, 1 16bit encoding
+ * #pkts: 7 bits: number of application packets contained
+ * 8bits encoding:
+ * lenX: 8 bits: len in bites of packet X
+ * 16bits econding:
+ * resv: 8 bits: reserved field (unused)
+ * lenX: 16bits: len in bytes of packet X
+ */
+
#pragma once
#ifndef _WIN32
#include <arpa/inet.h>
@@ -31,6 +52,8 @@
#include <hicn/transport/portability/win_portability.h>
#endif
+#include <cstring>
+
namespace transport {
namespace protocol {
@@ -82,8 +105,144 @@ struct nack_packet_t {
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); }
+ inline uint32_t getProductionSegment() const { return ntohl(prod_seg); }
+ inline void setProductionSegment(uint32_t seg) { prod_seg = htonl(seg); }
+};
+
+class AggrPktHeader {
+ public:
+ // XXX buf always point to the payload after the data header
+ AggrPktHeader(uint8_t *buf, uint16_t max_packet_len, uint16_t pkt_number)
+ : buf_(buf), pkt_num_(pkt_number) {
+ *buf_ = 0; // reset the first byte to correctly add the header
+ // encoding and the packet number
+ if (max_packet_len > 0xff) {
+ setAggrPktEncoding16bit();
+ } else {
+ setAggrPktEncoding8bit();
+ }
+ setAggrPktNUmber(pkt_number);
+ header_len_ = computeHeaderLen();
+ memset(buf_ + 1, 0, header_len_ - 1);
+ }
+
+ // XXX buf always point to the payload after the data header
+ AggrPktHeader(uint8_t *buf) : buf_(buf) {
+ encoding_ = getAggrPktEncoding();
+ pkt_num_ = getAggrPktNumber();
+ header_len_ = computeHeaderLen();
+ }
+
+ ~AggrPktHeader(){};
+
+ int addPacketToHeader(uint8_t index, uint16_t len) {
+ if (index > pkt_num_) return -1;
+
+ setAggrPktLen(index, len);
+ return 0;
+ }
+
+ int getPointerToPacket(uint8_t index, uint8_t **pkt_ptr, uint16_t *pkt_len) {
+ if (index > pkt_num_) return -1;
+
+ uint16_t len = 0;
+ for (int i = 0; i < index; i++)
+ len += getAggrPktLen(i); // sum the pkts len from 0 to index - 1
+
+ uint16_t offset = len + header_len_;
+ *pkt_ptr = buf_ + offset;
+ *pkt_len = getAggrPktLen(index);
+ return 0;
+ }
+
+ int getPacketOffsets(uint8_t index, uint16_t *pkt_offset, uint16_t *pkt_len) {
+ if (index > pkt_num_) return -1;
+
+ uint16_t len = 0;
+ for (int i = 0; i < index; i++)
+ len += getAggrPktLen(i); // sum the pkts len from 0 to index - 1
+
+ uint16_t offset = len + header_len_;
+ *pkt_offset = offset;
+ *pkt_len = getAggrPktLen(index);
+
+ return 0;
+ }
+
+ uint8_t *getPayloadAppendPtr() { return buf_ + header_len_; }
+
+ uint16_t getHeaderLen() { return header_len_; }
+
+ uint8_t getNumberOfPackets() { return pkt_num_; }
+
+ private:
+ inline uint16_t computeHeaderLen() const {
+ uint16_t len = 4; // min len in bytes
+ if (!encoding_) {
+ while (pkt_num_ >= len) {
+ len += 4;
+ }
+ } else {
+ while (pkt_num_ * 2 >= len) {
+ len += 4;
+ }
+ }
+ return len;
+ }
+
+ inline uint8_t getAggrPktEncoding() const {
+ // get the first bit of the first byte
+ return (*buf_ >> 7);
+ }
+
+ inline void setAggrPktEncoding8bit() {
+ // reset the first bit of the first byte
+ encoding_ = 0;
+ *buf_ &= 0x7f;
+ }
+
+ inline void setAggrPktEncoding16bit() {
+ // set the first bit of the first byte
+ encoding_ = 1;
+ *buf_ ^= 0x80;
+ }
+
+ inline uint8_t getAggrPktNumber() const {
+ // return the first byte with the first bit = 0
+ return (*buf_ & 0x7f);
+ }
+
+ inline void setAggrPktNUmber(uint8_t val) {
+ // set the val without modifying the first bit
+ *buf_ &= 0x80; // reset everithing but the first bit
+ val &= 0x7f; // reset the first bit
+ *buf_ |= val; // or the vals, done!
+ }
+
+ inline uint16_t getAggrPktLen(uint8_t pkt_index) const {
+ pkt_index++;
+ if (!encoding_) { // 8 bits
+ return (uint16_t) * (buf_ + pkt_index);
+ } else { // 16 bits
+ uint16_t *buf_16 = (uint16_t *)buf_;
+ return ntohs(*(buf_16 + pkt_index));
+ }
+ }
+
+ inline void setAggrPktLen(uint8_t pkt_index, uint16_t len) {
+ pkt_index++;
+ if (!encoding_) { // 8 bits
+ *(buf_ + pkt_index) = (uint8_t)len;
+ } else { // 16 bits
+ uint16_t *buf_16 = (uint16_t *)buf_;
+ *(buf_16 + pkt_index) = htons(len);
+ }
+ }
+
+ uint8_t *buf_;
+ uint8_t encoding_;
+ uint8_t pkt_num_;
+ uint16_t header_len_;
};
} // end namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_rc.h b/libtransport/src/protocols/rtc/rtc_rc.h
index 34d090092..62636ce40 100644
--- a/libtransport/src/protocols/rtc/rtc_rc.h
+++ b/libtransport/src/protocols/rtc/rtc_rc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -34,11 +34,15 @@ class RTCRateControl : public std::enable_shared_from_this<RTCRateControl> {
void turnOnRateControl() { rc_on_ = true; }
void setState(std::shared_ptr<RTCState> state) { protocol_state_ = state; };
- uint32_t getCongesionWindow() { return congestion_win_; };
+ uint32_t getCongestionWindow() { return congestion_win_; };
+ bool inCongestionState() {
+ if (congestion_state_ == CongestionState::Congested) return true;
+ return false;
+ }
virtual void onNewRound(double round_len) = 0;
- virtual void onDataPacketReceived(
- const core::ContentObject &content_object) = 0;
+ virtual void onDataPacketReceived(const core::ContentObject &content_object,
+ bool compute_stats) = 0;
protected:
enum class CongestionState { Normal = 0, Underuse = 1, Congested = 2, Last };
diff --git a/libtransport/src/protocols/rtc/rtc_rc_congestion_detection.cc b/libtransport/src/protocols/rtc/rtc_rc_congestion_detection.cc
new file mode 100644
index 000000000..6cd3094b5
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_congestion_detection.cc
@@ -0,0 +1,74 @@
+/*
+ * 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 <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rc_congestion_detection.h>
+
+#include <algorithm>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCRateControlCongestionDetection::RTCRateControlCongestionDetection()
+ : rounds_without_congestion_(4), last_queue_(0) {} // must be > 3
+
+RTCRateControlCongestionDetection::~RTCRateControlCongestionDetection() {}
+
+void RTCRateControlCongestionDetection::onNewRound(double round_len) {
+ if (!rc_on_) return;
+
+ double rtt = (double)protocol_state_->getMinRTT() / MILLI_IN_A_SEC;
+ double queue = protocol_state_->getQueuing();
+
+ if (rtt == 0.0) return; // no info from the producer
+
+ if (last_queue_ == queue) {
+ // if last_queue == queue the consumer didn't receive any
+ // packet from the producer. we do not change the current congestion state.
+ // we just increase the counter of rounds whithout congestion if needed
+ // (in case of congestion the counter is already set to 0)
+ if (congestion_state_ == CongestionState::Normal)
+ rounds_without_congestion_++;
+ } else {
+ if (queue > MAX_QUEUING_DELAY) {
+ // here we detect congestion.
+ congestion_state_ = CongestionState::Congested;
+ rounds_without_congestion_ = 0;
+ } else {
+ // wait 3 rounds before switch back to no congestion
+ if (rounds_without_congestion_ > 3) {
+ // nothing bad is happening
+ congestion_state_ = CongestionState::Normal;
+ }
+ rounds_without_congestion_++;
+ }
+ last_queue_ = queue;
+ }
+}
+
+void RTCRateControlCongestionDetection::onDataPacketReceived(
+ const core::ContentObject &content_object, bool compute_stats) {
+ // nothing to do
+ return;
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_congestion_detection.h b/libtransport/src/protocols/rtc/rtc_rc_congestion_detection.h
new file mode 100644
index 000000000..9afa6c39a
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_congestion_detection.h
@@ -0,0 +1,47 @@
+/*
+ * 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/shared_ptr_utils.h>
+#include <protocols/rtc/rtc_rc.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCRateControlCongestionDetection : public RTCRateControl {
+ public:
+ RTCRateControlCongestionDetection();
+
+ ~RTCRateControlCongestionDetection();
+
+ void onNewRound(double round_len);
+ void onDataPacketReceived(const core::ContentObject &content_object,
+ bool compute_stats);
+
+ auto shared_from_this() { return utils::shared_from(this); }
+
+ private:
+ uint32_t rounds_without_congestion_;
+ double last_queue_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_iat.cc b/libtransport/src/protocols/rtc/rtc_rc_iat.cc
new file mode 100644
index 000000000..f06f377f3
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_iat.cc
@@ -0,0 +1,287 @@
+/*
+ * 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 <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rc_iat.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCRateControlIAT::RTCRateControlIAT()
+ : rounds_since_last_drop_(0),
+ rounds_without_congestion_(0),
+ rounds_with_congestion_(0),
+ last_queue_(0),
+ last_rcv_time_(0),
+ last_prod_time_(0),
+ last_seq_number_(0),
+ target_rate_avg_(0),
+ round_index_(0),
+ congestion_cause_(CongestionCause::UNKNOWN) {}
+
+RTCRateControlIAT::~RTCRateControlIAT() {}
+
+void RTCRateControlIAT::onNewRound(double round_len) {
+ if (!rc_on_) return;
+
+ double received_rate = protocol_state_->getReceivedRate() +
+ protocol_state_->getRecoveredFecRate();
+
+ double target_rate =
+ protocol_state_->getProducerRate(); // * PRODUCTION_RATE_FRACTION;
+ double rtt = (double)protocol_state_->getMinRTT() / MILLI_IN_A_SEC;
+ // double packet_size = protocol_state_->getAveragePacketSize();
+ double queue = protocol_state_->getQueuing();
+
+ if (rtt == 0.0) return; // no info from the producer
+
+ CongestionState prev_congestion_state = congestion_state_;
+
+ target_rate_avg_ = target_rate_avg_ * (1 - MOVING_AVG_ALPHA) +
+ target_rate * MOVING_AVG_ALPHA;
+
+ if (prev_congestion_state == CongestionState::Congested) {
+ if (queue > MAX_QUEUING_DELAY || last_queue_ == queue) {
+ congestion_state_ = CongestionState::Congested;
+
+ received_rate_.push_back(received_rate);
+ target_rate_.push_back(target_rate);
+
+ // We assume the cause does not change
+ // Note that the first assumption about the cause could be wrong
+ // the cause of congestion could change
+ if (congestion_cause_ == CongestionCause::UNKNOWN)
+ if (rounds_with_congestion_ >= 1)
+ congestion_cause_ = apply_classification_tree(
+ rounds_with_congestion_ > ROUND_TO_WAIT_FORCE_DECISION);
+
+ rounds_with_congestion_++;
+ } else {
+ congestion_state_ = CongestionState::Normal;
+
+ // clear past history
+ reset_congestion_statistics();
+
+ // TODO maybe we can use some of these values for the stdev of the
+ // congestion mode
+ for (int i = 0; i < ROUND_HISTORY_SIZE; i++) {
+ iat_on_hold_[i].clear();
+ }
+ }
+ } else if (queue > MAX_QUEUING_DELAY) {
+ if (prev_congestion_state == CongestionState::Normal) {
+ rounds_with_congestion_ = 0;
+
+ if (rounds_without_congestion_ > ROUND_TO_RESET_CAUSE)
+ congestion_cause_ = CongestionCause::UNKNOWN;
+ }
+ congestion_state_ = CongestionState::Congested;
+ received_rate_.push_back(received_rate);
+ target_rate_.push_back(target_rate);
+ } else {
+ // nothing bad is happening
+ congestion_state_ = CongestionState::Normal;
+ reset_congestion_statistics();
+
+ int past_index = (round_index_ + 1) % ROUND_HISTORY_SIZE;
+ for (std::vector<double>::iterator it = iat_on_hold_[past_index].begin();
+ it != iat_on_hold_[past_index].end(); ++it) {
+ congestion_free_iat_.push_back(*it);
+ if (congestion_free_iat_.size() > 50) {
+ congestion_free_iat_.erase(congestion_free_iat_.begin());
+ }
+ }
+ iat_on_hold_[past_index].clear();
+ round_index_ = (round_index_ + 1) % ROUND_HISTORY_SIZE;
+ }
+
+ last_queue_ = queue;
+
+ if (congestion_state_ == CongestionState::Congested) {
+ if (prev_congestion_state == CongestionState::Normal) {
+ // init the congetion window using the received rate
+ // disabling for the moment the congestion window setup
+ // congestion_win_ = (uint32_t)ceil(received_rate * rtt / packet_size);
+ rounds_since_last_drop_ = ROUNDS_BEFORE_TAKE_ACTION + 1;
+ }
+
+ if (rounds_since_last_drop_ >= ROUNDS_BEFORE_TAKE_ACTION) {
+ // disabling for the moment the congestion window setup
+ // uint32_t win = congestion_win_ * WIN_DECREASE_FACTOR;
+ // congestion_win_ = std::max(win, WIN_MIN);
+ rounds_since_last_drop_ = 0;
+ return;
+ }
+
+ rounds_since_last_drop_++;
+ }
+
+ if (congestion_state_ == CongestionState::Normal) {
+ if (prev_congestion_state == CongestionState::Congested) {
+ rounds_without_congestion_ = 0;
+ }
+
+ rounds_without_congestion_++;
+ if (rounds_without_congestion_ < ROUNDS_BEFORE_TAKE_ACTION) return;
+
+ // disabling for the moment the congestion window setup
+ // congestion_win_ = congestion_win_ * WIN_INCREASE_FACTOR;
+ // congestion_win_ = std::min(congestion_win_, INITIAL_WIN_MAX);
+ }
+
+ if (received_rate_.size() > 1000)
+ received_rate_.erase(received_rate_.begin());
+ if (target_rate_.size() > 1000) target_rate_.erase(target_rate_.begin());
+}
+
+void RTCRateControlIAT::onDataPacketReceived(
+ const core::ContentObject &content_object, bool compute_stats) {
+ core::ParamsRTC params = RTCState::getDataParams(content_object);
+
+ uint64_t now = utils::SteadyTime::nowMs().count();
+
+ uint32_t segment_number = content_object.getName().getSuffix();
+
+ if (segment_number == (last_seq_number_ + 1) && compute_stats) {
+ uint64_t iat = now - last_rcv_time_;
+ uint64_t ist = params.timestamp - last_prod_time_;
+ if (now >= last_rcv_time_ && params.timestamp > last_prod_time_) {
+ if (iat >= ist && ist < MIN_IST_VALUE) {
+ if (congestion_state_ == CongestionState::Congested) {
+ iat_.push_back((iat - ist));
+ } else {
+ // no congestion, but we do not always add new values, but only when
+ // there is no sign of congestion
+ double queue = protocol_state_->getQueuing();
+ if (queue <= CONGESTION_FREE_QUEUEING_DELAY) {
+ iat_on_hold_[round_index_].push_back((iat - ist));
+ }
+ }
+ }
+ }
+ }
+
+ last_seq_number_ = segment_number;
+ last_rcv_time_ = now;
+ last_prod_time_ = params.timestamp;
+
+ if (iat_.size() > 1000) iat_.erase(iat_.begin());
+ return;
+}
+
+CongestionCause RTCRateControlIAT::apply_classification_tree(bool force_reply) {
+ if (iat_.size() <= 2 || received_rate_.size() < 2)
+ return CongestionCause::UNKNOWN;
+
+ double received_ratio = 0;
+ double iat_ratio = 0;
+ double iat_stdev = compute_iat_stdev(iat_);
+ double iat_congestion_free_stdev = compute_iat_stdev(congestion_free_iat_);
+
+ double iat_avg = 0.0;
+
+ double recv_avg = 0.0;
+ double recv_max = 0.0;
+
+ double target_rate_avg = 0.0;
+
+ int counter = 0;
+ std::vector<double>::reverse_iterator target_it = target_rate_.rbegin();
+ for (std::vector<double>::reverse_iterator it = received_rate_.rbegin();
+ it != received_rate_.rend(); ++it) {
+ recv_avg += *it;
+ target_rate_avg += *target_it;
+ if (counter < ROUND_HISTORY_SIZE)
+ if (recv_max < *it) {
+ recv_max = *it; // we consider only the last 2 seconds
+ }
+ counter++;
+ target_it++;
+ }
+ recv_avg = recv_avg / received_rate_.size();
+ target_rate_avg = target_rate_avg / target_rate_.size();
+
+ for (std::vector<double>::iterator it = iat_.begin(); it != iat_.end();
+ ++it) {
+ iat_avg += *it;
+ }
+ iat_avg = iat_avg / iat_.size();
+
+ double congestion_free_iat_avg = 0.0;
+ for (std::vector<double>::iterator it = congestion_free_iat_.begin();
+ it != congestion_free_iat_.end(); ++it) {
+ congestion_free_iat_avg += *it;
+ }
+ congestion_free_iat_avg =
+ congestion_free_iat_avg / congestion_free_iat_.size();
+
+ received_ratio = recv_avg / target_rate_avg;
+
+ iat_ratio = iat_stdev / iat_congestion_free_stdev;
+
+ CongestionCause congestion_cause = CongestionCause::UNKNOWN;
+ // applying classification tree model
+ if (received_ratio <= 0.87)
+ if (iat_stdev <= 6.48)
+ if (received_ratio <= 0.83)
+ congestion_cause = CongestionCause::LINK_CAPACITY;
+ else if (force_reply)
+ congestion_cause = CongestionCause::LINK_CAPACITY;
+ else
+ congestion_cause = CongestionCause::UNKNOWN; // accuracy is too low
+ else if (iat_ratio <= 2.46)
+ if (force_reply)
+ congestion_cause = CongestionCause::LINK_CAPACITY;
+ else
+ congestion_cause = CongestionCause::UNKNOWN; // accuracy is too low
+ else
+ congestion_cause = CongestionCause::COMPETING_CROSS_TRAFFIC;
+ else if (received_ratio <= 0.913 && iat_stdev <= 0.784)
+ congestion_cause = CongestionCause::LINK_CAPACITY;
+ else
+ congestion_cause = CongestionCause::COMPETING_CROSS_TRAFFIC;
+
+ return congestion_cause;
+}
+
+void RTCRateControlIAT::reset_congestion_statistics() {
+ iat_.clear();
+ received_rate_.clear();
+ target_rate_.clear();
+}
+
+double RTCRateControlIAT::compute_iat_stdev(std::vector<double> v) {
+ if (v.size() == 0) return 0;
+
+ float sum = 0.0, mean, standard_deviation = 0.0;
+ for (std::vector<double>::iterator it = v.begin(); it != v.end(); it++) {
+ sum += *it;
+ }
+
+ mean = sum / v.size();
+ for (std::vector<double>::iterator it = v.begin(); it != v.end(); it++) {
+ standard_deviation += pow(*it - mean, 2);
+ }
+ return sqrt(standard_deviation / v.size());
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_iat.h b/libtransport/src/protocols/rtc/rtc_rc_iat.h
new file mode 100644
index 000000000..715637807
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_iat.h
@@ -0,0 +1,93 @@
+/*
+ * 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/shared_ptr_utils.h>
+#include <protocols/rtc/rtc_rc.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+const int ROUND_HISTORY_SIZE = 10; // equivalent to two seconds
+const int ROUND_TO_WAIT_FORCE_DECISION = 5;
+
+// once congestion is gone, we need to wait for k rounds before changing the
+// congestion cause in the case it appears again
+const int ROUND_TO_RESET_CAUSE = 5;
+
+const int MIN_IST_VALUE = 150; // samples of ist larger than 150ms are
+ // discarded
+const double CONGESTION_FREE_QUEUEING_DELAY = 10;
+
+enum class CongestionCause : uint8_t {
+ COMPETING_CROSS_TRAFFIC,
+ FRIENDLY_CROSS_TRAFFIC,
+ UNKNOWN_CROSS_TRAFFIC,
+ LINK_CAPACITY,
+ UNKNOWN
+};
+
+class RTCRateControlIAT : public RTCRateControl {
+ public:
+ RTCRateControlIAT();
+
+ ~RTCRateControlIAT();
+
+ void onNewRound(double round_len);
+ void onDataPacketReceived(const core::ContentObject &content_object,
+ bool compute_stats);
+
+ auto shared_from_this() { return utils::shared_from(this); }
+
+ private:
+ void reset_congestion_statistics();
+
+ double compute_iat_stdev(std::vector<double> v);
+
+ CongestionCause apply_classification_tree(bool force_reply);
+
+ private:
+ uint32_t rounds_since_last_drop_;
+ uint32_t rounds_without_congestion_;
+ uint32_t rounds_with_congestion_;
+ double last_queue_;
+ uint64_t last_rcv_time_;
+ uint64_t last_prod_time_;
+ uint32_t last_seq_number_;
+ double target_rate_avg_;
+
+ // Iat values are not immediately added to the congestion free set of values
+ std::array<std::vector<double>, ROUND_HISTORY_SIZE> iat_on_hold_;
+ uint32_t round_index_;
+
+ // with congestion statistics
+ std::vector<double> iat_;
+ std::vector<double> received_rate_;
+ std::vector<double> target_rate_;
+
+ // congestion free statistics
+ std::vector<double> congestion_free_iat_;
+
+ CongestionCause congestion_cause_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_queue.cc b/libtransport/src/protocols/rtc/rtc_rc_queue.cc
index a1c89e329..ecabc5205 100644
--- a/libtransport/src/protocols/rtc/rtc_rc_queue.cc
+++ b/libtransport/src/protocols/rtc/rtc_rc_queue.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -37,7 +37,7 @@ void RTCRateControlQueue::onNewRound(double round_len) {
double received_rate = protocol_state_->getReceivedRate();
double target_rate =
protocol_state_->getProducerRate() * PRODUCTION_RATE_FRACTION;
- double rtt = (double)protocol_state_->getRTT() / MILLI_IN_A_SEC;
+ double rtt = (double)protocol_state_->getMinRTT() / MILLI_IN_A_SEC;
double packet_size = protocol_state_->getAveragePacketSize();
double queue = protocol_state_->getQueuing();
@@ -94,7 +94,7 @@ void RTCRateControlQueue::onNewRound(double round_len) {
}
void RTCRateControlQueue::onDataPacketReceived(
- const core::ContentObject &content_object) {
+ const core::ContentObject &content_object, bool compute_stats) {
// nothing to do
return;
}
diff --git a/libtransport/src/protocols/rtc/rtc_rc_queue.h b/libtransport/src/protocols/rtc/rtc_rc_queue.h
index 407354d43..cdf78fd47 100644
--- a/libtransport/src/protocols/rtc/rtc_rc_queue.h
+++ b/libtransport/src/protocols/rtc/rtc_rc_queue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -30,7 +30,8 @@ class RTCRateControlQueue : public RTCRateControl {
~RTCRateControlQueue();
void onNewRound(double round_len);
- void onDataPacketReceived(const core::ContentObject &content_object);
+ void onDataPacketReceived(const core::ContentObject &content_object,
+ bool compute_stats);
auto shared_from_this() { return utils::shared_from(this); }
diff --git a/libtransport/src/protocols/rtc/rtc_reassembly.cc b/libtransport/src/protocols/rtc/rtc_reassembly.cc
new file mode 100644
index 000000000..992bab50e
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_reassembly.cc
@@ -0,0 +1,109 @@
+/*
+ * 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_consumer.h>
+#include <implementation/socket_consumer.h>
+#include <protocols/rtc/rtc_reassembly.h>
+#include <protocols/transport_protocol.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RtcReassembly::RtcReassembly(implementation::ConsumerSocket* icn_socket,
+ TransportProtocol* transport_protocol)
+ : DatagramReassembly(icn_socket, transport_protocol) {
+ is_setup_ = false;
+}
+
+void RtcReassembly::reassemble(core::ContentObject& content_object) {
+ if (!is_setup_) {
+ is_setup_ = true;
+ reassembly_consumer_socket_->getSocketOption(
+ interface::RtcTransportOptions::AGGREGATED_DATA, data_aggregation_);
+ }
+
+ 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());
+
+ if (data_aggregation_) {
+ rtc::AggrPktHeader hdr((uint8_t*)read_buffer->data());
+
+ for (uint8_t i = 0; i < hdr.getNumberOfPackets(); i++) {
+ std::unique_ptr<utils::MemBuf> segment = read_buffer->clone();
+
+ uint16_t pkt_start = 0;
+ uint16_t pkt_len = 0;
+ int res = hdr.getPacketOffsets(i, &pkt_start, &pkt_len);
+ if (res == -1) {
+ // this should not happen
+ break;
+ }
+
+ segment->trimStart(pkt_start);
+ segment->trimEnd(segment->length() - pkt_len);
+
+ Reassembly::read_buffer_ = std::move(segment);
+ Reassembly::notifyApplication();
+ }
+ } else {
+ Reassembly::read_buffer_ = std::move(read_buffer);
+ Reassembly::notifyApplication();
+ }
+}
+
+void RtcReassembly::reassemble(utils::MemBuf& buffer, uint32_t suffix) {
+ if (!is_setup_) {
+ is_setup_ = true;
+ reassembly_consumer_socket_->getSocketOption(
+ interface::RtcTransportOptions::AGGREGATED_DATA, data_aggregation_);
+ }
+
+ if (data_aggregation_) {
+ rtc::AggrPktHeader hdr((uint8_t*)buffer.data());
+
+ for (uint8_t i = 0; i < hdr.getNumberOfPackets(); i++) {
+ std::unique_ptr<utils::MemBuf> segment = buffer.clone();
+
+ uint16_t pkt_start = 0;
+ uint16_t pkt_len = 0;
+ int res = hdr.getPacketOffsets(i, &pkt_start, &pkt_len);
+ if (res == -1) {
+ // this should not happen
+ break;
+ }
+
+ segment->trimStart(pkt_start);
+ segment->trimEnd(segment->length() - pkt_len);
+
+ Reassembly::read_buffer_ = std::move(segment);
+ Reassembly::notifyApplication();
+ }
+
+ } else {
+ Reassembly::read_buffer_ = buffer.cloneOne();
+ Reassembly::notifyApplication();
+ }
+}
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_reassembly.h b/libtransport/src/protocols/rtc/rtc_reassembly.h
index 15722a6d5..132004605 100644
--- a/libtransport/src/protocols/rtc/rtc_reassembly.h
+++ b/libtransport/src/protocols/rtc/rtc_reassembly.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -28,17 +28,14 @@ namespace rtc {
class RtcReassembly : public DatagramReassembly {
public:
RtcReassembly(implementation::ConsumerSocket *icn_socket,
- TransportProtocol *transport_protocol)
- : DatagramReassembly(icn_socket, transport_protocol) {}
-
- void reassemble(core::ContentObject &content_object) override {
- 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());
- Reassembly::read_buffer_ = std::move(read_buffer);
- Reassembly::notifyApplication();
- }
+ TransportProtocol *transport_protocol);
+
+ void reassemble(core::ContentObject &content_object) override;
+ void reassemble(utils::MemBuf &buffer, uint32_t suffix) override;
+
+ private:
+ bool is_setup_;
+ bool data_aggregation_;
};
} // namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc b/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc
new file mode 100644
index 000000000..888105eab
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc
@@ -0,0 +1,418 @@
+/*
+ * 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 <hicn/transport/interfaces/notification.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_recovery_strategy.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+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),
+ next_rtx_timer_(MAX_TIMER_RTX),
+ send_rtx_callback_(std::move(callback)),
+ indexer_(indexer),
+ round_id_(0),
+ last_fec_used_(0),
+ callback_(external_callback) {
+ setRtxFec(use_rtx, use_fec);
+ timer_ = std::make_unique<asio::steady_timer>(io_service);
+}
+
+RecoveryStrategy::RecoveryStrategy(RecoveryStrategy &&rs)
+ : rtx_state_(std::move(rs.rtx_state_)),
+ rtx_timers_(std::move(rs.rtx_timers_)),
+ recover_with_fec_(std::move(rs.recover_with_fec_)),
+ timer_(std::move(rs.timer_)),
+ next_rtx_timer_(std::move(rs.next_rtx_timer_)),
+ send_rtx_callback_(std::move(rs.send_rtx_callback_)),
+ n_(std::move(rs.n_)),
+ k_(std::move(rs.k_)),
+ indexer_(std::move(rs.indexer_)),
+ state_(std::move(rs.state_)),
+ rc_(std::move(rs.rc_)),
+ round_id_(std::move(rs.round_id_)),
+ last_fec_used_(std::move(rs.last_fec_used_)),
+ callback_(rs.callback_) {
+ setFecParams(n_, k_);
+}
+
+RecoveryStrategy::~RecoveryStrategy() {}
+
+void RecoveryStrategy::setFecParams(uint32_t n, uint32_t k) {
+ n_ = n;
+ k_ = k;
+
+ // XXX for the moment we go in steps of 5% loss rate.
+ // max loss rate = 95%
+ 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));
+
+ 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);
+ }
+}
+
+bool RecoveryStrategy::lossDetected(uint32_t seq) {
+ if (isRtx(seq)) {
+ // this packet is already in the list of rtx
+ return false;
+ }
+
+ auto it = recover_with_fec_.find(seq);
+ if (it != recover_with_fec_.end()) {
+ // this packet is already in list of packets to recover with fec
+ // this list contians also fec packets that will not be recovered with rtx
+ return false;
+ }
+
+ // new loss detected, recover it according to the strategy
+ newPacketLoss(seq);
+ return true;
+}
+
+void RecoveryStrategy::clear() {
+ rtx_state_.clear();
+ rtx_timers_.clear();
+ recover_with_fec_.clear();
+
+ if (next_rtx_timer_ != MAX_TIMER_RTX) {
+ next_rtx_timer_ = MAX_TIMER_RTX;
+ timer_->cancel();
+ }
+}
+
+// rtx functions
+void RecoveryStrategy::addNewRtx(uint32_t seq, bool force) {
+ if (!indexer_->isFec(seq) || force) {
+ // this packet needs to be re-transmitted
+ rtxState state;
+ state.first_send_ = state_->getInterestSentTime(seq);
+ if (state.first_send_ == 0) // this interest was never sent before
+ state.first_send_ = getNow();
+ state.next_send_ = computeNextSend(seq, true);
+ state.rtx_count_ = 0;
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Add " << seq << " to retransmissions. next rtx is in "
+ << state.next_send_ - getNow() << " ms";
+ rtx_state_.insert(std::pair<uint32_t, rtxState>(seq, state));
+ rtx_timers_.insert(std::pair<uint64_t, uint32_t>(state.next_send_, seq));
+
+ // if a new rtx is introduced, check the rtx timer
+ scheduleNextRtx();
+ } else {
+ // do not re-send fec packets but keep track of them
+ recover_with_fec_.insert(seq);
+ state_->onPossibleLossWithNoRtx(seq);
+ }
+}
+
+uint64_t RecoveryStrategy::computeNextSend(uint32_t seq, bool new_rtx) {
+ uint64_t now = getNow();
+ if (new_rtx) {
+ // for the new rtx we wait one estimated IAT after the loss detection. this
+ // is bacause, assuming that packets arrive with a constant IAT, we should
+ // get a new packet every IAT
+ double prod_rate = state_->getProducerRate();
+ uint32_t estimated_iat = SENTINEL_TIMER_INTERVAL;
+ uint32_t jitter = 0;
+
+ if (prod_rate != 0) {
+ double packet_size = state_->getAveragePacketSize();
+ estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
+ 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;
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "first rtx for " << seq << " in " << wait
+ << " ms, rtt = " << state_->getMinRTT() << " ait = " << estimated_iat
+ << " jttr = " << jitter;
+
+ return now + wait;
+ } else {
+ // wait one RTT
+ uint32_t wait = SENTINEL_TIMER_INTERVAL;
+
+ double prod_rate = state_->getProducerRate();
+ if (prod_rate == 0) {
+ return now + SENTINEL_TIMER_INTERVAL;
+ }
+
+ double packet_size = state_->getAveragePacketSize();
+ uint32_t estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
+
+ uint64_t rtt = state_->getMinRTT();
+ if (rtt == 0) rtt = SENTINEL_TIMER_INTERVAL;
+ wait = 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;
+
+ return now + wait;
+ }
+}
+
+void RecoveryStrategy::retransmit() {
+ if (rtx_timers_.size() == 0) return;
+
+ uint64_t now = getNow();
+
+ auto it = rtx_timers_.begin();
+ std::unordered_set<uint32_t> lost_pkt;
+ uint32_t sent_counter = 0;
+ while (it != rtx_timers_.end() && it->first <= now &&
+ sent_counter < MAX_RTX_IN_BATCH) {
+ uint32_t seq = it->second;
+ auto rtx_it =
+ rtx_state_.find(seq); // this should always return a valid iter
+ if (rtx_it->second.rtx_count_ >= RTC_MAX_RTX ||
+ (now - rtx_it->second.first_send_) >= RTC_MAX_AGE ||
+ seq < state_->getLastSeqNacked()) {
+ // max rtx reached or packet too old or packet nacked, this packet is lost
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "packet " << seq << " lost because 1) max rtx: "
+ << (rtx_it->second.rtx_count_ >= RTC_MAX_RTX) << " 2) max age: "
+ << ((now - rtx_it->second.first_send_) >= RTC_MAX_AGE)
+ << " 3) nacked: " << (seq < state_->getLastSeqNacked());
+ lost_pkt.insert(seq);
+ it++;
+ } else {
+ // resend the packet
+ state_->onRetransmission(seq);
+ double prod_rate = state_->getProducerRate();
+ if (prod_rate != 0) rtx_it->second.rtx_count_++;
+ rtx_it->second.next_send_ = computeNextSend(seq, false);
+ it = rtx_timers_.erase(it);
+ rtx_timers_.insert(
+ std::pair<uint64_t, uint32_t>(rtx_it->second.next_send_, seq));
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "send rtx for sequence " << seq << ", next send in "
+ << (rtx_it->second.next_send_ - now);
+ send_rtx_callback_(seq);
+ sent_counter++;
+ }
+ }
+
+ // remove packets if needed
+ for (auto lost_it = lost_pkt.begin(); lost_it != lost_pkt.end(); lost_it++) {
+ uint32_t seq = *lost_it;
+ state_->onPacketLost(seq);
+ deleteRtx(seq);
+ }
+}
+
+void RecoveryStrategy::scheduleNextRtx() {
+ if (rtx_timers_.size() == 0) {
+ // all the rtx were removed, reset timer
+ next_rtx_timer_ = MAX_TIMER_RTX;
+ return;
+ }
+
+ // check if timer is alreay set
+ if (next_rtx_timer_ != MAX_TIMER_RTX) {
+ // a new check for rtx is already scheduled
+ if (next_rtx_timer_ > rtx_timers_.begin()->first) {
+ // we need to re-schedule it
+ timer_->cancel();
+ } else {
+ // wait for the next timer
+ return;
+ }
+ }
+
+ // set a new timer
+ next_rtx_timer_ = rtx_timers_.begin()->first;
+ uint64_t now = utils::SteadyTime::nowMs().count();
+ uint64_t wait = 1;
+ if (next_rtx_timer_ != MAX_TIMER_RTX && next_rtx_timer_ > now)
+ wait = next_rtx_timer_ - now;
+
+ std::weak_ptr<RecoveryStrategy> self(shared_from_this());
+ timer_->expires_from_now(std::chrono::milliseconds(wait));
+ timer_->async_wait([self](const std::error_code &ec) {
+ if (ec) return;
+ if (auto s = self.lock()) {
+ s->retransmit();
+ s->next_rtx_timer_ = MAX_TIMER_RTX;
+ s->scheduleNextRtx();
+ }
+ });
+}
+
+void RecoveryStrategy::deleteRtx(uint32_t seq) {
+ auto it_rtx = rtx_state_.find(seq);
+ if (it_rtx == rtx_state_.end()) return; // rtx not found
+
+ // remove the rtx from the timers list
+ uint64_t ts = it_rtx->second.next_send_;
+ auto it_timers = rtx_timers_.find(ts);
+ while (it_timers != rtx_timers_.end() && it_timers->first == ts) {
+ if (it_timers->second == seq) {
+ rtx_timers_.erase(it_timers);
+ break;
+ }
+ it_timers++;
+ }
+ // remove rtx
+ rtx_state_.erase(it_rtx);
+}
+
+// fec functions
+uint32_t RecoveryStrategy::computeFecPacketsToAsk(bool in_sync) {
+ double loss_rate = state_->getMaxLossRate() * 100; // use loss rate in %
+
+ if (loss_rate > 95) loss_rate = 95; // max loss rate
+
+ 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 != 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;
+}
+
+void RecoveryStrategy::setRtxFec(std::optional<bool> rtx_on,
+ std::optional<bool> fec_on) {
+ if (rtx_on) rtx_on_ = *rtx_on;
+ if (fec_on) fec_on_ = *fec_on;
+
+ if (*callback_) {
+ notification::RecoveryStrategy strategy =
+ notification::RecoveryStrategy::RECOVERY_OFF;
+
+ if (rtx_on_ && fec_on_)
+ strategy = notification::RecoveryStrategy::RTX_AND_FEC;
+ else if (rtx_on_)
+ strategy = notification::RecoveryStrategy::RTX_ONLY;
+ else if (fec_on_)
+ strategy = notification::RecoveryStrategy::FEC_ONLY;
+
+ (*callback_)(strategy);
+ }
+}
+
+// common functions
+void RecoveryStrategy::onLostTimeout(uint32_t seq) { removePacketState(seq); }
+
+void RecoveryStrategy::removePacketState(uint32_t seq) {
+ auto it_fec = recover_with_fec_.find(seq);
+ if (it_fec != recover_with_fec_.end()) {
+ recover_with_fec_.erase(it_fec);
+ return;
+ }
+
+ 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--;
+ // std::cout << "reduce fec to ask for bin " << bin << std::endl;
+ }
+ }
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_recovery_strategy.h b/libtransport/src/protocols/rtc/rtc_recovery_strategy.h
new file mode 100644
index 000000000..9ffc69a1b
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_recovery_strategy.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <hicn/transport/interfaces/callbacks.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
+#include <protocols/indexer.h>
+#include <protocols/rtc/rtc_rc.h>
+#include <protocols/rtc/rtc_state.h>
+
+#include <map>
+#include <unordered_map>
+
+namespace transport {
+
+namespace protocol {
+
+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_;
+ };
+
+ using rtxState = struct rtx_state_;
+
+ public:
+ using SendRtxCallback = std::function<void(uint32_t)>;
+
+ RecoveryStrategy(Indexer *indexer, SendRtxCallback &&callback,
+ asio::io_service &io_service, bool use_rtx, bool use_fec,
+ interface::StrategyCallback *external_callback);
+
+ RecoveryStrategy(RecoveryStrategy &&rs);
+
+ virtual ~RecoveryStrategy();
+
+ void setRtxFec(std::optional<bool> rtx_on = {},
+ std::optional<bool> fec_on = {});
+ void setState(RTCState *state) { state_ = state; }
+ void setRateControl(RTCRateControl *rateControl) { rc_ = rateControl; }
+ void setFecParams(uint32_t n, uint32_t k);
+
+ void tunrOnRecovery() { recovery_on_ = true; }
+
+ bool isRtx(uint32_t seq) {
+ if (rtx_state_.find(seq) != rtx_state_.end()) return true;
+ return false;
+ }
+
+ bool isPossibleLossWithNoRtx(uint32_t seq) {
+ if (recover_with_fec_.find(seq) != recover_with_fec_.end()) return true;
+ return false;
+ }
+
+ bool isRtxOn() { return rtx_on_; }
+
+ RTCState *getState() { return state_; }
+ bool lossDetected(uint32_t seq);
+ void clear();
+
+ virtual void onNewRound(bool in_sync) = 0;
+ virtual void newPacketLoss(uint32_t seq) = 0;
+ virtual void receivedPacket(uint32_t seq) = 0;
+ void onLostTimeout(uint32_t seq);
+
+ void incRoundId() { round_id_++; }
+
+ // utils
+ uint64_t getNow() {
+ uint64_t now = utils::SteadyTime::nowMs().count();
+ return now;
+ }
+
+ protected:
+ // rtx functions
+ void addNewRtx(uint32_t seq, bool force);
+ uint64_t computeNextSend(uint32_t seq, bool new_rtx);
+ void retransmit();
+ void scheduleNextRtx();
+ void deleteRtx(uint32_t seq);
+
+ // fec functions
+ uint32_t computeFecPacketsToAsk(bool in_sync);
+
+ // common functons
+ void removePacketState(uint32_t seq);
+
+ bool recovery_on_;
+ bool rtx_on_;
+ bool fec_on_;
+
+ // this map keeps track of the retransmitted interest, ordered from the oldest
+ // to the newest one. the state contains the timer of the first send of the
+ // interest (from pendingIntetests_), the timer of the next send (key of the
+ // multimap) and the number of rtx
+ std::map<uint32_t, rtxState> rtx_state_;
+ // this map stored the rtx by timer. The key is the time at which the rtx
+ // should be sent, and the val is the interest seq number
+ std::multimap<uint64_t, uint32_t> rtx_timers_;
+
+ // lost packets that will be recovered with fec
+ std::unordered_set<uint32_t> recover_with_fec_;
+
+ // rtx vars
+ std::unique_ptr<asio::steady_timer> timer_;
+ uint64_t next_rtx_timer_;
+ SendRtxCallback send_rtx_callback_;
+
+ // fec vars
+ uint32_t n_;
+ uint32_t k_;
+ Indexer *indexer_;
+
+ RTCState *state_;
+ 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_;
+ interface::StrategyCallback *callback_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_delay.cc b/libtransport/src/protocols/rtc/rtc_rs_delay.cc
new file mode 100644
index 000000000..e2c60ca77
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_delay.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glog/logging.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rs_delay.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RecoveryStrategyDelayBased::RecoveryStrategyDelayBased(
+ Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::StrategyCallback *external_callback)
+ : RecoveryStrategy(indexer, std::move(callback), io_service, true, false,
+ external_callback), // start with rtx
+ congestion_state_(false),
+ probing_state_(false),
+ switch_rounds_(0) {}
+
+RecoveryStrategyDelayBased::RecoveryStrategyDelayBased(RecoveryStrategy &&rs)
+ : RecoveryStrategy(std::move(rs)) {
+ setRtxFec(true, false);
+ // we have to re-init congestion and
+ // probing
+ congestion_state_ = false;
+ probing_state_ = false;
+}
+
+RecoveryStrategyDelayBased::~RecoveryStrategyDelayBased() {}
+
+void RecoveryStrategyDelayBased::softSwitchToFec(uint32_t fec_to_ask) {
+ if (fec_to_ask == 0) {
+ setRtxFec(true, false);
+ switch_rounds_ = 0;
+ } else {
+ switch_rounds_++;
+ if (switch_rounds_ >= 5) {
+ setRtxFec(false, true);
+ } else {
+ setRtxFec({}, true);
+ }
+ }
+}
+
+void RecoveryStrategyDelayBased::onNewRound(bool in_sync) {
+ if (!recovery_on_) {
+ // disable fec so that no extra packet will be sent
+ // for rtx we check if recovery is on in newPacketLoss
+ setRtxFec(true, false);
+ indexer_->setNFec(0);
+ return;
+ }
+
+ uint64_t rtt = state_->getMinRTT();
+
+ bool congestion = false;
+ // XXX at the moment we are not looking at congestion events
+ // congestion = rc_->inCongestionState();
+
+ if ((!fec_on_ && rtt >= 100) || (fec_on_ && rtt > 80) || congestion) {
+ // 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.
+ uint32_t fec_to_ask = computeFecPacketsToAsk(in_sync);
+ softSwitchToFec(fec_to_ask);
+ indexer_->setNFec(fec_to_ask);
+ return;
+ }
+
+ if ((fec_on_ && rtt <= 80) || (!rtx_on_ && rtt <= 100)) {
+ // turn on rtx
+ softSwitchToFec(0);
+ indexer_->setNFec(0);
+ return;
+ }
+}
+
+void RecoveryStrategyDelayBased::newPacketLoss(uint32_t seq) {
+ if (rtx_on_ && recovery_on_) {
+ addNewRtx(seq, false);
+ } else {
+ if (!state_->isPending(seq) && !indexer_->isFec(seq)) {
+ addNewRtx(seq, true);
+ } else {
+ recover_with_fec_.insert(seq);
+ state_->onPossibleLossWithNoRtx(seq);
+ }
+ }
+}
+
+void RecoveryStrategyDelayBased::receivedPacket(uint32_t seq) {
+ removePacketState(seq);
+}
+
+void RecoveryStrategyDelayBased::probing() {
+ // TODO
+ // for the moment ask for all fec and exit the probing phase
+ probing_state_ = false;
+ setRtxFec(false, true);
+ indexer_->setNFec(computeFecPacketsToAsk(true));
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_delay.h b/libtransport/src/protocols/rtc/rtc_rs_delay.h
new file mode 100644
index 000000000..0dd199965
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_delay.h
@@ -0,0 +1,53 @@
+/*
+ * 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 <protocols/rtc/rtc_recovery_strategy.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RecoveryStrategyDelayBased : public RecoveryStrategy {
+ public:
+ RecoveryStrategyDelayBased(Indexer *indexer, SendRtxCallback &&callback,
+ asio::io_service &io_service,
+ interface::StrategyCallback *external_callback);
+
+ RecoveryStrategyDelayBased(RecoveryStrategy &&rs);
+
+ ~RecoveryStrategyDelayBased();
+
+ void onNewRound(bool in_sync);
+ void newPacketLoss(uint32_t seq);
+ void receivedPacket(uint32_t seq);
+
+ private:
+ void softSwitchToFec(uint32_t fec_to_ask);
+
+ bool congestion_state_;
+ bool probing_state_;
+ uint32_t switch_rounds_;
+
+ void probing();
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc b/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc
new file mode 100644
index 000000000..36d8e39f0
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc
@@ -0,0 +1,118 @@
+/*
+ * 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 <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rs_fec_only.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RecoveryStrategyFecOnly::RecoveryStrategyFecOnly(
+ Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::StrategyCallback *external_callback)
+ : RecoveryStrategy(indexer, std::move(callback), io_service, false, true,
+ external_callback),
+ congestion_state_(false),
+ probing_state_(false),
+ switch_rounds_(0) {}
+
+RecoveryStrategyFecOnly::RecoveryStrategyFecOnly(RecoveryStrategy &&rs)
+ : RecoveryStrategy(std::move(rs)) {
+ setRtxFec(false, true);
+ congestion_state_ = false;
+ probing_state_ = false;
+}
+
+RecoveryStrategyFecOnly::~RecoveryStrategyFecOnly() {}
+
+void RecoveryStrategyFecOnly::onNewRound(bool in_sync) {
+ if (!recovery_on_) {
+ indexer_->setNFec(0);
+ return;
+ }
+
+ // XXX for the moment we are considering congestion events
+ // if(rc_->inCongestionState()){
+ // congestion_state_ = true;
+ // probing_state_ = false;
+ // indexer_->setNFec(0);
+ // return;
+ // }
+
+ // no congestion
+ if (congestion_state_) {
+ // this is the first round after congestion
+ // enter probing phase
+ probing_state_ = true;
+ congestion_state_ = false;
+ }
+
+ if (probing_state_) {
+ probing();
+ } else {
+ uint32_t fec_to_ask = computeFecPacketsToAsk(in_sync);
+ // If fec_to_ask == 0 we use rtx even if in these strategy we use only fec.
+ // In this way the first packet loss that triggers the usage of fec can be
+ // recovered using rtx, otherwise it will always be lost
+ if (fec_to_ask == 0) {
+ setRtxFec(true, false);
+ switch_rounds_ = 0;
+ } else {
+ switch_rounds_++;
+ if (switch_rounds_ >= 5) {
+ setRtxFec(false, true);
+ } else {
+ setRtxFec({}, true);
+ }
+ }
+ indexer_->setNFec(fec_to_ask);
+ }
+}
+
+void RecoveryStrategyFecOnly::newPacketLoss(uint32_t seq) {
+ if (rtx_on_ && recovery_on_) {
+ addNewRtx(seq, false);
+ } else {
+ if (!state_->isPending(seq) && !indexer_->isFec(seq)) {
+ addNewRtx(seq, true);
+ } else {
+ // if not pending add rtc
+ recover_with_fec_.insert(seq);
+ state_->onPossibleLossWithNoRtx(seq);
+ }
+ }
+}
+
+void RecoveryStrategyFecOnly::receivedPacket(uint32_t seq) {
+ removePacketState(seq);
+}
+
+void RecoveryStrategyFecOnly::probing() {
+ // TODO
+ // for the moment ask for all fec and exit the probing phase
+ probing_state_ = false;
+ uint32_t fec_to_ask = computeFecPacketsToAsk(true);
+ indexer_->setNFec(fec_to_ask);
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_fec_only.h b/libtransport/src/protocols/rtc/rtc_rs_fec_only.h
new file mode 100644
index 000000000..37b505d35
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_fec_only.h
@@ -0,0 +1,51 @@
+/*
+ * 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 <protocols/rtc/rtc_recovery_strategy.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RecoveryStrategyFecOnly : public RecoveryStrategy {
+ public:
+ RecoveryStrategyFecOnly(Indexer *indexer, SendRtxCallback &&callback,
+ asio::io_service &io_service,
+ interface::StrategyCallback *external_callback);
+
+ RecoveryStrategyFecOnly(RecoveryStrategy &&rs);
+
+ ~RecoveryStrategyFecOnly();
+
+ void onNewRound(bool in_sync);
+ void newPacketLoss(uint32_t seq);
+ void receivedPacket(uint32_t seq);
+
+ private:
+ bool congestion_state_;
+ bool probing_state_;
+ uint32_t switch_rounds_;
+
+ void probing();
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc b/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc
new file mode 100644
index 000000000..bd153d209
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc
@@ -0,0 +1,167 @@
+/*
+ * 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 <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rs_low_rate.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RecoveryStrategyLowRate::RecoveryStrategyLowRate(
+ Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::StrategyCallback *external_callback)
+ : RecoveryStrategy(indexer, std::move(callback), io_service, false, true,
+ external_callback), // start with fec
+ fec_consecutive_rounds_((MILLI_IN_A_SEC / ROUND_LEN) * 5), // 5 sec
+ rtx_allowed_consecutive_rounds_(0) {
+ initSwitchVector();
+}
+
+RecoveryStrategyLowRate::RecoveryStrategyLowRate(RecoveryStrategy &&rs)
+ : RecoveryStrategy(std::move(rs)),
+ fec_consecutive_rounds_((MILLI_IN_A_SEC / ROUND_LEN) * 5), // 5 sec
+ rtx_allowed_consecutive_rounds_(0) {
+ setRtxFec(false, true);
+ initSwitchVector();
+}
+
+RecoveryStrategyLowRate::~RecoveryStrategyLowRate() {}
+
+void RecoveryStrategyLowRate::initSwitchVector() {
+ // TODO adjust thresholds here when new data are collected
+ // see resutls in
+ // https://confluence-eng-gpk1.cisco.com/conf/display/SPT/dailyreports
+ thresholds_t t1;
+ t1.rtt = 15; // 15ms
+ t1.loss_rtx_to_fec = 15; // 15%
+ t1.loss_fec_to_rtx = 10; // 10%
+ thresholds_t t2;
+ t2.rtt = 35; // 35ms
+ t2.loss_rtx_to_fec = 5; // 5%
+ t2.loss_fec_to_rtx = 1; // 1%
+ switch_vector.push_back(t1);
+ switch_vector.push_back(t2);
+}
+
+void RecoveryStrategyLowRate::setRecoveryParameters(bool use_rtx, bool use_fec,
+ uint32_t fec_to_ask) {
+ setRtxFec(use_rtx, use_fec);
+ indexer_->setNFec(fec_to_ask);
+}
+
+void RecoveryStrategyLowRate::selectRecoveryStrategy(bool in_sync) {
+ uint32_t fec_to_ask = computeFecPacketsToAsk(in_sync);
+ if (fec_to_ask == 0) {
+ // fec is off, turn on RTX immediatly to avoid packet losses
+ setRecoveryParameters(true, false, 0);
+ fec_consecutive_rounds_ = 0;
+ return;
+ }
+
+ uint32_t loss_rate = std::round(state_->getPerSecondLossRate() * 100);
+ uint32_t rtt = state_->getAvgRTT();
+
+ bool use_rtx = false;
+ for (size_t i = 0; i < switch_vector.size(); i++) {
+ uint32_t max_loss_rate = 0;
+ if (fec_on_)
+ max_loss_rate = switch_vector[i].loss_fec_to_rtx;
+ else
+ max_loss_rate = switch_vector[i].loss_rtx_to_fec;
+
+ if (rtt < switch_vector[i].rtt && loss_rate < max_loss_rate) {
+ use_rtx = true;
+ rtx_allowed_consecutive_rounds_++;
+ break;
+ }
+ }
+
+ if (!use_rtx) rtx_allowed_consecutive_rounds_ = 0;
+
+ if (use_rtx) {
+ if (fec_on_) {
+ // here we should swtich from RTX to FEC
+ // wait 10sec where the switch is allowed before actually switch
+ if (rtx_allowed_consecutive_rounds_ >=
+ ((MILLI_IN_A_SEC / ROUND_LEN) * 10)) { // 10 sec
+ // use RTX
+ setRecoveryParameters(true, false, 0);
+ fec_consecutive_rounds_ = 0;
+ } else {
+ // keep using FEC (and maybe RTX)
+ setRecoveryParameters(true, true, fec_to_ask);
+ fec_consecutive_rounds_++;
+ }
+ } else {
+ // keep using RTX
+ setRecoveryParameters(true, false, 0);
+ fec_consecutive_rounds_ = 0;
+ }
+ } else {
+ // use FEC and RTX
+ setRecoveryParameters(true, true, fec_to_ask);
+ fec_consecutive_rounds_++;
+ }
+
+ // everytime that we anable FEC we keep also RTX on. in this way the first
+ // losses that are not covered by FEC are recovered using RTX. after 5 sec we
+ // disable fec
+ if (fec_consecutive_rounds_ >= ((MILLI_IN_A_SEC / ROUND_LEN) * 5)) {
+ // turn off RTX
+ setRtxFec(false);
+ }
+}
+
+void RecoveryStrategyLowRate::onNewRound(bool in_sync) {
+ if (!recovery_on_) {
+ // disable fec so that no extra packet will be sent
+ // for rtx we check if recovery is on in newPacketLoss
+ setRtxFec(true, false);
+ indexer_->setNFec(0);
+ return;
+ }
+
+ // XXX since this strategy will be used only for flow at low rate we do not
+ // consider congestion events like in other strategies
+
+ selectRecoveryStrategy(in_sync);
+}
+
+void RecoveryStrategyLowRate::newPacketLoss(uint32_t seq) {
+ if (rtx_on_ && recovery_on_) {
+ addNewRtx(seq, false);
+ } else {
+ if (!state_->isPending(seq) && !indexer_->isFec(seq)) {
+ addNewRtx(seq, true);
+ } else {
+ recover_with_fec_.insert(seq);
+ state_->onPossibleLossWithNoRtx(seq);
+ }
+ }
+}
+
+void RecoveryStrategyLowRate::receivedPacket(uint32_t seq) {
+ removePacketState(seq);
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_low_rate.h b/libtransport/src/protocols/rtc/rtc_rs_low_rate.h
new file mode 100644
index 000000000..f0c7bd0d5
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_low_rate.h
@@ -0,0 +1,69 @@
+/*
+ * 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 <protocols/rtc/rtc_recovery_strategy.h>
+
+#include <vector>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+struct thresholds_t {
+ uint32_t rtt;
+ uint32_t loss_rtx_to_fec; // loss rate used to move from rtx to fec
+ uint32_t loss_fec_to_rtx; // loss rate used to move from fec to rtx
+};
+
+class RecoveryStrategyLowRate : public RecoveryStrategy {
+ public:
+ RecoveryStrategyLowRate(Indexer *indexer, SendRtxCallback &&callback,
+ asio::io_service &io_service,
+ interface::StrategyCallback *external_callback);
+
+ RecoveryStrategyLowRate(RecoveryStrategy &&rs);
+
+ ~RecoveryStrategyLowRate();
+
+ void onNewRound(bool in_sync);
+ void newPacketLoss(uint32_t seq);
+ void receivedPacket(uint32_t seq);
+
+ private:
+ void initSwitchVector();
+ void setRecoveryParameters(bool use_rtx, bool use_fec, uint32_t fec_to_ask);
+ void selectRecoveryStrategy(bool in_sync);
+
+ uint32_t fec_consecutive_rounds_;
+ uint32_t rtx_allowed_consecutive_rounds_;
+
+ // this table contains the thresholds that indicates when to switch from RTX
+ // to FEC and viceversa. values in the vector are detected with a set of
+ // experiments. the vector is used in the following way: if rtt and loss rate
+ // are less than one of the values in the in the vector, losses are
+ // recovered using RTX. otherwive losses are recovered using FEC. as for FEC
+ // only and delay based strategy, the swith from RTX to FEC is smooth,
+ // meaning that FEC and RTX are used together for some rounds
+ std::vector<thresholds_t> switch_vector;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc
new file mode 100644
index 000000000..499e978f1
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glog/logging.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rs_recovery_off.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RecoveryStrategyRecoveryOff::RecoveryStrategyRecoveryOff(
+ Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::StrategyCallback *external_callback)
+ : RecoveryStrategy(indexer, std::move(callback), io_service, false, false,
+ external_callback) {}
+
+RecoveryStrategyRecoveryOff::RecoveryStrategyRecoveryOff(RecoveryStrategy &&rs)
+ : RecoveryStrategy(std::move(rs)) {
+ setRtxFec(false, false);
+}
+
+RecoveryStrategyRecoveryOff::~RecoveryStrategyRecoveryOff() {}
+
+void RecoveryStrategyRecoveryOff::onNewRound(bool in_sync) {
+ // nothing to do
+ return;
+}
+
+void RecoveryStrategyRecoveryOff::newPacketLoss(uint32_t seq) {
+ // here we only keep track of the lost packets to avoid to
+ // count them multple times in the counters. for this we
+ // use the recover_with_fec_ set
+ recover_with_fec_.insert(seq);
+ state_->onPossibleLossWithNoRtx(seq);
+}
+
+void RecoveryStrategyRecoveryOff::receivedPacket(uint32_t seq) {
+ removePacketState(seq);
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h
new file mode 100644
index 000000000..98cd1e6a5
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <protocols/rtc/rtc_recovery_strategy.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RecoveryStrategyRecoveryOff : public RecoveryStrategy {
+ public:
+ RecoveryStrategyRecoveryOff(Indexer *indexer, SendRtxCallback &&callback,
+ asio::io_service &io_service,
+ interface::StrategyCallback *external_callback);
+
+ RecoveryStrategyRecoveryOff(RecoveryStrategy &&rs);
+
+ ~RecoveryStrategyRecoveryOff();
+
+ void onNewRound(bool in_sync);
+ void newPacketLoss(uint32_t seq);
+ void receivedPacket(uint32_t seq);
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc
new file mode 100644
index 000000000..c1ae9b53d
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc
@@ -0,0 +1,61 @@
+/*
+ * 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 <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rs_rtx_only.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RecoveryStrategyRtxOnly::RecoveryStrategyRtxOnly(
+ Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::StrategyCallback *external_callback)
+ : RecoveryStrategy(indexer, std::move(callback), io_service, true, false,
+ external_callback) {}
+
+RecoveryStrategyRtxOnly::RecoveryStrategyRtxOnly(RecoveryStrategy &&rs)
+ : RecoveryStrategy(std::move(rs)) {
+ setRtxFec(true, false);
+}
+
+RecoveryStrategyRtxOnly::~RecoveryStrategyRtxOnly() {}
+
+void RecoveryStrategyRtxOnly::onNewRound(bool in_sync) {
+ // nothing to do
+ return;
+}
+
+void RecoveryStrategyRtxOnly::newPacketLoss(uint32_t seq) {
+ if (!recovery_on_) {
+ recover_with_fec_.insert(seq);
+ state_->onPossibleLossWithNoRtx(seq);
+ return;
+ }
+ addNewRtx(seq, false);
+}
+
+void RecoveryStrategyRtxOnly::receivedPacket(uint32_t seq) {
+ removePacketState(seq);
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h
new file mode 100644
index 000000000..7ae909454
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <protocols/rtc/rtc_recovery_strategy.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RecoveryStrategyRtxOnly : public RecoveryStrategy {
+ public:
+ RecoveryStrategyRtxOnly(Indexer *indexer, SendRtxCallback &&callback,
+ asio::io_service &io_service,
+ interface::StrategyCallback *external_callback);
+
+ RecoveryStrategyRtxOnly(RecoveryStrategy &&rs);
+
+ ~RecoveryStrategyRtxOnly();
+
+ void onNewRound(bool in_sync);
+ void newPacketLoss(uint32_t seq);
+ void receivedPacket(uint32_t seq);
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_state.cc b/libtransport/src/protocols/rtc/rtc_state.cc
index c99205a26..6a21531f8 100644
--- a/libtransport/src/protocols/rtc/rtc_state.cc
+++ b/libtransport/src/protocols/rtc/rtc_state.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -24,15 +24,15 @@ namespace protocol {
namespace rtc {
RTCState::RTCState(Indexer *indexer,
- ProbeHandler::SendProbeCallback &&rtt_probes_callback,
+ ProbeHandler::SendProbeCallback &&probe_callback,
DiscoveredRttCallback &&discovered_rtt_callback,
asio::io_service &io_service)
- : indexer_(indexer),
- rtt_probes_(std::make_shared<ProbeHandler>(std::move(rtt_probes_callback),
- io_service)),
+ : loss_history_(10), // log 10sec history
+ indexer_(indexer),
+ probe_handler_(std::make_shared<ProbeHandler>(std::move(probe_callback),
+ io_service)),
discovered_rtt_callback_(std::move(discovered_rtt_callback)) {
init_rtt_timer_ = std::make_unique<asio::steady_timer>(io_service);
- initParams();
}
RTCState::~RTCState() {}
@@ -55,9 +55,19 @@ void RTCState::initParams() {
highest_seq_received_in_order_ = 0;
last_seq_nacked_ = 0;
loss_rate_ = 0.0;
- avg_loss_rate_ = 0.0;
+ avg_loss_rate_ = -1.0;
max_loss_rate_ = 0.0;
last_round_loss_rate_ = 0.0;
+
+ // loss rate per sec
+ lost_per_sec_ = 0;
+ total_expected_packets_ = 0;
+ per_sec_loss_rate_ = 0.0;
+
+ // residual losses counters
+ expected_packets_ = 0;
+ packets_sent_to_app_ = 0;
+ rounds_from_last_compute_ = 0;
residual_loss_rate_ = 0.0;
// fec counters
@@ -66,9 +76,13 @@ void RTCState::initParams() {
// bw counters
received_bytes_ = 0;
+ received_fec_bytes_ = 0;
+ recovered_bytes_with_fec_ = 0;
+
avg_packet_size_ = INIT_PACKET_SIZE;
production_rate_ = 0.0;
received_rate_ = 0.0;
+ fec_recovered_rate_ = 0.0;
// nack counter
nack_on_last_round_ = false;
@@ -95,31 +109,30 @@ void RTCState::initParams() {
path_table_.clear();
main_path_ = nullptr;
- // packet received
- received_or_lost_packets_.clear();
+ // packet cache (not pending anymore)
+ packet_cache_.clear();
// pending interests
pending_interests_.clear();
- // skipped interest
+ // used to keep track of the skipped interest
last_interest_sent_ = 0;
- skipped_interests_.clear();
// init rtt
first_interest_sent_time_ = ~0;
first_interest_sent_seq_ = 0;
+ // start probing the producer
init_rtt_ = false;
- rtt_probes_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
- rtt_probes_->sendProbes();
+ probe_handler_->setSuffixRange(MIN_INIT_PROBE_SEQ, MAX_INIT_PROBE_SEQ);
+ probe_handler_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
+ probe_handler_->sendProbes();
setInitRttTimer(INIT_RTT_PROBE_RESTART);
}
// packet events
void RTCState::onSendNewInterest(const core::Name *interest_name) {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint32_t seq = interest_name->getSuffix();
pending_interests_.insert(std::pair<uint32_t, uint64_t>(seq, now));
@@ -137,11 +150,12 @@ void RTCState::onSendNewInterest(const core::Name *interest_name) {
}
// TODO what happen in case of jumps?
- // look for skipped interests
- skipped_interests_.erase(seq); // remove seq if it is there
+ eraseFromPacketCache(
+ seq); // if we send this interest we don't know its state
for (uint32_t i = last_interest_sent_ + 1; i < seq; i++) {
if (indexer_->isFec(i)) {
- skipped_interests_.insert(i);
+ // only fec packets can be skipped
+ addToPacketCache(i, PacketState::SKIPPED);
}
}
@@ -155,6 +169,7 @@ void RTCState::onTimeout(uint32_t seq, bool lost) {
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) {
pending_interests_.erase(it);
+ if (indexer_->isFec(seq)) pending_fec_pkt_--;
}
received_timeouts_++;
@@ -162,11 +177,12 @@ void RTCState::onTimeout(uint32_t seq, bool lost) {
}
void RTCState::onLossDetected(uint32_t seq) {
- if (!indexer_->isFec(seq)) {
- packets_lost_++;
- } else if (skipped_interests_.find(seq) == skipped_interests_.end() &&
- seq >= first_interest_sent_seq_) {
+ PacketState state = getPacketState(seq);
+
+ // if the packet is already marked with a state, do nothing
+ if (state == PacketState::UNKNOWN) {
packets_lost_++;
+ addToPacketCache(seq, PacketState::LOST);
}
}
@@ -178,30 +194,40 @@ void RTCState::onRetransmission(uint32_t seq) {
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) {
pending_interests_.erase(it);
-#if 0
- packets_lost_++;
-#endif
+ if (indexer_->isFec(seq)) pending_fec_pkt_--;
}
sent_rtx_++;
sent_rtx_last_round_++;
}
+void RTCState::onPossibleLossWithNoRtx(uint32_t seq) {
+ // if fec is on or rtx is disable we don't need to do anything to recover a
+ // packet. however in both cases we need to remove possible missing packets
+ // from the window of pendinig interest in order to free space without wating
+ // for the timeout.
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) {
+ pending_interests_.erase(it);
+ if (indexer_->isFec(seq)) pending_fec_pkt_--;
+ }
+}
+
void RTCState::onDataPacketReceived(const core::ContentObject &content_object,
bool compute_stats) {
uint32_t seq = content_object.getName().getSuffix();
+
if (compute_stats) {
updatePathStats(content_object, false);
received_data_last_round_++;
}
received_data_++;
+ packets_sent_to_app_++;
- struct data_packet_t *data_pkt =
- (struct data_packet_t *)content_object.getPayload()->data();
- uint64_t production_time = data_pkt->getTimestamp();
- if (last_prod_update_ < production_time) {
- last_prod_update_ = production_time;
- uint32_t production_rate = data_pkt->getProductionRate();
- production_rate_ = (double)production_rate;
+ core::ParamsRTC params = RTCState::getDataParams(content_object);
+
+ if (last_prod_update_ < params.timestamp) {
+ last_prod_update_ = params.timestamp;
+ production_rate_ = (double)params.prod_rate;
}
updatePacketSize(content_object);
@@ -219,9 +245,18 @@ 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);
+ // updateReceivedBytes(content_object);
+ received_fec_bytes_ +=
+ (uint32_t)(content_object.headerSize() + content_object.payloadSize());
+
+ if (seq > highest_seq_received_) highest_seq_received_ = seq;
+
+ PacketState state = getPacketState(seq);
+ if (state != PacketState::LOST) {
+ // increase only for not lost packets
+ received_fec_pkt_++;
+ }
addRecvOrLost(seq, PacketState::RECEIVED);
- received_fec_pkt_++;
// the producer is responding
// it is generating valid data packets so we consider it active
producer_is_active_ = true;
@@ -233,7 +268,7 @@ void RTCState::onNackPacketReceived(const core::ContentObject &nack,
struct nack_packet_t *nack_pkt =
(struct nack_packet_t *)nack.getPayload()->data();
uint64_t production_time = nack_pkt->getTimestamp();
- uint32_t production_seq = nack_pkt->getProductionSegement();
+ uint32_t production_seq = nack_pkt->getProductionSegment();
uint32_t production_rate = nack_pkt->getProductionRate();
if (TRANSPORT_EXPECT_FALSE(main_path_ == nullptr) ||
@@ -255,6 +290,7 @@ void RTCState::onNackPacketReceived(const core::ContentObject &nack,
received_nacks_++;
received_nacks_last_round_++;
+ bool to_delete = false;
if (production_seq > seq) {
// old nack, seq is lost
// update last nacked
@@ -266,12 +302,19 @@ void RTCState::onNackPacketReceived(const core::ContentObject &nack,
// future nack
// remove the nack from the pending interest map
// (the packet is not received/lost yet)
- if (indexer_->isFec(seq)) pending_fec_pkt_--;
- pending_interests_.erase(seq);
+ to_delete = true;
} else {
// this should be a quite rear event. simply remove the
// packet from the pending interest list
- pending_interests_.erase(seq);
+ to_delete = true;
+ }
+
+ if (to_delete) {
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) {
+ pending_interests_.erase(it);
+ if (indexer_->isFec(seq)) pending_fec_pkt_--;
+ }
}
// the producer is responding
@@ -295,44 +338,58 @@ void RTCState::onPacketLost(uint32_t seq) {
}
#endif
if (!indexer_->isFec(seq)) {
- definitely_lost_pkt_++;
- DLOG_IF(INFO, VLOG_IS_ON(4)) << "packet " << seq << " is lost";
+ PacketState state = getPacketState(seq);
+ if (state == PacketState::LOST || state == PacketState::UNKNOWN) {
+ definitely_lost_pkt_++;
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "packet " << seq << " is lost";
+ }
}
- addRecvOrLost(seq, PacketState::LOST);
+ addRecvOrLost(seq, PacketState::DEFINITELY_LOST);
}
void RTCState::onPacketRecoveredRtx(uint32_t seq) {
+ packets_sent_to_app_++;
+ if (seq > highest_seq_received_) highest_seq_received_ = seq;
losses_recovered_++;
addRecvOrLost(seq, PacketState::RECEIVED);
}
-void RTCState::onPacketRecoveredFec(uint32_t seq) {
+void RTCState::onFecPacketRecoveredRtx(uint32_t seq) {
+ // 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_++;
+}
+
+void RTCState::onPacketRecoveredFec(uint32_t seq, uint32_t size) {
losses_recovered_++;
+ 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
+
+ if (getPacketState(seq) == PacketState::UNKNOWN)
+ onLossDetected(seq); // the pkt was lost but didn't account for it yet
+
addRecvOrLost(seq, PacketState::RECEIVED);
}
bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
uint32_t seq = probe.getName().getSuffix();
- uint64_t rtt;
-
- rtt = rtt_probes_->getRtt(seq);
+ uint64_t rtt;
+ rtt = probe_handler_->getRtt(seq);
if (rtt == 0) return false; // this is not a valid probe
- // like for data and nacks update the path stats. Here the RTT is computed
- // by the probe handler. Both probes for rtt and bw are good to esimate
- // info on the path
+ // Like for data and nacks update the path stats. Here the RTT is computed
+ // by the probe handler. Both probes for rtt and bw are good to estimate
+ // info on the path.
uint32_t path_label = probe.getPathLabel();
-
auto path_it = path_table_.find(path_label);
- // update production rate and last_seq_nacked like in case of a nack
- struct nack_packet_t *probe_pkt =
- (struct nack_packet_t *)probe.getPayload()->data();
- uint64_t sender_timestamp = probe_pkt->getTimestamp();
- uint32_t production_seq = probe_pkt->getProductionSegement();
- uint32_t production_rate = probe_pkt->getProductionRate();
-
if (path_it == path_table_.end()) {
// found a new path
std::shared_ptr<RTCDataPath> newPath =
@@ -344,26 +401,26 @@ bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
auto path = path_it->second;
- path->insertRttSample(rtt);
+ path->insertRttSample(utils::SteadyTime::Milliseconds(rtt), true);
path->receivedNack();
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
+
+ core::ParamsRTC params = RTCState::getProbeParams(probe);
- int64_t OWD = now - sender_timestamp;
+ int64_t OWD = now - params.timestamp;
path->insertOwdSample(OWD);
- if (last_prod_update_ < sender_timestamp) {
- last_production_seq_ = production_seq;
- last_prod_update_ = sender_timestamp;
- production_rate_ = (double)production_rate;
+ if (last_prod_update_ < params.timestamp) {
+ last_production_seq_ = params.prod_seg;
+ last_prod_update_ = params.timestamp;
+ production_rate_ = (double)params.prod_rate;
}
// the producer is responding
// we consider it active only if the production rate is not 0
// or the production sequence numner is not 1
- if (production_rate_ != 0 || production_seq != 1) {
+ if (production_rate_ != 0 || params.prod_seg != 1) {
producer_is_active_ = true;
}
@@ -375,7 +432,7 @@ bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
if (!init_rtt_ && received_probes_ <= INIT_RTT_PROBES) {
if (received_probes_ == 1) {
// we got the first probe, wait at most INIT_RTT_PROBE_WAIT sec for the
- // others
+ // others.
main_path_ = path;
setInitRttTimer(INIT_RTT_PROBE_WAIT);
}
@@ -393,11 +450,21 @@ bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
return true;
}
-void RTCState::onNewRound(double round_len, bool in_sync) {
- // XXX
- // here we take into account only the single path case so we assume that we
- // don't use two paths in parellel for this single flow
+void RTCState::onJumpForward(uint32_t next_seq) {
+ for (uint32_t seq = highest_seq_received_in_order_ + 1; seq < next_seq;
+ seq++) {
+ auto it = pending_interests_.find(seq);
+ PacketState packet_state = getPacketState(seq);
+ if (it == pending_interests_.end() &&
+ packet_state != PacketState::RECEIVED &&
+ packet_state != PacketState::DEFINITELY_LOST) {
+ onLossDetected(seq);
+ onPacketLost(seq);
+ }
+ }
+}
+void RTCState::onNewRound(double round_len, bool in_sync) {
if (path_table_.empty()) return;
double bytes_per_sec =
@@ -407,7 +474,24 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
else
received_rate_ = (received_rate_ * MOVING_AVG_ALPHA) +
((1 - MOVING_AVG_ALPHA) * bytes_per_sec);
+ double fec_bytes_per_sec =
+ ((double)received_fec_bytes_ * (MILLI_IN_A_SEC / round_len));
+
+ if (fec_received_rate_ == 0)
+ fec_received_rate_ = fec_bytes_per_sec;
+ else
+ fec_received_rate_ = (fec_received_rate_ * 0.8) + (0.2 * fec_bytes_per_sec);
+
+ double fec_recovered_bytes_per_sec =
+ ((double)recovered_bytes_with_fec_ * (MILLI_IN_A_SEC / round_len));
+ if (fec_recovered_rate_ == 0)
+ fec_recovered_rate_ = fec_recovered_bytes_per_sec;
+ else
+ fec_recovered_rate_ =
+ (fec_recovered_rate_ * 0.8) + (0.2 * fec_recovered_bytes_per_sec);
+
+#if 0
// search for an active path. There should be only one active path (meaning a
// path that leads to the producer socket -no cache- and from which we are
// currently getting data packets) at any time. However it may happen that
@@ -428,9 +512,36 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
}
}
}
+#endif
+
+ // search for an active path. Is it possible to have multiple path that are
+ // used at the same time. We use as reference path the one from where we gets
+ // more packets. This means that the path should have better lantecy or less
+ // channel losses
+
+ uint32_t last_round_packets = 0;
+ std::shared_ptr<RTCDataPath> old_main_path = main_path_;
+ main_path_ = nullptr;
+
+ for (auto it = path_table_.begin(); it != path_table_.end(); it++) {
+ if (it->second->isActive()) {
+ uint32_t pkt = it->second->getPacketsLastRound();
+ if (pkt > last_round_packets) {
+ last_round_packets = pkt;
+ main_path_ = it->second;
+ }
+ }
+ it->second->roundEnd();
+ }
- // if (in_sync) updateLossRate();
- updateLossRate();
+ if (main_path_ == nullptr) main_path_ = old_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
+ // old stats that may be outdated.
+ if (main_path_ != old_main_path) old_main_path->clearRtt();
+
+ updateLossRate(in_sync);
// handle nacks
if (!nack_on_last_round_ && received_bytes_ > 0) {
@@ -460,6 +571,8 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
// reset counters
received_bytes_ = 0;
+ received_fec_bytes_ = 0;
+ recovered_bytes_with_fec_ = 0;
packets_lost_ = 0;
definitely_lost_pkt_ = 0;
losses_recovered_ = 0;
@@ -516,20 +629,16 @@ void RTCState::updatePathStats(const core::ContentObject &content_object,
// it means that we are processing an interest
// that is not pending
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
uint64_t RTT = now - interest_sent_time;
- path->insertRttSample(RTT);
+ path->insertRttSample(utils::SteadyTime::Milliseconds(RTT), false);
// compute OWD (the first part of the nack and data packet header are the
// same, so we cast to data data packet)
- struct data_packet_t *packet =
- (struct data_packet_t *)content_object.getPayload()->data();
- uint64_t sender_timestamp = packet->getTimestamp();
- int64_t OWD = now - sender_timestamp;
+ core::ParamsRTC params = RTCState::getDataParams(content_object);
+ int64_t OWD = now - params.timestamp;
path->insertOwdSample(OWD);
// compute IAT or set path to producer
@@ -543,59 +652,106 @@ void RTCState::updatePathStats(const core::ContentObject &content_object,
}
}
-void RTCState::updateLossRate() {
+void RTCState::updateLossRate(bool in_sync) {
last_round_loss_rate_ = loss_rate_;
loss_rate_ = 0.0;
- residual_loss_rate_ = 0.0;
uint32_t number_theorically_received_packets_ =
highest_seq_received_ - first_seq_in_round_;
- // in this case no new packet was recevied after the previuos round, avoid
- // division by 0
- if (number_theorically_received_packets_ == 0) return;
-
// XXX this may be quite inefficient if the rate is high
// maybe is better to iterate over the set?
- for (uint32_t i = first_seq_in_round_; i < highest_seq_received_; i++) {
- auto it = skipped_interests_.find(i);
- if (it != skipped_interests_.end()) {
+
+ uint32_t fec_packets = 0;
+ for (uint32_t i = (first_seq_in_round_ + 1); i < highest_seq_received_; i++) {
+ PacketState state = getPacketState(i);
+ if (state == PacketState::SKIPPED) {
if (number_theorically_received_packets_ > 0)
number_theorically_received_packets_--;
- skipped_interests_.erase(it);
}
+ if (indexer_->isFec(i)) fec_packets++;
}
+ if (indexer_->isFec(highest_seq_received_)) fec_packets++;
- loss_rate_ = (double)((double)(packets_lost_) /
- (double)number_theorically_received_packets_);
+ // in this case no new packet was received after the previous round, avoid
+ // division by 0
+ if (number_theorically_received_packets_ == 0 && packets_lost_ == 0) return;
- if (rounds_ % 15 == 0) max_loss_rate_ = 0; // reset every 3 sec
- if (loss_rate_ > max_loss_rate_) max_loss_rate_ = loss_rate_;
+ if (number_theorically_received_packets_ != 0)
+ loss_rate_ = (double)((double)(packets_lost_) /
+ (double)number_theorically_received_packets_);
+ else
+ // we didn't receive anything except NACKs that triggered losses
+ loss_rate_ = 1.0;
- if (avg_loss_rate_ == 0)
+ if (avg_loss_rate_ == -1.0)
avg_loss_rate_ = loss_rate_;
else
avg_loss_rate_ =
avg_loss_rate_ * MOVING_AVG_ALPHA + loss_rate_ * (1 - MOVING_AVG_ALPHA);
- residual_loss_rate_ = (double)((double)(packets_lost_ - losses_recovered_) /
- (double)number_theorically_received_packets_);
+ // update counters for loss rate per second
+ total_expected_packets_ += number_theorically_received_packets_;
+ lost_per_sec_ += packets_lost_;
+
+ if (in_sync) {
+ // update counters for residual losses
+ // fec packets are not sent to the app so we don't want to count them here
+ expected_packets_ +=
+ ((highest_seq_received_ - first_seq_in_round_) - fec_packets);
+ } else {
+ packets_sent_to_app_ = 0;
+ }
+
+ if (rounds_from_last_compute_ >= (MILLI_IN_A_SEC / ROUND_LEN)) {
+ // compute loss rate per second
+ if (lost_per_sec_ > total_expected_packets_)
+ lost_per_sec_ = total_expected_packets_;
+
+ if (total_expected_packets_ == 0)
+ per_sec_loss_rate_ = 0;
+ else
+ per_sec_loss_rate_ =
+ (double)((double)(lost_per_sec_) / (double)total_expected_packets_);
+
+ loss_history_.pushBack(per_sec_loss_rate_);
+ max_loss_rate_ = getMaxLoss();
+
+ if (in_sync && expected_packets_ != 0) {
+ // compute residual loss rate
+ if (packets_sent_to_app_ > expected_packets_) {
+ // this may happen if we get packet from the prev bin that get recovered
+ // on the current one
+ packets_sent_to_app_ = expected_packets_;
+ }
+
+ residual_loss_rate_ =
+ 1.0 - ((double)packets_sent_to_app_ / (double)expected_packets_);
+ if (residual_loss_rate_ < 0.0) residual_loss_rate_ = 0.0;
+ }
+
+ lost_per_sec_ = 0;
+ total_expected_packets_ = 0;
+ expected_packets_ = 0;
+ packets_sent_to_app_ = 0;
+ rounds_from_last_compute_ = 0;
+ }
+
+ rounds_from_last_compute_++;
+}
- if (residual_loss_rate_ < 0) residual_loss_rate_ = 0;
+void RTCState::dataToBeReceived(uint32_t seq) {
+ addToPacketCache(seq, PacketState::TO_BE_RECEIVED);
}
void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
- if (indexer_->isFec(seq)) {
- pending_fec_pkt_--;
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) {
+ pending_interests_.erase(it);
+ if (indexer_->isFec(seq)) pending_fec_pkt_--;
}
- pending_interests_.erase(seq);
- if (received_or_lost_packets_.size() >= MAX_CACHED_PACKETS) {
- received_or_lost_packets_.erase(received_or_lost_packets_.begin());
- }
- // notice that it may happen that a packet that we consider lost arrives after
- // some time, in this case we simply overwrite the packet state.
- received_or_lost_packets_[seq] = state;
+ addToPacketCache(seq, state);
// keep track of the last packet received/lost
// without holes.
@@ -608,16 +764,25 @@ void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
} else if (seq <= highest_seq_received_in_order_) {
// here we do nothing
} else if (seq > highest_seq_received_in_order_) {
- // 1) there is a gap in the sequence so we do not update largest_in_seq_
- // 2) all the packets from largest_in_seq_ to seq are in
- // received_or_lost_packets_ an we upate largest_in_seq_
- // or are FEC packets
+ // 1) there is a gap in the sequence so we do not update
+ // highest_seq_received_in_order_
+ // 2) all the packets from highest_seq_received_in_order_ to seq are
+ // received or lost or are fec packetis. In this case we increase
+ // highest_seq_received_in_order_ until we find an hole in the sequence
for (uint32_t i = highest_seq_received_in_order_ + 1; i <= seq; i++) {
- if (received_or_lost_packets_.find(i) ==
- received_or_lost_packets_.end() &&
- !indexer_->isFec(i)) {
- break;
+ PacketState state = getPacketState(i);
+ if ((state == PacketState::UNKNOWN || state == PacketState::LOST)) {
+ if (indexer_->isFec(i)) {
+ // this is a fec packet and we don't care to receive it
+ // however we may need to increse the number or lost packets
+ // XXX: in case we want to use rtx to recover fec packets,
+ // this may prevent to detect a packet loss and no rtx will be sent
+ onLossDetected(i);
+ } else {
+ // this is a data packet and we need to get it
+ break;
+ }
}
// this packet is in order so we can update the
// highest_seq_received_in_order_
@@ -629,9 +794,14 @@ void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
void RTCState::setInitRttTimer(uint32_t wait) {
init_rtt_timer_->cancel();
init_rtt_timer_->expires_from_now(std::chrono::milliseconds(wait));
- init_rtt_timer_->async_wait([this](std::error_code ec) {
+
+ std::weak_ptr<RTCState> self = shared_from_this();
+ init_rtt_timer_->async_wait([self](const std::error_code &ec) {
if (ec) return;
- checkInitRttTimer();
+
+ if (auto ptr = self.lock()) {
+ ptr->checkInitRttTimer();
+ }
});
}
@@ -639,19 +809,25 @@ void RTCState::checkInitRttTimer() {
if (received_probes_ < INIT_RTT_MIN_PROBES_TO_RECV) {
// we didn't received enough probes, restart
received_probes_ = 0;
- rtt_probes_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
- rtt_probes_->sendProbes();
+ probe_handler_->setSuffixRange(MIN_INIT_PROBE_SEQ, MAX_INIT_PROBE_SEQ);
+ probe_handler_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
+ probe_handler_->sendProbes();
setInitRttTimer(INIT_RTT_PROBE_RESTART);
return;
}
+
init_rtt_ = true;
main_path_->roundEnd();
- rtt_probes_->setProbes(RTT_PROBE_INTERVAL, 0);
- rtt_probes_->sendProbes();
+ loss_history_.pushBack(probe_handler_->getProbeLossRate());
+ max_loss_rate_ = getMaxLoss();
+
+ probe_handler_->setSuffixRange(MIN_RTT_PROBE_SEQ, MAX_RTT_PROBE_SEQ);
+ probe_handler_->setProbes(RTT_PROBE_INTERVAL, 0);
+ probe_handler_->sendProbes();
// init last_seq_nacked_. skip packets that may come from the cache
double prod_rate = getProducerRate();
- double rtt = (double)getRTT() / MILLI_IN_A_SEC;
+ double rtt = (double)getMinRTT() / MILLI_IN_A_SEC;
double packet_size = getAveragePacketSize();
uint32_t pkt_in_rtt_ = std::floor(((prod_rate / packet_size) * rtt) * 0.8);
last_seq_nacked_ = last_production_seq_ + pkt_in_rtt_;
@@ -659,6 +835,68 @@ void RTCState::checkInitRttTimer() {
discovered_rtt_callback_();
}
+double RTCState::getMaxLoss() {
+ if (loss_history_.size() != 0) return loss_history_.begin();
+ return 0;
+}
+
+core::ParamsRTC RTCState::getProbeParams(const core::ContentObject &probe) {
+ uint32_t seq = probe.getName().getSuffix();
+ core::ParamsRTC params;
+
+ switch (ProbeHandler::getProbeType(seq)) {
+ case ProbeType::INIT: {
+ core::ContentObjectManifest manifest(
+ const_cast<core::ContentObject &>(probe));
+ manifest.decode();
+ params = manifest.getParamsRTC();
+ break;
+ }
+ case ProbeType::RTT: {
+ struct nack_packet_t *probe_pkt =
+ (struct nack_packet_t *)probe.getPayload()->data();
+ params = core::ParamsRTC{
+ .timestamp = probe_pkt->getTimestamp(),
+ .prod_rate = probe_pkt->getProductionRate(),
+ .prod_seg = probe_pkt->getProductionSegment(),
+ };
+ break;
+ }
+ default:
+ break;
+ }
+
+ return params;
+}
+
+core::ParamsRTC RTCState::getDataParams(const core::ContentObject &data) {
+ core::ParamsRTC params;
+
+ switch (data.getPayloadType()) {
+ case core::PayloadType::DATA: {
+ struct data_packet_t *data_pkt =
+ (struct data_packet_t *)data.getPayload()->data();
+ params = core::ParamsRTC{
+ .timestamp = data_pkt->getTimestamp(),
+ .prod_rate = data_pkt->getProductionRate(),
+ .prod_seg = data.getName().getSuffix(),
+ };
+ break;
+ }
+ case core::PayloadType::MANIFEST: {
+ core::ContentObjectManifest manifest(
+ const_cast<core::ContentObject &>(data));
+ manifest.decode();
+ params = manifest.getParamsRTC();
+ break;
+ }
+ default:
+ break;
+ }
+
+ return params;
+}
+
} // namespace rtc
} // namespace protocol
diff --git a/libtransport/src/protocols/rtc/rtc_state.h b/libtransport/src/protocols/rtc/rtc_state.h
index 729ba7a1b..8bf48ccc2 100644
--- a/libtransport/src/protocols/rtc/rtc_state.h
+++ b/libtransport/src/protocols/rtc/rtc_state.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -14,13 +14,16 @@
*/
#pragma once
+#include <core/facade.h>
#include <hicn/transport/config.h>
#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/name.h>
+#include <hicn/transport/utils/rtc_quality_score.h>
#include <protocols/indexer.h>
#include <protocols/rtc/probe_handler.h>
#include <protocols/rtc/rtc_data_path.h>
+#include <utils/max_filter.h>
#include <map>
#include <set>
@@ -31,25 +34,50 @@ namespace protocol {
namespace rtc {
-enum class PacketState : uint8_t { RECEIVED, LOST, UNKNOWN };
+// packet state
+// RECEIVED: the packet was already received
+// LOST: the packet is marked as lost but can be recovered
+// DEFINITELY_LOST: the packet is lost and cannot be recovered
+// TO_BE_RECEIVED: when a packet is received is sent to the FEC decoder. the fec
+// decoder may decide to send the packet directly to the app. to avoid
+// duplicated the packet is marked with this state
+// SKIPPED: an interest that was not sent, only for FEC packets
+// UNKNOWN: unknown state
+enum class PacketState : uint8_t {
+ RECEIVED,
+ TO_BE_RECEIVED,
+ LOST,
+ DEFINITELY_LOST,
+ SKIPPED,
+ UNKNOWN
+};
+
+class RTCState : public std::enable_shared_from_this<RTCState> {
+ using PendingInterestsMap = std::map<uint32_t, uint64_t>;
+
+ private:
+ const double MAX_CACHED_PACKETS = 8192; // XXX this value may be too small
+ // for high rate apps
-class RTCState : std::enable_shared_from_this<RTCState> {
public:
using DiscoveredRttCallback = std::function<void()>;
public:
- RTCState(Indexer *indexer,
- ProbeHandler::SendProbeCallback &&rtt_probes_callback,
+ RTCState(Indexer *indexer, ProbeHandler::SendProbeCallback &&probe_callback,
DiscoveredRttCallback &&discovered_rtt_callback,
asio::io_service &io_service);
~RTCState();
+ // initialization
+ void initParams();
+
// packet events
void onSendNewInterest(const core::Name *interest_name);
void onTimeout(uint32_t seq, bool lost);
void onLossDetected(uint32_t seq);
void onRetransmission(uint32_t seq);
+ void onPossibleLossWithNoRtx(uint32_t seq);
void onDataPacketReceived(const core::ContentObject &content_object,
bool compute_stats);
void onFecPacketReceived(const core::ContentObject &content_object);
@@ -57,8 +85,10 @@ class RTCState : std::enable_shared_from_this<RTCState> {
bool compute_stats);
void onPacketLost(uint32_t seq);
void onPacketRecoveredRtx(uint32_t seq);
- void onPacketRecoveredFec(uint32_t seq);
+ void onFecPacketRecoveredRtx(uint32_t seq);
+ void onPacketRecoveredFec(uint32_t seq, uint32_t size);
bool onProbePacketReceived(const core::ContentObject &probe);
+ void onJumpForward(uint32_t next_seq);
// protocol state
void onNewRound(double round_len, bool in_sync);
@@ -72,10 +102,21 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// delay metrics
bool isRttDiscovered() const { return init_rtt_; }
- uint64_t getRTT() const {
+ uint64_t getMinRTT() const {
if (mainPathIsValid()) return main_path_->getMinRtt();
return 0;
}
+
+ uint64_t getAvgRTT() const {
+ if (mainPathIsValid()) return main_path_->getAvgRtt();
+ return 0;
+ }
+
+ uint64_t getMaxRTT() const {
+ if (mainPathIsValid()) return main_path_->getMaxRtt();
+ return 0;
+ }
+
void resetRttStats() {
if (mainPathIsValid()) main_path_->clearRtt();
}
@@ -98,6 +139,7 @@ class RTCState : std::enable_shared_from_this<RTCState> {
uint64_t getInterestSentTime(uint32_t seq) {
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) return it->second;
+
return 0;
}
@@ -110,14 +152,15 @@ class RTCState : std::enable_shared_from_this<RTCState> {
return pending_interests_.size();
}
- PacketState isReceivedOrLost(uint32_t seq) {
- auto it = received_or_lost_packets_.find(seq);
- if (it != received_or_lost_packets_.end()) return it->second;
+ PacketState getPacketState(uint32_t seq) {
+ auto it = packet_cache_.find(seq);
+ if (it != packet_cache_.end()) return it->second;
return PacketState::UNKNOWN;
}
// loss rate
- double getLossRate() const { return loss_rate_; }
+ double getPerRoundLossRate() const { return loss_rate_; }
+ double getPerSecondLossRate() const { return per_sec_loss_rate_; }
double getAvgLossRate() const { return avg_loss_rate_; }
double getMaxLossRate() const { return max_loss_rate_; }
double getLastRoundLossRate() const { return last_round_loss_rate_; }
@@ -134,15 +177,22 @@ class RTCState : std::enable_shared_from_this<RTCState> {
return highest_seq_received_in_order_;
}
+ double getMaxLoss();
+
// fec packets
uint32_t getReceivedFecPackets() const { return received_fec_pkt_; }
uint32_t getPendingFecPackets() const { return pending_fec_pkt_; }
// generic stats
uint32_t getReceivedBytesInRound() const { return received_bytes_; }
+ uint32_t getReceivedFecBytesInRound() const { return received_fec_bytes_; }
+ uint32_t getRecoveredFecBytesInRound() const {
+ return recovered_bytes_with_fec_;
+ }
uint32_t getReceivedNacksInRound() const {
return received_nacks_last_round_;
}
+ uint32_t getReceivedDataInRound() const { return received_data_last_round_; }
uint32_t getSentInterestInRound() const { return sent_interests_last_round_; }
uint32_t getSentRtxInRound() const { return sent_rtx_last_round_; }
@@ -150,6 +200,9 @@ class RTCState : std::enable_shared_from_this<RTCState> {
double getAvailableBw() const { return 0.0; }; // TODO
double getProducerRate() const { return production_rate_; }
double getReceivedRate() const { return received_rate_; }
+ double getReceivedFecRate() const { return fec_received_rate_; }
+ double getRecoveredFecRate() const { return fec_recovered_rate_; }
+
double getAveragePacketSize() const { return avg_packet_size_; }
// nacks
@@ -162,22 +215,46 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// packets from cache
double getPacketFromCacheRatio() const { return data_from_cache_rate_; }
- std::map<uint32_t, uint64_t>::iterator getPendingInterestsMapBegin() {
+ PendingInterestsMap::iterator getPendingInterestsMapBegin() {
return pending_interests_.begin();
}
- std::map<uint32_t, uint64_t>::iterator getPendingInterestsMapEnd() {
+ PendingInterestsMap::iterator getPendingInterestsMapEnd() {
return pending_interests_.end();
}
+ // quality
+ uint8_t getQualityScore() {
+ uint8_t qs = quality_score_.getQualityScore(
+ getMaxRTT(), std::round(getResidualLossRate() * 100));
+ return qs;
+ }
+
+ // We received a data pkt that will be set to RECEIVED, but first we have to
+ // go through FEC. We do not want to consider this pkt as recovered, thus we
+ // set it as TO_BE_RECEIVED.
+ void dataToBeReceived(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);
+
private:
- void initParams();
+ void addToPacketCache(uint32_t seq, PacketState state) {
+ // this function adds or updates the current state
+ if (packet_cache_.size() >= MAX_CACHED_PACKETS) {
+ packet_cache_.erase(packet_cache_.begin());
+ }
+ packet_cache_[seq] = state;
+ }
+
+ void eraseFromPacketCache(uint32_t seq) { packet_cache_.erase(seq); }
// update stats
void updateState();
void updateReceivedBytes(const core::ContentObject &content_object);
void updatePacketSize(const core::ContentObject &content_object);
void updatePathStats(const core::ContentObject &content_object, bool is_nack);
- void updateLossRate();
+ void updateLossRate(bool in_sycn);
void addRecvOrLost(uint32_t seq, PacketState state);
@@ -211,22 +288,39 @@ class RTCState : std::enable_shared_from_this<RTCState> {
double avg_loss_rate_;
double max_loss_rate_;
double last_round_loss_rate_;
+ utils::MaxFilter<double> loss_history_;
+
+ // per second loss rate
+ uint32_t lost_per_sec_;
+ uint32_t total_expected_packets_;
+ double per_sec_loss_rate_;
+
+ // conunters for residual losses
+ // residual losses are computed every second and are used
+ // as feedback to the upper levels (e.g application)
+ uint32_t expected_packets_;
+ uint32_t packets_sent_to_app_;
+ uint32_t rounds_from_last_compute_;
double residual_loss_rate_;
// bw counters
uint32_t received_bytes_;
+ uint32_t received_fec_bytes_;
+ uint32_t recovered_bytes_with_fec_;
double avg_packet_size_;
- double production_rate_; // rate communicated by the producer using nacks
- double received_rate_; // rate recevied by the consumer
+ double production_rate_; // rate communicated by the producer using nacks
+ double received_rate_; // rate recevied by the consumer (only data)
+ double fec_received_rate_; // fec rate recevied by the consumer
+ double fec_recovered_rate_; // rate recovered using fec
- // nack counter
+ // nack counters
// the bool takes tracks only about the valid nacks (no rtx) and it is used to
// switch between the states. Instead received_nacks_last_round_ logs all the
// nacks for statistics
bool nack_on_last_round_;
uint32_t received_nacks_last_round_;
- // packets counter
+ // packets counters
uint32_t received_packets_last_round_;
uint32_t received_data_last_round_;
uint32_t received_data_from_cache_;
@@ -234,11 +328,11 @@ class RTCState : std::enable_shared_from_this<RTCState> {
uint32_t sent_interests_last_round_;
uint32_t sent_rtx_last_round_;
- // fec counter
+ // fec counters
uint32_t received_fec_pkt_;
uint32_t pending_fec_pkt_;
- // round conunters
+ // round counters
uint32_t rounds_;
uint32_t rounds_without_nacks_;
uint32_t rounds_without_packets_;
@@ -261,23 +355,27 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// packet received
// cache where to store info about the last MAX_CACHED_PACKETS
- std::map<uint32_t, PacketState> received_or_lost_packets_;
+ // these are packets that are received or lost or definitely lost and are not
+ // anymore in the pending intetest list
+ std::map<uint32_t, PacketState> packet_cache_;
// pending interests
- std::map<uint32_t, uint64_t> pending_interests_;
+ PendingInterestsMap pending_interests_;
// indexer
Indexer *indexer_;
- // skipped interests
+ // used to keep track of the skipped interests
uint32_t last_interest_sent_;
- std::unordered_set<uint32_t> skipped_interests_;
// probes
- std::shared_ptr<ProbeHandler> rtt_probes_;
+ std::shared_ptr<ProbeHandler> probe_handler_;
bool init_rtt_;
std::unique_ptr<asio::steady_timer> init_rtt_timer_;
+ // quality score
+ RTCQualityScore quality_score_;
+
// callbacks
DiscoveredRttCallback discovered_rtt_callback_;
};
diff --git a/libtransport/src/protocols/rtc/rtc_verifier.cc b/libtransport/src/protocols/rtc/rtc_verifier.cc
new file mode 100644
index 000000000..29968dd02
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_verifier.cc
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/facade.h>
+#include <protocols/rtc/rtc_packet.h>
+#include <protocols/rtc/rtc_verifier.h>
+
+namespace transport {
+namespace protocol {
+namespace rtc {
+
+RTCVerifier::RTCVerifier(std::shared_ptr<auth::Verifier> verifier,
+ uint32_t max_unverified_delay)
+ : verifier_(verifier), max_unverified_delay_(max_unverified_delay) {}
+
+void RTCVerifier::setState(std::shared_ptr<RTCState> rtc_state) {
+ rtc_state_ = rtc_state;
+}
+
+void RTCVerifier::setVerifier(std::shared_ptr<auth::Verifier> verifier) {
+ verifier_ = verifier;
+}
+
+void RTCVerifier::setMaxUnverifiedDelay(uint32_t max_unverified_delay) {
+ max_unverified_delay_ = max_unverified_delay;
+}
+
+auth::VerificationPolicy RTCVerifier::verify(
+ core::ContentObject &content_object, bool is_fec) {
+ uint32_t suffix = content_object.getName().getSuffix();
+ core::PayloadType payload_type = content_object.getPayloadType();
+
+ bool is_probe = ProbeHandler::getProbeType(suffix) != ProbeType::NOT_PROBE;
+ bool is_nack = !is_probe && content_object.payloadSize() == NACK_HEADER_SIZE;
+ bool is_manifest = !is_probe && !is_nack && !is_fec &&
+ payload_type == core::PayloadType::MANIFEST;
+ bool is_data = !is_probe && !is_nack && !is_fec &&
+ payload_type == core::PayloadType::DATA;
+
+ if (is_probe) return verifyProbe(content_object);
+ if (is_nack) return verifyNack(content_object);
+ if (is_fec) return verifyFec(content_object);
+ if (is_data) return verifyData(content_object);
+ if (is_manifest) return verifyManifest(content_object);
+
+ auth::VerificationPolicy policy = auth::VerificationPolicy::ABORT;
+ verifier_->callVerificationFailedCallback(suffix, policy);
+ return policy;
+}
+
+auth::VerificationPolicy RTCVerifier::verifyProbe(
+ core::ContentObject &content_object) {
+ switch (ProbeHandler::getProbeType(content_object.getName().getSuffix())) {
+ case ProbeType::INIT: {
+ auth::VerificationPolicy policy = verifyManifest(content_object);
+ if (policy != auth::VerificationPolicy::ACCEPT) {
+ return policy;
+ }
+ return processManifest(content_object);
+ }
+ case ProbeType::RTT:
+ return verifyNack(content_object);
+ default:
+ auth::VerificationPolicy policy = auth::VerificationPolicy::ABORT;
+ verifier_->callVerificationFailedCallback(
+ content_object.getName().getSuffix(), policy);
+ return policy;
+ }
+}
+
+auth::VerificationPolicy RTCVerifier::verifyNack(
+ core::ContentObject &content_object) {
+ return verifier_->verifyPackets(&content_object);
+}
+
+auth::VerificationPolicy RTCVerifier::verifyFec(
+ core::ContentObject &content_object) {
+ return verifier_->verifyPackets(&content_object);
+}
+
+auth::VerificationPolicy RTCVerifier::verifyData(
+ core::ContentObject &content_object) {
+ uint32_t suffix = content_object.getName().getSuffix();
+
+ if (_is_ah(content_object.getFormat())) {
+ return verifier_->verifyPackets(&content_object);
+ }
+
+ unverified_bytes_[suffix] =
+ content_object.headerSize() + content_object.payloadSize();
+ unverified_packets_[suffix] =
+ content_object.computeDigest(manifest_hash_algo_);
+
+ // An alert is raised when too much packets remain unverified
+ if (getTotalUnverified() > max_unverified_bytes_) {
+ unverified_bytes_.clear();
+ unverified_packets_.clear();
+
+ auth::VerificationPolicy policy = auth::VerificationPolicy::ABORT;
+ verifier_->callVerificationFailedCallback(suffix, policy);
+ return policy;
+ }
+
+ return auth::VerificationPolicy::ACCEPT;
+}
+
+auth::VerificationPolicy RTCVerifier::verifyManifest(
+ core::ContentObject &content_object) {
+ return verifier_->verifyPackets(&content_object);
+}
+
+auth::VerificationPolicy RTCVerifier::processManifest(
+ core::ContentObject &content_object) {
+ uint32_t suffix = content_object.getName().getSuffix();
+
+ core::ContentObjectManifest manifest(content_object);
+ manifest.decode();
+
+ // Update last manifest
+ if (suffix > last_manifest_) {
+ last_manifest_ = suffix;
+ }
+
+ // Extract parameters
+ manifest_hash_algo_ = manifest.getHashAlgorithm();
+ core::ParamsRTC params = manifest.getParamsRTC();
+
+ if (params.prod_rate > 0) {
+ max_unverified_bytes_ = static_cast<uint64_t>(
+ (max_unverified_delay_ / 1000.0) * params.prod_rate);
+ }
+
+ if (max_unverified_bytes_ == 0 || !rtc_state_) {
+ auth::VerificationPolicy policy = auth::VerificationPolicy::ABORT;
+ verifier_->callVerificationFailedCallback(suffix, policy);
+ return policy;
+ }
+
+ // Extract hashes
+ auth::Verifier::SuffixMap suffix_map =
+ core::ContentObjectManifest::getSuffixMap(&manifest);
+
+ // Return early if the manifest is empty
+ if (suffix_map.empty()) {
+ return auth::VerificationPolicy::ACCEPT;
+ }
+
+ // Remove lost packets from digest map
+ manifest_digests_.insert(suffix_map.begin(), suffix_map.end());
+ for (auto it = manifest_digests_.begin(); it != manifest_digests_.end();) {
+ if (rtc_state_->getPacketState(it->first) == PacketState::DEFINITELY_LOST) {
+ unverified_packets_.erase(it->first);
+ unverified_bytes_.erase(it->first);
+ it = manifest_digests_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Verify packets
+ auth::Verifier::PolicyMap policies =
+ verifier_->verifyHashes(unverified_packets_, manifest_digests_);
+
+ for (const auto &policy : policies) {
+ switch (policy.second) {
+ case auth::VerificationPolicy::ACCEPT: {
+ manifest_digests_.erase(policy.first);
+ unverified_packets_.erase(policy.first);
+ unverified_bytes_.erase(policy.first);
+ break;
+ }
+ case auth::VerificationPolicy::UNKNOWN:
+ break;
+ case auth::VerificationPolicy::DROP:
+ case auth::VerificationPolicy::ABORT:
+ auth::VerificationPolicy p = policy.second;
+ verifier_->callVerificationFailedCallback(policy.first, p);
+ return p;
+ }
+ }
+
+ return auth::VerificationPolicy::ACCEPT;
+}
+
+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
+ // probably won't be verified. Those packets have a suffix in the range
+ // [last_manifest_ + 1, next_suffix[.
+ for (auto it = unverified_packets_.begin();
+ it != unverified_packets_.end();) {
+ if (it->first > last_manifest_) {
+ unverified_bytes_.erase(it->first);
+ it = unverified_packets_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+uint32_t RTCVerifier::getTotalUnverified() const {
+ uint32_t total = 0;
+
+ for (auto bytes : unverified_bytes_) {
+ if (bytes.second > UINT32_MAX - total) {
+ total = UINT32_MAX;
+ break;
+ }
+ total += bytes.second;
+ }
+
+ return total;
+}
+
+uint32_t RTCVerifier::getMaxUnverified() const { return max_unverified_bytes_; }
+
+} // end namespace rtc
+} // end namespace protocol
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_verifier.h b/libtransport/src/protocols/rtc/rtc_verifier.h
new file mode 100644
index 000000000..596bd8536
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_verifier.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <core/facade.h>
+#include <hicn/transport/auth/verifier.h>
+#include <hicn/transport/core/content_object.h>
+#include <protocols/rtc/rtc_state.h>
+
+namespace transport {
+namespace protocol {
+namespace rtc {
+
+class RTCVerifier {
+ public:
+ RTCVerifier(std::shared_ptr<auth::Verifier> verifier,
+ uint32_t max_unverified_delay);
+
+ virtual ~RTCVerifier() = default;
+
+ void setState(std::shared_ptr<RTCState> rtc_state);
+
+ void setVerifier(std::shared_ptr<auth::Verifier> verifier);
+
+ void setMaxUnverifiedDelay(uint32_t max_unverified_delay);
+
+ void onDataRecoveredFec(uint32_t suffix);
+ void onJumpForward(uint32_t next_suffix);
+
+ uint32_t getTotalUnverified() const;
+ uint32_t getMaxUnverified() const;
+
+ auth::VerificationPolicy verify(core::ContentObject &content_object,
+ bool is_fec = false);
+ auth::VerificationPolicy verifyProbe(core::ContentObject &content_object);
+ auth::VerificationPolicy verifyNack(core::ContentObject &content_object);
+ auth::VerificationPolicy verifyFec(core::ContentObject &content_object);
+ auth::VerificationPolicy verifyData(core::ContentObject &content_object);
+ auth::VerificationPolicy verifyManifest(core::ContentObject &content_object);
+
+ auth::VerificationPolicy processManifest(core::ContentObject &content_object);
+
+ protected:
+ // The RTC state.
+ std::shared_ptr<RTCState> rtc_state_;
+ // The verifier instance.
+ std::shared_ptr<auth::Verifier> verifier_;
+ // Hash algorithm used by manifests.
+ auth::CryptoHashType manifest_hash_algo_;
+ // The last manifest processed.
+ auth::Suffix last_manifest_;
+ // Hold digests extracted from all manifests received.
+ auth::Verifier::SuffixMap manifest_digests_;
+ // Hold hashes of all content objects received before they are verified.
+ auth::Verifier::SuffixMap unverified_packets_;
+ // Hold number of unverified bytes.
+ std::unordered_map<auth::Suffix, uint32_t> unverified_bytes_;
+ // Maximum delay (in ms) for an unverified byte to become verifed.
+ uint32_t max_unverified_delay_;
+ // Maximum number of unverified bytes before aborting the connection.
+ uint64_t max_unverified_bytes_;
+};
+
+} // end namespace rtc
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/transport_protocol.cc b/libtransport/src/protocols/transport_protocol.cc
index d6954ac37..f1e49ec0b 100644
--- a/libtransport/src/protocols/transport_protocol.cc
+++ b/libtransport/src/protocols/transport_protocol.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -25,7 +25,8 @@ using namespace interface;
TransportProtocol::TransportProtocol(implementation::ConsumerSocket *icn_socket,
Indexer *indexer, Reassembly *reassembly)
- : socket_(icn_socket),
+ : Protocol(),
+ socket_(icn_socket),
indexer_verifier_(indexer),
reassembly_(reassembly),
fec_decoder_(nullptr),
@@ -36,90 +37,82 @@ TransportProtocol::TransportProtocol(implementation::ConsumerSocket *icn_socket,
on_interest_satisfied_(VOID_HANDLER),
on_content_object_input_(VOID_HANDLER),
stats_summary_(VOID_HANDLER),
+ on_fwd_strategy_(VOID_HANDLER),
+ on_rec_strategy_(VOID_HANDLER),
on_payload_(VOID_HANDLER),
- fec_type_(fec::FECType::UNKNOWN),
- is_running_(false) {
+ fec_type_(fec::FECType::UNKNOWN) {
socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
- // Set this transport protocol as portal's consumer callback
- portal_->setConsumerCallback(this);
-
indexer_verifier_->setReassembly(reassembly_.get());
reassembly->setIndexer(indexer_verifier_.get());
}
+TransportProtocol::~TransportProtocol() {}
+
int TransportProtocol::start() {
// If the protocol is already running, return otherwise set as running
- if (is_running_) return -1;
-
- // Get all callbacks references
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_RETRANSMISSION,
- &on_interest_retransmission_);
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_OUTPUT,
- &on_interest_output_);
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_EXPIRED,
- &on_interest_timeout_);
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_SATISFIED,
- &on_interest_satisfied_);
- socket_->getSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
- &on_content_object_input_);
- socket_->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
- &stats_summary_);
- socket_->getSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
- &on_payload_);
-
- socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
-
- // Set it is the first time we schedule an interest
- is_first_ = true;
-
- // Reset the protocol state machine
- reset();
-
- // Schedule next interests
- scheduleNextInterests();
-
- is_first_ = false;
-
- // Set the protocol as running
- is_running_ = true;
-
- if (!is_async_) {
- // Start Event loop
- portal_->runEventsLoop();
-
- // Not running anymore
- is_running_ = false;
+ if (isRunning()) {
+ return -1;
}
- return 0;
-}
-
-void TransportProtocol::stop() {
- is_running_ = false;
+ // Start protocol on its own thread
+ portal_->getThread().add([this]() {
+ // Get all callbacks references
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_RETRANSMISSION,
+ &on_interest_retransmission_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_OUTPUT,
+ &on_interest_output_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_EXPIRED,
+ &on_interest_timeout_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_SATISFIED,
+ &on_interest_satisfied_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
+ &on_content_object_input_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
+ &stats_summary_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::FWD_STRATEGY_CHANGE,
+ &on_fwd_strategy_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::REC_STRATEGY_CHANGE,
+ &on_rec_strategy_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
+ &on_payload_);
+
+ socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+
+ std::string fec_type_str = "";
+ socket_->getSocketOption(GeneralTransportOptions::FEC_TYPE, fec_type_str);
+ if (fec_type_str != "") {
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_type_str.c_str());
+ }
+
+ // Set it is the first time we schedule an interest
+ is_first_ = true;
+
+ // Reset the protocol state machine
+ reset();
+
+ // Set this transport protocol as portal's consumer callback
+ portal_->registerTransportCallback(this);
+
+ // Schedule next interests
+ scheduleNextInterests();
+
+ is_first_ = false;
+
+ // Set the protocol as running
+ setRunning();
+ });
- if (!is_async_) {
- portal_->stopEventsLoop();
- } else {
- portal_->clear();
- }
+ return 0;
}
void TransportProtocol::resume() {
if (isRunning()) return;
- is_running_ = true;
+ setRunning();
- scheduleNextInterests();
-
- if (!is_async_) {
- // Start Event loop
- portal_->runEventsLoop();
-
- // Not running anymore
- is_running_ = false;
- }
+ portal_->getThread().tryRunHandlerNow([this]() { scheduleNextInterests(); });
}
void TransportProtocol::reset() {
@@ -130,7 +123,7 @@ void TransportProtocol::reset() {
}
}
-void TransportProtocol::onContentReassembled(std::error_code ec) {
+void TransportProtocol::onContentReassembled(const std::error_code &ec) {
stop();
if (!on_payload_) {
@@ -153,7 +146,12 @@ void TransportProtocol::sendInterest(
uint32_t len) {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending interest for name " << interest_name;
- auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
+ Packet::Format format;
+ socket_->getSocketOption(interface::GeneralTransportOptions::PACKET_FORMAT,
+ format);
+
+ auto interest =
+ core::PacketManager<>::getInstance().getPacket<Interest>(format);
interest->setName(interest_name);
for (uint32_t i = 0; i < len; i++) {
@@ -176,6 +174,14 @@ void TransportProtocol::sendInterest(
portal_->sendInterest(std::move(interest));
}
+void TransportProtocol::onError(const std::error_code &ec) {
+ // error from portal: stop socket
+ stop();
+
+ // signal error to application
+ on_payload_->readError(ec);
+}
+
void TransportProtocol::onTimeout(Interest::Ptr &i, const Name &n) {
if (TRANSPORT_EXPECT_FALSE(!isRunning())) {
return;
diff --git a/libtransport/src/protocols/transport_protocol.h b/libtransport/src/protocols/transport_protocol.h
index 1008a238b..ad8cf0346 100644
--- a/libtransport/src/protocols/transport_protocol.h
+++ b/libtransport/src/protocols/transport_protocol.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -19,10 +19,10 @@
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/interfaces/statistics.h>
#include <hicn/transport/utils/object_pool.h>
-#include <implementation/socket.h>
#include <protocols/data_processing_events.h>
#include <protocols/fec_base.h>
#include <protocols/indexer.h>
+#include <protocols/protocol.h>
#include <protocols/reassembly.h>
#include <array>
@@ -38,8 +38,10 @@ class IndexVerificationManager;
using ReadCallback = interface::ConsumerSocket::ReadCallback;
-class TransportProtocol : public core::Portal::ConsumerCallback,
- public ContentObjectProcessingEventCallback {
+class TransportProtocol
+ : public ContentObjectProcessingEventCallback,
+ public Protocol,
+ public std::enable_shared_from_this<TransportProtocol> {
static constexpr std::size_t interest_pool_size = 4096;
friend class ManifestIndexManager;
@@ -48,13 +50,11 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
TransportProtocol(implementation::ConsumerSocket *icn_socket,
Indexer *indexer, Reassembly *reassembly);
- virtual ~TransportProtocol() = default;
-
- TRANSPORT_ALWAYS_INLINE bool isRunning() { return is_running_; }
+ virtual ~TransportProtocol();
virtual int start();
- virtual void stop();
+ using Protocol::stop;
virtual void resume();
@@ -69,7 +69,7 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
virtual void scheduleNextInterests() = 0;
// Events generated by the indexing
- virtual void onContentReassembled(std::error_code ec);
+ virtual void onContentReassembled(const std::error_code &ec);
virtual void onPacketDropped(Interest &interest,
ContentObject &content_object,
const std::error_code &ec) override = 0;
@@ -90,7 +90,8 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
AllocatorHandler &&allocator_handler) {
if (!fec_decoder_) {
// Try to get FEC from environment
- if (const char *fec_str = std::getenv("TRANSPORT_FEC_TYPE")) {
+ const char *fec_str = std::getenv("TRANSPORT_FEC_TYPE");
+ if (fec_str && (fec_type_ == fec::FECType::UNKNOWN)) {
LOG(INFO) << "Using FEC " << fec_str;
fec_type_ = fec::FECUtils::fecTypeFromString(fec_str);
}
@@ -114,14 +115,13 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
// Consumer Callback
void onContentObject(Interest &i, ContentObject &c) override;
void onTimeout(Interest::Ptr &i, const Name &n) override;
- void onError(std::error_code ec) override {}
+ void onError(const std::error_code &ec) override;
protected:
implementation::ConsumerSocket *socket_;
std::unique_ptr<Indexer> indexer_verifier_;
std::unique_ptr<Reassembly> reassembly_;
std::unique_ptr<fec::ConsumerFEC> fec_decoder_;
- std::shared_ptr<core::Portal> portal_;
// True if it si the first time we schedule an interest
std::atomic<bool> is_first_;
interface::TransportStatistics *stats_;
@@ -134,14 +134,13 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
interface::ConsumerContentObjectCallback *on_content_object_input_;
interface::ConsumerContentObjectCallback *on_content_object_;
interface::ConsumerTimerCallback *stats_summary_;
+ interface::StrategyCallback *on_fwd_strategy_;
+ interface::StrategyCallback *on_rec_strategy_;
ReadCallback *on_payload_;
bool is_async_;
fec::FECType fec_type_;
-
- private:
- std::atomic<bool> is_running_;
};
} // end namespace protocol
diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt
index 26fe7aee1..e7018ceed 100644
--- a/libtransport/src/test/CMakeLists.txt
+++ b/libtransport/src/test/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,42 +11,68 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-include(BuildMacros)
-
+##############################################################
+# Test sources
+##############################################################
list(APPEND TESTS_SRC
main.cc
+ test_aggregated_header.cc
test_auth.cc
- test_consumer_producer_rtc.cc
+ # test_consumer_producer_rtc.cc
test_core_manifest.cc
- test_event_thread.cc
+ # test_event_thread.cc
+ test_fec_base_rs.cc
test_fec_reedsolomon.cc
+ test_fixed_block_allocator.cc
test_indexer.cc
test_interest.cc
test_packet.cc
+ test_packet_allocator.cc
+ test_quality_score.cc
+ test_sessions.cc
+ test_thread_pool.cc
)
if (ENABLE_RELY)
list(APPEND TESTS_SRC
test_fec_rely_wrapper.cc
+ test_fec_base_rely.cc
+ )
+endif()
+
+if (UNIX AND NOT APPLE)
+ list(APPEND TESTS_SRC
+ test_memif_connector.cc
)
endif()
-build_executable(unit_tests
+
+##############################################################
+# Link libraries
+##############################################################
+set(MEMIF_MODULE_LIBRARIES
+ ${LIBRARIES}
+ ${LIBTRANSPORT_SHARED}
+ ${GTEST_LIBRARIES}
+)
+
+
+##############################################################
+# Build single unit test executable and add it to test list
+##############################################################
+build_executable(libtransport_tests
NO_INSTALL
SOURCES ${TESTS_SRC}
LINK_LIBRARIES
- ${LIBRARIES}
- ${LIBTRANSPORT_STATIC}
- ${GTEST_LIBRARIES}
+ ${MEMIF_MODULE_LIBRARIES}
INCLUDE_DIRS
- ${LIBTRANSPORT_INCLUDE_DIRS}
- ${LIBHICN_INCLUDE_DIRS}
- ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ $<TARGET_PROPERTY:${LIBTRANSPORT_SHARED},INCLUDE_DIRECTORIES>
${GTEST_INCLUDE_DIRS}
DEPENDS gtest ${LIBTRANSPORT_SHARED}
COMPONENT ${LIBTRANSPORT_COMPONENT}
- DEFINITIONS "${COMPILER_DEFINITIONS}"
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
LINK_FLAGS ${LINK_FLAGS}
)
-add_test_internal(unit_tests)
+add_test_internal(libtransport_tests)
diff --git a/libtransport/src/test/main.cc b/libtransport/src/test/main.cc
index a4d7ce1b3..591ed0d5b 100644
--- a/libtransport/src/test/main.cc
+++ b/libtransport/src/test/main.cc
@@ -16,7 +16,6 @@
#include <gtest/gtest.h>
int main(int argc, char **argv) {
- srand(time(0));
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
} \ No newline at end of file
diff --git a/libtransport/src/test/test_aggregated_header.cc b/libtransport/src/test/test_aggregated_header.cc
new file mode 100644
index 000000000..0d88af5ab
--- /dev/null
+++ b/libtransport/src/test/test_aggregated_header.cc
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <protocols/rtc/rtc_packet.h>
+#include <test/packet_samples.h>
+
+#include <climits>
+#include <random>
+#include <vector>
+
+namespace transport {
+
+namespace core {
+
+namespace {
+// The fixture for testing class Foo.
+class AggregatedPktHeaderTest : public ::testing::Test {
+ protected:
+ AggregatedPktHeaderTest() {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~AggregatedPktHeaderTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+};
+
+} // namespace
+
+TEST_F(AggregatedPktHeaderTest, Add2Packets8bit) {
+ uint8_t buf[1500];
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {11, 12, 13, 14, 15, 16, 17};
+ uint16_t pkt2_len = 7;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt1_len, 2);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ uint8_t* ptr = hdr.getPayloadAppendPtr();
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ *(ptr + i) = pkt1[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ *(ptr + i + pkt1_len) = pkt2[i];
+ }
+
+ // print
+ // for (uint16_t i = 0; i < 40; i++){
+ // std::cout << (int) i << " " << (int) buf[i] << std::endl;
+ //}
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ hdr.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+}
+
+TEST_F(AggregatedPktHeaderTest, Add2Packets8bit255) {
+ uint8_t buf[1500];
+
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 20
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 40
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 60
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 80
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 100
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 120
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 140
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 160
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 180
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 200
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 220
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 240
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14}; // 255
+ uint16_t pkt2_len = 255;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt2_len, 2);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ uint8_t* ptr = hdr.getPayloadAppendPtr();
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ *(ptr + i) = pkt1[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ *(ptr + i + pkt1_len) = pkt2[i];
+ }
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ hdr.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+}
+
+TEST_F(AggregatedPktHeaderTest, Add2Packets8bit256) {
+ uint8_t buf[1500];
+
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 20
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 40
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 60
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 80
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 100
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 120
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 140
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 160
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 180
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 200
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 220
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 240
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15}; // 256
+ uint16_t pkt2_len = 256;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt2_len, 2);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ uint8_t* ptr = hdr.getPayloadAppendPtr();
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ *(ptr + i) = pkt1[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ *(ptr + i + pkt1_len) = pkt2[i];
+ }
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ hdr.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+}
+
+TEST_F(AggregatedPktHeaderTest, Add4Packets8bit) {
+ uint8_t buf[1500];
+
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {11, 12, 13, 14, 15, 16, 17};
+ uint16_t pkt2_len = 7;
+
+ std::vector<uint8_t> pkt3 = {21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
+ uint16_t pkt3_len = 10;
+
+ std::vector<uint8_t> pkt4 = {100, 110};
+ uint16_t pkt4_len = 2;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt1_len, 4);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ hdr.addPacketToHeader(2, pkt3_len);
+ hdr.addPacketToHeader(3, pkt4_len);
+ uint8_t* ptr = hdr.getPayloadAppendPtr();
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ *(ptr + i) = pkt1[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ *(ptr + i + pkt1_len) = pkt2[i];
+ }
+
+ // copy packet 3
+ for (uint16_t i = 0; i < pkt3_len; i++) {
+ *(ptr + i + pkt1_len + pkt2_len) = pkt3[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt4_len; i++) {
+ *(ptr + i + pkt1_len + pkt2_len + pkt3_len) = pkt4[i];
+ }
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ hdr.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+
+ hdr.getPointerToPacket(2, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt3_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt3[i]);
+ }
+
+ hdr.getPointerToPacket(3, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt4_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt4[i]);
+ }
+}
+
+TEST_F(AggregatedPktHeaderTest, Add4Packets16bit) {
+ uint8_t buf[1500];
+
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {11, 12, 13, 14, 15, 16, 17};
+ uint16_t pkt2_len = 7;
+
+ std::vector<uint8_t> pkt3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 20
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 40
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 60
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 80
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 100
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 120
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 140
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 160
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 180
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 200
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 220
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 240
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; // 260
+ uint16_t pkt3_len = 260;
+
+ std::vector<uint8_t> pkt4 = {100, 110};
+ uint16_t pkt4_len = 2;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt3_len, 4);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ hdr.addPacketToHeader(2, pkt3_len);
+ hdr.addPacketToHeader(3, pkt4_len);
+ uint8_t* ptr = hdr.getPayloadAppendPtr();
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ *(ptr + i) = pkt1[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ *(ptr + i + pkt1_len) = pkt2[i];
+ }
+
+ // copy packet 3
+ for (uint16_t i = 0; i < pkt3_len; i++) {
+ *(ptr + i + pkt1_len + pkt2_len) = pkt3[i];
+ }
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt4_len; i++) {
+ *(ptr + i + pkt1_len + pkt2_len + pkt3_len) = pkt4[i];
+ }
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ hdr.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+
+ hdr.getPointerToPacket(2, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt3_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt3[i]);
+ }
+
+ hdr.getPointerToPacket(3, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt4_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt4[i]);
+ }
+}
+
+TEST_F(AggregatedPktHeaderTest, Defrag4Packets8bit) {
+ uint8_t buf[1500];
+
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {11, 12, 13, 14, 15, 16, 17};
+ uint16_t pkt2_len = 7;
+
+ std::vector<uint8_t> pkt3 = {21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
+ uint16_t pkt3_len = 10;
+
+ std::vector<uint8_t> pkt4 = {100, 110};
+ uint16_t pkt4_len = 2;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt1_len, 4);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ hdr.addPacketToHeader(2, pkt3_len);
+ hdr.addPacketToHeader(3, pkt4_len);
+
+ uint16_t offset = protocol::rtc::DATA_HEADER_SIZE + 8; // 8 = aggr hdr
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ buf[i + offset] = pkt1[i];
+ }
+ offset += pkt1_len;
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ buf[i + offset] = pkt2[i];
+ }
+ offset += pkt2_len;
+
+ // copy packet 3
+ for (uint16_t i = 0; i < pkt3_len; i++) {
+ buf[i + offset] = pkt3[i];
+ }
+ offset += pkt3_len;
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt4_len; i++) {
+ buf[i + offset] = pkt4[i];
+ }
+
+ protocol::rtc::AggrPktHeader hdr2(buf + protocol::rtc::DATA_HEADER_SIZE);
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ uint8_t packet_number = hdr2.getNumberOfPackets();
+ EXPECT_EQ(packet_number, 4);
+
+ hdr2.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr2.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+
+ hdr2.getPointerToPacket(2, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt3_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt3[i]);
+ }
+
+ hdr2.getPointerToPacket(3, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt4_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt4[i]);
+ }
+}
+
+TEST_F(AggregatedPktHeaderTest, Defrag4Packets16bit) {
+ uint8_t buf[1500];
+
+ std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ uint16_t pkt1_len = 14;
+
+ std::vector<uint8_t> pkt2 = {11, 12, 13, 14, 15, 16, 17};
+ uint16_t pkt2_len = 7;
+
+ std::vector<uint8_t> pkt3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 20
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 40
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 60
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 80
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 100
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 120
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 140
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 160
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 180
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 200
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 220
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 240
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; // 260
+ uint16_t pkt3_len = 260;
+
+ std::vector<uint8_t> pkt4 = {100, 110};
+ uint16_t pkt4_len = 2;
+
+ for (uint16_t i = 0; i < 1500; i++) {
+ buf[i] = 0;
+ }
+
+ // skip protocol::rtc::DATA_HEADER_SIZE that will be the rtc header
+ protocol::rtc::AggrPktHeader hdr(buf + protocol::rtc::DATA_HEADER_SIZE,
+ pkt3_len, 4);
+ hdr.addPacketToHeader(0, pkt1_len);
+ hdr.addPacketToHeader(1, pkt2_len);
+ hdr.addPacketToHeader(2, pkt3_len);
+ hdr.addPacketToHeader(3, pkt4_len);
+
+ uint16_t offset = protocol::rtc::DATA_HEADER_SIZE + 12; // 12 = aggr hdr
+
+ // copy packet 1
+ for (uint16_t i = 0; i < pkt1_len; i++) {
+ buf[i + offset] = pkt1[i];
+ }
+ offset += pkt1_len;
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt2_len; i++) {
+ buf[i + offset] = pkt2[i];
+ }
+ offset += pkt2_len;
+
+ // copy packet 3
+ for (uint16_t i = 0; i < pkt3_len; i++) {
+ buf[i + offset] = pkt3[i];
+ }
+ offset += pkt3_len;
+
+ // copy packet 2
+ for (uint16_t i = 0; i < pkt4_len; i++) {
+ buf[i + offset] = pkt4[i];
+ }
+
+ protocol::rtc::AggrPktHeader hdr2(buf + protocol::rtc::DATA_HEADER_SIZE);
+
+ uint8_t* pkt_ptr = nullptr;
+ uint16_t pkt_len = 0;
+
+ uint8_t packet_number = hdr2.getNumberOfPackets();
+ EXPECT_EQ(packet_number, 4);
+
+ hdr2.getPointerToPacket(0, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt1_len);
+ for (uint16_t i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt1[i]);
+ }
+
+ hdr2.getPointerToPacket(1, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt2_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt2[i]);
+ }
+
+ hdr2.getPointerToPacket(2, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt3_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt3[i]);
+ }
+
+ hdr2.getPointerToPacket(3, &pkt_ptr, &pkt_len);
+ EXPECT_EQ(pkt_len, pkt4_len);
+ for (int i = 0; i < pkt_len; i++) {
+ EXPECT_EQ(*(pkt_ptr + i), pkt4[i]);
+ }
+}
+
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/test/test_auth.cc b/libtransport/src/test/test_auth.cc
index db1c3b52f..d7fd55433 100644
--- a/libtransport/src/test/test_auth.cc
+++ b/libtransport/src/test/test_auth.cc
@@ -15,10 +15,15 @@
#include <gtest/gtest.h>
#include <hicn/transport/auth/crypto_hash.h>
-#include <hicn/transport/auth/identity.h>
#include <hicn/transport/auth/signer.h>
#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/core/content_object.h>
+#include <openssl/rand.h>
+
+using BN_ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
+using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
+using EC_KEY_ptr = std::unique_ptr<EC_KEY, decltype(&::EC_KEY_free)>;
+using DSA_ptr = std::unique_ptr<DSA, decltype(&::DSA_free)>;
namespace transport {
namespace auth {
@@ -50,11 +55,23 @@ TEST_F(AuthTest, VoidVerifier) {
}
TEST_F(AuthTest, AsymmetricRSA) {
- // Create the RSA signer from an Identity object
- Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u,
- 30, "RSAVerifier");
-
- std::shared_ptr<Signer> signer = identity.getSigner();
+ // Create the RSA keys
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
+ std::shared_ptr<EVP_PKEY> pubKey(EVP_PKEY_new(), EVP_PKEY_free);
+ RSA_ptr rsa(RSA_new(), ::RSA_free);
+ BN_ptr pub_exp(BN_new(), ::BN_free);
+
+ BN_set_word(pub_exp.get(), RSA_F4);
+ if (1 != RSA_generate_key_ex(rsa.get(), 2048u, pub_exp.get(), NULL))
+ throw errors::RuntimeException("can't generate the key");
+ RSA_ptr rsa_pub(RSAPublicKey_dup(rsa.get()), ::RSA_free);
+ RSA_ptr rsa_priv(RSAPrivateKey_dup(rsa.get()), ::RSA_free);
+ if (1 != EVP_PKEY_set1_RSA(pubKey.get(), rsa_pub.get()))
+ throw errors::RuntimeException("can't generate the key");
+ if (1 != EVP_PKEY_set1_RSA(privateKey.get(), rsa_priv.get()))
+ throw errors::RuntimeException("can't generate the key");
+ std::shared_ptr<AsymmetricSigner> signer = std::make_shared<AsymmetricSigner>(
+ CryptoSuite::RSA_SHA256, privateKey, pubKey);
// Create a content object
core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
@@ -68,61 +85,112 @@ TEST_F(AuthTest, AsymmetricRSA) {
// Create the RSA verifier
std::shared_ptr<Verifier> verifier =
- std::make_shared<AsymmetricVerifier>(identity.getCertificate());
+ std::make_shared<AsymmetricVerifier>(pubKey);
EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256);
EXPECT_EQ(signer->getSuite(), CryptoSuite::RSA_SHA256);
- EXPECT_EQ(signer->getSignatureSize(), 128u);
+ EXPECT_EQ(signer->getSignatureSize(), 256u);
EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
}
TEST_F(AuthTest, AsymmetricBufferRSA) {
- // Create the RSA signer from an Identity object
- Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u,
- 30, "RSAVerifier");
+ // Create the RSA keys
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
+ std::shared_ptr<EVP_PKEY> pubKey(EVP_PKEY_new(), EVP_PKEY_free);
+ RSA_ptr rsa(RSA_new(), ::RSA_free);
+ BN_ptr pub_exp(BN_new(), ::BN_free);
+
+ BN_set_word(pub_exp.get(), RSA_F4);
+ if (1 != RSA_generate_key_ex(rsa.get(), 2048u, pub_exp.get(), NULL))
+ throw errors::RuntimeException("can't generate the key");
+ RSA_ptr rsa_pub(RSAPublicKey_dup(rsa.get()), ::RSA_free);
+ RSA_ptr rsa_priv(RSAPrivateKey_dup(rsa.get()), ::RSA_free);
+ if (1 != EVP_PKEY_set1_RSA(pubKey.get(), rsa_pub.get()))
+ throw errors::RuntimeException("can't generate the key");
+ if (1 != EVP_PKEY_set1_RSA(privateKey.get(), rsa_priv.get()))
+ throw errors::RuntimeException("can't generate the key");
+ std::shared_ptr<AsymmetricSigner> signer = std::make_shared<AsymmetricSigner>(
+ CryptoSuite::RSA_SHA256, privateKey, pubKey);
- std::shared_ptr<AsymmetricSigner> signer = identity.getSigner();
std::string payload = "bonjour";
std::vector<uint8_t> buffer(payload.begin(), payload.end());
signer->signBuffer(buffer);
std::vector<uint8_t> sig = signer->getSignature();
- std::shared_ptr<X509> cert = identity.getCertificate();
- AsymmetricVerifier verif(cert);
- bool res = verif.verifyBuffer(
+ std::shared_ptr<AsymmetricVerifier> verif =
+ std::make_shared<AsymmetricVerifier>(pubKey);
+ bool res = verif->verifyBuffer(
buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
CryptoHashType::SHA256);
EXPECT_EQ(res, true);
}
TEST_F(AuthTest, AsymmetricBufferDSA) {
- // Create the DSA signer from an Identity object
- Identity identity("test_dsa.p12", PASSPHRASE, CryptoSuite::DSA_SHA256, 1024u,
- 30, "DSAVerifier");
+ // Create the DSA keys
+
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
+
+ DSA_ptr dsa(DSA_new(), ::DSA_free);
+ unsigned char buf[32];
+ if (RAND_bytes(buf, sizeof(buf)) != 1) {
+ throw errors::RuntimeException("can't generate the key");
+ }
+ if (DSA_generate_parameters_ex(dsa.get(), 1024u, buf, sizeof(buf), NULL, NULL,
+ NULL) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (DSA_generate_key(dsa.get()) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (EVP_PKEY_set1_DSA(privateKey.get(), dsa.get()) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (1 != EVP_PKEY_set1_DSA(privateKey.get(), dsa.get()))
+ throw errors::RuntimeException("can't generate the key");
+
+ std::shared_ptr<X509> cert(X509_new(), ::X509_free);
+ X509_set_pubkey(cert.get(), privateKey.get());
+ std::shared_ptr<EVP_PKEY> pubKey(X509_get_pubkey(cert.get()), EVP_PKEY_free);
+ std::shared_ptr<AsymmetricSigner> signer = std::make_shared<AsymmetricSigner>(
+ CryptoSuite::DSA_SHA256, privateKey, pubKey);
- std::shared_ptr<AsymmetricSigner> signer = identity.getSigner();
std::string payload = "bonjour";
std::vector<uint8_t> buffer(payload.begin(), payload.end());
signer->signBuffer(buffer);
std::vector<uint8_t> sig = signer->getSignature();
- std::shared_ptr<X509> cert = identity.getCertificate();
- AsymmetricVerifier verif(cert);
- bool res = verif.verifyBuffer(
+ std::shared_ptr<AsymmetricVerifier> verif =
+ std::make_shared<AsymmetricVerifier>(pubKey);
+ bool res = verif->verifyBuffer(
buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
CryptoHashType::SHA256);
EXPECT_EQ(res, true);
}
TEST_F(AuthTest, AsymmetricVerifierDSA) {
- // Create the DSA signer from an Identity object
- Identity identity("test_dsa.p12", PASSPHRASE, CryptoSuite::DSA_SHA256, 1024u,
- 30, "DSAVerifier");
+ // Create the DSA keys
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
- std::shared_ptr<Signer> signer = identity.getSigner();
+ DSA_ptr dsa(DSA_new(), ::DSA_free);
+ unsigned char buf[32];
+ if (RAND_bytes(buf, sizeof(buf)) != 1) {
+ throw errors::RuntimeException("can't generate the key");
+ }
+ if (DSA_generate_parameters_ex(dsa.get(), 1024u, buf, sizeof(buf), NULL, NULL,
+ NULL) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (DSA_generate_key(dsa.get()) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (EVP_PKEY_set1_DSA(privateKey.get(), dsa.get()) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (1 != EVP_PKEY_set1_DSA(privateKey.get(), dsa.get()))
+ throw errors::RuntimeException("can't generate the key");
+
+ std::shared_ptr<X509> cert(X509_new(), ::X509_free);
+ X509_set_pubkey(cert.get(), privateKey.get());
+ std::shared_ptr<EVP_PKEY> pubKey(X509_get_pubkey(cert.get()), EVP_PKEY_free);
+ std::shared_ptr<AsymmetricSigner> signer = std::make_shared<AsymmetricSigner>(
+ CryptoSuite::DSA_SHA256, privateKey, pubKey);
// Create a content object
core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
@@ -134,7 +202,7 @@ TEST_F(AuthTest, AsymmetricVerifierDSA) {
// EXPECT_EQ(signer->getSignatureSize(), 256u);
signer->signPacket(&packet);
std::shared_ptr<Verifier> verifier =
- std::make_shared<AsymmetricVerifier>(identity.getCertificate());
+ std::make_shared<AsymmetricVerifier>(cert);
EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256);
@@ -143,33 +211,59 @@ TEST_F(AuthTest, AsymmetricVerifierDSA) {
}
TEST_F(AuthTest, AsymmetricBufferECDSA) {
- // Create the ECDSA signer from an Identity object
- Identity identity("test_ecdsa.p12", PASSPHRASE, CryptoSuite::ECDSA_SHA256,
- 256u, 30, "ECDSAVerifier");
+ // Create the ECDSA keys
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
+ std::shared_ptr<EVP_PKEY> pubKey(EVP_PKEY_new(), EVP_PKEY_free);
+ EC_KEY_ptr ec_priv(EC_KEY_new_by_curve_name(NID_secp256k1), ::EC_KEY_free);
+ EC_KEY_ptr ec_pub(EC_KEY_new(), ::EC_KEY_free);
+ EC_KEY_set_asn1_flag(ec_priv.get(), OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_generate_key(ec_priv.get()) == 0)
+ throw errors::RuntimeException("can't generate the ecdsa key");
+ if (1 != EVP_PKEY_set1_EC_KEY(privateKey.get(), ec_priv.get()))
+ throw errors::RuntimeException("can't generate the key");
+ EC_KEY_set_group(ec_pub.get(), EC_KEY_get0_group(ec_priv.get()));
+ EC_KEY_set_public_key(ec_pub.get(), EC_KEY_get0_public_key(ec_priv.get()));
+ if (1 != EVP_PKEY_set1_EC_KEY(pubKey.get(), ec_pub.get()))
+ throw errors::RuntimeException("can't generate the key");
+
+ std::shared_ptr<AsymmetricSigner> signer = std::make_shared<AsymmetricSigner>(
+ CryptoSuite::ECDSA_SHA256, privateKey, pubKey);
- std::shared_ptr<AsymmetricSigner> signer = identity.getSigner();
std::string payload = "bonjour";
std::vector<uint8_t> buffer(payload.begin(), payload.end());
signer->signBuffer(buffer);
std::vector<uint8_t> sig = signer->getSignature();
- std::shared_ptr<X509> cert = identity.getCertificate();
- AsymmetricVerifier verif(cert);
- bool res = verif.verifyBuffer(
+ std::shared_ptr<AsymmetricVerifier> verif =
+ std::make_shared<AsymmetricVerifier>(pubKey);
+ bool res = verif->verifyBuffer(
buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
CryptoHashType::SHA256);
EXPECT_EQ(res, true);
-}
+} // namespace auth
TEST_F(AuthTest, AsymmetricVerifierECDSA) {
- Identity identity("test_ecdsa.p12", PASSPHRASE, CryptoSuite::ECDSA_SHA256,
- 256u, 30, "ECDSAVerifier");
-
- std::shared_ptr<Signer> signer = identity.getSigner();
- std::shared_ptr<Verifier> verifier =
- std::make_shared<AsymmetricVerifier>(identity.getCertificate());
- // Create a content object
+ // Create the ECDSA keys
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
+ std::shared_ptr<EVP_PKEY> pubKey(EVP_PKEY_new(), EVP_PKEY_free);
+ EC_KEY_ptr ec_priv(EC_KEY_new_by_curve_name(NID_secp256k1), ::EC_KEY_free);
+ EC_KEY_ptr ec_pub(EC_KEY_new(), ::EC_KEY_free);
+ EC_KEY_set_asn1_flag(ec_priv.get(), OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_generate_key(ec_priv.get()) == 0)
+ throw errors::RuntimeException("can't generate the ecdsa key");
+ if (1 != EVP_PKEY_set1_EC_KEY(privateKey.get(), ec_priv.get()))
+ throw errors::RuntimeException("can't generate the key");
+ EC_KEY_set_group(ec_pub.get(), EC_KEY_get0_group(ec_priv.get()));
+ EC_KEY_set_public_key(ec_pub.get(), EC_KEY_get0_public_key(ec_priv.get()));
+ if (1 != EVP_PKEY_set1_EC_KEY(pubKey.get(), ec_pub.get()))
+ throw errors::RuntimeException("can't generate the key");
+
+ std::shared_ptr<AsymmetricSigner> signer = std::make_shared<AsymmetricSigner>(
+ CryptoSuite::ECDSA_SHA256, privateKey, pubKey);
+
+ std::shared_ptr<AsymmetricVerifier> verifier =
+ std::make_shared<AsymmetricVerifier>(pubKey);
for (int i = 0; i < 100; i++) {
core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
diff --git a/libtransport/src/test/test_consumer_producer_rtc.cc b/libtransport/src/test/test_consumer_producer_rtc.cc
index 8541a9e1a..b11a6a388 100644
--- a/libtransport/src/test/test_consumer_producer_rtc.cc
+++ b/libtransport/src/test/test_consumer_producer_rtc.cc
@@ -41,7 +41,7 @@ class ConsumerProducerTest : public ::testing::Test,
rtc_timer_(io_service_),
stop_timer_(io_service_),
consumer_(TransportProtocolAlgorithms::RTC, io_service_),
- producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_),
+ producer_(ProductionProtocolAlgorithms::RTC_PROD, thread_),
producer_prefix_(prefix),
consumer_name_(name),
packets_sent_(0),
@@ -120,14 +120,13 @@ class ConsumerProducerTest : public ::testing::Test,
size_t maxBufferSize() const override { return receive_buffer_size; }
- void readError(const std::error_code ec) noexcept override {
- FAIL() << "Error while reading from RTC socket";
+ void readError(const std::error_code &ec) noexcept override {
io_service_.stop();
+ FAIL() << "Error while reading from RTC socket";
}
void readSuccess(std::size_t total_size) noexcept override {
packets_received_++;
- std::cout << "Received something" << std::endl;
}
asio::io_service io_service_;
diff --git a/libtransport/src/test/test_core_manifest.cc b/libtransport/src/test/test_core_manifest.cc
index 93f4e87cb..23fd5e342 100644
--- a/libtransport/src/test/test_core_manifest.cc
+++ b/libtransport/src/test/test_core_manifest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,6 +17,8 @@
#include <core/manifest_inline.h>
#include <gtest/gtest.h>
#include <hicn/transport/auth/crypto_hash.h>
+#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/auth/verifier.h>
#include <test/packet_samples.h>
#include <climits>
@@ -33,7 +35,7 @@ class ManifestTest : public ::testing::Test {
protected:
using ContentObjectManifest = ManifestInline<ContentObject, Fixed>;
- ManifestTest() : name_("b001::123|321"), manifest1_(name_) {
+ ManifestTest() : name_("b001::123|321"), manifest1_(HF_INET6_TCP_AH, name_) {
// You can do set-up work for each test here.
}
@@ -97,8 +99,8 @@ TEST_F(ManifestTest, MoveConstructor) {
TEST_F(ManifestTest, SetLastManifest) {
manifest1_.clear();
- manifest1_.setFinalManifest(true);
- bool fcn = manifest1_.isFinalManifest();
+ manifest1_.setIsLast(true);
+ bool fcn = manifest1_.getIsLast();
ASSERT_TRUE(fcn == true);
}
@@ -109,13 +111,13 @@ TEST_F(ManifestTest, SetManifestType) {
ManifestType type1 = ManifestType::INLINE_MANIFEST;
ManifestType type2 = ManifestType::FLIC_MANIFEST;
- manifest1_.setManifestType(type1);
- ManifestType type_returned1 = manifest1_.getManifestType();
+ manifest1_.setType(type1);
+ ManifestType type_returned1 = manifest1_.getType();
manifest1_.clear();
- manifest1_.setManifestType(type2);
- ManifestType type_returned2 = manifest1_.getManifestType();
+ manifest1_.setType(type2);
+ ManifestType type_returned2 = manifest1_.getType();
ASSERT_EQ(type1, type_returned1);
ASSERT_EQ(type2, type_returned2);
@@ -146,17 +148,80 @@ TEST_F(ManifestTest, SetHashAlgorithm) {
ASSERT_EQ(hash3, type_returned3);
}
-TEST_F(ManifestTest, SetNextSegmentCalculationStrategy) {
+TEST_F(ManifestTest, setParamsBytestream) {
manifest1_.clear();
- NextSegmentCalculationStrategy strategy1 =
- NextSegmentCalculationStrategy::INCREMENTAL;
+ ParamsBytestream params{
+ .final_segment = 1,
+ };
+
+ manifest1_.setParamsBytestream(params);
+ manifest1_.encode();
+
+ ContentObjectManifest manifest(manifest1_);
+ manifest.decode();
+
+ ASSERT_EQ(interface::ProductionProtocolAlgorithms::BYTE_STREAM,
+ manifest.getTransportType());
+ ASSERT_EQ(params, manifest.getParamsBytestream());
+}
+
+TEST_F(ManifestTest, SetParamsRTC) {
+ manifest1_.clear();
+
+ ParamsRTC params{
+ .timestamp = 1,
+ .prod_rate = 2,
+ .prod_seg = 3,
+ .support_fec = 1,
+ };
+
+ manifest1_.setParamsRTC(params);
+ manifest1_.encode();
- manifest1_.setNextSegmentCalculationStrategy(strategy1);
- NextSegmentCalculationStrategy type_returned1 =
- manifest1_.getNextSegmentCalculationStrategy();
+ ContentObjectManifest manifest(manifest1_);
+ manifest.decode();
+
+ ASSERT_EQ(interface::ProductionProtocolAlgorithms::RTC_PROD,
+ manifest.getTransportType());
+ ASSERT_EQ(params, manifest.getParamsRTC());
+}
- ASSERT_EQ(strategy1, type_returned1);
+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()));
+
+ // Add Manifest entry
+ auth::CryptoHash hash(signer->getHashType());
+ hash.computeDigest(std::vector<uint8_t>{0x01, 0x02, 0x03, 0x04});
+ manifest->addSuffixHash(1, hash);
+
+ // Encode manifest
+ manifest->encode();
+
+ // Sign manifest
+ signer->signPacket(manifest.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());
+
+ // Verify manifest
+ auth::VerificationPolicy policy = verifier->verifyPackets(manifest.get());
+ ASSERT_EQ(auth::VerificationPolicy::ACCEPT, policy);
}
TEST_F(ManifestTest, SetBaseName) {
@@ -198,23 +263,8 @@ TEST_F(ManifestTest, SetSuffixList) {
}
manifest1_.setBaseName(base_name);
-
core::Name ret_name = manifest1_.getBaseName();
- // auto & hash_list = manifest1_.getSuffixHashList();
-
- // bool cond;
- // int i = 0;
-
- // for (auto & item : manifest1_.getSuffixList()) {
- // auto hash = manifest1_.getHash(suffixes[i]);
- // cond = auth::CryptoHash::compareBinaryDigest(hash,
- // entries[i].second.getDigest<uint8_t>().data(),
- // entries[i].second.getType());
- // ASSERT_TRUE(cond);
- // i++;
- // }
-
ASSERT_EQ(base_name, ret_name);
delete[] entries;
diff --git a/libtransport/src/test/test_event_thread.cc b/libtransport/src/test/test_event_thread.cc
index 549ff9c1a..324250717 100644
--- a/libtransport/src/test/test_event_thread.cc
+++ b/libtransport/src/test/test_event_thread.cc
@@ -14,6 +14,7 @@
*/
#include <gtest/gtest.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <hicn/transport/utils/event_thread.h>
#include <cmath>
@@ -48,7 +49,7 @@ class EventThreadTest : public ::testing::Test {
utils::EventThread event_thread_;
};
-double average(const unsigned long samples[], int size) {
+inline double average(const unsigned long samples[], int size) {
double sum = 0;
for (int i = 0; i < size; i++) {
@@ -58,7 +59,7 @@ double average(const unsigned long samples[], int size) {
return sum / size;
}
-double stdDeviation(const unsigned long samples[], int size) {
+inline double stdDeviation(const unsigned long samples[], int size) {
double avg = average(samples, size);
double var = 0;
@@ -72,26 +73,23 @@ double stdDeviation(const unsigned long samples[], int size) {
} // namespace
TEST_F(EventThreadTest, DISABLED_SchedulingDelay) {
- using namespace std::chrono;
- const size_t size = 1000000;
- std::vector<unsigned long> samples(size);
-
- for (unsigned int i = 0; i < size; i++) {
- auto t0 = steady_clock::now();
- event_thread_.add([t0, &samples, i]() {
- auto t1 = steady_clock::now();
- samples[i] = duration_cast<nanoseconds>(t1 - t0).count();
- });
- }
+ // using namespace std::chrono;
+ // const size_t size = 1000000;
+ // std::vector<unsigned long> samples(size);
+
+ // for (unsigned int i = 0; i < size; i++) {
+ // event_thread_.add([t0, &samples, i]() {
+ // });
+ // }
- event_thread_.stop();
+ // event_thread_.stop();
- auto avg = average(&samples[0], size);
- auto sd = stdDeviation(&samples[0], size);
- (void)sd;
+ // auto avg = average(&samples[0], size);
+ // auto sd = stdDeviation(&samples[0], size);
+ // (void)sd;
- // Expect average to be less that 1 ms
- EXPECT_LT(avg, 1000000);
+ // // Expect average to be less that 1 ms
+ // EXPECT_LT(avg, 1000000);
}
} // namespace utils
diff --git a/libtransport/src/test/test_fec_base_rely.cc b/libtransport/src/test/test_fec_base_rely.cc
new file mode 100644
index 000000000..41e1eae49
--- /dev/null
+++ b/libtransport/src/test/test_fec_base_rely.cc
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <protocols/fec_base.h>
+#include <protocols/fec_utils.h>
+#include <protocols/rtc/rtc_consts.h>
+
+#include <algorithm>
+#include <iostream>
+#include <queue>
+#include <random>
+
+namespace transport {
+namespace protocol {
+
+class PacketFactory {
+ public:
+ PacketFactory(){};
+
+ ~PacketFactory(){};
+
+ std::shared_ptr<transport::core::ContentObject> createData(
+ core::Name &name, uint32_t suffix, uint32_t payload_size,
+ uint32_t payload_filler) {
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ // create payload
+ auto buff = packet_manager.getMemBuf();
+ buff->append(payload_size);
+ std::fill(buff->writableData(), buff->writableTail(), payload_filler);
+
+ // create data packet
+ auto data = packet_manager.getPacket<transport::core::ContentObject>(
+ HF_INET6_TCP, 0);
+ struct rtc::data_packet_t header;
+ header.setTimestamp(1000);
+ header.setProductionRate(1);
+ data->appendPayload((const uint8_t *)&header, rtc::DATA_HEADER_SIZE);
+ data->appendPayload(buff->data(), buff->length());
+ data->setName(name.setSuffix(suffix));
+ data->setLifetime(500);
+ data->setPathLabel(12);
+
+ return data;
+ }
+
+ std::shared_ptr<transport::core::ContentObject> createData(
+ core::Name &name, uint32_t suffix, fec::buffer payload) {
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ auto data = packet_manager.getPacket<transport::core::ContentObject>(
+ HF_INET6_TCP, 0);
+ struct rtc::data_packet_t header;
+ header.setTimestamp(1000);
+ header.setProductionRate(1);
+ data->appendPayload((const uint8_t *)&header, rtc::DATA_HEADER_SIZE);
+ data->appendPayload(payload->data(), payload->length());
+ data->setName(name.setSuffix(suffix));
+ data->setLifetime(500);
+ data->setPathLabel(12);
+
+ return data;
+ }
+};
+
+class Encoder {
+ public:
+ Encoder(std::string fec_str) {
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_str.c_str());
+ if (fec_type_ == fec::FECType::UNKNOWN)
+ std::cout << "x" << fec_str << "x" << std::endl;
+ encoder_ = fec::FECUtils::getEncoder(fec_type_, 1);
+ encoder_->setFECCallback(
+ std::bind(&Encoder::onFecPackets, this, std::placeholders::_1));
+ encoder_->setBufferCallback(
+ std::bind(&Encoder::getBuffer, this, std::placeholders::_1));
+ };
+
+ ~Encoder(){};
+
+ void onFecPackets(fec::BufferArray &packets) {
+ for (auto &packet : packets) {
+ fec_packets_.push(packet.getBuffer());
+ }
+ }
+
+ fec::buffer getBuffer(std::size_t size) {
+ auto ret = core::PacketManager<>::getInstance()
+ .getPacket<transport::core::ContentObject>(HF_INET6_TCP, 0);
+ ret->updateLength(rtc::DATA_HEADER_SIZE + size);
+ ret->append(rtc::DATA_HEADER_SIZE + size);
+ ret->trimStart(ret->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ return ret;
+ }
+
+ void onPacketProduced(core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata) {
+ encoder_->onPacketProduced(content_object, offset, metadata);
+ }
+
+ public:
+ std::queue<fec::buffer> fec_packets_;
+
+ private:
+ std::unique_ptr<fec::ProducerFEC> encoder_;
+ fec::FECType fec_type_;
+};
+
+class Decoder {
+ public:
+ Decoder(std::string fec_str) {
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_str.c_str());
+ decoder_ = fec::FECUtils::getDecoder(fec_type_, 1);
+ decoder_->setFECCallback(
+ std::bind(&Decoder::onFecPackets, this, std::placeholders::_1));
+ decoder_->setBufferCallback(fec::FECBase::BufferRequested(0));
+ };
+
+ ~Decoder(){};
+
+ void onFecPackets(fec::BufferArray &packets) {
+ for (auto &packet : packets) {
+ hicn_packet_dump(packet.getBuffer()->data(),
+ packet.getBuffer()->length());
+ recovered_packets_.push(packet.getBuffer());
+ }
+ }
+
+ void onPacketReceived(core::ContentObject &content_object, uint32_t offset) {
+ decoder_->onDataPacket(content_object, offset);
+ }
+
+ public:
+ std::queue<fec::buffer> recovered_packets_;
+
+ private:
+ std::unique_ptr<fec::ConsumerFEC> decoder_;
+ fec::FECType fec_type_;
+};
+
+TEST(FECtestRely, RelyTestInOrder1) {
+ // use Rely k = 2 N = 6
+ std::string fec_str = "Rely_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ // we cannot use the original data 1 to check it we recovered the packet
+ // correclty because Rely modifies the packet so here we create a copy
+ auto data1_copy = pf.createData(name, 1, 50, 1);
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decode in order, data 1 is lost
+ decoder.onPacketReceived(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // check recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ auto recovered = pf.createData(name, 1, decoder.recovered_packets_.front());
+
+ bool eq_len = (data1_copy->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data1_copy->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRely, RelyTestInOrder2) {
+ // use Rely k = 2 N = 6
+ std::string fec_str = "Rely_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ auto data2_copy = pf.createData(name, 2, 45, 2);
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decode in order, data 2 is lost
+ decoder.onPacketReceived(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // check recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ decoder.recovered_packets_.pop(); // pop data 1
+ auto recovered = pf.createData(name, 2, decoder.recovered_packets_.front());
+
+ bool eq_len = (data2_copy->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data2_copy->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+#if 0
+TEST(FECtestRely, RelyTestOutOfOrder1) {
+ //use Rely k = 2 N = 6
+ std::string fec_str = "Rely_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ auto data1_copy = pf.createData(name, 1, 50, 1);
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+
+ std::cout << "dump packet 2" << std::endl;
+ hicn_packet_dump(data2->data(), data2->length());
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ std::cout << "dump packet 2" << std::endl;
+ hicn_packet_dump(data2->data(), data2->length());
+
+ std::cout << "dump packet 3" << std::endl;
+ hicn_packet_dump(data3->data(), data3->length());
+
+ // decoding ooo packets. data 1 is lost.
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // get recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t) 2);
+ auto recovered = pf.createData(name, 1, decoder.recovered_packets_.front());
+ bool eq_len = (data1_copy->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if(eq_len)
+ ret = memcmp(data1_copy->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int) 0);
+}
+#endif
+
+TEST(FECtestRely, RelyTestOutOfOrder2) {
+ // use Rely k = 2 N = 6
+ std::string fec_str = "Rely_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ auto data2_copy = pf.createData(name, 2, 45, 2);
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decoding ooo packets. data 2 is lost.
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data1, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // get recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ decoder.recovered_packets_.pop(); // pop data 1
+ auto recovered = pf.createData(name, 2, decoder.recovered_packets_.front());
+ bool eq_len = (data2_copy->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data2_copy->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRely, RelyTestLargerBlocks) {
+ // use Rely k = 4 N = 7
+ std::string fec_str = "Rely_K4_N7";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+
+ auto data3 = pf.createData(name, 3, 12, 3);
+ auto data3_copy = pf.createData(name, 3, 12, 3);
+
+ auto data4 = pf.createData(name, 4, 20, 4);
+ auto data4_copy = pf.createData(name, 4, 20, 4);
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data4, data4->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data5 = pf.createData(name, 5, encoder.fec_packets_.front());
+ encoder.fec_packets_.pop(); // pop 5
+ encoder.fec_packets_.pop(); // pop 6
+ auto data7 = pf.createData(name, 7, encoder.fec_packets_.front());
+
+ // decoding packets: lost data 3 and data 4
+ decoder.onPacketReceived(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data7, data7->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data5, data5->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // get recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)4);
+ decoder.recovered_packets_.pop(); // pop data 1
+ decoder.recovered_packets_.pop(); // pop data 2
+ auto recovered3 = pf.createData(name, 3, decoder.recovered_packets_.front());
+ decoder.recovered_packets_.pop();
+ auto recovered4 = pf.createData(name, 4, decoder.recovered_packets_.front());
+
+ bool eq_len = (data3_copy->length() == recovered3->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data3_copy->data(), recovered3->data(), recovered3->length());
+ EXPECT_EQ(ret, (int)0);
+
+ eq_len = (data4_copy->length() == recovered4->length());
+ EXPECT_TRUE(eq_len);
+ ret = -1;
+ if (eq_len)
+ ret = memcmp(data4_copy->data(), recovered4->data(), recovered4->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRely, RelyTestK1_N3) {
+ // use Rely k = 1 N = 3
+ std::string fec_str = "Rely_K1_N3";
+ Encoder encoder(fec_str);
+ Decoder decoder1(fec_str); // recv 2
+ Decoder decoder2(fec_str); // recv 3
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ auto data1_copy = pf.createData(name, 1, 50, 1);
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packets
+ EXPECT_TRUE(encoder.fec_packets_.size() == 2);
+ auto data2 = pf.createData(name, 2, encoder.fec_packets_.front());
+ encoder.fec_packets_.pop(); // pop 2
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // test1: recv data 2
+ decoder1.onPacketReceived(*data2,
+ data2->headerSize() + rtc::DATA_HEADER_SIZE);
+ EXPECT_EQ(decoder1.recovered_packets_.size(), (size_t)1);
+
+ auto recovered = pf.createData(name, 1, decoder1.recovered_packets_.front());
+ bool eq_len = (data1_copy->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data1_copy->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+
+ // test2: recv data 3
+ decoder2.onPacketReceived(*data3,
+ data3->headerSize() + rtc::DATA_HEADER_SIZE);
+ EXPECT_EQ(decoder2.recovered_packets_.size(), (size_t)1);
+
+ recovered = pf.createData(name, 1, decoder2.recovered_packets_.front());
+ eq_len = (data1_copy->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ ret = -1;
+ if (eq_len)
+ ret = memcmp(data1_copy->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/test/test_fec_base_rs.cc b/libtransport/src/test/test_fec_base_rs.cc
new file mode 100644
index 000000000..7d7bcebc3
--- /dev/null
+++ b/libtransport/src/test/test_fec_base_rs.cc
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <protocols/fec_base.h>
+#include <protocols/fec_utils.h>
+#include <protocols/rtc/rtc_consts.h>
+
+#include <algorithm>
+#include <iostream>
+#include <queue>
+#include <random>
+
+namespace transport {
+namespace protocol {
+
+class PacketFactory {
+ public:
+ PacketFactory(){};
+
+ ~PacketFactory(){};
+
+ std::shared_ptr<transport::core::ContentObject> createData(
+ core::Name &name, uint32_t suffix, uint32_t payload_size,
+ uint32_t payload_filler) {
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ // create payload
+ auto buff = packet_manager.getMemBuf();
+ buff->append(payload_size);
+ std::fill(buff->writableData(), buff->writableTail(), payload_filler);
+
+ // create data packet
+ auto data = packet_manager.getPacket<transport::core::ContentObject>(
+ HF_INET6_TCP, 0);
+ struct rtc::data_packet_t header;
+ header.setTimestamp(1000);
+ header.setProductionRate(1);
+ data->appendPayload((const uint8_t *)&header, rtc::DATA_HEADER_SIZE);
+ data->appendPayload(buff->data(), buff->length());
+ data->setName(name.setSuffix(suffix));
+ data->setLifetime(500);
+ data->setPathLabel(12);
+
+ return data;
+ }
+
+ std::shared_ptr<transport::core::ContentObject> createData(
+ core::Name &name, uint32_t suffix, fec::buffer payload) {
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ auto data = packet_manager.getPacket<transport::core::ContentObject>(
+ HF_INET6_TCP, 0);
+ struct rtc::data_packet_t header;
+ header.setTimestamp(1000);
+ header.setProductionRate(1);
+ data->appendPayload((const uint8_t *)&header, rtc::DATA_HEADER_SIZE);
+ data->appendPayload(payload->data(), payload->length());
+ data->setName(name.setSuffix(suffix));
+ data->setLifetime(500);
+ data->setPathLabel(12);
+
+ return data;
+ }
+};
+
+class Encoder {
+ public:
+ Encoder(std::string fec_str) {
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_str.c_str());
+ encoder_ = fec::FECUtils::getEncoder(fec_type_, 1);
+ encoder_->setFECCallback(
+ std::bind(&Encoder::onFecPackets, this, std::placeholders::_1));
+ encoder_->setBufferCallback(
+ std::bind(&Encoder::getBuffer, this, std::placeholders::_1));
+ };
+
+ ~Encoder(){};
+
+ void onFecPackets(fec::BufferArray &packets) {
+ for (auto &packet : packets) {
+ fec_packets_.push(packet.getBuffer());
+ }
+ }
+
+ fec::buffer getBuffer(std::size_t size) {
+ auto ret = core::PacketManager<>::getInstance()
+ .getPacket<transport::core::ContentObject>(HF_INET6_TCP, 0);
+ ret->updateLength(rtc::DATA_HEADER_SIZE + size);
+ ret->append(rtc::DATA_HEADER_SIZE + size);
+ ret->trimStart(ret->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ return ret;
+ }
+
+ void onPacketProduced(core::ContentObject &content_object, uint32_t offset,
+ uint32_t metadata) {
+ encoder_->onPacketProduced(content_object, offset, metadata);
+ }
+
+ public:
+ std::queue<fec::buffer> fec_packets_;
+
+ private:
+ std::unique_ptr<fec::ProducerFEC> encoder_;
+ fec::FECType fec_type_;
+};
+
+class Decoder {
+ public:
+ Decoder(std::string fec_str) {
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_str.c_str());
+ decoder_ = fec::FECUtils::getDecoder(fec_type_, 1);
+ decoder_->setFECCallback(
+ std::bind(&Decoder::onFecPackets, this, std::placeholders::_1));
+ decoder_->setBufferCallback(fec::FECBase::BufferRequested(0));
+ };
+
+ ~Decoder(){};
+
+ void onFecPackets(fec::BufferArray &packets) {
+ for (auto &packet : packets) {
+ recovered_packets_.push(packet.getBuffer());
+ }
+ }
+
+ void onPacketReceived(core::ContentObject &content_object, uint32_t offset) {
+ decoder_->onDataPacket(content_object, offset);
+ }
+
+ public:
+ std::queue<fec::buffer> recovered_packets_;
+
+ private:
+ std::unique_ptr<fec::ConsumerFEC> decoder_;
+ fec::FECType fec_type_;
+};
+
+TEST(FECtestRS, RSTestInOrder1) {
+ // use RS k = 2 N = 6
+ std::string fec_str = "RS_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ const uint8_t *data1_ptr = data1->data();
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ const uint8_t *data2_ptr = data2->data();
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decode in order, data 1 is lost
+ decoder.onPacketReceived(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // test payload pointers off the original packets
+ EXPECT_EQ((const uint8_t *)data1->data(), data1_ptr);
+ EXPECT_EQ((const uint8_t *)data2->data(), data2_ptr);
+
+ // check recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ auto recovered = pf.createData(name, 1, decoder.recovered_packets_.front());
+ bool eq_len = (data1->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data1->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRS, RSTestInOrder2) {
+ // use RS k = 2 N = 6
+ std::string fec_str = "RS_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ const uint8_t *data1_ptr = data1->data();
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ const uint8_t *data2_ptr = data2->data();
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decode in order, data 2 is lost
+ decoder.onPacketReceived(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // test payload pointers off the original packets
+ EXPECT_EQ((const uint8_t *)data1->data(), data1_ptr);
+ EXPECT_EQ((const uint8_t *)data2->data(), data2_ptr);
+
+ // check recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ decoder.recovered_packets_.pop(); // pop data packet 1
+ auto recovered = pf.createData(name, 2, decoder.recovered_packets_.front());
+
+ bool eq_len = (data2->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data2->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRS, RSTestOutOfOrder1) {
+ // use RS k = 2 N = 6
+ std::string fec_str = "RS_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ const uint8_t *data1_ptr = data1->data();
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ const uint8_t *data2_ptr = data2->data();
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decoding ooo packets. data 1 is lost.
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // test payload pointers off the original packets
+ EXPECT_EQ((const uint8_t *)data1->data(), data1_ptr);
+ EXPECT_EQ((const uint8_t *)data2->data(), data2_ptr);
+
+ // get recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ auto recovered = pf.createData(name, 1, decoder.recovered_packets_.front());
+ bool eq_len = (data1->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data1->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRS, RSTestOutOfOrder2) {
+ // use RS k = 2 N = 6
+ std::string fec_str = "RS_K2_N6";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ const uint8_t *data1_ptr = data1->data();
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ const uint8_t *data2_ptr = data2->data();
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data3 = pf.createData(name, 3, encoder.fec_packets_.front());
+
+ // decoding ooo packets. data 2 is lost.
+ decoder.onPacketReceived(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data1, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // test payload pointers off the original packets
+ EXPECT_EQ((const uint8_t *)data1->data(), data1_ptr);
+ EXPECT_EQ((const uint8_t *)data2->data(), data2_ptr);
+
+ // get recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)2);
+ decoder.recovered_packets_.pop(); // pop data packet 1
+
+ auto recovered = pf.createData(name, 2, decoder.recovered_packets_.front());
+ bool eq_len = (data2->length() == recovered->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data2->data(), recovered->data(), recovered->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+TEST(FECtestRS, RSTestLargerBlocks) {
+ // use RS k = 4 N = 7
+ std::string fec_str = "RS_K4_N7";
+ Encoder encoder(fec_str);
+ Decoder decoder(fec_str);
+
+ PacketFactory pf;
+
+ core::Name name("b001::");
+
+ auto data1 = pf.createData(name, 1, 50, 1);
+ const uint8_t *data1_ptr = data1->data();
+
+ auto data2 = pf.createData(name, 2, 45, 2);
+ const uint8_t *data2_ptr = data2->data();
+
+ auto data3 = pf.createData(name, 3, 12, 3);
+ const uint8_t *data3_ptr = data3->data();
+
+ auto data4 = pf.createData(name, 4, 20, 4);
+ const uint8_t *data4_ptr = data4->data();
+
+ // encoding
+ uint32_t metadata = static_cast<uint32_t>(data1->getPayloadType());
+ encoder.onPacketProduced(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data3, data3->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+ encoder.onPacketProduced(*data4, data4->headerSize() + rtc::DATA_HEADER_SIZE,
+ metadata);
+
+ // create fec packet
+ auto data5 = pf.createData(name, 5, encoder.fec_packets_.front());
+ encoder.fec_packets_.pop(); // pop 5
+ encoder.fec_packets_.pop(); // pop 6
+ auto data7 = pf.createData(name, 7, encoder.fec_packets_.front());
+
+ // decoding packets: lost data 3 and data 4
+ decoder.onPacketReceived(*data2, data2->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data7, data7->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data1, data1->headerSize() + rtc::DATA_HEADER_SIZE);
+ decoder.onPacketReceived(*data5, data5->headerSize() + rtc::DATA_HEADER_SIZE);
+
+ // test payload pointers off the original packets
+ EXPECT_EQ((const uint8_t *)data1->data(), data1_ptr);
+ EXPECT_EQ((const uint8_t *)data2->data(), data2_ptr);
+ EXPECT_EQ((const uint8_t *)data3->data(), data3_ptr);
+ EXPECT_EQ((const uint8_t *)data4->data(), data4_ptr);
+
+ // get recovered packet
+ EXPECT_EQ(decoder.recovered_packets_.size(), (size_t)4);
+ decoder.recovered_packets_.pop(); // pop data 1
+ decoder.recovered_packets_.pop(); // pop data 2
+ auto recovered3 = pf.createData(name, 3, decoder.recovered_packets_.front());
+ decoder.recovered_packets_.pop(); // pop data 3
+ auto recovered4 = pf.createData(name, 4, decoder.recovered_packets_.front());
+
+ bool eq_len = (data3->length() == recovered3->length());
+ EXPECT_TRUE(eq_len);
+ int ret = -1;
+ if (eq_len)
+ ret = memcmp(data3->data(), recovered3->data(), recovered3->length());
+ EXPECT_EQ(ret, (int)0);
+
+ eq_len = (data4->length() == recovered4->length());
+ EXPECT_TRUE(eq_len);
+ ret = -1;
+ if (eq_len)
+ ret = memcmp(data4->data(), recovered4->data(), recovered4->length());
+ EXPECT_EQ(ret, (int)0);
+}
+
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/test/test_fec_reedsolomon.cc b/libtransport/src/test/test_fec_reedsolomon.cc
index c7e10d111..0973069b1 100644
--- a/libtransport/src/test/test_fec_reedsolomon.cc
+++ b/libtransport/src/test/test_fec_reedsolomon.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <gtest/gtest.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/global_object_pool.h>
@@ -30,28 +31,35 @@ double ReedSolomonTest(int k, int n, int seq_offset, int size) {
fec::RSEncoder encoder(k, n, seq_offset);
fec::RSDecoder decoder(k, n, seq_offset);
- std::vector<fec::buffer> tx_block(k);
- std::vector<fec::buffer> rx_block(k);
+ using BufferMetadata = std::pair<fec::buffer, uint32_t>;
+
+ std::vector<BufferMetadata> tx_block(k);
+ std::vector<BufferMetadata> rx_block(k);
int count = 0;
int run = 0;
+ // Setup random engine
+ std::random_device
+ rd; // Will be used to obtain a seed for the random number engine
+ std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
+ std::uniform_int_distribution<> dis(0, 99);
+
int iterations = 100;
auto &packet_manager = core::PacketManager<>::getInstance();
- encoder.setFECCallback(
- [&tx_block](
- std::vector<std::pair<uint32_t, fec::buffer>> &repair_packets) {
- for (auto &p : repair_packets) {
- // Append repair symbols to tx_block
- tx_block.emplace_back(std::move(p).second);
- }
- });
+ encoder.setFECCallback([&tx_block](fec::BufferArray &repair_packets) {
+ for (auto &p : repair_packets) {
+ // Append repair symbols to tx_block
+ tx_block.emplace_back(p.getBuffer(), p.getMetadata());
+ }
+ });
decoder.setFECCallback(
- [&](std::vector<std::pair<uint32_t, fec::buffer>> &source_packets) {
+ [&tx_block, &count, &k](fec::BufferArray &source_packets) {
for (int i = 0; i < k; i++) {
// Compare decoded source packets with original transmitted packets.
- if (*tx_block[i] != *source_packets[i].second) {
+ if (*tx_block[i].first != *source_packets[i].getBuffer() ||
+ tx_block[i].second != source_packets[i].getMetadata()) {
count++;
}
}
@@ -60,7 +68,7 @@ double ReedSolomonTest(int k, int n, int seq_offset, int size) {
do {
// Discard eventual packet appended in previous callback call
tx_block.erase(tx_block.begin() + k, tx_block.end());
- auto _seq_offet = seq_offset;
+ uint32_t _seq_offset = seq_offset;
// Initialization. Feed encoder with first k source packets
for (int i = 0; i < k; i++) {
@@ -69,45 +77,46 @@ double ReedSolomonTest(int k, int n, int seq_offset, int size) {
// Let's append a bit less than size, so that the FEC class will take care
// of filling the rest with zeros
- auto cur_size = size - (rand() % 100);
+ auto cur_size = size - dis(gen);
// Set payload, saving 2 bytes at the beginning of the buffer for encoding
// the length
packet->append(cur_size);
- packet->trimStart(2);
- std::generate(packet->writableData(), packet->writableTail(), rand);
std::fill(packet->writableData(), packet->writableTail(), i + 1);
// Set first byte of payload to seq_offset, to reorder at receiver side
- packet->writableData()[0] = uint8_t(_seq_offet++);
+ uint32_t *pkt_head = (uint32_t *)packet->writableData();
+ *pkt_head = _seq_offset++;
+
+ // Set a metadata integer
+ uint32_t metadata = dis(gen);
// Store packet in tx buffer and clear rx buffer
- tx_block[i] = std::move(packet);
+ tx_block[i] = std::make_pair(std::move(packet), metadata);
}
// Create the repair packets
for (auto &tx : tx_block) {
- encoder.consume(tx, tx->writableBuffer()[0]);
+ encoder.consume(tx.first, tx.first->writableBuffer()[0], 0, tx.second);
}
// Simulate transmission on lossy channel
- unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::vector<bool> losses(n, false);
for (int i = 0; i < n - k; i++) losses[i] = true;
int rxi = 0;
- std::shuffle(losses.begin(), losses.end(),
- std::default_random_engine(seed));
+ std::shuffle(losses.begin(), losses.end(), gen);
for (int i = 0; i < n && rxi < k; i++)
if (losses[i] == false) {
rx_block[rxi++] = tx_block[i];
if (i < k) {
// Source packet
- decoder.consumeSource(rx_block[rxi - 1],
- rx_block[rxi - 1]->data()[0]);
+ uint32_t index = *((uint32_t *)rx_block[rxi - 1].first->data());
+ decoder.consumeSource(rx_block[rxi - 1].first, index, 0,
+ rx_block[rxi - 1].second);
} else {
// Repair packet
- decoder.consumeRepair(rx_block[rxi - 1]);
+ decoder.consumeRepair(rx_block[rxi - 1].first);
}
}
@@ -126,6 +135,12 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
fec::RSEncoder encoder(k, n);
fec::RSDecoder decoder(k, n);
+ // Setup random engine
+ std::random_device
+ rd; // Will be used to obtain a seed for the random number engine
+ std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
+ std::uniform_int_distribution<> dis(0, 99);
+
auto &packet_manager = core::PacketManager<>::getInstance();
std::vector<std::pair<fec::buffer, uint32_t>> tx_block;
@@ -136,33 +151,39 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
// Receiver will receive packet for n_sourceblocks in a random order.
int total_packets = n * n_sourceblocks;
int tx_packets = k * n_sourceblocks;
- unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
- encoder.setFECCallback(
- [&](std::vector<std::pair<uint32_t, fec::buffer>> &repair_packets) {
- for (auto &p : repair_packets) {
- // Append repair symbols to tx_block
- tx_block.emplace_back(std::move(p.second), ++i);
- }
+ encoder.setFECCallback([&tx_block, &rx_block, &i, &n, &k,
+ &encoder](fec::BufferArray &repair_packets) {
+ for (auto &p : repair_packets) {
+ // Append repair symbols to tx_block
+ ++i;
+ tx_block.emplace_back(std::move(p.getBuffer()), i);
+ }
- EXPECT_EQ(tx_block.size(), size_t(n));
+ EXPECT_EQ(tx_block.size(), size_t(n));
- // Select k packets to send, including at least one symbol. We start
- // from the end for this reason.
- for (int j = n - 1; j > n - k - 1; j--) {
- rx_block.emplace_back(std::move(tx_block[j]));
- }
+ // Select k packets to send, including at least one symbol. We start
+ // from the end for this reason.
+ for (int j = n - 1; j > n - k - 1; j--) {
+ rx_block.emplace_back(std::move(tx_block[j]));
+ }
- // Clear tx block for next source block
- tx_block.clear();
- encoder.clear();
- });
+ // Clear tx block for next source block
+ tx_block.clear();
+ encoder.clear();
+ });
// The decode callback must be called exactly n_sourceblocks times
- decoder.setFECCallback(
- [&](std::vector<std::pair<uint32_t, fec::buffer>> &source_packets) {
- count++;
- });
+ decoder.setFECCallback([&count](fec::BufferArray &source_packets) {
+ // Check buffers
+ for (auto &packet : source_packets) {
+ auto packet_index = ((uint32_t *)packet.getBuffer()->writableData())[0];
+ EXPECT_EQ(packet_index, packet.getIndex())
+ << "Packet index: " << packet_index
+ << " -- FEC Index: " << packet.getIndex();
+ }
+ count++;
+ });
// Produce n * n_sourceblocks
// - ( k ) * n_sourceblocks source packets
@@ -173,7 +194,7 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
// Let's append a bit less than size, so that the FEC class will take care
// of filling the rest with zeros
- auto cur_size = size - (rand() % 100);
+ auto cur_size = size - dis(gen);
// Set payload, saving 2 bytes at the beginning of the buffer for encoding
// the length
@@ -182,7 +203,7 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
std::fill(packet->writableData(), packet->writableTail(), i + 1);
// Set first byte of payload to i, to reorder at receiver side
- packet->writableData()[0] = uint8_t(i);
+ ((uint32_t *)packet->writableData())[0] = uint32_t(i);
// Store packet in tx buffer
tx_block.emplace_back(packet, i);
@@ -195,8 +216,7 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
EXPECT_EQ(size_t(tx_packets), size_t(rx_block.size()));
// Lets shuffle the rx_block before starting feeding the decoder.
- std::shuffle(rx_block.begin(), rx_block.end(),
- std::default_random_engine(seed));
+ std::shuffle(rx_block.begin(), rx_block.end(), gen);
for (auto &p : rx_block) {
int index = p.second % n;
@@ -231,7 +251,7 @@ foreach_rs_fec_type
#undef _
TEST(ReedSolomonMultiBlockTest, RSMB10) {
- int blocks = 10;
+ int blocks = 1;
ReedSolomonMultiBlockTest(blocks);
}
diff --git a/libtransport/src/test/test_fec_rely_wrapper.cc b/libtransport/src/test/test_fec_rely_wrapper.cc
index c5b73f8d2..764e4dd2d 100644
--- a/libtransport/src/test/test_fec_rely_wrapper.cc
+++ b/libtransport/src/test/test_fec_rely_wrapper.cc
@@ -13,18 +13,23 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <gtest/gtest.h>
#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/utils/log.h>
#include <protocols/fec/rely.h>
#include <queue>
+#include <random>
namespace transport {
namespace protocol {
-std::string printMissing(
- const std::map<uint32_t, core::ContentObject::Ptr> &missing) {
+using SavedPacketMap =
+ std::map<uint32_t, std::pair<core::ContentObject::Ptr, uint32_t>>;
+
+std::string printMissing(const SavedPacketMap &missing) {
std::stringstream stream;
for (auto &[seq, packet] : missing) {
@@ -48,14 +53,15 @@ std::string printMissing(
* @param loss_rate The loss rate
*/
void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size,
- int64_t timeout, uint32_t max_iterations,
+ int64_t /* timeout */, uint32_t max_iterations,
int loss_rate) {
// Create 1 encoder and 1 decoder
fec::RelyEncoder _encoder(k, n);
fec::RelyDecoder _decoder(k, n);
// Seed the pseudo-random with known value to always get same loss pattern
- srand(k * n);
+ std::mt19937 gen(k *
+ n); // Standard mersenne_twister_engine seeded with rd();
// We will interact with rely encoder/decoder using the interface
fec::ProducerFEC &encoder = _encoder;
@@ -68,73 +74,78 @@ void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size,
auto &packet_manager = core::PacketManager<>::getInstance();
// Store packets to verify them in the decoder callback
- std::map<uint32_t, core::ContentObject::Ptr> saved_packets;
+ SavedPacketMap saved_packets;
// Save repair packets here in encoder callback
std::queue<fec::buffer> pending_repair_packets;
// Set callback called by encoder when a buffer is required.
- encoder.setBufferCallback([](std::size_t size) -> fec::buffer {
+ encoder.setBufferCallback([](std::size_t size) {
auto ret =
- core::PacketManager<>::getInstance().getPacket<core::ContentObject>();
+ core::PacketManager<>::getInstance().getPacket<core::ContentObject>(
+ transport::interface::default_values::packet_format);
ret->updateLength(size);
ret->append(size);
ret->trimStart(ret->headerSize());
- assert(ret->length() >= size);
+ DCHECK(ret->length() >= size);
return ret;
});
// Set callback to be called by encoder when repair packets are ready
- encoder.setFECCallback(
- [&](std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
- // We must get n - k symbols
- EXPECT_EQ(packets.size(), n - k);
- // TRANSPORT_LOGD("Got %zu symbols", packets.size());
-
- // Save symbols in pending_repair_packets queue and increment iterations
- for (auto &packet : packets) {
- ++iterations;
- pending_repair_packets.push(packet.second);
- }
- });
+ encoder.setFECCallback([&iterations, &pending_repair_packets, &n,
+ &k](fec::BufferArray &packets) {
+ // We must get n - k symbols
+ EXPECT_EQ(packets.size(), n - k);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Got " << packets.size() << " symbols";
+
+ // Save symbols in pending_repair_packets queue and increment iterations
+ for (auto &packet : packets) {
+ ++iterations;
+ pending_repair_packets.push(packet.getBuffer());
+ }
+ });
// Set callback to be called when decoder recover a packet
- decoder.setFECCallback(
- [&](std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
- for (auto &packet : packets) {
- // TRANSPORT_LOGD("Recovering packet %u", packet.first);
+ decoder.setFECCallback([&saved_packets](fec::BufferArray &packets) {
+ for (auto &packet : packets) {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Recovering packet " << packet.getIndex();
+
+ // Ensure recovered packet is in packets actually produced by encoder
+ auto original = saved_packets.find(packet.getIndex());
+ ASSERT_TRUE(original != saved_packets.end());
+ auto &original_packet = *original->second.first;
- // Ensure recovered packet is in packets actually produced by encoder
- auto original = saved_packets.find(packet.first);
- ASSERT_TRUE(original != saved_packets.end());
- auto &original_packet = *original->second;
+ // Remove additional headers at the beginning of the packet. This may
+ // change in the future.
+ original_packet.trimStart(60 /* Ip + TCP */ + 32 /* Rely header */ +
+ 4 /* Packet size */);
- // Remove additional headers at the beginning of the packet. This may
- // change in the future.
- original_packet.trimStart(60 /* Ip + TCP */ + 28 /* Rely header */ +
- 4 /* Packet size */);
+ // Recovered packet should be equal to the original one
+ EXPECT_TRUE(original_packet == *packet.getBuffer());
- // Recovered packet should be equal to the original one
- EXPECT_TRUE(original_packet == *packet.second);
+ // Also metadata should correspond
+ EXPECT_TRUE(original->second.second == packet.getMetadata());
- // Restore removed headers
- original_packet.prepend(60 + 28 + 4);
+ // Restore removed headers
+ original_packet.prepend(60 + 32 + 4);
- // Erase packet from saved packet list
- saved_packets.erase(original);
- }
- });
+ // Erase packet from saved packet list
+ saved_packets.erase(original);
+ }
+ });
// Send max_iterations packets from encoder to decoder
+ std::uniform_int_distribution<> dis(0, 1299);
while (iterations < max_iterations) {
// Create a payload, the size is between 50 and 1350 bytes.
- auto payload_size = 50 + (rand() % 1300);
+ auto payload_size = 50 + (dis(gen));
uint8_t payload[max_packet_size];
- std::generate(payload, payload + payload_size, rand);
+ std::generate(payload, payload + payload_size, gen);
// Get a packet from global pool and set name
- auto buffer = packet_manager.getPacket<core::ContentObject>();
+ auto buffer = packet_manager.getPacket<core::ContentObject>(
+ transport::interface::default_values::packet_format);
buffer->setName(core::Name("b001::abcd", iterations));
// Get offset
@@ -145,20 +156,23 @@ void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size,
// its own header).
buffer->appendPayload(payload, payload_size);
+ // Set an u32 metadata to pass altogether with the buffer
+ uint32_t metadata = dis(gen);
+
// Save packet in the saving_packets list
- // TRANSPORT_LOGD("Saving packet with index %lu", iterations);
- saved_packets.emplace(iterations, buffer);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Saving packet with index " << iterations;
+ saved_packets.emplace(iterations, std::make_pair(buffer, metadata));
// Feed buffer into the encoder. This will eventually trigger a call to the
// FEC callback as soon as k packets are fed into the endocer.
- encoder.onPacketProduced(*buffer, offset);
+ encoder.onPacketProduced(*buffer, offset, metadata);
// Check returned packet. We calculate the difference in size and we compare
// only the part of the returned packet corresponding to the original
// payload. Rely should only add a header and should not modify the actual
// payload content. If it does it, this check will fail.
auto diff = buffer->length() - payload_size - offset;
- // TRANSPORT_LOGD("Difference is %zu", diff);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Difference is " << diff;
auto cmp =
std::memcmp(buffer->data() + offset + diff, payload, payload_size);
EXPECT_FALSE(cmp);
@@ -170,29 +184,33 @@ void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size,
// using future packets that are not created in the test. For this reason,
// we ensure the test ends without losses.
#define DROP_CONDITION(loss_rate, max_iterations) \
- (rand() % 100) >= loss_rate || iterations >= max_iterations * 0.9
+ (dis(gen)) >= loss_rate || iterations >= max_iterations * 0.9
// Handle the source packet to the decoder, id drop condition returns true
if (DROP_CONDITION(loss_rate, max_iterations)) {
// Pass packet to decoder
- // TRANSPORT_LOGD("Passing packet %u to decoder",
- // buffer->getName().getSuffix());
- decoder.onDataPacket(*buffer, offset);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Passing packet " << buffer->getName().getSuffix()
+ << " to decoder";
+ decoder.onDataPacket(*buffer, offset, metadata);
} else {
- // TRANSPORT_LOGD("Packet %u, dropped", buffer->getName().getSuffix());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Packet " << buffer->getName().getSuffix() << " dropped";
}
- // Check if previous call to encoder.consumer() generated repair packets,
+ // Check if previous call to encoder.consume() generated repair packets,
// and if yes, feed them to the decoder.
while (pending_repair_packets.size()) {
// Also repair packets can be lost
if (DROP_CONDITION(loss_rate, max_iterations)) {
auto &packet = pending_repair_packets.front();
- // TRANSPORT_LOGD("Passing packet %u to decoder", iterations);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Passing packet " << iterations << " to decoder";
core::ContentObject &co = (core::ContentObject &)(*packet);
decoder.onDataPacket(co, 0);
} else {
- // TRANSPORT_LOGD("Packet (repair) %u dropped", iterations);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Packet (repair) " << iterations << " dropped";
}
// Remove packet from the queue
@@ -206,9 +224,6 @@ void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size,
// 0.001 residual losses
EXPECT_LE(saved_packets.size(), iterations * 0.001)
<< printMissing(saved_packets);
-
- // Reset seed
- srand(time(0));
}
/**
diff --git a/libtransport/src/test/test_fixed_block_allocator.cc b/libtransport/src/test/test_fixed_block_allocator.cc
new file mode 100644
index 000000000..33e048031
--- /dev/null
+++ b/libtransport/src/test/test_fixed_block_allocator.cc
@@ -0,0 +1,211 @@
+/*
+ * 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/fixed_block_allocator.h>
+
+namespace utils {
+
+class FixedBlockAllocatorTest : public ::testing::Test {
+ protected:
+ static inline const std::size_t default_size = 2048;
+ static inline const std::size_t default_n_buffer = 1024;
+
+ // Get fixed block allocator_ of 1024 buffers of size 2048 bytes
+ FixedBlockAllocatorTest()
+ : allocator_(
+ ::utils::FixedBlockAllocator<default_size,
+ default_n_buffer>::getInstance()) {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~FixedBlockAllocatorTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ allocator_.reset();
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ allocator_.reset();
+ }
+
+ static bool pointerIsAligned(const void *pointer, size_t byte_count) {
+ // Sanity check
+ EXPECT_THAT(reinterpret_cast<std::uintptr_t>(pointer) &
+ (alignof(std::max_align_t) - 1),
+ testing::Eq(std::uintptr_t(0)));
+
+ return uintptr_t(pointer) % byte_count == 0;
+ }
+
+ ::utils::FixedBlockAllocator<default_size, default_n_buffer> &allocator_;
+};
+
+TEST_F(FixedBlockAllocatorTest, DefaultChecks) {
+ EXPECT_EQ(allocator_.blockSize(), default_size);
+ EXPECT_EQ(allocator_.blockCount(), default_n_buffer);
+ EXPECT_EQ(allocator_.allocations(), 0UL);
+ EXPECT_EQ(allocator_.deallocations(), 0UL);
+ EXPECT_EQ(allocator_.blocksInUse(), 0UL);
+
+ // Allocate one single block of memory
+ auto block = allocator_.allocateBlock();
+
+ ASSERT_THAT(block, testing::NotNull());
+
+ // Check statistics
+ EXPECT_EQ(allocator_.allocations(), 1UL);
+ EXPECT_EQ(allocator_.deallocations(), 0UL);
+ EXPECT_EQ(allocator_.blocksInUse(), 1UL);
+
+ // Deallocate it
+ allocator_.deallocateBlock(block);
+
+ // check statistics
+ EXPECT_EQ(allocator_.allocations(), 1UL);
+ EXPECT_EQ(allocator_.deallocations(), 1UL);
+ EXPECT_EQ(allocator_.blocksInUse(), 0UL);
+
+ // Test reset
+ allocator_.reset();
+
+ EXPECT_EQ(allocator_.blockSize(), default_size);
+ EXPECT_EQ(allocator_.blockCount(), default_n_buffer);
+ EXPECT_EQ(allocator_.allocations(), 0UL);
+ EXPECT_EQ(allocator_.deallocations(), 0UL);
+ EXPECT_EQ(allocator_.blocksInUse(), 0UL);
+}
+
+TEST_F(FixedBlockAllocatorTest, CheckMemoryIsReused) {
+ // Get one block. As it is the first one, it will be retrieved from the pool
+ auto block = allocator_.allocateBlock();
+
+ // Make sure block is valid
+ ASSERT_THAT(block, testing::NotNull());
+
+ // Release block
+ allocator_.deallocateBlock(block);
+
+ // Get same memory block again
+ auto block2 = allocator_.allocateBlock();
+
+ // Make sure memory is reused
+ ASSERT_EQ(block, block2);
+
+ // Get a third block
+ auto block3 = allocator_.allocateBlock();
+
+ // Make sure is different memory
+ ASSERT_NE(block2, block3);
+
+ // Deallocate both and check we get back the laso one
+ allocator_.deallocateBlock(block2);
+ allocator_.deallocateBlock(block3);
+
+ auto block4 = allocator_.allocateBlock();
+ ASSERT_EQ(block3, block4);
+}
+
+TEST_F(FixedBlockAllocatorTest, CheckMemoryIsContiguous) {
+ // Get one block. As it is the first one, it will be retrieved from the pool
+ auto block = reinterpret_cast<uint8_t *>(allocator_.allocateBlock());
+
+ // Make sure block is valid
+ ASSERT_THAT(block, testing::NotNull());
+
+ // Get another block
+ auto block2 = reinterpret_cast<uint8_t *>(allocator_.allocateBlock());
+
+ // Make sure block is valid
+ ASSERT_THAT(block2, testing::NotNull());
+
+ // Check the 2 blocks come from contiguous memory
+ ASSERT_THAT(std::size_t(block2 - block), testing::Eq(default_size));
+}
+
+TEST_F(FixedBlockAllocatorTest, CheckPoolExpansion) {
+ // Get all the blocks we setup when constructing the allocator
+ std::array<uint8_t *, default_n_buffer> blocks;
+ blocks[0] = reinterpret_cast<uint8_t *>(allocator_.allocateBlock());
+ for (std::size_t i = 1; i < default_n_buffer; i++) {
+ blocks[i] = reinterpret_cast<uint8_t *>(allocator_.allocateBlock());
+ ASSERT_THAT(std::size_t(blocks[i] - blocks[i - 1]),
+ testing::Eq(default_size));
+ }
+
+ ASSERT_THAT(allocator_.blockCount(), testing::Eq(default_n_buffer));
+
+ // We should have finished all the blocks belonging to first pool. Let's get
+ // one additional block
+ auto new_block = reinterpret_cast<uint8_t *>(allocator_.allocateBlock());
+
+ // Make sure the block count doubled its size
+ ASSERT_THAT(allocator_.blockCount(), testing::Eq(2 * default_n_buffer));
+
+ // Check the new block is not contiguous with respect last block in blocks
+ ASSERT_THAT(std::size_t(new_block - blocks[default_n_buffer - 1]),
+ testing::Ne(default_size));
+}
+
+TEST_F(FixedBlockAllocatorTest, CheckMemoryIsAligned) {
+ for (std::size_t i = 0; i < default_n_buffer; i++) {
+ auto block = reinterpret_cast<uint8_t *>(allocator_.allocateBlock());
+ ASSERT_THAT(pointerIsAligned(block, alignof(std::max_align_t)),
+ testing::IsTrue);
+ }
+}
+
+TEST_F(FixedBlockAllocatorTest, Multithreading) {
+ // Create 4 threads
+ utils::EventThread threads[4];
+ ::utils::FixedBlockAllocator<default_size, default_n_buffer>
+ *allocator_addresses[4] = {nullptr, nullptr, nullptr, nullptr};
+ int i = 0;
+ for (auto &t : threads) {
+ t.add([&allocator_addresses, i]() {
+ auto &allocator =
+ ::utils::FixedBlockAllocator<default_size,
+ default_n_buffer>::getInstance();
+ allocator_addresses[i] = &allocator;
+ });
+ i++;
+ }
+
+ // Stop threads
+ for (auto &t : threads) {
+ t.stop();
+ }
+
+ // Check the instance of allocator was different for each thread
+ for (int i = 0; i < 4; i++) {
+ for (int j = i + 1; j < 4; j++) {
+ ASSERT_NE(allocator_addresses[i], allocator_addresses[j]);
+ }
+ }
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/test/test_interest.cc b/libtransport/src/test/test_interest.cc
index 8853563b0..d9c535881 100644
--- a/libtransport/src/test/test_interest.cc
+++ b/libtransport/src/test/test_interest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -30,7 +30,7 @@ namespace {
// The fixture for testing class Foo.
class InterestTest : public ::testing::Test {
protected:
- InterestTest() : name_("b001::123|321"), interest_() {
+ InterestTest() : name_("b001::123|321"), interest_(HF_INET6_TCP) {
// You can do set-up work for each test here.
}
@@ -108,7 +108,7 @@ TEST_F(InterestTest, ConstructorWithName) {
Name n("b001::1|123");
try {
- Interest interest(n);
+ Interest interest(HF_INET6_TCP, n);
} catch (...) {
FAIL() << "ERROR: Unexpected exception thrown";
}
@@ -176,27 +176,27 @@ TEST_F(InterestTest, SetGetLocator) {
auto l = interest.getLocator();
ip_address_t address;
- ip_address_pton("b006::ab:cdab:cdef", &address);
- auto ret = !std::memcmp(&l, &address, sizeof(address));
+ inet_pton(AF_INET6, "b006::ab:cdab:cdef", &address);
+ auto ret = !ip_address_cmp(&l, &address, AF_INET6);
EXPECT_TRUE(ret);
// Set different locator
- ip_address_pton("2001::1234::4321::abcd::", &address);
+ inet_pton(AF_INET6, "2001::1234::4321::abcd::", &address);
// Set it on interest
interest.setLocator(address);
// Check it was set
l = interest.getLocator();
- ret = !std::memcmp(&l, &address, sizeof(address));
+ ret = !ip_address_cmp(&l, &address, AF_INET6);
EXPECT_TRUE(ret);
}
TEST_F(InterestTest, SetGetLifetime) {
// Create interest from buffer
- Interest interest;
+ Interest interest(HF_INET6_TCP);
const constexpr uint32_t lifetime = 10000;
// Set lifetime
@@ -211,7 +211,7 @@ TEST_F(InterestTest, SetGetLifetime) {
TEST_F(InterestTest, HasManifest) {
// Create interest from buffer
- Interest interest;
+ Interest interest(HF_INET6_TCP);
// Let's expect anexception here
try {
@@ -232,7 +232,7 @@ TEST_F(InterestTest, HasManifest) {
TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) {
// Create interest from buffer
- Interest interest;
+ Interest interest(HF_INET6_TCP);
// Appenad some suffixes, with some duplicates
interest.appendSuffix(1);
diff --git a/libtransport/src/test/test_memif_connector.cc b/libtransport/src/test/test_memif_connector.cc
new file mode 100644
index 000000000..562a12c88
--- /dev/null
+++ b/libtransport/src/test/test_memif_connector.cc
@@ -0,0 +1,152 @@
+/*
+ * 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/memif_connector.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
+
+namespace transport {
+namespace core {
+
+namespace {
+
+using namespace std::placeholders;
+
+/**
+ * Master memif connector
+ */
+template <int Master>
+class Memif {
+ static inline std::size_t counter = 256;
+ static inline std::size_t total_packets = counter * 4096;
+ static inline std::size_t packet_size = 64;
+
+ public:
+ Memif(asio::io_service &io_service)
+ : io_service_(io_service),
+ memif_connector_(std::make_shared<MemifConnector>(
+ std::bind(&Memif::onPacketReceived, this, _1, _2, _3),
+ std::bind(&Memif::onPacketSent, this, _1, _2),
+ std::bind(&Memif::onClose, this, _1),
+ std::bind(&Memif::onReconnect, this, _1, _2), io_service_,
+ Master ? "test_master" : "test_slave")),
+ recv_counter_(0),
+ sent_counter_(0) {
+ memif_connector_->connect(0 /* Memif ID */, Master /* Is Master */,
+ "@hicntransport/test/memif");
+ }
+
+ void setStart() { t0_ = utils::SteadyTime::now(); }
+
+ void startTest() {
+ if constexpr (!Master) {
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ // Send in busrt of 256 packet per time
+ for (std::size_t i = 0; i < counter; i++) {
+ auto packet = packet_manager.getMemBuf();
+ packet->append(packet_size);
+ memif_connector_->send(packet);
+ sent_counter_++;
+ }
+
+ if (sent_counter_ < total_packets) {
+ asio::post(io_service_, std::bind(&Memif::startTest, this));
+ }
+ } else {
+ setStart();
+ }
+ }
+
+ auto getRecvCounter() { return recv_counter_; }
+ auto getSentCounter() { return sent_counter_; }
+
+ private:
+ void onPacketReceived(Connector *c,
+ const std::vector<utils::MemBuf::Ptr> &buffers,
+ const std::error_code &ec) {
+ if constexpr (Master) {
+ 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();
+ LOG(INFO) << "rate: " << rate << " packets/s";
+ io_service_.stop();
+ }
+ } else {
+ FAIL() << "Slave should not receive packets";
+ }
+ }
+ void onPacketSent(Connector *c, const std::error_code &ec) {}
+ void onClose(Connector *c) {}
+ void onReconnect(Connector *c, const std::error_code &ec) {}
+
+ private:
+ asio::io_service &io_service_;
+ std::shared_ptr<MemifConnector> memif_connector_;
+ std::size_t recv_counter_;
+ std::size_t sent_counter_;
+ utils::SteadyTime::TimePoint t0_;
+};
+
+using MemifMaster = Memif<1>;
+using MemifSlave = Memif<0>;
+
+} // namespace
+
+class MemifTest : public ::testing::Test {
+ protected:
+ MemifTest() : io_service_(), master_(io_service_), slave_(io_service_) {
+ // You can do set-up work for each test here.
+ }
+
+ void run() {
+ asio::post(io_service_, std::bind(&MemifSlave::startTest, &slave_));
+ master_.startTest();
+ io_service_.run();
+
+ EXPECT_THAT(master_.getRecvCounter(),
+ ::testing::Eq(slave_.getSentCounter()));
+ }
+
+ virtual ~MemifTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ protected:
+ asio::io_service io_service_;
+ MemifMaster master_;
+ MemifSlave slave_;
+};
+
+TEST_F(MemifTest, Test) { run(); }
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/test/test_packet.cc b/libtransport/src/test/test_packet.cc
index 76ad352d6..ca20cdfb7 100644
--- a/libtransport/src/test/test_packet.cc
+++ b/libtransport/src/test/test_packet.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#include <gtest/gtest.h>
#include <hicn/transport/core/packet.h>
#include <hicn/transport/errors/not_implemented_exception.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <test/packet_samples.h>
#include <climits>
@@ -33,7 +34,7 @@ namespace core {
class PacketForTest : public Packet {
public:
template <typename... Args>
- PacketForTest(Args &&... args) : Packet(std::forward<Args>(args)...) {}
+ PacketForTest(Args &&...args) : Packet(std::forward<Args>(args)...) {}
virtual ~PacketForTest() {}
@@ -302,7 +303,7 @@ TEST_F(PacketTest, ConstructorWithNew) {
auto &_packet = raw_packets_[HF_INET6_TCP];
auto packet_ptr = new PacketForTest(Packet::WRAP_BUFFER, &_packet[0],
_packet.size(), _packet.size());
- (void)packet_ptr;
+ delete packet_ptr;
}
TEST_F(PacketTest, ConstructorWithRawBufferInet6Tcp) {
@@ -682,9 +683,7 @@ TEST_F(PacketTest, SetGetTestSignatureTimestamp) {
// Let's try to set the signature timestamp in a packet without AH header. We
// expect an exception.
using namespace std::chrono;
- uint64_t now =
- duration_cast<milliseconds>(system_clock::now().time_since_epoch())
- .count();
+ uint64_t now = utils::SteadyTime::nowMs().count();
try {
packet.setSignatureTimestamp(now);
diff --git a/libtransport/src/test/test_packet_allocator.cc b/libtransport/src/test/test_packet_allocator.cc
new file mode 100644
index 000000000..b63ddde8d
--- /dev/null
+++ b/libtransport/src/test/test_packet_allocator.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glog/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/interest.h>
+#define ALLOCATION_CHECKS
+#include <hicn/transport/core/global_object_pool.h>
+#undef ALLOCATION_CHECKS
+#include <hicn/transport/utils/event_thread.h>
+
+namespace transport {
+namespace core {
+
+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;
+
+ // Get fixed block allocator_ of 1024 buffers of size 2048 bytes
+ PacketAllocatorTest() : allocator_(PacketManager<>::getInstance()) {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~PacketAllocatorTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {}
+
+ virtual void TearDown() {}
+
+ static bool pointerIsAligned(const void *pointer, size_t byte_count) {
+ return uintptr_t(pointer) % byte_count == 0;
+ }
+
+ template <typename T, typename... Args>
+ void allocationTest(Args &&...args) {
+ // Create packet
+ auto packet = allocator_.getPacket<T>(std::forward<Args>(args)...);
+
+ // Check boundaries
+ LOG(INFO) << "packet size: " << sizeof(*packet) + sizeof(packet)
+ << std::endl;
+ EXPECT_LE(sizeof(*packet) + sizeof(packet) + sizeof(std::max_align_t),
+ sizeof(PacketManager<>::PacketStorage::packet_and_shared_ptr));
+ }
+
+ PacketManager<> &allocator_;
+};
+
+TEST_F(PacketAllocatorTest, ContentObjectAllocation) {
+ allocationTest<core::ContentObject>(HF_INET_TCP);
+}
+
+TEST_F(PacketAllocatorTest, InterestAllocation) {
+ allocationTest<core::Interest>(HF_INET_TCP);
+}
+
+// TEST_F(PacketAllocatorTest, MemBufAllocation) {
+// allocationTest<::utils::MemBuf>();
+// }
+
+TEST_F(PacketAllocatorTest, CheckAllocationIsCorrect) {
+ // Create packet
+ auto packet = allocator_.getPacket<core::ContentObject>(HF_INET_TCP);
+
+ // Address of actual buffer
+ uint8_t *buffer_address = packet->writableData();
+
+ // Address of packet
+ uint8_t *packet_address = reinterpret_cast<uint8_t *>(packet.get());
+
+ uint8_t *start_address =
+ buffer_address -
+ sizeof(PacketManager<>::PacketStorage::packet_and_shared_ptr);
+
+ // Check memory was allocated on correct positions
+ EXPECT_TRUE(pointerIsAligned(start_address, alignof(std::max_align_t)));
+ EXPECT_TRUE(packet_address > start_address &&
+ packet_address < buffer_address);
+ EXPECT_TRUE(pointerIsAligned(buffer_address, alignof(std::max_align_t)));
+ EXPECT_THAT(std::size_t(buffer_address - start_address),
+ testing::Eq(sizeof(
+ PacketManager<>::PacketStorage::packet_and_shared_ptr)));
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/test/test_quality_score.cc b/libtransport/src/test/test_quality_score.cc
new file mode 100644
index 000000000..9513c94a6
--- /dev/null
+++ b/libtransport/src/test/test_quality_score.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/utils/rtc_quality_score.h>
+
+#include <climits>
+#include <random>
+#include <vector>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+TEST(QualityScoreTest, testQS) {
+ RTCQualityScore qs;
+ uint8_t score;
+
+ // 0 losses
+ score = qs.getQualityScore(0, 0);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(98, 0);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(188, 0);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(398, 0);
+ EXPECT_EQ(score, (uint8_t)4);
+
+ score = qs.getQualityScore(400, 0);
+ EXPECT_EQ(score, (uint8_t)3);
+
+ score = qs.getQualityScore(598, 0);
+ EXPECT_EQ(score, (uint8_t)3);
+
+ score = qs.getQualityScore(600, 0);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ score = qs.getQualityScore(700, 0);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ score = qs.getQualityScore(50000, 0);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ // 0 delay
+ score = qs.getQualityScore(0, 2);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(0, 9);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(0, 29);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(0, 30);
+ EXPECT_EQ(score, (uint8_t)4);
+
+ score = qs.getQualityScore(0, 39);
+ EXPECT_EQ(score, (uint8_t)4);
+
+ score = qs.getQualityScore(0, 40);
+ EXPECT_EQ(score, (uint8_t)3);
+
+ score = qs.getQualityScore(0, 50);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ score = qs.getQualityScore(0, 5000);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ // loss < 10
+ score = qs.getQualityScore(0, 3);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(98, 9);
+ EXPECT_EQ(score, (uint8_t)4);
+
+ score = qs.getQualityScore(100, 9);
+ EXPECT_EQ(score, (uint8_t)3);
+
+ score = qs.getQualityScore(398, 5);
+ EXPECT_EQ(score, (uint8_t)2);
+
+ score = qs.getQualityScore(400, 5);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ score = qs.getQualityScore(4000, 5);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ // loss < 20
+ score = qs.getQualityScore(0, 10);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(30, 10);
+ EXPECT_EQ(score, (uint8_t)3);
+
+ score = qs.getQualityScore(198, 15);
+ EXPECT_EQ(score, (uint8_t)2);
+
+ score = qs.getQualityScore(200, 19);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ score = qs.getQualityScore(300, 10);
+ EXPECT_EQ(score, (uint8_t)1);
+
+ // loss < 30
+
+ score = qs.getQualityScore(0, 29);
+ EXPECT_EQ(score, (uint8_t)5);
+
+ score = qs.getQualityScore(10, 29);
+ EXPECT_EQ(score, (uint8_t)2);
+
+ score = qs.getQualityScore(0, 100);
+ EXPECT_EQ(score, (uint8_t)1);
+}
+
+} // namespace rtc
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/test/test_sessions.cc b/libtransport/src/test/test_sessions.cc
new file mode 100644
index 000000000..d2e8c27bb
--- /dev/null
+++ b/libtransport/src/test/test_sessions.cc
@@ -0,0 +1,77 @@
+/*
+ * 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <hicn/transport/interfaces/socket_producer.h>
+
+namespace transport {
+namespace interface {
+
+class SessionsTest : public ::testing::Test {
+ protected:
+ static inline const std::size_t default_size = 2048;
+ static inline const std::size_t default_n_buffer = 1024;
+
+ // Get fixed block allocator_ of 1024 buffers of size 2048 bytes
+ SessionsTest() {
+ // You can do set-up work for each test here.
+ // Set io_module to local forwarder with no external connections
+ global_config::IoModuleConfiguration config;
+ config.name = "forwarder_module";
+ config.set();
+ }
+
+ virtual ~SessionsTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ std::vector<ConsumerSocket> consumers_;
+ std::vector<ProducerSocket> producers_;
+};
+
+TEST_F(SessionsTest, SessionAllocations) {
+ // Create 1000 consumer sockets and 1000 producer sockets
+ int cprotocol = TransportProtocolAlgorithms::RAAQM;
+ int pprotocol = ProductionProtocolAlgorithms::BYTE_STREAM;
+ int offset = 0;
+
+ for (int i = 0; i < 1000; i++) {
+ auto &c = consumers_.emplace_back(cprotocol + (offset % 3));
+ auto &p = producers_.emplace_back(pprotocol + (offset % 2));
+ c.connect();
+ p.connect();
+ offset++;
+ }
+}
+
+} // namespace interface
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/test/test_thread_pool.cc b/libtransport/src/test/test_thread_pool.cc
new file mode 100644
index 000000000..1b6b4cc81
--- /dev/null
+++ b/libtransport/src/test/test_thread_pool.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/utils/thread_pool.h>
+
+namespace utils {
+
+class ThreadPoolTest : public ::testing::Test {
+ protected:
+ ThreadPoolTest() : thread_pool_() {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~ThreadPoolTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ ::utils::ThreadPool thread_pool_;
+};
+
+TEST_F(ThreadPoolTest, DefaultConstructor) {
+ // EXPECT_EQ(thread_pool_.GetNumThreads(), 0);
+ // EXPECT_EQ(thread_pool_.GetNumIdleThreads(), 0);
+ // EXPECT_EQ(thread_pool_.GetNumBusyThreads(), 0);
+}
+
+TEST_F(ThreadPoolTest, GetNThreads) {
+ auto n_threads = thread_pool_.getNThreads();
+ EXPECT_GT(n_threads, std::size_t(0));
+ EXPECT_EQ(n_threads, std::thread::hardware_concurrency());
+
+ ::utils::ThreadPool pool(64);
+ n_threads = pool.getNThreads();
+ EXPECT_GT(n_threads, std::size_t(0));
+ EXPECT_NE(n_threads, std::thread::hardware_concurrency());
+ EXPECT_EQ(n_threads, std::size_t(64));
+
+ // EXPECT_EQ(thread_pool_.GetNumThreads(), 0);
+ // EXPECT_EQ(thread_pool_.GetNumIdleThreads(), 0);
+ // EXPECT_EQ(thread_pool_.GetNumBusyThreads(), 0);
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/transport.config b/libtransport/src/transport.config
index 89db204d5..d5c2918a6 100644
--- a/libtransport/src/transport.config
+++ b/libtransport/src/transport.config
@@ -17,7 +17,7 @@ forwarder = {
remote_port = 33436;
}
};
-
+
listeners = {
l0 = {
local_address = "127.0.0.1";
diff --git a/libtransport/src/utils/CMakeLists.txt b/libtransport/src/utils/CMakeLists.txt
index a85ab16bf..5bb76303a 100644
--- a/libtransport/src/utils/CMakeLists.txt
+++ b/libtransport/src/utils/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -23,6 +23,7 @@ list(APPEND SOURCE_FILES
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/event_reactor.h
${CMAKE_CURRENT_SOURCE_DIR}/min_filter.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/max_filter.h
${CMAKE_CURRENT_SOURCE_DIR}/stream_buffer.h
${CMAKE_CURRENT_SOURCE_DIR}/suffix_strategy.h
${CMAKE_CURRENT_SOURCE_DIR}/content_store.h
@@ -34,10 +35,6 @@ if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
${CMAKE_CURRENT_SOURCE_DIR}/epoll_event_reactor.h
${CMAKE_CURRENT_SOURCE_DIR}/fd_deadline_timer.h
)
-
- list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/epoll_event_reactor.cc
- )
endif()
if(NOT WIN32)
diff --git a/libtransport/src/utils/content_store.cc b/libtransport/src/utils/content_store.cc
index 8ae7fd4d4..d9d4147f7 100644
--- a/libtransport/src/utils/content_store.cc
+++ b/libtransport/src/utils/content_store.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,6 +17,7 @@
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/name.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <utils/content_store.h>
namespace utils {
@@ -56,7 +57,7 @@ void ContentStore::insert(
fifo_list_.push_front(std::cref(content_object->getName()));
auto pos = fifo_list_.begin();
content_store_hash_table_[content_object->getName()] = ContentStoreEntry(
- ObjectTimeEntry(content_object, std::chrono::steady_clock::now()), pos);
+ ObjectTimeEntry(content_object, utils::SteadyTime::now()), pos);
}
std::shared_ptr<ContentObject> ContentStore::find(const Name &name) {
@@ -67,8 +68,8 @@ std::shared_ptr<ContentObject> ContentStore::find(const Name &name) {
if (it != content_store_hash_table_.end()) {
auto content_lifetime = it->second.first.first->getLifetime();
auto time_passed_since_creation =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now() - it->second.first.second)
+ utils::SteadyTime::getDurationMs(it->second.first.second,
+ utils::SteadyTime::now())
.count();
if (time_passed_since_creation > content_lifetime) {
diff --git a/libtransport/src/utils/content_store.h b/libtransport/src/utils/content_store.h
index abe5e7f6c..ecd62cc2c 100644
--- a/libtransport/src/utils/content_store.h
+++ b/libtransport/src/utils/content_store.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -35,8 +35,7 @@ using Name = transport::core::Name;
using ContentObject = transport::core::ContentObject;
using Interest = transport::core::Interest;
-typedef std::pair<std::shared_ptr<ContentObject>,
- std::chrono::steady_clock::time_point>
+typedef std::pair<std::shared_ptr<ContentObject>, utils::SteadyTime::TimePoint>
ObjectTimeEntry;
typedef std::pair<ObjectTimeEntry,
std::list<std::reference_wrapper<const Name>>::iterator>
diff --git a/libtransport/src/utils/daemonizator.cc b/libtransport/src/utils/daemonizator.cc
index 6cb7d16ba..4c17aa96b 100644
--- a/libtransport/src/utils/daemonizator.cc
+++ b/libtransport/src/utils/daemonizator.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/deadline_timer.h b/libtransport/src/utils/deadline_timer.h
index 5187754f0..6c105ed3d 100644
--- a/libtransport/src/utils/deadline_timer.h
+++ b/libtransport/src/utils/deadline_timer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,61 +22,6 @@
#include <cstring>
#include <utility>
-namespace std {
-namespace chrono {
-namespace detail {
-
-template <typename From, typename To>
-struct posix_duration_cast;
-
-// chrono -> timespec caster
-template <typename Rep, typename Period>
-struct posix_duration_cast<std::chrono::duration<Rep, Period>,
- struct timespec> {
- static struct timespec cast(std::chrono::duration<Rep, Period> const &d) {
- struct timespec tv;
-
- std::chrono::seconds const sec =
- std::chrono::duration_cast<std::chrono::seconds>(d);
-
- tv.tv_sec = sec.count();
- tv.tv_nsec =
- std::chrono::duration_cast<std::chrono::nanoseconds>(d - sec).count();
-
- return tv;
- }
-};
-
-// timespec -> chrono caster
-template <typename Rep, typename Period>
-struct posix_duration_cast<struct timespec,
- std::chrono::duration<Rep, Period>> {
- static std::chrono::duration<Rep, Period> cast(struct timespec const &tv) {
- return std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
- std::chrono::seconds(tv.tv_sec) + std::chrono::nanoseconds(tv.tv_nsec));
- }
-};
-
-} // namespace detail
-
-// chrono -> timespec
-template <typename T, typename Rep, typename Period>
-auto duration_cast(std::chrono::duration<Rep, Period> const &d) ->
- typename std::enable_if<std::is_same<T, struct timespec>::value,
- struct timespec>::type {
- return detail::posix_duration_cast<std::chrono::duration<Rep, Period>,
- timespec>::cast(d);
-}
-
-// timespec -> chrono
-template <typename Duration>
-Duration duration_cast(struct timespec const &tv) {
- return detail::posix_duration_cast<struct timespec, Duration>::cast(tv);
-}
-
-} // namespace chrono
-} // namespace std
-
namespace utils {
template <typename Implementation>
diff --git a/libtransport/src/utils/epoll_event_reactor.cc b/libtransport/src/utils/epoll_event_reactor.cc
deleted file mode 100644
index 457727bbe..000000000
--- a/libtransport/src/utils/epoll_event_reactor.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <glog/logging.h>
-#include <hicn/transport/utils/branch_prediction.h>
-#include <signal.h>
-#include <unistd.h>
-#include <utils/epoll_event_reactor.h>
-#include <utils/fd_deadline_timer.h>
-
-#include <iostream>
-
-namespace utils {
-
-EpollEventReactor::EpollEventReactor()
- : epoll_fd_(epoll_create(20000)), run_event_loop_(true) {}
-
-EpollEventReactor::~EpollEventReactor() { close(epoll_fd_); }
-
-int EpollEventReactor::addFileDescriptor(int fd, uint32_t events) {
- if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
- LOG(ERROR) << "invalid fd " << fd;
- return -1;
- }
-
- struct epoll_event evt;
- std::memset(&evt, 0, sizeof(evt));
- evt.events = events;
- evt.data.fd = fd;
-
- if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &evt) <
- 0)) {
- LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
- return -1;
- }
-
- return 0;
-}
-
-int EpollEventReactor::modFileDescriptor(int fd, uint32_t events) {
- if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
- LOG(ERROR) << "invalid fd " << fd;
- return -1;
- }
-
- struct epoll_event evt;
- memset(&evt, 0, sizeof(evt));
- evt.events = events;
- evt.data.fd = fd;
-
- if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) <
- 0)) {
- LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
- return -1;
- }
-
- return 0;
-}
-
-std::size_t EpollEventReactor::mapSize() { return event_callback_map_.size(); }
-
-int EpollEventReactor::delFileDescriptor(int fd) {
- if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
- LOG(ERROR) << "invalid fd " << fd;
- return -1;
- }
-
- struct epoll_event evt;
- memset(&evt, 0, sizeof(evt));
-
- if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &evt) <
- 0)) {
- LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
- return -1;
- }
-
- utils::SpinLock::Acquire locked(event_callback_map_lock_);
- event_callback_map_.erase(fd);
-
- return 0;
-}
-
-void EpollEventReactor::runEventLoop(int timeout) {
- Event evt[128];
- int en = 0;
- EventCallbackMap::iterator it;
- EventCallback callback;
-
- // evt.events = EPOLLIN | EPOLLOUT;
- sigset_t sigset;
- sigemptyset(&sigset);
-
- while (run_event_loop_) {
- memset(&evt, 0, sizeof(evt));
- en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset);
-
- if (TRANSPORT_EXPECT_FALSE(en < 0)) {
- LOG(ERROR) << "epoll_pwait: " << strerror(errno);
- if (errno == EINTR) {
- continue;
- } else {
- return;
- }
- }
-
- for (int i = 0; i < en; i++) {
- if (evt[i].data.fd > 0) {
- {
- utils::SpinLock::Acquire locked(event_callback_map_lock_);
- it = event_callback_map_.find(evt[i].data.fd);
- }
-
- if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
- LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd;
- } else {
- {
- utils::SpinLock::Acquire locked(event_callback_map_lock_);
- callback = event_callback_map_[evt[i].data.fd];
- }
-
- callback(evt[i]);
-
- // In the callback the epoll event reactor could have been stopped,
- // then we need to check whether the event loop is still running.
- if (TRANSPORT_EXPECT_FALSE(!run_event_loop_)) {
- return;
- }
- }
- } else {
- LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd;
- }
- }
- }
-}
-
-void EpollEventReactor::runOneEvent() {
- Event evt;
- int en = 0;
- EventCallbackMap::iterator it;
- EventCallback callback;
-
- // evt.events = EPOLLIN | EPOLLOUT;
- sigset_t sigset;
- sigemptyset(&sigset);
-
- memset(&evt, 0, sizeof(evt));
-
- en = epoll_pwait(epoll_fd_, &evt, 1, -1, &sigset);
-
- if (TRANSPORT_EXPECT_FALSE(en < 0)) {
- LOG(ERROR) << "epoll_pwait: " << strerror(errno);
- return;
- }
-
- if (TRANSPORT_EXPECT_TRUE(evt.data.fd > 0)) {
- {
- utils::SpinLock::Acquire locked(event_callback_map_lock_);
- it = event_callback_map_.find(evt.data.fd);
- }
-
- if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
- LOG(ERROR) << "unexpected event. fd " << evt.data.fd;
- } else {
- {
- utils::SpinLock::Acquire locked(event_callback_map_lock_);
- callback = event_callback_map_[evt.data.fd];
- }
-
- callback(evt);
- }
- } else {
- LOG(ERROR) << "unexpected event. fd " << evt.data.fd;
- }
-}
-
-void EpollEventReactor::stop() { run_event_loop_ = false; }
-
-} // 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 9ebfca937..8e7681c20 100644
--- a/libtransport/src/utils/epoll_event_reactor.h
+++ b/libtransport/src/utils/epoll_event_reactor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,6 +15,7 @@
#pragma once
+#include <glog/logging.h>
#include <hicn/transport/utils/spinlock.h>
#include <sys/epoll.h>
#include <utils/event_reactor.h>
@@ -35,9 +36,10 @@ typedef std::unordered_map<int, EventCallback> EventCallbackMap;
class EpollEventReactor : public EventReactor {
public:
- explicit EpollEventReactor();
+ explicit EpollEventReactor()
+ : epoll_fd_(epoll_create(20000)), run_event_loop_(true) {}
- ~EpollEventReactor();
+ ~EpollEventReactor() { close(epoll_fd_); }
template <typename EventHandler>
int addFileDescriptor(int fd, uint32_t events, EventHandler &&callback) {
@@ -56,20 +58,163 @@ class EpollEventReactor : public EventReactor {
return ret;
}
- int delFileDescriptor(int fd);
+ int delFileDescriptor(int fd) {
+ if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
+ LOG(ERROR) << "invalid fd " << fd;
+ return -1;
+ }
+
+ struct epoll_event evt;
+ memset(&evt, 0, sizeof(evt));
+
+ if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &evt) <
+ 0)) {
+ return -1;
+ }
+
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ event_callback_map_.erase(fd);
+
+ return 0;
+ }
+
+ int modFileDescriptor(int fd, uint32_t events) {
+ if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
+ LOG(ERROR) << "invalid fd " << fd;
+ return -1;
+ }
+
+ struct epoll_event evt;
+ memset(&evt, 0, sizeof(evt));
+ evt.events = events;
+ evt.data.fd = fd;
+
+ if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) <
+ 0)) {
+ LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ void runEventLoop(int timeout = -1) override {
+ Event evt[128];
+ int en = 0;
+ EventCallbackMap::iterator it;
+ EventCallback callback;
+
+ // evt.events = EPOLLIN | EPOLLOUT;
+ sigset_t sigset;
+ sigemptyset(&sigset);
+
+ while (run_event_loop_) {
+ memset(&evt, 0, sizeof(evt));
+ en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset);
+
+ if (TRANSPORT_EXPECT_FALSE(en < 0)) {
+ LOG(ERROR) << "epoll_pwait: " << strerror(errno);
+ if (errno == EINTR) {
+ continue;
+ } else {
+ return;
+ }
+ }
+
+ for (int i = 0; i < en; i++) {
+ if (evt[i].data.fd > 0) {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ it = event_callback_map_.find(evt[i].data.fd);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
+ LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd;
+ } else {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ callback = event_callback_map_[evt[i].data.fd];
+ }
+
+ callback(evt[i]);
+
+ // In the callback the epoll event reactor could have been stopped,
+ // then we need to check whether the event loop is still running.
+ if (TRANSPORT_EXPECT_FALSE(!run_event_loop_)) {
+ return;
+ }
+ }
+ } else {
+ LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd;
+ }
+ }
+ }
+ }
+
+ void runOneEvent() override {
+ Event evt;
+ int en = 0;
+ EventCallbackMap::iterator it;
+ EventCallback callback;
- int modFileDescriptor(int fd, uint32_t events);
+ // evt.events = EPOLLIN | EPOLLOUT;
+ sigset_t sigset;
+ sigemptyset(&sigset);
- void runEventLoop(int timeout = -1) override;
+ memset(&evt, 0, sizeof(evt));
- void runOneEvent() override;
+ en = epoll_pwait(epoll_fd_, &evt, 1, -1, &sigset);
- void stop() override;
+ if (TRANSPORT_EXPECT_FALSE(en < 0)) {
+ LOG(ERROR) << "epoll_pwait: " << strerror(errno);
+ return;
+ }
+
+ if (TRANSPORT_EXPECT_TRUE(evt.data.fd > 0)) {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ it = event_callback_map_.find(evt.data.fd);
+ }
- std::size_t mapSize();
+ if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
+ LOG(ERROR) << "unexpected event. fd " << evt.data.fd;
+ } else {
+ {
+ utils::SpinLock::Acquire locked(event_callback_map_lock_);
+ callback = event_callback_map_[evt.data.fd];
+ }
+
+ callback(evt);
+ }
+ } else {
+ LOG(ERROR) << "unexpected event. fd " << evt.data.fd;
+ }
+ }
+
+ void stop() override { run_event_loop_ = false; }
+
+ std::size_t mapSize() { return event_callback_map_.size(); }
private:
- int addFileDescriptor(int fd, uint32_t events);
+ int addFileDescriptor(int fd, uint32_t events) {
+ if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
+ LOG(ERROR) << "invalid fd " << fd;
+ return -1;
+ }
+
+ struct epoll_event evt;
+ std::memset(&evt, 0, sizeof(evt));
+ evt.events = events;
+ evt.data.fd = fd;
+
+ if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &evt) <
+ 0)) {
+ LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
+ return -1;
+ }
+
+ return 0;
+ }
int epoll_fd_;
std::atomic_bool run_event_loop_;
diff --git a/libtransport/src/utils/event_reactor.h b/libtransport/src/utils/event_reactor.h
index 4f8b58296..09af6f84c 100644
--- a/libtransport/src/utils/event_reactor.h
+++ b/libtransport/src/utils/event_reactor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/fd_deadline_timer.h b/libtransport/src/utils/fd_deadline_timer.h
index 22c13a763..e15cd4d2a 100644
--- a/libtransport/src/utils/fd_deadline_timer.h
+++ b/libtransport/src/utils/fd_deadline_timer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/errors/runtime_exception.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <utils/deadline_timer.h>
@@ -37,6 +38,11 @@ class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> {
}
}
+ FdDeadlineTimer(const FdDeadlineTimer &other)
+ : reactor_(other.reactor_),
+ timer_fd_(other.timer_fd_),
+ flags_(other.flags_) {}
+
~FdDeadlineTimer() { close(timer_fd_); }
template <typename WaitHandler>
diff --git a/libtransport/src/utils/log.cc b/libtransport/src/utils/log.cc
index 755d5bafa..44acf4595 100644
--- a/libtransport/src/utils/log.cc
+++ b/libtransport/src/utils/log.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * 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:
@@ -36,7 +36,7 @@ foreach_log_level
static constexpr char log_config_section[] = "log";
#define LOG_NAME \
"Libhicntransport-" HICNTRANSPORT_VERSION_MAJOR \
- "." HICNTRANSPORT_VERSION_MINOR "." HICNTRANSPORT_VERSION_REVISION
+ "." HICNTRANSPORT_VERSION_MINOR "." HICNTRANSPORT_VERSION_PATCH
static constexpr char log_name[] = LOG_NAME;
#define foreach_log_config \
diff --git a/libtransport/src/utils/max_filter.h b/libtransport/src/utils/max_filter.h
new file mode 100644
index 000000000..7a2c6aace
--- /dev/null
+++ b/libtransport/src/utils/max_filter.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.sudo make instamake install
+ */
+
+#pragma once
+
+#include <deque>
+#include <iostream>
+#include <set>
+#include <type_traits>
+#include <vector>
+
+namespace utils {
+
+template <typename T>
+class MaxFilter {
+ public:
+ MaxFilter(std::size_t size) : size_(size) {}
+
+ std::size_t size() { return by_arrival_.size(); }
+
+ template <typename R>
+ void pushBack(R&& value) {
+ if (by_arrival_.size() >= size_) {
+ by_order_.erase(by_arrival_.back());
+ by_arrival_.pop_back();
+ }
+
+ by_arrival_.push_front(by_order_.insert(std::forward<R>(value)));
+ }
+
+ void clear() {
+ by_arrival_.clear();
+ by_order_.clear();
+ }
+
+ const T& begin() { return *by_order_.crbegin(); }
+
+ const T& rBegin() { return *by_order_.rbegin(); }
+
+ private:
+ std::multiset<T> by_order_;
+ std::deque<typename std::multiset<T>::const_iterator> by_arrival_;
+ std::size_t size_;
+};
+
+} // namespace utils
diff --git a/libtransport/src/utils/membuf.cc b/libtransport/src/utils/membuf.cc
index 73c45cf6d..952116bb7 100644
--- a/libtransport/src/utils/membuf.cc
+++ b/libtransport/src/utils/membuf.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Copyright 2013-present Facebook, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include <hicn/transport/portability/win_portability.h>
#endif
+#include <glog/logging.h>
#include <hicn/transport/utils/membuf.h>
#include <cassert>
@@ -209,7 +210,7 @@ MemBuf::MemBuf(CopyBufferOp /* op */, const void* buf, std::size_t size,
: MemBuf(CREATE, headroom + size + min_tailroom) {
advance(headroom);
if (size > 0) {
- assert(buf != nullptr);
+ DCHECK(buf != nullptr);
memcpy(writableData(), buf, size);
append(size);
}
@@ -369,8 +370,8 @@ MemBuf::MemBuf(InternalConstructor, uintptr_t flagsAndSharedInfo, uint8_t* buf,
length_(length),
capacity_(capacity),
flags_and_shared_info_(flagsAndSharedInfo) {
- assert(data >= buf);
- assert(data + length <= buf + capacity);
+ DCHECK(data >= buf);
+ DCHECK(data + length <= buf + capacity);
}
MemBuf::~MemBuf() {
@@ -559,7 +560,7 @@ void MemBuf::unshareOneSlow() {
// minimum capacity we also maintain at least the same amount of tailroom.
std::size_t headlen = headroom();
if (length_ > 0) {
- assert(data_ != nullptr);
+ DCHECK(data_ != nullptr);
memcpy(buf + headlen, data_, length_);
}
@@ -576,7 +577,7 @@ void MemBuf::unshareOneSlow() {
void MemBuf::unshareChained() {
// unshareChained() should only be called if we are part of a chain of
// multiple MemBufs. The caller should have already verified this.
- assert(isChained());
+ DCHECK(isChained());
MemBuf* current = this;
while (true) {
@@ -606,7 +607,7 @@ void MemBuf::markExternallyShared() {
}
void MemBuf::makeManagedChained() {
- assert(isChained());
+ DCHECK(isChained());
MemBuf* current = this;
while (true) {
@@ -677,15 +678,15 @@ void MemBuf::coalesceAndReallocate(size_t new_headroom, size_t new_length,
size_t remaining = new_length;
do {
if (current->length_ > 0) {
- assert(current->length_ <= remaining);
- assert(current->data_ != nullptr);
+ DCHECK(current->length_ <= remaining);
+ DCHECK(current->data_ != nullptr);
remaining -= current->length_;
memcpy(p, current->data_, current->length_);
p += current->length_;
}
current = current->next_;
} while (current != end);
- assert(remaining == 0);
+ DCHECK(remaining == 0);
// Point at the new buffer
decrementRefcount();
@@ -799,7 +800,7 @@ void MemBuf::reserveSlow(std::size_t min_headroom, std::size_t min_tailroom) {
new_allocated_capacity = goodExtBufferSize(new_capacity);
new_buffer = static_cast<uint8_t*>(malloc(new_allocated_capacity));
if (length_ > 0) {
- assert(data_ != nullptr);
+ DCHECK(data_ != nullptr);
memcpy(new_buffer + min_headroom, data_, length_);
}
if (sharedInfo()) {
diff --git a/libtransport/src/utils/memory_pool_allocator.h b/libtransport/src/utils/memory_pool_allocator.h
index a960b91bb..c2b34e7aa 100644
--- a/libtransport/src/utils/memory_pool_allocator.h
+++ b/libtransport/src/utils/memory_pool_allocator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/min_filter.h b/libtransport/src/utils/min_filter.h
index 092555ce0..4c7ae81f1 100644
--- a/libtransport/src/utils/min_filter.h
+++ b/libtransport/src/utils/min_filter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/stream_buffer.h b/libtransport/src/utils/stream_buffer.h
index adfb696f2..dde769a55 100644
--- a/libtransport/src/utils/stream_buffer.h
+++ b/libtransport/src/utils/stream_buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/string_tokenizer.cc b/libtransport/src/utils/string_tokenizer.cc
index a280a3c43..cb0a4a3ad 100644
--- a/libtransport/src/utils/string_tokenizer.cc
+++ b/libtransport/src/utils/string_tokenizer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/suffix_strategy.h b/libtransport/src/utils/suffix_strategy.h
index ee016308e..96eaed662 100644
--- a/libtransport/src/utils/suffix_strategy.h
+++ b/libtransport/src/utils/suffix_strategy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,72 +15,88 @@
#pragma once
-#include <core/manifest_format.h>
+#include <hicn/transport/core/name.h>
+#include <hicn/transport/errors/runtime_exception.h>
namespace utils {
-using transport::core::NextSegmentCalculationStrategy;
+/**
+ * INCREMENTAL: Manifests will be received inline with the data with no specific
+ * assumption regarding the manifest capacity. Consumers can send interests
+ * using a +1 heuristic.
+ *
+ * MANIFEST_CAPACITY_BASED: manifests with capacity N have a suffix multiple of
+ * N+1: 0, N+1, 2(N+1) etc. Contents have a suffix incremented by 1 except when
+ * it conflicts with a manifest: 1, 2, ..., N, N+2, N+3, ..., 2N+1, 2N+3
+ */
+enum class NextSuffixStrategy : uint8_t {
+ INCREMENTAL = 1,
+};
class SuffixStrategy {
public:
- static constexpr uint32_t INVALID_SUFFIX =
- std::numeric_limits<uint32_t>::max();
+ static constexpr uint32_t MAX_SUFFIX = std::numeric_limits<uint32_t>::max();
+ static constexpr uint8_t MAX_MANIFEST_CAPACITY =
+ std::numeric_limits<uint8_t>::max();
- SuffixStrategy(NextSegmentCalculationStrategy strategy)
+ SuffixStrategy(NextSuffixStrategy strategy, uint32_t offset = 0,
+ uint32_t manifest_capacity = MAX_MANIFEST_CAPACITY)
: suffix_stragegy_(strategy),
+ next_suffix_(offset),
+ manifest_capacity_(manifest_capacity),
total_count_(0),
- final_suffix_(INVALID_SUFFIX) {}
+ final_suffix_(MAX_SUFFIX) {}
virtual ~SuffixStrategy() = default;
- virtual uint32_t checkNextSuffix() = 0;
-
+ virtual uint32_t checkNextSuffix() const = 0;
virtual uint32_t getNextSuffix() = 0;
- virtual uint32_t getFinalSuffix() { return final_suffix_; }
-
- virtual void setFinalSuffix(std::uint32_t final_suffix) {
- if (final_suffix != INVALID_SUFFIX) {
- final_suffix_ = final_suffix;
- }
- }
-
- virtual uint32_t checkNextManifestSuffix() = 0;
-
+ virtual uint32_t checkNextManifestSuffix() const = 0;
virtual uint32_t getNextManifestSuffix() = 0;
- virtual uint32_t checkNextContentSuffix() = 0;
-
+ virtual uint32_t checkNextContentSuffix() const = 0;
virtual uint32_t getNextContentSuffix() = 0;
- virtual void reset(uint32_t offset = 0) = 0;
+ virtual void reset(uint32_t offset = 0) {
+ next_suffix_ = offset;
+ total_count_ = 0;
+ }
- virtual uint32_t getManifestCapacity() = 0;
+ virtual uint32_t getManifestCapacity() const { return manifest_capacity_; };
- virtual void setManifestCapacity(uint32_t capacity) = 0;
+ virtual void setManifestCapacity(uint8_t capacity) {
+ manifest_capacity_ = capacity;
+ }
- virtual uint32_t getTotalCount() { return total_count_; };
+ virtual uint32_t getFinalSuffix() const { return final_suffix_; }
- NextSegmentCalculationStrategy getSuffixStrategy() {
- return suffix_stragegy_;
+ virtual void setFinalSuffix(std::uint32_t final_suffix) {
+ if (final_suffix != MAX_SUFFIX) {
+ final_suffix_ = final_suffix;
+ }
}
- protected:
- inline void incrementTotalCount() { total_count_++; };
+ NextSuffixStrategy getSuffixStrategy() const { return suffix_stragegy_; }
+
+ virtual uint32_t getTotalCount() const { return total_count_; }
protected:
- NextSegmentCalculationStrategy suffix_stragegy_;
+ NextSuffixStrategy suffix_stragegy_;
+ std::uint32_t next_suffix_;
+ std::uint8_t manifest_capacity_;
std::uint32_t total_count_;
std::uint32_t final_suffix_;
+
+ inline void incrementTotalCount() { total_count_++; };
};
class IncrementalSuffixStrategy : public SuffixStrategy {
public:
IncrementalSuffixStrategy(std::uint32_t start_offset)
- : SuffixStrategy(NextSegmentCalculationStrategy::INCREMENTAL),
- next_suffix_(start_offset) {}
+ : SuffixStrategy(NextSuffixStrategy::INCREMENTAL, start_offset) {}
- TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextSuffix() override {
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextSuffix() const override {
return next_suffix_;
}
@@ -89,7 +105,8 @@ class IncrementalSuffixStrategy : public SuffixStrategy {
return next_suffix_++;
}
- TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextContentSuffix() override {
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextContentSuffix()
+ const override {
return checkNextSuffix();
}
@@ -97,7 +114,8 @@ class IncrementalSuffixStrategy : public SuffixStrategy {
return getNextSuffix();
}
- TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextManifestSuffix() override {
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextManifestSuffix()
+ const override {
return checkNextSuffix();
}
@@ -105,90 +123,20 @@ class IncrementalSuffixStrategy : public SuffixStrategy {
return getNextSuffix();
}
- uint32_t getManifestCapacity() override {
- throw errors::RuntimeException(
- "No manifest capacity in IncrementalSuffixStrategy.");
- }
-
- void setManifestCapacity(uint32_t capacity) override {
- throw errors::RuntimeException(
- "No manifest capacity in IncrementalSuffixStrategy.");
- }
-
void reset(std::uint32_t offset = 0) override { next_suffix_ = offset; }
-
- protected:
- std::uint32_t next_suffix_;
-};
-
-class CapacityBasedSuffixStrategy : public SuffixStrategy {
- public:
- CapacityBasedSuffixStrategy(std::uint32_t start_offset,
- std::uint32_t manifest_capacity)
- : SuffixStrategy(NextSegmentCalculationStrategy::INCREMENTAL),
- next_suffix_(start_offset),
- segments_in_manifest_(manifest_capacity),
- current_manifest_iteration_(0) {}
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextSuffix() override {
- return next_suffix_;
- }
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t getNextSuffix() override {
- incrementTotalCount();
- return next_suffix_++;
- }
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextContentSuffix() override {
- return next_suffix_ % segments_in_manifest_ == 0 ? next_suffix_
- : (next_suffix_ + 1);
- }
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t getNextContentSuffix() override {
- incrementTotalCount();
- return next_suffix_ % segments_in_manifest_ == 0 ? next_suffix_++
- : ++next_suffix_;
- }
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextManifestSuffix() override {
- return (current_manifest_iteration_ + 1) * (segments_in_manifest_ + 1);
- }
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t getNextManifestSuffix() override {
- incrementTotalCount();
- return (current_manifest_iteration_++) * (segments_in_manifest_ + 1);
- }
-
- TRANSPORT_ALWAYS_INLINE uint32_t getManifestCapacity() override {
- return segments_in_manifest_;
- }
-
- TRANSPORT_ALWAYS_INLINE void setManifestCapacity(uint32_t capacity) override {
- segments_in_manifest_ = capacity;
- }
-
- void reset(std::uint32_t offset = 0) override { next_suffix_ = offset; }
-
- protected:
- std::uint32_t next_suffix_;
- std::uint32_t segments_in_manifest_;
- std::uint32_t current_manifest_iteration_;
};
class SuffixStrategyFactory {
public:
static std::unique_ptr<SuffixStrategy> getSuffixStrategy(
- NextSegmentCalculationStrategy strategy, uint32_t start_offset,
- uint32_t manifest_capacity = 0) {
+ NextSuffixStrategy strategy, uint32_t start_offset = 0,
+ uint32_t manifest_capacity = SuffixStrategy::MAX_MANIFEST_CAPACITY) {
switch (strategy) {
- case NextSegmentCalculationStrategy::INCREMENTAL:
+ case NextSuffixStrategy::INCREMENTAL:
return std::make_unique<IncrementalSuffixStrategy>(start_offset);
- case NextSegmentCalculationStrategy::MANIFEST_CAPACITY_BASED:
- return std::make_unique<CapacityBasedSuffixStrategy>(start_offset,
- manifest_capacity);
default:
throw errors::RuntimeException(
- "No valid NextSegmentCalculationStrategy specified.");
+ "No valid NextSuffixStrategy specified.");
}
}
};
diff --git a/libtransport/src/utils/test.h b/libtransport/src/utils/test.h
index e3dd619ac..b91c8cb1f 100644
--- a/libtransport/src/utils/test.h
+++ b/libtransport/src/utils/test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/utils/uri.cc b/libtransport/src/utils/uri.cc
index 33eb8b45b..12b11641c 100644
--- a/libtransport/src/utils/uri.cc
+++ b/libtransport/src/utils/uri.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/third-party/CMakeLists.txt b/libtransport/third-party/CMakeLists.txt
index 46a4c0f23..ad7b14ead 100644
--- a/libtransport/third-party/CMakeLists.txt
+++ b/libtransport/third-party/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-include(FetchContent)
-
set (THIRD_PARTY_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})
option(ENABLE_RELY "Enable download/build of rely library" OFF)
@@ -20,21 +18,34 @@ option(ENABLE_RELY "Enable download/build of rely library" OFF)
if (ENABLE_RELY)
##################################
# Download librely
-
- if(DEFINED ENV{BITBUCKET_USERNAME} AND DEFINED ENV{BITBUCKET_PASSWORD})
- set(GIT_REPO https://$ENV{BITBUCKET_USERNAME}:$ENV{BITBUCKET_PASSWORD}@bitbucket-eng-gpk1.cisco.com/bitbucket/scm/icn/rely.git)
+
+ if (INTERNAL_ENVIRONMENT)
+ include(SetRelyGitRepo)
+ SetRelyGitRepo()
else()
- set(GIT_REPO ssh://git@bitbucket-eng-gpk1.cisco.com:7999/icn/rely.git)
+ if(DEFINED ENV{GITHUB_USERNAME} AND DEFINED ENV{GITHUB_PASSWORD})
+ set(GIT_REPO https://$ENV{GITHUB_USERNAME}:$ENV{GITHUB_PASSWORD}@github.com/steinwurf/rely.git)
+ else()
+ set(GIT_REPO ssh://github.com/steinwurf/rely.git)
+ endif()
endif()
FetchContent_Declare(
rely
GIT_REPOSITORY ${GIT_REPO}
GIT_TAG release/latest
+ GIT_SHALLOW
+ GIT_PROGRESS
+ EXCLUDE_FROM_ALL
)
set(ENABLE_PIC ON)
- FetchContent_MakeAvailable(rely)
+ FetchContent_GetProperties(rely)
+ if(NOT rely_POPULATED)
+ pr("Download and build" "rely")
+ FetchContent_Populate(rely)
+ add_subdirectory(${rely_SOURCE_DIR} ${rely_BINARY_DIR} EXCLUDE_FROM_ALL)
+ endif()
list(APPEND THIRD_PARTY_INCLUDE_DIRS
${rely_BINARY_DIR}
@@ -44,7 +55,7 @@ if (ENABLE_RELY)
# Get rely libraries
get_property(steinwurf_object_libraries GLOBAL
PROPERTY steinwurf::object_libraries)
-
+
foreach(rely_library ${steinwurf_object_libraries})
list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
$<TARGET_OBJECTS:${rely_library}>
@@ -60,9 +71,19 @@ FetchContent_Declare(
glog
URL https://github.com/google/glog/archive/refs/tags/v0.5.0.zip
PATCH_COMMAND patch -p1 CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/glog.patch
+ EXCLUDE_FROM_ALL
)
-FetchContent_MakeAvailable(glog)
+FetchContent_GetProperties(glog)
+if(NOT glog_POPULATED)
+ pr("Download and build" "glog")
+ FetchContent_Populate(glog)
+ option(WITH_GFLAGS OFF)
+ option(WITH_GTEST OFF)
+ option(WITH_UNWIND OFF)
+ option(BUILD_TESTING OFF)
+ add_subdirectory(${glog_SOURCE_DIR} ${glog_BINARY_DIR} EXCLUDE_FROM_ALL)
+endif()
list(APPEND THIRD_PARTY_INCLUDE_DIRS
${glog_BINARY_DIR}
@@ -77,6 +98,42 @@ list(APPEND THIRD_PARTY_DEPENDENCIES
glog
)
+if(UNIX AND (NOT APPLE) AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES Android))
+ ##############################################################
+ # Get memif version
+ ##############################################################
+ list(GET LIBMEMIF_DEFAULT_VERSION 0 MEMIF_VERSION)
+
+ FetchContent_Declare(
+ memif
+ GIT_REPOSITORY https://github.com/FDio/vpp
+ GIT_TAG v${MEMIF_VERSION}
+ GIT_SHALLOW
+ GIT_PROGRESS
+ PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/memif.patch
+ EXCLUDE_FROM_ALL
+ )
+
+ FetchContent_GetProperties(memif)
+ if(NOT memif_POPULATED)
+ FetchContent_Populate(memif)
+ add_subdirectory(${memif_SOURCE_DIR}/extras/libmemif ${memif_BINARY_DIR} EXCLUDE_FROM_ALL)
+ endif()
+
+ list(APPEND THIRD_PARTY_INCLUDE_DIRS
+ ${memif_BINARY_DIR}
+ ${memif_SOURCE_DIR}/extras/libmemif/src
+ )
+
+ list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
+ $<TARGET_OBJECTS:memif>
+ )
+
+ list(APPEND THIRD_PARTY_DEPENDENCIES
+ memif
+ )
+endif()
+
set (THIRD_PARTY_LIBRARIES ${THIRD_PARTY_LIBRARIES} PARENT_SCOPE)
set (THIRD_PARTY_OBJECT_LIBRARIES ${THIRD_PARTY_OBJECT_LIBRARIES} PARENT_SCOPE)
set (THIRD_PARTY_INCLUDE_DIRS ${THIRD_PARTY_INCLUDE_DIRS} PARENT_SCOPE)
diff --git a/libtransport/third-party/CMakeLists.txt.orig b/libtransport/third-party/CMakeLists.txt.orig
deleted file mode 100644
index 84db8cb4c..000000000
--- a/libtransport/third-party/CMakeLists.txt.orig
+++ /dev/null
@@ -1,85 +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(FetchContent)
-
-set (THIRD_PARTY_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})
-
-option(ENABLE_RELY "Enable download/build of rely library" OFF)
-
-if (ENABLE_RELY)
- ##################################
- # Download librely
-
- if(DEFINED ENV{BITBUCKET_USERNAME} AND DEFINED ENV{BITBUCKET_PASSWORD})
- set(GIT_REPO https://$ENV{BITBUCKET_USERNAME}:$ENV{BITBUCKET_PASSWORD}@bitbucket-eng-gpk1.cisco.com/bitbucket/scm/icn/rely.git)
- else()
- set(GIT_REPO ssh://git@bitbucket-eng-gpk1.cisco.com:7999/icn/rely.git)
- endif()
-
- FetchContent_Declare(
- rely
- GIT_REPOSITORY ${GIT_REPO}
- GIT_TAG release/latest
- FETCHCONTENT_QUIET
- )
-
- set(ENABLE_PIC ON)
- FetchContent_MakeAvailable(rely)
-
- list(APPEND THIRD_PARTY_INCLUDE_DIRS
- ${rely_BINARY_DIR}
- ${rely_SOURCE_DIR}/src
- )
-
- # Get rely libraries
- get_property(steinwurf_object_libraries GLOBAL
- PROPERTY steinwurf::object_libraries)
-
- foreach(rely_library ${steinwurf_object_libraries})
- list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
- $<TARGET_OBJECTS:${rely_library}>
- )
- endforeach()
-
- list(APPEND THIRD_PARTY_DEPENDENCIES
- rely
- )
-endif()
-
-FetchContent_Declare(
- glog
- URL https://github.com/google/glog/archive/refs/tags/v0.5.0.zip
- PATCH_COMMAND patch -p1 CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/glog.patch
- FETCHCONTENT_QUIET
-)
-
-FetchContent_MakeAvailable(glog)
-
-list(APPEND THIRD_PARTY_INCLUDE_DIRS
- ${glog_BINARY_DIR}
- ${glog_SOURCE_DIR}/src
-)
-
-list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
- $<TARGET_OBJECTS:glog>
-)
-
-list(APPEND THIRD_PARTY_DEPENDENCIES
- glog
-)
-
-set (THIRD_PARTY_LIBRARIES ${THIRD_PARTY_LIBRARIES} PARENT_SCOPE)
-set (THIRD_PARTY_OBJECT_LIBRARIES ${THIRD_PARTY_OBJECT_LIBRARIES} PARENT_SCOPE)
-set (THIRD_PARTY_INCLUDE_DIRS ${THIRD_PARTY_INCLUDE_DIRS} PARENT_SCOPE)
-set (THIRD_PARTY_DEPENDENCIES ${THIRD_PARTY_DEPENDENCIES} PARENT_SCOPE)
diff --git a/libtransport/third-party/CMakeLists.txt.rej b/libtransport/third-party/CMakeLists.txt.rej
deleted file mode 100644
index 4ebaf9061..000000000
--- a/libtransport/third-party/CMakeLists.txt.rej
+++ /dev/null
@@ -1,21 +0,0 @@
---- CMakeLists.txt
-+++ CMakeLists.txt
-@@ -41,9 +41,6 @@ if (NOT WITH_THREADS)
- set (CMAKE_DISABLE_FIND_PACKAGE_Threads ON)
- endif (NOT WITH_THREADS)
-
--set (CMAKE_C_VISIBILITY_PRESET hidden)
--set (CMAKE_CXX_VISIBILITY_PRESET hidden)
--set (CMAKE_VISIBILITY_INLINES_HIDDEN 1)
- list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-
- include (CheckCXXSourceCompiles)
-@@ -570,7 +567,7 @@ if (_glog_CMake_MODULES)
- )
- endif (_glog_CMake_MODULES)
-
--add_library (glog
-+add_library (glog OBJECT
- ${GLOG_SRCS}
- ${_glog_BINARY_CMake_MODULES}
- )
diff --git a/libtransport/third-party/glog.patch b/libtransport/third-party/glog.patch
index 9d6e46df0..4f4d440eb 100644
--- a/libtransport/third-party/glog.patch
+++ b/libtransport/third-party/glog.patch
@@ -20,4 +20,4 @@ index 62ebbcc..7d92fa5 100644
+add_library (glog OBJECT
${GLOG_SRCS}
${_glog_BINARY_CMake_MODULES}
- )
+ ) \ No newline at end of file
diff --git a/libtransport/third-party/memif.patch b/libtransport/third-party/memif.patch
new file mode 100644
index 000000000..0a64513e3
--- /dev/null
+++ b/libtransport/third-party/memif.patch
@@ -0,0 +1,43 @@
+diff --git a/extras/libmemif/CMakeLists.txt b/extras/libmemif/CMakeLists.txt
+index b6b658c2d..28bb8c135 100644
+--- a/extras/libmemif/CMakeLists.txt
++++ b/extras/libmemif/CMakeLists.txt
+@@ -24,7 +24,7 @@ if (NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release")
+ endif ()
+
+-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -DMEMIF_DBG -DICMP_DBG")
++set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -DICMP_DBG")
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+ set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
+ set(CMAKE_INSTALL_MESSAGE NEVER)
+diff --git a/extras/libmemif/src/CMakeLists.txt b/extras/libmemif/src/CMakeLists.txt
+index ddb8a52f8..b52566e5c 100644
+--- a/extras/libmemif/src/CMakeLists.txt
++++ b/extras/libmemif/src/CMakeLists.txt
+@@ -32,22 +32,7 @@ list(APPEND MEMIF_SOURCES
+
+ include_directories(${HEADERS_DIR})
+
+-add_library(memif SHARED ${MEMIF_SOURCES})
+-target_link_libraries(memif ${CMAKE_THREAD_LIBS_INIT})
++add_library(memif OBJECT ${MEMIF_SOURCES})
++set_property(TARGET memif PROPERTY POSITION_INDEPENDENT_CODE ON)
+
+-find_library(LIB_BSD bsd)
+-if(LIB_BSD)
+- add_compile_definitions(HAS_LIB_BSD)
+- target_link_libraries(memif ${LIB_BSD})
+-endif()
+-
+-foreach(file ${MEMIF_HEADERS})
+- get_filename_component(dir ${file} DIRECTORY)
+- install(
+- FILES ${file}
+- DESTINATION include/${lib}/${dir}
+- COMPONENT libmemif-dev
+- )
+-endforeach()
+-
+-install(TARGETS memif DESTINATION lib COMPONENT libmemif)
++target_link_libraries(memif ${CMAKE_THREAD_LIBS_INIT})
diff --git a/scripts/build-packages.sh b/scripts/build-packages.sh
index bc386c398..d7684e400 100644
--- a/scripts/build-packages.sh
+++ b/scripts/build-packages.sh
@@ -28,21 +28,11 @@ function build_package() {
echo "*******************************************************************"
# Make the package
- mkdir -p ${SCRIPT_PATH}/../build && pushd ${SCRIPT_PATH}/../build
- rm -rf *
+ make -C ${SCRIPT_PATH}/.. INSTALL_PREFIX=/usr test package-release
- cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr \
- -DBUILD_HICNPLUGIN=ON \
- -DBUILD_LIBTRANSPORT=ON \
- -DBUILD_APPS=ON \
- -DBUILD_HICNLIGHT=ON \
- -DBUILD_TELEMETRY=ON \
- ${SCRIPT_PATH}/..
-
- ninja -j8 package
-
- find . -not -name '*.deb' -not -name '*.rpm' -print0 | xargs -0 rm -rf -- || true
- rm *Unspecified* *Development* *development* || true
+ pushd ${SCRIPT_PATH}/../build-release-${ID}
+ find . -not -name '*.deb' -not -name '*.rpm' -print0 | xargs -0 rm -rf -- || true
+ rm *Unspecified* *Development* *development* || true
popd
echo "*******************************************************************"
@@ -57,30 +47,15 @@ build_sphinx() {
echo "********************* STARTING DOC BUILD **************************"
echo "*******************************************************************"
- # Make the package
- pip3 install -r ${SCRIPT_PATH}/../docs/etc/requirements.txt
- pushd ${SCRIPT_PATH}/../docs
- make html
-
- popd
+ make doc
echo "*******************************************************************"
echo "***************** BUILD COMPLETED SUCCESSFULLY *******************"
echo "*******************************************************************"
}
-build_doxygen() {
- setup
-
- mkdir -p ${SCRIPT_PATH}/../build-doxygen
- pushd ${SCRIPT_PATH}/../build-doxygen
- cmake -DBUILD_HICNPLUGIN=On -DBUILD_HICNLIGHT=OFF -DBUILD_LIBTRANSPORT=OFF -DBUILD_UTILS=OFF -DBUILD_APPS=OFF -DBUILD_CTRL=OFF ..
- make doc
- popd
-}
-
function usage() {
- echo "Usage: ${0} [sphinx|doxygen|packages]"
+ echo "Usage: ${0} [sphinx|packages]"
exit 1
}
@@ -92,9 +67,6 @@ case "${1}" in
sphinx)
build_sphinx
;;
- doxygen)
- build_doxygen
- ;;
packages)
build_package
;;
diff --git a/scripts/checkstyle.sh b/scripts/checkstyle.sh
index ae775aca9..46cba4507 100644
--- a/scripts/checkstyle.sh
+++ b/scripts/checkstyle.sh
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -11,4 +11,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-exit 0 \ No newline at end of file
+exit 0
diff --git a/scripts/functions.sh b/scripts/functions.sh
index abb34fb7b..e416ee274 100644
--- a/scripts/functions.sh
+++ b/scripts/functions.sh
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
+# 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:
@@ -14,121 +14,62 @@
#!/bin/bash
set -euxo pipefail
-APT_PATH=`which apt-get` || true
+APT_PATH=$(which apt-get) || true
apt_get=${APT_PATH:-"/usr/local/bin/apt-get"}
# Cmake executable
CMAKE_INSTALL_DIR="/opt/cmake"
export PATH=:${CMAKE_INSTALL_DIR}/bin:${PATH}
-PACKAGECLOUD_RELEASE_REPO_DEB="https://packagecloud.io/install/repositories/fdio/release/script.deb.sh"
-PACKAGECLOUD_RELEASE_REPO_RPM="https://packagecloud.io/install/repositories/fdio/release/script.rpm.sh"
-PACKAGECLOUD_HICN_REPO_DEB="https://packagecloud.io/install/repositories/fdio/hicn/script.deb.sh"
-PACKAGECLOUD_HICN_REPO_RPM="https://packagecloud.io/install/repositories/fdio/hicn/script.rpm.sh"
-
-VPP_GIT_REPO="https://github.com/FDio/vpp"
-VPP_BRANCH="stable/2005"
-
- # Figure out what system we are running on
+# Figure out what system we are running on
if [ -f /etc/os-release ]; then
- . /etc/os-release
+ . /etc/os-release
else
- echo "ERROR: System configuration not recognized. Build failed"
- exit 1
+ echo "ERROR: System configuration not recognized. Build failed"
+ exit 1
fi
-VERSION_REGEX="s/v([0-9]+).([0-9]+)(.*)?-([0-9]+)-(g[0-9a-f]+)/\1.\2-release/g"
-VPP_VERSION_DEB=$(git describe --long --match "v*" | sed -E ${VERSION_REGEX})
-VPP_VERSION_RPM="${VPP_VERSION_DEB}.x86_64"
-
-DEPS_UBUNTU=("build-essential"
- "doxygen"
- "curl"
- "cmake"
- "libasio-dev"
- "libconfig-dev"
- "libconfig++-dev"
- "libcurl4-openssl-dev"
- "libevent-dev"
- "libssl-dev"
- "ninja-build"
- "python3-ply")
-
-DEPS_UBUNTU_PKGCLOUD=("libparc-dev"
- "libmemif-dev"
- "libmemif"
- "vpp=${VPP_VERSION_DEB}"
- "vpp-dev=${VPP_VERSION_DEB}"
- "libvppinfra=${VPP_VERSION_DEB}"
- "libvppinfra-dev=${VPP_VERSION_DEB}"
- "vpp-plugin-core=${VPP_VERSION_DEB}"
- "libparc-dev")
-
COLLECTD_SOURCE="https://github.com/collectd/collectd/releases/download/collectd-5.12.0/collectd-5.12.0.tar.bz2"
function install_collectd_headers() {
- curl -OL ${COLLECTD_SOURCE}
- tar -xf collectd-5.12.0.tar.bz2
+ curl -OL ${COLLECTD_SOURCE}
+ tar -xf collectd-5.12.0.tar.bz2
- pushd collectd-5.12.0
- ./configure && make -j$(nproc)
- popd
+ pushd collectd-5.12.0
+ ./configure && make -j$(nproc)
+ popd
- export COLLECTD_HOME=${PWD}/collectd-5.12.0/src
+ export COLLECTD_HOME=${PWD}/collectd-5.12.0/src
}
-function setup_fdio_repo() {
- DISTRIB_ID=${ID}
-
- if [ "${DISTRIB_ID}" == "ubuntu" ]; then
- curl -s ${PACKAGECLOUD_RELEASE_REPO_DEB} | sudo bash
- curl -s ${PACKAGECLOUD_HICN_REPO_DEB} | sudo bash
- elif [ "${DISTRIB_ID}" == "centos" ]; then
- curl -s ${PACKAGECLOUD_RELEASE_REPO_RPM} | sudo bash
- curl -s ${PACKAGECLOUD_HICN_REPO_RPM} | sudo bash
- else
- echo "Distribution ${DISTRIB_ID} is not supported"
- exit 1
- fi
+# Call a function once
+function call_once() {
+ # OP_NAME is the name of the function
+ OP_NAME=${1}
+ # If function was already called return
+ [[ -f /tmp/${OP_NAME} ]] && return 0
+ # Otherwise call the function
+ ${@}
+ # And mark the function as called if no error occurred
+ echo ${OP_NAME} >/tmp/${OP_NAME}
}
# Install dependencies
function install_deps() {
- DISTRIB_ID=${ID}
- echo ${DEPS_UBUNTU[@]} | xargs sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends
-}
-
-function install_pkgcloud_deps() {
- DISTRIB_ID=${ID}
- echo ${DEPS_UBUNTU_PKGCLOUD[@]} | xargs sudo ${apt_get} install -y --allow-unauthenticated --no-install-recommends
-}
-
-# Call a function once
-function call_once() {
- # OP_NAME is the name of the function
- OP_NAME=${1}
- # If function was already called return
- [[ -f /tmp/${OP_NAME} ]] && return 0
- # Otherwise call the function
- ${@}
- # And mark the function as called if no error occurred
- echo ${OP_NAME} > /tmp/${OP_NAME}
+ make -C ${SCRIPT_PATH}/.. deps
}
function setup() {
- echo DISTRIBUTION: ${PRETTY_NAME}
- # export variables depending on the platform we are running
-
- call_once setup_fdio_repo
- call_once install_deps
- call_once install_pkgcloud_deps
- call_once install_collectd_headers
+ echo DISTRIBUTION: ${PRETTY_NAME}
+ # export variables depending on the platform we are running
+ call_once install_deps
+ call_once install_collectd_headers
}
function setup_extras() {
- echo DISTRIBUTION: ${PRETTY_NAME}
- # export variables depending on the platform we are running
+ echo DISTRIBUTION: ${PRETTY_NAME}
+ # export variables depending on the platform we are running
- call_once install_deps
- call_once install_collectd_headers
+ call_once install_deps
+ call_once install_collectd_headers
}
diff --git a/scripts/install-vpp.sh b/scripts/install-vpp.sh
new file mode 100644
index 000000000..a58e1bcad
--- /dev/null
+++ b/scripts/install-vpp.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+################################################################
+# Install defined VPP version
+################################################################
+
+if [[ -z ${VERSION_PATH} ]]; then
+ echo >&2 "No version path provided. Exit now."
+ exit 1
+fi
+
+# Prevent vpp to set sysctl
+export VPP_INSTALL_SKIP_SYSCTL=1
+VPP_VERSION=$(cat "${VERSION_PATH}" | grep VPP_DEFAULT_VERSION | cut -d ' ' -f 2 | tr -d '"' | grep -Po '\d\d.\d\d')
+
+curl -s https://packagecloud.io/install/repositories/fdio/${VPP_VERSION//./}/script.deb.sh | bash
+curl -L https://packagecloud.io/fdio/${VPP_VERSION//./}/gpgkey | apt-key add -
+sed -E -i 's/(deb.*)(\[.*\])(.*)/\1\3/g' /etc/apt/sources.list.d/fdio_${VPP_VERSION//./}.list
+
+# create apt pinning
+cat << EOF | tee /etc/apt/preferences.d/vpp-pin
+Package: vpp*
+Pin: release o=packagecloud.io/fdio/${VPP_VERSION//./}
+Pin-Priority: 1000
+
+Package: libvpp*
+Pin: release o=packagecloud.io/fdio/${VPP_VERSION//./}
+Pin-Priority: 1000
+EOF
+
+apt-get update
+
+apt-get install -y \
+ vpp-dev \
+ libvppinfra-dev \
+ vpp-plugin-core \
+ vpp \
+ libvppinfra
diff --git a/telemetry/CMakeLists.txt b/telemetry/CMakeLists.txt
index fbb929529..eff855646 100644
--- a/telemetry/CMakeLists.txt
+++ b/telemetry/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -14,8 +14,16 @@
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-if ((CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) OR
+##############################################################
+# Packaging and versioning
+##############################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+
+
+##############################################################
+# Subdirectories
+##############################################################
+if ((CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) OR
(BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
add_subdirectory(vpp-collectd)
endif ()
-
diff --git a/telemetry/vpp-collectd/CMakeLists.txt b/telemetry/vpp-collectd/CMakeLists.txt
index 7afb3f432..54a1a4b76 100644
--- a/telemetry/vpp-collectd/CMakeLists.txt
+++ b/telemetry/vpp-collectd/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,18 +11,50 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(COLLECTD_PLUGINS hicn-collectd-plugins)
project(hicn-collectd-plugins)
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/" "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules/")
-include(BuildMacros)
+##############################################################
+# 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)
+
+
+##############################################################
+# Compiler Options
+##############################################################
+set(COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+)
+
+##############################################################
+# Subdirectories
+##############################################################
add_subdirectory(vpp)
add_subdirectory(vpp-hicn)
-include(Packaging)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- include(Packager)
- make_packages()
+ make_packages()
endif()
diff --git a/telemetry/vpp-collectd/cmake/Modules/Packaging.cmake b/telemetry/vpp-collectd/cmake/packaging.cmake
index 72da05d02..49a617342 100644
--- a/telemetry/vpp-collectd/cmake/Modules/Packaging.cmake
+++ b/telemetry/vpp-collectd/cmake/packaging.cmake
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -21,11 +21,11 @@ set(${COLLECTD_PLUGINS}_DESCRIPTION
)
set(${COLLECTD_PLUGINS}_DEB_DEPENDENCIES
- "collectd, hicn-plugin-dev"
+ "collectd, hicn-plugin-dev (= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${COLLECTD_PLUGINS}_RPM_DEPENDENCIES
- "collectd, hicn-plugin-dev"
+ "collectd, hicn-plugin-dev = stable_version"
CACHE STRING "Dependencies for deb/rpm package."
) \ No newline at end of file
diff --git a/telemetry/vpp-collectd/common/plugin.h b/telemetry/vpp-collectd/common/plugin.h
index 0e75adc9b..bbd69e003 100644
--- a/telemetry/vpp-collectd/common/plugin.h
+++ b/telemetry/vpp-collectd/common/plugin.h
@@ -43,13 +43,11 @@
#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"
+ (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
diff --git a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
index 9db20be38..d55aede80 100644
--- a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,45 +11,56 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
-
-# Dependencies
-find_package(Collectd REQUIRED)
-find_package(Vpp REQUIRED)
-
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
if(${CMAKE_SOURCE_DIR}/vpp-collectd STREQUAL ${PROJECT_SOURCE_DIR})
message (STATUS "not compiling in the same folder")
- find_package(HicnPlugin REQUIRED)
- find_package(VapiSafe REQUIRED)
+ find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
+ find_package(Vapisafe ${CURRENT_VERSION} REQUIRED)
else()
message (STATUS "compiling in the same folder")
list(APPEND DEPENDENCIES
- hicn_plugin
+ ${HICNPLUGIN_SHARED}
)
endif()
+
+##############################################################
+# Sources
+##############################################################
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp_hicn.c)
+ ${CMAKE_CURRENT_SOURCE_DIR}/vpp_hicn.c
+)
list(APPEND INCLUDE_DIRS
- ${COLLECTD_INCLUDE_DIRS}
- ${HICNPLUGIN_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
- ${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR}
- "${CMAKE_CURRENT_SOURCE_DIR}/../common")
+ ${COLLECTD_INCLUDE_DIRS}
+ ${HICNPLUGIN_INCLUDE_DIRS}
+ ${SAFE_VAPI_INCLUDE_DIRS}
+ ${VPP_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ "${CMAKE_CURRENT_SOURCE_DIR}/../common"
+)
+
+##############################################################
+# Libs
+##############################################################
list(APPEND LIBRARIES
- ${VPP_LIBRARY_VAPICLIENT}
- ${SAFE_VAPI_LIBRARIES})
+ ${VPP_LIBRARY_VAPICLIENT}
+ ${SAFE_VAPI_LIBRARIES}
+)
+
+##############################################################
+# Build library
+##############################################################
build_library(vpp_hicn
- SHARED
- SOURCES ${SOURCE_FILES}
- LINK_LIBRARIES ${LIBRARIES}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_FULL_PATH_DIR ${CMAKE_INSTALL_PREFIX}/lib/collectd
- COMPONENT "${COLLECTD_PLUGINS}"
- DEPENDS ${DEPENDENCIES}
- EMPTY_PREFIX true
- )
+ SOURCES ${SOURCE_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${CMAKE_INSTALL_PREFIX}/lib/collectd
+ 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 b6bc3af49..a724c1124 100644
--- a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
+++ b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -14,8 +14,8 @@
*/
/* Keep order as it is */
-#include <config.h>
#include "common.h"
+#include <config.h>
#define counter_t vpp_counter_t
#include <vapi/hicn.api.vapi.h>
diff --git a/telemetry/vpp-collectd/vpp/CMakeLists.txt b/telemetry/vpp-collectd/vpp/CMakeLists.txt
index c36787355..41c19208a 100644
--- a/telemetry/vpp-collectd/vpp/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2021-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:
@@ -11,29 +11,39 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Dependencies
-find_package(Vpp REQUIRED)
-find_package(Collectd REQUIRED)
-
+##############################################################
+# Sources
+##############################################################
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp.c)
+ ${CMAKE_CURRENT_SOURCE_DIR}/vpp.c
+)
+
+##############################################################
+# Include directories
+##############################################################
list(APPEND INCLUDE_DIRS
- ${COLLECTD_INCLUDE_DIRS}
- ${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR}
- "${CMAKE_CURRENT_SOURCE_DIR}/../common")
+ ${COLLECTD_INCLUDE_DIRS}
+ ${VPP_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ "${CMAKE_CURRENT_SOURCE_DIR}/../common"
+)
+
+##############################################################
+# Libraries
+##############################################################
list(APPEND LIBRARIES
- ${VPP_LIBRARY_VPPAPICLIENT}
- ${VPP_LIBRARY_INFRA})
+ ${VPP_LIBRARY_VPPAPICLIENT}
+ ${VPP_LIBRARY_INFRA}
+)
+
-build_library(vpp
- SHARED
- SOURCES ${SOURCE_FILES}
- LINK_LIBRARIES ${LIBRARIES}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_FULL_PATH_DIR ${CMAKE_INSTALL_PREFIX}/lib/collectd
- COMPONENT ${COLLECTD_PLUGINS}
- EMPTY_PREFIX true
- )
+build_module(vpp
+ SOURCES ${SOURCE_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${CMAKE_INSTALL_PREFIX}/lib/collectd
+ COMPONENT ${COLLECTD_PLUGINS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
diff --git a/telemetry/vpp-collectd/vpp/vpp.c b/telemetry/vpp-collectd/vpp/vpp.c
index dcf956c93..85d0971d0 100644
--- a/telemetry/vpp-collectd/vpp/vpp.c
+++ b/telemetry/vpp-collectd/vpp/vpp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * 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:
@@ -14,8 +14,8 @@
*/
/* Keep order as it is */
-#include <config.h>
#include "common.h"
+#include <config.h>
#define counter_t vpp_counter_t
#include <vpp-api/client/stat_client.h>
diff --git a/tests/.env b/tests/.env
new file mode 100644
index 000000000..35c861bda
--- /dev/null
+++ b/tests/.env
@@ -0,0 +1,13 @@
+# Topologies
+TOPOLOGY_2_NODES=2-nodes
+
+# Container names
+TEST_LIGHT=hicn-light
+TEST_VPP_BRIDGE=vpp-bridge
+TEST_VPP_MEMIF=vpp-memif
+TEST_VPP_MEMIF_REPLICATION=vpp-memif-replication
+
+# names
+RTC_PRODUCER=b002::1
+RAAQM_PRODUCER=b002::2
+PING_PRODUCER=b002::3
diff --git a/tests/2-nodes-hicn-light.yml b/tests/2-nodes-hicn-light.yml
new file mode 100644
index 000000000..e62a6c705
--- /dev/null
+++ b/tests/2-nodes-hicn-light.yml
@@ -0,0 +1,65 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_LIGHT}-client
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo ip link add br0 type bridge
+ sudo ip addr add 192.168.1.1/24 dev br0
+ sudo ip link set eth0 master br0
+ sudo ip link set eth0 up
+ sudo ip link set br0 up
+ sudo ip route add 192.168.1.2 via 192.168.1.1 dev br0
+ tee -a /tmp/hicn-light.conf <<EOF
+ add listener udp local0 192.168.1.1 9199 br0
+ add connection udp conn0 192.168.1.2 9199 192.168.1.1 9199
+ add route conn0 b002::/64 1
+ EOF
+
+ rm -f /tmp/lite_client.log
+
+ sudo hicn-light-daemon \
+ --daemon \
+ --log-file /tmp/lite_client.log \
+ --config /tmp/hicn-light.conf --capacity 0
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_LIGHT}-server
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo ip link add br0 type bridge
+ sudo ip addr add 192.168.1.2/24 dev br0
+ sudo ip link set eth0 master br0
+ sudo ip link set eth0 up
+ sudo ip link set br0 up
+
+ tee -a /tmp/hicn-light.conf <<EOF
+ add listener udp local0 192.168.1.2 9199 br0
+ add connection udp conn0 192.168.1.1 9199 192.168.1.2 9199
+ add route conn0 b002::/64 1
+ EOF
+
+ rm -f /tmp/lite_server.log
+
+ sudo hicn-light-daemon \
+ --daemon \
+ --log-file /tmp/lite_server.log \
+ --config /tmp/hicn-light.conf --capacity 0
+
+ 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
+
+ tail -f /dev/null
diff --git a/tests/2-nodes-vpp-bridge.yml b/tests/2-nodes-vpp-bridge.yml
new file mode 100644
index 000000000..d9426844f
--- /dev/null
+++ b/tests/2-nodes-vpp-bridge.yml
@@ -0,0 +1,107 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_VPP_BRIDGE}-client
+ volumes:
+ - ..:/workspace
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo ip link add br0 type bridge
+ sudo ip link set eth0 master br0
+ sudo ip link set eth0 up
+ sudo ip link set br0 up
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ plugins {
+ path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log /var/log/vpp/vpp.log
+ }
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ create tap id 0 host-bridge br0
+ set int state tap0 up
+ set int ip addr tap0 192.168.1.1/24
+ set int ip addr tap0 2001::1/64
+ ip route add b002::1/64 via 2001::2 tap0
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+ sudo vppctl hicn enable b002::1/64
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_VPP_BRIDGE}-server
+ volumes:
+ - ..:/workspace
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo ip link add br0 type bridge
+ sudo ip link set eth0 master br0
+ sudo ip link set eth0 up
+ sudo ip link set br0 up
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ plugins {
+ path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log /var/log/vpp/vpp.log
+ }
+ EOF
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ create tap id 0 host-bridge br0
+ set int state tap0 up
+ set int ip addr tap0 192.168.1.12/24
+ set int ip addr tap0 2001::2/64
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128
+ sleep 1
+ sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128
+ sleep 1
+ sudo hicn-ping-server -d -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
new file mode 100644
index 000000000..37f028dac
--- /dev/null
+++ b/tests/2-nodes-vpp-memif-replication.yml
@@ -0,0 +1,143 @@
+version: "3"
+services:
+ vpp_client_memif:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ BASE_IMAGE: ${BASE_IMAGE}
+ stdin_open: true
+ tty: true
+ working_dir: /workspace
+ container_name: ${TEST_VPP_MEMIF_REPLICATION}-client
+ hostname: client
+ volumes:
+ - /tmp/memif:/memif
+ - ..:/workspace
+ entrypoint: [/bin/bash, -c]
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ buffers { buffers-per-numa 600000 }
+ plugins {
+ path /hicn-root/lib/vpp_plugins:/usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log /var/log/vpp/vpp.log
+ }
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 hw-addr aa:bb:cc:dd:ee:01 master
+ set int state memif1/0 up
+ set int ip addr memif1/0 192.168.1.1/24
+ set int ip addr memif1/0 2001::1/64
+ set ip neighbor memif1/0 2001::2 aa:bb:cc:dd:ee:02 static
+ ip route add b002::1/64 via 2001::2 memif1/0
+ create interface memif id 1 socket-id 1 hw-addr aa:bb:bb:bb:ee:01 master
+ set int state memif1/1 up
+ set int ip addr memif1/1 192.168.2.1/24
+ set int ip addr memif1/1 2002::1/64
+ set ip neighbor memif1/1 2002::2 aa:bb:bb:bb:ee:02 static
+ ip route add b002::1/64 via 2002::2 memif1/1
+ EOF
+
+ sudo rm /memif/memif1.sock
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo vppctl hicn enable b002::1/64
+ sudo vppctl hicn strategy set 2 prefix b002::/64
+
+ tail -f /dev/null
+ vpp_server_memif:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ BASE_IMAGE: ${BASE_IMAGE}
+ stdin_open: true
+ tty: true
+ working_dir: /workspace
+ container_name: ${TEST_VPP_MEMIF_REPLICATION}-server
+ hostname: server
+ volumes:
+ - /tmp/memif:/memif
+ - ..:/workspace
+ entrypoint: [/bin/bash, -c]
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ buffers { buffers-per-numa 600000 }
+
+ plugins {
+ path /hicn-root/lib/vpp_plugins:/usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log /var/log/vpp/vpp.log
+ }
+ EOF
+
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 hw-addr aa:bb:cc:dd:ee:02 slave
+ set int state memif1/0 up
+ set int ip addr memif1/0 192.168.1.2/24
+ set int ip addr memif1/0 2001::2/64
+ set ip neighbor memif1/0 2001::1 aa:bb:cc:dd:ee:01 static
+ create interface memif id 1 socket-id 1 hw-addr aa:bb:bb:bb:ee:02 slave
+ set int state memif1/1 up
+ set int ip addr memif1/1 192.168.2.2/24
+ set int ip addr memif1/1 2002::2/64
+ set ip neighbor memif1/1 2002::1 aa:bb:bb:bb:ee:01 static
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 10
+
+ sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128
+ sleep 5
+ sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128
+ sleep 5
+ sudo hicn-ping-server -d -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
new file mode 100644
index 000000000..034437dbc
--- /dev/null
+++ b/tests/2-nodes-vpp-memif.yml
@@ -0,0 +1,116 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_VPP_MEMIF}-client
+ networks: []
+ volumes:
+ - /tmp/memif:/memif
+ - ..:/workspace
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ buffers { buffers-per-numa 600000 }
+ plugins {
+ path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log /var/log/vpp/vpp.log
+ }
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ comment { Creating memif }
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 mode ip master
+ set int state memif1/0 up
+ comment { Configuring memif }
+ set int ip addr memif1/0 192.168.1.1/24
+ set int ip addr memif1/0 2001::1/64
+ comment { Add route }
+ ip route add b002::1/64 via 2001::2 memif1/0
+ EOF
+
+ sudo rm /memif/memif1.sock
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo vppctl hicn enable b002::1/64
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_VPP_MEMIF}-server
+ networks: []
+ volumes:
+ - /tmp/memif:/memif
+ - ..:/workspace
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ buffers { buffers-per-numa 600000 }
+
+ plugins {
+ path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log /var/log/vpp/vpp.log
+ }
+ EOF
+
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ comment { Creating memif }
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 mode ip slave
+ set int state memif1/0 up
+ comment { Configuring memif }
+ set int ip addr memif1/0 192.168.1.2/24
+ set int ip addr memif1/0 2001::2/64
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 10
+
+ sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128
+ sleep 5
+ sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128
+ sleep 5
+ sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module
+
+ tail -f /dev/null
diff --git a/tests/2-nodes.yml b/tests/2-nodes.yml
new file mode 100644
index 000000000..ce87e5876
--- /dev/null
+++ b/tests/2-nodes.yml
@@ -0,0 +1,43 @@
+version: "3"
+services:
+ client:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ BASE_IMAGE: ${BASE_IMAGE}
+ privileged: true
+ stdin_open: true
+ hostname: client
+ tty: true
+ working_dir: /workspace
+ networks:
+ - kernel
+ volumes:
+ - ..:/workspace
+ entrypoint: [/bin/bash, -x, -c]
+ command:
+ - tail -f /dev/null
+
+ server:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ BASE_IMAGE: ${BASE_IMAGE}
+ privileged: true
+ stdin_open: true
+ hostname: server
+ tty: true
+ working_dir: /workspace
+ networks:
+ - kernel
+ volumes:
+ - ..:/workspace
+ entrypoint: [/bin/bash, -x, -c]
+ command:
+ - tail -f /dev/null
+
+networks:
+ kernel:
+ driver: bridge
diff --git a/tests/Dockerfile.ci b/tests/Dockerfile.ci
new file mode 100644
index 000000000..29f2e9dac
--- /dev/null
+++ b/tests/Dockerfile.ci
@@ -0,0 +1,5 @@
+ARG BASE_IMAGE
+
+FROM ${BASE_IMAGE}
+
+RUN sudo sed -i 's,secure_path="\(.*\)",secure_path="/hicn-root/bin:\1",' /etc/sudoers
diff --git a/tests/channel.sh b/tests/channel.sh
new file mode 100755
index 000000000..28a187e72
--- /dev/null
+++ b/tests/channel.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+set -e
+
+DEV=$2
+RATE=$3mbit
+DELAY=$4ms
+JITTER=$5ms
+LOSS=$6
+
+if [[ $1 -eq "set" ]]; then
+ tc qdisc add dev "$DEV" root handle 1:0 htb default 1
+ tc class add dev "$DEV" parent 1:0 classid 1:1 htb rate "$RATE"
+ tc qdisc add dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY"
+ "$JITTER" loss random "$LOSS"
+ echo "Dev: $DEV, rate: $RATE, delay: $DELAY, jitter: $JITTER, loss: $LOSS%"
+elif [[ $1 -eq "change" ]]; then
+ tc qdisc change dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" "$JITTER" loss random "$LOSS"
+ echo "Dev: $DEV, rate: $RATE, delay: $DELAY, jitter: $JITTER, loss: $LOSS%"
+else
+ echo "set or change"
+fi
diff --git a/tests/config.sh b/tests/config.sh
new file mode 100755
index 000000000..bcd27e0b9
--- /dev/null
+++ b/tests/config.sh
@@ -0,0 +1,290 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+SCRIPT_PATH=$(
+ cd "$(dirname "${BASH_SOURCE}")"
+ pwd -P
+)
+
+# Import test configurations and names
+source ${SCRIPT_PATH}/.env
+
+set -a
+DOCKERFILE=${DOCKERFILE:-Dockerfile.dev}
+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_MEMIF_RTC="${HIPERF_CMD_RTC} -z memif_module"
+POSTPROCESS_COMMAND_RAAQM_RTC='tail -n +3 | \
+ tr -s " " | \
+ cut -f 4 -d " " | \
+ sort -n | \
+ tail -n 40 | \
+ head -n 35 | \
+ awk "BEGIN { \
+ c=0; \
+ s=0; \
+ }{ \
+ a[n++]=\$1; \
+ s+=\$1; \
+ } END { \
+ 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_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"
+
+PING_CMD="hicn-ping-client -m 50 -i 200000 -n ${PING_PRODUCER}"
+PING_CMD_MEMIF="${PING_CMD} -z memif_module"
+POSTPROCESS_COMMAND_PING='grep trip | \
+ cut -f 4 -d " " | \
+ sort -n | \
+ tail -n 40 | \
+ head -n 35 | \
+ awk "BEGIN { \
+ c=0; \
+ s=0; \
+ }{ \
+ a[n++]=\$1; \
+ s+=\$1; \
+ } END { \
+ print int(a[0]), int(a[n-1]), int(s/n) \
+ }"'
+
+declare -a topologies
+declare -a configurations
+
+# Fill topology array using the same values in the .env file
+for topology in $(compgen -A variable | grep TOPOLOGY_); do
+ topologies+=("${!topology}")
+done
+
+# Fill configurations array using the same values in the .env file
+for test in $(compgen -A variable | grep TEST_); do
+ configurations+=("${!test}")
+done
+
+declare -A tests=(
+ ["hicn-light-rtc"]="${HIPERF_CMD_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-bridge-rtc"]="${HIPERF_CMD_MEMIF_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-rtc"]="${HIPERF_CMD_MEMIF_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-replication-rtc"]="${HIPERF_CMD_MEMIF_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+
+ ["hicn-light-requin"]="${HIPERF_CMD_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-bridge-requin"]="${HIPERF_CMD_MEMIF_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-requin"]="${HIPERF_CMD_MEMIF_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-replication-requin"]="${HIPERF_CMD_MEMIF_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+
+ ["hicn-light-cbr"]="${HIPERF_CMD_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-bridge-cbr"]="${HIPERF_CMD_MEMIF_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-cbr"]="${HIPERF_CMD_MEMIF_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-replication-cbr"]="${HIPERF_CMD_MEMIF_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+
+ ["hicn-light-latency"]="${PING_CMD} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["vpp-bridge-latency"]="${PING_CMD_MEMIF} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["vpp-memif-latency"]="${PING_CMD_MEMIF} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["vpp-memif-replication-latency"]="${PING_CMD_MEMIF} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+)
+
+declare -A link_model=(
+ ["500-0-0-0"]="500 0 0 0"
+ ["500-1-0-0"]="500 1 0 0"
+ ["500-5-0-0"]="500 5 0 0"
+ ["500-200-0-0"]="500 200 0 0"
+ ["100-1-0-0"]="100 1 0 0"
+ ["100-10-0-0"]="100 10 0 0"
+ ["100-15-0-0"]="100 15 0 0"
+ ["200-5-0-0"]="200 5 0 0"
+ ["300-5-0-0"]="300 5 0 0"
+ ["400-5-0-0"]="400 5 0 0"
+ ["1000-1-0-0"]="1000 1 0 0"
+ ["10-50-1-10"]="10 50 1 10"
+)
+
+function topology_exists() {
+ [[ "${topologies[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function test_exists() {
+ [[ "${!tests[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function conf_exists() {
+ [[ "${configurations[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+
+# test-name client/server link-model
+function setchannel() {
+ if ! conf_exists "${1}"; then
+ error "Error: topology does not exist."
+ fi
+
+ if ! test_exists "${1}"; then
+ error "Error: test does not exist."
+ fi
+ docker exec "${1}-${2}" bash -c "/workspace/tests/config.sh link set br0\
+ ${link_model[${3}]}"
+}
+# test-name client/server link-model
+function changechannel() {
+ if ! conf_exists "${1}"; then
+ error "Error: topology does not exist."
+ fi
+
+ if ! test_exists "${1}"; then
+ error "Error: test does not exist."
+ fi
+ docker exec "${1}-${2}" bash -c "/workspace/tests/config.sh link change br0\
+ ${link_model[${3}]}"
+}
+
+# channel set/change dev rate delay jitter lossrate
+function channel() {
+ DEV=${2}
+ RATE=${3}mbit
+ DELAY=${4}ms
+ JITTER=${5}ms
+ LOSS=${6}
+ if [[ $1 == set ]]; then
+ sudo tc qdisc add dev "${DEV}" root handle 1:0 htb default 1
+ sudo tc class add dev "${DEV}" parent 1:0 classid 1:1 htb rate "$RATE"
+ sudo tc qdisc add dev "${DEV}" parent 1:1 handle 2:0 netem delay "${DELAY}" \
+ "${JITTER}" loss random "${LOSS}"
+ echo "Dev: ${DEV}, rate: ${RATE}, delay: ${DELAY}, jitter: ${JITTER}, loss: ${LOSS}%"
+ elif [[ ${1} == change ]]; then
+ sudo tc qdisc change dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" \
+ "${JITTER}" loss random "${LOSS}"
+ echo "Dev: ${DEV}, rate: ${RATE}, delay: ${DELAY}, jitter: ${JITTER}, loss: ${LOSS}%"
+ else
+ sudo tc qdisc del dev "${DEV}" root
+ echo "set or change"
+ fi
+}
+function error() {
+ echo >&2 "${@}"
+ return 1
+}
+
+function build() {
+ docker-compose -f build.yml build
+ docker-compose -f build.yml up --force-recreate --remove-orphans >/dev/null
+}
+
+function setup() {
+ topology=${1}
+ conf=${2}
+
+ if ! topology_exists "${topology}"; then
+ error "Error: topology does not exist."
+ fi
+
+ if ! conf_exists "${conf}"; then
+ error "Error: topology does not exist."
+ fi
+
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml build
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml up --remove-orphans --force-recreate -d
+
+ sleep 10
+}
+
+function start() {
+ conf=${1}
+ test=${2}
+
+ if ! conf_exists "${conf}"; then
+ error "Error: configuration does not exist."
+ fi
+
+ TESTNAME="${conf}-${test}"
+
+ if ! test_exists "${TESTNAME}"; then
+ error "Error: test does not exist."
+ fi
+
+ docker exec "${1}"-client bash -c "/workspace/tests/config.sh runtest ${tests[${TESTNAME}]}"
+}
+
+function stop() {
+ topology="${1}"
+ conf="${2}"
+
+ if ! topology_exists "${topology}"; then
+ error "Error: topology does not exist."
+ fi
+
+ if ! conf_exists "${conf}"; then
+ error "Error: tect configuration does not exist."
+ fi
+
+ LOG_FILE="${SCRIPT_PATH}/${topology}-${conf}.log"
+ rm -f "${LOG_FILE}"
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml down || true
+}
+
+function stopall() {
+ for topology in "${topologies[@]}"; do
+ for conf in "${configurations[@]}"; do
+ stop "${topology}" "${conf}"
+ done
+ done
+}
+
+function runtest() {
+ echo "${@}" | sudo -i
+}
+
+while (("${#}")); do
+ case "$1" in
+ 'build')
+ build
+ shift
+ ;;
+ 'link')
+ shift
+ channel "$@"
+ shift 6
+ ;;
+ 'setchannel')
+ shift
+ setchannel "$@"
+ shift 4
+ ;;
+ 'changechannel')
+ shift
+ changechannel "$@"
+ shift 4
+ ;;
+ 'setup')
+ setup "${2}" "${3}"
+ shift 3
+ ;;
+ 'start')
+ start "${2}" "${3}"
+ shift 3
+ ;;
+ 'stop')
+ stop "${2}" "${3}"
+ shift 3
+ ;;
+ 'stopall')
+ stopall
+ shift
+ ;;
+ 'runtest')
+ runtest "${@:2}"
+ break
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+exit 0
diff --git a/tests/forwarder.robot b/tests/forwarder.robot
new file mode 100644
index 000000000..60345dbb0
--- /dev/null
+++ b/tests/forwarder.robot
@@ -0,0 +1,45 @@
+*** 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/functional-tests/2-nodes-hicn-light.robot b/tests/functional-tests/2-nodes-hicn-light.robot
new file mode 100644
index 000000000..9aa5923a0
--- /dev/null
+++ b/tests/functional-tests/2-nodes-hicn-light.robot
@@ -0,0 +1,24 @@
+*** Settings ***
+Resource resources/libraries/robot/runtest.robot
+Resource resources/libraries/robot/common.robot
+Suite Setup Run Keywords
+... Build Topology 2-nodes hicn-light AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+Resource resources/libraries/robot/runtest.robot
+
+*** Test Cases ***
+
+Throughput Testing Raaqm Mobile
+ Run Throughput Test Raaqm hicn-light 200 500 400
+
+Throughput Testing CBR Mobile
+ Run Throughput Test CBR hicn-light 200 500 400
+
+RTC Testing Mobile
+ Run RTC Test hicn-light 4 4 4
+
+Latency Testing Mobile
+ Set Link hicn-light 500 1 0 0
+ Run Latency Test hicn-light 3000 3000 3000
diff --git a/tests/functional-tests/2-nodes-vpp-bridge.robot b/tests/functional-tests/2-nodes-vpp-bridge.robot
new file mode 100644
index 000000000..83c8818ab
--- /dev/null
+++ b/tests/functional-tests/2-nodes-vpp-bridge.robot
@@ -0,0 +1,24 @@
+*** Settings ***
+Resource resources/libraries/robot/runtest.robot
+Resource resources/libraries/robot/common.robot
+Suite Setup Run Keywords
+... Build Topology 2-nodes vpp-bridge AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+Resource resources/libraries/robot/runtest.robot
+
+*** Test Cases ***
+
+Throughput Testing Raaqm Server VPP bridge
+ Run Throughput Test Raaqm vpp-bridge 500 500 500
+
+Throughput Testing CBR Server VPP bridge
+ Run Throughput Test CBR vpp-bridge 1000 1300 1200
+
+RTC Testing Server VPP bridge
+ Run RTC Test vpp-bridge 4 4 4
+
+Latency Testing Server VPP bridge
+ Set Link hicn-light 500 1 0 0
+ Run Latency Test vpp-bridge 3000 3000 3000
diff --git a/tests/functional-tests/2-nodes-vpp-memif-replication.robot b/tests/functional-tests/2-nodes-vpp-memif-replication.robot
new file mode 100644
index 000000000..8c13f4fb9
--- /dev/null
+++ b/tests/functional-tests/2-nodes-vpp-memif-replication.robot
@@ -0,0 +1,23 @@
+*** Settings ***
+Resource resources/libraries/robot/runtest.robot
+Resource resources/libraries/robot/common.robot
+Suite Setup Run Keywords
+... Build Topology 2-nodes vpp-memif-replication AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+Resource resources/libraries/robot/runtest.robot
+
+*** Test Cases ***
+
+Throughput Testing Raaqm Server VPP memif replication
+ Run Throughput Test Raaqm vpp-memif-replication 500 500 500
+
+Throughput Testing CBR Server VPP memif
+ Run Throughput Test CBR vpp-memif-replication 2000 2000 2000
+
+RTC Testing Server VPP memif replication
+ Run RTC Test vpp-memif-replication 4 4 4
+
+Latency Testing Server VPP memif replication
+ Run Latency Test vpp-memif-replication 3000 3000 3000
diff --git a/tests/functional-tests/2-nodes-vpp-memif.robot b/tests/functional-tests/2-nodes-vpp-memif.robot
new file mode 100644
index 000000000..1a69da787
--- /dev/null
+++ b/tests/functional-tests/2-nodes-vpp-memif.robot
@@ -0,0 +1,23 @@
+*** Settings ***
+Resource resources/libraries/robot/runtest.robot
+Resource resources/libraries/robot/common.robot
+Suite Setup Run Keywords
+... Build Topology 2-nodes vpp-memif AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+Resource resources/libraries/robot/runtest.robot
+
+*** Test Cases ***
+
+Throughput Testing Raaqm Server VPP memif
+ Run Throughput Test Raaqm vpp-memif 500 500 500
+
+Throughput Testing CBR Server VPP memif
+ Run Throughput Test CBR vpp-memif 2000 2000 2000
+
+RTC Testing Server VPP memif
+ Run RTC Test vpp-memif 4 4 4
+
+Latency Testing Server VPP memif
+ Run Latency Test vpp-memif 3000 3000 3000
diff --git a/tests/resources/libraries/robot/common.robot b/tests/resources/libraries/robot/common.robot
new file mode 100644
index 000000000..c1e3f20a4
--- /dev/null
+++ b/tests/resources/libraries/robot/common.robot
@@ -0,0 +1,23 @@
+*** Settings ***
+Library OperatingSystem
+Library Process
+Library String
+
+*** Variables ***
+
+*** Keywords ***
+
+Build Topology
+ [Arguments] ${TEST_TOPOLOGY}=${NONE} ${TEST_CONFIGURATION}=${NONE}
+ Log to console Building topology ${TEST_TOPOLOGY} ${TEST_CONFIGURATION}
+ ${result_setup} = Run Process ${EXECDIR}/config.sh build setup ${TEST_TOPOLOGY} ${TEST_CONFIGURATION}
+ Log to console Done
+ Log Many stdout: ${result_setup.stdout} stderr: ${result_setup.stderr}
+
+Check Environment
+ ${result} = Run Process docker ps
+ Log Many stdout: ${result.stdout} stderr: ${result.stderr}
+
+Destroy Topology
+ ${result_teardown} = Run Process ${EXECDIR}/config.sh stopall
+ Log Many stdout: ${result_teardown.stdout} stderr: ${result_teardown.stderr}
diff --git a/tests/resources/libraries/robot/runtest.robot b/tests/resources/libraries/robot/runtest.robot
new file mode 100644
index 000000000..d5201d765
--- /dev/null
+++ b/tests/resources/libraries/robot/runtest.robot
@@ -0,0 +1,92 @@
+*** Settings ***
+Library OperatingSystem
+Library Process
+Library String
+
+*** Variables ***
+
+*** Keywords ***
+
+Infra ${VALUE}
+ Run Process ${EXECDIR}/config.sh ${VALUE}
+
+Run Test
+ [Arguments] ${TEST_SETUP}=${NONE} ${TESTID}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE}
+ ${result_test} = Run Process ${EXECDIR}/config.sh start ${TEST_SETUP} ${TESTID} stdout=${TEMPDIR}/stdout.txt stderr=${TEMPDIR}/stderr.txt
+ Log Many stdout: ${result_test.stdout} stderr: ${result_test.stderr}
+ @{min_max_avg} = Split String ${result_test.stdout.strip()}
+ Log To Console Min Max Average Array: @{min_max_avg}
+ IF '${TESTID}' == 'rtc'
+ Should Be True ${min_max_avg}[0] == ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] != ${EXPECTED_MIN})"
+ Should Be True ${min_max_avg}[1] == ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] != ${EXPECTED_MAX})"
+ Should Be True ${min_max_avg}[2] == ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] != ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'requin'
+ Should Be True ${min_max_avg}[0] >= ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})"
+ Should Be True ${min_max_avg}[1] >= ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})"
+ Should Be True ${min_max_avg}[2] >= ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'latency'
+ Should Be True ${min_max_avg}[0] <= ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] > ${EXPECTED_MIN})"
+ Should Be True ${min_max_avg}[1] <= ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] > ${EXPECTED_MAX})"
+ Should Be True ${min_max_avg}[2] <= ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] > ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'cbr'
+ Should Be True ${min_max_avg}[0] >= ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})"
+ Should Be True ${min_max_avg}[1] >= ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})"
+ Should Be True ${min_max_avg}[2] >= ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})"
+ ELSE
+ Fail "Provided Test ID does not exist"
+ END
+
+Set Link
+ [Documentation] Configure link rate/delay/jitter/loss
+ ... Arguments:
+ ... ${RATE} Rate of the link
+ ... ${DELAY} Delay of the link
+ ... ${JITTER} Jitter of the link
+ ... ${LOSS} Loss of the link
+ [Arguments] ${TEST_SETUP}=${NONE}
+ ... ${RATE}=${NONE}
+ ... ${DELAY}=${NONE}
+ ... ${JITTER}=${NONE}
+ ... ${LOSS}=${NONE}
+ ${result_link} = Run Process ${EXECDIR}/config.sh setchannel ${TEST_SETUP} server ${RATE}-${DELAY}-${JITTER}-${LOSS}
+ Log Many stdout: ${result_link.stdout} stderr: ${result_link.stderr}
+
+Run Latency Test
+ [Documentation] Run hicn-ping on the ${TEST_SETUP} topology and measure latency.
+ ... Arguments:
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min latency
+ ... ${EXPECTED_MAX} The expected max latency
+ ... ${EXPECTED_AVG} The expected avg latency
+ [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE}
+ Run Test ${TEST_SETUP} latency ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG}
+
+Run Throughput Test Raaqm
+ [Documentation] Run hiperf on the ${TEST_SETUP} topology and measure throughput.
+ ... Arguments:
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min throughput
+ ... ${EXPECTED_MAX} The expected max throughput
+ ... ${EXPECTED_AVG} The expected avg throughput
+ [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE}
+ Run Test ${TEST_SETUP} requin ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG}
+
+Run Throughput Test CBR
+ [Documentation] Run hiperf on the ${TEST_SETUP} topology and measure throughput.
+ ... Arguments:
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min throughput
+ ... ${EXPECTED_MAX} The expected max throughput
+ ... ${EXPECTED_AVG} The expected avg throughput
+ [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE}
+ Run Test ${TEST_SETUP} cbr ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG}
+
+Run RTC Test
+ [Documentation] Run hiperf RTC on the ${TEST_SETUP} topology and check consumer syncs to producer bitrate.
+ ... Arguments:
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min bitrate
+ ... ${EXPECTED_MAX} The expected max bitrate
+ ... ${EXPECTED_AVG} The expected avg bitrate
+ [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE}
+ Run Test ${TEST_SETUP} rtc ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG}
diff --git a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt b/tests/run-functional.sh
index a86826f09..b8dfbc437 100644
--- a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
+++ b/tests/run-functional.sh
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -11,20 +11,30 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-list(APPEND DAEMON_SRC
- hicnLightDaemon_main.c
+SCRIPT_PATH=$(
+ cd "$(dirname "${BASH_SOURCE}")"
+ pwd -P
)
-if (WIN32)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"")
-endif()
-
-if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android")
- build_executable(${HICN_LIGHT_DAEMON}
- SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC}
- DEPENDS ${LIBHICN_LIGHT_STATIC}
- COMPONENT ${HICN_LIGHT}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- )
-endif ()
+pushd "${SCRIPT_PATH}" || exit 1
+
+declare -a REPORTS
+
+for t in functional-tests/*; do
+ [[ -e "$t" ]] || break # handle the case of no test files
+
+ test=$(basename "$t")
+
+ robot --NoStatusRC \
+ --outputdir report_"${test}" \
+ -P ${PWD} functional-tests/"${test}"
+
+ REPORTS+=(report_"${test}"/output.xml)
+done
+
+rebot --output output.xml \
+ -l log.html -r report.html \
+ --nostatusrc \
+ "${REPORTS[@]}"
+
+popd || exit 1
diff --git a/tests/test_forwarder.sh b/tests/test_forwarder.sh
new file mode 100644
index 000000000..aba85d8d8
--- /dev/null
+++ b/tests/test_forwarder.sh
@@ -0,0 +1,437 @@
+#!/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
new file mode 100644
index 000000000..3bce94504
--- /dev/null
+++ b/versions.cmake
@@ -0,0 +1,8 @@
+set(OPENSSL_DEFAULT_VERSION "1.1.1" "EXACT")
+set(LIBEVENT_DEFAULT_VERSION "2.1.11")
+set(ASIO_DEFAULT_VERSION "1.12.2")
+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(ANDORID_SDK_DEP_DEFAULT_VERSION "2.1.1" "EXACT")