summaryrefslogtreecommitdiffstats
path: root/hicn-light
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light')
-rw-r--r--hicn-light/.clang-format (renamed from hicn-light/src/hicn/command_line/daemon/CMakeLists.txt)21
-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/controlAdd.h32
-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/controlAddPunting.h22
-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/controlCache.h22
-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/controlRemovePolicy.h36
-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.c (renamed from hicn-light/src/hicn/config/controlAddPolicy.h)31
-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.h (renamed from hicn-light/src/hicn/config/controlUpdateConnection.h)30
-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.h37
-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/commands.h434
-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
357 files changed, 24894 insertions, 33032 deletions
diff --git a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt b/hicn-light/.clang-format
index a86826f09..2dc5c0c54 100644
--- a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
+++ 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,20 +11,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-list(APPEND DAEMON_SRC
- hicnLightDaemon_main.c
-)
-
-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 ()
+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/controlAdd.h b/hicn-light/src/hicn/config/controlAdd.h
deleted file mode 100644
index 7c160b5f7..000000000
--- a/hicn-light/src/hicn/config/controlAdd.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 control_Add.h
- * @brief Command-line "add" node
- *
- * Implements the "add" node of the CLI tree
- *
- *
- */
-
-#ifndef control_Add_h
-#define control_Add_h
-
-#include <hicn/config/controlState.h>
-
-CommandOps *webControlAdd_Create(ControlState *state);
-CommandOps *controlAdd_CreateHelp(ControlState *state);
-#endif // control_Add_h
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/controlAddPunting.h b/hicn-light/src/hicn/config/controlAddPunting.h
deleted file mode 100644
index 9cab76359..000000000
--- a/hicn-light/src/hicn/config/controlAddPunting.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 controlAddPunting_h
-#define controlAddPunting_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlAddPunting_Create(ControlState *state);
-CommandOps *controlAddPunting_HelpCreate(ControlState *state);
-#endif
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/controlCache.h b/hicn-light/src/hicn/config/controlCache.h
deleted file mode 100644
index c2f2402f1..000000000
--- a/hicn-light/src/hicn/config/controlCache.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 controlCache_h
-#define controlCache_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlCache_Create(ControlState *state);
-CommandOps *controlCache_HelpCreate(ControlState *state);
-#endif // controlCache_h
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/controlRemovePolicy.h b/hicn-light/src/hicn/config/controlRemovePolicy.h
deleted file mode 100644
index ebe098985..000000000
--- a/hicn-light/src/hicn/config/controlRemovePolicy.h
+++ /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.
- */
-
-/**
- * @file control_RemovePolicy.h
- * @brief Remove a policy from the FIB
- *
- * Implements the "remove policy" and "help remove policy" nodes of the command
- * tree
- *
- */
-
-#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);
-
-#endif /* WITH_POLICY */
-
-#endif // Control_RemovePolicy_h
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/config/controlAddPolicy.h b/hicn-light/src/hicn/core/listener_vft.c
index 273e3a476..600c9482f 100644
--- a/hicn-light/src/hicn/config/controlAddPolicy.h
+++ b/hicn-light/src/hicn/core/listener_vft.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,22 +14,23 @@
*/
/**
- * @file control_AddPolicy.h
- * @brief Add a static policy
- *
- * Implements the "add policy" node of the CLI tree
- *
+ * @file listener_vft.c
+ * @brief Implementation of listener VFT
*/
-#ifndef Control_AddPolicy_h
-#define Control_AddPolicy_h
-
-#ifdef WITH_POLICY
+#include "listener_vft.h"
-#include <hicn/config/controlState.h>
-CommandOps *controlAddPolicy_Create(ControlState *state);
-CommandOps *controlAddPolicy_HelpCreate(ControlState *state);
+#ifdef __linux__
+extern listener_ops_t listener_hicn;
+#endif
+extern listener_ops_t listener_tcp;
+extern listener_ops_t listener_udp;
-#endif /* WITH_POLICY */
+const listener_ops_t* listener_vft[] = {
+#ifdef __linux__
+ [FACE_PROTOCOL_HICN] = &listener_hicn,
+#endif
-#endif // Control_AddPolicy_h
+ [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/config/controlUpdateConnection.h b/hicn-light/src/hicn/io/base.h
index eea303202..3463c6760 100644
--- a/hicn-light/src/hicn/config/controlUpdateConnection.h
+++ b/hicn-light/src/hicn/io/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:
@@ -14,22 +14,24 @@
*/
/**
- * @file control_UpdateConnection.h
- * @brief Update a connection to an interface
- *
- * <#Detailed Description#>
- *
+ * @file base.h
+ * #brief Base IO functions.
*/
-#ifndef Control_UpdateConnection_h
-#define Control_UpdateConnection_h
+#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
-#ifdef WITH_POLICY
+ssize_t io_read_single_fd(int fd, msgbuf_t* msgbuf, address_t* address);
-#include <hicn/config/controlState.h>
-CommandOps *controlUpdateConnection_Create(ControlState *state);
-CommandOps *controlUpdateConnection_HelpCreate(ControlState *state);
+ssize_t io_read_single_socket(int fd, msgbuf_t* msgbuf, address_t* address);
-#endif /* WITH_POLICY */
+ssize_t io_read_batch_socket(int fd, msgbuf_t** msgbuf, address_t** address,
+ size_t n);
-#endif // Control_UpdateConnection_h
+#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/strategies/replication.h b/hicn-light/src/hicn/strategies/replication.h
new file mode 100644
index 000000000..753ae4744
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/replication.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.
+ */
+
+/**
+ * Forward replication of the interest on all the paths
+ */
+
+#ifndef HICNLIGHT_STRATEGY_REPLICATION_H
+#define HICNLIGHT_STRATEGY_REPLICATION_H
+
+#include "local_prefixes.h"
+
+typedef struct {
+ void *_;
+} strategy_replication_nexthop_state_t;
+
+typedef struct {
+ void *prev_nexthops;
+} strategy_replication_state_t;
+
+typedef struct {
+ local_prefixes_t *local_prefixes;
+} strategy_replication_options_t;
+
+#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/commands.h b/hicn-light/src/hicn/utils/commands.h
deleted file mode 100644
index 3758f0f41..000000000
--- a/hicn-light/src/hicn/utils/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/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