aboutsummaryrefslogtreecommitdiffstats
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.txt137
-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.txt119
-rw-r--r--hicn-light/src/hicn/base/CMakeLists.txt (renamed from hicn-light/src/hicn/messenger/CMakeLists.txt)21
-rw-r--r--hicn-light/src/hicn/base/loop.c205
-rw-r--r--hicn-light/src/hicn/base/loop.h141
-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.c237
-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.txt114
-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/commands.c1737
-rw-r--r--hicn-light/src/hicn/config/commands.h165
-rw-r--r--hicn-light/src/hicn/config/configuration.c1564
-rw-r--r--hicn-light/src/hicn/config/configuration.h122
-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.c135
-rw-r--r--hicn-light/src/hicn/config/configuration_file.h57
-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/controlRemovePunting.h27
-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/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.txt76
-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.c43
-rw-r--r--hicn-light/src/hicn/core/address_pair.h66
-rw-r--r--hicn-light/src/hicn/core/connection.c573
-rw-r--r--hicn-light/src/hicn/core/connection.h328
-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.c240
-rw-r--r--hicn-light/src/hicn/core/connection_table.h257
-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.c88
-rw-r--r--hicn-light/src/hicn/core/content_store.h108
-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.c743
-rw-r--r--hicn-light/src/hicn/core/fib.h86
-rw-r--r--hicn-light/src/hicn/core/fib_entry.c667
-rw-r--r--hicn-light/src/hicn/core/fib_entry.h208
-rw-r--r--hicn-light/src/hicn/core/forwarder.c1837
-rw-r--r--hicn-light/src/hicn/core/forwarder.h337
-rw-r--r--hicn-light/src/hicn/core/listener.c425
-rw-r--r--hicn-light/src/hicn/core/listener.h140
-rw-r--r--hicn-light/src/hicn/core/listener_table.c206
-rw-r--r--hicn-light/src/hicn/core/listener_table.h270
-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.c1647
-rw-r--r--hicn-light/src/hicn/core/mapme.h107
-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.h758
-rw-r--r--hicn-light/src/hicn/core/messagePacketType.h32
-rw-r--r--hicn-light/src/hicn/core/msgbuf.c55
-rw-r--r--hicn-light/src/hicn/core/msgbuf.h205
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.c123
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.h157
-rw-r--r--hicn-light/src/hicn/core/name.c264
-rw-r--r--hicn-light/src/hicn/core/name.h104
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.c364
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.h58
-rw-r--r--hicn-light/src/hicn/core/nexthops.c155
-rw-r--r--hicn-light/src/hicn/core/nexthops.h182
-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.c884
-rw-r--r--hicn-light/src/hicn/core/packet_cache.h502
-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.c202
-rw-r--r--hicn-light/src/hicn/core/policy_stats.h92
-rw-r--r--hicn-light/src/hicn/core/strategy.c60
-rw-r--r--hicn-light/src/hicn/core/strategy.h81
-rw-r--r--hicn-light/src/hicn/core/strategy_vft.c39
-rw-r--r--hicn-light/src/hicn/core/strategy_vft.h124
-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.c118
-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.txt44
-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.c131
-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.c448
-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.c532
-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.c565
-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.c81
-rw-r--r--hicn-light/src/hicn/socket/api.h9
-rw-r--r--hicn-light/src/hicn/socket/ops.h18
-rw-r--r--hicn-light/src/hicn/socket/ops_linux.c131
-rw-r--r--hicn-light/src/hicn/strategies/CMakeLists.txt27
-rw-r--r--hicn-light/src/hicn/strategies/best_path.c353
-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.c148
-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.c82
-rw-r--r--hicn-light/src/hicn/strategies/local_prefixes.h46
-rw-r--r--hicn-light/src/hicn/strategies/local_remote.c105
-rw-r--r--hicn-light/src/hicn/strategies/local_remote.h40
-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/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.c113
-rw-r--r--hicn-light/src/hicn/strategies/probe_generator.h49
-rw-r--r--hicn-light/src/hicn/strategies/random.c77
-rw-r--r--hicn-light/src/hicn/strategies/random.h (renamed from hicn-light/src/hicn/strategies/loadBalancer.h)22
-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.txt40
-rw-r--r--hicn-light/src/hicn/test/main.cc (renamed from hicn-light/src/hicn/strategies/rnd.h)18
-rw-r--r--hicn-light/src/hicn/test/test-configuration.cc83
-rw-r--r--hicn-light/src/hicn/test/test-connection_table.cc301
-rw-r--r--hicn-light/src/hicn/test/test-ctrl.cc197
-rw-r--r--hicn-light/src/hicn/test/test-fib.cc338
-rw-r--r--hicn-light/src/hicn/test/test-listener_table.cc244
-rw-r--r--hicn-light/src/hicn/test/test-local_prefixes.cc252
-rw-r--r--hicn-light/src/hicn/test/test-loop.cc294
-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.cc703
-rw-r--r--hicn-light/src/hicn/test/test-parser.cc71
-rw-r--r--hicn-light/src/hicn/test/test-probe_generator.cc154
-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-local-remote.cc233
-rw-r--r--hicn-light/src/hicn/test/test-strategy-random.cc150
-rw-r--r--hicn-light/src/hicn/test/test-strategy-replication.cc162
-rw-r--r--hicn-light/src/hicn/test/test-subscription.cc204
-rw-r--r--hicn-light/src/hicn/test/test-utils.h26
-rw-r--r--hicn-light/src/hicn/test/test_hash.cc216
-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
333 files changed, 22264 insertions, 34127 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..e82100a91 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,104 @@
# 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)
+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)
+
+
+##############################################################
+# 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 ()
-
-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..97b3e0dbf 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), libevent-2.1-7 (= 2.1.11-stable-1)"
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..feaac5c39 100644
--- a/hicn-light/src/hicn/CMakeLists.txt
+++ b/hicn-light/src/hicn/CMakeLists.txt
@@ -1,55 +1,130 @@
-# 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
+ PRIVATE ${DEFAULT_COMPILER_OPTIONS}
+ #PRIVATE "-Wno-address-of-packed-member"
)
+##############################################################
+# 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 +132,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..2541ed830 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,18 @@
# 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}/loop.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
)
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/loop.c b/hicn-light/src/hicn/base/loop.c
new file mode 100644
index 000000000..3407bfc1c
--- /dev/null
+++ b/hicn-light/src/hicn/base/loop.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+ unsigned id;
+ 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->id,
+ 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, unsigned id,
+ void *callback_data) {
+ *event = malloc(sizeof(event_t));
+ (*event)->callback = (cb_wrapper_args_t){
+ .owner = callback_owner,
+ .callback = callback,
+ .id = id,
+ .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,
+ unsigned id, void *callback_data) {
+ _event_create(event, loop, EVTYPE_FD, callback_owner, callback, id,
+ 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, 0,
+ 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..0eecb60fe
--- /dev/null
+++ b/hicn-light/src/hicn/base/loop.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 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, unsigned id, void *data);
+
+typedef struct {
+ int fd;
+ void *owner;
+ fd_callback_t callback;
+ unsigned id;
+ 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] id - User parameter to pass alongside callback invocation,
+ * allowing to pass an id without allocating memory.
+ * \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,
+ unsigned id, 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/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..ed8d4ed97
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicnc.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <hicn/ctrl/parse.h>
+#include <hicn/ctrl/hicn-light.h>
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.h>
+
+#define PORT 9695
+
+/*
+ * Duplicated from hicn_light_ng_api.c while is only available as a module in
+ * libhicnctrl
+ */
+const char *command_type_str[] = {
+#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u),
+ foreach_command_type
+#undef _
+};
+
+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, "dhS:P:", longFormOptions, &optind);
+ if (c == -1) break;
+
+ switch (c) {
+ case 'd':
+ log_conf.log_level = LOG_DEBUG;
+ break;
+ 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_TYPE_HICNLIGHT, url);
+ } else {
+ s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL);
+ }
+ if (!s) {
+ fprintf(stderr, "Could not create socket.\n");
+ goto ERR_SOCKET;
+ }
+
+ 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;
+
+ rc = hc_execute(s, command.action, command.object_type, &command.object,
+ &data);
+
+ if (rc < 0) {
+ switch (rc) {
+ case INPUT_ERROR:
+ ERROR("Wrong input parameters");
+ break;
+ case UNSUPPORTED_CMD_ERROR:
+ ERROR("Unsupported command");
+ break;
+ default:
+ ERROR("Error executing command");
+ break;
+ }
+ goto ERR_COMMAND;
+ }
+
+ if (!data) goto ERR_QUERY;
+ if (!hc_data_get_result(data)) goto ERR_DATA;
+
+ if (command.action == ACTION_LIST) {
+ char buf[MAXSZ_HC_OBJECT];
+ hc_data_foreach(data, obj, {
+ rc = hc_object_snprintf(buf, MAXSZ_HC_OBJECT, command.object_type, obj);
+ if (rc < 0)
+ WARN("Display error");
+ else if (rc >= MAXSZ_HC_OBJECT)
+ WARN("Output truncated");
+ else
+ printf("%s\n", buf);
+ });
+ }
+
+ hc_data_free(data);
+ hc_sock_free(s);
+ return EXIT_SUCCESS;
+
+ERR_DATA:
+ hc_data_free(data);
+ERR_QUERY:
+ERR_COMMAND:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCKET:
+ERR_PARSE:
+ERR_PARAM:
+ ERROR("Error");
+ return 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..fa1b1c024
--- /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 <hicn/base/loop.h>
+
+#include "logo.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..c03fa8599
--- /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 <hicn/ctrl/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 (line != NULL && (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_TYPE_HICNLIGHT, url);
+ } else {
+ s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL);
+ }
+ 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..8e9415f7d 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-2023 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.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,35 @@
# 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}/commands.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}/../../../../ctrl/libhicnctrl/src/module_object.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/connection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/face.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/mapme.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/route.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/stats.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/strategy.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/subscription.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_cache.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_connection.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_face.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_listener.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_mapme.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_policy.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_punting.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_route.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_stats.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_strategy.c
+ #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_subscription.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/commands.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
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/commands.c b/hicn-light/src/hicn/config/commands.c
new file mode 100644
index 000000000..47ea23a8a
--- /dev/null
+++ b/hicn-light/src/hicn/config/commands.c
@@ -0,0 +1,1737 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.h>
+//#include <hicn/utils/utils.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) \
+ do { \
+ ((msg_header_t *)msg)->header.message_type = ACK_LIGHT; \
+ ((msg_header_t *)msg)->header.length = 0; \
+ } while (0)
+
+#define make_nack(msg) \
+ do { \
+ ((msg_header_t *)msg)->header.message_type = NACK_LIGHT; \
+ ((msg_header_t *)msg)->header.length = 0; \
+ } while (0)
+
+#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 = (unsigned int)connection_table_get_id_by_name(table,
+ symbolic_or_connid);
+ if (connection_id_is_valid(conn_id)) {
+ DEBUG("Resolved symbolic name '%s' to conn_id %u", symbolic_or_connid,
+ conn_id);
+ } 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;
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_HICN:
+ ERROR("Wrong listener type");
+ 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;
+ memset(&address, 0, sizeof(address_t));
+ 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 = (unsigned int)listener_table_get_id_by_name(
+ table, symbolic_or_listener_id);
+ if (listener_id_is_valid(listener_id)) {
+ DEBUG("Resolved symbolic name '%s' to conn_id %u",
+ symbolic_or_listener_id, listener_id);
+ } 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 =
+ (unsigned)connection_table_get_connection_id(table, connection);
+
+ /* Remove connection from the FIB */
+ // XXX TODO get entries, raise notifications...
+ // XXX isn't it possible to implement this in the forwarder ?????
+ 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(const listener_t *listener,
+ cmd_listener_list_item_t *cmd) {
+ 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 = (uint8_t)AF_INET;
+ cmd->local_addr.v4.as_inaddr = sin->sin_addr;
+ cmd->local_port = sin->sin_port;
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)addr;
+ cmd->family = (uint8_t)AF_INET6;
+ cmd->local_addr.v6.as_in6addr = sin6->sin6_addr;
+ cmd->local_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;
+ INFO("listener list seq num %d", msg_received->header.seq_num);
+ uint32_t seq_num = msg_received->header.seq_num;
+
+ msg_listener_list_reply_t *msg = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_listener_list_item_t *payload = &msg->payload;
+ listener_table_foreach(table, listener, {
+ fill_listener_command(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;
+ case FACE_TYPE_UDP_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_UNDEFINED:
+ case FACE_TYPE_N:
+ goto NACK;
+ }
+
+ if (!face_type_is_defined(control->type)) goto NACK;
+
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ char *symbolic_name = control->symbolic;
+
+ // Generate connection name if not specified
+ if (symbolic_name[0] == '\0') {
+ int rc = connection_table_get_random_name(table, symbolic_name);
+ if (rc < 0) {
+ ERROR("Unable to generate new connection name");
+ goto NACK;
+ }
+ } else {
+ if (connection_table_get_by_name(table, symbolic_name)) {
+ ERROR("Connection symbolic name already exists");
+ goto NACK;
+ }
+ }
+
+ address_pair_t pair;
+ if (address_pair_from_ip_port(&pair, control->family, &control->local_ip,
+ control->local_port, &control->remote_ip,
+ control->remote_port) < 0)
+ goto NACK;
+
+ if (forwarder_add_connection(forwarder, symbolic_name, control->type, &pair,
+ control->tags, control->priority,
+ control->admin_state) < 0)
+ goto NACK;
+
+ 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;
+ }
+
+ /*
+ *
+ * Don't close the fd for SELF otherwise it won't be possible
+ * to send the reply back. The connection is finalized later in
+ * _forwarder_finalize_connection_if_self
+ */
+ bool finalize = (strcmp(control->symbolic_or_connid, "SELF") != 0);
+
+ if (forwarder_remove_connection(forwarder, conn_id, finalize) < 0) goto NACK;
+
+ WITH_DEBUG({
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_table_print_by_pair(table);
+ })
+
+ 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(const connection_t *connection,
+ cmd_connection_list_item_t *cmd) {
+ 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 = (uint8_t)connection_get_state(connection),
+ cmd->admin_state = (uint8_t)connection_get_admin_state(connection),
+ cmd->type = (uint8_t)connection_get_type(connection),
+#ifdef WITH_POLICY
+ cmd->priority = connection_get_priority(connection),
+ cmd->tags = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_connection_list_item_t *payload = &msg->payload;
+ connection_table_foreach_new(table, connection, {
+ if (connection->id == ingress_id) continue;
+ fill_connections_command(connection, payload);
+ payload++;
+ });
+
+ *reply_size = sizeof(msg->header) + n * sizeof(msg->payload);
+ return (uint8_t *)msg;
+
+NACK:
+ *reply_size = sizeof(msg_header_t);
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+#if 0
+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);
+
+ /* Hook: connection event */
+ forwarder_on_connection_event(forwarder, conn,
+ control->admin_state == FACE_STATE_UP
+ ? CONNECTION_EVENT_SET_UP
+ : CONNECTION_EVENT_SET_DOWN);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+#endif
+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;
+}
+
+#if 0
+
+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);
+
+ /* Hook: connection event */
+ forwarder_on_connection_event(forwarder, conn,
+ CONNECTION_EVENT_PRIORITY_CHANGED);
+
+ 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);
+
+ /* Hook: connection event */
+ forwarder_on_connection_event(forwarder, conn, CONNECTION_EVENT_TAGS_CHANGED);
+
+ make_ack(msg);
+ return (uint8_t *)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+#endif
+
+/* 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);
+
+ /* We accept routes without conn_id */
+#if 0
+ if (!connection_id_is_valid(conn_id)) goto NACK;
+#endif
+
+ hicn_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;
+
+ hicn_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;
+}
+
+static inline off_t fill_route_command(const fib_entry_t *entry,
+ cmd_route_list_item_t *cmd) {
+ 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);
+ off_t pos = 0;
+
+ if (num_nexthops == 0) return 0;
+
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(entry);
+ const hicn_ip_address_t *address = hicn_prefix_get_ip_address(prefix);
+ int family = hicn_ip_address_get_family(address);
+
+ nexthops_foreach(nexthops, nexthop, {
+ cmd->family = family;
+ cmd->remote_addr = *address;
+ cmd->face_id = nexthop;
+ cmd->len = hicn_prefix_get_len(prefix);
+ cmd->cost = DEFAULT_COST;
+
+ pos++;
+ cmd++;
+ });
+ return pos;
+}
+
+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);
+
+ /*
+ * 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 = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_route_list_item_t *payload = &msg->payload;
+ off_t pos = 0;
+ fib_foreach_entry(fib, entry,
+ { pos += fill_route_command(entry, payload + pos); });
+
+ *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 = (unsigned int)forwarder_cs_get_size(forwarder),
+ .num_stale_entries =
+ (unsigned int)forwarder_cs_get_num_stale_entries(forwarder)}};
+
+ *reply_size = sizeof(*msg);
+ return (uint8_t *)msg;
+}
+
+/* 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];
+ hicn_ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len,
+ };
+ int rc = hicn_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;
+
+ // XXX check control->family
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&control->address, control->len,
+ &name_prefix);
+
+ // 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 buf[MAXSZ_HICN_PREFIX];
+ hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, &name_prefix);
+ WARN("Strategy for prefix %s not updated", buf);
+ })
+ }
+
+ 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];
+ hicn_ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len,
+ };
+ int rc = hicn_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;
+
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&control->address, control->len,
+ &name_prefix);
+
+ strategy_options_t options;
+ hicn_prefix_t local_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&control->address, control->len,
+ &local_prefix);
+
+ // 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;
+}
+
+/* Statistics */
+
+uint8_t *configuration_on_stats_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder && packet);
+ INFO("CMD: stats list (ingress=%d)", ingress_id);
+
+ size_t n = 1;
+ msg_stats_list_t *msg_received = (msg_stats_list_t *)packet;
+ uint8_t command_id = msg_received->header.command_id;
+ uint32_t seq_num = msg_received->header.seq_num;
+
+ msg_stats_list_reply_t *msg = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_stats_list_item_t *payload = &msg->payload;
+ payload->stats.forwarder = forwarder_get_stats(forwarder);
+ payload->stats.pkt_cache =
+ pkt_cache_get_stats(forwarder_get_pkt_cache(forwarder));
+
+ *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_face_stats_list(forwarder_t *forwarder,
+ uint8_t *packet, unsigned ingress_id,
+ size_t *reply_size) {
+ assert(forwarder && packet);
+ INFO("CMD: face stats list (ingress=%d)", ingress_id);
+
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ // -1 since current connection (i.e. the one used to send
+ // the command) is not considered
+ size_t n = connection_table_len(table) - 1;
+ msg_face_stats_list_t *msg_received = (msg_face_stats_list_t *)packet;
+ uint8_t command_id = msg_received->header.command_id;
+ uint32_t seq_num = msg_received->header.seq_num;
+
+ msg_face_stats_list_reply_t *msg = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_face_stats_list_item_t *payload = &msg->payload;
+ connection_t *connection;
+ connection_table_foreach(table, connection, {
+ if (connection->id == ingress_id) continue;
+ payload->stats = connection->stats;
+ payload++;
+ });
+
+ *reply_size = sizeof(msg->header) + n * sizeof(msg->payload);
+ return (uint8_t *)msg;
+
+NACK:
+ *reply_size = sizeof(msg_header_t);
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+/* WLDR */
+
+uint8_t *configuration_on_wldr_set(forwarder_t *forwarder, uint8_t *packet,
+ 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 (hicn_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;
+ }
+
+ hicn_ip_prefix_t prefix = {.family = control->family,
+ .address = control->address,
+ .len = control->len};
+ char prefix_s[MAXSZ_IP_PREFIX];
+ int rc = hicn_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_add(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder);
+ assert(packet);
+
+ /* Check ingress is local (for now this is only used locally) */
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ const connection_t *connection = connection_table_at(table, ingress_id);
+
+ msg_mapme_add_t *msg = (msg_mapme_add_t *)packet;
+
+ if (!connection_is_local(connection)) goto NACK;
+
+ *reply_size = sizeof(msg_header_t);
+
+ fib_t *fib = forwarder_get_fib(forwarder);
+ if (!fib) goto NACK;
+
+ mapme_t *mapme = forwarder_get_mapme(forwarder);
+
+ cmd_mapme_add_t *control = &msg->payload;
+ /* If the message comes from the producer, address, family, len and
+ * face_id will be NULL
+ */
+ if (hicn_ip_address_empty(&control->address) && (control->len == 0) &&
+ (control->family == 0) && (control->face_id == 0)) {
+ /*
+ * The command triggers a mapme update for all prefixes produced on this
+ * face
+ *
+ * XXX This should in fact be an UPDATE command
+ */
+
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ nexthops_foreach(nexthops, nexthop, {
+ if (nexthop != ingress_id) continue;
+ /* This entry points to the producer face */
+ mapme_set_all_adjacencies(mapme, entry);
+ break;
+ });
+ });
+
+ goto END;
+ }
+
+ /* Control plane triggered
+ *
+ * We might not only receive MAP-Me update requests for prefixes we own,
+ * but also for more specific ones (for instance, we have a /64 and
+ * want to send an update on a /128). This requires a FIB lookup.
+ *
+ * NOTE: we need to avoid modifying the FIB because of this.
+ *
+ * TODO:
+ * - assert face_id is valid and exists
+ * - assert family is correct
+ */
+
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&control->address, control->len,
+ &name_prefix);
+
+#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+ fib_entry_t *entry = fib_contains(fib, &name_prefix);
+ if (!entry) {
+ entry = mapme_create_fib_entry(mapme, &name_prefix, INVALID_FACE_ID);
+ if (!entry) goto NACK; // we could also perform as in the other branch
+ }
+ mapme_set_adjacency(mapme, entry, control->face_id, NULL);
+
+#else
+ fib_entry_t *entry = fib_match_prefix(fib, &name_prefix);
+
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(entry);
+ if (hicn_prefix_get_len(prefix) == control->len) {
+ mapme_set_adjacency(mapme, entry, control->face_id, NULL);
+ } else {
+ mapme_set_adjacency(mapme, NULL, control->face_id, prefix);
+ }
+#endif
+
+END:
+ 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;
+
+ hicn_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;
+
+ hicn_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;
+}
+
+static inline void fill_policy_command(const fib_entry_t *entry,
+ cmd_policy_list_item_t *cmd) {
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(entry);
+ const hicn_ip_address_t *ip_address = hicn_prefix_get_ip_address(prefix);
+ cmd->remote_addr = *ip_address;
+ cmd->family = hicn_ip_address_get_family(ip_address);
+ cmd->len = hicn_prefix_get_len(prefix);
+
+ hicn_policy_t policy = fib_entry_get_policy(entry);
+ _hicn_policy_t _policy = {
+ .stats = {
+ .wired = {.throughput = htonf(policy.stats.wired.throughput),
+ .latency = htonf(policy.stats.wired.latency),
+ .loss_rate = htonf(policy.stats.wired.loss_rate)},
+ .wifi = {.throughput = htonf(policy.stats.wifi.throughput),
+ .latency = htonf(policy.stats.wifi.latency),
+ .loss_rate = htonf(policy.stats.wifi.loss_rate)},
+ .cellular = {.throughput = htonf(policy.stats.cellular.throughput),
+ .latency = htonf(policy.stats.cellular.latency),
+ .loss_rate = htonf(policy.stats.cellular.loss_rate)},
+ .all = {.throughput = htonf(policy.stats.all.throughput),
+ .latency = htonf(policy.stats.all.latency),
+ .loss_rate = htonf(policy.stats.all.loss_rate)}}};
+ for (unsigned i = 0; i < POLICY_TAG_N; i++) {
+ _policy.tags[i] = (_policy_tag_state_t){
+ .state = policy.tags[i].state,
+ .disabled = policy.tags[i].disabled,
+ };
+ }
+ memcpy(_policy.app_name, policy.app_name, APP_NAME_LEN);
+ memcpy(cmd->policy, &_policy, sizeof(_policy));
+}
+
+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 = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_policy_list_item_t *payload = &msg->payload;
+
+ fib_foreach_entry(fib, entry, {
+ fill_policy_command(entry, payload);
+ 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 *configuration_on_active_interface_update(forwarder_t *forwarder,
+ uint8_t *packet,
+ unsigned ingress_id,
+ size_t *reply_size) {
+ msg_active_interface_update_t *msg = (msg_active_interface_update_t *)packet;
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet,
+ 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.
+ */
+ command_type_t command_type = ((msg_header_t *)packet)->header.command_id;
+ 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;
+
+ reply = command_process(forwarder, packet, 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);
+ }
+
+ /* Free allocated replies */
+ if (reply != packet) free(reply);
+ return msgbuf_get_len(msgbuf);
+}
+
+void commands_notify(const forwarder_t *forwarder, hc_topic_t topic,
+ uint8_t *msg, size_t size) {
+ // Retrieve subscribed connections
+ subscription_table_t *subscriptions = forwarder_get_subscriptions(forwarder);
+ unsigned *subscribed_conn_ids =
+ subscription_table_get_connections_for_topic(subscriptions, topic);
+
+ // Send notification to subscribed connections
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
+ for (int i = 0; i < vector_len(subscribed_conn_ids); i++) {
+ const connection_t *conn =
+ connection_table_at(table, subscribed_conn_ids[i]);
+ connection_send_packet(conn, msg, size);
+ }
+}
+
+void commands_notify_connection(const forwarder_t *forwarder,
+ connection_event_t event,
+ const connection_t *connection) {
+#if 0
+ uint8_t command_id;
+ switch (event) {
+ case CONNECTION_EVENT_CREATE:
+ command_id = COMMAND_TYPE_CONNECTION_ADD;
+ break;
+ case CONNECTION_EVENT_DELETE:
+ command_id = COMMAND_TYPE_CONNECTION_REMOVE;
+ break;
+ case CONNECTION_EVENT_UPDATE:
+ case CONNECTION_EVENT_SET_UP:
+ case CONNECTION_EVENT_SET_DOWN:
+ case CONNECTION_EVENT_PRIORITY_CHANGED:
+ case CONNECTION_EVENT_TAGS_CHANGED:
+ command_id = COMMAND_TYPE_CONNECTION_UPDATE;
+ break;
+ case CONNECTION_EVENT_UNDEFINED:
+ case CONNECTION_EVENT_N:
+ default:
+ return;
+ }
+#endif
+
+ msg_connection_notify_t msg = {.header = {
+ .message_type = NOTIFICATION_LIGHT,
+ .command_id = OBJECT_TYPE_CONNECTION,
+ .length = 1,
+ .seq_num = 0,
+ }};
+ fill_connections_command(connection, &msg.payload);
+
+ commands_notify(forwarder, TOPIC_CONNECTION, (uint8_t *)&msg, sizeof(msg));
+}
+
+void commands_notify_route(const forwarder_t *forwarder,
+ const fib_entry_t *entry) {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ size_t n = nexthops_get_len(nexthops);
+ msg_route_notify_t *msg = NULL;
+ msg_malloc_list(msg, OBJECT_TYPE_ROUTE, n, 0);
+ if (!msg) return;
+
+ fill_route_command(entry, &msg->payload);
+
+ commands_notify(forwarder, TOPIC_ROUTE, (uint8_t *)&msg, sizeof(msg));
+ free(msg);
+}
+
+void commands_notify_active_interface_update(const forwarder_t *forwarder,
+ hicn_ip_prefix_t *prefix,
+ netdevice_flags_t flags) {
+ struct {
+ cmd_header_t header;
+ hc_active_interface_t payload;
+ } msg = {.header =
+ {
+ .message_type = NOTIFICATION_LIGHT,
+ .command_id = OBJECT_TYPE_ACTIVE_INTERFACE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload = {.prefix = *prefix, .interface_types = flags}};
+
+ INFO("Notify active interface");
+ commands_notify(forwarder, TOPIC_ACTIVE_INTERFACE, (uint8_t *)&msg,
+ sizeof(msg));
+}
diff --git a/hicn-light/src/hicn/config/commands.h b/hicn-light/src/hicn/config/commands.h
new file mode 100644
index 000000000..f212c1b0b
--- /dev/null
+++ b/hicn-light/src/hicn/config/commands.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.h>
+
+uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet,
+ 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);
+
+uint8_t *configuration_on_stats_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
+void commands_notify_connection(const forwarder_t *forwarder,
+ connection_event_t event,
+ const connection_t *connection);
+
+void commands_notify_route(const forwarder_t *forwarder,
+ const fib_entry_t *entry);
+
+void commands_notify_active_interface_update(const forwarder_t *forwarder,
+ hicn_ip_prefix_t *prefix,
+ netdevice_flags_t flags);
+
+#endif // HICNLIGHT_COMMANDS_H
diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c
index e414f05e3..b7e931e53 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,202 @@
#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.h>
+//#include <hicn/utils/utils.h>
+#include <hicn/utils/punting.h>
+#include <hicn/util/log.h>
+#include <hicn/face.h>
+#include <hicn/util/slab.h>
+#include <hicn/util/sstrncpy.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);
+
+typedef struct {
+ char prefix[MAXSZ_HICN_PREFIX];
+} prefix_key_t;
+
+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;
+ slab_t *prefix_keys;
+
+ size_t n_suffixes_per_split;
+ int_manifest_split_strategy_t split_strategy;
};
-// ========================================================================================
-
-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);
+configuration_t *configuration_create() {
+ configuration_t *config = malloc(sizeof(configuration_t));
+ if (!config) return NULL;
- 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 */
-
- 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));
- }
+ 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();
+ config->prefix_keys = slab_create(prefix_key_t, SLAB_INIT_SIZE);
+ config->n_suffixes_per_split = DEFAULT_N_SUFFIXES_PER_SPLIT;
+ config->split_strategy = DEFAULT_DISAGGREGATION_STRATEGY;
- return response;
+ return config;
}
-struct iovec *configuration_ProcessCacheClear(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
+void configuration_free(configuration_t *config) {
+ assert(config);
- forwarder_ClearCache(config->forwarder);
+ kh_destroy_strategy_map(config->strategy_map);
+ slab_free(config->prefix_keys);
- struct iovec *response = utils_CreateAck(header, NULL, 0);
- return response;
+ free(config);
}
-size_t configuration_GetObjectStoreSize(Configuration *config) {
- return config->maximumContentObjectStoreSize;
+size_t configuration_get_cs_size(const configuration_t *config) {
+ return config->cs_capacity;
}
-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);
+void configuration_set_cs_size(configuration_t *config, size_t size) {
+ config->cs_capacity = size;
}
-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;
-
- const char *symbolicOrConnid = control->symbolicOrConnid;
-
- 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
- }
- }
-
- // 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;
+const char *configuration_get_fn_config(const configuration_t *config) {
+ return config->fn_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;
- }
+void configuration_set_fn_config(configuration_t *config,
+ const char *fn_config) {
+ config->fn_config = fn_config;
}
-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_suffixes_per_split(configuration_t *config,
+ size_t n_suffixes_per_split) {
+ config->n_suffixes_per_split = n_suffixes_per_split;
}
-void configuration_SetObjectStoreSize(Configuration *config,
- size_t maximumObjectCount) {
- config->maximumContentObjectStoreSize = maximumObjectCount;
-
- forwarder_SetContentObjectStoreSize(config->forwarder,
- config->maximumContentObjectStoreSize);
+size_t configuration_get_suffixes_per_split(const configuration_t *config) {
+ return config->n_suffixes_per_split;
}
-Forwarder *configuration_GetForwarder(const Configuration *config) {
- return config->forwarder;
+void configuration_set_split_strategy(
+ configuration_t *config, int_manifest_split_strategy_t split_strategy) {
+ config->split_strategy = split_strategy;
}
-Logger *configuration_GetLogger(const Configuration *config) {
- return config->logger;
+int_manifest_split_strategy_t configuration_get_split_strategy(
+ const configuration_t *config) {
+ return config->split_strategy;
}
-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));
+void configuration_set_port(configuration_t *config, uint16_t port) {
+ config->port = 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));
+uint16_t configuration_get_port(const configuration_t *config) {
+ return config->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));
+void configuration_set_configuration_port(configuration_t *config,
+ uint16_t configuration_port) {
+ config->configuration_port = configuration_port;
}
-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;
+void configuration_set_strategy(configuration_t *config, const char *prefix,
+ strategy_type_t strategy_type) {
+ int res;
+ prefix_key_t *prefix_copy = slab_get(prefix_key_t, config->prefix_keys);
+ strcpy_s(prefix_copy->prefix, sizeof(prefix_key_t), prefix);
- 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));
+ khiter_t k =
+ kh_put_strategy_map(config->strategy_map, prefix_copy->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..0d1a2b8e7 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,19 @@
*
*/
-#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 <hicn/util/khash.h>
+#include "../core/msgbuf.h"
+#include "../core/strategy.h"
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/hicn-light.h>
+#include <hicn/interest_manifest.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 +51,7 @@ typedef struct forwarder Forwarder;
* <#example#>
* @endcode
*/
-Configuration *configuration_Create(Forwarder *forwarder);
+configuration_t *configuration_create();
/**
* <#One Line Description#>
@@ -65,13 +67,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 +83,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 +97,54 @@ 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_suffixes_per_split(configuration_t *config,
+ size_t n_suffixes_per_split);
+
+size_t configuration_get_suffixes_per_split(const configuration_t *config);
+
+void configuration_set_split_strategy(
+ configuration_t *config,
+ int_manifest_split_strategy_t n_suffixes_per_split);
+
+int_manifest_split_strategy_t configuration_get_split_strategy(
+ const configuration_t *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..8649e0143
--- /dev/null
+++ b/hicn-light/src/hicn/config/configuration_file.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <hicn/ctrl/hicn-light.h>
+#include <hicn/config/configuration_file.h>
+#include <hicn/util/sstrncpy.h>
+
+#include "commands.h"
+#include <hicn/ctrl/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;
+
+#if 0
+ // TODO(eloparco): We could use a fake socket since we only need the vft
+ hc_sock_t *s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL);
+ if (!s) {
+ ERROR("Could not create socket");
+ goto ERR_SOCK;
+ }
+#else
+ hc_sock_initialize_module(NULL);
+#endif
+
+ 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;
+ }
+
+ /* Serialize request into message */
+ // hc_msg_t msg;
+ uint8_t msg[1024];
+ ssize_t msg_len = hc_light_command_serialize(
+ command.action, command.object_type, &command.object, msg);
+ switch (msg_len) {
+ case -1:
+ case -2:
+ ERROR("Command '%s' not supported", cmd);
+ continue;
+ case -3:
+ ERROR("Error during command serialization '%s'", cmd);
+ continue;
+ default:
+ break;
+ }
+
+ size_t _unused;
+ command_process(forwarder, (uint8_t *)msg, CONNECTION_ID_UNDEFINED,
+ &_unused);
+ }
+
+#if 0
+ hc_sock_free(s);
+#endif
+
+ 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;
+
+#if 0
+ERR_SOCK:
+ hc_sock_free(s);
+#endif
+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..03599d4f4
--- /dev/null
+++ b/hicn-light/src/hicn/config/configuration_file.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.
+ */
+
+/**
+ * @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>
+#include <hicn/ctrl/hicn-light.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/controlRemovePunting.h b/hicn-light/src/hicn/config/controlRemovePunting.h
deleted file mode 100644
index 858d6f969..000000000
--- a/hicn-light/src/hicn/config/controlRemovePunting.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_RemovePunting.h
- *
- */
-
-#ifndef Control_RemovePunting_h
-#define Control_RemovePunting_h
-
-#include <hicn/config/controlState.h>
-CommandOps *controlRemovePunting_Create(ControlState *state);
-CommandOps *controlRemovePunting_HelpCreate(ControlState *state);
-#endif // Control_RemovePunting_h
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/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..94295bdf1 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -1,9 +1,9 @@
-# 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:
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -12,49 +12,59 @@
# 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}/name.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.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}/msgbuf.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.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
- ${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.c
- ${CMAKE_CURRENT_SOURCE_DIR}/name.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..65664fa17
--- /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,
+ hicn_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..38cd1e87c
--- /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,
+ hicn_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..c4f8b397b
--- /dev/null
+++ b/hicn-light/src/hicn/core/address_pair.c
@@ -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.
+ */
+
+/**
+ * \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,
+ hicn_ip_address_t* local_addr,
+ uint16_t local_port,
+ hicn_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..b2872ad35
--- /dev/null
+++ b/hicn-light/src/hicn/core/address_pair.h
@@ -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_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,
+ hicn_ip_address_t* local_addr,
+ uint16_t local_port,
+ hicn_ip_address_t* remote_addr,
+ uint16_t remote_port);
+
+static inline int address_pair_equals(const address_pair_t* pair1,
+ const address_pair_t* pair2) {
+ return address_equals(&pair1->local, &pair2->local) &&
+ address_equals(&pair1->remote, &pair2->remote);
+}
+
+#define address_pair_get_local(pair) (&(pair)->local)
+#define address_pair_get_remote(pair) (&(pair)->remote)
+
+#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..a9d632d52 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-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -13,347 +13,358 @@
* 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/core/forwarder.h>
+#include <hicn/core/listener.h>
+#include <hicn/core/wldr.h>
#include <hicn/policy.h>
-#endif /* WITH_POLICY */
+#include <hicn/util/log.h>
+
+#include "connection.h"
+#include "connection_vft.h"
+
+// This is called by configuration
+connection_t *connection_create(face_type_t type, const char *name,
+ const address_pair_t *pair,
+ const forwarder_t *forwarder) {
+ assert(face_type_is_valid(type));
+ assert(pair);
+ assert(forwarder);
+
+ /* initialized so that gcc-9 does not complain */
+ face_type_t listener_type = FACE_TYPE_UNDEFINED;
+ switch (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:
+ return NULL; /* Not implemented */
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UNDEFINED:
+ case FACE_TYPE_N:
+ return NULL;
+ }
-struct connection {
+ listener_table_t *ltable = forwarder_get_listener_table(forwarder);
+ listener_key_t key = listener_key_factory(pair->local, listener_type);
- const AddressPair *addressPair;
- IoOperations *ops;
+ 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 refCount;
+ return NULL;
+ }
- unsigned counter;
+ 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);
+}
- 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;
+netdevice_type_t connection_get_netdevice_type(const char *interface_name) {
+ if (strncmp(interface_name, "lo", 2) == 0) {
+ return NETDEVICE_TYPE_LOOPBACK;
+ }
+ if ((strncmp(interface_name, "eth", 3) == 0) ||
+ (strncmp(interface_name, "en", 2) == 0)) {
+ /* eth* en* enx* */
+ return NETDEVICE_TYPE_WIRED;
+ }
+ if (strncmp(interface_name, "wl", 2) == 0) {
+ /* wlan* wlp* wlx* */
+ return NETDEVICE_TYPE_WIFI;
+ }
+ if (strncmp(interface_name, "rmnet_ipa", 9) == 0) {
+ /* Qualcomm IPA driver */
+ return NETDEVICE_TYPE_UNDEFINED;
+ }
+ if ((strncmp(interface_name, "rmnet", 5) == 0) ||
+ (strncmp(interface_name, "rev_rmnet", 9) == 0) ||
+ (strncmp(interface_name, "ccmni", 5) == 0)) {
+ /*
+ * rmnet* (Qualcomm) ccmni* (MediaTek)
+ */
+ return NETDEVICE_TYPE_CELLULAR;
+ }
+ /* usb0 might be cellular (eg Zenfone2) */
+ /* what about tethering */
+ /* tun* dummy* ... */
+ /* bnet* pan* hci* for bluetooth */
+ return NETDEVICE_TYPE_UNDEFINED;
+}
+/**
+ * @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 */
-};
-
-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;
+ .listener = listener,
+ .closed = false,
- conn->wldrAutoStart = true;
- conn->counter = 0;
+ /* WLDR */
+ .wldr = NULL,
+ .wldr_autostart = true,
+ };
+ connection->stats.conn_id = connection_id;
- /* By default, a connection will aim at the UP state */
- connection_SetAdminState(conn, CONNECTION_STATE_UP);
+ connection->interface_type =
+ connection_get_netdevice_type(connection->interface_name);
#ifdef WITH_POLICY
- conn->tags = POLICY_TAGS_EMPTY;
-#endif /* WITH_POLICY */
+ connection_clear_tags(connection);
+ switch (connection->interface_type) {
+#if 0
+ case NETDEVICE_TYPE_LOOPBACK:
+ connection_add_tag(connection, POLICY_TAG_LOOPBACK);
+ break;
+#endif
+ case NETDEVICE_TYPE_WIRED:
+ connection_add_tag(connection, POLICY_TAG_WIRED);
+ break;
+ case NETDEVICE_TYPE_WIFI:
+ connection_add_tag(connection, POLICY_TAG_WIFI);
+ break;
+ case NETDEVICE_TYPE_CELLULAR:
+ connection_add_tag(connection, POLICY_TAG_CELLULAR);
+ default:
+ break;
+ }
+#endif
- return conn;
-}
+ connection->data =
+ malloc(connection_vft[get_protocol(connection->type)]->data_size);
+ if (!connection->data) goto ERR_DATA;
-Connection *connection_Acquire(Connection *connection) {
- parcAssertNotNull(connection, "Parameter conn must be non-null");
- connection->refCount++;
- return connection;
-}
+ assert(connection_has_valid_id(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, connection->id,
+ 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;
-}
+bool 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(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(connection_t *connection) {
+ return connection_vft[get_protocol(connection->type)]->flush(connection);
}
-bool connection_WldrAutoStartAllowed(const Connection *conn) {
- return conn->wldrAutoStart;
-}
+bool connection_send(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 0
+ if (connection->wldr)
+ wldr_set_label(connection->wldr, msgbuf);
+ else
+ msgbuf_reset_wldr_label(msgbuf);
+#endif
-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(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..e177e2039 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-2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.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,184 +15,230 @@
/**
* @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
-#ifdef WITH_MAPME
-typedef enum {
- CONNECTION_EVENT_CREATE,
- CONNECTION_EVENT_DELETE,
- CONNECTION_EVENT_UPDATE,
- CONNECTION_EVENT_SET_UP,
- CONNECTION_EVENT_SET_DOWN,
- CONNECTION_EVENT_PRIORITY_CHANGED,
- CONNECTION_EVENT_TAGS_CHANGED,
-} connection_event_t;
+#include <hicn/face.h>
-#endif /* WITH_MAPME */
+#include "address_pair.h"
+#include "listener.h"
+#include "msgbuf.h"
#ifdef WITH_POLICY
#include <hicn/policy.h>
#endif /* WITH_POLICY */
-struct connection;
-typedef struct connection Connection;
+#define CONNECTION_ID_UNDEFINED INVALID_FACE_ID
-/**
- * Creates a connection object.
- */
-Connection *connection_Create(IoOperations *ops);
+#define foreach_connection_event \
+ _(UNDEFINED) \
+ _(CREATE) \
+ _(DELETE) \
+ _(UPDATE) \
+ _(SET_UP) \
+ _(SET_DOWN) \
+ _(PRIORITY_CHANGED) \
+ _(TAGS_CHANGED) \
+ _(N)
-/**
- * @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);
+typedef enum {
+#define _(x) CONNECTION_EVENT_##x,
+ foreach_connection_event
+#undef _
+} connection_event_t;
-/**
- * @function connection_Acquire
- * @abstract A reference counted copy.
- * @discussion
- * A shallow copy, they share the same memory.
- */
-Connection *connection_Acquire(Connection *connection);
+struct wldr_s;
+
+typedef struct {
+ unsigned id;
+ char* name;
+ char* interface_name;
+ netdevice_type_t interface_type;
+ face_type_t type;
+ address_pair_t pair;
+ // bool up;
+ bool local;
+ face_state_t state;
+ face_state_t admin_state;
+#ifdef WITH_POLICY
+ policy_tags_t tags;
+ uint32_t priority;
+#endif /* WITH_POLICY */
-/**
- * @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);
+ 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_stats_t stats;
+} 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)
+#define connection_get_interface_type(C) ((C)->interface_type)
-/**
- * @function connection_SendIOVBuffer
- * @abstract Sends an IOV buffer
- */
-bool connection_SendIOVBuffer(const Connection *conn, struct iovec *msg,
- size_t size);
+#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(C), 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_SendBuffer
- * @abstract Sends a buffer
- */
-bool connection_SendBuffer(const Connection *conn, u8 * buffer, size_t length);
+#endif /* WITH_POLICY */
-/**
- * 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);
+#else
-/**
- * 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);
+/* Accessors */
+static inline unsigned connection_get_id(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_id_is_valid(id) (id != CONNECTION_ID_UNDEFINED)
+#define connection_has_valid_id(C) (connection_id_is_valid(connection_get_id(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 char* connection_get_name(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 face_type_t connection_get_type(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 address_pair_t* connection_get_pair(
+ const connection_t* connection);
-bool connection_ReSend(const Connection *conn, Message *message,
- bool notification);
+#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)))
-void connection_Probe(Connection *conn, uint8_t *probe);
+static inline bool connection_is_up(const connection_t* connection);
-void connection_HandleProbe(Connection *conn, uint8_t *message);
+static inline bool connection_is_local(const connection_t* connection);
-void connection_AllowWldrAutoStart(Connection *conn, bool allow);
+static inline face_state_t connection_get_state(const connection_t* connection);
-void connection_EnableWldr(Connection *conn);
+static inline void connection_set_state(connection_t* connection,
+ face_state_t state);
-void connection_DisableWldr(Connection *conn);
+static inline face_state_t connection_get_admin_state(
+ const connection_t* connection);
-bool connection_HasWldr(const Connection *conn);
+static inline void connection_set_admin_state(connection_t* connection,
+ face_state_t state);
-bool connection_WldrAutoStartAllowed(const Connection *conn);
+static inline const char* connection_get_interface_name(
+ const connection_t* connection);
-void connection_DetectLosses(Connection *conn, Message *message);
+#ifdef WITH_POLICY
-void connection_HandleWldrNotification(Connection *conn, Message *message);
+static inline uint32_t connection_get_priority(const connection_t* connection);
-connection_state_t connection_GetState(const Connection *conn);
+static inline void connection_set_priority(connection_t* connection,
+ uint32_t priority);
-void connection_SetState(Connection *conn, connection_state_t state);
+static inline policy_tags_t connection_get_tags(const connection_t* connection);
-connection_state_t connection_GetAdminState(const Connection *conn);
+static inline void connection_set_tags(connection_t* connection,
+ policy_tags_t tags);
-void connection_SetAdminState(Connection *conn, connection_state_t admin_state);
+#define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG)
-#ifdef WITH_POLICY
-uint32_t connection_GetPriority(const Connection *conn);
+#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG)
-void connection_SetPriority(Connection *conn, uint32_t priority);
-#endif /* WITH_POLICY */
+#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)
-const char * connection_GetInterfaceName(const Connection * conn);
+#define connection_clear_tags(C) connection_set_tags(C, POLICY_TAGS_EMPTY)
-#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 */
-#endif // connection_h
+#endif
+
+connection_t* connection_create(face_type_t type, const char* name,
+ const address_pair_t* pair,
+ const struct forwarder_s* forwarder);
+
+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 connection_finalize(connection_t* connection);
+
+bool connection_send_packet(const connection_t* connection,
+ const uint8_t* packet, size_t size);
+
+bool connection_flush(connection_t* connection);
+
+bool connection_send(connection_t* connection, off_t msgbuf_id, bool queue);
+
+size_t connection_process_buffer(connection_t* connection,
+ const uint8_t* buffer, size_t size);
+
+/* 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 /* 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..a6b114c01
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_table.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file connection_table.c
+ * \brief Implementation of hICN connection table
+ */
+
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.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
+
+typedef struct {
+ char name[SYMBOLIC_NAME_LEN];
+} name_key_t;
+
+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->pair_keys = slab_create(address_pair_t, SLAB_INIT_SIZE);
+ table->id_by_name = kh_init_ct_name();
+ table->name_keys = slab_create(name_key_t, SLAB_INIT_SIZE);
+
+ /*
+ * 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) {
+ unsigned conn_id;
+ kh_foreach_value(table->id_by_name, conn_id, {
+ connection_t *connection = connection_table_get_by_id(table, conn_id);
+ const char *name = connection_get_name(connection);
+
+ INFO("Removing connection %s [%d]", name, connection->fd);
+ connection_finalize(connection);
+ });
+
+ kh_destroy_ct_pair(table->id_by_pair);
+ slab_free(table->pair_keys);
+ kh_destroy_ct_name(table->id_by_name);
+ slab_free(table->name_keys);
+
+ pool_free(table->connections);
+ free(table);
+}
+
+connection_t *connection_table_allocate(const connection_table_t *table,
+ const address_pair_t *pair,
+ const char *name) {
+ connection_t *conn = NULL;
+ pool_get(table->connections, conn);
+ if (!conn) return NULL;
+
+#ifdef __APPLE__
+ // set __uint8_t sin_len to 0
+ uint8_t *ptr = (uint8_t *)address_pair_get_local(pair);
+ *ptr = 0x0;
+ ptr = (uint8_t *)address_pair_get_remote(pair);
+ *ptr = 0x0;
+#endif /* __APPLE__ */
+
+ off_t id = conn - table->connections;
+ int rc;
+
+ // Add in name hash table
+ name_key_t *name_copy = slab_get(name_key_t, table->name_keys);
+ strcpy_s(name_copy->name, sizeof(name_key_t), name);
+
+ khiter_t k = kh_put_ct_name(table->id_by_name, name_copy->name, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_name, k) = (unsigned int)id;
+
+ // Add in pair hash table
+ address_pair_t *pair_copy = slab_get(address_pair_t, table->pair_keys);
+ memcpy(pair_copy, pair, sizeof(address_pair_t));
+
+ k = kh_put_ct_pair(table->id_by_pair, pair_copy, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_pair, k) = (unsigned int)id;
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_pair));
+ return conn;
+}
+
+void connection_table_deallocate(const connection_table_t *table,
+ const connection_t *conn) {
+ const char *name = connection_get_name(conn);
+ const address_pair_t *pair = connection_get_pair(conn);
+
+#ifdef __APPLE__
+ // set __uint8_t sin_len to 0
+ uint8_t *ptr = (uint8_t *)address_pair_get_local(pair);
+ *ptr = 0x0;
+ ptr = (uint8_t *)address_pair_get_remote(pair);
+ *ptr = 0x0;
+#endif /* __APPLE__ */
+
+ // Remove from name hash table
+ khiter_t k = kh_get_ct_name(table->id_by_name, name);
+ assert(k != kh_end(table->id_by_name));
+ kh_del_ct_name(table->id_by_name, k);
+ slab_put(table->name_keys, kh_key(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));
+ kh_del_ct_pair(table->id_by_pair, k);
+ slab_put(table->pair_keys, kh_key(table->id_by_pair, k));
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_pair));
+ pool_put(table->connections, conn);
+}
+
+connection_t *connection_table_get_by_pair(const connection_table_t *table,
+ const address_pair_t *pair) {
+#ifdef __APPLE__
+ // set __uint8_t sin_len to 0
+ uint8_t *ptr = (uint8_t *)address_pair_get_local(pair);
+ *ptr = 0x0;
+ ptr = (uint8_t *)address_pair_get_remote(pair);
+ *ptr = 0x0;
+#endif /* __APPLE__ */
+
+ 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 = (unsigned int)connection_table_get_id_by_name(table, name);
+ if (!connection_id_is_valid(conn_id)) return NULL;
+ return connection_table_at(table, conn_id);
+}
+
+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);
+}
+
+static inline u16 RAND16() { return rand() & 0xFFFF; }
+
+int connection_table_get_random_name(const connection_table_t *table,
+ char *name) {
+ int i, n_attempts = 2 * USHRT_MAX;
+ for (i = 0; i < n_attempts; i++) {
+ int rc = snprintf(name, SYMBOLIC_NAME_LEN, "conn%u", RAND16());
+ if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) continue;
+
+ // Check if generated connection name is a duplicate
+ khiter_t k = kh_get_ct_name(table->id_by_name, name);
+ if (k == kh_end(table->id_by_name)) break;
+ }
+
+ if (i == n_attempts) {
+ ERROR("Unable to generate new unique connection name");
+ return -1;
+ }
+
+ return 0;
+}
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..dcfb1e1dd
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_table.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <hicn/util/khash.h>
+#include <hicn/util/hash.h>
+#include <hicn/util/slab.h>
+#include "address_pair.h"
+#include "connection.h"
+#include <hicn/util/pool.h>
+
+/* Hash functions for indices. */
+#define address_pair_hash(pair) (hash_struct(pair))
+
+/* Hash table types for indices. */
+KHASH_INIT(ct_pair, const address_pair_t *, unsigned, 1, address_pair_hash,
+ address_pair_equals);
+KHASH_MAP_INIT_STR(ct_name, unsigned);
+
+typedef struct {
+ size_t max_size;
+
+ kh_ct_pair_t *id_by_pair;
+ slab_t *pair_keys;
+ kh_ct_name_t *id_by_name;
+ slab_t *name_keys;
+
+ 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.
+ */
+connection_t *connection_table_allocate(const connection_table_t *table,
+ const address_pair_t *pair,
+ const char *name);
+/**
+ * @brief Deallocate a connection and return it to the connection table pool.
+ *
+ * @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.
+ */
+void connection_table_deallocate(const connection_table_t *table,
+ const connection_t *conn);
+
+/**
+ * @brief Returns the length of the connection table, the number of active
+ * 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) \
+ (unsigned)(conn - table->connections)
+
+#define connection_table_foreach(table, conn, BODY) \
+ pool_foreach(table->connections, (conn), BODY)
+
+#define connection_table_foreach_new(table, CONN, BODY) \
+ pool_foreach_typed(table->connections, connection_t *, 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);
+
+int connection_table_get_random_name(const connection_table_t *table,
+ char *name);
+
+#endif /* HICNLIGHT_CONNECTION_TABLE_H */
diff --git a/hicn-light/src/hicn/core/connection_vft.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..cc736905c
--- /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)(connection_t* connection);
+ bool (*send)(connection_t* connection, msgbuf_t* msgbuf, bool queue);
+ bool (*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..360e6d333
--- /dev/null
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file 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);
+}
+
+cs_lru_stats_t cs_get_lru_stats(cs_t *cs) { return cs->stats.lru; }
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
new file mode 100644
index 000000000..ceaf05e6b
--- /dev/null
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -0,0 +1,108 @@
+#ifndef HICNLIGHT_CS_H
+#define HICNLIGHT_CS_H
+
+#include <hicn/util/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);
+
+cs_lru_stats_t cs_get_lru_stats(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..c44d2daf0
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 *child[2]; /* 0: left, 1: right */
+ fib_entry_t *entry;
+ bool is_used;
+} fib_node_t;
+
+#define ZERO 0
+#define ONE 1
+
+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){
+ .child = {left, 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->child[ZERO]);
+ fib_node_free(node->child[ONE]);
+
+ 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;
+}
+
+/*
+ * This struct will hold various information related to the returned node such
+ * as its parent and grandparent if any, as well as some already computed
+ * information about the prefix.
+ */
+typedef struct {
+ /* Result node ancestors (NULL if not applicable) */
+ fib_node_t *parent;
+ fib_node_t *gparent;
+ fib_node_t *lpm;
+ /* Information related to the result node */
+ hicn_prefix_t *prefix;
+ uint32_t prefix_len;
+ uint32_t match_len;
+} fib_search_t;
+/*
+ * @brief Search for longest subprefix (helper function)
+ * @param [in] fib - Pointer to the FIB to search
+ * @param [in] prefix - The prefix used for search
+ * @param [out] search - A pointer to a structure that will hold related search
+ * information, that can be NULL if this is not needed.
+ *
+ * @returns The node whose entry corresponds to the longest subprefix of the
+ * prefix passed in parameter, or NULL if not found. The longest prefix match is
+ * thus the resulting node if curr_len == prefix_len, and its parent
+ * otherwise.
+ *
+ * Implementation details:
+ *
+ * This function performs a descent in the tree, following branches
+ * corresponding to the value of the next bit, until reaching past a leaf, or
+ * either the current node prefix:
+ * when one of the two following conditions is met:
+ * - is not a prefix of the searched one (match_len < curr_len), or
+ * - is longer or equal than the inserted one (curr_len >= prefix_len)
+ */
+fib_node_t *fib_search(const fib_t *fib, const hicn_prefix_t *prefix,
+ fib_search_t *search) {
+ uint32_t prefix_len = hicn_prefix_get_len(prefix);
+ uint32_t curr_len;
+ uint32_t match_len;
+
+ WITH_DEBUG({
+ char buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)");
+ DEBUG("[fib_search] prefix=%s prefix_len=%d\n", buf, prefix_len);
+ });
+
+ fib_node_t *parent = NULL;
+ fib_node_t *gparent = NULL;
+ fib_node_t *lpm = NULL;
+ fib_node_t *curr = fib->root;
+ while (curr) {
+ const hicn_prefix_t *curr_prefix = fib_entry_get_prefix(curr->entry);
+
+ curr_len = hicn_prefix_get_len(curr_prefix);
+ match_len = hicn_prefix_lpm(prefix, curr_prefix);
+
+ // store the lpm
+ if (match_len == curr_len && curr->is_used) lpm = curr;
+
+ // curr_len >= prefix_len l >= L
+ // L is a prefix of l
+ // > means we did not find
+ // = means we could have found
+ if (match_len < curr_len || curr_len >= prefix_len) break;
+
+ gparent = parent;
+ parent = curr;
+
+ /* The following lookup won't fail since curr_len < prefix_len */
+ uint8_t next_bit = hicn_prefix_get_bit(prefix, curr_len);
+ curr = curr->child[next_bit];
+ }
+
+ if (search) {
+ search->parent = parent;
+ search->gparent = gparent;
+ search->lpm = lpm;
+ if (curr) {
+ search->prefix_len = curr_len;
+ search->match_len = match_len;
+ }
+ }
+ return curr;
+}
+
+/*
+ * Helper: insert a new node between parent and child.
+ *
+ * parent == NULL means we set the root of the FIB
+ * child == NULL means our node has no child
+ */
+fib_node_t *_fib_insert(fib_t *fib, fib_entry_t *entry, fib_node_t *parent,
+ fib_node_t *child, bool is_used) {
+ fib_node_t *new_node = fib_node_create(NULL, NULL, entry, is_used);
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(entry);
+
+ if (!parent) {
+ fib->root = new_node;
+ } else {
+ const hicn_prefix_t *parent_prefix = fib_entry_get_prefix(parent->entry);
+ uint32_t parent_prefix_len = hicn_prefix_get_len(parent_prefix);
+ uint8_t next_bit = hicn_prefix_get_bit(prefix, parent_prefix_len);
+ parent->child[next_bit] = new_node;
+ }
+
+ if (child) {
+ const hicn_prefix_t *child_prefix = fib_entry_get_prefix(child->entry);
+ uint32_t match_len = hicn_prefix_lpm(prefix, child_prefix);
+ uint8_t next_bit = hicn_prefix_get_bit(child_prefix, match_len);
+ new_node->child[next_bit] = child;
+ }
+
+ if (is_used) fib->size++;
+ return new_node;
+}
+
+/*
+ * Helper: remove a node from parent
+ */
+void _fib_remove(fib_t *fib, fib_node_t *curr, fib_node_t *parent) {
+ /*
+ * If we remove the node, curr has either 0 or 1 child. In the latter case,
+ * we attach it to parent
+ */
+ fib_node_t *child = curr->child[ZERO] ? curr->child[ZERO] : curr->child[ONE];
+ if (!parent) {
+ fib->root = child;
+ } else {
+ if (parent->child[ZERO] == curr)
+ parent->child[ZERO] = child;
+ else
+ parent->child[ONE] = child;
+ }
+ if (curr->is_used) fib->size--;
+ fib_node_free(curr);
+}
+
+/*
+ * - Stop condition: curr == NULL. This corresponds to:
+ *
+ * (CASE 1) Our parent is a strict prefix and we simply have to create a new
+ * leaf child in the correct branch based on the next bit following the parent
+ * prefix.
+ *
+ * Otherwise, our parent node exist. Based on the stop condition, we
+ * either have:
+ *
+ * - Stop condition 1 : curr_len == match_len AND curr_len >=
+ * prefix_len l == m && l >= L
+ *
+ * 2 sub-cases:
+ * - l = m > L : IMPOSSIBLE L < m since m = LPM(l, L) means L >= m
+ * - l = m = L : insert the current node, either it exists or not
+ *
+ * We thus have:
+ *
+ * (CASE 2) The node already exist. If is not in use we turn it on and we set
+ * the right fib entry.
+ *
+ * The case when it is used should never occur because of the way we add
+ * entries in the FIB... but let's add the nexthops we wish to insert into
+ * the existing FIB entry.
+ *
+ * - Stop condition 2: curr_len != match_len
+ * l != m => l > m
+ *
+ * We have two possibilities:
+ * - Only one is bigger than m (case 3)
+ * - They are both bigger than m (case 4)
+ *
+ * (CASE 3) Only one is bigger than m
+ * L == m => L < l (since l != m and l >= m)
+ * l > L = m
+ *
+ * This means L is a prefix of l.
+ * l'
+ * /
+ * L
+ * /
+ * l
+ *
+ * (CASE 4) They are both bigger than m
+ * - l > L > m
+ * - L > l > m
+ * - L = l > m
+ *
+ * Both share L and l share l' as a common prefix, and this is not l' since
+ * they share the name next bit.
+ *
+ * So this case is impossible and we would have taken the other branch during
+ * the descent:
+ *
+ * l'
+ * / \
+ * l L
+ *
+ * We are in a situation where e need to insert an internal node:
+ *
+ * l'
+ * |
+ * X <------ internal node
+ * / \
+ * l L
+ */
+fib_entry_t *fib_add(fib_t *fib, fib_entry_t *entry) {
+ assert(fib);
+ assert(entry);
+
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(entry);
+ uint32_t prefix_len = hicn_prefix_get_len(prefix);
+
+ fib_search_t search;
+ fib_node_t *curr = fib_search(fib, prefix, &search);
+
+ char buf[MAXSZ_HICN_PREFIX];
+ char buf2[MAXSZ_HICN_PREFIX];
+ int rc;
+
+ rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)");
+ if (curr) {
+ rc = hicn_prefix_snprintf(buf2, MAXSZ_HICN_PREFIX,
+ fib_entry_get_prefix(curr->entry));
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf2, MAXSZ_HICN_PREFIX, "%s", "(error)");
+ } else {
+ snprintf(buf2, MAXSZ_HICN_PREFIX, "%s", "(null)");
+ search.prefix_len = 0;
+ search.match_len = 0;
+ }
+ DEBUG("fib_search(%s) result: curr=%s, prefix_len=%d; match_len=%d\n", buf,
+ buf2, search.prefix_len, search.match_len);
+
+ /* Case 1 */
+ if (!curr) {
+ _fib_insert(fib, entry, search.parent, NULL, true);
+ goto END;
+ }
+
+ /* Case 2 */
+ if (search.prefix_len == search.match_len && prefix_len == search.match_len) {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+ nexthops_foreach(nexthops, nexthop,
+ { fib_entry_nexthops_add(curr->entry, nexthop); });
+ fib_entry_free(entry);
+ entry = curr->entry;
+ curr->is_used = true;
+ goto END;
+ }
+
+ /* Case 3 */
+ if (prefix_len == search.match_len) {
+ _fib_insert(fib, entry, search.parent, curr, true);
+ goto END;
+ }
+
+ /* Case 4 */
+ hicn_prefix_t inner_prefix; /* dup'ed in fib_entry_create */
+ hicn_prefix_copy(&inner_prefix, prefix);
+
+ hicn_prefix_truncate(&inner_prefix, search.match_len);
+
+ fib_entry_t *inner_entry = fib_entry_create(
+ &inner_prefix, STRATEGY_TYPE_UNDEFINED, NULL, fib->forwarder);
+
+ fib_node_t *new_node =
+ _fib_insert(fib, inner_entry, search.parent, curr, false);
+ _fib_insert(fib, entry, new_node, NULL, true);
+
+END:
+#if 0
+ fib_dump(fib);
+#endif
+ return entry;
+}
+
+/*
+ * Implementation details:
+ *
+ * To find whether the fib contains a prefix, we issue a search, and based on
+ * the stopping conditions, we return the fib note if and only if curr
+ * is not NULL, and prefix_len == curr_len (== match_len)
+ */
+fib_node_t *fib_contains_node(const fib_t *fib, const hicn_prefix_t *prefix) {
+ assert(fib);
+ assert(prefix);
+
+ uint32_t prefix_len = hicn_prefix_get_len(prefix);
+
+ fib_search_t search;
+ fib_node_t *curr = fib_search(fib, prefix, &search);
+
+ if (!curr) return NULL;
+ if (search.match_len != prefix_len) return NULL;
+ if (prefix_len != search.prefix_len) return NULL;
+
+ return curr->is_used ? curr : NULL;
+}
+
+fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix) {
+ fib_node_t *node = fib_contains_node(fib, prefix);
+ if (!node) return NULL;
+ return node->entry;
+}
+
+/*
+ * @brief Remove a prefix (and the associated node) from FIB
+ *
+ * We search for
+ *
+ * Actions depend on N, the number of children of the node to remove
+ * Examples are build using 'left' children only, but the cases with 'right'
+ * children are symmetrical.
+ *
+ * Legend:
+ * (empty) : no children
+ * * : 0 or more children
+ * + : at least one children
+ *
+ * N == 2 - Mark the node as unused
+ *
+ * parent parent
+ * / \ / \
+ * curr ... ==> (curr) ...
+ * / \ / \
+ * L R L R
+ *
+ * N == 1 - Attach the child to the parent node (whether parent is used or not)
+ *
+ * a) curr has no parent (curr is the root)
+ *
+ * curr +
+ * / ==>
+ * +
+ *
+ * b) curr has a parent
+ * parent parent
+ * / \ / \
+ * curr * ==> L *
+ * / \
+ * L
+ *
+ * (parent) (parent)
+ * / \ / \
+ * curr + ==> L +
+ * / \
+ * L
+ *
+ * N == 0
+ *
+ * a) curr has no parent (curr is the root)
+ *
+ * curr
+ * / \ ==>
+ *
+ * b) parent is unused.
+ *
+ * Assuming curr is the left child, then parent must have a
+ * right child, and the grand-parent must be used.
+ *
+ * gp gp gp
+ * / / /
+ * (parent) ==> (parent) ==> +
+ * / \ / \
+ * curr + +
+ * / \
+ *
+ * c) parent is used.
+ *
+ * Assuming curr is the left child, we simply remove it from
+ * parent, leaving parent unchanged whether it has a right child or not.
+ *
+ * parent parent
+ * / \ / \
+ * curr * ==> *
+ * / \
+ *
+ *
+ */
+static void fib_node_remove(fib_t *fib, const hicn_prefix_t *prefix) {
+ assert(fib);
+ assert(prefix);
+
+ uint32_t prefix_len = hicn_prefix_get_len(prefix);
+
+ fib_search_t search;
+ fib_node_t *curr = fib_search(fib, prefix, &search);
+
+ /*
+ * If we reach a NULL, unused node, or a node not matching, that means the
+ * node does not exist
+ */
+ if (!curr || !curr->is_used || (search.prefix_len != prefix_len)) return;
+
+ uint8_t N = 0;
+ if (curr->child[ZERO]) N++;
+ if (curr->child[ONE]) N++;
+
+ switch (N) {
+ case 2:
+ curr->is_used = false;
+ break;
+
+ case 1:
+ _fib_remove(fib, curr, search.parent);
+ break;
+
+ case 0:
+ _fib_remove(fib, curr, search.parent);
+ if (search.parent && !search.parent->is_used)
+ _fib_remove(fib, search.parent, search.gparent);
+ break;
+ }
+}
+
+void fib_remove(fib_t *fib, const hicn_prefix_t *prefix, unsigned conn_id) {
+ assert(fib);
+ assert(prefix);
+
+ fib_node_t *node = fib_contains_node(fib, prefix);
+ if (!node) return;
+
+ fib_entry_nexthops_remove(node->entry, conn_id);
+ if (fib_entry_nexthops_len(node->entry) == 0)
+ /* When using MAP-Me, we keep empty FIB entries but we mark them as unused*/
+#ifdef WITH_MAPME
+ node->is_used = false;
+#else
+ 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);
+
+ /* When using MAP-Me, we keep empty FIB entries but we mark them as unused*/
+ if (fib_entry_nexthops_len(node->entry) == 0)
+#ifdef WITH_MAPME
+ node->is_used = false;
+#else
+ array[pos++] = node->entry;
+#endif /* WITH_MAPME */
+ }
+ pos = fib_node_remove_connection_id(node->child[ONE], conn_id, array, pos);
+ pos = fib_node_remove_connection_id(node->child[ZERO], conn_id, array, pos);
+ return pos;
+}
+
+void fib_remove_entry(fib_t *fib, fib_entry_t *entry) {
+ fib_node_remove(fib, fib_entry_get_prefix(entry));
+}
+
+void fib_remove_connection(fib_t *fib, unsigned conn_id,
+ fib_entry_t ***removed_entries,
+ size_t *num_removed_entries) {
+ 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);
+
+ if (removed_entries) {
+ /*
+ * The caller is taking charge of releasing entries (as well as the returned
+ * array
+ */
+ assert(num_removed_entries);
+
+ *removed_entries = array;
+ *num_removed_entries = pos;
+
+ } else {
+ for (int i = 0; i < pos; i++)
+ fib_node_remove(fib, fib_entry_get_prefix(array[i]));
+ }
+ free(array);
+}
+
+fib_entry_t *fib_match_msgbuf(const fib_t *fib, const msgbuf_t *msgbuf) {
+ assert(fib);
+ assert(msgbuf);
+
+ return fib_match_name(fib, msgbuf_get_name(msgbuf));
+}
+
+/*
+ * fib_search returns the longest non-strict subprefix.
+ * the LPM is stored in search if it exists
+ */
+fib_entry_t *fib_match_prefix(const fib_t *fib, const hicn_prefix_t *prefix) {
+ assert(fib);
+ assert(prefix);
+
+ fib_search_t search;
+ fib_search(fib, prefix, &search);
+ if (!search.lpm) return NULL;
+ return search.lpm->entry;
+}
+
+fib_entry_t *fib_match_name(const fib_t *fib, const hicn_name_t *name) {
+ hicn_prefix_t prefix;
+ const hicn_name_prefix_t *name_prefix = hicn_name_get_prefix(name);
+ prefix.name = *name_prefix;
+ prefix.len = hicn_name_prefix_get_len_bits(name_prefix);
+ return fib_match_prefix(fib, &prefix);
+}
+
+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->child[ONE], array, pos);
+ pos = fib_node_collect_entries(node->child[ZERO], 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;
+}
+
+bool _fib_is_valid(const fib_node_t *node) {
+ if (!node) return true;
+
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry);
+ uint32_t prefix_len = hicn_prefix_get_len(prefix);
+
+ for (unsigned i = 0; i < 2; i++) {
+ const fib_node_t *child = node->child[i];
+ if (!child) continue;
+ const hicn_prefix_t *child_prefix = fib_entry_get_prefix(child->entry);
+
+ uint32_t match_len = hicn_prefix_lpm(prefix, child_prefix);
+ if (match_len != prefix_len) return false;
+ if (hicn_prefix_get_bit(child_prefix, match_len) != i) return false;
+ if (!_fib_is_valid(child)) return false;
+ }
+ return true;
+}
+
+/*
+ * @brief Check that the structure of the FIB is correct : prefixes are
+ * correctly nested, 0 are on the left, 1 on the right, and that we have no
+ * more than 1 unused prefix as parents.
+ */
+bool fib_is_valid(const fib_t *fib) { return _fib_is_valid(fib->root); }
+
+/*
+ * Checks whether the preorder traversal of the sub-tree corresponds to the
+ * prefix and used arrays, starting from pos (helper)
+ */
+bool __fib_check_preorder(const fib_node_t *node,
+ const hicn_prefix_t **prefix_array, bool *used_array,
+ size_t size, size_t *pos) {
+ /* Check left subtree... */
+ fib_node_t *left = node->child[ZERO];
+ if (left && !__fib_check_preorder(left, prefix_array, used_array, size, pos))
+ return false;
+
+ /* ... then current node ... */
+ if (*pos > size) {
+ ERROR("size error");
+ return false;
+ }
+
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry);
+
+ if (!hicn_prefix_equals(prefix, prefix_array[*pos])) {
+ char buf[MAXSZ_HICN_PREFIX];
+ char buf2[MAXSZ_HICN_PREFIX];
+ int rc;
+
+ rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)");
+ rc = hicn_prefix_snprintf(buf2, MAXSZ_HICN_PREFIX, prefix_array[*pos]);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf2, MAXSZ_HICN_PREFIX, "%s", "(error)");
+ ERROR("Prefix mismatch in position %ld %s != %s", *pos, buf, buf2);
+ return false;
+ }
+
+ (*pos)++;
+
+ /* ... then right subtree */
+ fib_node_t *right = node->child[ONE];
+ if (right &&
+ !__fib_check_preorder(right, prefix_array, used_array, size, pos))
+ return false;
+
+ return true;
+}
+
+/*
+ * Checks whether the preorder traversal of the trie
+ * corresponds to the prefix and used arrays.
+ */
+bool _fib_check_preorder(const fib_t *fib, const hicn_prefix_t **prefix_array,
+ bool *used_array, size_t size) {
+ if (!fib->root) return true;
+ size_t pos = 0;
+ if (!__fib_check_preorder(fib->root, prefix_array, used_array, size, &pos))
+ return false;
+ /* We need to check that we don't miss elements */
+ return pos == size;
+}
+
+// XXX print empty node but not recurse
+void _fib_dump(const fib_node_t *node, int start, int indent, int location) {
+ char buf[MAXSZ_HICN_PREFIX];
+
+ if (node) {
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry);
+ int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "%s %d", "(error)", rc);
+ } else {
+ snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(null)");
+ }
+
+ if (indent > 0) {
+ for (int i = 0; i < start; i++) printf(" ");
+ for (int i = 0; i < indent - start - 1; i++) printf("| ");
+ printf("|_ ");
+ }
+ printf("%s", buf);
+ if (node && !node->is_used) printf(" [inner]");
+ printf("\n");
+
+ if (!node) return;
+
+ if (location == 2) {
+ start++;
+ location = 0;
+ }
+ _fib_dump(node->child[ZERO], start, indent + 1,
+ (location == 0) ? 1 : location);
+ _fib_dump(node->child[ONE], start, indent + 1,
+ (location == 0) ? 2 : location);
+}
+
+void fib_dump(const fib_t *fib) { _fib_dump(fib->root, 0, 0, 0); }
diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h
new file mode 100644
index 000000000..4fb5009f5
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <hicn/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);
+
+fib_entry_t *fib_add(fib_t *fib, fib_entry_t *node);
+
+fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix);
+
+void fib_remove(fib_t *fib, const hicn_prefix_t *prefix, unsigned conn_id);
+
+void fib_remove_entry_connection(fib_t *fib, fib_entry_t *entry,
+ unsigned conn_id, fib_entry_t **removed_entry);
+
+void fib_remove_name_connection(fib_t *fib, const hicn_prefix_t *prefix,
+ unsigned conn_id);
+
+void fib_remove_entry(fib_t *fib, fib_entry_t *entry);
+
+void fib_remove_connection(fib_t *fib, unsigned conn_id,
+ fib_entry_t ***removed_entries,
+ size_t *num_removed_entries);
+
+fib_entry_t *fib_match_msgbuf(const fib_t *fib, const msgbuf_t *msgbuf);
+
+fib_entry_t *fib_match_prefix(const fib_t *fib, const hicn_prefix_t *prefix);
+
+fib_entry_t *fib_match_name(const fib_t *fib, const hicn_name_t *name);
+
+size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p);
+
+/*
+ * NOTE : do not use return on the loop body to avoid leaking memory
+ */
+#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); \
+ fib_entry_t *ENTRY; \
+ 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)
+
+bool fib_is_valid(const fib_t *fib);
+bool _fib_check_preorder(const fib_t *fib, const hicn_prefix_t **prefix_array,
+ bool *used_array, size_t size);
+
+#define fib_check_preorder(F, PA, UA) \
+ _fib_check_preorder(F, PA, UA, sizeof(PA) / sizeof(hicn_prefix_t *))
+
+void fib_dump(const fib_t *fib);
+
+#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..b510b68b4
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib_entry.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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>
+
+#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(const hicn_prefix_t *prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options,
+ const forwarder_t *forwarder) {
+ assert(prefix);
+ /*
+ * For tests, we allow forwarder to be NULL, some
+ * functions cannot be called but otherwise we need a main loop, etc.
+ */
+ // assert(forwarder);
+
+ fib_entry_t *entry = malloc(sizeof(fib_entry_t));
+ if (!entry) goto ERR_MALLOC;
+
+ memset(entry, 0, sizeof(*entry));
+ hicn_prefix_copy(&entry->prefix, prefix);
+ 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);
+}
+
+/*
+ * Filters the set of nexthops passed as parameters (and not the one stored in
+ * the FIB entry
+ */
+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;
+ 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)));
+
+#ifdef WITH_POLICY
+ /* 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)));
+#endif /* WITH_POLICY */
+ });
+
+ 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 */
+
+#ifdef WITH_POLICY
+ /*
+ * 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;
+ }
+// XXX backup curlen ???
+#endif /* WITH_POLICY */
+
+ 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));
+
+ /* Nexthop priority */
+
+ /*
+ * Filter out nexthops with lowest strategy priority.
+ * Initializing at 0 allows to disable nexthops with a negative priority
+ */
+ max_priority = 0;
+ 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.
+ */
+ 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);
+ }
+
+ return nexthops;
+}
+
+/*
+ * Retrieve all candidate nexthops for sending mapme updates == all non local
+ * connections. We don't apply the policy at this stage.
+ */
+nexthops_t *fib_entry_get_mapme_nexthops(fib_entry_t *entry,
+ nexthops_t *new_nexthops) {
+ assert(new_nexthops);
+
+ const connection_table_t *table =
+ forwarder_get_connection_table(entry->forwarder);
+
+ /* 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);
+ });
+
+ return new_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)] =
+ (unsigned int)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
+}
+
+#ifdef WITH_POLICY
+
+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) {
+ INFO("fib_entry_set_policy");
+ entry->policy = policy;
+
+ forwarder_on_route_event(entry->forwarder, entry);
+
+ // XXX generic mechanism to perform a mapme update
+#if 0
+#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);
+#endif /* WITH_MAPME */
+#endif
+}
+
+#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;
+ nexthops_enumerate(nexthops, i, 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 hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *entry) {
+ assert(entry);
+ return &(entry->prefix);
+}
+
+/*
+ * 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);
+
+ 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;
+}
+
+bool fib_entry_has_all_local_nexthops(const fib_entry_t *entry) {
+ connection_table_t *table = forwarder_get_connection_table(entry->forwarder);
+
+ int count = 0;
+ 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)) return false;
+ count++;
+ });
+ return (count > 0);
+}
+
+#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..e1e48c871
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib_entry.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <hicn/name.h>
+#include "strategy.h"
+#include "msgbuf.h"
+#include "nexthops.h"
+#include "policy_stats.h"
+
+typedef struct {
+ hicn_prefix_t prefix;
+ unsigned refcount;
+ nexthops_t nexthops;
+
+ /* This is used for producer prefixes only */
+ uint32_t nexthops_hash;
+
+ 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
+#if 0
+ /* 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;
+#endif
+ 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_get_nexthops_hash(E) ((E)->nexthops_hash)
+#define fib_entry_set_nexthops_hash(E, H) (E)->nexthops_hash = (H)
+
+static inline void fib_entry_set_nexthops(fib_entry_t *entry,
+ nexthops_t *nexthops) {
+ entry->nexthops = *nexthops;
+}
+
+static inline void fib_entry_initialize_nexthops(fib_entry_t *entry) {
+ entry->nexthops = NEXTHOPS_EMPTY;
+}
+
+static inline bool fib_entry_nexthops_changed(fib_entry_t *entry,
+ nexthops_t *nexthops) {
+ uint32_t old_hash = fib_entry_get_nexthops_hash(entry);
+ uint32_t hash = nexthops_get_hash(nexthops);
+ if (hash != old_hash) {
+ fib_entry_set_nexthops_hash(entry, hash);
+ return true;
+ }
+ return false;
+};
+
+struct forwarder_s;
+
+/*
+ * This does a copy of the name passed as parameter
+ */
+fib_entry_t *fib_entry_create(const hicn_prefix_t *prefix,
+ 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);
+
+/**
+ * @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_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops,
+ unsigned ingress_id, bool prefer_local);
+
+nexthops_t *fib_entry_get_mapme_nexthops(fib_entry_t *entry,
+ nexthops_t *new_nexthops);
+
+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
+ * @return The FIB entry prefix
+ */
+const hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *fib_entry);
+
+bool fib_entry_has_local_nexthop(const fib_entry_t *entry);
+bool fib_entry_has_all_local_nexthops(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..8c276bfef 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-2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.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,20 @@
* 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
+
+/* Shall we send mapme updates to advertise all local prefixes on newly created
+ * faces
+ */
+//#define ADVERTISE_PREFIXES_ON_NEW_FACES
+
#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
@@ -30,8 +44,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 +54,71 @@
#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/interest_manifest.h>
+#include <hicn/util/log.h>
-#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_s {
+ // uint16_t server_port;
-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;
-#if !defined(__APPLE__)
- hicn_socket_helper_t
- *hicnSocketHelper; // state required to manage hicn connections
-#endif
- // used by seed48 and nrand48
- unsigned short seed[3];
+ subscription_table_t *subscriptions;
-#ifdef WITH_MAPME
- MapMe *mapme;
-#endif /* WITH_MAPME */
+ // Used to store the msgbufs that need to be released
+ off_t *acquired_msgbuf_ids;
};
-// 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 +144,1533 @@ 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__ */
-
-#ifdef WITH_MAPME
- if (!(mapme_create(&forwarder->mapme, forwarder)))
- goto ERR_MAPME;
-#endif /* WITH_MAPME */
+ forwarder->msgbuf_pool = msgbuf_pool_create();
+ if (!forwarder->msgbuf_pool) goto ERR_PACKET_POOL;
+ size_t objectStoreSize = configuration_get_cs_size(configuration);
+ forwarder->pkt_cache = pkt_cache_create(objectStoreSize);
+ if (!forwarder->pkt_cache) goto ERR_PKT_CACHE;
- /* ignore child */
-#ifndef _WIN32
- signal(SIGCHLD, SIG_IGN);
+ forwarder->subscriptions = subscription_table_create();
+ if (!forwarder->subscriptions) goto ERR_SUBSCRIPTION;
- /* 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));
+ vector_init(forwarder->pending_conn, MAX_MSG, 0);
+ vector_init(forwarder->acquired_msgbuf_ids, MAX_MSG, 0);
- 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);
+ char *n_suffixes_per_split_str = getenv("N_SUFFIXES_PER_SPLIT");
+ if (n_suffixes_per_split_str)
+ configuration_set_suffixes_per_split(forwarder_get_configuration(forwarder),
+ atoi(n_suffixes_per_split_str));
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));
-
- listenerSet_Destroy(&(forwarder->listenerSet));
- connectionManager_Destroy(&(forwarder->connectionManager));
- connectionTable_Destroy(&(forwarder->connectionTable));
- messageProcessor_Destroy(&(forwarder->processor));
- configuration_Destroy(&(forwarder->config));
+void forwarder_free(forwarder_t *forwarder) {
+ assert(forwarder);
- // 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);
+ vector_free(forwarder->pending_conn);
+ vector_free(forwarder->acquired_msgbuf_ids);
+ free(forwarder);
+}
+
+/*
+ * An event occurred that might trigger an update of the FIB cache. It is
+ * possible that the flags have been reset following a connection add or remote.
+ * The objective of this function is to prepare the cache entry, and to alert of
+ * any change for both consumer and producer prefixes.
+ */
+void forwarder_on_route_event(const forwarder_t *forwarder,
+ fib_entry_t *entry) {
+ commands_notify_route(forwarder, entry);
+
+#ifdef ADVERTISE_PREFIXES_ON_NEW_FACES
+ nexthops_t new_nexthops = NEXTHOPS_EMPTY;
+#endif /* ADVERTISE_PREFIXES_ON_NEW_FACES */
+
+ nexthops_t *nexthops = NULL;
+ char *prefix_type_s;
+
+ const connection_table_t *table =
+ forwarder_get_connection_table(entry->forwarder);
+
+ const hicn_prefix_t *prefix = fib_entry_get_prefix(entry);
+
+ WITH_INFO({
+ char buf[MAXSZ_HICN_PREFIX];
+ hicn_prefix_snprintf(buf, MAXSZ_HICN_NAME, prefix);
+ INFO("fib_entry_on_event: %s", buf);
+ )};
+
+ if (!fib_entry_has_local_nexthop(entry)) {
+ /* Recompute FIB cache, then check whether it has changed based on hash */
+ prefix_type_s = "consumer";
+ nexthops = fib_entry_get_nexthops(entry);
+ nexthops_reset(nexthops);
+ fib_entry_filter_nexthops(entry, nexthops, ~0, false);
+#ifdef ADVERTISE_PREFIXES_ON_NEW_FACES
+ } else {
+ /* Check available non-local connections (on which we would send MAP-Me
+ * updates */
+ prefix_type_s = "producer";
+
+ nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops);
+ fib_entry_filter_nexthops(entry, nexthops, ~0, true);
+
+#ifdef WITH_MAPME
+ mapme_set_adjacencies(forwarder->mapme, entry, nexthops, NULL);
+#endif /* WITH_MAPME */
+#endif /* ADVERTISE_PREFIXES_ON_NEW_FACES */
+ }
+
+ if (!nexthops)
+ return;
- parcClock_Release(&forwarder->clock);
- logger_Release(&forwarder->logger);
+ if (!fib_entry_nexthops_changed(entry, nexthops)) return;
- // do the dispatcher last
- dispatcher_Destroy(&(forwarder->dispatcher));
+ /* Send notification */
+ WITH_INFO({
+ char buf[MAXSZ_HICN_PREFIX];
+ hicn_prefix_snprintf(buf, MAXSZ_HICN_NAME, prefix);
+ INFO("Active interfaces changed for %s prefix %s", prefix_type_s, buf);
+ });
- parcMemory_Deallocate((void **)&forwarder);
- *ptr = NULL;
+ netdevice_flags_t flags = NETDEVICE_FLAGS_EMPTY;
+ nexthops_foreach(nexthops, nh, {
+ connection_t *connection = connection_table_get_by_id(table, nh);
+ netdevice_flags_add(flags, connection_get_interface_type(connection));
+ });
+
+ hicn_ip_prefix_t ip_prefix;
+ hicn_prefix_get_ip_prefix(prefix, &ip_prefix);
+ commands_notify_active_interface_update(forwarder, &ip_prefix, flags);
}
-void forwarder_SetupAllListeners(Forwarder *forwarder, uint16_t port,
- const char *localPath) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
+int forwarder_add_connection(const forwarder_t *forwarder,
+ const char *symbolic_name, face_type_t type,
+ address_pair_t *pair, policy_tags_t tags,
+ int priority, face_state_t admin_state) {
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *connection = connection_table_get_by_pair(table, pair);
+
+ if (!connection) {
+ connection = connection_create(type, symbolic_name, pair, forwarder);
+ if (!connection) {
+ ERROR("Failed to create %s connection", face_type_str(type));
+ return -1;
+ }
+
+ } else {
+ WARN("Connection already exists");
+ }
+
+#ifdef WITH_POLICY
+ connection_set_tags(connection, tags);
+ connection_set_priority(connection, priority);
+#endif /* WITH_POLICY */
- configurationListeners_SetupAll(forwarder->config, port, localPath);
+ connection_set_admin_state(connection, admin_state);
+ return 0;
}
-void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- configurationListeners_SetutpLocalIPv4(forwarder->config, port);
+int forwarder_remove_connection(const forwarder_t *forwarder,
+ unsigned connection_id, bool finalize) {
+ /* Remove connection from the FIB */
+ forwarder_remove_connection_id_from_routes(forwarder, connection_id);
+
+ /* Remove connection */
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+
+ /* Hook: connection deleted through the control protocol */
+ connection_t *connection = connection_table_at(table, connection_id);
+ forwarder_on_connection_event(forwarder, connection, CONNECTION_EVENT_DELETE);
+
+ connection_table_remove_by_id(table, connection_id);
+ if (finalize) connection_finalize(connection);
+
+ return 0;
}
-void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename) {
- ConfigurationFile *configFile = configurationFile_Create(forwarder, filename);
- if (configFile) {
- configurationFile_Process(configFile);
- configurationFile_Release(&configFile);
- }
+/*
+ * This is currently called from commands.c for every command sent to update
+ * a connection.
+ */
+void forwarder_on_connection_event(const forwarder_t *forwarder,
+ const connection_t *connection,
+ connection_event_t event) {
+ assert(connection);
+
+ commands_notify_connection(forwarder, event, connection);
+
+ unsigned conn_id = connection_get_id(connection);
+
+ /* We need to send a MapMe update on the newly selected connections for
+ * each concerned fib_entry : connection is involved, or no more involved */
+ fib_t *fib = forwarder_get_fib(forwarder);
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t *nexthops = fib_entry_get_nexthops(entry);
+
+ if (!fib_entry_has_local_nexthop(entry)) {
+ /* Consumer prefix */
+ /*
+ * A new connection has no impact until it is added to FIB, which will
+ * be handled in a route event
+ */
+ if (event == CONNECTION_EVENT_CREATE) break;
+
+ /*
+ * For each FIB entry, trigger an event only if the connection is part
+ * of nexthops */
+ // XXX Replace this by a function
+ nexthops_foreach(nexthops, nexthop, {
+ if (nexthop != conn_id) continue;
+ forwarder_on_route_event(forwarder, entry);
+ break;
+ });
+ } else {
+ /* Producer prefix */
+ if (connection_is_local(connection)) break;
+
+ // XXX we could optimize event more
+ forwarder_on_route_event(forwarder, entry);
+ }
+ });
+}
+
+void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port) {
+ assert(forwarder);
+ listener_setup_local(forwarder, port);
}
-Configuration *forwarder_GetConfiguration(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
+configuration_t *forwarder_get_configuration(forwarder_t *forwarder) {
+ assert(forwarder);
return forwarder->config;
}
-// ============================================================================
+subscription_table_t *forwarder_get_subscriptions(
+ const forwarder_t *forwarder) {
+ return forwarder->subscriptions;
+}
+
+connection_table_t *forwarder_get_connection_table(
+ const forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->connection_table;
+}
-unsigned forwarder_GetNextConnectionId(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->nextConnectionid++;
+listener_table_t *forwarder_get_listener_table(const forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->listener_table;
}
-Messenger *forwarder_GetMessenger(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->messenger;
+pkt_cache_t *forwarder_get_pkt_cache(const forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->pkt_cache;
}
-Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->dispatcher;
+void forwarder_cs_set_store(forwarder_t *forwarder, bool val) {
+ assert(forwarder);
+ forwarder->store_in_cs = val;
}
-#ifdef WITH_POLICY
-ConnectionTable *forwarder_GetConnectionTable(const Forwarder *forwarder) {
-#else
-ConnectionTable *forwarder_GetConnectionTable(Forwarder *forwarder) {
-#endif /* WITH_POLICY */
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->connectionTable;
+bool forwarder_cs_get_store(forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->store_in_cs;
}
-ListenerSet *forwarder_GetListenerSet(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->listenerSet;
+void forwarder_cs_set_serve(forwarder_t *forwarder, bool val) {
+ assert(forwarder);
+ forwarder->serve_from_cs = val;
}
-void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- messageProcessor_SetCacheStoreFlag(forwarder->processor, val);
+bool forwarder_cs_get_serve(forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->serve_from_cs;
}
-bool forwarder_GetChacheStoreFlag(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return messageProcessor_GetCacheStoreFlag(forwarder->processor);
+void forwarder_cs_set_size(forwarder_t *forwarder, size_t size) {
+ assert(forwarder);
+
+ 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));
+ }
}
-void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- messageProcessor_SetCacheServeFlag(forwarder->processor, val);
+size_t forwarder_cs_get_size(forwarder_t *forwarder) {
+ assert(forwarder);
+ return pkt_cache_get_cs_size(forwarder->pkt_cache);
}
-bool forwarder_GetChacheServeFlag(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return messageProcessor_GetCacheServeFlag(forwarder->processor);
+size_t forwarder_cs_get_num_stale_entries(forwarder_t *forwarder) {
+ assert(forwarder);
+ return pkt_cache_get_num_cs_stale_entries(forwarder->pkt_cache);
}
-void forwarder_ReceiveCommand(Forwarder *forwarder, command_id command,
- struct iovec *message, unsigned ingressId) {
- configuration_ReceiveCommand(forwarder->config, command, message, ingressId);
+void forwarder_cs_clear(forwarder_t *forwarder) {
+ assert(forwarder);
+
+ pkt_cache_cs_clear(forwarder->pkt_cache);
}
-void forwarder_Receive(Forwarder *forwarder, Message *message) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
+/**
+ * @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);
- // this takes ownership of the message, so we're done here
+ switch (msgbuf_get_type(msgbuf)) {
+ case HICN_PACKET_TYPE_INTEREST:
+ forwarder->stats.countInterestsDropped++;
+ break;
- // 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.
- // 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));
+ case HICN_PACKET_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);
+
+ connection_t *conn = connection_table_get_by_id(table, conn_id);
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;
+ 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);
}
- if (message_HasWldr(message)) {
- if (connection_HasWldr(conn)) {
+ /* 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) == HICN_PACKET_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
+
+ // 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 */
+ if (!vector_contains(forwarder->pending_conn, conn_id))
+ vector_push(forwarder->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 HICN_PACKET_TYPE_INTEREST:
+ forwarder->stats.countInterestForwarded++;
+ break;
+
+ case HICN_PACKET_TYPE_DATA:
+ forwarder->stats.countObjectsForwarded++;
+ break;
+
+ default:
+ break;
+ }
+
+ TRACE("forward msgbuf %p (size=%u) to interface %u", msgbuf,
+ msgbuf_get_len(msgbuf), conn_id);
+ return msgbuf_get_len(msgbuf);
+}
+
+/**
+ * @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);
+
+ 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;
+}
+
+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 && entry && msgbuf_id_is_valid(msgbuf_id));
+
+ bool ret = true;
+
+ 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) == HICN_PACKET_TYPE_INTEREST);
+
+ fib_entry_t *fib_entry = fib_match_msgbuf(forwarder->fib, msgbuf);
+ if (!fib_entry) return false;
+
+ nexthops_t *nexthops = fib_entry_get_nexthops(fib_entry);
+
+ /* Backup flags and cur_len*/
+ uint_fast32_t flags = nexthops->flags;
+ size_t cur_len = nexthops_get_curlen(nexthops);
+
+ /* This affects the nexthops */
+ nexthops = strategy_lookup_nexthops(&fib_entry->strategy, nexthops, msgbuf);
+
+ if (nexthops_get_curlen(nexthops) == 0) {
+ ERROR("Message %p returned an empty next hop set", msgbuf);
+ ret = false;
+ goto END;
+ }
+
+ pit_entry_t *pit_entry = &entry->u.pit_entry;
+ if (!pit_entry) {
+ ret = false;
+ goto END;
+ }
+
+ 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)
+ 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) {
+ ERROR("Error forwarding mMessage %p to next hops", msgbuf);
+ ret = false;
+ }
+
+END:
+ /* Restore flags & curlen */
+ nexthops->flags = flags;
+ nexthops->cur_elts = cur_len;
+
+ return ret;
+}
+
+#endif /* ! BYPASS_FIB */
+
+int _forwarder_forward_upon_interest(
+ forwarder_t *forwarder, msgbuf_pool_t *msgbuf_pool, off_t data_msgbuf_id,
+ off_t interest_msgbuf_id, pkt_cache_entry_t *entry,
+ pkt_cache_verdict_t verdict, bool is_aggregated) {
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, interest_msgbuf_id);
+
+ // - Aggregation can be perfomed, do not forward
+ if (verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST) {
+ forwarder_drop(forwarder, interest_msgbuf_id);
+ return (int)msgbuf_get_len(msgbuf);
+ }
+
+ // - Data packet matching the interest was found, forward reply
+ 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));
+ return (int)msgbuf_get_len(msgbuf);
+ }
+
+ // - For aggregated interest, the interest forwarding is done in
+ // `_forwarder_forward_aggregated_interest()`
+ if (is_aggregated) return (int)msgbuf_get_len(msgbuf);
+
+ // - Try to forward the interest
+ int rc =
+ forwarder_forward_via_fib(forwarder, interest_msgbuf_id, verdict, entry);
+ if (!rc) {
+ // - Not able to forward, drop the packet
+ forwarder->stats.countDroppedNoRoute++;
+ INFO("Message %lu did not match FIB, no route (count %u)",
+ interest_msgbuf_id, forwarder->stats.countDroppedNoRoute);
+
+ forwarder_drop(forwarder, interest_msgbuf_id);
+ return -1;
+ }
+
+ return (int)msgbuf_get_len(msgbuf);
+}
+
+static void _forwarder_update_interest_stats(forwarder_t *forwarder,
+ pkt_cache_verdict_t verdict,
+ msgbuf_t *msgbuf,
+ bool has_expire_ts,
+ uint64_t expire_ts) {
+ long expiration = has_expire_ts ? expire_ts : -1;
+ switch (verdict) {
+ case PKT_CACHE_VERDICT_FORWARD_INTEREST:
+ DEBUG("Message added to PIT (expiration=%ld)", 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("Invalid packet cache content");
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * Return the interest manifest from the interest payload
+ */
+static int _forwarder_get_interest_manifest(
+ msgbuf_t *msgbuf, interest_manifest_header_t **int_manifest_header,
+ size_t *payload_size) {
+ uint8_t *payload;
+
+ hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf);
+
+ hicn_payload_type_t payload_type;
+ HICN_UNUSED(int rc) = hicn_packet_get_payload_type(pkbuf, &payload_type);
+ // XXX ASSERT HERE !!!
+ if (rc != HICN_LIB_ERROR_NONE) return -1;
+ // assert(rc == HICN_LIB_ERROR_NONE);
+
+ if (payload_type != HPT_MANIFEST) return -1;
+
+ rc = hicn_packet_get_payload(pkbuf, &payload, payload_size, false);
+ // assert(rc == HICN_LIB_ERROR_NONE);
+ if (rc != HICN_LIB_ERROR_NONE) return -1;
+
+ *int_manifest_header = (interest_manifest_header_t *)payload;
+
+ return 0;
+}
+
+// Manifest is split using splitting strategy, then every
+// sub-manifest is sent using the forwarding strategy defined for the prefix
+int _forwarder_forward_aggregated_interest(
+ forwarder_t *forwarder, interest_manifest_header_t *int_manifest_header,
+ msgbuf_t *msgbuf, off_t msgbuf_id, pkt_cache_entry_t **entries) {
+ assert(msgbuf_id_is_valid(msgbuf_id) &&
+ msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST);
+
+ int ret = -1;
+
+ fib_entry_t *fib_entry = fib_match_msgbuf(forwarder->fib, msgbuf);
+ if (!fib_entry) goto END;
+
+ nexthops_t *nexthops = fib_entry_get_nexthops(fib_entry);
+ if (nexthops_get_curlen(nexthops) == 0) {
+ ret = 0;
+ goto END;
+ }
+
+ /* Backup flags and cur_len*/
+ uint_fast32_t flags = nexthops->flags;
+ size_t cur_len = nexthops_get_curlen(nexthops);
+
+ size_t n_suffixes_per_split = configuration_get_suffixes_per_split(
+ forwarder_get_configuration(forwarder));
+ int_manifest_split_strategy_t disaggregation_strategy =
+ configuration_get_split_strategy(forwarder_get_configuration(forwarder));
+ switch (disaggregation_strategy) {
+ case INT_MANIFEST_SPLIT_STRATEGY_NONE:
+ n_suffixes_per_split = int_manifest_header->n_suffixes + 1;
+
+ case INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES: {
+ // Generate sub-manifests: same as original manifest,
+ // but different suffix in the header and different bitmap
+
+ int total_len = 0;
+ // Suffixes in manifest plus the one in the header
+ int total_suffixes = int_manifest_header->n_suffixes + 1;
+
+ // Save copy of original bitmap to use as a reference
+ // to generate bitmaps for sub-manifests
+ hicn_uword original_bitmap[BITMAP_SIZE] = {0};
+ memcpy(&original_bitmap, int_manifest_header->request_bitmap,
+ BITMAP_SIZE * sizeof(hicn_uword));
+
+ size_t suffix_index = 0; // Position of suffix in initial manifest
+ interest_manifest_header_t *manifest = NULL;
+ size_t payload_size;
+ while (suffix_index < total_suffixes) {
+ // If more than one sub-manifest,
+ // clone original interest manifest and update suffix
+ if (suffix_index > 0) {
+ msgbuf_t *clone;
+ off_t clone_id =
+ msgbuf_pool_clone(forwarder->msgbuf_pool, &clone, msgbuf_id);
+ msgbuf_pool_acquire(clone);
+ forwarder_acquired_msgbuf_ids_push(forwarder, clone_id);
+
+ msgbuf_id = clone_id;
+ msgbuf = clone;
+ }
+
+ hicn_uword curr_bitmap[BITMAP_SIZE] = {0};
+ size_t first_suffix_index_in_submanifest = suffix_index;
+ suffix_index = interest_manifest_update_bitmap(
+ original_bitmap, curr_bitmap, suffix_index, total_suffixes,
+ n_suffixes_per_split);
+ size_t first_suffix_index_in_next_submanifest = suffix_index;
+
+ // Update manifest bitmap in current msgbuf
+
+ int ret =
+ _forwarder_get_interest_manifest(msgbuf, &manifest, &payload_size);
+ _ASSERT(ret == 0);
+ memcpy(manifest->request_bitmap, curr_bitmap,
+ BITMAP_SIZE * sizeof(hicn_uword));
+ WITH_TRACE({
+ bitmap_print(manifest->request_bitmap, BITMAP_SIZE);
+ printf("\n");
+ });
+
+ /*
+ * Update PIT entries for suffixes in current sub-manifest.
+ *
+ * Note that strategy lookup affects the nexthops, and we need to
+ *restore the initial state before every lookup
+ */
+ nexthops->flags = flags;
+ nexthops->cur_elts = cur_len;
+ nexthops =
+ strategy_lookup_nexthops(&fib_entry->strategy, nexthops, msgbuf);
+
+ if (nexthops_get_curlen(nexthops) == 0) {
+ ERROR("Message %p returned an empty next hop set", msgbuf);
+ goto RESTORE;
+ }
+
+ for (size_t i = first_suffix_index_in_submanifest;
+ i < first_suffix_index_in_next_submanifest; i++) {
+ if (!bitmap_is_set_no_check(manifest->request_bitmap, i)) continue;
+
+ pit_entry_t *pit_entry = &(entries[i]->u.pit_entry);
+ if (!pit_entry) goto RESTORE;
+
+ pit_entry_set_fib_entry(pit_entry, fib_entry);
+ nexthops_foreach(nexthops, nexthop,
+ { pit_entry_egress_add(pit_entry, nexthop); });
+ }
+
+ // Serialize manifest before sending it
+ interest_manifest_serialize(int_manifest_header);
+
+ if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <=
+ 0) {
+ ERROR("Message %p returned an empty next hop set", msgbuf);
+ continue;
+ }
+
+ total_len += msgbuf_get_len(msgbuf);
+ }
+
+ ret = total_len;
+ goto END;
+ }
+
+ default:
+ break;
+ }
+
+RESTORE:
+ /* Restore flags & curlen */
+ nexthops->flags = flags;
+ nexthops->cur_elts = cur_len;
+
+END:
+ return ret;
+}
+
+static ssize_t forwarder_process_single_interest(forwarder_t *forwarder,
+ msgbuf_pool_t *msgbuf_pool,
+ msgbuf_t *msgbuf,
+ off_t msgbuf_id) {
+ pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
+ off_t data_msgbuf_id = INVALID_MSGBUF_ID;
+ pkt_cache_entry_t *entry = NULL;
+
+ // Update packet cache
+ pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, &verdict,
+ &data_msgbuf_id, &entry, msgbuf_get_name(msgbuf),
+ forwarder->serve_from_cs);
+
+ _forwarder_update_interest_stats(forwarder, verdict, msgbuf,
+ entry->has_expire_ts, entry->expire_ts);
+
+ int rc = _forwarder_forward_upon_interest(
+ forwarder, msgbuf_pool, data_msgbuf_id, msgbuf_id, entry, verdict, false);
+
+ // No route when trying to forward interest, remove from PIT
+ if (rc == -1) pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry);
+
+ return msgbuf_get_len(msgbuf);
+}
+
+static ssize_t forwarder_process_aggregated_interest(
+ forwarder_t *forwarder, interest_manifest_header_t *int_manifest_header,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf, off_t msgbuf_id) {
+ pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
+ off_t data_msgbuf_id = INVALID_MSGBUF_ID;
+ pkt_cache_entry_t *entry = NULL;
+ // Save PIT entries to avoid re-doing pkt cache lookup in
+ // `_forwarder_forward_aggregated_interest()`
+ pkt_cache_entry_t *entries[BITMAP_SIZE * WORD_WIDTH];
+
+ int n_suffixes_to_fwd = 0;
+
+ hicn_name_t name_copy = HICN_NAME_EMPTY;
+ hicn_name_copy(&name_copy, msgbuf_get_name(msgbuf));
+
+ // Suffixes in interest manifest also contains suffix in main name. We can
+ // then just iterate the interest manifest and update the suffix in the name
+ // struct
+ hicn_name_suffix_t *suffix;
+ unsigned long pos;
+ interest_manifest_foreach_suffix(int_manifest_header, suffix, pos) {
+ // Update name
+ hicn_name_set_suffix(&name_copy, *suffix);
+
+ // Update packet cache
+ pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id,
+ &verdict, &data_msgbuf_id, &entry, &name_copy,
+ forwarder->serve_from_cs);
+
+ entries[pos] = entry;
+ _forwarder_update_interest_stats(forwarder, verdict, msgbuf,
+ entry->has_expire_ts, entry->expire_ts);
+
+ // Here only data forwarding is performed, interest forwarding is done
+ // in '_forwarder_forward_aggregated_interest()'
+ int rc =
+ _forwarder_forward_upon_interest(forwarder, msgbuf_pool, data_msgbuf_id,
+ msgbuf_id, entry, verdict, true);
+
+ // No route when trying to forward interest, remove from PIT
+ if (rc == -1) pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry);
+
+ // Unset in bitmap if no interest forwarding needed,
+ // otherwise increase count of suffixes to forward
+ if (rc == -1 || verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST ||
+ verdict == PKT_CACHE_VERDICT_FORWARD_DATA) {
+ bitmap_unset_no_check(int_manifest_header->request_bitmap, pos);
+ } else {
+ n_suffixes_to_fwd++;
+ }
+
+ WITH_DEBUG({
+ char buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, &name_copy);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "(error)");
+ DEBUG("Next in manifest: %s", buf);
+ });
+ }
+
+ // Return if nothing in the manifest to forward
+ if (n_suffixes_to_fwd == 0) return msgbuf_get_len(msgbuf);
+
+ return _forwarder_forward_aggregated_interest(forwarder, int_manifest_header,
+ msgbuf, msgbuf_id, entries);
+}
+
+/**
+ * @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);
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *conn =
+ connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
+
+ assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST);
+
+ u32 n_suffixes = 0;
+ interest_manifest_header_t *int_manifest_header = NULL;
+ size_t payload_size;
+ int ret = _forwarder_get_interest_manifest(msgbuf, &int_manifest_header,
+ &payload_size);
+ if (ret == 0) {
+ // Deserialize intrest manifest
+ interest_manifest_deserialize(int_manifest_header);
+
+ if (!interest_manifest_is_valid(int_manifest_header, payload_size))
+ return -1;
+
+ n_suffixes = int_manifest_header->n_suffixes;
+ }
+
+ // Update stats
+ forwarder->stats.countInterestsReceived++;
+ conn->stats.interests.rx_pkts++;
+ conn->stats.interests.rx_bytes += msgbuf_get_len(msgbuf);
+
+ WITH_DEBUG({
+ char buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf));
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "(error)");
+ DEBUG("INTEREST (%s) msgbuf_id=%lu ingress=%u length=%u", buf, msgbuf_id,
+ msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf));
+ DEBUG("INTEREST (%s) suffixes=%u msgbuf_id=%lu ingress=%u length=%u", buf,
+ n_suffixes, msgbuf_id, msgbuf_get_connection_id(msgbuf),
+ msgbuf_get_len(msgbuf));
+ });
+
+ // Cache suffixes for current prefix to (possibly) avoid double lookups
+ pkt_cache_save_suffixes_for_prefix(
+ forwarder->pkt_cache, hicn_name_get_prefix(msgbuf_get_name(msgbuf)));
+
+ if (ret == -1)
+ return forwarder_process_single_interest(forwarder, msgbuf_pool, msgbuf,
+ msgbuf_id);
+ return forwarder_process_aggregated_interest(forwarder, int_manifest_header,
+ msgbuf_pool, msgbuf, msgbuf_id);
+}
+
+static void _forwarder_log_on_data(forwarder_t *forwarder,
+ 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("Invalid packet cache content");
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @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 buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf));
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "(error)");
+ DEBUG("DATA (%s) msgbuf_id=%lu ingress=%u length=%u", buf, msgbuf_id,
+ msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf));
+ });
+
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *conn =
+ connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
+
+ // Update stats
+ forwarder->stats.countObjectsReceived++;
+ conn->stats.data.rx_pkts++;
+ conn->stats.data.rx_bytes += msgbuf_get_len(msgbuf);
+
+ // Cache suffixes for current prefix to (possibly) avoid double lookups
+ pkt_cache_save_suffixes_for_prefix(
+ forwarder->pkt_cache, hicn_name_get_prefix(msgbuf_get_name(msgbuf)));
+
+ pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
+ bool wrong_egress;
+ nexthops_t *ingressSetUnion = pkt_cache_on_data(
+ forwarder->pkt_cache, msgbuf_pool, msgbuf_id, forwarder->store_in_cs,
+ connection_is_local(conn), &wrong_egress, &verdict);
+
+ _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);
+
+ // NOTE : probes are not stored in PIT
+ if (msgbuf_is_probe(msgbuf)) {
+ fib_entry_t *entry = fib_match_msgbuf(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());
+ }
+ }
+ 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_flush_connections(forwarder_t *forwarder) {
+ // DEBUG("[forwarder_flush_connections]");
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
+
+ unsigned num_pending_conn = (unsigned)vector_len(forwarder->pending_conn);
+ for (unsigned i = 0; i < num_pending_conn; i++) {
+ unsigned conn_id = forwarder->pending_conn[i];
+ 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...
+ }
+ }
+ vector_reset(forwarder->pending_conn);
+ // DEBUG("[forwarder_flush_connections] done");
+}
+
+#if WITH_WLDR
+// 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 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
+ 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);
}
+#endif
-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,
+ hicn_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 = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) return false;
+
+ INFO("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");
+ 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);
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len,
+ &name_prefix);
+ fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix);
+ if (!entry) {
+ entry = fib_entry_create(&name_prefix, strategy_type, NULL, forwarder);
+ if (ingress_id != INVALID_FACE_ID)
+ fib_entry_nexthops_add(entry, ingress_id);
+ entry = fib_add(forwarder->fib, entry);
- return res;
+ } else {
+ if (ingress_id != INVALID_FACE_ID)
+ fib_entry_nexthops_add(entry, ingress_id);
+ }
+
+ forwarder_on_route_event(forwarder, entry);
+
+ return true;
}
+bool forwarder_remove_route(forwarder_t *forwarder, hicn_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");
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len,
+ &name_prefix);
+ 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,
+ hicn_ip_prefix_t *prefix,
+ hicn_policy_t *policy) {
+ assert(forwarder);
+ assert(prefix);
+ assert(policy);
+
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len,
+ &name_prefix);
+ fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix);
+ if (!entry) return false;
- return messageProcessor_AddOrUpdatePolicy(forwarder->processor, control);
+ 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, hicn_ip_prefix_t *prefix) {
+ assert(forwarder);
+ assert(prefix);
+
+ hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY;
+ hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len,
+ &name_prefix);
+ fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix);
+ if (!entry) return false;
- return messageProcessor_RemovePolicy(forwarder->processor, control);
+ fib_entry_set_policy(entry, POLICY_EMPTY);
+
+ 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(const forwarder_t *forwarder,
+ unsigned connection_id) {
+ fib_entry_t **removed_entries = NULL;
+ size_t num_removed_entries;
+
+ assert(forwarder);
+
+ fib_remove_connection(forwarder->fib, connection_id, &removed_entries,
+ &num_removed_entries);
+
+ if (num_removed_entries > 0) {
+ assert(removed_entries);
+
+ for (int i = 0; i < num_removed_entries; i++) {
+ fib_entry_t *entry = removed_entries[i];
+ forwarder_on_route_event(forwarder, entry);
+ fib_remove_entry(forwarder->fib, entry);
+ }
+ free(removed_entries);
+ }
}
-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,
+ hicn_prefix_t *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));
- processor_SetStrategy(forwarder->processor, prefix, strategy,
- related_prefixes_len, related_prefixes);
+ fib_entry_t *entry = fib_contains(forwarder->fib, name_prefix);
+ if (!entry) return;
+
+ 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, hicn_prefix_t *prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options) {
+ assert(forwarder);
+ assert(prefix);
+ assert(STRATEGY_TYPE_VALID(strategy_type));
+ /* strategy_options might be NULL */
+
+ fib_entry_t *entry = fib_contains(forwarder->fib, 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_prefix(forwarder->fib, 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);
+// IMPORTANT: Use this function ONLY for read-only operations since a
+// realloc would otherwise modify the returned copy but not the original
+// msgbuf ids vector in the forwarder. This constraint cannot be enforced
+// by returning a (const off_t *) because the vector_t macros still cast
+// to (void **).
+off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder) {
+ return forwarder->acquired_msgbuf_ids;
}
-PARCClock *forwarder_GetClock(const Forwarder *forwarder) {
- return forwarder->clock;
+void forwarder_acquired_msgbuf_ids_reset(const forwarder_t *forwarder) {
+ vector_reset(forwarder->acquired_msgbuf_ids);
}
-#if !defined(__APPLE__)
-hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder) {
- return forwarder->hicnSocketHelper;
+void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder,
+ off_t msgbuf_id) {
+ vector_push(forwarder->acquired_msgbuf_ids, msgbuf_id);
}
-#endif
// =======================================================
-static void _signal_cb(int sig, PARCEventType events, void *user_data) {
- Forwarder *forwarder = (Forwarder *)user_data;
+fib_t *forwarder_get_fib(const forwarder_t *forwarder) {
+ return forwarder->fib;
+}
+
+msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder) {
+ return forwarder->msgbuf_pool;
+}
+
+mapme_t *forwarder_get_mapme(const forwarder_t *forwarder) {
+ return forwarder->mapme;
+}
+
+#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 */
+
+/**
+ * @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);
+}
- logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning,
- __func__, "signal %d events %d", sig, events);
+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);
+
+ hicn_name_t name;
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ assert(msgbuf);
+
+ size_t size = msgbuf_get_len(msgbuf);
+
+ const connection_table_t *table =
+ forwarder_get_connection_table(listener->forwarder);
+
+ /* Connection lookup */
+ if (msgbuf_get_connection_id(msgbuf) == CONNECTION_ID_UNDEFINED) {
+ connection_t *connection = connection_table_get_by_pair(table, pair);
+ unsigned conn_id =
+ connection
+ ? (unsigned)connection_table_get_connection_id(table, connection)
+ : CONNECTION_ID_UNDEFINED;
+
+ assert((conn_id != CONNECTION_ID_UNDEFINED) || listener);
+ msgbuf->connection_id = conn_id;
+ }
- switch ((int)sig) {
- case SIGTERM:
- logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning,
- __func__, "Caught an terminate signal; exiting cleanly.");
- dispatcher_Stop(forwarder->dispatcher);
+ forwarder->stats.countReceived++;
+
+ /* Initialize packet buffer stored in msgbuf through libhicn */
+ msgbuf_initialize_from_packet(msgbuf);
+
+ /* Detect packet type */
+ hicn_packet_analyze(msgbuf_get_pkbuf(msgbuf));
+
+ msgbuf->recv_ts = now;
+
+RETRY:
+
+ switch (msgbuf_get_type(msgbuf)) {
+ case HICN_PACKET_TYPE_INTEREST:
+ if (!connection_id_is_valid(msgbuf->connection_id)) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(table, conn_name);
+ if (rc < 0) {
+ ERROR("Could not create name for new connection");
+ goto DROP;
+ }
+
+ unsigned connection_id =
+ listener_create_connection(listener, conn_name, pair);
+ if (connection_id == CONNECTION_ID_UNDEFINED) {
+ ERROR("Could not create new connection");
+ goto DROP;
+ }
+ msgbuf->connection_id = connection_id;
+ }
+ msgbuf->path_label = 0; // not used for interest packets
+ hicn_interest_get_name(msgbuf_get_pkbuf(msgbuf), &name);
+ msgbuf_set_name(msgbuf, &name);
+#ifdef WITH_WLDR
+ forwarder_apply_wldr(forwarder, msgbuf, connection);
+#endif /* WITH_WLDR */
+ forwarder_process_interest(forwarder, msgbuf_id);
+
+ pkt_cache_log(forwarder->pkt_cache);
break;
- case SIGINT:
- logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning,
- __func__, "Caught an interrupt signal; exiting cleanly.");
- dispatcher_Stop(forwarder->dispatcher);
+ case HICN_PACKET_TYPE_DATA:
+ /* This include probes */
+ if (!connection_id_is_valid(msgbuf->connection_id)) {
+ ERROR("Invalid connection for data packet");
+ goto DROP;
+ }
+ msgbuf_init_pathlabel(msgbuf);
+ hicn_data_get_name(msgbuf_get_pkbuf(msgbuf), &name);
+ msgbuf_set_name(msgbuf, &name);
+#ifdef WITH_WLDR
+ forwarder_apply_wldr(forwarder, msgbuf, connection);
+#endif /* WITH_WLDR */
+ forwarder_process_data(forwarder, msgbuf_id);
+
+ pkt_cache_log(forwarder->pkt_cache);
break;
-#ifndef _WIN32
- case SIGUSR1:
- // dump stats
+
+#ifdef WITH_WLDR
+ case HICN_PACKET_TYPE_WLDR_NOTIFICATION:
+ if (!connection_id_is_valid(msgbuf->connection_id)) {
+ ERROR("Invalid connection for WLDR packet");
+ goto DROP;
+ }
+ connection_t *connection =
+ connection_table_get_by_id(table, msgbuf->connection_id);
+ connection_wldr_handle_notification(connection, msgbuf);
break;
#endif
- default:
+ case HICN_PACKET_TYPE_MAPME:
+ INFO("Received MAP-Me packet");
+ if (!connection_id_is_valid(msgbuf->connection_id)) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(table, conn_name);
+ if (rc < 0) {
+ ERROR("Could not create name for new connection");
+ goto DROP;
+ }
+
+ unsigned connection_id =
+ listener_create_connection(listener, conn_name, pair);
+ if (connection_id == CONNECTION_ID_UNDEFINED) {
+ ERROR("Could not create new connection");
+ goto DROP;
+ }
+ INFO("Created connection upon MAP-Me packet");
+ msgbuf->connection_id = connection_id;
+ }
+ mapme_process(forwarder->mapme, msgbuf);
break;
- }
-}
-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
-}
+ case HICN_PACKET_TYPE_COMMAND:
+ // Create the connection to send the ack back
+ if (!connection_id_is_valid(msgbuf->connection_id)) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(table, conn_name);
+ if (rc < 0) {
+ ERROR("Could not create name for new connection");
+ goto DROP;
+ }
+
+ unsigned connection_id =
+ listener_create_connection(listener, conn_name, pair);
+ if (connection_id == CONNECTION_ID_UNDEFINED) {
+ ERROR("Could not create new connection");
+ goto DROP;
+ }
+ msgbuf->connection_id = connection_id;
+ }
+
+ msg_header_t *msg = (msg_header_t *)msgbuf_get_packet(msgbuf);
+ msgbuf->command.type = msg->header.command_id;
+ if (!command_type_is_valid(msgbuf->command.type)) {
+ ERROR("Invalid command %d", msgbuf->command.type);
+ goto DROP;
+ }
+
+ /*
+ * We need to retrieve the connection (in case it is useful) before
+ * proceeding through the removal
+ */
+ connection_t *connection =
+ connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
+ size = command_process_msgbuf(forwarder, msgbuf);
+ if (msgbuf->command.type == COMMAND_TYPE_CONNECTION_REMOVE)
+ _forwarder_finalize_connection_if_self(connection, msgbuf);
+ return size;
-#ifdef WITH_MAPME
-FIB *forwarder_getFib(Forwarder *forwarder) {
- return messageProcessor_getFib(forwarder->processor);
-}
+ default:
+ /* Commands are not recognized by the packet parser */
+ if (msgbuf_is_command(msgbuf)) {
+ msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND);
+ goto RETRY;
+ }
+ goto DROP;
+ }
-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 */
-}
+ return size;
-void forwarder_ProcessMapMe(Forwarder *forwarder, const uint8_t *msgBuffer,
- unsigned conn_id) {
- mapme_Process(forwarder->mapme, msgBuffer, conn_id);
+DROP:
+ 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 */
+forwarder_stats_t forwarder_get_stats(forwarder_t *forwarder) {
+ return forwarder->stats;
+}
diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h
index d1815b7d4..b7ce5ff4d 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-2022 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -18,292 +18,241 @@
* 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);
+void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port);
-/**
- * @function forwarder_GetNextConnectionId
- * @abstract Get the next identifier for a new connection
- */
-unsigned forwarder_GetNextConnectionId(Forwarder *forwarder);
+configuration_t *forwarder_get_configuration(forwarder_t *forwarder);
-Messenger *forwarder_GetMessenger(Forwarder *forwarder);
-
-Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder);
+subscription_table_t *forwarder_get_subscriptions(const 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(const 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);
+pkt_cache_t *forwarder_get_pkt_cache(const forwarder_t *forwarder);
-/**
- * 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);
+void forwarder_cs_set_store(forwarder_t *forwarder, bool val);
+
+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_ReceiveCommand(Forwarder *forwarder, command_id command,
- struct iovec *message, unsigned ingressId);
+void forwarder_cs_set_size(forwarder_t *forwarder, size_t size);
-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,
+ hicn_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, hicn_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,
+ hicn_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, hicn_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(const 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,
+ hicn_prefix_t *name_prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options);
+
+void forwarder_set_strategy(forwarder_t *forwarder, hicn_prefix_t *prefix,
+ strategy_type_t strategy_type,
+ strategy_options_t *strategy_options);
-FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder);
+cs_t *forwarder_get_cs(const forwarder_t *forwarder);
+
+off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder);
/**
- * Sets the maximum number of content objects in the content store
- *
- * Implementation dependent - may wipe the cache.
+ * @note Acquire msgbuf ids vector ONLY for read-only operations.
*/
-void forwarder_SetContentObjectStoreSize(Forwarder *forwarder,
- size_t maximumContentStoreSize);
-
-void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val);
+off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder);
-bool forwarder_GetChacheStoreFlag(Forwarder *forwarder);
+void forwarder_acquired_msgbuf_ids_reset(const forwarder_t *forwarder);
-void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val);
+void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder,
+ off_t msgbuf_id);
-bool forwarder_GetChacheServeFlag(Forwarder *forwarder);
+/**
+ * @brief Returns the forwarder's FIB.
+ * @param[in] forwarder - Pointer to the forwarder.
+ * @returns Pointer to the hICN FIB.
+ */
+fib_t *forwarder_get_fib(const forwarder_t *forwarder);
-void forwarder_ClearCache(Forwarder *forwarder);
+/**
+ * @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.
+ */
+msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *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
-/**
- * @function forwarder_getFib
- * @abstract Returns the hICN forwarder's FIB.
- * @param [in] forwarder - Pointer to the hICN forwarder.
- * @returns Pointer to the hICN FIB.
- */
-FIB *forwarder_getFib(Forwarder *forwarder);
+void forwarder_on_route_event(const forwarder_t *forwarder, fib_entry_t *entry);
+
+int forwarder_add_connection(const forwarder_t *forwarder,
+ const char *symbolic_name, face_type_t type,
+ address_pair_t *pair, policy_tags_t tags,
+ int priority, face_state_t admin_state);
+
+int forwarder_remove_connection(const forwarder_t *forwarder,
+ unsigned connection_id, bool finalize);
/**
- * @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);
+
+forwarder_stats_t forwarder_get_stats(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..d2f547863
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 "../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 =
+ (unsigned int)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,
+ CONNECTION_ID_UNDEFINED, 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);
+
+ /* initialized so that gcc-9 does not complain */
+ face_type_t connection_type = FACE_TYPE_UNDEFINED;
+ 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;
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UNDEFINED:
+ case FACE_TYPE_N:
+ return CONNECTION_ID_UNDEFINED;
+ }
+
+#ifdef USE_CONNECTED_SOCKETS
+ /*
+ * 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.
+ */
+ int fd = listener_get_socket(listener, address_pair_get_local(pair),
+ address_pair_get_remote(pair),
+ listener->interface_name);
+ if (fd < 0) return CONNECTION_ID_UNDEFINED;
+#else
+ int fd = 0; // means listener->fd;
+#endif
+ bool local = address_is_local(address_pair_get_local(pair));
+
+ connection_table_t *table =
+ forwarder_get_connection_table(listener->forwarder);
+ connection_t *connection =
+ connection_table_allocate(table, pair, connection_name);
+ unsigned connection_id =
+ (unsigned int)connection_table_get_connection_id(table, connection);
+
+ 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);
+ })
+
+ forwarder_on_connection_event(listener->forwarder, connection,
+ CONNECTION_EVENT_CREATE);
+
+ 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,
+ unsigned connection_id) {
+ 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);
+ msgbuf_set_connection_id(msgbuf, connection_id);
+
+ // 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,
+ unsigned connection_id) {
+ assert(listener);
+
+ size_t total_processed_bytes = 0;
+ ssize_t num_msg_received = 0;
+
+ forwarder_t *forwarder = listener->forwarder;
+ msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ forwarder_acquired_msgbuf_ids_reset(forwarder);
+
+ /* Receive messages in the loop as long as we manage to fill the buffers */
+ do {
+ /* 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]);
+ msgbuf_set_connection_id(msgbufs[i], connection_id);
+ forwarder_acquired_msgbuf_ids_push(forwarder, 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);
+
+ const off_t *acquired_msgbuf_ids =
+ forwarder_get_acquired_msgbuf_ids(forwarder);
+ for (int i = 0; i < vector_len(acquired_msgbuf_ids); i++) {
+ msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, acquired_msgbuf_ids[i]);
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+ }
+
+ 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,
+ unsigned connection_id, void *user_data) {
+ assert(listener);
+ assert(!user_data);
+
+ /*
+ * 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, connection_id);
+
+ return listener_read_single(listener, fd, connection_id);
+}
+
+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);
+}
diff --git a/hicn-light/src/hicn/core/listener.h b/hicn-light/src/hicn/core/listener.h
new file mode 100644
index 000000000..76d865c5d
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <hicn/base/loop.h>
+
+#define LISTENER_ID_UNDEFINED ~0
+
+struct forwarder_s;
+
+typedef struct {
+ address_t address;
+ face_type_t type;
+} listener_key_t;
+
+static inline int listener_key_equals(const listener_key_t *key1,
+ const listener_key_t *key2) {
+ return address_equals(&key1->address, &key2->address) &&
+ (key1->type == key2->type);
+}
+
+/**
+ * @brief Create a listener key starting from an address and a face type.
+ *
+ * @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,
+ unsigned connection_id);
+ssize_t listener_read_batch(listener_t *listener, int fd,
+ unsigned connection_id);
+
+/**
+ * @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,
+ unsigned connection_id, 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..4a0f74a13
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener_table.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.
+ */
+
+/**
+ * \file listener_table.c
+ * \brief Implementation of hICN listener table
+ */
+
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.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
+
+typedef struct {
+ char name[SYMBOLIC_NAME_LEN];
+} name_key_t;
+
+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->name_keys = slab_create(name_key_t, SLAB_INIT_SIZE);
+ table->id_by_key = kh_init_lt_key();
+ table->listener_keys = slab_create(listener_key_t, SLAB_INIT_SIZE);
+
+ /*
+ * 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) {
+ unsigned listener_id;
+ kh_foreach_value(table->id_by_key, listener_id, {
+ listener_t *listener = listener_table_get_by_id(table, listener_id);
+ const char *name = listener_get_name(listener);
+ INFO("Removing listener %s [%d]", name, listener->fd);
+ listener_finalize(listener);
+ });
+
+ kh_destroy_lt_name(table->id_by_name);
+ slab_free(table->name_keys);
+ kh_destroy_lt_key(table->id_by_key);
+ slab_free(table->listener_keys);
+
+ pool_free(table->listeners);
+ free(table);
+}
+
+listener_t *listener_table_allocate(const listener_table_t *table,
+ const listener_key_t *key,
+ const char *name) {
+ listener_t *listener = NULL;
+ pool_get(table->listeners, listener);
+ if (!listener) return NULL;
+
+ off_t id = listener - table->listeners;
+ int rc;
+
+ // Add in name hash table
+ name_key_t *name_copy = slab_get(name_key_t, table->name_keys);
+ strcpy_s(name_copy->name, sizeof(name_key_t), name);
+
+ khiter_t k = kh_put_lt_name(table->id_by_name, name_copy->name, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_name, k) = (unsigned int)id;
+
+ // Add in key hash table
+ listener_key_t *key_copy = slab_get(listener_key_t, table->listener_keys);
+ memcpy(key_copy, key, sizeof(listener_key_t));
+
+ k = kh_put_lt_key(table->id_by_key, key_copy, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_key, k) = (unsigned int)id;
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_key));
+ return listener;
+}
+
+void listener_table_deallocate(const listener_table_t *table,
+ listener_t *listener) {
+ const char *name = listener_get_name(listener);
+ listener_key_t *key = listener_get_key(listener);
+
+ // Remove from name hash table
+ khiter_t k = kh_get_lt_name(table->id_by_name, name);
+ assert(k != kh_end(table->id_by_name));
+ kh_del_lt_name(table->id_by_name, k);
+ slab_put(table->name_keys, kh_key(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));
+ kh_del_lt_key(table->id_by_key, k);
+ slab_put(table->listener_keys, kh_key(table->id_by_key, k));
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_key));
+ pool_put(table->listeners, listener);
+}
+
+listener_t *listener_table_get_by_address(listener_table_t *table,
+ face_type_t type,
+ const address_t *address) {
+ 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 =
+ (unsigned int)listener_table_get_id_by_name(table, name);
+ if (!listener_id_is_valid(listener_id)) return NULL;
+ return listener_table_at(table, listener_id);
+}
+
+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);
+ })
+}
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..062d1748e
--- /dev/null
+++ b/hicn-light/src/hicn/core/listener_table.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <hicn/util/khash.h>
+#include <hicn/util/hash.h>
+#include <hicn/util/slab.h>
+#include "address.h"
+#include "listener.h"
+#include <hicn/util/pool.h>
+
+/* Hash functions for indices */
+#define key_hash(key) (hash_struct(key))
+
+/* Hash table types for indices */
+KHASH_MAP_INIT_STR(lt_name, unsigned);
+KHASH_INIT(lt_key, const listener_key_t *, unsigned, 1, key_hash,
+ listener_key_equals);
+
+typedef struct {
+ size_t max_size;
+
+ kh_lt_key_t *id_by_key;
+ slab_t *listener_keys;
+ kh_lt_name_t *id_by_name;
+ slab_t *name_keys;
+
+ 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.
+ */
+listener_t *listener_table_allocate(const listener_table_t *table,
+ const listener_key_t *key,
+ const char *name);
+
+/**
+ * @brief Deallocate a listener and return it to the listener table pool.
+ *
+ * @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.
+ */
+void listener_table_deallocate(const listener_table_t *table,
+ listener_t *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) \
+ do { \
+ listener_t *listener; \
+ (void)listener; \
+ pool_foreach( \
+ table->listeners, listener, do { BODY } while (0)); \
+ } 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..acda2b8cd 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-2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.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,739 +116,779 @@
#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_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 */
+
+ /*
+ * 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 *forwarder;
+ 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, unsigned id, void *data);
- /* Internal state : set default values */
- memcpy(*mapme, &MapMeDefault, sizeof(MapMe));
+mapme_t *mapme_create(void *forwarder) {
+ mapme_t *mapme = malloc(sizeof(mapme_t));
+ if (!mapme) return NULL;
- (*mapme)->forwarder = forwarder;
-
- /* 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;
-static MapMeTFIB *mapmeTFIB_Create() {
- MapMeTFIB *tfib;
- tfib = malloc(sizeof(MapMeTFIB));
- if (!tfib) goto ERR_MALLOC;
+#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;
+
+ // 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);
-
- tfib = mapmeTFIB_Create();
- fibEntry_setUserData(fibEntry, mapme, tfib, (void (*)(const void*, void**))mapmeTFIB_Release);
-}
+static void mapme_create_tfib(const mapme_t *mapme, fib_entry_t *entry) {
+ mapme_tfib_t *tfib;
-#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);
+/**
+ * @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_get_type_from_heuristic(const mapme_t *mapme,
+ fib_entry_t *entry) {
+#if 0
+ if (!entry) return UPDATE;
+ if (fib_entry_has_local_nexthop(entry))
+ /* We are a producer for this entry, send update */
+ return UPDATE;
+#else /* Always send IU */
+ return UPDATE;
+#endif
}
-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);
- }
+/**
+ *
+ * Here nexthops is not necessarily FIB nexthops as we might advertise given FIB
+ * entries on various other connections.
+ *
+ * prefix can be specified to send an update for a More Specific Prefix (MSP),
+ * or left NULL for the default behaviour. Note there will be no support for
+ * retransmission for MSP.
+ *
+ * NOTES:
+ * - if the face is pending an we receive an IN, maybe we should not cancel the
+ * timer
+ * - this function should never be called for Notifications.
+ */
+int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry,
+ const nexthops_t *nexthops,
+ const hicn_prefix_t *prefix) {
+ INFO("mapme send to nexthops");
+ const hicn_prefix_t *mapme_prefix;
+ uint32_t mapme_seq;
+
+ assert(!!prefix ^ !!entry);
+
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
}
- 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);
+ if (prefix) {
+ INFO("mapme with given prefix");
+ mapme_prefix = prefix;
+ mapme_seq = 1;
+ } else {
+ INFO("mapme wih fib entry prefix");
+ mapme_tfib_t *tfib = TFIB(entry);
+ if (tfib == NULL) {
+ mapme_create_tfib(mapme, entry);
+ tfib = TFIB(entry);
}
- 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;
- nameBitvector_ToIPAddress(bv, &ip_prefix);
- /* The name length will be equal to ip address' prefix length */
- 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;
+ mapme_prefix = fib_entry_get_prefix(entry);
+ mapme_seq = tfib->seq;
}
-
- 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;
+ char prefix_s[MAXSZ_IP_PREFIX];
+ int rc = hicn_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, mapme_prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) NULL;
+
+ INFO("mapme send to nexthops prefix= %s", prefix_s);
+
+ WITH_INFO({
+ char buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, mapme_prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "(error)");
+ INFO("sending IU/IN for name %s on nexthops", buf);
+ })
+
+ mapme_params_t params = {.protocol = mapme->protocol,
+ .type = mapme_get_type_from_heuristic(mapme, entry),
+ .seq = mapme_seq};
+
+ uint8_t packet[MTU];
+ size_t size = hicn_mapme_create_packet(packet, mapme_prefix, &params);
+ if (size <= 0) {
+ ERROR("Could not create MAP-Me packet");
+ return -1;
}
- // hicn_packet_dump(icmp_pkt, MAPME_HDRLEN);
+ connection_table_t *table = forwarder_get_connection_table(mapme->forwarder);
- return message_CreateFromByteArray(NO_INGRESS, icmp_pkt,
- MessagePacketType_Interest, now, logger);
+ nexthops_foreach(nexthops, nexthop, {
+ const connection_t *conn = connection_table_get_by_id(table, nexthop);
+ assert(!connection_is_local(conn));
+ connection_send_packet(conn, packet, size);
+ });
-ERR_CREATE:
- parcMemory_Deallocate(&icmp_pkt);
-ERR_NAME:
- return NULL;
+ return 0;
}
-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;
+#if 0
+/**
+ *
+ * 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;
}
- 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);
+ /* Detect change */
+ if (!fib_entry_nexthops_changed(fib_entry)) {
+ INFO("No change in nexthops");
+ return;
+ }
+ fib_entry_set_prev_nexthops(fib_entry);
- 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);
+ mapme_send_to_nexthops(mapme, fib_entry, nexthops);
}
-
-/**
- * @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) {
-#if 0 /* interplay of IU/IN */
- if (TFIB(fibEntry)->lastAckedUpdate == 0) {
- return UPDATE;
- } else {
- Ticks interval = now - TFIB(fibEntry)->lastAckedUpdate;
- return (T2NS(interval) > MS2NS(mapme->Tu)) ? 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;
+/******************************************************************************
+ * MAPME API
+ ******************************************************************************/
- INFO(mapme, "[MAP-Me] SetFacePending connection=%d prefix=XX retx=%d",
- conn_id, num_retx);
+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;
+ }
- /* 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;
+ /* Apply the policy of the fib_entry over all neighbours */
+ nexthops_t new_nexthops = NEXTHOPS_EMPTY;
+ nexthops_t *nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops);
- /* Safeguard during retransmissions */
- if (!TFIB(fibEntry))
- return true;
+ /* We set force to true to avoid overriding the FIB cache */
+ return mapme_set_adjacencies(mapme, entry, nexthops, NULL);
+}
+// XXX this will change with the FIB cache
+// XXX we are sometimes incrementing tfib seq for nothing
+int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ nexthops_t *nexthops, const hicn_prefix_t *prefix) {
+ INFO("mapme set adjacenies");
/*
- * On the producer side, we have to clear the TFIB everytime we change the list
- * of adjacencies, otherwise retransmissions will occur to preserve them.
+ * - entry is provided in case of a producer reannouncement
+ * - prefix is provided for control plane triggered updates
*/
- 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) {
-
- NumberSet * conns = numberSet_Create();
-
- 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);
-
- for (size_t i = 0; i < numberSet_Length(conns); i++) {
- unsigned conn_id = numberSet_GetItem(conns, i);
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_id);
- }
+ assert(!!prefix ^ !!entry);
- numberSet_Release(&conns);
- }
+ if (mapme->enabled == false) {
+ WARN("MAP-Me is NOT enabled");
+ return -1;
}
- // 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;
- }
+ if (entry) {
+ /* Check disabled, we need to be able to send an update for a larger prefix
+ * that the one being served.
+ */
+ // if (!fib_entry_has_local_nexthop(entry)) return -1;
- 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;
+ mapme_tfib_t *tfib = TFIB(entry);
+ if (tfib == NULL) {
+ mapme_create_tfib(mapme, entry);
+ tfib = TFIB(entry);
}
- } else {
- INFO(mapme, "[MAP-Me] - not forwarding as send is False");
- timer = NULL;
- }
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_id);
- mapmeTFIB_Put(TFIB(fibEntry), conn_id, timer);
+ /*
+ * We need to prevent pending updates to recreate a link which does not make
+ * since anymore since we edit the graph here.
+ */
+ nexthops_clear(&tfib->nexthops);
- return true;
+ /* We update the sequence number in all cases otherwise this won't allow
+ * repetition
+ */
+ tfib->seq++;
+ }
-ERR_TIMER:
- dispatcher_DestroyTimerEvent(dispatcher, &timer);
-ERR_MALLOC:
- return false;
+ INFO("calling send to nh");
+ mapme_send_to_nexthops(mapme, entry, nexthops, prefix);
+ return 0;
}
-/*------------------------------------------------------------------------------
- * Event handling
- *----------------------------------------------------------------------------*/
+int mapme_set_adjacency(const mapme_t *mapme, fib_entry_t *entry,
+ nexthop_t nexthop, const hicn_prefix_t *prefix) {
+ nexthops_t nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, nexthop);
-/*
- * 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 */
-
- return true;
- }
- return false;
+ return mapme_set_adjacencies(mapme, entry, &nexthops, prefix);
}
-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";
- }
-
- 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;
+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;
}
- INFO(mapme, "[MAP-Me] Done sending MAP-Me update");
- free(name_str);
-}
-
-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++;
-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;
+ mapme_send_to_nexthops(mapme, entry, &tfib->nexthops, NULL);
+ return 0;
+}
- /* Apply the policy of the fibEntry over all neighbours */
- NumberSet * available_nexthops = fibEntry_GetAvailableNextHops(fibEntry, ~0);
+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;
+ }
- /* Advertise prefix on all available next hops (if needed) */
- mapme_send_updates(mapme, fibEntry, available_nexthops);
+ nexthops_t nexthops = NEXTHOPS_EMPTY;
+ nexthops_add(&nexthops, nexthop);
- numberSet_Release(&available_nexthops);
+ return mapme_send_to_nexthops(mapme, entry, &nexthops, NULL);
}
+#if 0
/*
* 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_foreach_entry(fib, entry, { mapme_set_all_adjacencies(mapme, entry); });
}
+#endif
/*------------------------------------------------------------------------------
* 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);
+#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+fib_entry_t *mapme_create_fib_entry(const mapme_t *mapme,
+ const hicn_prefix_t *prefix,
+ unsigned ingress_id) {
+ INFO(" - creating FIB entry with next hop on connection %d", ingress_id);
/*
- * Immediately send an acknowledgement back on the ingress connection
- * We always ack, even duplicates.
+ * 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.
+ * Also in case we have an intermediate node with just a less specific prefix
+ * (eg. a default route), and thus an announcement with 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 (before adding).
*/
- Message *ack = mapme_createAckMessage(mapme, msgBuffer, params);
- if (!ack) {
- name_Release(&name);
- return false;
- }
- rv = connection_ReSend(conn_in, ack, NOT_A_NOTIFICATION);
- message_Release(&ack);
+ forwarder_t *forwarder = mapme->forwarder;
+
+ fib_t *fib = forwarder_get_fib(forwarder);
+ configuration_t *config = forwarder_get_configuration(forwarder);
+
+ char prefix_s[MAXSZ_IP_PREFIX];
+ int rc = hicn_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0) NULL;
+
+ INFO("creating FIB entry for prefix %s", prefix_s);
- if (!rv) {
- name_Release(&name);
- return false;
+ strategy_type_t strategy_type = configuration_get_strategy(config, prefix_s);
+ fib_entry_t *entry = fib_entry_create(prefix, strategy_type, NULL, forwarder);
+ mapme_create_tfib(mapme, entry);
+
+ fib_entry_t *lpm = fib_match_prefix(fib, prefix);
+
+ // Keep this after the LPM lookup
+ fib_add(fib, entry);
+
+ if (!lpm) {
+ TFIB(entry)->seq = 0;
+ if (ingress_id != INVALID_FACE_ID)
+ fib_entry_nexthops_add(entry, ingress_id);
+ return entry;
}
- /* EPM on FIB */
- /* only the processor has access to the FIB */
- FIB *fib = forwarder_getFib(mapme->forwarder);
+ /*
+ * 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 nexthops_t *lpm_nexthops = fib_entry_get_nexthops(lpm);
+ nexthops_foreach(lpm_nexthops, nh, { fib_entry_nexthops_add(entry, nh); });
+ return entry;
+}
+#endif
- FibEntry *fibEntry = fib_Contains(fib, name);
+int mapme_on_timeout(void *mapme_arg, int fd, unsigned id, void *data) {
+ mapme_t *mapme = mapme_arg;
+ assert(mapme);
+ assert(id == 0);
+ 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;
- name_Release(&name);
+ for (uint8_t pos = 0; pos < CURLEN; pos++) {
+ mapme_retx_t *retx = &CUR[pos];
- 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;
+ if (!retx->entry) /* deleted entry */
+ continue;
- /*
- * 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.
+ mapme_tfib_t *tfib = TFIB(retx->entry);
+ assert(tfib);
+
+ /* 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)) {
+ /* We accept the packet knowing we will get a retransmit */
+ ERROR("Failed to send ACK packet");
+ }
+
+ msgbuf_pool_put(msgbuf_pool, ack);
+
+ WITH_INFO({
+ char buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)");
+ INFO("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, buf,
+ params->seq);
+ });
+
+ /* EPM on FIB */
+ const fib_t *fib = forwarder_get_fib(mapme->forwarder);
+ fib_entry_t *entry = fib_contains(fib, prefix);
+ if (!entry) {
+#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+ entry = mapme_create_fib_entry(mapme, prefix, ingress_id);
+ if (!entry) {
+ 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 +899,57 @@ 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 ?
- 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);
- }
- }
+ /* Initially we were detecting that the update completed when it returned to
+ * the producer, Because there might be proxies (using local/remote strategy),
+ * we need instead to verify if there is no non-local faces.
+ */
- /* 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);
+ if (fib_entry_has_all_local_nexthops(entry)) {
+ INFO("Received original interest... Update complete");
+ return;
+ }
- /* 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
+ * This could might optimized for situations where nothing changes, but
+ * this is very unlikely if not impossible...
*/
-
- INFO(mapme, "[MAP-Me] - (3/3) next hops ~~> prev hops");
- mapmeTFIB_Remove(mapme, TFIB(fibEntry), conn_in_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;
+ nexthops_t nexthops_keep = NEXTHOPS_EMPTY;
+ nexthops_foreach(&entry->nexthops, prevhop, {
+ const connection_t *conn = connection_table_get_by_id(table, prevhop);
+ /* Preserve local connections, migrate others to TFIB */
+ if (connection_is_local(conn)) {
+ nexthops_add(&nexthops_keep, prevhop);
+ } else {
+ nexthops_add(&tfib->nexthops, prevhop);
}
+ });
- 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;
- }
+ nexthops_remove(&tfib->nexthops, ingress_id);
- /*
- * The update is completed when the IU could not be sent to any
- * other next hop.
- */
- if (complete) INFO(mapme, "[MAP-Me] - Update completed !");
+ nexthops_clear(&entry->nexthops);
+ nexthops_add(&entry->nexthops, ingress_id);
+ nexthops_foreach(&nexthops_keep, nh,
+ { nexthops_add(&entry->nexthops, nh); });
+
+ event = MAPME_EVENT_NH_SET;
- numberSet_Release(&nexthops);
+ // XXX tell things are complete if we have no IU to send
- } else if (seq == fibSeq) {
+ } else if (params->seq == tfib->seq) {
/*
* Multipath, multihoming, multiple producers or duplicate interest
*
@@ -873,142 +960,77 @@ 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);
- INFO(mapme, "[MAP-Me] - Adding multipath next hop on connection %d",
- conn_in_id);
- fibEntry_AddNexthop(fibEntry, conn_in_id);
+ /* Move ingress to nexthops (and eventually remove it from TFIB) */
+ nexthops_add(&entry->nexthops, ingress_id);
+ nexthops_remove(&tfib->nexthops, ingress_id);
- } else { // seq < fibSeq
+ event = MAPME_EVENT_NH_ADD;
+
+ } 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 {
+ INFO("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) {
+ WITH_INFO({
+ char buf[MAXSZ_HICN_PREFIX];
+ int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+ if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
+ snprintf(buf, MAXSZ_HICN_PREFIX, "(error)");
+ INFO("Received ack for name prefix=%s seq=%d on conn id=%d", buf,
+ params->seq, ingress_id);
+ })
+
+ const fib_t *fib = forwarder_get_fib(mapme->forwarder);
+ fib_entry_t *entry = fib_contains(fib, prefix);
+ 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 +1045,70 @@ 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
+ INFO("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;
}
}
+#if 0
+/*
+ * 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;
+ }
+}
+#endif
+
+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..9ece8a090 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-2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.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,34 @@
#include <stdbool.h>
#include <stdint.h>
+#include <hicn/ctrl/hicn-light.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"
+
+// Allow processing of MAP-Me requests when no FIB entry is present.
+// An alternative would be to perform a LPM
+#define HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+
+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 +61,68 @@ 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.
+ * @param [in] prefix - A more specific prefix (special use with no retx), or
+ * NULL
*/
-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, const hicn_prefix_t *prefix);
/**
- * @function mapme_reconsiderFibEntry
- * @abstract Process a fib entry for changes that might trigger new updates
+ * @function mapme_set_adjacencies
+ * @abstract sends an update to the specified adjacency. Used by control plane
+ * commands.
* @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] nexthop - nexthop on which to send the update.
+ * @param [in] prefix - A more specific prefix (special use with no retx), or
+ * NULL
*/
-void mapme_reconsiderFibEntry(const MapMe *mapme, FibEntry * fibEntry);
+int mapme_set_adjacency(const mapme_t *mapme, fib_entry_t *entry,
+ nexthop_t nexthop, const hicn_prefix_t *prefix);
/**
- * @function mapme_onConnectionEvent
+ * @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] 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
+ */
+int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry,
+ bool inc_iu_seq);
+
+/**
+ * @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 +130,27 @@ 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);
-
-MessagePacketType mapme_LibHicnPktType_To_PktType(hicn_mapme_type_t type);
+// nexthops_t * mapme_get_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry,
+// const msgbuf_t *interest);
+
+#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY
+fib_entry_t *mapme_create_fib_entry(const mapme_t *mapme,
+ const hicn_prefix_t *prefix,
+ unsigned ingress_id);
+#endif /* HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY */
+
+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
deleted file mode 100644
index b41c9a7f0..000000000
--- a/hicn-light/src/hicn/core/messageHandler.h
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 messageHandler
-#define messageHandler
-
-#include <stdlib.h>
-#ifndef _WIN32
-#include <unistd.h> // close
-#endif
-
-#include <hicn/hicn.h>
-#include <hicn/core/messagePacketType.h>
-
-#define H(packet) ((hicn_header_t *)packet)
-#define H6(packet) (H(packet)->v6.ip)
-#define H6T(packet) (H(packet)->v6.tcp)
-#define H4(packet) (H(packet)->v4.ip)
-#define H4T(packet) (H(packet)->v4.tcp)
-
-#define HICN_V6_LEN(packet) (H6(packet).len)
-#define HICN_V4_LEN(packet) (H4(packet).len)
-
-/*** codes and types ***/
-#define IPv6_TYPE 6
-#define IPv4_TYPE 4
-#define ICMP_WLDR_TYPE 42
-#define ICMP_WLDR_CODE 0
-#define ICMP_LB_TYPE 43
-
-/*** masks and constants ***/
-#define PATH_LABEL_MASK 0x8000 // 1000 0000 0000 0000
-#define NOT_PATH_LABEL_MASK 0x7fff // 0111 0000 0000 0000
-#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111
-
-/*** HICN ALLOWED PORTS ***/
-#define CONTROL_PORT 9695
-#define HTTP_PORT 8080
-
-#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>
-
-#ifdef WITH_MAPME
-#include <hicn/core/mapme.h>
-#include <hicn/socket/api.h>
-#endif /* WITH_MAPME */
-
-#define CONNECTION_ID_UNDEFINED -1
-
-#define BFD_PORT 3784
-
-static inline uint8_t messageHandler_GetIPPacketType(const uint8_t *message) {
- return HICN_IP_VERSION(message);
-}
-
-static inline void messageHandler_UpdateTCPCheckSum(uint8_t *message,
- uint16_t *old_val,
- uint16_t *new_val,
- uint8_t size) {
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv4_TYPE:
- for (uint8_t i = 0; i < size; i++) {
- uint16_t old_csum = ~(H4T(message).csum);
- uint16_t not_old_val = ~(*old_val);
- uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val;
-
- while (sum >> 16) {
- sum = (sum >> 16) + (sum & UINT16_T_MASK);
- }
-
- H4T(message).csum = ~sum;
- ++old_val;
- ++new_val;
- }
- break;
- case IPv6_TYPE:
- for (uint8_t i = 0; i < size; i++) {
- uint16_t old_csum = ~(H6T(message).csum);
- uint16_t not_old_val = ~(*old_val);
- uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val;
-
- while (sum >> 16) {
- sum = (sum >> 16) + (sum & UINT16_T_MASK);
- }
-
- H6T(message).csum = ~sum;
- ++old_val;
- ++new_val;
- }
- break;
- default:
- return;
- }
-}
-
-static inline void messageHandler_UpdateIPv4CheckSum(uint8_t *message,
- uint16_t *old_val,
- uint16_t *new_val,
- uint8_t size) {
- for (uint8_t i = 0; i < size; i++) {
- uint16_t old_csum = ~(H4(message).csum);
- uint16_t not_old_val = ~(*old_val);
- uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val;
-
- while (sum >> 16) {
- sum = (sum >> 16) + (sum & UINT16_T_MASK);
- }
-
- H4(message).csum = ~sum;
- ++old_val;
- ++new_val;
- }
-}
-
-static inline size_t messageHandler_GetEmptyTCPPacketSize(unsigned ipVersion) {
- if (ipVersion == IPv4_TYPE)
- return IPV4_HDRLEN + TCP_HDRLEN;
- else if (ipVersion == IPv6_TYPE)
- return IPV6_HDRLEN + TCP_HDRLEN;
- else
- return 0;
-}
-
-static inline size_t messageHandler_GetICMPPacketSize(unsigned ipVersion) {
- if (ipVersion == IPv4_TYPE)
- return IPV4_HDRLEN + ICMP_HDRLEN;
- else if (ipVersion == IPv6_TYPE)
- return IPV6_HDRLEN + ICMP_HDRLEN;
- else
- return 0;
-}
-
-static inline size_t messageHandler_GetIPHeaderLength(unsigned ipVersion) {
- if (ipVersion == IPv4_TYPE)
- return IPV4_HDRLEN;
- else if (ipVersion == IPv6_TYPE)
- return IPV6_HDRLEN;
- else
- return 0;
-}
-
-static inline bool messageHandler_IsValidHicnPacket(const uint8_t *message) {
- uint8_t version = messageHandler_GetIPPacketType(message);
- if (version == IPv6_TYPE || version == IPv4_TYPE) {
- return true;
- }
- return false;
-}
-
-static inline uint8_t messageHandler_NextHeaderType(const uint8_t *message) {
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- return (uint8_t)H6(message).nxt;
- case IPv4_TYPE:
- return (uint8_t)H4(message).protocol;
- default:
- return 0;
- }
-}
-
-/* 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;
-}
-
-static inline bool messageHandler_IsInterest(const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return false;
-
- bool flag;
- hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message,
- &flag); // ECE flag is set to 0 in interest packets
- if (flag == false) return true;
- return false;
-}
-
-static inline bool messageHandler_IsData(const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return false;
-
- bool flag;
- hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message,
- &flag); // ECE flag is set to 1 in data packets
- if (flag == true) return true;
- return false;
-}
-
-static inline bool messageHandler_IsWldrNotification(const uint8_t *message) {
- // this function returns true only if the packet is an ICMP packet in Wldr
- // form. type must be equal to ICMP_WLDR_TYPE and code equal to ICMP_WLDR_CODE
- uint8_t next_header = messageHandler_NextHeaderType(message);
-
- const uint8_t *icmp_ptr;
- if (next_header == IPPROTO_ICMP) {
- icmp_ptr = message + IPV4_HDRLEN;
- } else if (next_header == IPPROTO_ICMPV6) {
- icmp_ptr = message + IPV6_HDRLEN;
- } else {
- return false;
- }
-
- uint8_t type = ((_icmp_header_t *)icmp_ptr)->type;
- uint8_t code = ((_icmp_header_t *)icmp_ptr)->code;
- if (type == ICMP_WLDR_TYPE && code == ICMP_WLDR_CODE) {
- return true;
- }
-
- return false;
-}
-
-static inline bool messageHandler_IsLoadBalancerProbe(const uint8_t *message) {
- uint8_t next_header = messageHandler_NextHeaderType(message);
-
- const uint8_t *icmp_ptr;
- if (next_header == IPPROTO_ICMP) {
- icmp_ptr = message + IPV4_HDRLEN;
- } else if (next_header == IPPROTO_ICMPV6) {
- icmp_ptr = message + IPV6_HDRLEN;
- } else {
- return false;
- }
-
- uint8_t type = ((_icmp_header_t *)icmp_ptr)->type;
- if (type == ICMP_LB_TYPE) {
- return true;
- }
-
- return false;
-}
-
-static inline uint16_t messageHandler_GetTotalPacketLength(
- const uint8_t *message) {
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- return ntohs((uint16_t)HICN_V6_LEN(message)) + IPV6_HDRLEN;
- case IPv4_TYPE:
- return ntohs((uint16_t)HICN_V4_LEN(message));
- default:
- return 0;
- }
-}
-
-static inline uint32_t messageHandler_GetSegment(const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return 0;
-
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- return ntohl((uint32_t)H6T(message).seq);
- case IPv4_TYPE:
- return ntohl((uint32_t)H4T(message).seq);
- default:
- return 0;
- }
-}
-
-static inline uint16_t messageHandler_GetExpectedWldrLabel(
- const uint8_t *message) {
- const uint8_t *icmp_ptr;
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- icmp_ptr = message + IPV6_HDRLEN;
- break;
- case IPv4_TYPE:
- icmp_ptr = message + IPV4_HDRLEN;
- break;
- default:
- return 0;
- }
-
- return ntohs(((_icmp_wldr_header_t *)icmp_ptr)->expected_lbl);
-}
-
-static inline uint16_t messageHandler_GetWldrLastReceived(
- const uint8_t *message) {
- const uint8_t *icmp_ptr;
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- icmp_ptr = message + IPV6_HDRLEN;
- break;
- case IPv4_TYPE:
- icmp_ptr = message + IPV4_HDRLEN;
- break;
- default:
- return 0;
- }
-
- return ntohs(((_icmp_wldr_header_t *)icmp_ptr)->received_lbl);
-}
-
-static inline uint16_t messageHandler_GetWldrLabel(const uint8_t *message) {
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- return ntohs((uint16_t)H6T(message).window);
- case IPv4_TYPE:
- return ntohs((uint16_t)H4T(message).window);
- default:
- return 0;
- }
-}
-
-static inline void messageHandler_SetWldrLabel(uint8_t *message,
- uint16_t label) {
- uint16_t old_val = messageHandler_GetWldrLabel(message);
-
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- H6T(message).window = htons(label);
- break;
- case IPv4_TYPE:
- H4T(message).window = htons(label);
- break;
- default:
- break;
- }
-
- messageHandler_UpdateTCPCheckSum(message, &old_val, &label, 1);
-}
-
-static inline void messageHandler_ResetWldrLabel(uint8_t *message) {
- messageHandler_SetWldrLabel(message, 0);
-}
-
-static inline bool messageHandler_HasWldr(const uint8_t *message) {
- if (messageHandler_IsTCP(message)) {
- uint16_t lbl = messageHandler_GetWldrLabel(message);
- if (lbl != 0) {
- return true;
- }
- }
- return false;
-}
-
-static inline uint32_t messageHandler_GetPathLabel(const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return 0;
-
- uint32_t path_label;
- int res = hicn_data_get_path_label((hicn_header_t *)message, &path_label);
- if (res < 0) return 0;
- return path_label;
-}
-
-static inline void messageHandler_SetPathLabel(uint8_t *message,
- uint32_t old_path_label,
- uint32_t new_path_label) {
- if (!messageHandler_IsTCP(message)) return;
-
- hicn_data_set_path_label((hicn_header_t *)message, new_path_label);
-
- messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&old_path_label,
- (uint16_t *)&new_path_label, 2);
-}
-
-static inline void messageHandler_UpdatePathLabel(uint8_t *message,
- uint8_t outFace) {
- if (!messageHandler_IsTCP(message)) return;
-
- uint32_t pl_old_32bit = messageHandler_GetPathLabel(message);
- uint8_t pl_old_8bit = (uint8_t)(pl_old_32bit >> 24UL);
- uint32_t pl_new_32bit =
- (uint32_t)((((pl_old_8bit << 1) | (pl_old_8bit >> 7)) ^ outFace) << 24UL);
-
- messageHandler_SetPathLabel(message, pl_old_32bit, pl_new_32bit);
-}
-
-static inline void messageHandler_ResetPathLabel(uint8_t *message) {
- messageHandler_SetPathLabel(message, messageHandler_GetPathLabel(message), 0);
-}
-
-static inline uint16_t messageHandler_GetInterestLifetime(
- const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return 0;
-
- hicn_lifetime_t lifetime;
- int res = hicn_interest_get_lifetime((hicn_header_t *)message, &lifetime);
- if (res < 0) return 0;
- return lifetime;
-}
-
-static inline bool messageHandler_HasInterestLifetime(const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return false;
-
- if (messageHandler_GetInterestLifetime(message) == 0) return false;
- return true;
-}
-
-static inline uint32_t messageHandler_GetContentExpiryTime(
- const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return 0;
-
- uint32_t expirationTime;
- int res =
- hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime);
- if (res < 0) return 0;
- return expirationTime;
-}
-
-static inline bool messageHandler_HasContentExpiryTime(const uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return 0;
-
- uint32_t expirationTime;
- int res =
- hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime);
- if (res < 0) return false;
-
- if (expirationTime == HICN_MAX_LIFETIME) return false;
-
- return true;
-}
-
-static inline void *messageHandler_GetSource(const uint8_t *message) {
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- return &H6(message).saddr;
- break;
- case IPv4_TYPE:
- return &H4(message).saddr;
- break;
- default:
- return NULL;
- }
-}
-
-static inline void *messageHandler_GetDestination(const uint8_t *message) {
- switch (messageHandler_GetIPPacketType(message)) {
- case IPv6_TYPE:
- return &H6(message).daddr;
- break;
- case IPv4_TYPE:
- return &H4(message).daddr;
- break;
- default:
- return NULL;
- }
-}
-
-static inline void messageHandler_SetSource_IPv6(uint8_t *message,
- struct in6_addr *address) {
- if (messageHandler_IsTCP(message)) {
- uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message);
- messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 8);
- }
- H6(message).saddr.as_in6addr = *address;
-}
-
-static inline void messageHandler_SetDestination_IPv6(
- uint8_t *message, struct in6_addr *address) {
- if (messageHandler_IsTCP(message)) {
- uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message);
- messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 8);
- }
- H6(message).daddr.as_in6addr = *address;
-}
-
-static inline void messageHandler_SetSource_IPv4(uint8_t *message,
- uint32_t *address) {
- // update tcp checksum
- uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message);
- if (messageHandler_IsTCP(message)) {
- messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 2);
- }
- // update IPv4 cheksum
- // the IPv4 checksum is not part of the psudo header for TCP checksum
- // calculation we can update them separetelly
- messageHandler_UpdateIPv4CheckSum(message, old_src, (uint16_t *)address, 2);
-
- H4(message).saddr.as_u32 = *address;
-}
-
-static inline void messageHandler_SetDestination_IPv4(uint8_t *message,
- uint32_t *address) {
- uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message);
- if (messageHandler_IsTCP(message)) {
- messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 2);
- }
- messageHandler_UpdateIPv4CheckSum(message, old_dst, (uint16_t *)address, 2);
- H4(message).daddr.as_u32 = *address;
-}
-
-static inline void messageHandler_SetWldrNotification(uint8_t *notification,
- uint8_t *original,
- uint16_t expected,
- uint16_t received) {
- hicn_header_t *h = (hicn_header_t *)notification;
- switch (messageHandler_GetIPPacketType(original)) {
- case IPv6_TYPE: {
- *h = (hicn_header_t){.v6 = {
- .ip =
- {
- .version_class_flow = htonl(
- (IPV6_DEFAULT_VERSION << 28) |
- (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
- (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
- .len = htons(ICMP_HDRLEN),
- .nxt = IPPROTO_ICMPV6,
- .hlim = 5,
- },
- .wldr =
- {
- .type = ICMP_WLDR_TYPE,
- .code = ICMP_WLDR_CODE,
- .expected_lbl = htons(expected),
- .received_lbl = htons(received),
- },
- }};
- messageHandler_SetSource_IPv6(
- notification,
- (struct in6_addr *)messageHandler_GetDestination(original));
- messageHandler_SetDestination_IPv6(
- notification, (struct in6_addr *)messageHandler_GetSource(original));
- break;
- }
- case IPv4_TYPE: {
- break;
- }
- default:
- break;
- }
-}
-
-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);
-
- 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);
-
- return pkt;
-}
-
-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);
- ip_address_t 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_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));
- 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 bool messageHandler_IsAProbe(const uint8_t *packet){
- uint16_t src_prt;
- uint16_t dst_prt;
- hicn_packet_get_src_port (HF_INET6_TCP, (const hicn_header_t *) packet, &src_prt);
- hicn_packet_get_dst_port (HF_INET6_TCP, (const hicn_header_t *) packet, &dst_prt);
-
- if(dst_prt == BFD_PORT){
- //interest probe
- return true;
- }
-
- if(src_prt == BFD_PORT){
- //data (could be a probe)
- uint32_t expiry_time;
- hicn_data_get_expiry_time ((const hicn_header_t *) packet, &expiry_time);
- if(expiry_time == 0){
- //this is a probe
- return true;
- }
- }
-
- return false;
-}
-
-#endif // Metis_metis_MessageHandler
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/core/msgbuf.c b/hicn-light/src/hicn/core/msgbuf.c
new file mode 100644
index 000000000..c58f7a7dc
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf.c
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file msgbuf.c
+ * \brief Implementation hICN message buffer
+ */
+
+#include "msgbuf.h"
+#include "../strategies/probe_generator.h"
+
+int msgbuf_initialize(msgbuf_t *msgbuf) {
+ /*
+ * We define the format and the storage area of the packet buffer we
+ * manipulate
+ */
+ hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf);
+ hicn_packet_set_buffer(pkbuf, msgbuf->packet, MTU, 0);
+ hicn_packet_init_header(pkbuf, 0);
+ return 0;
+}
+
+int msgbuf_initialize_from_packet(msgbuf_t *msgbuf) {
+ hicn_packet_set_buffer(msgbuf_get_pkbuf(msgbuf), msgbuf->packet, MTU,
+ msgbuf_get_len(msgbuf));
+ return 0;
+}
+
+bool msgbuf_is_command(const msgbuf_t *msgbuf) {
+ return (*msgbuf->packet == REQUEST_LIGHT);
+}
+
+bool msgbuf_is_probe(const msgbuf_t *msgbuf) {
+ hicn_name_t name;
+ hicn_name_suffix_t suffix;
+
+ assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA);
+
+ const hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf);
+ hicn_data_get_name(pkbuf, &name);
+ suffix = hicn_name_get_suffix(&name);
+ return (suffix >= MIN_PROBE_SUFFIX && suffix <= MAX_PROBE_SUFFIX);
+}
diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h
new file mode 100644
index 000000000..7a35929f4
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <hicn/name.h>
+#include "ticks.h"
+#include <hicn/hicn.h>
+#include <hicn/ctrl/hicn-light.h>
+
+#define MTU 1500
+#define INVALID_MSGBUF_ID ~0ul
+
+#define msgbuf_id_is_valid(msgbuf_id) \
+ ((unsigned long)msgbuf_id != INVALID_MSGBUF_ID)
+
+typedef struct {
+ hicn_packet_buffer_t pkbuf;
+ unsigned connection_id; // ingress
+ Ticks recv_ts; // timestamp
+ unsigned refs; // refcount
+ unsigned path_label; // original path label of the received message. used
+ // as a base for the path label computation when the
+ // same data packet needs to be forwarded on multiple
+ // face.
+
+ // XXX Cache storage
+ union {
+ /* Interest or data packet */
+ struct {
+ hicn_name_t name;
+ u32 name_hash; // XXX should be always populate when name is assigned
+ } id;
+ /* Command packet */
+ struct {
+ command_type_t type;
+ } command;
+ };
+ uint8_t packet[MTU];
+} msgbuf_t;
+
+int msgbuf_initialize(msgbuf_t *msgbuf);
+int msgbuf_initialize_from_packet(msgbuf_t *msgbuf);
+
+#define msgbuf_get_pkbuf(M) (&(M)->pkbuf)
+
+static inline hicn_packet_type_t msgbuf_get_type(const msgbuf_t *msgbuf) {
+ return hicn_packet_get_type(msgbuf_get_pkbuf(msgbuf));
+}
+
+static inline void msgbuf_set_type(msgbuf_t *msgbuf, hicn_packet_type_t type) {
+ hicn_packet_set_type(msgbuf_get_pkbuf(msgbuf), type);
+}
+
+static inline const hicn_name_t *msgbuf_get_name(const msgbuf_t *msgbuf) {
+ hicn_packet_type_t type = msgbuf_get_type(msgbuf);
+ assert(type == HICN_PACKET_TYPE_INTEREST || type == HICN_PACKET_TYPE_DATA);
+ (void)type;
+
+ return &msgbuf->id.name;
+}
+
+#define msgbuf_get_connection_id(M) ((M)->connection_id)
+#define msgbuf_set_connection_id(M, ID) (M)->connection_id = (ID)
+#define msgbuf_get_packet(M) ((M)->packet)
+#define msgbuf_get_command_type(M) ((M)->command.type)
+#if WITH_WLDR
+#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet))
+#endif
+
+static inline void msgbuf_set_name(msgbuf_t *msgbuf, const hicn_name_t *name) {
+ msgbuf->id.name = *name;
+}
+
+static inline size_t msgbuf_get_len(const msgbuf_t *msgbuf) {
+ return hicn_packet_get_len(msgbuf_get_pkbuf(msgbuf));
+}
+
+static inline void msgbuf_set_len(msgbuf_t *msgbuf, size_t len) {
+ int rc = hicn_packet_set_len(msgbuf_get_pkbuf(msgbuf), len);
+ assert(rc == HICN_LIB_ERROR_NONE); // XXX
+ _unused(rc);
+}
+
+static inline u32 msgbuf_get_name_hash(const msgbuf_t *msgbuf) {
+ hicn_packet_type_t type = msgbuf_get_type(msgbuf);
+ assert(type == HICN_PACKET_TYPE_INTEREST || type == HICN_PACKET_TYPE_DATA);
+ _unused(type);
+ return msgbuf->id.name_hash;
+}
+
+// Lifetimes/expiry times in milliseconds
+static inline u32 msgbuf_get_interest_lifetime(const msgbuf_t *msgbuf) {
+ u32 lifetime;
+ int rc = hicn_interest_get_lifetime(msgbuf_get_pkbuf(msgbuf), &lifetime);
+ if (rc != HICN_LIB_ERROR_NONE) return 0;
+ return lifetime;
+}
+
+//#define msgbuf_get_lifetime(M)
+// (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) *
+// 1000000ULL))
+#define msgbuf_get_lifetime msgbuf_get_interest_lifetime
+
+static inline bool msgbuf_set_interest_lifetime(msgbuf_t *msgbuf,
+ u32 lifetime) {
+ int rc = hicn_interest_set_lifetime(msgbuf_get_pkbuf(msgbuf), lifetime);
+ return (rc == HICN_LIB_ERROR_NONE);
+}
+
+static inline u32 msgbuf_get_data_expiry_time(const msgbuf_t *msgbuf) {
+ u32 lifetime;
+ int rc = hicn_data_get_expiry_time(msgbuf_get_pkbuf(msgbuf), &lifetime);
+ if (rc != HICN_LIB_ERROR_NONE) return 0;
+ return lifetime;
+}
+
+static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) {
+ int rc = hicn_data_set_expiry_time(msgbuf_get_pkbuf(msgbuf), lifetime);
+ return (rc == HICN_LIB_ERROR_NONE);
+}
+
+/* Path label */
+
+static inline void msgbuf_init_pathlabel(msgbuf_t *msgbuf) {
+ hicn_path_label_t pl;
+ int rc = hicn_data_get_path_label(msgbuf_get_pkbuf(msgbuf), &pl);
+ assert(rc == HICN_LIB_ERROR_NONE);
+ _unused(rc);
+ msgbuf->path_label = pl;
+}
+
+static inline int msgbuf_get_path_label(const msgbuf_t *msgbuf,
+ hicn_path_label_t *pl) {
+ assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA);
+ return hicn_data_get_path_label(msgbuf_get_pkbuf(msgbuf), pl);
+}
+
+static inline int msgbuf_set_path_label(msgbuf_t *msgbuf,
+ hicn_path_label_t pl) {
+ assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA);
+ return hicn_data_set_path_label(msgbuf_get_pkbuf(msgbuf), pl);
+}
+
+static inline int msgbuf_update_pathlabel(msgbuf_t *msgbuf,
+ hicn_faceid_t outface) {
+ assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA);
+
+ hicn_path_label_t pl, newpl;
+ if (msgbuf_get_path_label(msgbuf, &pl) < 0) return -1;
+
+ update_path_label(pl, outface, &newpl);
+
+ return msgbuf_set_path_label(msgbuf, newpl);
+}
+
+static inline void msgbuf_reset_pathlabel(msgbuf_t *msgbuf) {
+ msgbuf->path_label = 0;
+ hicn_data_set_path_label(msgbuf_get_pkbuf(msgbuf), 0);
+ // ERROR ?
+}
+
+static inline void msgbuf_modify_suffix(msgbuf_t *msgbuf, uint32_t new_suffix) {
+ hicn_name_t name;
+ assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST);
+ hicn_interest_get_name(msgbuf_get_pkbuf(msgbuf), &name);
+ hicn_name_set_suffix(&name, new_suffix);
+ hicn_interest_set_name(msgbuf_get_pkbuf(msgbuf), &name);
+}
+
+bool msgbuf_is_command(const msgbuf_t *msgbuf);
+bool msgbuf_is_probe(const msgbuf_t *msgbuf);
+
+/* WLDR */
+
+#if 0
+#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
+
+#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..892bd59a1
--- /dev/null
+++ b/hicn-light/src/hicn/core/msgbuf_pool.c
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file msgbuf_pool.c
+ * @brief Implementation of hICN packet pool.
+ */
+
+#include <hicn/util/pool.h>
+#include <hicn/util/log.h>
+#include "msgbuf_pool.h"
+
+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) {
+ off_t id = pool_get(msgbuf_pool->buffers, *msgbuf);
+ (*msgbuf)->refs = 0;
+ return id;
+}
+
+void msgbuf_pool_put(msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf) {
+ 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_get_type(msgbuf) != HICN_PACKET_TYPE_INTEREST &&
+ msgbuf_get_type(msgbuf) != HICN_PACKET_TYPE_DATA) {
+ TRACE("Msgbuf %d (%p) - put to msgbuf pool", msgbuf_id, msgbuf);
+ } else {
+ char buf[MAXSZ_HICN_NAME];
+ int rc =
+ hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf));
+ if (rc < 0 || rc >= MAXSZ_HICN_NAME)
+ snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)");
+ const char *msgbuf_type_str =
+ msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST ? "interest"
+ : "data";
+ TRACE("Msgbuf %d (%p) - %s (%s) put to msgbuf pool", msgbuf_id, msgbuf,
+ buf, msgbuf_type_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
deleted file mode 100644
index b4a5e8d1b..000000000
--- a/hicn-light/src/hicn/core/name.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 <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/core/messageHandler.h>
-#include <hicn/core/name.h>
-
-#include <parc/algol/parc_Hash.h>
-
-#include <parc/assert/parc_Assert.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");
-
- uint32_t hash1 = nameBitvector_GetHash32(name->content_name);
- return parcHash32_Data_Cumulative((const uint8_t *)&name->segment, 4, 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));
-
- 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;
- }
- } 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;
- }
- } else {
- printf("Error: unknown message type\n");
- parcMemory_Deallocate((void **)&name);
- return NULL;
- }
-
- 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);
- } else {
- parcTrapNotImplemented("Unkown packet type");
- }
-
- name->segment = 0;
- 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));
- }
- 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 *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));
-
- copy->content_name = nameBitvector_Copy(original->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");
- return name->name_hash;
-}
-
-NameBitvector *name_GetContentName(const Name *name) {
- parcAssertNotNull(name, "Parameter must be non-null");
- return 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");
-
- /* BEGIN: Workaround for HICN-400 */
- if ((!a->content_name) || (!b->content_name))
- return false;
- /* END: Workaround for HICN-400 */
-
- 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");
-
- if (a == NULL && b == NULL) {
- return 0;
- }
- if (a == NULL) {
- return -1;
- }
- if (b == NULL) {
- return +1;
- }
-
- int res = nameBitvector_Compare(a->content_name, b->content_name);
-
- if (res != 0) {
- return res;
- } else {
- if (a->segment < b->segment) {
- return -1;
- } else if (a->segment > b->segment) {
- return +1;
- } else {
- return 0;
- }
- }
-}
-
-char *name_ToString(const Name *name) {
- char *output = malloc(128);
-
- Address *packetAddr = nameBitvector_ToAddress(name_GetContentName(name));
-
- char * address_str = addressToString(packetAddr);
- sprintf(output, "name: %s seq: %u", address_str, name->segment);
- parcMemory_Deallocate((void **)&address_str);
-
- addressDestroy(&packetAddr);
-
- return output;
-}
-
-void name_setLen(Name *name, uint8_t 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;
-}
-
-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
deleted file mode 100644
index db9438150..000000000
--- a/hicn-light/src/hicn/core/name.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.
- */
-
-#ifndef name_h
-#define name_h
-
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include <hicn/core/messagePacketType.h>
-#include <hicn/core/nameBitvector.h>
-#include <hicn/utils/address.h>
-
-#include <hicn/utils/commands.h>
-
-struct name;
-typedef struct name Name;
-
-/**
- * Creates a name from packet
- *
- */
-Name *name_CreateFromPacket(const uint8_t *memory, MessagePacketType type);
-
-/**
- * Releases one reference count, and frees memory after last reference
- */
-void name_Release(Name **namePtr);
-
-/**
- * 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.
- */
-Name *name_Acquire(const Name *original);
-
-/**
- * returns a copy of the name
- */
-Name *name_Copy(const Name *original);
-
-/**
- * A hash value for use in hash tables
- *
- */
-uint32_t name_HashCode(const Name *name);
-
-/**
- * Returns the content name without the segment value
- *
- */
-NameBitvector *name_GetContentName(const Name *name);
-
-/**
- * Determine if two HicnName instances are equal.
- */
-bool name_Equals(const Name *a, const Name *b);
-
-/**
- * Compares two names and returns their ordering
- *
- */
-int name_Compare(const Name *a, const Name *b);
-
-/**
- * return the name in string format (bitvector + segment number)
- *
- */
-char *name_ToString(const Name *name);
-
-/**
- * @function message_setNameLen
- * @abstract Sets a message name length
- * @param [in] message - Interest message
- * @param [in] len - Name length
- */
-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);
-
-#ifdef WITH_POLICY
-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
deleted file mode 100644
index 653560750..000000000
--- a/hicn-light/src/hicn/core/nameBitvector.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#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>
-
-#define NAME_LEN 2
-
-const uint64_t BV_SIZE = 64;
-const uint64_t WIDTH = 128;
-const uint64_t ONE = 0x1;
-
-// address b000:0000:0000:0001:c000:0000:0000:0001 is encodend as follow
-// [bits[0] uint64_t ] [bits[1] unit64_t ]
-// ^ ^ ^ ^
-// 63 0 127 64
-// [1000 0000 ... 0000 1101] [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));
-
- bitvector->bits[0] = 0;
- bitvector->bits[1] = 0;
-
- uint8_t addr_1 = (addr & 0xff000000) >> 24;
- uint8_t addr_2 = (addr & 0x00ff0000) >> 16;
- uint8_t addr_3 = (addr & 0x0000ff00) >> 8;
- uint8_t addr_4 = (addr & 0x000000ff);
-
- bitvector->bits[0] = (bitvector->bits[0] | addr_4) << 8;
- bitvector->bits[0] = (bitvector->bits[0] | addr_3) << 8;
- bitvector->bits[0] = (bitvector->bits[0] | addr_2) << 8;
- bitvector->bits[0] = (bitvector->bits[0] | addr_1);
- bitvector->bits[0] = bitvector->bits[0] << 32;
-
- 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));
-
- bitvector->bits[0] = 0;
- bitvector->bits[1] = 0;
-
- for (int i = 0; i < 8; ++i) {
- bitvector->bits[0] = (bitvector->bits[0] << 8) | addr->s6_addr[i];
- }
-
- for (int i = 8; i < 16; ++i) {
- bitvector->bits[1] = (bitvector->bits[1] << 8) | addr->s6_addr[i];
- }
-
- 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));
-
- 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;
-}
-
-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);
-}
-
-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;
- return false;
-}
-
-int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b) {
- if (a == NULL && b == NULL) {
- return 0;
- }
- if (a == NULL) {
- return -1;
- }
- if (b == NULL) {
- return +1;
- }
-
- if (a->bits[0] < b->bits[0]) {
- return -1;
- } else if (a->bits[0] > b->bits[0]) {
- return +1;
- } else if (a->bits[1] < b->bits[1]) {
- return -1;
- } else if (a->bits[1] > b->bits[1]) {
- return +1;
- } else if (a->len < b->len) {
- return -1;
- } else if (a->len > b->len) {
- return +1;
- } else {
- return 0;
- }
-}
-
-int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit) {
- if(pos >= name->len || pos > (WIDTH -1))
- return -1;
-
- *bit = (name->bits[pos / BV_SIZE] & (ONE << ((BV_SIZE - 1) - (pos % BV_SIZE))));
-
- return 0;
-}
-
-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)
- uint64_t result = 0;
-
- if (val & 0xFFFFFFFF00000000) {
- val = val >> 32;
- result = result | 32;
- }
- if (val & 0xFFFF0000) {
- val = val >> 16;
- result = result | 16;
- }
- if (val & 0xFF00) {
- val = val >> 8;
- result = result | 8;
- }
- if (val & 0xF0) {
- val = val >> 4;
- result = result | 4;
- }
- if (val & 0xC) {
- val = val >> 2;
- result = result | 2;
- }
- if (val & 0x2) {
- val = val >> 1;
- result = result | 1;
- }
- return result;
-}
-
-uint32_t nameBitvector_lpm(const NameBitvector *a,
- const NameBitvector *b) {
- uint32_t limit;
- uint32_t prefix_len;
- if (a->len < b->len)
- limit = a->len;
- else
- limit = b->len;
-
- uint64_t diff = a->bits[0] ^ b->bits[0];
- 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;
- 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(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)));
-}
-
-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;
- prefix->len = IPV4_ADDR_LEN_BITS;
-
- uint32_t tmp_addr = name->bits[0] >> 32ULL;
- uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24;
- uint8_t addr_2 = (tmp_addr & 0x00ff0000) >> 16;
- uint8_t addr_3 = (tmp_addr & 0x0000ff00) >> 8;
- uint8_t addr_4 = (tmp_addr & 0x000000ff);
-
- addr->s_addr = 0;
- addr->s_addr = (addr->s_addr | addr_4) << 8;
- addr->s_addr = (addr->s_addr | addr_3) << 8;
- addr->s_addr = (addr->s_addr | addr_2) << 8;
- addr->s_addr = (addr->s_addr | addr_1);
-
- } else {
- struct in6_addr *addr = (struct in6_addr *)(&prefix->address.v6.buffer);
- prefix->family = AF_INET6;
- prefix->len = name->len; // IPV6_ADDR_LEN_BITS;
-
- for (int i = 0; i < 8; i++) {
- addr->s6_addr[i] = (uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF);
- }
-
- int x = 0;
- for (int i = 8; i < 16; ++i) {
- addr->s6_addr[i] = (uint8_t)((name->bits[1] >> 8 * (7 - x)) & 0xFF);
- x++;
- }
- }
- return true;
-}
-
-void nameBitvector_setLen(NameBitvector *name, uint8_t len) { name->len = len; }
-
-Address *nameBitvector_ToAddress(const NameBitvector *name) {
- if (name->IPversion == IPv4_TYPE) {
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(1234);
-
- uint32_t tmp_addr = name->bits[0] >> 32ULL;
- uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24;
- uint8_t addr_2 = (tmp_addr & 0x00ff0000) >> 16;
- 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;
-
- } else {
- struct sockaddr_in6 addr;
- addr.sin6_family = AF_INET6;
- addr.sin6_port = htons(1234);
- addr.sin6_scope_id = 0;
- addr.sin6_flowinfo = 0;
-
- for (int i = 0; i < 8; i++) {
- addr.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] =
- (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);
-
- addressDestroy(&packetAddr);
-
- return output;
-}
diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h
deleted file mode 100644
index 19944778c..000000000
--- a/hicn-light/src/hicn/core/nameBitvector.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 name_bitvector_h
-#define name_bitvector_h
-
-#include <hicn/hicn.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <hicn/utils/address.h>
-
-struct name_bitvector;
-typedef struct name_bitvector NameBitvector;
-
-NameBitvector *nameBitvector_CreateFromInAddr(uint32_t addr, uint8_t len);
-
-NameBitvector *nameBitvector_CreateFromIn6Addr(struct in6_addr *addr,
- uint8_t len);
-
-NameBitvector *nameBitvector_Copy(const NameBitvector *original);
-
-void nameBitvector_Destroy(NameBitvector **bitvectorPtr);
-
-uint8_t nameBitvector_GetLength(const NameBitvector *name);
-
-uint32_t nameBitvector_GetHash32(const NameBitvector *name);
-
-bool nameBitvector_Equals(const NameBitvector *a, const NameBitvector *b);
-
-int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b);
-
-int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit);
-
-uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b);
-
-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);
-
-char *nameBitvector_ToString(const NameBitvector *name);
-
-#endif // name_bitvector_h
diff --git a/hicn-light/src/hicn/core/nexthops.c b/hicn-light/src/hicn/core/nexthops.c
new file mode 100644
index 000000000..1a6096777
--- /dev/null
+++ b/hicn-light/src/hicn/core/nexthops.c
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file nexthops.c
+ * \brief Nexthops implementation
+ */
+
+#include <hicn/util/hash.h>
+
+#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;
+}
+
+int nexthops_disable_all(nexthops_t *nexthops) {
+ nexthops->flags = ~0;
+ nexthops->cur_elts = 0;
+ 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;
+ 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) {
+ 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) {
+ nexthops_foreach(nexthops, n, {
+ if (n == nexthop) return true;
+ });
+ return false;
+}
+
+off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop) {
+ nexthops_enumerate(nexthops, i, n, {
+ if (n == nexthop) return i;
+ });
+ return INVALID_NEXTHOP;
+}
+
+unsigned nexthops_get_one(nexthops_t *nexthops) {
+ 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) {
+ 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) {
+ nexthops_enumerate(nexthops, i, nh, {
+ (void)nh;
+ nexthops_reset_priority(nexthops, i);
+ });
+}
+
+bool nexthops_equal(nexthops_t *a, nexthops_t *b) {
+ 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;
+}
+
+/* Adapted from Jenkins hash (commutative) */
+uint32_t nexthops_get_hash(nexthops_t *nexthops) {
+ uint32_t hash = 0;
+
+ nexthops_foreach(nexthops, nh, {
+ hash += nh;
+ hash += hash << 10;
+ hash ^= hash >> 6;
+ });
+ hash += hash << 3;
+ hash ^= hash >> 11;
+ hash += hash << 15;
+ return hash;
+}
+
+#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..232c74388
--- /dev/null
+++ b/hicn-light/src/hicn/core/nexthops.h
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+/**
+ * \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);
+int nexthops_disable_all(nexthops_t *nexthops);
+
+#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 { \
+ nexthop_t X; \
+ (void)X; \
+ unsigned I; \
+ (void)I; \
+ 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 { \
+ 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 */
+
+uint32_t nexthops_get_hash(nexthops_t *nexthops);
+
+#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..937b0480b
--- /dev/null
+++ b/hicn-light/src/hicn/core/packet_cache.c
@@ -0,0 +1,884 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file packet_cache.c
+ * \brief Implementation of hICN packet cache
+ *
+ * _get_suffixes : first level lookup to return the suffixes
+ *
+ * _remove_suffix : Remove suffix from the two level packet cache structure
+ *
+ * __add_suffix : Add a packet cache entry in the second level of the
+ * two-level data structure _add_suffix : Add a packet cache entry in the both
+ * the first and second level of the two-level data tructure (helper)
+ *
+ * __get_suffix : Lookup in the second level of the packet cache
+ *
+ * _get_suffix : Lookup in both the first and second levels of the packet cache
+ *
+ * ----
+ *
+ * pkt_cache_save_suffixes_for_prefix : always done at packet reception to keep
+ * the latest suffixes
+ *
+ * pkt_cache_reset_suffixes_for_prefix
+ *
+ * ----
+ *
+ * pkt_cache_allocate
+ *
+ * pkt_cache_add_to_index
+ *
+ * pkt_cache_remove_from_index
+ *
+ * pkt_cache_pit_remove_entry
+ *
+ * pkt_cache_cs_remove_entry
+ *
+ * pkt_cache_add_to_pit
+ * pkt_cache_add_to_cs
+ *
+ * _pkt_cache_add_to_pit
+ * used by pkt_cache_add_to_pit
+ * plt_cache_update_pit
+ * _pkt_cache_add_to_cs
+ *
+ * pkt_cache_pit_to_cs
+ * pkt_cache_cs_to_pit
+ *
+ * pkt_cache_update_pit : when an interest expired
+ * pkt_cache_update_cs
+ *
+ * pkt_cache_try_aggregate_in_pit
+ *
+ *
+ *
+ */
+
+#include <hicn/core/forwarder.h>
+#include "packet_cache.h"
+
+const char *_pkt_cache_verdict_str[] = {
+#define _(x) [PKT_CACHE_VERDICT_##x] = #x,
+ foreach_kh_verdict
+#undef _
+};
+
+/******************************************************************************
+ * Low-level operations on the hash table
+ ******************************************************************************/
+
+/**
+ * Free the two level packet cache structure (helper)
+ */
+void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes) {
+ kh_pkt_cache_suffix_t *suffix;
+ kh_foreach_value(prefix_to_suffixes, suffix,
+ { kh_destroy_pkt_cache_suffix(suffix); });
+ kh_destroy_pkt_cache_prefix(prefix_to_suffixes);
+}
+
+/**
+ * Perform the first level lookup to return the suffixes (helper)
+ */
+kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes,
+ const hicn_name_prefix_t *prefix,
+ bool create, slab_t *prefix_keys) {
+ khiter_t k = kh_get_pkt_cache_prefix(prefix_to_suffixes, prefix);
+
+ /* Return suffixes if found... */
+ if (k != kh_end(prefix_to_suffixes)) {
+ kh_pkt_cache_suffix_t *suffixes = kh_val(prefix_to_suffixes, k);
+ return suffixes;
+ }
+
+ if (!create) return NULL;
+
+ /* ... otherwise populate the first level and return the newly added entry.
+ */
+ kh_pkt_cache_suffix_t *suffixes = kh_init_pkt_cache_suffix();
+
+ hicn_name_prefix_t *prefix_copy = slab_get(hicn_name_prefix_t, prefix_keys);
+ memcpy(prefix_copy, prefix, sizeof(hicn_name_prefix_t));
+
+ int rc;
+ k = kh_put_pkt_cache_prefix(prefix_to_suffixes, prefix_copy, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(prefix_to_suffixes, k) = suffixes;
+ return suffixes;
+}
+
+/**
+ * Remove suffix from the two level packet cache structure (helper)
+ */
+void _remove_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_prefix_t *prefix,
+ const hicn_name_suffix_t suffix, slab_t *prefix_keys) {
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefixes, prefix, false, prefix_keys);
+ assert(suffixes != NULL);
+
+ khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix);
+ assert(k != kh_end(suffixes));
+ kh_del_pkt_cache_suffix(suffixes, k);
+
+ // TODO(eloparco): Remove prefix if no associated suffixes?
+}
+
+/**
+ * Add a packet cache entry in the second level of the two-level data structure
+ * (helper)
+ */
+void __add_suffix(kh_pkt_cache_suffix_t *suffixes, hicn_name_suffix_t suffix,
+ unsigned val) {
+ // INFO("suffix add suffixes=%p suffix=%d val=%d", suffixes, suffix, val);
+ int rc;
+ khiter_t k = kh_put_pkt_cache_suffix(suffixes, suffix, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(suffixes, k) = val;
+}
+
+/**
+ * Add a packet cache entry in the both the first and second level of the
+ * two-level data tructure (helper)
+ */
+void _add_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_prefix_t *prefix,
+ const hicn_name_suffix_t suffix, unsigned val,
+ slab_t *prefix_keys) {
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefixes, prefix, true, prefix_keys);
+ assert(suffixes != NULL);
+
+ __add_suffix(suffixes, suffix, val);
+}
+
+/**
+ * Lookup in the second level of the packet cache (helper)
+ */
+unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes,
+ hicn_name_suffix_t suffix) {
+ khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix);
+
+ // Not Found
+ if (k == kh_end(suffixes)) {
+ return HICN_INVALID_SUFFIX;
+ }
+
+ unsigned index = kh_val(suffixes, k);
+ return index;
+}
+
+unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_prefix_t *prefix,
+ hicn_name_suffix_t suffix, slab_t *prefix_keys) {
+ /* create is false as this function is always called by lookup */
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefixes, prefix, false, prefix_keys);
+ if (!suffixes) {
+ return HICN_INVALID_SUFFIX;
+ }
+ return __get_suffix(suffixes, suffix);
+}
+
+/**
+ * Lookup in both the first and second levels of the packet cache (helper)
+ */
+unsigned _get_suffix_from_name(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_t *name, slab_t *prefix_keys) {
+ const hicn_name_prefix_t *prefix = hicn_name_get_prefix(name);
+ const hicn_name_suffix_t suffix = hicn_name_get_suffix(name);
+
+ return _get_suffix(prefixes, prefix, suffix, prefix_keys);
+}
+
+void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache,
+ const hicn_name_prefix_t *prefix) {
+ // Cached prefix matches the current one
+ if (hicn_name_prefix_equals(&pkt_cache->cached_prefix, prefix)) return;
+
+ char buf[MAXSZ_HICN_PREFIX];
+ hicn_name_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, &pkt_cache->cached_prefix);
+ hicn_name_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix);
+
+ // Update cached prefix information
+ pkt_cache->cached_prefix = *prefix;
+ pkt_cache->cached_suffixes =
+ _get_suffixes(pkt_cache->prefix_to_suffixes, prefix, true,
+ pkt_cache->prefix_keys); // XXX
+ //
+}
+
+void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache) {
+ pkt_cache->cached_suffixes = NULL;
+}
+
+/******************************************************************************
+ * Public API
+ ******************************************************************************/
+
+pkt_cache_t *pkt_cache_create(size_t cs_size) {
+ pkt_cache_t *pkt_cache = (pkt_cache_t *)malloc(sizeof(pkt_cache_t));
+
+ 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->prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ pkt_cache->prefix_keys = slab_create(hicn_name_prefix_t, SLAB_INIT_SIZE);
+ pool_init(pkt_cache->entries, DEFAULT_PKT_CACHE_SIZE, 0);
+
+ pkt_cache->cached_prefix = HICN_NAME_PREFIX_EMPTY;
+ pkt_cache->cached_suffixes = NULL;
+
+ return pkt_cache;
+}
+
+void pkt_cache_free(pkt_cache_t *pkt_cache) {
+ assert(pkt_cache);
+
+ // Free prefix hash table and pool
+ _prefix_map_free(pkt_cache->prefix_to_suffixes);
+ slab_free(pkt_cache->prefix_keys);
+ pool_free(pkt_cache->entries);
+
+ // Free PIT and CS
+ pit_free(pkt_cache->pit);
+ cs_free(pkt_cache->cs);
+
+ free(pkt_cache);
+}
+
+kh_pkt_cache_suffix_t *pkt_cache_get_suffixes(const pkt_cache_t *pkt_cache,
+ const hicn_name_prefix_t *prefix,
+ bool create,
+ slab_t *prefix_keys) {
+ return _get_suffixes(pkt_cache->prefix_to_suffixes, prefix, create,
+ prefix_keys);
+}
+
+pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache) {
+ pkt_cache_entry_t *entry = NULL;
+ pool_get(pkt_cache->entries, entry);
+ assert(entry);
+ return entry;
+}
+
+void pkt_cache_add_to_index(const pkt_cache_t *pkt_cache,
+ const pkt_cache_entry_t *entry) {
+ off_t id = entry - pkt_cache->entries;
+
+ /* It is important that the name used for the index is the one in the packet
+ * cache entry, which is common for PIT and CS
+ */
+ const hicn_name_t *name = &entry->name;
+
+ if (pkt_cache->cached_suffixes) {
+ __add_suffix(pkt_cache->cached_suffixes, hicn_name_get_suffix(name),
+ (unsigned int)id);
+ } else {
+ _add_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name),
+ hicn_name_get_suffix(name), (unsigned int)id,
+ pkt_cache->prefix_keys);
+ }
+}
+
+/**
+ * Remove a name pointer to the packet cache index (helper)
+ */
+void pkt_cache_remove_from_index(const pkt_cache_t *pkt_cache,
+ const hicn_name_t *name) {
+ _remove_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name),
+ hicn_name_get_suffix(name), pkt_cache->prefix_keys);
+
+// TODO
+#if 0
+ khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, name);
+ assert(k != kh_end(pkt_cache->index_by_name));
+ kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
+#endif
+}
+
+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 hicn_name_t *name,
+ msgbuf_pool_t *msgbuf_pool,
+ pkt_cache_lookup_t *lookup_result,
+ off_t *entry_id,
+ bool is_serve_from_cs_enabled) {
+ unsigned index = HICN_INVALID_SUFFIX;
+ if (pkt_cache->cached_suffixes) {
+ index =
+ __get_suffix(pkt_cache->cached_suffixes, hicn_name_get_suffix(name));
+ } else {
+ index = _get_suffix_from_name(pkt_cache->prefix_to_suffixes, name,
+ pkt_cache->prefix_keys);
+ }
+
+ if (index == HICN_INVALID_SUFFIX) {
+ *lookup_result = PKT_CACHE_LU_NONE;
+ return NULL;
+ }
+
+ 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);
+
+ // XXX const hicn_name_t *name = msgbuf_get_name(msgbuf);
+ _remove_suffix(pkt_cache->prefix_to_suffixes,
+ hicn_name_get_prefix(&entry->name),
+ hicn_name_get_suffix(&entry->name), pkt_cache->prefix_keys);
+
+ // 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 buf[MAXSZ_HICN_NAME];
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, &entry->name);
+ if (rc < 0 || rc >= MAXSZ_HICN_NAME)
+ snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)");
+ DEBUG("Packet %s removed from CS", buf);
+ })
+
+ msgbuf_pool_release(msgbuf_pool, &msgbuf);
+}
+
+void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ const hicn_name_t *name = &entry->name;
+ _remove_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name),
+ hicn_name_get_suffix(name), pkt_cache->prefix_keys);
+
+ pool_put(pkt_cache->entries, entry);
+
+ WITH_DEBUG({
+ char buf[MAXSZ_HICN_NAME];
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, name);
+ if (rc < 0 || rc >= MAXSZ_HICN_NAME)
+ snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)");
+ DEBUG("Packet %s removed from PIT", buf);
+ })
+}
+
+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}};
+ Ticks now = ticks_now();
+ entry->create_ts = now;
+ entry->expire_ts = 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 = (int)(pkt_cache->cs->lru.tail);
+ int result = cs_vft[pkt_cache->cs->type]->add_entry(pkt_cache, entry_id);
+ if (result == LRU_EVICTION) {
+ // Remove tail (already removed from LRU cache)
+ 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 *entry,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf,
+ off_t msgbuf_id, off_t entry_id) {
+ assert(pkt_cache);
+ assert(entry);
+ assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
+
+ _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id,
+ entry_id);
+}
+
+/**
+ * entry : newly allocated cache entry
+ * msgbuf : used for name, ingress connection id and lifetime
+ */
+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,
+ const hicn_name_t *name) {
+ assert(pkt_cache);
+
+ pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache);
+ entry->name = *name;
+ _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
+ pkt_cache_add_to_index(pkt_cache, entry);
+ 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);
+ const hicn_name_t *name = msgbuf_get_name(msgbuf);
+ entry->name = *name;
+ 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);
+ pkt_cache_add_to_index(pkt_cache, entry);
+ 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,
+ const hicn_name_t *name) {
+ 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 the strategy to use for this packet is STRATEGY_TYPE_LOCAL_REMOTE we may
+ // want to forward the packet even if it should be aggregated. This is useful
+ // when a local consumer socket and a remote one are asking for the same
+ // content. If the interest coming from the remote socket is received before
+ // the one from the local socket, the second interest is aggregated in the PIT
+ // and no interest is satisfied (IRIS app).
+ // Forward the interest if: 1) the strategy in the fib_entry stored in the pit
+ // entry is STRATEGY_TYPE_LOCAL_REMOTE 2) the ingress connection of the
+ // interest if a local connection 3) the ingress list of pit entry has no
+ // other local ingress connection if all these conditions are satisfied, send
+ // the interest. if is_aggregated = false avoid the check (it will be useless)
+
+ if (is_aggregated) {
+ fib_entry_t *fib_entry = pit_entry_get_fib_entry(pit_entry);
+ if (fib_entry &&
+ (fib_entry_strategy_type(fib_entry) == STRATEGY_TYPE_LOCAL_REMOTE)) {
+ // the strategy is STRATEGY_TYPE_LOCAL_REMOTE, check the input face
+ connection_table_t *table =
+ forwarder_get_connection_table(fib_entry->forwarder);
+ if (table) {
+ connection_t *msg_conn =
+ connection_table_get_by_id(table, connection_id);
+ if (msg_conn && connection_is_local(msg_conn)) {
+ // The face is local, check that no other input face is local. With
+ // this check only the first local consumer is able to send
+ // the interest, while the other interests will be aggregated
+ // (however this is quite inefficient)
+ nexthops_t *ingressIdSet = pit_entry_get_ingress(pit_entry);
+ bool in_local_connextion_exists = false;
+ nexthops_enumerate(ingressIdSet, i, nexthop, {
+ connection_t *in_conn = connection_table_get_by_id(table, nexthop);
+ if (in_conn && connection_is_local(in_conn)) {
+ in_local_connextion_exists = true;
+ break;
+ }
+ });
+ if (!in_local_connextion_exists) is_aggregated = false;
+ }
+ }
+ }
+ }
+
+ if (is_aggregated) pit_entry_ingress_add(pit_entry, connection_id);
+
+ WITH_DEBUG({
+ char buf[MAXSZ_HICN_NAME];
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf));
+ if (rc < 0 || rc >= MAXSZ_HICN_NAME)
+ snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)");
+ if (is_aggregated) {
+ DEBUG("Interest %s already existing (expiry %lu): aggregate", buf,
+ entry->expire_ts);
+ } else {
+ DEBUG("Interest %s already existing (expiry %lu): retransmit", buf,
+ entry->expire_ts);
+ }
+ })
+
+ 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) == HICN_PACKET_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);
+ *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);
+ *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("Invalid 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,
+ const hicn_name_t *name,
+ 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) == HICN_PACKET_TYPE_INTEREST);
+
+ off_t entry_id;
+ pkt_cache_lookup_t lookup_result;
+ pkt_cache_entry_t *entry =
+ pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id,
+ is_serve_from_cs_enabled);
+ *entry_ptr = entry;
+
+ cs_entry_t *cs_entry = NULL;
+ bool is_cs_miss = true;
+ bool is_aggregated;
+ switch (lookup_result) {
+ case PKT_CACHE_LU_NONE:
+ entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
+ *entry_ptr = entry;
+
+ *verdict = PKT_CACHE_VERDICT_FORWARD_INTEREST;
+ break;
+
+ 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, name);
+
+ *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);
+
+ kh_pkt_cache_suffix_t *v_suffixes;
+ u32 k_suffix;
+ u32 v_pkt_cache_entry_id;
+ kh_foreach_value(pkt_cache->prefix_to_suffixes, v_suffixes, {
+ kh_foreach(v_suffixes, k_suffix, v_pkt_cache_entry_id, {
+ pkt_cache_entry_t *entry = pkt_cache_at(pkt_cache, v_pkt_cache_entry_id);
+ if (entry->entry_type == PKT_CACHE_CS_TYPE) {
+ // Remove from hash table
+ khiter_t k = kh_get_pkt_cache_suffix(v_suffixes, k_suffix);
+ assert(k != kh_end(v_suffixes));
+ kh_del_pkt_cache_suffix(v_suffixes, k);
+
+ // Remove from pool
+ pool_put(pkt_cache->entries, entry);
+ }
+ });
+ });
+
+ // Reset cached prefix
+ pkt_cache->cached_prefix = HICN_NAME_PREFIX_EMPTY;
+ pkt_cache->cached_suffixes = NULL;
+
+ // Re-create CS
+ cs_clear(pkt_cache->cs);
+}
+
+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_size(pkt_cache_t *pkt_cache) {
+ return pool_len(pkt_cache->entries);
+}
+
+size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache) {
+ return pkt_cache->cs->num_entries;
+}
+
+size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache) {
+ uint64_t pkt_cache_size = pkt_cache_get_size(pkt_cache);
+ uint64_t pit_size = pkt_cache_size - pkt_cache_get_cs_size(pkt_cache);
+ return pit_size;
+}
+
+void pkt_cache_log(pkt_cache_t *pkt_cache) {
+ DEBUG("Packet cache: total size = %lu, PIT size = %lu, CS size = %u",
+ pkt_cache_get_size(pkt_cache), pkt_cache_get_pit_size(pkt_cache),
+ pkt_cache_get_cs_size(pkt_cache));
+
+ cs_log(pkt_cache->cs);
+}
+
+pkt_cache_stats_t pkt_cache_get_stats(pkt_cache_t *pkt_cache) {
+ cs_lru_stats_t lru_stats = cs_get_lru_stats(pkt_cache_get_cs(pkt_cache));
+ pkt_cache_stats_t stats = {
+ .n_pit_entries = (uint32_t)pkt_cache_get_pit_size(pkt_cache),
+ .n_cs_entries = (uint32_t)pkt_cache_get_cs_size(pkt_cache),
+ .n_lru_evictions = (uint32_t)lru_stats.countLruEvictions,
+ };
+
+ return stats;
+}
diff --git a/hicn-light/src/hicn/core/packet_cache.h b/hicn-light/src/hicn/core/packet_cache.h
new file mode 100644
index 000000000..1abdc57c2
--- /dev/null
+++ b/hicn-light/src/hicn/core/packet_cache.h
@@ -0,0 +1,502 @@
+/*
+ * 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.
+ */
+
+/**
+ * \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 two-level hash table.
+ *
+ * Each entry has shared fields, e.g. entry type (PIT or CS) and timestamps,
+ * which are used by both PIT and CS entries. In addition, a C union holds
+ * the PIT or CS specific fields.
+ *
+ * Having a single entry that can hold PIT or CS entries allows to reduce
+ * the number of lookups.
+ *
+ * A prefix hash table <prefix, suffix_hashtable> stores the suffixes associated
+ * to each prefix, where each value in the map points to a separate hash
+ * table <suffix, packet_cache_reference> that can be used to retrieved the
+ * packet cache entry.
+ * When an interest/data packet is received, the prefix and the associated
+ * suffixes are saved; if the next packet cache operation involves the same
+ * prefix, no additional lookups in the prefix hash hashtable are needed.
+ */
+
+#ifndef HICNLIGHT_PACKET_CACHE_H
+#define HICNLIGHT_PACKET_CACHE_H
+
+#include <hicn/util/khash.h>
+#include <hicn/util/slab.h>
+#include "content_store.h"
+#include "pit.h"
+#include "msgbuf_pool.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;
+
+#define foreach_kh_verdict \
+ _(FORWARD_INTEREST) \
+ _(AGGREGATE_INTEREST) \
+ _(RETRANSMIT_INTEREST) \
+ _(FORWARD_DATA) \
+ _(INTEREST_EXPIRED_FORWARD_INTEREST) \
+ _(DATA_EXPIRED_FORWARD_INTEREST) \
+ _(STORE_DATA) \
+ _(CLEAR_DATA) \
+ _(UPDATE_DATA) \
+ _(IGNORE_DATA) \
+ _(ERROR)
+
+typedef enum {
+#define _(x) PKT_CACHE_VERDICT_##x,
+ foreach_kh_verdict
+#undef _
+} pkt_cache_verdict_t;
+
+extern const char *_pkt_cache_verdict_str[];
+
+#define pkt_cache_verdict_str(x) _pkt_cache_verdict_str[x]
+
+#define foreach_kh_lookup \
+ _(INTEREST_NOT_EXPIRED) \
+ _(INTEREST_EXPIRED) \
+ _(DATA_NOT_EXPIRED) \
+ _(DATA_EXPIRED) \
+ _(NONE)
+
+typedef enum {
+#define _(x) PKT_CACHE_LU_##x,
+ foreach_kh_lookup
+#undef _
+} pkt_cache_lookup_t;
+
+KHASH_MAP_INIT_INT(pkt_cache_suffix, unsigned);
+KHASH_INIT(pkt_cache_prefix, const hicn_name_prefix_t *,
+ kh_pkt_cache_suffix_t *, 1, hicn_name_prefix_get_hash,
+ hicn_name_prefix_equals);
+
+typedef struct {
+ hicn_name_t name;
+ 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_prefix_t *prefix_to_suffixes;
+ slab_t *prefix_keys;
+
+ // Cached prefix info to avoid double lookups,
+ // used for both single interest speculation and interest manifest
+ hicn_name_prefix_t cached_prefix;
+ kh_pkt_cache_suffix_t *cached_suffixes;
+} 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);
+
+/**
+ * @brief Add an entry with the specified name to the packet cache.
+ *
+ * @param[in] pkt_cache Pointer to the 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 hicn_name_t to use
+ *
+ * NOTE: unlike other pools, PIT and CS entries allocation does not update the
+ * index as the key is a hicn_name_t * which should point to :
+ * - the name inside the PIT entry (which is thus not set during allocation),
+ * - the name inside the msgbuf_t in the CS entry, which is always available
+ * during the lifetime of the cache entry.
+ *
+ * The index is therefore updated in pkt_cache_add_to_pit and
+ * pkt_cache_add_to_cs functions.
+ *
+ *
+ */
+pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache);
+
+void pkt_cache_add_to_index(const pkt_cache_t *pkt_cache,
+ const pkt_cache_entry_t *entry);
+
+void pkt_cache_remove_from_index(const pkt_cache_t *pkt_cache,
+ const hicn_name_t *name);
+
+/**
+ * @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);
+
+#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 hicn_name_t *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 (PIT entries are left unmodified).
+ *
+ * @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);
+
+pkt_cache_stats_t pkt_cache_get_stats(pkt_cache_t *pkt_cache);
+
+// TODO(eloparco): To implement
+void pkt_cache_print(const pkt_cache_t *pkt_cache);
+
+/************** 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 PIT entry to remove
+ */
+void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache,
+ pkt_cache_entry_t *entry);
+
+/**
+ * @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
+ * @param[in] name Interest name to use; in case of aggregated interests, it is
+ * different from the name stored in the msgbuf
+ * @return pkt_cache_entry_t* Pointer to the packet cache (PIT) entry created
+ */
+pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache,
+ const msgbuf_t *msgbuf,
+ const hicn_name_t *name);
+
+/**
+ * @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
+ * @param[in] name Interest name to use; in case of aggregated interests, it is
+ * different from the name stored in the msgbuf
+ * @return true If aggregation (interest sent from a connection not stored in
+ * the PIT entry)
+ * @return false If retransmission (interest sent from a connection already
+ * 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,
+ const hicn_name_t *name);
+
+/**
+ * @brief Cache prefix info (prefix + associated suffixes) to speed up lookups.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] prefix Name prefix to cache
+ */
+void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache,
+ const hicn_name_prefix_t *prefix);
+
+/**
+ * @brief Reset cached prefix info to force double lookups.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ */
+void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache);
+
+/************ Handle data/interest packets received *******/
+
+/**
+ * @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,
+ const hicn_name_t *name,
+ bool is_serve_from_cs_enabled);
+
+/********* Low-level operations on the hash table *********/
+#ifdef WITH_TESTS
+unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes,
+ hicn_name_suffix_t suffix);
+unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_prefix_t *prefix,
+ hicn_name_suffix_t suffix, slab_t *prefix_keys);
+void __add_suffix(kh_pkt_cache_suffix_t *suffixes, hicn_name_suffix_t suffix,
+ unsigned val);
+void _add_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_prefix_t *prefix,
+ const hicn_name_suffix_t suffix, unsigned val, slab_t *slab);
+void _remove_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const hicn_name_prefix_t *prefix, hicn_name_suffix_t suffix,
+ slab_t *slab);
+void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes);
+kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes,
+ const hicn_name_prefix_t *prefix,
+ bool create, slab_t *prefix_keys);
+#endif
+
+/************** 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..8706a9244
--- /dev/null
+++ b/hicn-light/src/hicn/core/policy_stats.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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, unsigned id,
+ void* data) {
+ policy_stats_mgr_t* mgr = mgr_arg;
+ assert(mgr);
+ assert(id == 0);
+ 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_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);
+ 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);
+
+ 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);
+
+ 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..aee68e515
--- /dev/null
+++ b/hicn-light/src/hicn/core/policy_stats.h
@@ -0,0 +1,92 @@
+
+#ifndef HICNLIGHT_POLICY_STATS_H
+#define HICNLIGHT_POLICY_STATS_H
+
+#ifdef WITH_POLICY_STATS
+
+#include <hicn/policy.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..46c83ef02
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \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);
+}
+
+int strategy_finalize(strategy_entry_t *entry) {
+ return strategy_vft[entry->type]->finalize(entry);
+}
+
+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..9f1a7dac7
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy.h
@@ -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.
+ */
+
+/**
+ * \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);
+
+int strategy_finalize(strategy_entry_t *entry);
+
+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..0af035c88
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy_vft.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \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;
+extern const strategy_ops_t strategy_local_remote;
+
+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,
+ [STRATEGY_TYPE_LOCAL_REMOTE] = &strategy_local_remote,
+#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..55e61db17
--- /dev/null
+++ b/hicn-light/src/hicn/core/strategy_vft.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+/**
+ * \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/random.h"
+#include "../strategies/replication.h"
+
+typedef union {
+ strategy_load_balancer_options_t load_balancer;
+ 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_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_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..fb954a245
--- /dev/null
+++ b/hicn-light/src/hicn/core/subscription.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#include "subscription.h"
+#include <hicn/util/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)))
+
+/*----------------------------------------------------------------------------*
+ * 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_type_str(topic_index));
+ return -1;
+ }
+
+ if (num_duplicates > 0) {
+ DEBUG("Connection %d had already a subscription for topic %s",
+ connection_id, object_type_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_TYPE_UNDEFINED + 1; topic_index < NUM_TOPICS;
+ topic_index++) {
+ printf("topic %s (%lu subscription/s) from connection/s: [ ",
+ object_type_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");
+ }
+}
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..1a04aad75 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,14 @@
# 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
-)
-
-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
+ ${CMAKE_CURRENT_SOURCE_DIR}/base.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tcp.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp.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/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..38d36efbe
--- /dev/null
+++ b/hicn-light/src/hicn/io/base.c
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+/**
+ * @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_set_len(msgbuf, (size_t)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 *sa = &(address->as_sa);
+ 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_set_len(msgbuf, (size_t)n);
+
+#ifdef __APPLE__
+ // set __uint8_t sin_len to 0
+ uint8_t *ptr = (uint8_t *)sa;
+ *ptr = 0x0;
+#endif /* __APPLE__ */
+
+ 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);
+ // INFO("Got n=%d messages", n);
+ 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_set_len(msgbuf[i], msg->msg_len);
+
+ 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..c5859fbe3
--- /dev/null
+++ b/hicn-light/src/hicn/io/hicn.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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(connection_t *connection) { return false; }
+
+static bool connection_hicn_send(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 bool 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..a924b6330
--- /dev/null
+++ b/hicn-light/src/hicn/io/tcp.c
@@ -0,0 +1,532 @@
+/*
+ * 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.
+ */
+
+/**
+ * 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"
+
+// 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(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(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 bool 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..d881b4b01
--- /dev/null
+++ b/hicn-light/src/hicn/io/udp.c
@@ -0,0 +1,565 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file udp.c
+ * #brief Implementation of the native UDP face leveraging the new packet format
+ * to avoid encapsulation.
+ *
+ */
+
+/* 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 <hicn/util/ring.h>
+
+#include "base.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/msgbuf.h"
+
+#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 {
+#ifdef __linux__
+ /* Ring buffer */
+ off_t *ring;
+
+ 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);
+#ifdef __linux__
+ connection_udp_data_t *data = connection->data;
+ assert(data);
+
+ ring_free(data->ring);
+#endif /* __linux__ */
+}
+
+static bool connection_udp_flush(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) == HICN_PACKET_TYPE_DATA) {
+ msgbuf_update_pathlabel(msgbuf, connection_get_id(connection));
+
+ connection->stats.data.tx_pkts++;
+ connection->stats.data.tx_bytes += msgbuf_get_len(msgbuf);
+ } else {
+ connection->stats.interests.tx_pkts++;
+ connection->stats.interests.tx_bytes += msgbuf_get_len(msgbuf);
+ }
+
+ data->iovecs[i].iov_base = msgbuf_get_packet(msgbuf);
+ data->iovecs[i].iov_len = msgbuf_get_len(msgbuf);
+ cpt++;
+ });
+
+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(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) == HICN_PACKET_TYPE_DATA) {
+ msgbuf_update_pathlabel(msgbuf, connection_get_id(connection));
+
+ connection->stats.data.tx_pkts++;
+ connection->stats.data.tx_bytes += msgbuf_get_len(msgbuf);
+ } else {
+ connection->stats.interests.tx_pkts++;
+ connection->stats.interests.tx_bytes += msgbuf_get_len(msgbuf);
+ }
+
+ ssize_t writeLength = write(connection->fd, msgbuf_get_packet(msgbuf),
+ msgbuf_get_len(msgbuf));
+
+ if (writeLength < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ return false;
+ } else {
+ // this print is for debugging
+ printf("Incorrect write length %zd, expected %lu: (%d) %s\n",
+ writeLength, (long unsigned int)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 bool 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 false;
+ }
+#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 false;
+#endif
+
+ return true;
+}
+
+#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..db377aecd 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
@@ -39,7 +43,7 @@ static hicn_conf_t hicn_default_conf = {
struct ip_rule_state_ {
char tun_name[IF_NAMESIZE];
- ip_prefix_t prefix;
+ hicn_ip_prefix_t prefix;
uint32_t table_id;
uint8_t priority;
uint8_t address_family;
@@ -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) {
@@ -197,7 +193,7 @@ int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) {
return b->fd - a->fd;
}
-ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) {
+hicn_ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) {
if (socket->type != HS_CONNECTION) {
return NULL;
}
@@ -245,7 +241,8 @@ int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address,
*/
/* Copy the local IP address inside the connection */
- rc = ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address);
+ rc =
+ hicn_ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address);
if (rc < 0) {
rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR;
goto end;
@@ -255,14 +252,14 @@ end:
return rc;
}
-int hicn_get_local_address(const ip_prefix_t *remote_address,
- ip_prefix_t *local_address) {
+int hicn_get_local_address(const hicn_ip_prefix_t *remote_address,
+ hicn_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));
+ rc = hicn_ip_prefix_ntop_short(remote_address, remote_address_str,
+ sizeof(remote_address_str));
if (rc < 0) {
rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR;
goto ERR;
@@ -293,7 +290,7 @@ ERR:
int hicn_set_remote_endpoint(hicn_socket_t *socket,
const char *remote_ip_address) {
int af, rc = HICN_SOCKET_ERROR_NONE;
- ip_prefix_t addr;
+ hicn_ip_prefix_t addr;
af = get_addr_family(remote_ip_address);
if ((af != AF_INET6) && (af != AF_INET)) {
@@ -301,7 +298,7 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket,
}
/* Bind local endpoint if not done yet */
- if (ip_prefix_empty(&socket->connection.tun_ip_address)) {
+ if (hicn_ip_prefix_empty(&socket->connection.tun_ip_address)) {
char local_ip_address[INET_MAX_ADDRSTRLEN + 4];
/* Local interface id */
@@ -331,7 +328,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 = hicn_ip_prefix_ntop_short(&addr, local_ip_address,
+ sizeof(local_ip_address));
if (rc < 0) {
rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR;
goto ERR;
@@ -448,8 +446,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) {
return rc;
}
- ip_prefix_t ip_prefix;
- rc = ip_prefix_pton(prefix, &ip_prefix);
+ hicn_ip_prefix_t hicn_ip_prefix;
+ rc = hicn_ip_prefix_pton(prefix, &hicn_ip_prefix);
if (rc < 0) {
return rc;
}
@@ -460,16 +458,18 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) {
if (punting_table_id == -1) punting_table_id = socket->connection.table_id;
- rc = ops.add_prio_rule(&ip_prefix, ip_prefix.family, 0,
+ rc = ops.add_prio_rule(&hicn_ip_prefix, hicn_ip_prefix.family, 0,
socket->connection.table_id);
if (rc < 0) {
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;
+ rules_to_remove[rules_counter].prefix = hicn_ip_prefix;
+ rules_to_remove[rules_counter].address_family = hicn_ip_prefix.family;
rules_to_remove[rules_counter].table_id = socket->connection.table_id;
rules_to_remove[rules_counter].priority = 0;
++rules_counter;
@@ -533,7 +533,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 +566,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..3caf9ef1e 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 \
@@ -84,7 +83,7 @@ typedef struct hicn_socket_s {
union {
struct {
- ip_prefix_t tun_ip_address;
+ hicn_ip_prefix_t tun_ip_address;
uint32_t interface_id;
/* ID of the corresponding table : avoid default values of 0, 32766 and
@@ -163,8 +162,8 @@ void hicn_free(hicn_socket_helper_t *hicn);
*
* @return 0 in case of success, -1 otherwise.
*/
-int hicn_get_local_address(const ip_prefix_t *remote_address,
- ip_prefix_t *local_address);
+int hicn_get_local_address(const hicn_ip_prefix_t *remote_address,
+ hicn_ip_prefix_t *local_address);
/* hICN socket */
diff --git a/hicn-light/src/hicn/socket/ops.h b/hicn-light/src/hicn/socket/ops.h
index 1bee7c6f6..854b0c461 100644
--- a/hicn-light/src/hicn/socket/ops.h
+++ b/hicn-light/src/hicn/socket/ops.h
@@ -17,10 +17,10 @@ typedef struct {
int (*get_output_ifid)(const char *ip_address, uint8_t address_family,
uint32_t *interface_id);
int (*get_ip_addr)(uint32_t interface_id, uint8_t address_family,
- ip_prefix_t *ip_address);
- int (*set_ip_addr)(uint32_t interface_id, ip_prefix_t *ip_address);
+ hicn_ip_prefix_t *ip_address);
+ int (*set_ip_addr)(uint32_t interface_id, hicn_ip_prefix_t *ip_address);
int (*up_if)(uint32_t interface_id);
- int (*add_in_route_table)(const ip_prefix_t *prefix,
+ int (*add_in_route_table)(const hicn_ip_prefix_t *prefix,
const uint32_t interface_id,
const uint8_t table_id);
int (*add_in_route_table_s)(const char *prefix, const uint32_t interface_id,
@@ -30,23 +30,23 @@ typedef struct {
const uint8_t table_id, int default_route);
int (*del_out_route)(const char *gateway, const uint8_t address_family,
const uint8_t table_id);
- int (*del_lo_route)(const ip_prefix_t *ip_address);
+ int (*del_lo_route)(const hicn_ip_prefix_t *ip_address);
int (*add_rule)(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
int (*del_rule)(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
- int (*add_neigh_proxy)(const ip_prefix_t *ip_address,
+ int (*add_neigh_proxy)(const hicn_ip_prefix_t *ip_address,
const uint32_t interface_id);
- int (*add_prio_rule)(const ip_prefix_t *ip_address,
+ int (*add_prio_rule)(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
- int (*add_lo_prio_rule)(const ip_prefix_t *ip_address,
+ int (*add_lo_prio_rule)(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family,
const uint32_t priority);
- int (*del_prio_rule)(const ip_prefix_t *ip_address,
+ int (*del_prio_rule)(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
- int (*del_lo_prio_rule)(const ip_prefix_t *ip_address,
+ int (*del_lo_prio_rule)(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family,
const uint32_t priority);
} hicn_socket_ops_t;
diff --git a/hicn-light/src/hicn/socket/ops_linux.c b/hicn-light/src/hicn/socket/ops_linux.c
index 8bfc438f3..a3675e929 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 */
@@ -60,13 +62,13 @@ int _nl_get_output_ifid(const char *ip_address, uint8_t address_family,
* @see getifaddrs
*/
int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family,
- ip_prefix_t *ip_address);
+ hicn_ip_prefix_t *ip_address);
-int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *ip_address);
+int _nl_set_ip_addr(uint32_t interface_id, hicn_ip_prefix_t *ip_address);
int _nl_up_if(uint32_t interface_id);
-int _nl_add_in_route_table(const ip_prefix_t *prefix,
+int _nl_add_in_route_table(const hicn_ip_prefix_t *prefix,
const uint32_t interface_id, const uint8_t table_id);
int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id,
const uint8_t table_id);
@@ -77,25 +79,25 @@ int _nl_add_out_route(const char *gateway, const uint8_t address_family,
int _nl_del_out_route(const char *gateway, const uint8_t address_family,
const uint8_t table_id);
-int _nl_del_lo_route(const ip_prefix_t *ip_address);
+int _nl_del_lo_route(const hicn_ip_prefix_t *ip_address);
int _nl_add_rule(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
int _nl_del_rule(const char *interface_name, const uint8_t address_family,
const uint8_t table_id);
-int _nl_add_neigh_proxy(const ip_prefix_t *ip_address,
+int _nl_add_neigh_proxy(const hicn_ip_prefix_t *ip_address,
const uint32_t interface_id);
-int _nl_add_prio_rule(const ip_prefix_t *ip_address,
+int _nl_add_prio_rule(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
-int _nl_add_lo_prio_rule(const ip_prefix_t *ip_address,
+int _nl_add_lo_prio_rule(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority);
-int _nl_del_prio_rule(const ip_prefix_t *ip_address,
+int _nl_del_prio_rule(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority,
const uint8_t table_id);
-int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address,
+int _nl_del_lo_prio_rule(const hicn_ip_prefix_t *ip_address,
const uint8_t address_family, const uint32_t priority);
#endif /* HICN_NETLINK_H */
@@ -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)},
@@ -530,7 +533,7 @@ ERR:
}
int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family,
- ip_prefix_t *prefix) {
+ hicn_ip_prefix_t *prefix) {
char buffer[BUFSIZE];
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
@@ -599,7 +602,7 @@ ERR_SOCKET:
return HICN_SOCKET_ERROR_UNSPEC;
}
-int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) {
+int _nl_set_ip_addr(uint32_t interface_id, hicn_ip_prefix_t *prefix) {
char buffer[BUFSIZE];
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
@@ -619,15 +622,15 @@ int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) {
.payload.ifa_index = interface_id};
/* Set attributes = length/type/value */
- struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(prefix->family)),
+ struct rtattr ifa_address = {RTA_LENGTH(hicn_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 =
+ hicn_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, hicn_ip_address_len(prefix->family)},
};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
@@ -965,7 +968,7 @@ ERR_SOCKET:
* ip route del 1:2::2 dev lo table local
*
*/
-int _nl_del_lo_route(const ip_prefix_t *prefix) {
+int _nl_del_lo_route(const hicn_ip_prefix_t *prefix) {
char buffer[BUFSIZE];
struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
size_t n;
@@ -991,16 +994,17 @@ int _nl_del_lo_route(const ip_prefix_t *prefix) {
/* Set attribute = length/type/value */
uint32_t one = 1;
- struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST};
+ struct rtattr a_dst = {RTA_LENGTH(hicn_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 void *address =
+ hicn_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)},
+ {(void *)address, hicn_ip_address_len(prefix->family)},
/* Interface id */
{&a_ifid_lo, sizeof(a_ifid_lo)},
{&one, sizeof(one)}};
@@ -1048,7 +1052,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 +1098,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) {
@@ -1131,7 +1135,7 @@ ERR_SOCKET:
* ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei
*
*/
-int _nl_add_neigh_proxy(const ip_prefix_t *prefix,
+int _nl_add_neigh_proxy(const hicn_ip_prefix_t *prefix,
const uint32_t interface_id) {
/* Buffer for holding the response, with appropriate casting on the header */
char buffer[BUFSIZE];
@@ -1156,18 +1160,19 @@ 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};
+ struct rtattr a_dst = {RTA_LENGTH(hicn_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 =
+ hicn_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, hicn_ip_address_len(prefix->family)},
};
msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov));
@@ -1205,7 +1210,7 @@ ERR:
/* ip -6 route add 0:1::/64 dev hicn-if0 table 100 */
/* ip -6 route add 0:2::/64 dev hicn-if1 table 100 */
-int _nl_add_in_route_table(const ip_prefix_t *prefix,
+int _nl_add_in_route_table(const hicn_ip_prefix_t *prefix,
const uint32_t interface_id,
const uint8_t table_id) {
/* Buffer for holding the response, with appropriate casting on the header */
@@ -1237,19 +1242,20 @@ int _nl_add_in_route_table(const ip_prefix_t *prefix,
};
/* Message attributes = length/type/value */
- struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST};
+ struct rtattr a_dst = {RTA_LENGTH(hicn_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 =
+ hicn_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, hicn_ip_address_len(prefix->family)},
/* Output interface */
{&a_oif, sizeof(a_oif)},
{(void *)&interface_id, sizeof(uint32_t)},
@@ -1293,9 +1299,9 @@ ERR:
int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id,
const uint8_t table_id) {
int rc;
- ip_prefix_t ip_address;
+ hicn_ip_prefix_t ip_address;
- rc = ip_prefix_pton(prefix, &ip_address);
+ rc = hicn_ip_prefix_pton(prefix, &ip_address);
if (rc < 0) {
return rc;
}
@@ -1308,7 +1314,7 @@ int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) {
}
/* ip -6 rule add from b001::/16 prio 0 table 100 */
-int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
+int _nl_add_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family,
const uint32_t priority, const uint8_t table_id) {
/* Buffer for holding the response, with appropriate casting on the header */
char buffer[BUFSIZE];
@@ -1343,18 +1349,19 @@ int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
if (prefix) {
/* Message attributes = length/type/value */
- struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC};
+ struct rtattr a_src = {RTA_LENGTH(hicn_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 =
+ hicn_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, hicn_ip_address_len(prefix->family)},
/* Priority */
{&a_prio, sizeof(a_prio)},
{(void *)&priority, sizeof(uint32_t)},
@@ -1405,14 +1412,13 @@ ERR:
return HICN_SOCKET_ERROR_UNSPEC;
}
-int _nl_add_lo_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
+int _nl_add_lo_prio_rule(const hicn_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 */
-int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
+int _nl_del_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family,
const uint32_t priority, const uint8_t table_id) {
/* Buffer for holding the response, with appropriate casting on the header */
char buffer[BUFSIZE];
@@ -1447,19 +1453,20 @@ int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family,
/* Message attributes = length/type/value */
if (prefix) {
- struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC};
+ struct rtattr a_src = {RTA_LENGTH(hicn_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 =
+ hicn_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, hicn_ip_address_len(prefix->family)},
/* Priority */
{&a_prio, sizeof(a_prio)},
{(void *)&priority, sizeof(uint32_t)},
@@ -1512,8 +1519,8 @@ ERR:
return HICN_SOCKET_ERROR_UNSPEC;
}
-int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, uint8_t address_family,
- const uint32_t priority) {
+int _nl_del_lo_prio_rule(const hicn_ip_prefix_t *ip_address,
+ uint8_t address_family, const uint32_t priority) {
return _nl_del_prio_rule(ip_address, address_family, priority,
RT_TABLE_LOCAL);
}
@@ -1539,7 +1546,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 +1570,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 +1584,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..754974ee4 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}/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
+ ${CMAKE_CURRENT_SOURCE_DIR}/local_remote.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}/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
+ ${CMAKE_CURRENT_SOURCE_DIR}/local_remote.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..9223cc8ac
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/best_path.c
@@ -0,0 +1,353 @@
+/*
+ * 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 <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);
+
+ /* Backup flags and cur_len: because our code is called from
+ * strategy_on_data / check_stop_probing / stop_probing
+ * which does not expect the nexthop flags to be modified.
+ */
+ uint_fast32_t flags = nexthops->flags;
+ size_t cur_len = nexthops_get_curlen(nexthops);
+
+ nexthops_select(nexthops, offset);
+ update_remote_node_paths(nexthops, entry->forwarder, options->local_prefixes);
+
+ /* Restore flags & curlen */
+ nexthops->flags = flags;
+ nexthops->cur_elts = cur_len;
+}
+
+// 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;
+ best_nexthop = state->best_nexthop;
+ 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;
+
+ 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);
+
+ // TODO explain the purpose of this test
+ 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 = hicn_name_get_suffix(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 = hicn_name_get_suffix(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;
+ }
+
+ 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..0e1a170f7
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/load_balancer.c
@@ -0,0 +1,148 @@
+/*
+ * 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 <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) {
+ 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) {
+ if (nexthops_get_curlen(nexthops) == 0) return nexthops;
+ /* Compute the sum of weights of potential next hops */
+ double sum = 0;
+ 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.
+ */
+ nexthops_foreach(timeout_nexthops, timeout_nexthop, {
+ 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..fb161ab2a
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/local_prefixes.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2021-2023 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/mapme.h>
+
+#define MAX_PREFIXES 10
+
+struct local_prefixes_s {
+ hicn_prefix_t 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(const local_prefixes_t *prefixes,
+ const hicn_prefix_t *prefix) {
+ for (unsigned i = 0; i < prefixes->len; i++) {
+ if (hicn_prefix_equals(&(prefixes->local_prefixes[i]), prefix)) 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]))) {
+ hicn_prefix_copy(&prefixes->local_prefixes[prefixes->len],
+ &new_prefixes->local_prefixes[i]);
+ prefixes->len++;
+ }
+ i++;
+ }
+}
+
+void local_prefixes_add_prefix(local_prefixes_t *prefixes,
+ const hicn_prefix_t *prefix) {
+ if (prefixes->len >= MAX_PREFIXES) return;
+ if (!contain_prefix(prefixes, prefix)) {
+ hicn_prefix_copy(&(prefixes->local_prefixes[prefixes->len]), prefix);
+ 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_prefix(fib, &prefixes->local_prefixes[i]);
+ if (!entry) continue;
+ // XXX we don't want to force
+ mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops, NULL);
+ }
+}
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..9d7d8ec78
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/local_prefixes.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * 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
+
+#include <hicn/name.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 hicn_prefix_t* 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/local_remote.c b/hicn-light/src/hicn/strategies/local_remote.c
new file mode 100644
index 000000000..7edf62643
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/local_remote.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/core/nexthops.h>
+#include <hicn/core/forwarder.h>
+
+#include "local_remote.h"
+
+static int strategy_local_remote_initialize(strategy_entry_t *entry,
+ const void *forwarder) {
+ printf("INIT FWD STRATEGY REMOTE LOCAL\n");
+ srand((unsigned int)time(NULL));
+ entry->forwarder = forwarder;
+ return 0;
+}
+
+static int strategy_local_remote_finalize(strategy_entry_t *entry) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_local_remote_add_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static int strategy_local_remote_remove_nexthop(strategy_entry_t *entry,
+ nexthops_t *nexthops,
+ off_t offset) {
+ /* Nothing to do */
+ return 0;
+}
+
+static nexthops_t *strategy_local_remote_lookup_nexthops(
+ strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) {
+ if (!entry->forwarder) {
+ // the forwarder does not exists, drop packet
+ nexthops_disable_all(nexthops);
+ return nexthops;
+ }
+
+ unsigned cid = msgbuf_get_connection_id(msgbuf);
+ connection_table_t *table = forwarder_get_connection_table(entry->forwarder);
+ if (!table) {
+ // the connection table does not exists, drop packet.
+ nexthops_disable_all(nexthops);
+ return nexthops;
+ }
+
+ connection_t *in = connection_table_get_by_id(table, cid);
+ if (!in) {
+ // the ingress connection does not exists, drop packet.
+ nexthops_disable_all(nexthops);
+ return nexthops;
+ }
+
+ bool in_is_local = connection_is_local(in);
+ nexthops_enumerate(nexthops, i, nexthop, {
+ connection_t *out = connection_table_get_by_id(table, nexthop);
+ if (out) {
+ if (connection_is_local(out) != in_is_local) {
+ // this connection satisfies the requirements, send the intetest here.
+ nexthops_select(nexthops, i);
+ return nexthops;
+ }
+ }
+ });
+
+ // no out connection satisfies the requirements, drop packet.
+ nexthops_disable_all(nexthops);
+ return nexthops;
+}
+
+static int strategy_local_remote_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_local_remote_on_timeout(
+ strategy_entry_t *entry, nexthops_t *nexthops,
+ const nexthops_t *timeout_nexthops) {
+ /* Nothing to do */
+ return 0;
+}
+
+DECLARE_STRATEGY(local_remote);
diff --git a/hicn-light/src/hicn/strategies/local_remote.h b/hicn-light/src/hicn/strategies/local_remote.h
new file mode 100644
index 000000000..58ca5abc3
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/local_remote.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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. If the incoming interest arrives from a local face,
+ * the interest shuold be forwarded only on a remote face. Viceversa, if the
+ * interest comes from remote it should be sent to a local face. Notice that if
+ * the condition cannot be satified (e.g. an interest comes from a local face
+ * and only an other local face can be satified to send the interest) the
+ * interest is dropped
+ */
+
+#ifndef HICNLIGHT_STRATEGY_LOCAL_REMOTE_H
+#define HICNLIGHT_STRATEGY_LOCAL_REMOTE_H
+
+typedef struct {
+ void *_;
+} strategy_loc_rem_nexthop_state_t;
+
+typedef struct {
+ void *_;
+} strategy_loc_rem_state_t;
+
+typedef struct {
+ void *_;
+} strategy_loc_rem_options_t;
+
+#endif /* HICNLIGHT_STRATEGY_LOCAL_REMOTE_H */
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/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..fd0bf5471
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/probe_generator.c
@@ -0,0 +1,113 @@
+/*
+ * 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 "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);
+ 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;
+ msgbuf_modify_suffix(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..065d824a1
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/probe_generator.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef HICNLIGHT_PROBE_GENERATOR
+#define HICNLIGHT_PROBE_GENERATOR
+
+#include <hicn/util/khash.h>
+#include <hicn/core/ticks.h>
+#include <hicn/core/msgbuf.h>
+
+#define MIN_PROBE_SUFFIX 0xefffffff
+#define MAX_PROBE_SUFFIX 0xffffffff - 1
+
+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..aabae73bc
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/random.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <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) {
+ if (nexthops_get_curlen(nexthops) == 0) return nexthops;
+ 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/strategies/loadBalancer.h b/hicn-light/src/hicn/strategies/random.h
index 74920768d..bdea5e4dd 100644
--- a/hicn-light/src/hicn/strategies/loadBalancer.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 @@
*/
/**
- * Forward on the less loaded path
+ * Forward randomly
*/
-#ifndef loadBalancer_h
-#define loadBalancer_h
+#ifndef HICNLIGHT_STRATEGY_RANDOM_H
+#define HICNLIGHT_STRATEGY_RANDOM_H
-#include <hicn/strategies/strategyImpl.h>
+typedef struct {
+ void *_;
+} strategy_random_nexthop_state_t;
-StrategyImpl *strategyLoadBalancer_Create();
+typedef struct {
+ void *_;
+} strategy_random_state_t;
-#endif // loadBalancer_h
+typedef struct {
+ void *_;
+} strategy_random_options_t;
+
+#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..395b6e333
--- /dev/null
+++ b/hicn-light/src/hicn/test/CMakeLists.txt
@@ -0,0 +1,40 @@
+# Copyright (c) 2021-2022 Cisco and/or its affiliates.
+
+include(BuildMacros)
+
+list(APPEND TESTS_SRC
+ test-configuration.cc
+ test-fib.cc
+ test-loop.cc
+ test-parser.cc
+ test-ctrl.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-strategy-local-remote.cc
+ test-subscription.cc
+ test-local_prefixes.cc
+ test-probe_generator.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/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}"
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
+
+add_test_internal(hicn_light_tests)
diff --git a/hicn-light/src/hicn/strategies/rnd.h b/hicn-light/src/hicn/test/main.cc
index 78fb34758..49cc28f66 100644
--- a/hicn-light/src/hicn/strategies/rnd.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 randomly
- */
-
-#ifndef rnd_h
-#define rnd_h
-
-#include <hicn/strategies/strategyImpl.h>
-
-StrategyImpl* strategyRnd_Create();
+#include <gtest/gtest.h>
-#endif // rnd_h
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
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..2d3b5329f
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-configuration.cc
@@ -0,0 +1,83 @@
+/*
+ * 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);
+ configuration_flush_log();
+}
+
+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..6723d0ff1
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-connection_table.cc
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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>
+#include <hicn/util/log.h>
+#include <hicn/validation.h>
+}
+
+#define CONNECTION_NAME "conn_name"
+#define CONNECTION_NAME_2 "conn_name_2"
+
+class ConnectionTableTest : public ::testing::Test {
+ protected:
+ ConnectionTableTest() {
+ assert(is_symbolic_name(CONNECTION_NAME, SYMBOLIC_NAME_LEN));
+ assert(is_symbolic_name(CONNECTION_NAME_2, SYMBOLIC_NAME_LEN));
+
+ log_conf.log_level = LOG_WARN;
+
+ 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) {
+ // Set verbose log level
+ int old_log_level = log_conf.log_level;
+ log_conf.log_level = LOG_INFO;
+
+ connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
+ connection_->type = FACE_TYPE_TCP;
+
+ // 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"));
+
+ log_conf.log_level = old_log_level; // Restore old log level
+}
+
+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"));
+}
+
+TEST_F(ConnectionTableTest, GenerateConnName) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(conn_table_, conn_name);
+ EXPECT_EQ(rc, 0);
+
+ connection_ = connection_table_allocate(conn_table_, &pair_, conn_name);
+ connection_->type = FACE_TYPE_TCP;
+ connection_->pair = pair_;
+
+ char conn_name2[SYMBOLIC_NAME_LEN];
+ rc = connection_table_get_random_name(conn_table_, conn_name2);
+ EXPECT_EQ(rc, 0);
+ EXPECT_NE(strncmp(conn_name, conn_name2, SYMBOLIC_NAME_LEN), 0);
+}
+
+TEST_F(ConnectionTableTest, GenerateConnNameExhaustion) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ bool unable_to_allocate = false;
+
+ // Force name exhaustion
+ int n_connections = 1 + USHRT_MAX;
+ for (int i = 0; i <= n_connections; i++) {
+ int rc = connection_table_get_random_name(conn_table_, conn_name);
+ if (rc < 0) {
+ unable_to_allocate = true;
+ break;
+ }
+
+ address_pair_t pair =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(i));
+ connection_t *conn =
+ connection_table_allocate(conn_table_, &pair, conn_name);
+ memset(conn, 0, sizeof(connection_t));
+ conn->type = FACE_TYPE_TCP;
+ conn->pair = pair;
+ }
+
+ EXPECT_TRUE(unable_to_allocate);
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test-ctrl.cc b/hicn-light/src/hicn/test/test-ctrl.cc
new file mode 100644
index 000000000..f0d3e7c37
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-ctrl.cc
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/ctrl/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(FORWARDER_TYPE_HICNLIGHT);
+ }
+ 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.
+ */
+#if 0
+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_EQ(success, false);
+}
+
+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);
+}
+
+TEST_F(CtrlTest, RouteNameOrID) {
+ hc_route_t route = {
+ .face_id = (face_id_t)INVALID_FACE_ID,
+ .family = AF_INET6,
+ .remote_addr = IPV6_LOOPBACK,
+ .len = 64,
+ .cost = 1,
+ };
+
+ // At least one between name (symbolic or ID) and face_id
+ // should be set to make the route valid
+
+ // Valid name (symbolic)
+ snprintf(route.name, SYMBOLIC_NAME_LEN, "%s", "test");
+ EXPECT_EQ(hc_route_validate(&route), 0);
+
+ // Valid name (ID)
+ snprintf(route.name, SYMBOLIC_NAME_LEN, "%s", "conn0");
+ EXPECT_EQ(hc_route_validate(&route), 0);
+
+ // Valid face_id
+ route.face_id = 1;
+ snprintf(route.name, SYMBOLIC_NAME_LEN, "%s", "");
+ EXPECT_EQ(hc_route_validate(&route), 0);
+
+ // Invalid name stating with number
+ // (face_id is only checked if empty name)
+ route.face_id = 1;
+ snprintf(route.name, SYMBOLIC_NAME_LEN, "%s", "1test");
+ EXPECT_EQ(hc_route_validate(&route), -1);
+}
+#endif
diff --git a/hicn-light/src/hicn/test/test-fib.cc b/hicn-light/src/hicn/test/test-fib.cc
new file mode 100644
index 000000000..5068b4fa2
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-fib.cc
@@ -0,0 +1,338 @@
+/*
+ * 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 <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 <vector>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/util/ip_address.h>
+#include <hicn/config/configuration.h>
+#include <hicn/core/forwarder.h>
+#include <hicn/core/fib.h>
+}
+
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+#define ARRAY_SIZE(a) ((sizeof(a) / sizeof(*(a))))
+
+class FibTest : public ::testing::Test {
+ protected:
+ FibTest() { fib = fib_create(NULL); }
+ virtual ~FibTest() { fib_free(fib); }
+
+ configuration_t *configuration;
+ forwarder_t *forwarder;
+ fib_t *fib;
+};
+
+fib_entry_t *_fib_add_prefix(fib_t *fib, const hicn_prefix_t *prefix,
+ std::vector<uint32_t> &nexthops) {
+ fib_entry_t *entry =
+ fib_entry_create(prefix, STRATEGY_TYPE_UNDEFINED, NULL, NULL);
+ for (size_t i = 0; i < nexthops.size(); i++)
+ fib_entry_nexthops_add(entry, nexthops[i]);
+ fib_add(fib, entry);
+ return entry;
+}
+
+int compare_str_prefix_to_prefix(char *p1, hicn_prefix_t *p2) {
+ char prefix_s[MAXSZ_IP_PREFIX];
+ hicn_ip_prefix_t ipp;
+ hicn_prefix_get_ip_prefix(p2, &ipp);
+ hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX,
+ (const hicn_ip_prefix_t *)&ipp);
+ return strcmp(prefix_s, p1);
+}
+
+#define HICN_PREFIX(P, STR) \
+ hicn_prefix_t P; \
+ hicn_ip_prefix_t _##P; \
+ EXPECT_EQ(hicn_ip_prefix_pton(STR, &_##P), 0); \
+ EXPECT_EQ(hicn_prefix_create_from_ip_prefix(&_##P, &P), 0);
+
+/* TEST: Fib allocation and initialization */
+TEST_F(FibTest, FibAddOne) {
+ /* Empty fib should be valid */
+
+ HICN_PREFIX(pfx, "1122:3344:5566:7788:9900:aabb:ccdd:eeff/4");
+
+ const hicn_prefix_t *empty_prefix_array[] = {};
+ bool empty_used_array[] = {};
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, empty_prefix_array, empty_used_array));
+
+ const hicn_prefix_t *prefix_array[] = {&pfx};
+ bool used_array[] = {true};
+
+ std::vector<uint32_t> empty_nexthop;
+ for (unsigned i = 0; i < ARRAY_SIZE(prefix_array); i++) {
+ if (!used_array[i]) continue;
+ _fib_add_prefix(fib, prefix_array[i], empty_nexthop);
+ }
+
+ fib_dump(fib);
+
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array, used_array));
+
+ /* Check that free indices and bitmaps are correctly updated */
+}
+
+TEST_F(FibTest, FibAddTwo) {
+ HICN_PREFIX(b001, "b001::/64");
+ HICN_PREFIX(c001, "c001::/64");
+ HICN_PREFIX(inner_8000_1, "8000::/1");
+
+ const hicn_prefix_t *prefix_array[] = {&b001, &inner_8000_1, &c001};
+ bool used_array[] = {true, false, true};
+
+ std::vector<uint32_t> empty_nexthop;
+ _fib_add_prefix(fib, &b001, empty_nexthop);
+ _fib_add_prefix(fib, &c001, empty_nexthop);
+
+ fib_dump(fib);
+
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array, used_array));
+}
+
+TEST_F(FibTest, FibAddFive) {
+ HICN_PREFIX(b002, "b002::/64");
+ HICN_PREFIX(b002_abcd_0, "b002::abcd:0:0:0/128");
+ HICN_PREFIX(b002_2, "b002::2/128");
+ HICN_PREFIX(b002_abcd_1, "b002::abcd:0:0:1/128");
+ HICN_PREFIX(b002_3, "b002::3/128");
+ HICN_PREFIX(inner_b002_2, "b002::2/127");
+ HICN_PREFIX(inner_b002_abcd_0, "b002::abcd:0:0:0/127");
+
+ const hicn_prefix_t *prefix_array[] = {
+ &b002_2, &inner_b002_2, &b002_3, &b002,
+ &b002_abcd_0, &inner_b002_abcd_0, &b002_abcd_1};
+ bool used_array[] = {true, false, true, true, true, false, true};
+
+ std::vector<uint32_t> empty_nexthop;
+ _fib_add_prefix(fib, &b002, empty_nexthop);
+ _fib_add_prefix(fib, &b002_abcd_0, empty_nexthop);
+ _fib_add_prefix(fib, &b002_2, empty_nexthop);
+ _fib_add_prefix(fib, &b002_abcd_1, empty_nexthop);
+ _fib_add_prefix(fib, &b002_3, empty_nexthop);
+
+ fib_dump(fib);
+
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array, used_array));
+}
+
+TEST_F(FibTest, FibAddRemove) {
+ HICN_PREFIX(b002_64, "b002::/64");
+ HICN_PREFIX(b002_128, "b002::/128");
+
+ const hicn_prefix_t *prefix_array_1[] = {&b002_128};
+ bool used_array_1[] = {true};
+ const hicn_prefix_t *prefix_array_2[] = {};
+ bool used_array_2[] = {};
+ const hicn_prefix_t *prefix_array_3[] = {&b002_64};
+ bool used_array_3[] = {true};
+
+ std::vector<uint32_t> empty_nexthop;
+ fib_entry_t *entry = _fib_add_prefix(fib, &b002_128, empty_nexthop);
+ fib_dump(fib);
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array_1, used_array_1));
+
+ fib_remove_entry(fib, entry);
+ fib_dump(fib);
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array_2, used_array_2));
+
+ entry = _fib_add_prefix(fib, &b002_64, empty_nexthop);
+ fib_dump(fib);
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array_3, used_array_3));
+}
+
+TEST_F(FibTest, FibAddNested) {
+ HICN_PREFIX(b002_64, "b002::/64");
+ HICN_PREFIX(b002_128, "b002::/128");
+
+ const hicn_prefix_t *prefix_array_1[] = {&b002_128};
+ bool used_array_1[] = {true};
+ const hicn_prefix_t *prefix_array_2[] = {&b002_128, &b002_64};
+ bool used_array_2[] = {true, true};
+
+ std::vector<uint32_t> empty_nexthop;
+ _fib_add_prefix(fib, &b002_128, empty_nexthop);
+ fib_dump(fib);
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array_1, used_array_1));
+
+ _fib_add_prefix(fib, &b002_64, empty_nexthop);
+ fib_dump(fib);
+ EXPECT_TRUE(fib_is_valid(fib));
+ EXPECT_TRUE(fib_check_preorder(fib, prefix_array_2, used_array_2));
+}
+
+TEST_F(FibTest, IRIStest) {
+ char p_0_s[] = "b001:0:0:3039::/64";
+ char p_1_3_s[] = "b001::3039:0:1:2:0/128";
+ HICN_PREFIX(p_0, p_0_s);
+
+ HICN_PREFIX(p_1_2, "b001::3039:0:1:0:0/128");
+ HICN_PREFIX(p_1_1, "b001::3039:0:1:0:100/128");
+ HICN_PREFIX(p_1_3, p_1_3_s);
+ HICN_PREFIX(p_1_4, "b001::3039:0:1:0:102/128");
+
+ HICN_PREFIX(p_2_2, "b001::3039:0:2:0:0/128");
+ HICN_PREFIX(p_2_1, "b001::3039:0:2:0:100/128");
+ HICN_PREFIX(p_2_3, "b001::3039:0:2:2:0/128");
+ HICN_PREFIX(p_2_4, "b001::3039:0:2:0:102/128");
+
+ HICN_PREFIX(to_match1, "b001::3039:0:1:0:101/128");
+ HICN_PREFIX(to_match2, "b001:0:0:3039:ffff:ffff::/128");
+ HICN_PREFIX(to_match3, "b001:1::/128");
+ HICN_PREFIX(to_match4, "b001::3039:0:1:2:0/128");
+
+ std::vector<uint32_t> nexthop;
+ nexthop.push_back(2); // add nexthop 2 to the fib entry
+ /*** add ***/
+ _fib_add_prefix(fib, &p_0, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+
+ _fib_add_prefix(fib, &p_1_1, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+
+ _fib_add_prefix(fib, &p_1_2, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+
+ _fib_add_prefix(fib, &p_1_3, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+
+ _fib_add_prefix(fib, &p_1_4, nexthop);
+ fib_dump(fib);
+ EXPECT_TRUE(fib_is_valid(fib));
+
+ /*** match ***/
+ fib_entry_t *entry = fib_match_prefix(fib, &to_match1);
+ // the matching prefix should be p0
+ EXPECT_TRUE(entry != NULL);
+ if (entry) {
+ int ret = compare_str_prefix_to_prefix(p_0_s, &(entry->prefix));
+ EXPECT_EQ(ret, 0);
+ }
+
+ entry = fib_match_prefix(fib, &to_match2);
+ // the matching prefix should be p0
+ EXPECT_TRUE(entry != NULL);
+ if (entry) {
+ int ret = compare_str_prefix_to_prefix(p_0_s, &(entry->prefix));
+ EXPECT_EQ(ret, 0);
+ }
+
+ entry = fib_match_prefix(fib, &to_match3);
+ // we expect no match
+ EXPECT_FALSE(entry != NULL);
+
+ entry = fib_match_prefix(fib, &to_match4);
+ // the matching prefix should be p_1_3
+ EXPECT_TRUE(entry != NULL);
+ if (entry) {
+ int ret = compare_str_prefix_to_prefix(p_1_3_s, &(entry->prefix));
+ EXPECT_EQ(ret, 0);
+ }
+
+ /*** remove ***/
+ fib_remove(fib, &p_0, nexthop[0]);
+ EXPECT_TRUE(fib_is_valid(fib));
+ fib_remove(fib, &p_1_1, nexthop[0]);
+ EXPECT_TRUE(fib_is_valid(fib));
+ fib_remove(fib, &p_1_2, nexthop[0]);
+ EXPECT_TRUE(fib_is_valid(fib));
+ fib_remove(fib, &p_1_3, nexthop[0]);
+ EXPECT_TRUE(fib_is_valid(fib));
+ fib_remove(fib, &p_1_4, nexthop[0]);
+ EXPECT_TRUE(fib_is_valid(fib));
+ fib_dump(fib);
+
+ /*** match ***/
+ entry = fib_match_prefix(fib, &to_match1);
+ // we expect no match
+ EXPECT_FALSE(entry != NULL);
+
+ entry = fib_match_prefix(fib, &to_match2);
+ // we expect no match
+ EXPECT_FALSE(entry != NULL);
+
+ entry = fib_match_prefix(fib, &to_match3);
+ // we expect no match
+ EXPECT_FALSE(entry != NULL);
+
+ entry = fib_match_prefix(fib, &to_match4);
+ // we expect no match
+ EXPECT_FALSE(entry != NULL);
+
+ // add again
+ _fib_add_prefix(fib, &p_0, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+ _fib_add_prefix(fib, &p_2_1, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+ _fib_add_prefix(fib, &p_2_2, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+ _fib_add_prefix(fib, &p_2_3, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+ _fib_add_prefix(fib, &p_2_4, nexthop);
+ EXPECT_TRUE(fib_is_valid(fib));
+ fib_dump(fib);
+
+ entry = fib_match_prefix(fib, &to_match1);
+ // the matching prefix should be p0
+ EXPECT_TRUE(entry != NULL);
+ if (entry) {
+ int ret = compare_str_prefix_to_prefix(p_0_s, &(entry->prefix));
+ EXPECT_EQ(ret, 0);
+ }
+
+ entry = fib_match_prefix(fib, &to_match2);
+ // the matching prefix should be p0
+ EXPECT_TRUE(entry != NULL);
+ if (entry) {
+ int ret = compare_str_prefix_to_prefix(p_0_s, &(entry->prefix));
+ EXPECT_EQ(ret, 0);
+ }
+
+ entry = fib_match_prefix(fib, &to_match3);
+ // we expect no match
+ EXPECT_FALSE(entry != NULL);
+
+ entry = fib_match_prefix(fib, &to_match4);
+ // the matching prefix should be p0
+ EXPECT_TRUE(entry != NULL);
+ if (entry) {
+ int ret = compare_str_prefix_to_prefix(p_0_s, &(entry->prefix));
+ EXPECT_EQ(ret, 0);
+ }
+}
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..6bd2a6ab7
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-listener_table.cc
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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>
+#include <hicn/util/log.h>
+#include <hicn/validation.h>
+}
+
+#define LISTENER_NAME "listener_name"
+#define LISTENER_NAME_2 "listener_name_2"
+
+class ListenerTableTest : public ::testing::Test {
+ protected:
+ ListenerTableTest() {
+ assert(is_symbolic_name(LISTENER_NAME, SYMBOLIC_NAME_LEN));
+ assert(is_symbolic_name(LISTENER_NAME_2, SYMBOLIC_NAME_LEN));
+
+ 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
+ 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..52b1c746e
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-local_prefixes.cc
@@ -0,0 +1,252 @@
+/*
+ * 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 <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>
+}
+
+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) {
+ int rc;
+ local_prefixes_t *lp = create_local_prefixes();
+ EXPECT_FALSE(lp == nullptr);
+
+ hicn_ip_address_t result = IP_ADDRESS_EMPTY;
+ hicn_ip_address_pton(name_str1, &result);
+ hicn_prefix_t name1;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name1);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str2, &result);
+ hicn_prefix_t name2;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name2);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str3, &result);
+ hicn_prefix_t name3;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name3);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str4, &result);
+ hicn_prefix_t name4;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name4);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str5, &result);
+ hicn_prefix_t name5;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name5);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str6, &result);
+ hicn_prefix_t name6;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name6);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str7, &result);
+ hicn_prefix_t name7;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name7);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str8, &result);
+ hicn_prefix_t name8;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name8);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str9, &result);
+ hicn_prefix_t name9;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name9);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str10, &result);
+ hicn_prefix_t name10;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name10);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str11, &result);
+ hicn_prefix_t name11;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name11);
+ EXPECT_EQ(rc, 0);
+
+ 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) {
+ int rc;
+ local_prefixes_t *lp = create_local_prefixes();
+ EXPECT_FALSE(lp == nullptr);
+
+ hicn_ip_address_t result;
+
+ local_prefixes_t *lp1 = create_local_prefixes();
+ EXPECT_FALSE(lp1 == nullptr);
+
+ hicn_ip_address_pton(name_str1, &result);
+ hicn_prefix_t name1;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name1);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str2, &result);
+ hicn_prefix_t name2;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name2);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str3, &result);
+ hicn_prefix_t name3;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name3);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str4, &result);
+ hicn_prefix_t name4;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name4);
+ EXPECT_EQ(rc, 0);
+
+ 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);
+
+ hicn_ip_address_pton(name_str5, &result);
+ hicn_prefix_t name5;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name5);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str6, &result);
+ hicn_prefix_t name6;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name6);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str7, &result);
+ hicn_prefix_t name7;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name7);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str8, &result);
+ hicn_prefix_t name8;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name8);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str9, &result);
+ hicn_prefix_t name9;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name9);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str10, &result);
+ hicn_prefix_t name10;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name10);
+ EXPECT_EQ(rc, 0);
+
+ hicn_ip_address_pton(name_str11, &result);
+ hicn_prefix_t name11;
+ rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name11);
+ EXPECT_EQ(rc, 0);
+
+ 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..71635c929
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-loop.cc
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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, unsigned id,
+ void *arg) {
+ assert(id == 0);
+ std::cout << "This function should never be called" << std::endl;
+ EXPECT_TRUE(false);
+ return -1;
+ }
+
+ static int onSecondTimerExpiration(void *owner, int fd, unsigned id,
+ void *arg) {
+ assert(id == 0);
+ 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, unsigned id, void *arg) {
+ assert(id == 0);
+ // 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, unsigned id, void *arg) {
+ assert(id == 0);
+ 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) { // NOSONAR
+ 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, 0, 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, 0, 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..0a78a7a5d
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-msgbuf_pool.cc
@@ -0,0 +1,191 @@
+/*
+ * 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 <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/util/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_set_type(msgbuf, HICN_PACKET_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_set_type(msgbuf, HICN_PACKET_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_set_type(msgbuf, HICN_PACKET_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_set_type(msgbuf, HICN_PACKET_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_set_type(msgbuf, HICN_PACKET_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..37f4fe985
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-packet_cache.cc
@@ -0,0 +1,703 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <optional>
+#include <random>
+#include <hicn/test/test-utils.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/core/packet_cache.h>
+}
+
+static constexpr unsigned CS_SIZE = 100;
+static constexpr unsigned CONN_ID = 0;
+static constexpr unsigned CONN_ID_2 = 1;
+static constexpr unsigned MSGBUF_ID = 0;
+static constexpr unsigned MSGBUF_ID_2 = 1;
+static constexpr unsigned MSGBUF_ID_3 = 2;
+static constexpr unsigned FIVE_SECONDS = 5000;
+
+static constexpr int N_OPS = 50000;
+
+class PacketCacheTest : public ::testing::Test {
+ protected:
+ PacketCacheTest() {
+ pkt_cache = pkt_cache_create(CS_SIZE);
+ int rc = hicn_name_create_from_ip_address(IPV4_ANY, 0, &name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_pool = msgbuf_pool_create();
+ msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name);
+ }
+
+ virtual ~PacketCacheTest() {
+ msgbuf_pool_free(msgbuf_pool);
+ pkt_cache_free(pkt_cache);
+ }
+
+ msgbuf_t *msgbuf_create(msgbuf_pool_t *msgbuf_pool, unsigned conn_id,
+ hicn_name_t *name,
+ std::optional<Ticks> lifetime = FIVE_SECONDS) {
+ msgbuf_t *msgbuf;
+ msgbuf_pool_get(msgbuf_pool, &msgbuf);
+
+ msgbuf->connection_id = conn_id;
+ msgbuf_set_name(msgbuf, name);
+
+ hicn_packet_set_format(msgbuf_get_pkbuf(msgbuf),
+ HICN_PACKET_FORMAT_IPV6_TCP);
+ hicn_packet_set_type(msgbuf_get_pkbuf(msgbuf), HICN_PACKET_TYPE_INTEREST);
+
+ hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf);
+ hicn_packet_set_buffer(pkbuf, msgbuf->packet, MTU, 0);
+
+ int rc = hicn_packet_init_header(msgbuf_get_pkbuf(msgbuf), 0);
+ EXPECT_EQ(rc, 0);
+
+ // Same as 'msgbuf_set_data_expiry_time',
+ // it would write in the same field
+ msgbuf_set_interest_lifetime(msgbuf, *lifetime);
+
+ return msgbuf;
+ }
+
+ hicn_name_t get_name_from_prefix(const char *prefix_str) {
+ hicn_ip_address_t prefix;
+ inet_pton(AF_INET6, prefix_str, (struct in6_addr *)&prefix);
+
+ hicn_name_t name;
+ int rc = hicn_name_create_from_ip_address(prefix, 0, &name);
+ EXPECT_EQ(rc, 0);
+
+ return name;
+ }
+
+ pkt_cache_t *pkt_cache;
+ pkt_cache_entry_t *entry = nullptr;
+ msgbuf_pool_t *msgbuf_pool;
+ hicn_name_t name;
+ msgbuf_t *msgbuf;
+};
+
+TEST_F(PacketCacheTest, LowLevelOperations) {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ const hicn_name_prefix_t *prefix = hicn_name_get_prefix(&name);
+ _add_suffix(prefix_to_suffixes, prefix, 1, 11, pkt_cache->prefix_keys);
+ _add_suffix(prefix_to_suffixes, prefix, 2, 22, pkt_cache->prefix_keys);
+
+ unsigned id =
+ _get_suffix(prefix_to_suffixes, prefix, 1, pkt_cache->prefix_keys);
+ EXPECT_EQ(id, 11UL);
+
+ id = _get_suffix(prefix_to_suffixes, prefix, 2, pkt_cache->prefix_keys);
+ EXPECT_EQ(id, 22UL);
+
+ id = _get_suffix(prefix_to_suffixes, prefix, 5, pkt_cache->prefix_keys);
+ EXPECT_EQ(id, HICN_INVALID_SUFFIX);
+
+ _add_suffix(prefix_to_suffixes, prefix, 5, 55, pkt_cache->prefix_keys);
+ id = _get_suffix(prefix_to_suffixes, prefix, 5, pkt_cache->prefix_keys);
+ EXPECT_EQ(id, 55UL);
+
+ _remove_suffix(prefix_to_suffixes, prefix, 2, pkt_cache->prefix_keys);
+ _add_suffix(prefix_to_suffixes, prefix, 2, 222, pkt_cache->prefix_keys);
+ id = _get_suffix(prefix_to_suffixes, prefix, 2, pkt_cache->prefix_keys);
+ EXPECT_EQ(id, 222UL);
+
+ _prefix_map_free(prefix_to_suffixes);
+}
+
+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);
+ EXPECT_NE(entry, nullptr);
+ entry->name = name;
+ ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u);
+ pkt_cache_add_to_index(pkt_cache, entry);
+
+ // Get entry by name
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id,
+ true);
+ EXPECT_NE(lookup_result, PKT_CACHE_LU_NONE);
+}
+
+TEST_F(PacketCacheTest, GetCS) {
+ 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);
+ entry->name = name;
+ entry->entry_type = PKT_CACHE_PIT_TYPE;
+ ASSERT_NE(entry, nullptr);
+ pkt_cache_add_to_index(pkt_cache, entry);
+
+ // 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) {
+ // Check if entry properly created
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ ASSERT_NE(entry, nullptr);
+ EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE);
+ EXPECT_TRUE(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID));
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // 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) {
+ // 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 PIT entry
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // 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 CS entry
+ pkt_cache_entry_t *entry =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+ 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_TRUE(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID));
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ // 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 PIT entry
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+
+ hicn_name_t new_name;
+ int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
+
+ // Check if entry properly updated
+ pkt_cache_update_pit(pkt_cache, entry, new_msgbuf);
+ 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 CS entry
+ pkt_cache_entry_t *entry =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
+
+ hicn_name_t new_name;
+ int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
+
+ // Check if entry properly updated
+ pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, new_msgbuf, MSGBUF_ID_2);
+ 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 PIT entry
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+
+ pkt_cache_pit_remove_entry(pkt_cache, entry);
+ 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 CS entry
+ pkt_cache_entry_t *entry =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
+ 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 another msgbuf
+ hicn_name_t new_name;
+ int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
+
+ pkt_cache_entry_t *entry_1 =
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ 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 another msgbuf
+ hicn_name_t new_name;
+ int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
+
+ // Check if entry properly created (use sleep to get an updated ts)
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ Ticks old_lifetime = entry->expire_ts;
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ bool is_aggregated =
+ pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, &name);
+ 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 another msgbuf (using same connection ID)
+ hicn_name_t new_name;
+ int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &new_name);
+
+ // Check if entry properly created (use sleep to get an updated ts)
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ Ticks old_lifetime = entry->expire_ts;
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ bool is_aggregated =
+ pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, &name);
+ 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_create(msgbuf_pool, CONN_ID, &name, 0);
+
+ // Add to PIT
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name);
+ 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_create(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_create(msgbuf_pool, CONN_ID, &name, 0);
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+
+ // Add to CS another msgbuf with immediate expiration (i.e. stale)
+ hicn_name_t name_2;
+ int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &name_2);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *msgbuf_2 = msgbuf_create(msgbuf_pool, CONN_ID, &name_2, 0);
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_2, MSGBUF_ID_2);
+
+ // Add to CS a msgbuf with 5-seconds expiration (i.e. not stale)
+ hicn_name_t name_3;
+ rc = hicn_name_create_from_ip_address(IPV6_LOOPBACK, 0, &name_3);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *msgbuf_3 =
+ msgbuf_create(msgbuf_pool, CONN_ID, &name_3, FIVE_SECONDS);
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_3, MSGBUF_ID_3);
+
+ size_t num_stale_entries = pkt_cache_get_num_cs_stale_entries(pkt_cache);
+ EXPECT_EQ(num_stale_entries, 2u);
+}
+
+TEST_F(PacketCacheTest, GetMultipleStaleEntries) {
+ hicn_ip_address_t addr;
+ char name[30];
+ const int NUM_STALES = 10;
+ int rc;
+
+ // 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);
+ hicn_name_t name;
+ rc = hicn_name_create_from_ip_address(addr, 0, &name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *msgbuf = msgbuf_create(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);
+ hicn_name_t name;
+ rc = hicn_name_create_from_ip_address(addr, 0, &name);
+ EXPECT_EQ(rc, 0);
+ msgbuf_t *msgbuf = msgbuf_create(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);
+}
+
+TEST_F(PacketCacheTest, PerformanceDoubleLookup) {
+ hicn_name_t tmp = get_name_from_prefix("b001::0");
+
+ auto elapsed_time_double = get_execution_time([&]() {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+
+ // Add to hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ hicn_name_set_suffix(&tmp, seq);
+ _add_suffix(prefix_to_suffixes, hicn_name_get_prefix(&tmp),
+ hicn_name_get_suffix(&tmp), hicn_name_get_suffix(&tmp),
+ pkt_cache->prefix_keys);
+ }
+
+ // Read from hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ hicn_name_set_suffix(&tmp, seq);
+ _get_suffix(prefix_to_suffixes, hicn_name_get_prefix(&tmp), seq,
+ pkt_cache->prefix_keys);
+ }
+
+ _prefix_map_free(prefix_to_suffixes);
+ });
+ std::cout << "Double lookup: " << elapsed_time_double << " ms\n";
+}
+
+TEST_F(PacketCacheTest, PerformanceCachedLookup) {
+ hicn_name_t tmp = get_name_from_prefix("b001::0");
+
+ auto elapsed_time_single = get_execution_time([&]() {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefix_to_suffixes, hicn_name_get_prefix(&tmp), true,
+ pkt_cache->prefix_keys);
+
+ // Add to hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ hicn_name_set_suffix(&tmp, seq);
+ __add_suffix(suffixes, hicn_name_get_suffix(&tmp),
+ hicn_name_get_suffix(&tmp));
+ }
+
+ // Read from hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ hicn_name_set_suffix(&tmp, seq);
+ __get_suffix(suffixes, hicn_name_get_suffix(&tmp));
+ }
+
+ _prefix_map_free(prefix_to_suffixes);
+ });
+ std::cout << "Cached lookup: " << elapsed_time_single << " ms\n";
+}
+
+TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) {
+ hicn_name_t tmp = get_name_from_prefix("b001::0");
+
+ // Prepare random sequence numbers
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ uint32_t seqs[N_OPS];
+ for (int seq = 0; seq < N_OPS; seq++) seqs[seq] = seq;
+ std::shuffle(std::begin(seqs), std::end(seqs), gen);
+
+ auto elapsed_time_single_rand = get_execution_time([&]() {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefix_to_suffixes, hicn_name_get_prefix(&tmp), true,
+ pkt_cache->prefix_keys);
+
+ // Add to hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ hicn_name_set_suffix(&tmp, seqs[seq]);
+ __add_suffix(suffixes, hicn_name_get_suffix(&tmp),
+ hicn_name_get_suffix(&tmp));
+ }
+
+ // Read from hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ hicn_name_set_suffix(&tmp, seqs[seq]);
+ __get_suffix(suffixes, hicn_name_get_suffix(&tmp));
+ }
+
+ _prefix_map_free(prefix_to_suffixes);
+ });
+ std::cout << "Cached lookup (rand): " << elapsed_time_single_rand << " ms\n";
+}
+
+TEST_F(PacketCacheTest, Clear) {
+ hicn_name_t tmp_name1, tmp_name2;
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+
+ // Create name and add to msgbuf pool
+ hicn_name_copy(&tmp_name1, &name);
+ hicn_name_set_suffix(&tmp_name1, 1);
+ msgbuf_t *tmp_msgbuf1 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name1);
+
+ // Create (another) name and add to msgbuf pool
+ hicn_name_copy(&tmp_name2, &name);
+ hicn_name_set_suffix(&tmp_name2, 2);
+ msgbuf_t *tmp_msgbuf2 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name2);
+
+ // Add to packet cache (2 entries in the CS, 1 in the PIT)
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ pkt_cache_add_to_pit(pkt_cache, tmp_msgbuf1, &tmp_name1);
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, tmp_msgbuf2, MSGBUF_ID_2);
+
+ // Check stats (before clearing the packet cache)
+ ASSERT_EQ(pkt_cache_get_size(pkt_cache), 3u);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 2u);
+ ASSERT_EQ(cs->num_entries, 2);
+ ASSERT_EQ(cs->stats.lru.countAdds, 2u);
+
+ // Clear packet cache (i.e. remove content packets from packet cache):
+ // PIT entry should still be there while CS entries are cleared
+ pkt_cache_cs_clear(pkt_cache);
+ cs = pkt_cache_get_cs(pkt_cache);
+
+ // Check stats (after clearing the packet cache)
+ ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+ ASSERT_EQ(cs->num_entries, 0);
+ ASSERT_EQ(cs->stats.lru.countAdds, 0u);
+}
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..2e396b97d
--- /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/ctrl/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);
+}
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-strategy-best-path.cc b/hicn-light/src/hicn/test/test-strategy-best-path.cc
new file mode 100644
index 000000000..f909c15f2
--- /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_finalize(&entry); }
+
+ 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-local-remote.cc b/hicn-light/src/hicn/test/test-strategy-local-remote.cc
new file mode 100644
index 000000000..6693e29c8
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-strategy-local-remote.cc
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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>
+#include <arpa/inet.h>
+
+extern "C" {
+#define WITH_TESTS
+#include <hicn/base/loop.h>
+#include <hicn/config/configuration.h>
+#include <hicn/core/forwarder.h>
+#include <hicn/core/listener.h>
+#include <hicn/core/address_pair.h>
+#include <hicn/core/address.h>
+#include <hicn/core/strategy.h>
+#include <hicn/strategies/local_remote.h>
+}
+
+class StrategyLocalRemoteTest : public ::testing::Test {
+ protected:
+ StrategyLocalRemoteTest() {
+ conf_ = configuration_create();
+ MAIN_LOOP = loop_create();
+ fwd_ = forwarder_create(conf_);
+
+ /* Strategy and strategy entry */
+ entry_ = {
+ .type = STRATEGY_TYPE_LOCAL_REMOTE,
+ .options =
+ {
+ .random = {},
+ },
+ .state = {.random = {}},
+ };
+
+ strategy_initialize(&entry_, fwd_);
+ }
+
+ virtual ~StrategyLocalRemoteTest() {
+ INFO("loop stopped");
+ forwarder_free(fwd_);
+ loop_free(MAIN_LOOP);
+ MAIN_LOOP = NULL;
+ strategy_finalize(&entry_);
+ }
+
+ strategy_entry_t entry_;
+ nexthops_t available_nexthops_ = NEXTHOPS_EMPTY;
+ configuration_t* conf_;
+ forwarder_t* fwd_;
+ msgbuf_t msgbuf_;
+};
+
+TEST_F(StrategyLocalRemoteTest, InputLocalOutputLocal) {
+ address_t prod_addr = ADDRESS4_LOCALHOST(12345);
+ address_t cons_addr = ADDRESS4_LOCALHOST(12346);
+ address_t listener_addr = ADDRESS4_LOCALHOST(9596);
+
+ listener_t* listener = listener_create(FACE_TYPE_UDP_LISTENER, &listener_addr,
+ "lo", "lo_udp4", fwd_);
+
+ address_pair_t pair_conn_prod = {
+ .local = listener_addr,
+ .remote = prod_addr,
+ };
+
+ address_pair_t pair_conn_cons = {
+ .local = listener_addr,
+ .remote = cons_addr,
+ };
+
+ unsigned prod_conn_id =
+ listener_create_connection(listener, "conp", &pair_conn_prod);
+ unsigned cons_conn_id =
+ listener_create_connection(listener, "conc", &pair_conn_cons);
+
+ msgbuf_.connection_id = cons_conn_id;
+
+ nexthops_add(&available_nexthops_, prod_conn_id);
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry_, &available_nexthops_, &msgbuf_);
+
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)0);
+}
+
+TEST_F(StrategyLocalRemoteTest, InputRemoteOutputRemote) {
+ address_t prod_addr = ADDRESS4_LOCALHOST(12345);
+ address_t cons_addr = ADDRESS4_LOCALHOST(12346);
+ address_t listener_addr = ADDRESS4_LOCALHOST(9596);
+
+ listener_t* listener = listener_create(FACE_TYPE_UDP_LISTENER, &listener_addr,
+ "lo", "lo_udp4", fwd_);
+
+ address_pair_t pair_conn_prod = {
+ .local = listener_addr,
+ .remote = prod_addr,
+ };
+
+ address_pair_t pair_conn_cons = {
+ .local = listener_addr,
+ .remote = cons_addr,
+ };
+
+ connection_t* conn;
+ unsigned prod_conn_id =
+ listener_create_connection(listener, "conp", &pair_conn_prod);
+ unsigned cons_conn_id =
+ listener_create_connection(listener, "conc", &pair_conn_cons);
+
+ // fake two remote connections
+ conn = connection_table_get_by_id(forwarder_get_connection_table(fwd_),
+ prod_conn_id);
+ ASSERT_TRUE(conn != NULL);
+ conn->local = false;
+
+ conn = connection_table_get_by_id(forwarder_get_connection_table(fwd_),
+ cons_conn_id);
+ ASSERT_TRUE(conn != NULL);
+ conn->local = false;
+
+ msgbuf_.connection_id = cons_conn_id;
+
+ nexthops_add(&available_nexthops_, prod_conn_id);
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry_, &available_nexthops_, &msgbuf_);
+
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)0);
+}
+
+TEST_F(StrategyLocalRemoteTest, InputLocalOutputRemote) {
+ address_t prod_addr = ADDRESS4_LOCALHOST(12345);
+ address_t cons_addr = ADDRESS4_LOCALHOST(12346);
+ address_t listener_addr = ADDRESS4_LOCALHOST(9596);
+
+ listener_t* listener = listener_create(FACE_TYPE_UDP_LISTENER, &listener_addr,
+ "lo", "lo_udp4", fwd_);
+
+ address_pair_t pair_conn_prod = {
+ .local = listener_addr,
+ .remote = prod_addr,
+ };
+
+ address_pair_t pair_conn_cons = {
+ .local = listener_addr,
+ .remote = cons_addr,
+ };
+
+ connection_t* conn;
+ unsigned prod_conn_id =
+ listener_create_connection(listener, "conp", &pair_conn_prod);
+ unsigned cons_conn_id =
+ listener_create_connection(listener, "conc", &pair_conn_cons);
+
+ conn = connection_table_get_by_id(forwarder_get_connection_table(fwd_),
+ prod_conn_id);
+ ASSERT_TRUE(conn != NULL);
+ conn->local = false;
+ conn = connection_table_get_by_id(forwarder_get_connection_table(fwd_),
+ cons_conn_id);
+ ASSERT_TRUE(conn != NULL);
+ conn->local = true;
+
+ msgbuf_.connection_id = cons_conn_id;
+
+ nexthops_add(&available_nexthops_, prod_conn_id);
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry_, &available_nexthops_, &msgbuf_);
+
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+}
+
+TEST_F(StrategyLocalRemoteTest, InputRemoteOutputLocal) {
+ address_t cons_addr = ADDRESS4_LOCALHOST(12345);
+ address_t prod_addr = ADDRESS4_LOCALHOST(12346);
+ address_t listener_addr = ADDRESS4_LOCALHOST(9695);
+
+ listener_t* listener = listener_create(FACE_TYPE_UDP_LISTENER, &listener_addr,
+ "lo", "lo_udp4", fwd_);
+
+ address_pair_t pair_conn_prod = {
+ .local = listener_addr,
+ .remote = prod_addr,
+ };
+
+ address_pair_t pair_conn_cons = {
+ .local = listener_addr,
+ .remote = cons_addr,
+ };
+
+ connection_t* conn;
+ unsigned prod_conn_id =
+ listener_create_connection(listener, "conp", &pair_conn_prod);
+ unsigned cons_conn_id =
+ listener_create_connection(listener, "conc", &pair_conn_cons);
+
+ conn = connection_table_get_by_id(forwarder_get_connection_table(fwd_),
+ prod_conn_id);
+ ASSERT_TRUE(conn != NULL);
+ conn->local = true;
+ conn = connection_table_get_by_id(forwarder_get_connection_table(fwd_),
+ cons_conn_id);
+ ASSERT_TRUE(conn != NULL);
+ conn->local = false;
+
+ msgbuf_.connection_id = cons_conn_id;
+
+ nexthops_add(&available_nexthops_, prod_conn_id);
+ nexthops_t* nexthops;
+ nexthops = strategy_lookup_nexthops(&entry_, &available_nexthops_, &msgbuf_);
+
+ EXPECT_EQ(nexthops_get_curlen(nexthops), (size_t)1);
+}
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..1c4d824b8
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-strategy-replication.cc
@@ -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.
+ */
+
+#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_finalize(&entry); }
+
+ 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 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..5fd3ab57d
--- /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/util/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_TYPE_STRATEGY);
+
+ object_type = object_from_topic(TOPIC_FACE);
+ EXPECT_EQ(object_type, OBJECT_TYPE_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);
+}
diff --git a/hicn-light/src/hicn/test/test-utils.h b/hicn-light/src/hicn/test/test-utils.h
new file mode 100644
index 000000000..577629584
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-utils.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <vector>
+#include <thread>
+#include <numeric>
+
+static constexpr int N_RUNS = 100;
+
+// Utility function for time execution calculation
+template <typename F, typename... Args>
+double get_execution_time(F func, Args &&...args) {
+ std::vector<float> execution_times;
+
+ for (int i = 0; i < N_RUNS; i++) {
+ auto start = std::chrono::high_resolution_clock::now();
+ func(std::forward<Args>(args)...);
+ auto end = std::chrono::high_resolution_clock::now();
+
+ std::chrono::duration<double, std::milli> ms = end - start;
+ execution_times.emplace_back(ms.count());
+ }
+
+ // Calculate average
+ return std::reduce(execution_times.begin(), execution_times.end()) /
+ execution_times.size();
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test_hash.cc b/hicn-light/src/hicn/test/test_hash.cc
new file mode 100644
index 000000000..c742aa248
--- /dev/null
+++ b/hicn-light/src/hicn/test/test_hash.cc
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <unordered_set>
+#include <hicn/test/test-utils.h>
+
+extern "C" {
+#include <hicn/util/hash.h>
+#include <hicn/core/address_pair.h>
+#include <hicn/core/listener.h>
+}
+
+static constexpr uint32_t init_val = 2166136261UL;
+static constexpr int N_HASHES = 50000;
+
+TEST(HashTest, MultipleHashesForSameAddrPair) {
+ address_pair_t pair =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
+
+ 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) {
+ std::unordered_set<uint32_t> hashes;
+ int n_collisions = 0;
+ for (int i = 0; i < 50000; i++) {
+ uint32_t seg = i;
+ // u32 h = utils::hash::fnv32_buf(&seg, sizeof(seg));
+ // u32 h = cumulative_hash32(&seg, sizeof(uint32_t), init_val);
+ u32 h = hash(&seg, sizeof(seg));
+
+ if (hashes.find(h) != hashes.end()) n_collisions++;
+ hashes.insert(h);
+ }
+ EXPECT_EQ(n_collisions, 0);
+}
+
+/*** Compare FNV with Jenkins ***/
+
+typedef struct {
+ uint32_t data[6];
+} small_struct_t; // Same size as 'NameBitvector'
+
+typedef struct {
+ uint64_t data[32];
+} big_struct_t; // Same size as 'address_pair_t'
+
+TEST(HashTest, PerformanceComparisonSmallStruct) {
+ small_struct_t small_struct;
+
+ // FNV
+ auto time_fnv = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ small_struct.data[0] = i;
+ cumulative_hash32(&small_struct, sizeof(small_struct_t), init_val);
+ }
+ });
+
+ // Jenkins
+ auto time_jenkins = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ small_struct.data[0] = i;
+ hash(&small_struct, sizeof(small_struct_t));
+ }
+ });
+
+ std::cout << "Small struct (size = " << sizeof(small_struct_t) << " bytes)\n";
+ std::cout << "FNV: " << time_fnv << "ms\n";
+ std::cout << "Jenkins: " << time_jenkins << "ms\n";
+}
+
+TEST(HashTest, PerformanceComparisonBigStruct) {
+ big_struct_t big_struct;
+
+ // FNV
+ auto time_fnv = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ big_struct.data[0] = i;
+ cumulative_hash32(&big_struct, sizeof(big_struct_t), init_val);
+ }
+ });
+
+ // Jenkins
+ auto time_jenkins = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ big_struct.data[0] = i;
+ hash(&big_struct, sizeof(big_struct_t));
+ }
+ });
+
+ std::cout << "Big struct (size = " << sizeof(big_struct_t) << " bytes)\n";
+ std::cout << "FNV: " << time_fnv << "ms\n";
+ std::cout << "Jenkins: " << time_jenkins << "ms\n";
+}
+
+TEST(HashTest, CollisionsComparison) {
+ small_struct_t small_struct = {0};
+ std::unordered_set<uint32_t> hashes;
+ int n_collisions_fnv = 0, n_collisions_jenkins = 0;
+
+ // FNV
+ for (int i = 0; i < 10 * N_HASHES; i++) {
+ small_struct.data[0] = i;
+ uint32_t h =
+ cumulative_hash32(&small_struct, sizeof(small_struct_t), init_val);
+
+ if (hashes.find(h) != hashes.end()) n_collisions_fnv++;
+ hashes.insert(h);
+ }
+
+ hashes.clear();
+
+ // Jenkins
+ for (int i = 0; i < 10 * N_HASHES; i++) {
+ small_struct.data[0] = i;
+ uint32_t h = hash(&small_struct, sizeof(small_struct_t));
+
+ if (hashes.find(h) != hashes.end()) n_collisions_jenkins++;
+ hashes.insert(h);
+ }
+
+ std::cout << "Small struct (size = " << sizeof(small_struct_t) << " bytes)\n";
+ std::cout << "FNV: " << n_collisions_fnv << " collision/s\n";
+ std::cout << "Jenkins: " << n_collisions_jenkins << " collision/s\n";
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/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