aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar@cisco.com>2022-03-30 22:29:28 +0200
committerMauro Sardara <msardara@cisco.com>2022-03-31 19:51:47 +0200
commitc46e5df56b67bb8ea7a068d39324c640084ead2b (patch)
treeeddeb17785938e09bc42eec98ee09b8a28846de6
parent18fa668f25d3cc5463417ce7df6637e31578e898 (diff)
feat: boostrap hicn 22.02
The current patch provides several new features, improvements, bug fixes and also complete rewrite of entire components. - lib The hicn packet parser has been improved with a new packet format fully based on UDP. The TCP header is still temporarily supported but the UDP header will replace completely the new hicn packet format. Improvements have been made to make sure every packet parsing operation is made via this library. The current new header can be used as header between the payload and the UDP header or as trailer in the UDP surplus area to be tested when UDP options will start to be used. - hicn-light The portable packet forwarder has been completely rewritten from scratch with the twofold objective to improve performance and code size but also to drop dependencies such as libparc which is now removed by the current implementation. - hicn control the control library is the agent that is used to program the packet forwarders via their binary API. This component has benefited from significant improvements in terms of interaction model which is now event driven and more robust to failures. - VPP plugin has been updated to support VPP 22.02 - transport Major improvement have been made to the RTC protocol, to the support of IO modules and to the security sub system. Signed manifests are the default data authenticity and integrity framework. Confidentiality can be enabled by sharing the encryption key to the prod/cons layer. The library has been tested with group key based applications such as broadcast/multicast and real-time on-line meetings with trusted server keys or MLS. - testing Unit testing has been introduced using GoogleTest. One third of the code base is covered by unit testing with priority on critical features. Functional testing has also been introduce using Docker, linux bridging and Robot Framework to define test with Less Code techniques to facilitate the extension of the coverage. Co-authored-by: Mauro Sardara <msardara@cisco.com> Co-authored-by: Jordan Augé <jordan.auge+fdio@cisco.com> Co-authored-by: Michele Papalini <micpapal@cisco.com> Co-authored-by: Angelo Mantellini <manangel@cisco.com> Co-authored-by: Jacques Samain <jsamain@cisco.com> Co-authored-by: Olivier Roques <oroques+fdio@cisco.com> Co-authored-by: Enrico Loparco <eloparco@cisco.com> Co-authored-by: Giulio Grassi <gigrassi@cisco.com> Change-Id: I75d0ef70f86d921e3ef503c99271216ff583c215 Signed-off-by: Luca Muscariello <muscariello@ieee.org> Signed-off-by: Mauro Sardara <msardara@cisco.com>
-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")