From eb323e056e747d71867cf965434811c1de925de2 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Sat, 23 Mar 2019 14:13:53 +0100 Subject: [HICN-141] Definition of a C API for hicn-light Change-Id: Id861f0abe58b1e3c9ba8cc76701da0f9c6801748 Signed-off-by: Luca Muscariello Signed-off-by: Angelo Mantellini --- hicn-light/src/CMakeLists.txt | 49 - hicn-light/src/command_line/CMakeLists.txt | 2 - .../src/command_line/controller/CMakeLists.txt | 23 - .../controller/hicnLightControl_main.c | 342 ---- hicn-light/src/command_line/daemon/CMakeLists.txt | 23 - .../src/command_line/daemon/hicnLightDaemon_main.c | 408 ----- hicn-light/src/config.h.in | 9 - hicn-light/src/config/CMakeLists.txt | 97 -- hicn-light/src/config/commandOps.c | 70 - hicn-light/src/config/commandOps.h | 126 -- hicn-light/src/config/commandParser.c | 218 --- hicn-light/src/config/commandParser.h | 196 --- hicn-light/src/config/commandReturn.h | 43 - hicn-light/src/config/configuration.c | 1089 ------------- hicn-light/src/config/configuration.h | 152 -- hicn-light/src/config/configurationFile.c | 309 ---- hicn-light/src/config/configurationFile.h | 93 -- hicn-light/src/config/configurationListeners.c | 591 ------- hicn-light/src/config/configurationListeners.h | 74 - hicn-light/src/config/controlAdd.c | 93 -- hicn-light/src/config/controlAdd.h | 32 - hicn-light/src/config/controlAddConnection.c | 389 ----- hicn-light/src/config/controlAddConnection.h | 31 - hicn-light/src/config/controlAddListener.c | 177 -- hicn-light/src/config/controlAddListener.h | 30 - hicn-light/src/config/controlAddPunting.c | 159 -- hicn-light/src/config/controlAddPunting.h | 22 - hicn-light/src/config/controlAddRoute.c | 162 -- hicn-light/src/config/controlAddRoute.h | 30 - hicn-light/src/config/controlCache.c | 90 - hicn-light/src/config/controlCache.h | 22 - hicn-light/src/config/controlCacheClear.c | 83 - hicn-light/src/config/controlCacheClear.h | 30 - hicn-light/src/config/controlCacheServe.c | 102 -- hicn-light/src/config/controlCacheServe.h | 22 - hicn-light/src/config/controlCacheStore.c | 102 -- hicn-light/src/config/controlCacheStore.h | 22 - hicn-light/src/config/controlList.c | 96 -- hicn-light/src/config/controlList.h | 30 - hicn-light/src/config/controlListConnections.c | 159 -- hicn-light/src/config/controlListConnections.h | 30 - hicn-light/src/config/controlListInterfaces.c | 75 - hicn-light/src/config/controlListInterfaces.h | 31 - hicn-light/src/config/controlListListeners.c | 140 -- hicn-light/src/config/controlListListeners.h | 31 - hicn-light/src/config/controlListRoutes.c | 153 -- hicn-light/src/config/controlListRoutes.h | 29 - hicn-light/src/config/controlMapMe.c | 93 -- hicn-light/src/config/controlMapMe.h | 22 - hicn-light/src/config/controlMapMeDiscovery.c | 102 -- hicn-light/src/config/controlMapMeDiscovery.h | 22 - hicn-light/src/config/controlMapMeEnable.c | 100 -- hicn-light/src/config/controlMapMeEnable.h | 22 - hicn-light/src/config/controlMapMeRetx.c | 93 -- hicn-light/src/config/controlMapMeRetx.h | 22 - hicn-light/src/config/controlMapMeTimescale.c | 96 -- hicn-light/src/config/controlMapMeTimescale.h | 22 - hicn-light/src/config/controlQuit.c | 62 - hicn-light/src/config/controlQuit.h | 29 - hicn-light/src/config/controlRemove.c | 91 -- hicn-light/src/config/controlRemove.h | 29 - hicn-light/src/config/controlRemoveConnection.c | 114 -- hicn-light/src/config/controlRemoveConnection.h | 31 - hicn-light/src/config/controlRemovePunting.c | 75 - hicn-light/src/config/controlRemovePunting.h | 27 - hicn-light/src/config/controlRemoveRoute.c | 152 -- hicn-light/src/config/controlRemoveRoute.h | 31 - hicn-light/src/config/controlRoot.c | 133 -- hicn-light/src/config/controlRoot.h | 31 - hicn-light/src/config/controlSet.c | 87 - hicn-light/src/config/controlSet.h | 29 - hicn-light/src/config/controlSetDebug.c | 73 - hicn-light/src/config/controlSetDebug.h | 30 - hicn-light/src/config/controlSetStrategy.c | 188 --- hicn-light/src/config/controlSetStrategy.h | 22 - hicn-light/src/config/controlSetWldr.c | 121 -- hicn-light/src/config/controlSetWldr.h | 22 - hicn-light/src/config/controlState.c | 238 --- hicn-light/src/config/controlState.h | 233 --- hicn-light/src/config/controlUnset.c | 77 - hicn-light/src/config/controlUnset.h | 29 - hicn-light/src/config/controlUnsetDebug.c | 76 - hicn-light/src/config/controlUnsetDebug.h | 30 - hicn-light/src/config/symbolicNameTable.c | 175 -- hicn-light/src/config/symbolicNameTable.h | 131 -- hicn-light/src/content_store/CMakeLists.txt | 33 - hicn-light/src/content_store/contentStoreEntry.c | 136 -- hicn-light/src/content_store/contentStoreEntry.h | 146 -- .../src/content_store/contentStoreInterface.c | 57 - .../src/content_store/contentStoreInterface.h | 211 --- hicn-light/src/content_store/contentStoreLRU.c | 457 ------ hicn-light/src/content_store/contentStoreLRU.h | 39 - hicn-light/src/content_store/listLRU.c | 135 -- hicn-light/src/content_store/listLRU.h | 94 -- hicn-light/src/content_store/listTimeOrdered.c | 94 -- hicn-light/src/content_store/listTimeOrdered.h | 103 -- hicn-light/src/core/CMakeLists.txt | 55 - hicn-light/src/core/connection.c | 272 --- hicn-light/src/core/connection.h | 154 -- hicn-light/src/core/connectionList.c | 68 - hicn-light/src/core/connectionList.h | 70 - hicn-light/src/core/connectionManager.c | 196 --- hicn-light/src/core/connectionManager.h | 37 - hicn-light/src/core/connectionTable.c | 226 --- hicn-light/src/core/connectionTable.h | 99 -- hicn-light/src/core/dispatcher.c | 474 ------ hicn-light/src/core/dispatcher.h | 288 ---- hicn-light/src/core/forwarder.c | 519 ------ hicn-light/src/core/forwarder.h | 294 ---- hicn-light/src/core/logger.c | 176 -- hicn-light/src/core/logger.h | 169 -- hicn-light/src/core/mapMe.c | 813 --------- hicn-light/src/core/mapMe.h | 89 - hicn-light/src/core/message.c | 297 ---- hicn-light/src/core/message.h | 180 -- hicn-light/src/core/messageHandler.h | 578 ------- hicn-light/src/core/messagePacketType.h | 32 - hicn-light/src/core/name.c | 236 --- hicn-light/src/core/name.h | 105 -- hicn-light/src/core/nameBitvector.c | 383 ----- hicn-light/src/core/nameBitvector.h | 63 - hicn-light/src/core/numberSet.c | 203 --- hicn-light/src/core/numberSet.h | 157 -- hicn-light/src/core/streamBuffer.c | 142 -- hicn-light/src/core/streamBuffer.h | 129 -- hicn-light/src/core/system.h | 60 - hicn-light/src/core/ticks.h | 31 - hicn-light/src/core/wldr.c | 182 --- hicn-light/src/core/wldr.h | 52 - hicn-light/src/hicn/CMakeLists.txt | 51 + hicn-light/src/hicn/api/CMakeLists.txt | 36 + hicn-light/src/hicn/api/api.c | 1391 ++++++++++++++++ hicn-light/src/hicn/api/api.h | 580 +++++++ hicn-light/src/hicn/api/commands.h | 357 ++++ hicn-light/src/hicn/api/face.h | 213 +++ hicn-light/src/hicn/api/fib_policy.h | 39 + hicn-light/src/hicn/api/ip_address.h | 221 +++ hicn-light/src/hicn/api/token.h | 39 + hicn-light/src/hicn/api/types.h | 40 + hicn-light/src/hicn/command_line/CMakeLists.txt | 2 + .../hicn/command_line/controller/CMakeLists.txt | 23 + .../controller/hicnLightControl_main.c | 342 ++++ .../src/hicn/command_line/daemon/CMakeLists.txt | 23 + .../command_line/daemon/hicnLightDaemon_main.c | 408 +++++ hicn-light/src/hicn/config.h.in | 9 + hicn-light/src/hicn/config/CMakeLists.txt | 97 ++ hicn-light/src/hicn/config/commandOps.c | 70 + hicn-light/src/hicn/config/commandOps.h | 126 ++ hicn-light/src/hicn/config/commandParser.c | 218 +++ hicn-light/src/hicn/config/commandParser.h | 196 +++ hicn-light/src/hicn/config/commandReturn.h | 43 + hicn-light/src/hicn/config/configuration.c | 1089 +++++++++++++ hicn-light/src/hicn/config/configuration.h | 152 ++ hicn-light/src/hicn/config/configurationFile.c | 309 ++++ hicn-light/src/hicn/config/configurationFile.h | 93 ++ .../src/hicn/config/configurationListeners.c | 591 +++++++ .../src/hicn/config/configurationListeners.h | 74 + hicn-light/src/hicn/config/controlAdd.c | 93 ++ hicn-light/src/hicn/config/controlAdd.h | 32 + hicn-light/src/hicn/config/controlAddConnection.c | 389 +++++ hicn-light/src/hicn/config/controlAddConnection.h | 31 + hicn-light/src/hicn/config/controlAddListener.c | 177 ++ hicn-light/src/hicn/config/controlAddListener.h | 30 + hicn-light/src/hicn/config/controlAddPunting.c | 159 ++ hicn-light/src/hicn/config/controlAddPunting.h | 22 + hicn-light/src/hicn/config/controlAddRoute.c | 162 ++ hicn-light/src/hicn/config/controlAddRoute.h | 30 + hicn-light/src/hicn/config/controlCache.c | 90 + hicn-light/src/hicn/config/controlCache.h | 22 + hicn-light/src/hicn/config/controlCacheClear.c | 83 + hicn-light/src/hicn/config/controlCacheClear.h | 30 + hicn-light/src/hicn/config/controlCacheServe.c | 102 ++ hicn-light/src/hicn/config/controlCacheServe.h | 22 + hicn-light/src/hicn/config/controlCacheStore.c | 102 ++ hicn-light/src/hicn/config/controlCacheStore.h | 22 + hicn-light/src/hicn/config/controlList.c | 96 ++ hicn-light/src/hicn/config/controlList.h | 30 + .../src/hicn/config/controlListConnections.c | 159 ++ .../src/hicn/config/controlListConnections.h | 30 + hicn-light/src/hicn/config/controlListInterfaces.c | 75 + hicn-light/src/hicn/config/controlListInterfaces.h | 31 + hicn-light/src/hicn/config/controlListListeners.c | 140 ++ hicn-light/src/hicn/config/controlListListeners.h | 31 + hicn-light/src/hicn/config/controlListRoutes.c | 153 ++ hicn-light/src/hicn/config/controlListRoutes.h | 29 + hicn-light/src/hicn/config/controlMapMe.c | 93 ++ hicn-light/src/hicn/config/controlMapMe.h | 22 + hicn-light/src/hicn/config/controlMapMeDiscovery.c | 102 ++ hicn-light/src/hicn/config/controlMapMeDiscovery.h | 22 + hicn-light/src/hicn/config/controlMapMeEnable.c | 100 ++ hicn-light/src/hicn/config/controlMapMeEnable.h | 22 + hicn-light/src/hicn/config/controlMapMeRetx.c | 93 ++ hicn-light/src/hicn/config/controlMapMeRetx.h | 22 + hicn-light/src/hicn/config/controlMapMeTimescale.c | 96 ++ hicn-light/src/hicn/config/controlMapMeTimescale.h | 22 + hicn-light/src/hicn/config/controlQuit.c | 62 + hicn-light/src/hicn/config/controlQuit.h | 29 + hicn-light/src/hicn/config/controlRemove.c | 91 ++ hicn-light/src/hicn/config/controlRemove.h | 29 + .../src/hicn/config/controlRemoveConnection.c | 114 ++ .../src/hicn/config/controlRemoveConnection.h | 31 + hicn-light/src/hicn/config/controlRemovePunting.c | 75 + hicn-light/src/hicn/config/controlRemovePunting.h | 27 + hicn-light/src/hicn/config/controlRemoveRoute.c | 152 ++ hicn-light/src/hicn/config/controlRemoveRoute.h | 31 + hicn-light/src/hicn/config/controlRoot.c | 133 ++ hicn-light/src/hicn/config/controlRoot.h | 31 + hicn-light/src/hicn/config/controlSet.c | 87 + hicn-light/src/hicn/config/controlSet.h | 29 + hicn-light/src/hicn/config/controlSetDebug.c | 73 + hicn-light/src/hicn/config/controlSetDebug.h | 30 + hicn-light/src/hicn/config/controlSetStrategy.c | 188 +++ hicn-light/src/hicn/config/controlSetStrategy.h | 22 + hicn-light/src/hicn/config/controlSetWldr.c | 121 ++ hicn-light/src/hicn/config/controlSetWldr.h | 22 + hicn-light/src/hicn/config/controlState.c | 238 +++ hicn-light/src/hicn/config/controlState.h | 233 +++ hicn-light/src/hicn/config/controlUnset.c | 77 + hicn-light/src/hicn/config/controlUnset.h | 29 + hicn-light/src/hicn/config/controlUnsetDebug.c | 76 + hicn-light/src/hicn/config/controlUnsetDebug.h | 30 + hicn-light/src/hicn/config/symbolicNameTable.c | 175 ++ hicn-light/src/hicn/config/symbolicNameTable.h | 131 ++ hicn-light/src/hicn/content_store/CMakeLists.txt | 33 + .../src/hicn/content_store/contentStoreEntry.c | 136 ++ .../src/hicn/content_store/contentStoreEntry.h | 146 ++ .../src/hicn/content_store/contentStoreInterface.c | 57 + .../src/hicn/content_store/contentStoreInterface.h | 211 +++ .../src/hicn/content_store/contentStoreLRU.c | 457 ++++++ .../src/hicn/content_store/contentStoreLRU.h | 39 + hicn-light/src/hicn/content_store/listLRU.c | 135 ++ hicn-light/src/hicn/content_store/listLRU.h | 94 ++ .../src/hicn/content_store/listTimeOrdered.c | 94 ++ .../src/hicn/content_store/listTimeOrdered.h | 103 ++ hicn-light/src/hicn/core/CMakeLists.txt | 55 + hicn-light/src/hicn/core/connection.c | 272 +++ hicn-light/src/hicn/core/connection.h | 154 ++ hicn-light/src/hicn/core/connectionList.c | 68 + hicn-light/src/hicn/core/connectionList.h | 70 + hicn-light/src/hicn/core/connectionManager.c | 196 +++ hicn-light/src/hicn/core/connectionManager.h | 37 + hicn-light/src/hicn/core/connectionTable.c | 226 +++ hicn-light/src/hicn/core/connectionTable.h | 99 ++ hicn-light/src/hicn/core/dispatcher.c | 474 ++++++ hicn-light/src/hicn/core/dispatcher.h | 288 ++++ hicn-light/src/hicn/core/forwarder.c | 519 ++++++ hicn-light/src/hicn/core/forwarder.h | 294 ++++ hicn-light/src/hicn/core/logger.c | 176 ++ hicn-light/src/hicn/core/logger.h | 169 ++ hicn-light/src/hicn/core/mapMe.c | 813 +++++++++ hicn-light/src/hicn/core/mapMe.h | 89 + hicn-light/src/hicn/core/message.c | 297 ++++ hicn-light/src/hicn/core/message.h | 180 ++ hicn-light/src/hicn/core/messageHandler.h | 578 +++++++ hicn-light/src/hicn/core/messagePacketType.h | 32 + hicn-light/src/hicn/core/name.c | 236 +++ hicn-light/src/hicn/core/name.h | 105 ++ hicn-light/src/hicn/core/nameBitvector.c | 383 +++++ hicn-light/src/hicn/core/nameBitvector.h | 63 + hicn-light/src/hicn/core/numberSet.c | 203 +++ hicn-light/src/hicn/core/numberSet.h | 157 ++ hicn-light/src/hicn/core/streamBuffer.c | 142 ++ hicn-light/src/hicn/core/streamBuffer.h | 129 ++ hicn-light/src/hicn/core/system.h | 60 + hicn-light/src/hicn/core/ticks.h | 31 + hicn-light/src/hicn/core/wldr.c | 182 +++ hicn-light/src/hicn/core/wldr.h | 52 + hicn-light/src/hicn/io/CMakeLists.txt | 53 + hicn-light/src/hicn/io/addressPair.c | 129 ++ hicn-light/src/hicn/io/addressPair.h | 128 ++ hicn-light/src/hicn/io/hicnConnection.c | 524 ++++++ hicn-light/src/hicn/io/hicnConnection.h | 53 + hicn-light/src/hicn/io/hicnListener.c | 727 +++++++++ hicn-light/src/hicn/io/hicnListener.h | 42 + hicn-light/src/hicn/io/hicnTunnel.c | 106 ++ hicn-light/src/hicn/io/hicnTunnel.h | 65 + hicn-light/src/hicn/io/ioOperations.c | 69 + hicn-light/src/hicn/io/ioOperations.h | 366 +++++ hicn-light/src/hicn/io/listener.h | 105 ++ hicn-light/src/hicn/io/listenerSet.c | 132 ++ hicn-light/src/hicn/io/listenerSet.h | 137 ++ hicn-light/src/hicn/io/streamConnection.c | 692 ++++++++ hicn-light/src/hicn/io/streamConnection.h | 75 + hicn-light/src/hicn/io/tcpListener.c | 233 +++ hicn-light/src/hicn/io/tcpListener.h | 40 + hicn-light/src/hicn/io/tcpTunnel.c | 43 + hicn-light/src/hicn/io/tcpTunnel.h | 42 + hicn-light/src/hicn/io/udpConnection.c | 391 +++++ hicn-light/src/hicn/io/udpConnection.h | 53 + hicn-light/src/hicn/io/udpListener.c | 556 +++++++ hicn-light/src/hicn/io/udpListener.h | 35 + hicn-light/src/hicn/io/udpTunnel.c | 105 ++ hicn-light/src/hicn/io/udpTunnel.h | 42 + hicn-light/src/hicn/messenger/CMakeLists.txt | 32 + hicn-light/src/hicn/messenger/messenger.c | 171 ++ hicn-light/src/hicn/messenger/messenger.h | 69 + hicn-light/src/hicn/messenger/messengerRecipient.c | 62 + hicn-light/src/hicn/messenger/messengerRecipient.h | 104 ++ hicn-light/src/hicn/messenger/missive.c | 54 + hicn-light/src/hicn/messenger/missive.h | 89 + hicn-light/src/hicn/messenger/missiveDeque.c | 77 + hicn-light/src/hicn/messenger/missiveDeque.h | 55 + hicn-light/src/hicn/messenger/missiveType.h | 55 + hicn-light/src/hicn/platforms/CMakeLists.txt | 40 + hicn-light/src/hicn/platforms/README.txt | 17 + hicn-light/src/hicn/platforms/android/system.c | 183 +++ hicn-light/src/hicn/platforms/darwin/system.c | 146 ++ hicn-light/src/hicn/platforms/linux/system.c | 184 +++ hicn-light/src/hicn/platforms/windows/system.c | 223 +++ .../src/hicn/platforms/windows/win_portability.c | 50 + .../src/hicn/platforms/windows/win_portability.h | 45 + hicn-light/src/hicn/processor/CMakeLists.txt | 40 + hicn-light/src/hicn/processor/fib.c | 448 +++++ hicn-light/src/hicn/processor/fib.h | 43 + hicn-light/src/hicn/processor/fibEntry.c | 223 +++ hicn-light/src/hicn/processor/fibEntry.h | 143 ++ hicn-light/src/hicn/processor/fibEntryList.c | 72 + hicn-light/src/hicn/processor/fibEntryList.h | 96 ++ hicn-light/src/hicn/processor/hashTableFunction.c | 47 + hicn-light/src/hicn/processor/hashTableFunction.h | 73 + hicn-light/src/hicn/processor/matchingRulesTable.c | 132 ++ hicn-light/src/hicn/processor/matchingRulesTable.h | 113 ++ hicn-light/src/hicn/processor/messageProcessor.c | 742 +++++++++ hicn-light/src/hicn/processor/messageProcessor.h | 166 ++ hicn-light/src/hicn/processor/pit.c | 45 + hicn-light/src/hicn/processor/pit.h | 114 ++ hicn-light/src/hicn/processor/pitEntry.c | 142 ++ hicn-light/src/hicn/processor/pitEntry.h | 164 ++ hicn-light/src/hicn/processor/pitStandard.c | 304 ++++ hicn-light/src/hicn/processor/pitStandard.h | 41 + hicn-light/src/hicn/processor/pitVerdict.h | 36 + hicn-light/src/hicn/socket/CMakeLists.txt | 31 + hicn-light/src/hicn/socket/api.c | 604 +++++++ hicn-light/src/hicn/socket/api.h | 217 +++ hicn-light/src/hicn/socket/error.c | 7 + hicn-light/src/hicn/socket/error.h | 46 + hicn-light/src/hicn/socket/ops.h | 54 + hicn-light/src/hicn/socket/ops_linux.c | 1723 ++++++++++++++++++++ hicn-light/src/hicn/strategies/CMakeLists.txt | 36 + hicn-light/src/hicn/strategies/loadBalancer.c | 278 ++++ hicn-light/src/hicn/strategies/loadBalancer.h | 26 + .../src/hicn/strategies/loadBalancerWithPD.c | 368 +++++ .../src/hicn/strategies/loadBalancerWithPD.h | 30 + hicn-light/src/hicn/strategies/nexthopState.c | 206 +++ hicn-light/src/hicn/strategies/nexthopState.h | 94 ++ .../src/hicn/strategies/nexthopStateWithPD.c | 254 +++ .../src/hicn/strategies/nexthopStateWithPD.h | 106 ++ hicn-light/src/hicn/strategies/rnd.c | 175 ++ hicn-light/src/hicn/strategies/rnd.h | 26 + hicn-light/src/hicn/strategies/rndSegment.c | 207 +++ hicn-light/src/hicn/strategies/rndSegment.h | 27 + hicn-light/src/hicn/strategies/strategyImpl.h | 66 + hicn-light/src/hicn/utils/CMakeLists.txt | 42 + hicn-light/src/hicn/utils/address.c | 450 +++++ hicn-light/src/hicn/utils/address.h | 524 ++++++ hicn-light/src/hicn/utils/addressList.c | 133 ++ hicn-light/src/hicn/utils/addressList.h | 196 +++ hicn-light/src/hicn/utils/commands.h | 332 ++++ hicn-light/src/hicn/utils/interface.c | 168 ++ hicn-light/src/hicn/utils/interface.h | 208 +++ hicn-light/src/hicn/utils/interfaceSet.c | 149 ++ hicn-light/src/hicn/utils/interfaceSet.h | 198 +++ hicn-light/src/hicn/utils/punting.c | 98 ++ hicn-light/src/hicn/utils/punting.h | 72 + hicn-light/src/hicn/utils/utils.c | 236 +++ hicn-light/src/hicn/utils/utils.h | 70 + hicn-light/src/io/CMakeLists.txt | 53 - hicn-light/src/io/addressPair.c | 129 -- hicn-light/src/io/addressPair.h | 128 -- hicn-light/src/io/hicnConnection.c | 524 ------ hicn-light/src/io/hicnConnection.h | 53 - hicn-light/src/io/hicnListener.c | 727 --------- hicn-light/src/io/hicnListener.h | 42 - hicn-light/src/io/hicnTunnel.c | 106 -- hicn-light/src/io/hicnTunnel.h | 65 - hicn-light/src/io/ioOperations.c | 69 - hicn-light/src/io/ioOperations.h | 366 ----- hicn-light/src/io/listener.h | 105 -- hicn-light/src/io/listenerSet.c | 132 -- hicn-light/src/io/listenerSet.h | 137 -- hicn-light/src/io/streamConnection.c | 692 -------- hicn-light/src/io/streamConnection.h | 75 - hicn-light/src/io/tcpListener.c | 233 --- hicn-light/src/io/tcpListener.h | 40 - hicn-light/src/io/tcpTunnel.c | 43 - hicn-light/src/io/tcpTunnel.h | 42 - hicn-light/src/io/udpConnection.c | 391 ----- hicn-light/src/io/udpConnection.h | 53 - hicn-light/src/io/udpListener.c | 556 ------- hicn-light/src/io/udpListener.h | 35 - hicn-light/src/io/udpTunnel.c | 105 -- hicn-light/src/io/udpTunnel.h | 42 - hicn-light/src/messenger/CMakeLists.txt | 32 - hicn-light/src/messenger/messenger.c | 171 -- hicn-light/src/messenger/messenger.h | 69 - hicn-light/src/messenger/messengerRecipient.c | 62 - hicn-light/src/messenger/messengerRecipient.h | 104 -- hicn-light/src/messenger/missive.c | 54 - hicn-light/src/messenger/missive.h | 89 - hicn-light/src/messenger/missiveDeque.c | 77 - hicn-light/src/messenger/missiveDeque.h | 55 - hicn-light/src/messenger/missiveType.h | 55 - hicn-light/src/platforms/CMakeLists.txt | 40 - hicn-light/src/platforms/README.txt | 17 - hicn-light/src/platforms/android/system.c | 183 --- hicn-light/src/platforms/darwin/system.c | 146 -- hicn-light/src/platforms/linux/system.c | 184 --- hicn-light/src/platforms/windows/system.c | 223 --- hicn-light/src/platforms/windows/win_portability.c | 50 - hicn-light/src/platforms/windows/win_portability.h | 45 - hicn-light/src/processor/CMakeLists.txt | 40 - hicn-light/src/processor/fib.c | 448 ----- hicn-light/src/processor/fib.h | 43 - hicn-light/src/processor/fibEntry.c | 223 --- hicn-light/src/processor/fibEntry.h | 143 -- hicn-light/src/processor/fibEntryList.c | 72 - hicn-light/src/processor/fibEntryList.h | 96 -- hicn-light/src/processor/hashTableFunction.c | 47 - hicn-light/src/processor/hashTableFunction.h | 73 - hicn-light/src/processor/matchingRulesTable.c | 132 -- hicn-light/src/processor/matchingRulesTable.h | 113 -- hicn-light/src/processor/messageProcessor.c | 742 --------- hicn-light/src/processor/messageProcessor.h | 166 -- hicn-light/src/processor/pit.c | 45 - hicn-light/src/processor/pit.h | 114 -- hicn-light/src/processor/pitEntry.c | 142 -- hicn-light/src/processor/pitEntry.h | 164 -- hicn-light/src/processor/pitStandard.c | 304 ---- hicn-light/src/processor/pitStandard.h | 41 - hicn-light/src/processor/pitVerdict.h | 36 - hicn-light/src/socket/CMakeLists.txt | 31 - hicn-light/src/socket/api.c | 604 ------- hicn-light/src/socket/api.h | 217 --- hicn-light/src/socket/error.c | 7 - hicn-light/src/socket/error.h | 46 - hicn-light/src/socket/ops.h | 54 - hicn-light/src/socket/ops_linux.c | 1723 -------------------- hicn-light/src/strategies/CMakeLists.txt | 36 - hicn-light/src/strategies/loadBalancer.c | 278 ---- hicn-light/src/strategies/loadBalancer.h | 26 - hicn-light/src/strategies/loadBalancerWithPD.c | 368 ----- hicn-light/src/strategies/loadBalancerWithPD.h | 30 - hicn-light/src/strategies/nexthopState.c | 206 --- hicn-light/src/strategies/nexthopState.h | 94 -- hicn-light/src/strategies/nexthopStateWithPD.c | 254 --- hicn-light/src/strategies/nexthopStateWithPD.h | 106 -- hicn-light/src/strategies/rnd.c | 175 -- hicn-light/src/strategies/rnd.h | 26 - hicn-light/src/strategies/rndSegment.c | 207 --- hicn-light/src/strategies/rndSegment.h | 27 - hicn-light/src/strategies/strategyImpl.h | 66 - hicn-light/src/utils/CMakeLists.txt | 42 - hicn-light/src/utils/address.c | 450 ----- hicn-light/src/utils/address.h | 524 ------ hicn-light/src/utils/addressList.c | 133 -- hicn-light/src/utils/addressList.h | 196 --- hicn-light/src/utils/commands.h | 332 ---- hicn-light/src/utils/interface.c | 168 -- hicn-light/src/utils/interface.h | 208 --- hicn-light/src/utils/interfaceSet.c | 149 -- hicn-light/src/utils/interfaceSet.h | 198 --- hicn-light/src/utils/punting.c | 98 -- hicn-light/src/utils/punting.h | 72 - hicn-light/src/utils/utils.c | 236 --- hicn-light/src/utils/utils.h | 70 - 465 files changed, 37738 insertions(+), 34820 deletions(-) delete mode 100644 hicn-light/src/CMakeLists.txt delete mode 100644 hicn-light/src/command_line/CMakeLists.txt delete mode 100644 hicn-light/src/command_line/controller/CMakeLists.txt delete mode 100644 hicn-light/src/command_line/controller/hicnLightControl_main.c delete mode 100644 hicn-light/src/command_line/daemon/CMakeLists.txt delete mode 100644 hicn-light/src/command_line/daemon/hicnLightDaemon_main.c delete mode 100644 hicn-light/src/config.h.in delete mode 100644 hicn-light/src/config/CMakeLists.txt delete mode 100644 hicn-light/src/config/commandOps.c delete mode 100644 hicn-light/src/config/commandOps.h delete mode 100644 hicn-light/src/config/commandParser.c delete mode 100644 hicn-light/src/config/commandParser.h delete mode 100644 hicn-light/src/config/commandReturn.h delete mode 100644 hicn-light/src/config/configuration.c delete mode 100644 hicn-light/src/config/configuration.h delete mode 100644 hicn-light/src/config/configurationFile.c delete mode 100644 hicn-light/src/config/configurationFile.h delete mode 100644 hicn-light/src/config/configurationListeners.c delete mode 100644 hicn-light/src/config/configurationListeners.h delete mode 100644 hicn-light/src/config/controlAdd.c delete mode 100644 hicn-light/src/config/controlAdd.h delete mode 100644 hicn-light/src/config/controlAddConnection.c delete mode 100644 hicn-light/src/config/controlAddConnection.h delete mode 100644 hicn-light/src/config/controlAddListener.c delete mode 100644 hicn-light/src/config/controlAddListener.h delete mode 100644 hicn-light/src/config/controlAddPunting.c delete mode 100644 hicn-light/src/config/controlAddPunting.h delete mode 100644 hicn-light/src/config/controlAddRoute.c delete mode 100644 hicn-light/src/config/controlAddRoute.h delete mode 100644 hicn-light/src/config/controlCache.c delete mode 100644 hicn-light/src/config/controlCache.h delete mode 100644 hicn-light/src/config/controlCacheClear.c delete mode 100644 hicn-light/src/config/controlCacheClear.h delete mode 100644 hicn-light/src/config/controlCacheServe.c delete mode 100644 hicn-light/src/config/controlCacheServe.h delete mode 100644 hicn-light/src/config/controlCacheStore.c delete mode 100644 hicn-light/src/config/controlCacheStore.h delete mode 100644 hicn-light/src/config/controlList.c delete mode 100644 hicn-light/src/config/controlList.h delete mode 100644 hicn-light/src/config/controlListConnections.c delete mode 100644 hicn-light/src/config/controlListConnections.h delete mode 100644 hicn-light/src/config/controlListInterfaces.c delete mode 100644 hicn-light/src/config/controlListInterfaces.h delete mode 100644 hicn-light/src/config/controlListListeners.c delete mode 100644 hicn-light/src/config/controlListListeners.h delete mode 100644 hicn-light/src/config/controlListRoutes.c delete mode 100644 hicn-light/src/config/controlListRoutes.h delete mode 100644 hicn-light/src/config/controlMapMe.c delete mode 100644 hicn-light/src/config/controlMapMe.h delete mode 100644 hicn-light/src/config/controlMapMeDiscovery.c delete mode 100644 hicn-light/src/config/controlMapMeDiscovery.h delete mode 100644 hicn-light/src/config/controlMapMeEnable.c delete mode 100644 hicn-light/src/config/controlMapMeEnable.h delete mode 100644 hicn-light/src/config/controlMapMeRetx.c delete mode 100644 hicn-light/src/config/controlMapMeRetx.h delete mode 100644 hicn-light/src/config/controlMapMeTimescale.c delete mode 100644 hicn-light/src/config/controlMapMeTimescale.h delete mode 100644 hicn-light/src/config/controlQuit.c delete mode 100644 hicn-light/src/config/controlQuit.h delete mode 100644 hicn-light/src/config/controlRemove.c delete mode 100644 hicn-light/src/config/controlRemove.h delete mode 100644 hicn-light/src/config/controlRemoveConnection.c delete mode 100644 hicn-light/src/config/controlRemoveConnection.h delete mode 100644 hicn-light/src/config/controlRemovePunting.c delete mode 100644 hicn-light/src/config/controlRemovePunting.h delete mode 100644 hicn-light/src/config/controlRemoveRoute.c delete mode 100644 hicn-light/src/config/controlRemoveRoute.h delete mode 100644 hicn-light/src/config/controlRoot.c delete mode 100644 hicn-light/src/config/controlRoot.h delete mode 100644 hicn-light/src/config/controlSet.c delete mode 100644 hicn-light/src/config/controlSet.h delete mode 100644 hicn-light/src/config/controlSetDebug.c delete mode 100644 hicn-light/src/config/controlSetDebug.h delete mode 100644 hicn-light/src/config/controlSetStrategy.c delete mode 100644 hicn-light/src/config/controlSetStrategy.h delete mode 100644 hicn-light/src/config/controlSetWldr.c delete mode 100644 hicn-light/src/config/controlSetWldr.h delete mode 100644 hicn-light/src/config/controlState.c delete mode 100644 hicn-light/src/config/controlState.h delete mode 100644 hicn-light/src/config/controlUnset.c delete mode 100644 hicn-light/src/config/controlUnset.h delete mode 100644 hicn-light/src/config/controlUnsetDebug.c delete mode 100644 hicn-light/src/config/controlUnsetDebug.h delete mode 100644 hicn-light/src/config/symbolicNameTable.c delete mode 100644 hicn-light/src/config/symbolicNameTable.h delete mode 100644 hicn-light/src/content_store/CMakeLists.txt delete mode 100644 hicn-light/src/content_store/contentStoreEntry.c delete mode 100644 hicn-light/src/content_store/contentStoreEntry.h delete mode 100644 hicn-light/src/content_store/contentStoreInterface.c delete mode 100644 hicn-light/src/content_store/contentStoreInterface.h delete mode 100644 hicn-light/src/content_store/contentStoreLRU.c delete mode 100644 hicn-light/src/content_store/contentStoreLRU.h delete mode 100644 hicn-light/src/content_store/listLRU.c delete mode 100644 hicn-light/src/content_store/listLRU.h delete mode 100644 hicn-light/src/content_store/listTimeOrdered.c delete mode 100644 hicn-light/src/content_store/listTimeOrdered.h delete mode 100644 hicn-light/src/core/CMakeLists.txt delete mode 100644 hicn-light/src/core/connection.c delete mode 100644 hicn-light/src/core/connection.h delete mode 100644 hicn-light/src/core/connectionList.c delete mode 100644 hicn-light/src/core/connectionList.h delete mode 100644 hicn-light/src/core/connectionManager.c delete mode 100644 hicn-light/src/core/connectionManager.h delete mode 100644 hicn-light/src/core/connectionTable.c delete mode 100644 hicn-light/src/core/connectionTable.h delete mode 100644 hicn-light/src/core/dispatcher.c delete mode 100644 hicn-light/src/core/dispatcher.h delete mode 100644 hicn-light/src/core/forwarder.c delete mode 100644 hicn-light/src/core/forwarder.h delete mode 100644 hicn-light/src/core/logger.c delete mode 100644 hicn-light/src/core/logger.h delete mode 100644 hicn-light/src/core/mapMe.c delete mode 100644 hicn-light/src/core/mapMe.h delete mode 100644 hicn-light/src/core/message.c delete mode 100644 hicn-light/src/core/message.h delete mode 100644 hicn-light/src/core/messageHandler.h delete mode 100644 hicn-light/src/core/messagePacketType.h delete mode 100644 hicn-light/src/core/name.c delete mode 100644 hicn-light/src/core/name.h delete mode 100644 hicn-light/src/core/nameBitvector.c delete mode 100644 hicn-light/src/core/nameBitvector.h delete mode 100644 hicn-light/src/core/numberSet.c delete mode 100644 hicn-light/src/core/numberSet.h delete mode 100644 hicn-light/src/core/streamBuffer.c delete mode 100644 hicn-light/src/core/streamBuffer.h delete mode 100644 hicn-light/src/core/system.h delete mode 100644 hicn-light/src/core/ticks.h delete mode 100644 hicn-light/src/core/wldr.c delete mode 100644 hicn-light/src/core/wldr.h create mode 100644 hicn-light/src/hicn/CMakeLists.txt create mode 100644 hicn-light/src/hicn/api/CMakeLists.txt create mode 100644 hicn-light/src/hicn/api/api.c create mode 100644 hicn-light/src/hicn/api/api.h create mode 100644 hicn-light/src/hicn/api/commands.h create mode 100644 hicn-light/src/hicn/api/face.h create mode 100644 hicn-light/src/hicn/api/fib_policy.h create mode 100644 hicn-light/src/hicn/api/ip_address.h create mode 100644 hicn-light/src/hicn/api/token.h create mode 100644 hicn-light/src/hicn/api/types.h create mode 100644 hicn-light/src/hicn/command_line/CMakeLists.txt create mode 100644 hicn-light/src/hicn/command_line/controller/CMakeLists.txt create mode 100644 hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c create mode 100644 hicn-light/src/hicn/command_line/daemon/CMakeLists.txt create mode 100644 hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c create mode 100644 hicn-light/src/hicn/config.h.in create mode 100644 hicn-light/src/hicn/config/CMakeLists.txt create mode 100644 hicn-light/src/hicn/config/commandOps.c create mode 100644 hicn-light/src/hicn/config/commandOps.h create mode 100644 hicn-light/src/hicn/config/commandParser.c create mode 100644 hicn-light/src/hicn/config/commandParser.h create mode 100644 hicn-light/src/hicn/config/commandReturn.h create mode 100644 hicn-light/src/hicn/config/configuration.c create mode 100644 hicn-light/src/hicn/config/configuration.h create mode 100644 hicn-light/src/hicn/config/configurationFile.c create mode 100644 hicn-light/src/hicn/config/configurationFile.h create mode 100644 hicn-light/src/hicn/config/configurationListeners.c create mode 100644 hicn-light/src/hicn/config/configurationListeners.h create mode 100644 hicn-light/src/hicn/config/controlAdd.c create mode 100644 hicn-light/src/hicn/config/controlAdd.h create mode 100644 hicn-light/src/hicn/config/controlAddConnection.c create mode 100644 hicn-light/src/hicn/config/controlAddConnection.h create mode 100644 hicn-light/src/hicn/config/controlAddListener.c create mode 100644 hicn-light/src/hicn/config/controlAddListener.h create mode 100644 hicn-light/src/hicn/config/controlAddPunting.c create mode 100644 hicn-light/src/hicn/config/controlAddPunting.h create mode 100644 hicn-light/src/hicn/config/controlAddRoute.c create mode 100644 hicn-light/src/hicn/config/controlAddRoute.h create mode 100644 hicn-light/src/hicn/config/controlCache.c create mode 100644 hicn-light/src/hicn/config/controlCache.h create mode 100644 hicn-light/src/hicn/config/controlCacheClear.c create mode 100644 hicn-light/src/hicn/config/controlCacheClear.h create mode 100644 hicn-light/src/hicn/config/controlCacheServe.c create mode 100644 hicn-light/src/hicn/config/controlCacheServe.h create mode 100644 hicn-light/src/hicn/config/controlCacheStore.c create mode 100644 hicn-light/src/hicn/config/controlCacheStore.h create mode 100644 hicn-light/src/hicn/config/controlList.c create mode 100644 hicn-light/src/hicn/config/controlList.h create mode 100644 hicn-light/src/hicn/config/controlListConnections.c create mode 100644 hicn-light/src/hicn/config/controlListConnections.h create mode 100644 hicn-light/src/hicn/config/controlListInterfaces.c create mode 100644 hicn-light/src/hicn/config/controlListInterfaces.h create mode 100644 hicn-light/src/hicn/config/controlListListeners.c create mode 100644 hicn-light/src/hicn/config/controlListListeners.h create mode 100644 hicn-light/src/hicn/config/controlListRoutes.c create mode 100644 hicn-light/src/hicn/config/controlListRoutes.h create mode 100644 hicn-light/src/hicn/config/controlMapMe.c create mode 100644 hicn-light/src/hicn/config/controlMapMe.h create mode 100644 hicn-light/src/hicn/config/controlMapMeDiscovery.c create mode 100644 hicn-light/src/hicn/config/controlMapMeDiscovery.h create mode 100644 hicn-light/src/hicn/config/controlMapMeEnable.c create mode 100644 hicn-light/src/hicn/config/controlMapMeEnable.h create mode 100644 hicn-light/src/hicn/config/controlMapMeRetx.c create mode 100644 hicn-light/src/hicn/config/controlMapMeRetx.h create mode 100644 hicn-light/src/hicn/config/controlMapMeTimescale.c create mode 100644 hicn-light/src/hicn/config/controlMapMeTimescale.h create mode 100644 hicn-light/src/hicn/config/controlQuit.c create mode 100644 hicn-light/src/hicn/config/controlQuit.h create mode 100644 hicn-light/src/hicn/config/controlRemove.c create mode 100644 hicn-light/src/hicn/config/controlRemove.h create mode 100644 hicn-light/src/hicn/config/controlRemoveConnection.c create mode 100644 hicn-light/src/hicn/config/controlRemoveConnection.h create mode 100644 hicn-light/src/hicn/config/controlRemovePunting.c create mode 100644 hicn-light/src/hicn/config/controlRemovePunting.h create mode 100644 hicn-light/src/hicn/config/controlRemoveRoute.c create mode 100644 hicn-light/src/hicn/config/controlRemoveRoute.h create mode 100644 hicn-light/src/hicn/config/controlRoot.c create mode 100644 hicn-light/src/hicn/config/controlRoot.h create mode 100644 hicn-light/src/hicn/config/controlSet.c create mode 100644 hicn-light/src/hicn/config/controlSet.h create mode 100644 hicn-light/src/hicn/config/controlSetDebug.c create mode 100644 hicn-light/src/hicn/config/controlSetDebug.h create mode 100644 hicn-light/src/hicn/config/controlSetStrategy.c create mode 100644 hicn-light/src/hicn/config/controlSetStrategy.h create mode 100644 hicn-light/src/hicn/config/controlSetWldr.c create mode 100644 hicn-light/src/hicn/config/controlSetWldr.h create mode 100644 hicn-light/src/hicn/config/controlState.c create mode 100644 hicn-light/src/hicn/config/controlState.h create mode 100644 hicn-light/src/hicn/config/controlUnset.c create mode 100644 hicn-light/src/hicn/config/controlUnset.h create mode 100644 hicn-light/src/hicn/config/controlUnsetDebug.c create mode 100644 hicn-light/src/hicn/config/controlUnsetDebug.h create mode 100644 hicn-light/src/hicn/config/symbolicNameTable.c create mode 100644 hicn-light/src/hicn/config/symbolicNameTable.h create mode 100644 hicn-light/src/hicn/content_store/CMakeLists.txt create mode 100644 hicn-light/src/hicn/content_store/contentStoreEntry.c create mode 100644 hicn-light/src/hicn/content_store/contentStoreEntry.h create mode 100644 hicn-light/src/hicn/content_store/contentStoreInterface.c create mode 100644 hicn-light/src/hicn/content_store/contentStoreInterface.h create mode 100644 hicn-light/src/hicn/content_store/contentStoreLRU.c create mode 100644 hicn-light/src/hicn/content_store/contentStoreLRU.h create mode 100644 hicn-light/src/hicn/content_store/listLRU.c create mode 100644 hicn-light/src/hicn/content_store/listLRU.h create mode 100644 hicn-light/src/hicn/content_store/listTimeOrdered.c create mode 100644 hicn-light/src/hicn/content_store/listTimeOrdered.h create mode 100644 hicn-light/src/hicn/core/CMakeLists.txt create mode 100644 hicn-light/src/hicn/core/connection.c create mode 100644 hicn-light/src/hicn/core/connection.h create mode 100644 hicn-light/src/hicn/core/connectionList.c create mode 100644 hicn-light/src/hicn/core/connectionList.h create mode 100644 hicn-light/src/hicn/core/connectionManager.c create mode 100644 hicn-light/src/hicn/core/connectionManager.h create mode 100644 hicn-light/src/hicn/core/connectionTable.c create mode 100644 hicn-light/src/hicn/core/connectionTable.h create mode 100644 hicn-light/src/hicn/core/dispatcher.c create mode 100644 hicn-light/src/hicn/core/dispatcher.h create mode 100644 hicn-light/src/hicn/core/forwarder.c create mode 100644 hicn-light/src/hicn/core/forwarder.h create mode 100644 hicn-light/src/hicn/core/logger.c create mode 100644 hicn-light/src/hicn/core/logger.h create mode 100644 hicn-light/src/hicn/core/mapMe.c create mode 100644 hicn-light/src/hicn/core/mapMe.h create mode 100644 hicn-light/src/hicn/core/message.c create mode 100644 hicn-light/src/hicn/core/message.h create mode 100644 hicn-light/src/hicn/core/messageHandler.h create mode 100644 hicn-light/src/hicn/core/messagePacketType.h create mode 100644 hicn-light/src/hicn/core/name.c create mode 100644 hicn-light/src/hicn/core/name.h create mode 100644 hicn-light/src/hicn/core/nameBitvector.c create mode 100644 hicn-light/src/hicn/core/nameBitvector.h create mode 100644 hicn-light/src/hicn/core/numberSet.c create mode 100644 hicn-light/src/hicn/core/numberSet.h create mode 100644 hicn-light/src/hicn/core/streamBuffer.c create mode 100644 hicn-light/src/hicn/core/streamBuffer.h create mode 100644 hicn-light/src/hicn/core/system.h create mode 100644 hicn-light/src/hicn/core/ticks.h create mode 100644 hicn-light/src/hicn/core/wldr.c create mode 100644 hicn-light/src/hicn/core/wldr.h create mode 100644 hicn-light/src/hicn/io/CMakeLists.txt create mode 100644 hicn-light/src/hicn/io/addressPair.c create mode 100644 hicn-light/src/hicn/io/addressPair.h create mode 100644 hicn-light/src/hicn/io/hicnConnection.c create mode 100644 hicn-light/src/hicn/io/hicnConnection.h create mode 100644 hicn-light/src/hicn/io/hicnListener.c create mode 100644 hicn-light/src/hicn/io/hicnListener.h create mode 100644 hicn-light/src/hicn/io/hicnTunnel.c create mode 100644 hicn-light/src/hicn/io/hicnTunnel.h create mode 100644 hicn-light/src/hicn/io/ioOperations.c create mode 100644 hicn-light/src/hicn/io/ioOperations.h create mode 100644 hicn-light/src/hicn/io/listener.h create mode 100644 hicn-light/src/hicn/io/listenerSet.c create mode 100644 hicn-light/src/hicn/io/listenerSet.h create mode 100644 hicn-light/src/hicn/io/streamConnection.c create mode 100644 hicn-light/src/hicn/io/streamConnection.h create mode 100644 hicn-light/src/hicn/io/tcpListener.c create mode 100644 hicn-light/src/hicn/io/tcpListener.h create mode 100644 hicn-light/src/hicn/io/tcpTunnel.c create mode 100644 hicn-light/src/hicn/io/tcpTunnel.h create mode 100644 hicn-light/src/hicn/io/udpConnection.c create mode 100644 hicn-light/src/hicn/io/udpConnection.h create mode 100644 hicn-light/src/hicn/io/udpListener.c create mode 100644 hicn-light/src/hicn/io/udpListener.h create mode 100644 hicn-light/src/hicn/io/udpTunnel.c create mode 100644 hicn-light/src/hicn/io/udpTunnel.h create mode 100644 hicn-light/src/hicn/messenger/CMakeLists.txt create mode 100644 hicn-light/src/hicn/messenger/messenger.c create mode 100644 hicn-light/src/hicn/messenger/messenger.h create mode 100644 hicn-light/src/hicn/messenger/messengerRecipient.c create mode 100644 hicn-light/src/hicn/messenger/messengerRecipient.h create mode 100644 hicn-light/src/hicn/messenger/missive.c create mode 100644 hicn-light/src/hicn/messenger/missive.h create mode 100644 hicn-light/src/hicn/messenger/missiveDeque.c create mode 100644 hicn-light/src/hicn/messenger/missiveDeque.h create mode 100644 hicn-light/src/hicn/messenger/missiveType.h create mode 100644 hicn-light/src/hicn/platforms/CMakeLists.txt create mode 100644 hicn-light/src/hicn/platforms/README.txt create mode 100644 hicn-light/src/hicn/platforms/android/system.c create mode 100644 hicn-light/src/hicn/platforms/darwin/system.c create mode 100644 hicn-light/src/hicn/platforms/linux/system.c create mode 100644 hicn-light/src/hicn/platforms/windows/system.c create mode 100644 hicn-light/src/hicn/platforms/windows/win_portability.c create mode 100644 hicn-light/src/hicn/platforms/windows/win_portability.h create mode 100644 hicn-light/src/hicn/processor/CMakeLists.txt create mode 100644 hicn-light/src/hicn/processor/fib.c create mode 100644 hicn-light/src/hicn/processor/fib.h create mode 100644 hicn-light/src/hicn/processor/fibEntry.c create mode 100644 hicn-light/src/hicn/processor/fibEntry.h create mode 100644 hicn-light/src/hicn/processor/fibEntryList.c create mode 100644 hicn-light/src/hicn/processor/fibEntryList.h create mode 100644 hicn-light/src/hicn/processor/hashTableFunction.c create mode 100644 hicn-light/src/hicn/processor/hashTableFunction.h create mode 100644 hicn-light/src/hicn/processor/matchingRulesTable.c create mode 100644 hicn-light/src/hicn/processor/matchingRulesTable.h create mode 100644 hicn-light/src/hicn/processor/messageProcessor.c create mode 100644 hicn-light/src/hicn/processor/messageProcessor.h create mode 100644 hicn-light/src/hicn/processor/pit.c create mode 100644 hicn-light/src/hicn/processor/pit.h create mode 100644 hicn-light/src/hicn/processor/pitEntry.c create mode 100644 hicn-light/src/hicn/processor/pitEntry.h create mode 100644 hicn-light/src/hicn/processor/pitStandard.c create mode 100644 hicn-light/src/hicn/processor/pitStandard.h create mode 100644 hicn-light/src/hicn/processor/pitVerdict.h create mode 100644 hicn-light/src/hicn/socket/CMakeLists.txt create mode 100644 hicn-light/src/hicn/socket/api.c create mode 100644 hicn-light/src/hicn/socket/api.h create mode 100644 hicn-light/src/hicn/socket/error.c create mode 100644 hicn-light/src/hicn/socket/error.h create mode 100644 hicn-light/src/hicn/socket/ops.h create mode 100644 hicn-light/src/hicn/socket/ops_linux.c create mode 100644 hicn-light/src/hicn/strategies/CMakeLists.txt create mode 100644 hicn-light/src/hicn/strategies/loadBalancer.c create mode 100644 hicn-light/src/hicn/strategies/loadBalancer.h create mode 100644 hicn-light/src/hicn/strategies/loadBalancerWithPD.c create mode 100644 hicn-light/src/hicn/strategies/loadBalancerWithPD.h create mode 100644 hicn-light/src/hicn/strategies/nexthopState.c create mode 100644 hicn-light/src/hicn/strategies/nexthopState.h create mode 100644 hicn-light/src/hicn/strategies/nexthopStateWithPD.c create mode 100644 hicn-light/src/hicn/strategies/nexthopStateWithPD.h create mode 100644 hicn-light/src/hicn/strategies/rnd.c create mode 100644 hicn-light/src/hicn/strategies/rnd.h create mode 100644 hicn-light/src/hicn/strategies/rndSegment.c create mode 100644 hicn-light/src/hicn/strategies/rndSegment.h create mode 100644 hicn-light/src/hicn/strategies/strategyImpl.h create mode 100644 hicn-light/src/hicn/utils/CMakeLists.txt create mode 100644 hicn-light/src/hicn/utils/address.c create mode 100644 hicn-light/src/hicn/utils/address.h create mode 100644 hicn-light/src/hicn/utils/addressList.c create mode 100644 hicn-light/src/hicn/utils/addressList.h create mode 100644 hicn-light/src/hicn/utils/commands.h create mode 100644 hicn-light/src/hicn/utils/interface.c create mode 100644 hicn-light/src/hicn/utils/interface.h create mode 100644 hicn-light/src/hicn/utils/interfaceSet.c create mode 100644 hicn-light/src/hicn/utils/interfaceSet.h create mode 100644 hicn-light/src/hicn/utils/punting.c create mode 100644 hicn-light/src/hicn/utils/punting.h create mode 100644 hicn-light/src/hicn/utils/utils.c create mode 100644 hicn-light/src/hicn/utils/utils.h delete mode 100644 hicn-light/src/io/CMakeLists.txt delete mode 100644 hicn-light/src/io/addressPair.c delete mode 100644 hicn-light/src/io/addressPair.h delete mode 100644 hicn-light/src/io/hicnConnection.c delete mode 100644 hicn-light/src/io/hicnConnection.h delete mode 100644 hicn-light/src/io/hicnListener.c delete mode 100644 hicn-light/src/io/hicnListener.h delete mode 100644 hicn-light/src/io/hicnTunnel.c delete mode 100644 hicn-light/src/io/hicnTunnel.h delete mode 100644 hicn-light/src/io/ioOperations.c delete mode 100644 hicn-light/src/io/ioOperations.h delete mode 100644 hicn-light/src/io/listener.h delete mode 100644 hicn-light/src/io/listenerSet.c delete mode 100644 hicn-light/src/io/listenerSet.h delete mode 100644 hicn-light/src/io/streamConnection.c delete mode 100644 hicn-light/src/io/streamConnection.h delete mode 100644 hicn-light/src/io/tcpListener.c delete mode 100644 hicn-light/src/io/tcpListener.h delete mode 100644 hicn-light/src/io/tcpTunnel.c delete mode 100644 hicn-light/src/io/tcpTunnel.h delete mode 100644 hicn-light/src/io/udpConnection.c delete mode 100644 hicn-light/src/io/udpConnection.h delete mode 100644 hicn-light/src/io/udpListener.c delete mode 100644 hicn-light/src/io/udpListener.h delete mode 100644 hicn-light/src/io/udpTunnel.c delete mode 100644 hicn-light/src/io/udpTunnel.h delete mode 100644 hicn-light/src/messenger/CMakeLists.txt delete mode 100644 hicn-light/src/messenger/messenger.c delete mode 100644 hicn-light/src/messenger/messenger.h delete mode 100644 hicn-light/src/messenger/messengerRecipient.c delete mode 100644 hicn-light/src/messenger/messengerRecipient.h delete mode 100644 hicn-light/src/messenger/missive.c delete mode 100644 hicn-light/src/messenger/missive.h delete mode 100644 hicn-light/src/messenger/missiveDeque.c delete mode 100644 hicn-light/src/messenger/missiveDeque.h delete mode 100644 hicn-light/src/messenger/missiveType.h delete mode 100644 hicn-light/src/platforms/CMakeLists.txt delete mode 100644 hicn-light/src/platforms/README.txt delete mode 100644 hicn-light/src/platforms/android/system.c delete mode 100644 hicn-light/src/platforms/darwin/system.c delete mode 100644 hicn-light/src/platforms/linux/system.c delete mode 100644 hicn-light/src/platforms/windows/system.c delete mode 100644 hicn-light/src/platforms/windows/win_portability.c delete mode 100644 hicn-light/src/platforms/windows/win_portability.h delete mode 100644 hicn-light/src/processor/CMakeLists.txt delete mode 100644 hicn-light/src/processor/fib.c delete mode 100644 hicn-light/src/processor/fib.h delete mode 100644 hicn-light/src/processor/fibEntry.c delete mode 100644 hicn-light/src/processor/fibEntry.h delete mode 100644 hicn-light/src/processor/fibEntryList.c delete mode 100644 hicn-light/src/processor/fibEntryList.h delete mode 100644 hicn-light/src/processor/hashTableFunction.c delete mode 100644 hicn-light/src/processor/hashTableFunction.h delete mode 100644 hicn-light/src/processor/matchingRulesTable.c delete mode 100644 hicn-light/src/processor/matchingRulesTable.h delete mode 100644 hicn-light/src/processor/messageProcessor.c delete mode 100644 hicn-light/src/processor/messageProcessor.h delete mode 100644 hicn-light/src/processor/pit.c delete mode 100644 hicn-light/src/processor/pit.h delete mode 100644 hicn-light/src/processor/pitEntry.c delete mode 100644 hicn-light/src/processor/pitEntry.h delete mode 100644 hicn-light/src/processor/pitStandard.c delete mode 100644 hicn-light/src/processor/pitStandard.h delete mode 100644 hicn-light/src/processor/pitVerdict.h delete mode 100644 hicn-light/src/socket/CMakeLists.txt delete mode 100644 hicn-light/src/socket/api.c delete mode 100644 hicn-light/src/socket/api.h delete mode 100644 hicn-light/src/socket/error.c delete mode 100644 hicn-light/src/socket/error.h delete mode 100644 hicn-light/src/socket/ops.h delete mode 100644 hicn-light/src/socket/ops_linux.c delete mode 100644 hicn-light/src/strategies/CMakeLists.txt delete mode 100644 hicn-light/src/strategies/loadBalancer.c delete mode 100644 hicn-light/src/strategies/loadBalancer.h delete mode 100644 hicn-light/src/strategies/loadBalancerWithPD.c delete mode 100644 hicn-light/src/strategies/loadBalancerWithPD.h delete mode 100644 hicn-light/src/strategies/nexthopState.c delete mode 100644 hicn-light/src/strategies/nexthopState.h delete mode 100644 hicn-light/src/strategies/nexthopStateWithPD.c delete mode 100644 hicn-light/src/strategies/nexthopStateWithPD.h delete mode 100644 hicn-light/src/strategies/rnd.c delete mode 100644 hicn-light/src/strategies/rnd.h delete mode 100644 hicn-light/src/strategies/rndSegment.c delete mode 100644 hicn-light/src/strategies/rndSegment.h delete mode 100644 hicn-light/src/strategies/strategyImpl.h delete mode 100644 hicn-light/src/utils/CMakeLists.txt delete mode 100644 hicn-light/src/utils/address.c delete mode 100644 hicn-light/src/utils/address.h delete mode 100644 hicn-light/src/utils/addressList.c delete mode 100644 hicn-light/src/utils/addressList.h delete mode 100644 hicn-light/src/utils/commands.h delete mode 100644 hicn-light/src/utils/interface.c delete mode 100644 hicn-light/src/utils/interface.h delete mode 100644 hicn-light/src/utils/interfaceSet.c delete mode 100644 hicn-light/src/utils/interfaceSet.h delete mode 100644 hicn-light/src/utils/punting.c delete mode 100644 hicn-light/src/utils/punting.h delete mode 100644 hicn-light/src/utils/utils.c delete mode 100644 hicn-light/src/utils/utils.h (limited to 'hicn-light/src') diff --git a/hicn-light/src/CMakeLists.txt b/hicn-light/src/CMakeLists.txt deleted file mode 100644 index c7a4b5efd..000000000 --- a/hicn-light/src/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# Define a few configuration variables that we want accessible in the software - -include(BuildMacros) -configure_file(config.h.in config.h @ONLY) - -if(NOT ANDROID_API AND NOT COMPILE_FOR_IOS) - add_subdirectory(command_line) -endif () - -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 HEADER_FILES - ${CMAKE_CURRENT_BINARY_DIR}/config.h -) - -if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND ENABLE_PUNTING) - list(APPEND COMPILER_DEFINITIONS - "-DPUNTING" - ) -endif() - -list(APPEND COMPILER_DEFINITIONS - "-DWITH_MAPME -DWITH_MAPME_FIXES" -) - -list(INSERT HICN_LIGHT_INCLUDE_DIRS 0 - ${CMAKE_CURRENT_SOURCE_DIR}/.. -) - -build_library(${LIBHICN_LIGHT} - STATIC - SOURCES ${SOURCE_FILES} - INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} - LINK_LIBRARIES ${LIBRARIES} - DEPENDS ${DEPENDENCIES} - COMPONENT ${LIBHICN_LIGHT} - INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS} - INSTALL_ROOT_DIR hicn/light - DEFINITIONS ${COMPILER_DEFINITIONS} -) diff --git a/hicn-light/src/command_line/CMakeLists.txt b/hicn-light/src/command_line/CMakeLists.txt deleted file mode 100644 index 16c23dc5c..000000000 --- a/hicn-light/src/command_line/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(controller) -add_subdirectory(daemon) diff --git a/hicn-light/src/command_line/controller/CMakeLists.txt b/hicn-light/src/command_line/controller/CMakeLists.txt deleted file mode 100644 index b53e610a1..000000000 --- a/hicn-light/src/command_line/controller/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT 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 -) - -build_executable(${HICN_LIGHT_CONTROL} - SOURCES ${CONTROLLER_SRC} - LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES} - DEPENDS hicn-light - COMPONENT hicn-light -) diff --git a/hicn-light/src/command_line/controller/hicnLightControl_main.c b/hicn-light/src/command_line/controller/hicnLightControl_main.c deleted file mode 100644 index b43789fe5..000000000 --- a/hicn-light/src/command_line/controller/hicnLightControl_main.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#endif -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -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_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)}; - -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 **keystorePath, - char **keystorePassword, PARCList *commandList) { - static struct option longFormOptions[] = { - {"help", no_argument, 0, 'h'}, - {"keystore", required_argument, 0, 'k'}, - {"password", 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, "hk:p:", longFormOptions, &optionIndex); - - // Detect the end of the options. - if (c == -1) { - break; - } - - switch (c) { - case 'k': - *keystorePath = optarg; - break; - - case 'p': - *keystorePassword = optarg; - break; - - case 'h': - default: - _displayUsage(argv[0]); - return 0; - } - } - - // Any remaining parameters get put in the command list. - 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); - - if (!_parseArgs(argc, argv, NULL, NULL, commands)) { - parcList_Release(&commands); - exit(EXIT_FAILURE); - } - - ControlMainState mainState; - mainState.controlState = - controlState_Create(&mainState, _writeAndReadMessage, true); - - 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); - controlState_DispatchCommand(mainState.controlState, commands); - char **commandOutputMain = - controlState_GetCommandOutput(mainState.controlState); - if (commandOutputMain != NULL && commandOutputLen > 0) { - for (size_t j = 0; j < commandOutputLen; j++) { - printf("Output %zu: %s \n", j, commandOutputMain[j]); - } - 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/command_line/daemon/CMakeLists.txt b/hicn-light/src/command_line/daemon/CMakeLists.txt deleted file mode 100644 index fd6cc9310..000000000 --- a/hicn-light/src/command_line/daemon/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT 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 DAEMON_SRC - hicnLightDaemon_main.c -) - -build_executable(${HICN_LIGHT_DAEMON} - SOURCES ${DAEMON_SRC} - LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES} - DEPENDS hicn-light - COMPONENT hicn-light -) \ No newline at end of file diff --git a/hicn-light/src/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/command_line/daemon/hicnLightDaemon_main.c deleted file mode 100644 index 14192618b..000000000 --- a/hicn-light/src/command_line/daemon/hicnLightDaemon_main.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -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 */ - for (int i = getdtablesize(); i >= 0; --i) { - close(i); - } - - // 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?"); - 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/config.h.in b/hicn-light/src/config.h.in deleted file mode 100644 index 8b763df40..000000000 --- a/hicn-light/src/config.h.in +++ /dev/null @@ -1,9 +0,0 @@ -/* CPU Cache line size */ -#define LEVEL1_DCACHE_LINESIZE @LEVEL1_DCACHE_LINESIZE@ - -#ifndef _WIN32 -#define _GNU_SOURCE -#else -#include -#endif - diff --git a/hicn-light/src/config/CMakeLists.txt b/hicn-light/src/config/CMakeLists.txt deleted file mode 100644 index 5ce680bfc..000000000 --- a/hicn-light/src/config/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -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}/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}/controlQuit.h - ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h - ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h - ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.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 -) - -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}/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}/controlQuit.c - ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c - ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c - ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.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 -) - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/config/commandOps.c b/hicn-light/src/config/commandOps.c deleted file mode 100644 index 28d3369e1..000000000 --- a/hicn-light/src/config/commandOps.c +++ /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. - */ - -#include -#include -#include -#include -#include -#include - -#ifndef __ANDROID__ -#ifdef HAVE_ERRNO_H -#include -#else -#ifndef _WIN32 -extern int errno; -#endif -#endif -#endif - -#include -#include -#include -#include - -CommandOps *commandOps_Create(void *closure, const char *command, - void (*init)(CommandParser *parser, - CommandOps *ops), - CommandReturn (*execute)(CommandParser *parser, - CommandOps *ops, - PARCList *args), - 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/config/commandOps.h b/hicn-light/src/config/commandOps.h deleted file mode 100644 index 6428a3ebf..000000000 --- a/hicn-light/src/config/commandOps.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 - -#include - -// 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); - 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), - 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/config/commandParser.c b/hicn-light/src/config/commandParser.c deleted file mode 100644 index 9759d2e37..000000000 --- a/hicn-light/src/config/commandParser.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#ifndef __ANDROID__ -#ifdef HAVE_ERRNO_H -#include -#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) { - CommandOps *ops = commandParser_MatchCommand(state, args); - - if (ops == NULL) { - printf("Command not found.\n"); - return CommandReturn_Failure; - } else { - return ops->execute(state, ops, args); - } -} - -bool commandParser_ContainsCommand(CommandParser *parser, const char *command) { - CommandOps *ops = parcTreeRedBlack_Get(parser->commandTree, command); - return (ops != NULL); -} diff --git a/hicn-light/src/config/commandParser.h b/hicn-light/src/config/commandParser.h deleted file mode 100644 index 78e19e6e3..000000000 --- a/hicn-light/src/config/commandParser.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. - */ - -/** - * @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 -#include - -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 - * - * @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); - -/** - * 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/config/commandReturn.h b/hicn-light/src/config/commandReturn.h deleted file mode 100644 index 16ee93db1..000000000 --- a/hicn-light/src/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/config/configuration.c b/hicn-light/src/config/configuration.c deleted file mode 100644 index 3d25e425d..000000000 --- a/hicn-light/src/config/configuration.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#endif -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#ifdef WITH_MAPME -#include -#endif /* WITH_MAPME */ - -#include - -#include -#include -#include - -#include -#include //the listener list -#include // needed to print -#include -#include - -#include - -#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; -}; - -// ======================================================================================== - -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 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) > 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.ipv4 = tmpAddr.sin_addr.s_addr; - } else if (addressGetType(addressEntry) == ADDR_INET6) { - addressGetInet6(addressEntry, &tmpAddr6); - listRouteCommand->addressType = ADDR_INET6; - listRouteCommand->address.ipv6 = tmpAddr6.sin6_addr; - } - listRouteCommand->connid = numberSet_GetItem(nexthops, j); - listRouteCommand->len = nameBitvector_GetLength(prefix); - listRouteCommand->cost = 1; // cost - - pointerLocation++; - 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_routes_command) * 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_SendCommandResponse(conn, msg); - // IoOperations *ops = connection_GetIoOperations(conn); - // streamState_SendCommandResponse(ops, msg); -} - -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; - bool exists = true; - - const char *symbolicName = control->symbolic; - - Address *source = NULL; - Address *destination = NULL; - - if (!symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) { - if (control->ipType == ADDR_INET) { - source = - addressFromInaddr4Port(&control->localIp.ipv4, &control->localPort); - destination = - addressFromInaddr4Port(&control->remoteIp.ipv4, &control->remotePort); - } else if (control->ipType == ADDR_INET6) { - source = - addressFromInaddr6Port(&control->localIp.ipv6, &control->localPort); - destination = - addressFromInaddr6Port(&control->remoteIp.ipv6, &control->remotePort); - } else { - printf("Invalid IP type.\n"); // will generate a Nack - } - - AddressPair *pair = addressPair_Create(source, destination); - const Connection *conn = connectionTable_FindByAddressPair( - forwarder_GetConnectionTable(config->forwarder), pair); - - addressPair_Release(&pair); - - if (conn == NULL) { - // the connection does not exists (even without a name) - exists = false; - } - } - - if (!exists) { - 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); - - connectionTable_Add(forwarder_GetConnectionTable(config->forwarder), - conn); - symbolicNameTable_Add(config->symbolicNameTable, symbolicName, - connection_GetConnectionId(conn)); - - success = true; - - } else { - printf("failed, could not create IoOperations"); - } - - } else { - printf("failed, symbolic name or connextion already exist\n"); - } - - addressDestroy(&source); - addressDestroy(&destination); - - // generate ACK/NACK - struct iovec *response; - - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(add_connection_command)); - } else { // NACK - response = - utils_CreateNack(header, control, sizeof(add_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); - 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); - - 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); - 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; -} - -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); - listConnectionsCommand->state = - connection_IsUp(original) ? IFACE_UP : IFACE_DOWN; - listConnectionsCommand->connectionData.connectionType = - ioOperations_GetConnectionType(connection_GetIoOperations(original)); - - 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.ipv4 = - tmpAddr.sin_addr.s_addr; - memset(&tmpAddr, 0, sizeof(tmpAddr)); - // get remote port/address - addressGetInet(remoteAddress, &tmpAddr); - listConnectionsCommand->connectionData.remotePort = tmpAddr.sin_port; - listConnectionsCommand->connectionData.remoteIp.ipv4 = - tmpAddr.sin_addr.s_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.ipv6 = tmpAddr6.sin6_addr; - memset(&tmpAddr6, 0, sizeof(tmpAddr6)); - // get remote port/address - addressGetInet6(remoteAddress, &tmpAddr6); - listConnectionsCommand->connectionData.remotePort = tmpAddr6.sin6_port; - listConnectionsCommand->connectionData.remoteIp.ipv6 = 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.ipv4 = tmpAddr.sin_addr.s_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.ipv6 = tmpAddr6.sin6_addr; - listListenersCommand->port = tmpAddr6.sin6_port; - } - } - - // send response - header_control_message *header = request[0].iov_base; - header->messageType = RESPONSE_LIGHT; - header->length = (uint16_t)listenerSet_Length(listenerList); - - struct iovec *response = - parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); - - response[0].iov_base = header; - response[0].iov_len = sizeof(header_control_message); - response[1].iov_base = payloadResponse; - response[1].iov_len = - sizeof(list_listeners_command) * listenerSet_Length(listenerList); - - return response; -} - -struct iovec *configuration_ProcessCacheStore(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - ; - cache_store_command *control = request[1].iov_base; - ; - - bool success = false; - - switch (control->activate) { - case ACTIVATE_ON: - forwarder_SetChacheStoreFlag(config->forwarder, true); - if (forwarder_GetChacheStoreFlag(config->forwarder)) { - success = true; - } - break; - - case ACTIVATE_OFF: - forwarder_SetChacheStoreFlag(config->forwarder, false); - if (!forwarder_GetChacheStoreFlag(config->forwarder)) { - success = true; - } - break; - - default: - break; - } - - struct iovec *response; - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(cache_store_command)); - } else { // NACK - response = utils_CreateNack(header, control, sizeof(cache_store_command)); - } - - return response; -} - -struct iovec *configuration_ProcessCacheServe(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - cache_serve_command *control = request[1].iov_base; - - bool success = false; - - switch (control->activate) { - case ACTIVATE_ON: - forwarder_SetChacheServeFlag(config->forwarder, true); - if (forwarder_GetChacheServeFlag(config->forwarder)) { - success = true; - } - break; - - case ACTIVATE_OFF: - forwarder_SetChacheServeFlag(config->forwarder, false); - if (!forwarder_GetChacheServeFlag(config->forwarder)) { - success = true; - } - break; - - default: - break; - } - - struct iovec *response; - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(cache_store_command)); - } else { // NACK - response = utils_CreateNack(header, control, sizeof(cache_store_command)); - } - - return response; -} - -struct iovec *configuration_ProcessCacheClear(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - - forwarder_ClearCache(config->forwarder); - - struct iovec *response = utils_CreateAck(header, NULL, 0); - return response; -} - -size_t configuration_GetObjectStoreSize(Configuration *config) { - return config->maximumContentObjectStoreSize; -} - -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); -} - -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; -} - -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; - } -} - -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); - forwarder_SetStrategy(config->forwarder, hicnPrefix, strategy); - name_Release(&hicnPrefix); - } - - struct iovec *response = - utils_CreateAck(header, control, sizeof(set_strategy_command)); - - return response; -} - -void configuration_SetObjectStoreSize(Configuration *config, - size_t maximumObjectCount) { - config->maximumContentObjectStoreSize = maximumObjectCount; - - forwarder_SetContentObjectStoreSize(config->forwarder, - config->maximumContentObjectStoreSize); -} - -Forwarder *configuration_GetForwarder(const Configuration *config) { - return config->forwarder; -} - -Logger *configuration_GetLogger(const Configuration *config) { - return config->logger; -} - -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); - - struct iovec *response = - utils_CreateAck(header, control, sizeof(mapme_activator_command)); - - return response; -} - -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); - - struct iovec *response = - utils_CreateAck(header, control, sizeof(mapme_activator_command)); - - return response; -} - -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); - - struct iovec *response = - utils_CreateAck(header, control, sizeof(mapme_timing_command)); - - return response; -} - -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); - - struct iovec *response = - utils_CreateAck(header, control, sizeof(mapme_timing_command)); - - return response; -} - -// =========================== -// 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_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; - - default: - break; - } - - return response; -} - -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); - - switch (command) { - case LIST_CONNECTIONS: - case LIST_ROUTES: // case LIST_INTERFACES: case ETC...: - parcMemory_Deallocate( - &response[1] - .iov_base); // deallocate payload only if generated at fwd side - break; - default: - break; - } - - // deallocate received request. It coincides with response[0].iov_base memory - // parcMemory_Deallocate(&request); //deallocate header and payload (if - // same sent by controller) - parcMemory_Deallocate(&response); // deallocate iovec pointer -} diff --git a/hicn-light/src/config/configuration.h b/hicn-light/src/config/configuration.h deleted file mode 100644 index 4dfcb0d16..000000000 --- a/hicn-light/src/config/configuration.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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.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 configuration_h -#define configuration_h - -#include -#include - -struct configuration; -typedef struct configuration Configuration; - -struct forwarder; -typedef struct forwarder Forwarder; - -/** - * <#One Line Description#> - * - * <#Paragraphs Of Explanation#> - * - * @param [<#in out in,out#>] <#name#> <#description#> - * - * @retval <#value#> <#explanation#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -Configuration *configuration_Create(Forwarder *forwarder); - -/** - * <#One Line Description#> - * - * <#Paragraphs Of Explanation#> - * - * @param [<#in out in,out#>] <#name#> <#description#> - * - * @retval <#value#> <#explanation#> - * - * Example: - * @code - * <#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); - -/** - * Returns the configured size of the content store - * - * <#Paragraphs Of Explanation#> - * - * @param [<#in out in,out#>] <#name#> <#description#> - * - * @retval <#value#> <#explanation#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -size_t configuration_GetObjectStoreSize(Configuration *config); - -/** - * Sets the size of the content store (in objects, not bytes) - * - * Must be set before starting the forwarder - * - * @param [<#in out in,out#>] <#name#> <#description#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -void configuration_SetObjectStoreSize(Configuration *config, - size_t maximumContentObjectCount); - -strategy_type configuration_GetForwardingStrategy(Configuration *config, - const char *prefix); - -/** - * 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); - -/** - * 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); - -struct iovec *configuration_DispatchCommand(Configuration *config, - command_id command, - struct iovec *control, - unsigned ingressId); - -#endif // configuration_h diff --git a/hicn-light/src/config/configurationFile.c b/hicn-light/src/config/configurationFile.c deleted file mode 100644 index 3facf5afe..000000000 --- a/hicn-light/src/config/configurationFile.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#endif -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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); - - // 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); - CommandReturn result = - controlState_DispatchCommand(configFile->controlState, args); - - // 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; - } - parcList_Release(&args); - parcMemory_Deallocate((void **)©); - } - } - } - - 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/config/configurationFile.h b/hicn-light/src/config/configurationFile.h deleted file mode 100644 index 54548191d..000000000 --- a/hicn-light/src/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 - -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/config/configurationListeners.c b/hicn-light/src/config/configurationListeners.c deleted file mode 100644 index 8a3ecddfc..000000000 --- a/hicn-light/src/config/configurationListeners.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#endif -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -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] addr4 The ipv4 address in network byte order - * @param [in] port The port number in network byte order - * - * return true if success, false otherwise - */ -static bool _setupTcpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4, - uint16_t *port) { - 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, addr); - if (ops) { - success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); - parcAssertTrue(success, "Failed to add TCP listener on %s to ListenerSet", - addressToString(ops->getListenAddress(ops))); - } - return success; -} - -/* - * Create a new IPV4/UDP listener. - * - * @param [in,out] forwarder The hicn-light forwarder instance - * @param [in] addr4 The ipv4 address in network byte order - * @param [in] port The port number in network byte order - * - * return true if success, false otherwise - */ -static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4, - uint16_t *port) { - 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, addr); - if (ops) { - success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); - parcAssertTrue(success, "Failed to add UDP listener on %s to ListenerSet", - addressToString(ops->getListenAddress(ops))); - } - 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 - * - * return true if success, false otherwise - */ -static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, - ipv6_addr_t *addr6, uint16_t *port, - 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, addr); - if (ops) { - success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); - parcAssertTrue(success, "Failed to add TCP6 listener on %s to ListenerSet", - addressToString(ops->getListenAddress(ops))); - } - return success; -} - -/* - * Create a new IPV6/UDP 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 - * - * return true if success, false otherwise - */ -static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder, - ipv6_addr_t *addr6, uint16_t *port) { - 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, addr); - if (ops) { - success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); - parcAssertTrue(success, "Failed to add UDP6 listener on %s to ListenerSet", - addressToString(ops->getListenAddress(ops))); - } - 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.ipv4, &control->port); - success = _setupHicnListenerOnInet4(configuration_GetForwarder(config), - symbolic, localAddress); - break; - } - - case ADDR_INET6: { - localAddress = - addressFromInaddr6Port(&control->address.ipv6, &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)) { - logger_Log(configuration_GetLogger(config), LoggerFacility_Config, - PARCLogLevel_Info, __func__, - "Setup hicn listener on address %s", - addressToString(localAddress)); - } - } - - addressDestroy(&localAddress); - - return success; -} - -bool _addIP(Configuration *config, add_listener_command *control, - unsigned ingressId) { - bool success = false; - - switch (control->addressType) { - case ADDR_INET: { - if (control->connectionType == UDP_CONN) { - success = - _setupUdpListenerOnInet(configuration_GetForwarder(config), - &control->address.ipv4, &control->port); - } else if (control->connectionType == TCP_CONN) { - success = - _setupTcpListenerOnInet(configuration_GetForwarder(config), - &control->address.ipv4, &control->port); - } - break; - } - - case ADDR_INET6: { - if (control->connectionType == UDP_CONN) { - success = _setupUdpListenerOnInet6Light( - configuration_GetForwarder(config), &control->address.ipv6, - &control->port); - } else if (control->connectionType == TCP_CONN) { - success = _setupTcpListenerOnInet6Light( - configuration_GetForwarder(config), &control->address.ipv6, - &control->port, 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; - - 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.ipv4, &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.ipv6, &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, - const Address *address, uint16_t port, - const char *interfaceName) { - address_type type = addressGetType(address); - switch (type) { - case ADDR_INET: { - struct sockaddr_in tmp; - addressGetInet(address, &tmp); - _setupTcpListenerOnInet(forwarder, &tmp.sin_addr.s_addr, &port); - break; - } - - case ADDR_INET6: { - struct sockaddr_in6 tmp; - addressGetInet6(address, &tmp); - _setupTcpListenerOnInet6Light(forwarder, &tmp.sin6_addr, &port, - 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 - if (addressGetType(address) != ADDR_LINK) { - _setupListenersOnAddress(forwarder, address, port, - 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); - - _setupUdpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr), - &network_byte_order_port); - _setupTcpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr), - &network_byte_order_port); -} diff --git a/hicn-light/src/config/configurationListeners.h b/hicn-light/src/config/configurationListeners.h deleted file mode 100644 index 25d40e27e..000000000 --- a/hicn-light/src/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 -#include - -#include - -/** - * 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/config/controlAdd.c b/hicn-light/src/config/controlAdd.c deleted file mode 100644 index 7feee98ad..000000000 --- a/hicn-light/src/config/controlAdd.c +++ /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. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -// =================================================== - -static void _controlAdd_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlAdd_Execute(CommandParser *parser, CommandOps *ops, - PARCList *args); -static CommandReturn _controlAdd_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -// =================================================== - -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) { - 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); - - printf("Available commands:\n"); - printf(" %s\n", ops_add_connection->command); - printf(" %s\n", ops_add_route->command); - printf(" %s\n", ops_add_punting->command); - printf(" %s\n", ops_add_listener->command); - printf("\n"); - - commandOps_Destroy(&ops_add_connection); - commandOps_Destroy(&ops_add_route); - commandOps_Destroy(&ops_add_punting); - commandOps_Destroy(&ops_add_listener); - 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)); -} - -static CommandReturn _controlAdd_Execute(CommandParser *parser, CommandOps *ops, - PARCList *args) { - return _controlAdd_HelpExecute(parser, ops, args); -} diff --git a/hicn-light/src/config/controlAdd.h b/hicn-light/src/config/controlAdd.h deleted file mode 100644 index e1955f200..000000000 --- a/hicn-light/src/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 - -CommandOps *webControlAdd_Create(ControlState *state); -CommandOps *controlAdd_CreateHelp(ControlState *state); -#endif // control_Add_h diff --git a/hicn-light/src/config/controlAddConnection.c b/hicn-light/src/config/controlAddConnection.c deleted file mode 100644 index 7a95e5d91..000000000 --- a/hicn-light/src/config/controlAddConnection.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -// =================================================== - -static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlAddConnection_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlAddConnection_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -// =================================================== - -static CommandReturn _controlAddConnection_HicnHelpExecute( - CommandParser *parser, CommandOps *ops, PARCList *args); -static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -static CommandReturn _controlAddConnection_TcpHelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -// =================================================== - -static const char *_commandAddConnection = "add connection"; -static const char *_commandAddConnectionHicn = "add connection hicn"; -static const char *_commandAddConnectionUdp = "add connection udp"; -static const char *_commandAddConnectionTcp = "add connection tcp"; -static const char *_commandAddConnectionHelp = "help add connection"; -static const char *_commandAddConnectionHicnHelp = "help add connection hicn"; -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); -} - -// =================================================== - -static CommandOps *_controlAddConnection_HicnCreate(ControlState *state) { - return commandOps_Create(state, _commandAddConnectionHicn, NULL, - _controlAddConnection_HicnExecute, - commandOps_Destroy); -} - -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); -} - -// =================================================== - -static CommandOps *_controlAddConnection_HicnHelpCreate(ControlState *state) { - return commandOps_Create(state, _commandAddConnectionHicnHelp, NULL, - _controlAddConnection_HicnHelpExecute, - commandOps_Destroy); -} - -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) { - printf("Available commands:\n"); - printf(" %s\n", _commandAddConnectionHicn); - printf(" %s\n", _commandAddConnectionUdp); - printf(" %s\n", _commandAddConnectionTcp); - printf("\n"); - return CommandReturn_Success; -} - -static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops) { - ControlState *state = ops->closure; - controlState_RegisterCommand(state, - _controlAddConnection_HicnHelpCreate(state)); - controlState_RegisterCommand(state, - _controlAddConnection_UdpHelpCreate(state)); - controlState_RegisterCommand(state, - _controlAddConnection_TcpHelpCreate(state)); - - controlState_RegisterCommand(state, _controlAddConnection_HicnCreate(state)); - controlState_RegisterCommand(state, _controlAddConnection_UdpCreate(state)); - controlState_RegisterCommand(state, _controlAddConnection_TcpCreate(state)); -} - -static CommandReturn _controlAddConnection_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - return _controlAddConnection_HelpExecute(parser, ops, args); -} - -// =================================================== -// 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) - * - * @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) { - 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.ipv4) == - 1 && - inet_pton(AF_INET, local_ip, &addConnectionCommand->localIp.ipv4) == 1) { - addConnectionCommand->ipType = ADDR_INET; - - } else if (inet_pton(AF_INET6, remote_ip, - &addConnectionCommand->remoteIp.ipv6) == 1 && - inet_pton(AF_INET6, local_ip, - &addConnectionCommand->localIp.ipv6) == 1) { - addConnectionCommand->ipType = ADDR_INET6; - - } else { - printf("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) { - printf("add connection hicn \n"); - printf( - "add connection udp \n"); - printf( - " : symbolic name, e.g. 'conn1' (must be " - "unique, start with alpha)\n"); - printf( - " : the IPv4 or IPv6 or hostname of the remote system\n"); - printf(" : optional local IP address to bind to\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlAddConnection_HicnHelpExecute( - CommandParser *parser, CommandOps *ops, PARCList *args) { - _controlAddConnection_IpHelp(parser, ops, args, "hicn"); - - return CommandReturn_Success; -} - -static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - 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); - return CommandReturn_Failure; - } - - char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); - - if (!utils_ValidateSymbolicName(symbolic)) { - printf( - "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); -} - -static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - _controlAddConnection_IpHelp(parser, ops, args, "udp"); - - return CommandReturn_Success; -} - -static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - 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); - return CommandReturn_Failure; - } - - char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); - - if (!utils_ValidateSymbolicName(symbolic)) { - printf( - "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); -} - -static CommandReturn _controlAddConnection_TcpHelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - _controlAddConnection_IpHelp(parser, ops, args, "tcp"); - - return CommandReturn_Success; -} - -static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - 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); - return CommandReturn_Failure; - } - - char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); - - if (!utils_ValidateSymbolicName(symbolic)) { - printf( - "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); -} diff --git a/hicn-light/src/config/controlAddConnection.h b/hicn-light/src/config/controlAddConnection.h deleted file mode 100644 index 788306989..000000000 --- a/hicn-light/src/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 -CommandOps *controlAddConnection_Create(ControlState *state); -CommandOps *controlAddConnection_HelpCreate(ControlState *state); -#endif // controlAddConnection_h diff --git a/hicn-light/src/config/controlAddListener.c b/hicn-light/src/config/controlAddListener.c deleted file mode 100644 index 2cabfd035..000000000 --- a/hicn-light/src/config/controlAddListener.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. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#include -#include - -static CommandReturn _controlAddListener_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlAddListener_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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 CommandReturn _controlAddListener_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - printf("commands:\n"); - printf(" add listener hicn \n"); - printf(" add listener udp \n"); - printf(" add listener tcp \n"); - printf("\n"); - printf( - " symbolic: User defined name for listener, must start with " - "alpha and be alphanum\n"); - printf(" protocol: hicn | udp\n"); - printf( - " localAddress: IPv4 or IPv6 address (or prefix protocol = hicn) " - "assigend to the local interface\n"); - printf(" port: Udp port\n"); - printf("\n"); - printf("Notes:\n"); - printf(" The symblic name must be unique or the source will reject it.\n"); - printf( - " If protocol = hinc: the address 0::0 indicates the main listern, " - "for which we can set punting rules.\n"); - return CommandReturn_Success; -} - -static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops, - const char *symbolic, const char *addr, - const char *port, listener_mode mode, - connection_type type) { - 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.ipv4) == 1) { - addListenerCommand->addressType = ADDR_INET; - - } else if (inet_pton(AF_INET6, addr, &addListenerCommand->address.ipv6) == - 1) { - addListenerCommand->addressType = ADDR_INET6; - - } else { - printf("Error: %s is not a valid network address \n", addr); - parcMemory_Deallocate(&addListenerCommand); - return CommandReturn_Failure; - } - - // Fill remaining payload fields - 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) { - if (parcList_Size(args) != 5 && parcList_Size(args) != 6) { - _controlAddListener_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - CommandReturn result = CommandReturn_Failure; - - const char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); - - if (!utils_ValidateSymbolicName(symbolic)) { - printf( - "Error: symbolic name must begin with an alpha and be alphanum " - "after\n"); - return result; - } - - const char *host = parcList_GetAtIndex(args, _indexAddress); - const char *protocol = parcList_GetAtIndex(args, _indexProtocol); - - 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_MODE, - HICN_CONN); - } - - const char *port = parcList_GetAtIndex(args, _indexPort); - - if ((strcasecmp("udp", protocol) == 0)) { - return _CreateListener(parser, ops, symbolic, host, port, IP_MODE, - UDP_CONN); - } else if ((strcasecmp("tcp", protocol) == 0)) { - return _CreateListener(parser, ops, symbolic, host, port, IP_MODE, - TCP_CONN); - } else { - _controlAddListener_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - if (result == CommandReturn_Failure) printf("creation failed\n"); - - return result; -} diff --git a/hicn-light/src/config/controlAddListener.h b/hicn-light/src/config/controlAddListener.h deleted file mode 100644 index d3fc55aaf..000000000 --- a/hicn-light/src/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 -CommandOps *controlAddListener_Create(ControlState *state); -CommandOps *controlAddListener_HelpCreate(ControlState *state); -#endif // Control_AddListener_h diff --git a/hicn-light/src/config/controlAddPunting.c b/hicn-light/src/config/controlAddPunting.c deleted file mode 100644 index 13d00b7e0..000000000 --- a/hicn-light/src/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 - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include -#include - -static CommandReturn _controlAddPunting_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlAddPunting_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("add punting \n"); - printf(" : listener symbolic name\n"); - printf( - "
: prefix to add as a punting rule. (example " - "1234::0/64)\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlAddPunting_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - ControlState *state = ops->closure; - - if (parcList_Size(args) != 4) { - _controlAddPunting_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - const char *symbolicOrConnid = parcList_GetAtIndex(args, _indexSymbolic); - - if (!utils_ValidateSymbolicName(symbolicOrConnid) && - !utils_IsNumber(symbolicOrConnid)) { - printf( - "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'; - } - - if (len == 0) { - printf("ERROR: a prefix can not be of length 0\n"); - free(addr); - return CommandReturn_Failure; - } - - // 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.ipv4) == 1) { - if (len > 32) { - printf("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.ipv6) == 1) { - if (len > 128) { - printf("ERROR: exceeded INET6 mask length, max=128\n"); - parcMemory_Deallocate(&addPuntingCommand); - free(addr); - return CommandReturn_Failure; - } - addPuntingCommand->addressType = ADDR_INET6; - } else { - printf("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/config/controlAddPunting.h b/hicn-light/src/config/controlAddPunting.h deleted file mode 100644 index e4d4aac7e..000000000 --- a/hicn-light/src/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 -CommandOps *controlAddPunting_Create(ControlState *state); -CommandOps *controlAddPunting_HelpCreate(ControlState *state); -#endif diff --git a/hicn-light/src/config/controlAddRoute.c b/hicn-light/src/config/controlAddRoute.c deleted file mode 100644 index 27aae4019..000000000 --- a/hicn-light/src/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 - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#include -#include - -static CommandReturn _controlAddRoute_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlAddRoute_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("commands:\n"); - printf(" add route \n"); - printf("\n"); - printf(" symbolic: The symbolic name for an exgress\n"); - printf( - " connid: The egress connection id (see 'help list connections')\n"); - printf( - " prefix: The hicn name as IPv4 or IPv6 address (e.g 1234::0/64)\n"); - printf(" cost: positive integer representing cost\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlAddRoute_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - ControlState *state = ops->closure; - - if (parcList_Size(args) != 5) { - _controlAddRoute_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - const char *symbolicOrConnid = parcList_GetAtIndex(args, 2); - - if (!utils_ValidateSymbolicName(symbolicOrConnid) && - !utils_IsNumber(symbolicOrConnid)) { - printf( - "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) { - printf("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'; - } - - if (len == 0) { - printf("ERROR: a prefix can not be of length 0\n"); - free(addr); - return CommandReturn_Failure; - } - - // 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.ipv4) == 1) { - if (len > 32) { - printf("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.ipv6) == 1) { - if (len > 128) { - printf("ERROR: exceeded INET6 mask length, max=128\n"); - parcMemory_Deallocate(&addRouteCommand); - free(addr); - return CommandReturn_Failure; - } - addRouteCommand->addressType = ADDR_INET6; - } else { - printf("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/config/controlAddRoute.h b/hicn-light/src/config/controlAddRoute.h deleted file mode 100644 index be0ad1368..000000000 --- a/hicn-light/src/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 -CommandOps *controlAddRoute_Create(ControlState *state); -CommandOps *controlAddRoute_HelpCreate(ControlState *state); -#endif // Control_AddRoute_h diff --git a/hicn-light/src/config/controlCache.c b/hicn-light/src/config/controlCache.c deleted file mode 100644 index e8d19e828..000000000 --- a/hicn-light/src/config/controlCache.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 - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -static void _controlCache_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlCache_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlCache_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - CommandOps *ops_cache_serve = controlCacheServe_HelpCreate(NULL); - CommandOps *ops_cache_store = controlCacheStore_HelpCreate(NULL); - CommandOps *ops_cache_clear = controlCacheClear_HelpCreate(NULL); - - printf("Available commands:\n"); - printf(" %s\n", ops_cache_serve->command); - printf(" %s\n", ops_cache_store->command); - printf(" %s\n", ops_cache_clear->command); - printf("\n"); - - 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) { - return _controlCache_HelpExecute(parser, ops, args); -} - -// ====================================================================== diff --git a/hicn-light/src/config/controlCache.h b/hicn-light/src/config/controlCache.h deleted file mode 100644 index a3614fce1..000000000 --- a/hicn-light/src/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 -CommandOps *controlCache_Create(ControlState *state); -CommandOps *controlCache_HelpCreate(ControlState *state); -#endif // controlCache_h diff --git a/hicn-light/src/config/controlCacheClear.c b/hicn-light/src/config/controlCacheClear.c deleted file mode 100644 index 2679f368e..000000000 --- a/hicn-light/src/config/controlCacheClear.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 - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include - -static CommandReturn _controlCacheClear_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlCacheClear_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("cache clear\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlCacheClear_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 2) { - _controlCacheClear_HelpExecute(parser, ops, args); - 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/config/controlCacheClear.h b/hicn-light/src/config/controlCacheClear.h deleted file mode 100644 index 348ddba12..000000000 --- a/hicn-light/src/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 -CommandOps *controlCacheClear_Create(ControlState *state); -CommandOps *controlCacheClear_HelpCreate(ControlState *state); -#endif // Control_CacheClear_h diff --git a/hicn-light/src/config/controlCacheServe.c b/hicn-light/src/config/controlCacheServe.c deleted file mode 100644 index 9181810dd..000000000 --- a/hicn-light/src/config/controlCacheServe.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 - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include - -static CommandReturn _controlCacheServe_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlCacheServe_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("cache serve [on|off]\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlCacheServe_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 3) { - _controlCacheServe_HelpExecute(parser, ops, args); - 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); - 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/config/controlCacheServe.h b/hicn-light/src/config/controlCacheServe.h deleted file mode 100644 index 4bcec51f0..000000000 --- a/hicn-light/src/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 -CommandOps *controlCacheServe_Create(ControlState *state); -CommandOps *controlCacheServe_HelpCreate(ControlState *state); -#endif // Control_CacheServe_h diff --git a/hicn-light/src/config/controlCacheStore.c b/hicn-light/src/config/controlCacheStore.c deleted file mode 100644 index d586188fb..000000000 --- a/hicn-light/src/config/controlCacheStore.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 - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include - -static CommandReturn _controlCacheStore_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlCacheStore_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("cache store [on|off]\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlCacheStore_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 3) { - _controlCacheStore_HelpExecute(parser, ops, args); - 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); - 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/config/controlCacheStore.h b/hicn-light/src/config/controlCacheStore.h deleted file mode 100644 index ef5aca504..000000000 --- a/hicn-light/src/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 -CommandOps *controlCacheStore_Create(ControlState *state); -CommandOps *controlCacheStore_HelpCreate(ControlState *state); -#endif // Control_CacheStore_h diff --git a/hicn-light/src/config/controlList.c b/hicn-light/src/config/controlList.c deleted file mode 100644 index 7e4636b00..000000000 --- a/hicn-light/src/config/controlList.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -//#include -#include -#include - -static void _controlList_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlList_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlList_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - 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); - - printf("Available commands:\n"); - printf(" %s\n", ops_list_connections->command); - // printf(" %s\n", ops_list_interfaces->command); - printf(" %s\n", ops_list_routes->command); - printf(" %s\n", ops_list_listeners->command); - printf("\n"); - - commandOps_Destroy(&ops_list_connections); - // commandOps_Destroy(&ops_list_interfaces); - commandOps_Destroy(&ops_list_routes); - commandOps_Destroy(&ops_list_listeners); - - 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)); -} - -static CommandReturn _controlList_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - return _controlList_HelpExecute(parser, ops, args); -} - -// ====================================================================== diff --git a/hicn-light/src/config/controlList.h b/hicn-light/src/config/controlList.h deleted file mode 100644 index 53197331f..000000000 --- a/hicn-light/src/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 -CommandOps *controlList_Create(ControlState *state); -CommandOps *controlList_HelpCreate(ControlState *state); -#endif // controlList_h diff --git a/hicn-light/src/config/controlListConnections.c b/hicn-light/src/config/controlListConnections.c deleted file mode 100644 index b7dda0bbe..000000000 --- a/hicn-light/src/config/controlListConnections.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 - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include - -static CommandReturn _controlListConnections_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlListConnections_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("list connections: displays a 1-line summary of each connection\n"); - printf("\n"); - printf("The columns are:\n"); - printf(" connection id : an integer index for the connection\n"); - printf(" state : UP or DOWN\n"); - printf( - " local address : the local network address associated with the " - "connection\n"); - printf( - " remote address: the remote network address associated with the " - "connection\n"); - printf( - " protocol : the network protocol (tcp, udp, gre, mcast, " - "ether)\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlListConnections_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 2) { - _controlListConnections_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - 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) * 128); - } - } - - // 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(); - - parcBufferComposer_Format( - composer, "%5d %4s %s %s %s", listConnectionsCommand->connid, - stateString[listConnectionsCommand->state], sourceString, - destinationString, - connTypeString[listConnectionsCommand->connectionData.connectionType]); - - 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); - } - - 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/config/controlListConnections.h b/hicn-light/src/config/controlListConnections.h deleted file mode 100644 index 17422c963..000000000 --- a/hicn-light/src/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 -CommandOps *controlListConnections_Create(ControlState *state); -CommandOps *controlListConnections_HelpCreate(ControlState *state); -#endif // Control_ListConnections_h diff --git a/hicn-light/src/config/controlListInterfaces.c b/hicn-light/src/config/controlListInterfaces.c deleted file mode 100644 index 914cc3552..000000000 --- a/hicn-light/src/config/controlListInterfaces.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#include - -static CommandReturn _controlListInterfaces_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlListInterfaces_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("list interfaces\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlListInterfaces_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 2) { - _controlListInterfaces_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - //========================== NOT IMPLEMENTED - //=========================== - - return CommandReturn_Success; -} diff --git a/hicn-light/src/config/controlListInterfaces.h b/hicn-light/src/config/controlListInterfaces.h deleted file mode 100644 index 0c0ca95cf..000000000 --- a/hicn-light/src/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 -CommandOps *controlListInterfaces_Create(ControlState *state); -CommandOps *controlListInterfaces_HelpCreate(ControlState *state); -#endif // Control_ListInterfaces_h diff --git a/hicn-light/src/config/controlListListeners.c b/hicn-light/src/config/controlListListeners.c deleted file mode 100644 index e84912205..000000000 --- a/hicn-light/src/config/controlListListeners.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -static CommandReturn _controlListListeners_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlListListeners_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("list listeners\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlListListeners_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 2) { - _controlListListeners_HelpExecute(parser, ops, args); - 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; - if (receivedHeader->length > 0) { - printf("%6.6s %50.70s %s\n", "iface", "address", "type"); - } else { - printf(" --- 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(); - - parcBufferComposer_Format(composer, "%6u %50.70s %3s", - listListenersCommand->connid, addrString, - listenerType[listListenersCommand->encapType]); - - 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); - } - - 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/config/controlListListeners.h b/hicn-light/src/config/controlListListeners.h deleted file mode 100644 index 1f34eea56..000000000 --- a/hicn-light/src/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 -CommandOps *controlListListeners_Create(ControlState *state); -CommandOps *controlListListeners_HelpCreate(ControlState *state); -#endif // Control_ListListeners_h diff --git a/hicn-light/src/config/controlListRoutes.c b/hicn-light/src/config/controlListRoutes.c deleted file mode 100644 index ba116ce76..000000000 --- a/hicn-light/src/config/controlListRoutes.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#include -#include - -static CommandReturn _controlListRoutes_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlListRoutes_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("command: list routes\n"); - printf("\n"); - printf( - "This command will fetch the prefix routing table. For each route, it " - "will list:\n"); - printf(" iface: interface\n"); - printf( - " protocol: the routing protocol, such as STATIC, CONNECTED, etc.\n"); - printf( - " type: LMP or EXACT (longest matching prefix or exact match)\n"); - printf(" cost: The route cost, lower being preferred\n"); - printf(" next: List of next hops by interface id\n"); - printf(" prefix: name prefix\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlListRoutes_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 2) { - _controlListRoutes_HelpExecute(parser, ops, args); - 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 - - if (receivedHeader->length > 0) { - printf("%6.6s %8.8s %70.70s %s\n", "iface", "cost", "prefix", "len"); - } else { - printf(" --- 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); - } - - puts(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/config/controlListRoutes.h b/hicn-light/src/config/controlListRoutes.h deleted file mode 100644 index 018c88ab0..000000000 --- a/hicn-light/src/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 -CommandOps *controlListRoutes_Create(ControlState *state); -CommandOps *controlListRoutes_HelpCreate(ControlState *state); -#endif // Control_ListRoutes_h diff --git a/hicn-light/src/config/controlMapMe.c b/hicn-light/src/config/controlMapMe.c deleted file mode 100644 index a839a9173..000000000 --- a/hicn-light/src/config/controlMapMe.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -static void _controlMapMe_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlMapMe_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlMapMe_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - 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); - - printf("Available commands:\n"); - printf(" %s\n", ops_mapme_enable->command); - printf(" %s\n", ops_mapme_discovery->command); - printf(" %s\n", ops_mapme_timescale->command); - printf(" %s\n", ops_mapme_retx->command); - printf("\n"); - - 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) { - return _controlMapMe_HelpExecute(parser, ops, args); -} - -// ====================================================================== diff --git a/hicn-light/src/config/controlMapMe.h b/hicn-light/src/config/controlMapMe.h deleted file mode 100644 index d9cfdb82c..000000000 --- a/hicn-light/src/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 -CommandOps *controlMapMe_Create(ControlState *state); -CommandOps *controlMapMe_HelpCreate(ControlState *state); -#endif // controlMapMe_h diff --git a/hicn-light/src/config/controlMapMeDiscovery.c b/hicn-light/src/config/controlMapMeDiscovery.c deleted file mode 100644 index fd10cf18e..000000000 --- a/hicn-light/src/config/controlMapMeDiscovery.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 - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -static CommandReturn _controlMapMeDiscovery_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlMapMeDiscovery_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("mapme discovery [on|off]\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlMapMeDiscovery_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 3) { - _controlMapMeDiscovery_HelpExecute(parser, ops, args); - 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); - 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/config/controlMapMeDiscovery.h b/hicn-light/src/config/controlMapMeDiscovery.h deleted file mode 100644 index c492fa0ab..000000000 --- a/hicn-light/src/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 -CommandOps *controlMapMeDiscovery_Create(ControlState *state); -CommandOps *controlMapMeDiscovery_HelpCreate(ControlState *state); -#endif // Control_MapMeDiscovery_h diff --git a/hicn-light/src/config/controlMapMeEnable.c b/hicn-light/src/config/controlMapMeEnable.c deleted file mode 100644 index 587aa6eb6..000000000 --- a/hicn-light/src/config/controlMapMeEnable.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 - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -static CommandReturn _controlMapMeEnable_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlMapMeEnable_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("mapme enable [on|off]\n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlMapMeEnable_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 3) { - _controlMapMeEnable_HelpExecute(parser, ops, args); - 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); - 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/config/controlMapMeEnable.h b/hicn-light/src/config/controlMapMeEnable.h deleted file mode 100644 index f7ca6204d..000000000 --- a/hicn-light/src/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 -CommandOps *controlMapMeEnable_Create(ControlState *state); -CommandOps *controlMapMeEnable_HelpCreate(ControlState *state); -#endif // Control_MapMeEnable_h diff --git a/hicn-light/src/config/controlMapMeRetx.c b/hicn-light/src/config/controlMapMeRetx.c deleted file mode 100644 index 21541d837..000000000 --- a/hicn-light/src/config/controlMapMeRetx.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -static CommandReturn _controlMapMeRetx_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlMapMeRetx_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("mapme retx n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlMapMeRetx_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 3) { - _controlMapMeRetx_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - const char *rtx = parcList_GetAtIndex(args, 2); - if (!utils_IsNumber(rtx)) { - printf( - "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/config/controlMapMeRetx.h b/hicn-light/src/config/controlMapMeRetx.h deleted file mode 100644 index 611bd3663..000000000 --- a/hicn-light/src/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 -CommandOps *controlMapMeRetx_Create(ControlState *state); -CommandOps *controlMapMeRetx_HelpCreate(ControlState *state); -#endif // Control_MapMeRetx_h diff --git a/hicn-light/src/config/controlMapMeTimescale.c b/hicn-light/src/config/controlMapMeTimescale.c deleted file mode 100644 index 872a50abc..000000000 --- a/hicn-light/src/config/controlMapMeTimescale.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -static CommandReturn _controlMapMeTimescale_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlMapMeTimescale_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("mapme timescale n"); - printf("\n"); - - return CommandReturn_Success; -} - -static CommandReturn _controlMapMeTimescale_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 3) { - _controlMapMeTimescale_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - const char *ts = parcList_GetAtIndex(args, 2); - if (!utils_IsNumber(ts)) { - printf( - "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/config/controlMapMeTimescale.h b/hicn-light/src/config/controlMapMeTimescale.h deleted file mode 100644 index d4b383696..000000000 --- a/hicn-light/src/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 -CommandOps *controlMapMeTimescale_Create(ControlState *state); -CommandOps *controlMapMeTimescale_HelpCreate(ControlState *state); -#endif // Control_MapMeTimescale_h diff --git a/hicn-light/src/config/controlQuit.c b/hicn-light/src/config/controlQuit.c deleted file mode 100644 index 6df163c49..000000000 --- a/hicn-light/src/config/controlQuit.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 - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -static CommandReturn _controlQuit_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlQuit_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - printf("Exits the interactive control program\n\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlQuit_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - printf("exiting interactive shell\n"); - return CommandReturn_Exit; -} diff --git a/hicn-light/src/config/controlQuit.h b/hicn-light/src/config/controlQuit.h deleted file mode 100644 index e2ba3540e..000000000 --- a/hicn-light/src/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 -CommandOps *controlQuit_Create(ControlState *state); -CommandOps *controlQuit_HelpCreate(ControlState *state); -#endif // Control_Quit_h diff --git a/hicn-light/src/config/controlRemove.c b/hicn-light/src/config/controlRemove.c deleted file mode 100644 index da4b69fd9..000000000 --- a/hicn-light/src/config/controlRemove.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -static void _controlRemove_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlRemove_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlRemove_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - CommandOps *ops_remove_connection = controlRemoveConnection_Create(NULL); - CommandOps *ops_remove_route = controlRemoveRoute_Create(NULL); - CommandOps *ops_remove_punting = controlRemovePunting_Create(NULL); - - printf("Available commands:\n"); - printf(" %s\n", ops_remove_connection->command); - printf(" %s\n", ops_remove_route->command); - printf(" %s\n", ops_remove_punting->command); - printf("\n"); - - commandOps_Destroy(&ops_remove_connection); - commandOps_Destroy(&ops_remove_route); - commandOps_Destroy(&ops_remove_punting); - return CommandReturn_Success; -} - -static void _controlRemove_Init(CommandParser *parser, CommandOps *ops) { - ControlState *state = ops->closure; - controlState_RegisterCommand(state, - controlRemoveConnection_HelpCreate(state)); - controlState_RegisterCommand(state, controlRemoveRoute_HelpCreate(state)); - controlState_RegisterCommand(state, controlRemoveConnection_Create(state)); - controlState_RegisterCommand(state, controlRemoveRoute_Create(state)); - controlState_RegisterCommand(state, controlRemovePunting_Create(state)); - controlState_RegisterCommand(state, controlRemovePunting_HelpCreate(state)); -} - -static CommandReturn _controlRemove_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - return _controlRemove_HelpExecute(parser, ops, args); -} diff --git a/hicn-light/src/config/controlRemove.h b/hicn-light/src/config/controlRemove.h deleted file mode 100644 index d75ecfe70..000000000 --- a/hicn-light/src/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 -CommandOps *controlRemove_Create(ControlState *state); -CommandOps *controlRemove_HelpCreate(ControlState *state); -#endif // controlRemove_h diff --git a/hicn-light/src/config/controlRemoveConnection.c b/hicn-light/src/config/controlRemoveConnection.c deleted file mode 100644 index c701fc77f..000000000 --- a/hicn-light/src/config/controlRemoveConnection.c +++ /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. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include -#include - -static CommandReturn _controlRemoveConnection_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlRemoveConnection_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -// =================================================== - -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) { - printf("command:\n"); - printf(" remove connection \n"); - return CommandReturn_Success; -} - -static CommandReturn _controlRemoveConnection_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - ControlState *state = ops->closure; - - if (parcList_Size(args) != 3) { - _controlRemoveConnection_HelpExecute(parser, ops, args); - return false; - } - - if ((strcmp(parcList_GetAtIndex(args, 0), "remove") != 0) || - (strcmp(parcList_GetAtIndex(args, 1), "connection") != 0)) { - _controlRemoveConnection_HelpExecute(parser, ops, args); - return false; - } - - const char *symbolicOrConnid = parcList_GetAtIndex(args, 2); - - if (!utils_ValidateSymbolicName(symbolicOrConnid) && - !utils_IsNumber(symbolicOrConnid)) { - printf( - "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/config/controlRemoveConnection.h b/hicn-light/src/config/controlRemoveConnection.h deleted file mode 100644 index 1dd1af23b..000000000 --- a/hicn-light/src/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 -CommandOps *controlRemoveConnection_Create(ControlState *state); -CommandOps *controlRemoveConnection_HelpCreate(ControlState *state); -#endif // Control_RemoveConnection_h diff --git a/hicn-light/src/config/controlRemovePunting.c b/hicn-light/src/config/controlRemovePunting.c deleted file mode 100644 index 0ae80ec9b..000000000 --- a/hicn-light/src/config/controlRemovePunting.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -static CommandReturn _controlRemovePunting_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlRemovePunting_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -// =================================================== - -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) { - printf("remove punting \n"); - return CommandReturn_Success; -} - -static CommandReturn _controlRemovePunting_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - printf("command not implemented\n"); - return _controlRemovePunting_HelpExecute(parser, ops, args); -} - -// ================================================== diff --git a/hicn-light/src/config/controlRemovePunting.h b/hicn-light/src/config/controlRemovePunting.h deleted file mode 100644 index 89b1343e7..000000000 --- a/hicn-light/src/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 -CommandOps *controlRemovePunting_Create(ControlState *state); -CommandOps *controlRemovePunting_HelpCreate(ControlState *state); -#endif // Control_RemovePunting_h diff --git a/hicn-light/src/config/controlRemoveRoute.c b/hicn-light/src/config/controlRemoveRoute.c deleted file mode 100644 index c4efb04df..000000000 --- a/hicn-light/src/config/controlRemoveRoute.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlRemoveRoute_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -// =================================================== - -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) { - printf("commands:\n"); - printf(" remove route \n"); - return CommandReturn_Success; -} - -static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - ControlState *state = ops->closure; - - if (parcList_Size(args) != 4) { - _controlRemoveRoute_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - const char *symbolicOrConnid = parcList_GetAtIndex(args, 2); - - if (!utils_ValidateSymbolicName(symbolicOrConnid) && - !utils_IsNumber(symbolicOrConnid)) { - printf( - "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'; - } - - if (len == 0) { - printf("ERROR: a prefix can not be of length 0\n"); - free(addr); - return CommandReturn_Failure; - } - - // 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.ipv4) == 1) { - if (len > 32) { - printf("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.ipv6) == - 1) { - if (len > 128) { - printf("ERROR: exceeded INET6 mask length, max=128\n"); - parcMemory_Deallocate(&removeRouteCommand); - free(addr); - return CommandReturn_Failure; - } - removeRouteCommand->addressType = ADDR_INET6; - } else { - printf("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/config/controlRemoveRoute.h b/hicn-light/src/config/controlRemoveRoute.h deleted file mode 100644 index a3c0ee46a..000000000 --- a/hicn-light/src/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 -CommandOps *controlRemoveRoute_Create(ControlState *state); -CommandOps *controlRemoveRoute_HelpCreate(ControlState *state); -#endif // Control_RemoveRoute_h diff --git a/hicn-light/src/config/controlRoot.c b/hicn-light/src/config/controlRoot.c deleted file mode 100644 index 49b613208..000000000 --- a/hicn-light/src/config/controlRoot.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 - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void _controlRoot_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlRoot_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlRoot_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - printf("Command-line execution:\n"); - printf( - " controller [--keystore ] [--password ] " - "command\n"); - printf("\n"); - printf("Interactive execution:\n"); - printf(" controller [--keystore ] [--password ]\n"); - printf("\n"); - printf( - "If the keystore is not specified, the default path is used. Keystore " - "must exist prior to running program.\n"); - printf("If the password is not specified, the user will be prompted.\n"); - printf("\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); - - printf("Available commands:\n"); - printf(" %s\n", ops_help_add->command); - printf(" %s\n", ops_help_list->command); - printf(" %s\n", ops_help_quit->command); - printf(" %s\n", ops_help_remove->command); - printf(" %s\n", ops_help_set->command); - printf(" %s\n", ops_help_unset->command); - printf(" %s\n", ops_help_cache->command); - printf(" %s\n", ops_help_mapme->command); - printf("\n"); - - 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); - - 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)); - - 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)); -} - -static CommandReturn _controlRoot_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - return CommandReturn_Success; -} - -// ====================================================================== diff --git a/hicn-light/src/config/controlRoot.h b/hicn-light/src/config/controlRoot.h deleted file mode 100644 index a62126eba..000000000 --- a/hicn-light/src/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 -CommandOps *controlRoot_Create(ControlState *state); -CommandOps *controlRoot_HelpCreate(ControlState *state); -#endif // Control_Root_h diff --git a/hicn-light/src/config/controlSet.c b/hicn-light/src/config/controlSet.c deleted file mode 100644 index 07ca7e6b0..000000000 --- a/hicn-light/src/config/controlSet.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -static void _controlSet_Init(CommandParser *parser, CommandOps *ops); -static CommandReturn _controlSet_Execute(CommandParser *parser, CommandOps *ops, - PARCList *args); -static CommandReturn _controlSet_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - CommandOps *ops_help_set_debug = controlSetDebug_HelpCreate(NULL); - CommandOps *ops_help_set_strategy = controlSetStrategy_HelpCreate(NULL); - CommandOps *ops_help_set_wldr = controlSetWldr_HelpCreate(NULL); - - printf("Available commands:\n"); - printf(" %s\n", ops_help_set_debug->command); - printf(" %s\n", ops_help_set_strategy->command); - printf(" %s\n", ops_help_set_wldr->command); - printf("\n"); - - 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) { - return _controlSet_HelpExecute(parser, ops, args); -} diff --git a/hicn-light/src/config/controlSet.h b/hicn-light/src/config/controlSet.h deleted file mode 100644 index 4289aad8c..000000000 --- a/hicn-light/src/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 -CommandOps *controlSet_Create(ControlState *state); -CommandOps *controlSet_HelpCreate(ControlState *state); -#endif // Control_Set_h diff --git a/hicn-light/src/config/controlSetDebug.c b/hicn-light/src/config/controlSetDebug.c deleted file mode 100644 index 1739e777a..000000000 --- a/hicn-light/src/config/controlSetDebug.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -static CommandReturn _controlSetDebug_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlSetDebug_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("set debug: will enable the debug flag for more verbose output\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlSetDebug_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - if (parcList_Size(args) != 2) { - _controlSetDebug_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - ControlState *state = ops->closure; - controlState_SetDebug(state, true); - printf("Debug flag set\n\n"); - return CommandReturn_Success; -} diff --git a/hicn-light/src/config/controlSetDebug.h b/hicn-light/src/config/controlSetDebug.h deleted file mode 100644 index 5335ebcab..000000000 --- a/hicn-light/src/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 -CommandOps *controlSetDebug_Create(ControlState *state); -CommandOps *controlSetDebug_HelpCreate(ControlState *state); -#endif // Control_SetDebug_h diff --git a/hicn-light/src/config/controlSetStrategy.c b/hicn-light/src/config/controlSetStrategy.c deleted file mode 100644 index 579862eeb..000000000 --- a/hicn-light/src/config/controlSetStrategy.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include -#include - -static CommandReturn _controlSetStrategy_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -static const char *_commandSetStrategy = "set strategy"; -static const char *_commandSetStrategyHelp = "help set strategy"; - -static const char *_commandSetStrategyOptions[LAST_STRATEGY_VALUE] = { - "loadbalancer", - "random", - "random_per_dash_segment", - "loadbalancer_with_delay", - "loadbalancer_by_rate", - "loadbalancer_best_route"}; - -// ==================================================== - -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 CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - printf("set strategy \n"); - printf("prefix: ipv4/ipv6 address (ex: 1234::/64)\n"); - printf("strategy: strategy identifier\n"); - printf("available strategies:\n"); - printf(" random\n"); - printf(" loadbalancer\n"); - printf(" random_per_dash_segment\n"); - printf(" loadbalancer_with_delay\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlSetStrategy_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - ControlState *state = ops->closure; - - if (parcList_Size(args) != 4) { - _controlSetStrategy_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - if (((strcmp(parcList_GetAtIndex(args, 0), "set") != 0) || - (strcmp(parcList_GetAtIndex(args, 1), "strategy") != 0))) { - _controlSetStrategy_HelpExecute(parser, ops, args); - 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 = UINT32_MAX; - strcpy(addr, prefixStr); - slash = strrchr(addr, '/'); - if (slash != NULL) { - len = atoi(slash + 1); - *slash = '\0'; - } - if (len == 0) { - printf("ERROR: a prefix can not be of length 0\n"); - free(addr); - return CommandReturn_Failure; - } - - // allocate command payload - set_strategy_command *setStrategyCommand = - parcMemory_AllocateAndClear(sizeof(set_strategy_command)); - - // check and set IP address - if (inet_pton(AF_INET, addr, &setStrategyCommand->address.ipv4) == 1) { - if (len == UINT32_MAX) { - printf("Netmask not specified: set to 32 by default\n"); - len = 32; - } else if (len > 32) { - printf("ERROR: exceeded INET mask length, max=32\n"); - parcMemory_Deallocate(&setStrategyCommand); - free(addr); - return CommandReturn_Failure; - } - setStrategyCommand->addressType = ADDR_INET; - } else if (inet_pton(AF_INET6, addr, &setStrategyCommand->address.ipv6) == - 1) { - if (len == UINT32_MAX) { - printf("Netmask not specified: set to 128 by default\n"); - len = 128; - } else if (len > 128) { - printf("ERROR: exceeded INET6 mask length, max=128\n"); - parcMemory_Deallocate(&setStrategyCommand); - free(addr); - return CommandReturn_Failure; - } - setStrategyCommand->addressType = ADDR_INET6; - } else { - printf("Error: %s is not a valid network address \n", addr); - parcMemory_Deallocate(&setStrategyCommand); - return CommandReturn_Failure; - } - - const char *strategyStr = parcList_GetAtIndex(args, 3); - // check valid strategy - strategy_type strategy; - if ((strategy = _validStrategy(strategyStr)) == LAST_STRATEGY_VALUE) { - printf("Error: invalid strategy \n"); - parcMemory_Deallocate(&setStrategyCommand); - _controlSetStrategy_HelpExecute(parser, ops, args); - free(addr); - return CommandReturn_Failure; - } - - free(addr); - - // Fill remaining payload fields - setStrategyCommand->len = len; - setStrategyCommand->strategyType = strategy; - - // 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/config/controlSetStrategy.h b/hicn-light/src/config/controlSetStrategy.h deleted file mode 100644 index 53ce8912c..000000000 --- a/hicn-light/src/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 -CommandOps *controlSetStrategy_Create(ControlState *state); -CommandOps *controlSetStrategy_HelpCreate(ControlState *state); -#endif // Control_SetStrategy_h diff --git a/hicn-light/src/config/controlSetWldr.c b/hicn-light/src/config/controlSetWldr.c deleted file mode 100644 index 7bb055af8..000000000 --- a/hicn-light/src/config/controlSetWldr.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include -#include - -static CommandReturn _controlSetWldr_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlSetWldr_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("set wldr \n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlSetWldr_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - ControlState *state = ops->closure; - - if (parcList_Size(args) != 4) { - _controlSetWldr_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - if (((strcmp(parcList_GetAtIndex(args, 0), "set") != 0) || - (strcmp(parcList_GetAtIndex(args, 1), "wldr") != 0))) { - _controlSetWldr_HelpExecute(parser, ops, args); - 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); - return CommandReturn_Failure; - } - - // check if valid connid - const char *symbolicOrConnid = parcList_GetAtIndex(args, 3); - - if (!utils_ValidateSymbolicName(symbolicOrConnid) && - !utils_IsNumber(symbolicOrConnid)) { - printf( - "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/config/controlSetWldr.h b/hicn-light/src/config/controlSetWldr.h deleted file mode 100644 index 59c0b0fe6..000000000 --- a/hicn-light/src/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 -CommandOps *controlSetWldr_Create(ControlState *state); -CommandOps *controlSetWldr_HelpCreate(ControlState *state); -#endif // Control_SetWldr_h diff --git a/hicn-light/src/config/controlState.c b/hicn-light/src/config/controlState.c deleted file mode 100644 index c3b7d535b..000000000 --- a/hicn-light/src/config/controlState.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define SRV_IP "127.0.0.1" -#define PORT 9695 - -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() { - int sockfd; - struct sockaddr_in servaddr; - - if ((sockfd = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) { - printf("\nSocket Creation Failed \n"); - exit(EXIT_FAILURE); - } - - memset(&servaddr, 0, sizeof(servaddr)); - - // Filling server information - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(PORT); - inet_pton(AF_INET, SRV_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"); - exit(EXIT_FAILURE); - } - - return sockfd; -} - -ControlState *controlState_Create( - void *userdata, - struct iovec *(*writeRead)(ControlState *state, struct iovec *msg), - bool openControllerConnetion) { - 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(); - } 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) { - parcAssertNotNull(state, "Parameter state must be non-null"); - return commandParser_DispatchCommand(state->parser, args); -} - -int controlState_Interactive(ControlState *state) { - parcAssertNotNull(state, "Parameter state must be non-null"); - char *line = NULL; - size_t linecap = 0; - CommandReturn controlReturn = CommandReturn_Success; - - 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); - // 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; - } -} \ No newline at end of file diff --git a/hicn-light/src/config/controlState.h b/hicn-light/src/config/controlState.h deleted file mode 100644 index 905c56c30..000000000 --- a/hicn-light/src/config/controlState.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 -#include - -#include - -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); - -/** - * 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 - * - * @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); - -/** - * 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/config/controlUnset.c b/hicn-light/src/config/controlUnset.c deleted file mode 100644 index 2742940fa..000000000 --- a/hicn-light/src/config/controlUnset.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. - */ - -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -static void _controlUnset_Init(CommandParser *parser, CommandOps *ops); - -static CommandReturn _controlUnset_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args); -static CommandReturn _controlUnset_HelpExecute(CommandParser *parser, - CommandOps *ops, PARCList *args); - -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) { - CommandOps *ops_help_unset_debug = controlUnsetDebug_HelpCreate(NULL); - - printf("Available commands:\n"); - printf(" %s\n", ops_help_unset_debug->command); - printf("\n"); - - commandOps_Destroy(&ops_help_unset_debug); - return CommandReturn_Success; -} - -static CommandReturn _controlUnset_Execute(CommandParser *parser, - CommandOps *ops, PARCList *args) { - return _controlUnset_HelpExecute(parser, ops, args); -} diff --git a/hicn-light/src/config/controlUnset.h b/hicn-light/src/config/controlUnset.h deleted file mode 100644 index 6eeb983f7..000000000 --- a/hicn-light/src/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 -CommandOps *controlUnset_Create(ControlState *state); -CommandOps *controlUnset_HelpCreate(ControlState *state); -#endif // Control_Unset_h diff --git a/hicn-light/src/config/controlUnsetDebug.c b/hicn-light/src/config/controlUnsetDebug.c deleted file mode 100644 index bf3f6fe68..000000000 --- a/hicn-light/src/config/controlUnsetDebug.c +++ /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. - */ - -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -static CommandReturn _controlUnsetDebug_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args); -static CommandReturn _controlUnsetDebug_HelpExecute(CommandParser *parser, - CommandOps *ops, - PARCList *args); - -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) { - printf("unset debug: will disable the debug flag\n"); - printf("\n"); - return CommandReturn_Success; -} - -static CommandReturn _controlUnsetDebug_Execute(CommandParser *parser, - CommandOps *ops, - PARCList *args) { - if (parcList_Size(args) != 2) { - _controlUnsetDebug_HelpExecute(parser, ops, args); - return CommandReturn_Failure; - } - - ControlState *state = ops->closure; - controlState_SetDebug(state, false); - printf("Debug flag cleared\n\n"); - - return CommandReturn_Success; -} diff --git a/hicn-light/src/config/controlUnsetDebug.h b/hicn-light/src/config/controlUnsetDebug.h deleted file mode 100644 index e34f8aa5f..000000000 --- a/hicn-light/src/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 -CommandOps *controlUnsetDebug_Create(ControlState *state); -CommandOps *controlUnsetDebug_HelpCreate(ControlState *state); -#endif // Control_UnsetDebug_h diff --git a/hicn-light/src/config/symbolicNameTable.c b/hicn-light/src/config/symbolicNameTable.c deleted file mode 100644 index ccf416d67..000000000 --- a/hicn-light/src/config/symbolicNameTable.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -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 *key = _createKey(symbolicName); - - uint32_t *value = parcMemory_Allocate(sizeof(uint32_t)); - *value = connid; - - bool success = parcHashCodeTable_Add(table->symbolicNameTable, key, value); - success = parcHashCodeTable_Add(table->indexToNameTable, value, key); - if (!success) { - parcMemory_Deallocate((void **)&key); - parcMemory_Deallocate((void **)&value); - } - - 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/config/symbolicNameTable.h b/hicn-light/src/config/symbolicNameTable.h deleted file mode 100644 index 69919cf00..000000000 --- a/hicn-light/src/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 - -/** - * 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/content_store/CMakeLists.txt b/hicn-light/src/content_store/CMakeLists.txt deleted file mode 100644 index 85643cf5e..000000000 --- a/hicn-light/src/content_store/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -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 -) - -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 -) - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/content_store/contentStoreEntry.c b/hicn-light/src/content_store/contentStoreEntry.c deleted file mode 100644 index d36ed61a0..000000000 --- a/hicn-light/src/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 -#include - -#include -#include - -#include - -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/content_store/contentStoreEntry.h b/hicn-light/src/content_store/contentStoreEntry.h deleted file mode 100644 index 766cc15e4..000000000 --- a/hicn-light/src/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 -#include - -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 - * contentStoreEntry_Destroy() 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/content_store/contentStoreInterface.c b/hicn-light/src/content_store/contentStoreInterface.c deleted file mode 100644 index a42041670..000000000 --- a/hicn-light/src/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 -#include - -#include - -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/content_store/contentStoreInterface.h b/hicn-light/src/content_store/contentStoreInterface.h deleted file mode 100644 index d73c63019..000000000 --- a/hicn-light/src/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 - -#include - -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/content_store/contentStoreLRU.c b/hicn-light/src/content_store/contentStoreLRU.c deleted file mode 100644 index 2eb043d8e..000000000 --- a/hicn-light/src/content_store/contentStoreLRU.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#endif -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -#include -#include - -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; - } - - 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/content_store/contentStoreLRU.h b/hicn-light/src/content_store/contentStoreLRU.h deleted file mode 100644 index 3c0815ebd..000000000 --- a/hicn-light/src/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 -#include -#include - -/** - * 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/content_store/listLRU.c b/hicn-light/src/content_store/listLRU.c deleted file mode 100644 index 0a1631bab..000000000 --- a/hicn-light/src/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 -#endif -#include -#include -#include - -#include -#include -#include - -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/content_store/listLRU.h b/hicn-light/src/content_store/listLRU.h deleted file mode 100644 index 75f698b61..000000000 --- a/hicn-light/src/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 LruEntry_Destroy() 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/content_store/listTimeOrdered.c b/hicn-light/src/content_store/listTimeOrdered.c deleted file mode 100644 index 44697d202..000000000 --- a/hicn-light/src/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 -#include -#include - -#include -#include - -/** - * 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/content_store/listTimeOrdered.h b/hicn-light/src/content_store/listTimeOrdered.h deleted file mode 100644 index b18bd16f7..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -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/core/CMakeLists.txt b/hicn-light/src/core/CMakeLists.txt deleted file mode 100644 index 1d7dc03e9..000000000 --- a/hicn-light/src/core/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -list(APPEND HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.h - ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h - ${CMAKE_CURRENT_SOURCE_DIR}/connectionList.h - ${CMAKE_CURRENT_SOURCE_DIR}/connectionTable.h - ${CMAKE_CURRENT_SOURCE_DIR}/connection.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}/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 -) - -list(APPEND SOURCE_FILES - ${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}/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}/mapMe.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) \ No newline at end of file diff --git a/hicn-light/src/core/connection.c b/hicn-light/src/core/connection.c deleted file mode 100644 index 525fe29c4..000000000 --- a/hicn-light/src/core/connection.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -struct connection { - const AddressPair *addressPair; - IoOperations *ops; - - unsigned refCount; - - bool probing_active; - unsigned probing_interval; - unsigned counter; - Ticks last_sent; - Ticks delay; - - bool wldrAutoStart; // if true, wldr can be set automatically - // by default this value is set to true. - // if wldr is activated using a command (config - // file/hicnLightControl) this value is set to false so - // that a base station can not disable wldr at the client - Wldr *wldr; -}; - -Connection *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; - conn->probing_active = false; - - conn->wldrAutoStart = true; - conn->probing_interval = 0; - conn->counter = 0; - conn->last_sent = 0; - conn->delay = INT_MAX; - return conn; -} - -Connection *connection_Acquire(Connection *connection) { - parcAssertNotNull(connection, "Parameter conn must be non-null"); - connection->refCount++; - return connection; -} - -void connection_Release(Connection **connectionPtr) { - parcAssertNotNull(connectionPtr, "Parameter must be non-null double pointer"); - parcAssertNotNull(*connectionPtr, - "Parameter must dereference to non-null pointer"); - Connection *conn = *connectionPtr; - - parcAssertTrue( - conn->refCount > 0, - "Invalid state, connection reference count should be positive, got 0."); - conn->refCount--; - if (conn->refCount == 0) { - // don't destroy addressPair, its part of ops. - ioOperations_Release(&conn->ops); - if (conn->wldr != NULL) { - wldr_Destroy(&(conn->wldr)); - } - parcMemory_Deallocate((void **)&conn); - } - *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 (conn->wldr != NULL) { - wldr_SetLabel(conn->wldr, message); - } else { - message_ResetWldrLabel(message); - } - return ioOperations_Send(conn->ops, NULL, message); - } - return false; -} - -bool connection_SendCommandResponse(const Connection *conn, struct iovec *msg){ - parcAssertNotNull(conn, "Parameter conn must be non-null"); - parcAssertNotNull(msg, "Parameter message must be non-null"); - - return ioOperations_SendCommandResponse(conn->ops, msg); -} - -static void _sendProbe(Connection *conn, unsigned probeType, uint8_t *message) { - parcAssertNotNull(conn, "Parameter conn must be non-null"); - - if (probeType == PACKET_TYPE_PROBE_REQUEST) { - Ticks now = ioOperations_SendProbe(conn->ops, probeType, message); - if (now != 0) { - conn->last_sent = now; - } - } else { - ioOperations_SendProbe(conn->ops, probeType, message); - } -} - -void connection_Probe(Connection *conn) { - _sendProbe(conn, PACKET_TYPE_PROBE_REQUEST, NULL); -} - -void connection_HandleProbe(Connection *conn, uint8_t *probe, - Ticks actualTime) { - parcAssertNotNull(conn, "Parameter conn must be non-null"); - parcAssertNotNull(probe, "Parameter pkt must be non-null"); - - uint8_t probeType = messageHandler_GetProbePacketType(probe); - if (probeType == PACKET_TYPE_PROBE_REQUEST) { - _sendProbe(conn, PACKET_TYPE_PROBE_REPLY, probe); - } else if (probeType == PACKET_TYPE_PROBE_REPLY) { - Ticks delay = actualTime - conn->last_sent; - if (delay == 0) { - delay = 1; - } - if (delay < conn->delay) { - conn->delay = delay; - } - } else { - printf("receivde unkwon probe type\n"); - } -} - -uint64_t connection_GetDelay(Connection *conn) { return (uint64_t)conn->delay; } - -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); -} - -const void *connection_Class(const Connection *conn) { - parcAssertNotNull(conn, "Parameter conn must be non-null"); - return ioOperations_Class(conn->ops); -} - -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); - } - } - - if (notification) { - // the notification is never destroyed - message_Release(&message); - } - - return res; -} - -void connection_AllowWldrAutoStart(Connection *conn, bool allow) { - conn->wldrAutoStart = allow; -} - -void connection_EnableWldr(Connection *conn) { - if (!connection_IsLocal(conn)) { - if (conn->wldr == NULL) { - printf("----------------- enable wldr\n"); - conn->wldr = wldr_Init(); - } - } -} - -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_HasWldr(const Connection *conn) { - if (conn->wldr == NULL) { - return false; - } else { - return true; - } -} - -bool connection_WldrAutoStartAllowed(const Connection *conn) { - return conn->wldrAutoStart; -} - -void connection_DetectLosses(Connection *conn, Message *message) { - if (conn->wldr != NULL) wldr_DetectLosses(conn->wldr, conn, message); -} - -void connection_HandleWldrNotification(Connection *conn, Message *message) { - if (conn->wldr != NULL) - wldr_HandleWldrNotification(conn->wldr, conn, message); -} diff --git a/hicn-light/src/core/connection.h b/hicn-light/src/core/connection.h deleted file mode 100644 index 56fa131b5..000000000 --- a/hicn-light/src/core/connection.h +++ /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. - */ - -/** - * @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. - * - */ - -#ifndef connection_h -#define connection_h -#include -#include -#include - -// packet types for probing -#define PACKET_TYPE_PROBE_REQUEST 5 -#define PACKET_TYPE_PROBE_REPLY 6 - -struct connection; -typedef struct connection Connection; - -/** - * Creates a connection object. - */ -Connection *connection_Create(IoOperations *ops); - -/** - * @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); - -/** - * @function connection_Acquire - * @abstract A reference counted copy. - * @discussion - * A shallow copy, they share the same memory. - */ -Connection *connection_Acquire(Connection *connection); - -/** - * @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); - -/** - * @function connection_SendCommandResponse - * @abstract Sends a response (ack/nack) for a command - */ -bool connection_SendCommandResponse(const Connection *conn, struct iovec *msg); - -/** - * 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); - -/** - * 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); - -/** - * 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); - -/** - * 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); - -/** - * 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); - -/** - * 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); - -bool connection_ReSend(const Connection *conn, Message *message, - bool notification); - -void connection_Probe(Connection *conn); - -void connection_HandleProbe(Connection *conn, uint8_t *message, - Ticks actualTime); - -uint64_t connection_GetDelay(Connection *conn); - -void connection_AllowWldrAutoStart(Connection *conn, bool allow); - -void connection_EnableWldr(Connection *conn); - -void connection_DisableWldr(Connection *conn); - -bool connection_HasWldr(const Connection *conn); - -bool connection_WldrAutoStartAllowed(const Connection *conn); - -void connection_DetectLosses(Connection *conn, Message *message); - -void connection_HandleWldrNotification(Connection *conn, Message *message); -#endif // connection_h diff --git a/hicn-light/src/core/connectionList.c b/hicn-light/src/core/connectionList.c deleted file mode 100644 index b2913fa05..000000000 --- a/hicn-light/src/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 -#include - -#include -#include - -#include -#include - -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/core/connectionList.h b/hicn-light/src/core/connectionList.h deleted file mode 100644 index cdca12993..000000000 --- a/hicn-light/src/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 - -/** - * 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/core/connectionManager.c b/hicn-light/src/core/connectionManager.c deleted file mode 100644 index 2089e1495..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include -#include -#include - -#include - -#include - -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/core/connectionManager.h b/hicn-light/src/core/connectionManager.h deleted file mode 100644 index b77553e0d..000000000 --- a/hicn-light/src/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 - -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/core/connectionTable.c b/hicn-light/src/core/connectionTable.c deleted file mode 100644 index 8634ec825..000000000 --- a/hicn-light/src/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 -#endif -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -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(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/core/connectionTable.h b/hicn-light/src/core/connectionTable.h deleted file mode 100644 index 30517ae1d..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -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(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/core/dispatcher.c b/hicn-light/src/core/dispatcher.c deleted file mode 100644 index b6ef5e21f..000000000 --- a/hicn-light/src/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 -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include - -#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/core/dispatcher.h b/hicn-light/src/core/dispatcher.h deleted file mode 100644 index 96bceb451..000000000 --- a/hicn-light/src/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 -#endif -#include - -struct dispatcher; -typedef struct dispatcher Dispatcher; - -#include -#include -#include -#include -#include -#include -#include - -#include - -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 dispatcher_WaitForStopped() 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 dispatcher_Stop() 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 forwarder_NewBind() - * that received the client connection - * @constant client_socket is the client socket - * @constant user_data is the user_data passed to - * forwarder_NewBind() - * @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 - * Forwarder_CreateEvent() - */ -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 - * forwarder_StartTimer() - * - * @param isPeriodic means the timer will fire repeatidly, otherwise it is a - * one-shot and needs to be set again with dispatcher_StartTimer() - */ -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 - * forwarder_StartNetworkEvent() - * - * @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 - * forwarder_StartSignalEvent() - * - * @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 -#include - -/** - * @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/core/forwarder.c b/hicn-light/src/core/forwarder.c deleted file mode 100644 index a7d151314..000000000 --- a/hicn-light/src/core/forwarder.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Event based router - * - * This module is the glue around the event scheduler. - * Its the packet i/o module. - * - * Packet processing is done in dispatcher.c, which is the actual wrapper around - * the event scheduler - */ - -#ifndef _WIN32 -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define __STDC_FORMAT_MACROS -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#ifdef WITH_MAPME -#include -#endif /* WITH_MAPME */ -#include -#include -#include -#include - -#include - -#include - -// the router's clock frequency (we now use the monotonic clock) -#define HZ 1000 - -// these will all be a little off because its all integer division -#define MSEC_PER_TICK (1000 / HZ) -#define USEC_PER_TICK (1000000 / HZ) -#define NSEC_PER_TICK ((1000000000ULL) / HZ) -#define MSEC_TO_TICKS(msec) \ - ((msec < FC_MSEC_PER_TICK) ? 1 : msec / FC_MSEC_PER_TICK) -#define NSEC_TO_TICKS(nsec) ((nsec < NSEC_PER_TICK) ? 1 : nsec / NSEC_PER_TICK) - -struct forwarder { - Dispatcher *dispatcher; - - uint16_t server_port; - - PARCEventSignal *signal_int; - PARCEventSignal *signal_term; -#ifndef _WIN32 - PARCEventSignal *signal_usr1; -#endif - PARCEventTimer *keepalive_event; - - // will skew the virtual clock forward. In normal operaiton, it is 0. - Ticks clockOffset; - - unsigned nextConnectionid; - Messenger *messenger; - ConnectionManager *connectionManager; - ConnectionTable *connectionTable; - ListenerSet *listenerSet; - Configuration *config; - - // we'll eventually want to setup a threadpool of these - MessageProcessor *processor; - - Logger *logger; - - PARCClock *clock; - - hicn_socket_helper_t - *hicnSocketHelper; // state required to manage hicn connections - - // used by seed48 and nrand48 - unsigned short seed[3]; - -#ifdef WITH_MAPME - MapMe *mapme; -#endif /* WITH_MAPME */ -}; - -// 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) { -#ifndef _WIN32 - int fd; - ssize_t res; - - res = -1; - fd = open("/dev/urandom", O_RDONLY); - if (fd != -1) { - res = read(fd, forwarder->seed, sizeof(forwarder->seed)); - close(fd); - } - if (res != sizeof(forwarder->seed)) { - forwarder->seed[1] = (unsigned short)getpid(); /* better than no entropy */ - forwarder->seed[2] = (unsigned short)time(NULL); - } - /* - * The call to seed48 is needed by cygwin, and should be harmless - * on other platforms. - */ - seed48(forwarder->seed); -#else - forwarder->seed[1] = (unsigned short)getpid(); /* better than no entropy */ - forwarder->seed[2] = (unsigned short)time(NULL); -#endif -} - -Logger *forwarder_GetLogger(const Forwarder *forwarder) { - return forwarder->logger; -} - -// ============================================================================ -// Setup and destroy section - -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->clock = parcClock_Monotonic(); - forwarder->clockOffset = 0; - - 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->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 - -#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING) - forwarder->hicnSocketHelper = hicn_create(); - if (forwarder->hicnSocketHelper == NULL) return NULL; -#endif /* __APPLE__ */ - /* ignore child */ -#ifndef _WIN32 - signal(SIGCHLD, SIG_IGN); - - /* ignore tty signals */ - signal(SIGTSTP, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - signal(SIGTTIN, SIG_IGN); -#endif - - // We no longer use this for ticks, but we need to have at least one event - // schedule to keep Libevent happy. - - struct timeval wtnow_timeout; - timerclear(&wtnow_timeout); - - wtnow_timeout.tv_sec = 0; - wtnow_timeout.tv_usec = 50000; // 20 Hz keepalive - -#ifdef WITH_MAPME - if (!(mapMe_Init(&forwarder->mapme, forwarder))) return NULL; -#endif /* WITH_MAPME */ - - 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); - - return forwarder; -} - -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_destroy(); -#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)); - - // the messenger is used by many of the other pieces, so destroy it last - 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); - *ptr = NULL; -} - -void forwarder_SetupAllListeners(Forwarder *forwarder, uint16_t port, - const char *localPath) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - - configurationListeners_SetupAll(forwarder->config, port, localPath); -} - -void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - configurationListeners_SetutpLocalIPv4(forwarder->config, port); -} - -void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename) { - ConfigurationFile *configFile = configurationFile_Create(forwarder, filename); - if (configFile) { - configurationFile_Process(configFile); - configurationFile_Release(&configFile); - } -} - -Configuration *forwarder_GetConfiguration(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return forwarder->config; -} - -// ============================================================================ - -unsigned forwarder_GetNextConnectionId(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return forwarder->nextConnectionid++; -} - -Messenger *forwarder_GetMessenger(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return forwarder->messenger; -} - -Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return forwarder->dispatcher; -} - -ConnectionTable *forwarder_GetConnectionTable(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return forwarder->connectionTable; -} - -ListenerSet *forwarder_GetListenerSet(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return forwarder->listenerSet; -} - -void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - messageProcessor_SetCacheStoreFlag(forwarder->processor, val); -} - -bool forwarder_GetChacheStoreFlag(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return messageProcessor_GetCacheStoreFlag(forwarder->processor); -} - -void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - messageProcessor_SetCacheServeFlag(forwarder->processor, val); -} - -bool forwarder_GetChacheServeFlag(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return messageProcessor_GetCacheServeFlag(forwarder->processor); -} - -void forwarder_ReceiveCommand(Forwarder *forwarder, command_id command, - struct iovec *message, unsigned ingressId) { - configuration_ReceiveCommand(forwarder->config, command, message, ingressId); -} - -void forwarder_Receive(Forwarder *forwarder, Message *message) { - parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null"); - parcAssertNotNull(message, "Parameter message must be non-null"); - - // this takes ownership of the message, so we're done here - - // 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)); - - if (!conn) { - return; - } - - if (message_HasWldr(message)) { - if (connection_HasWldr(conn)) { - // case 1: WLDR is enabled - connection_DetectLosses((Connection *)conn, message); - } else if (!connection_HasWldr(conn) && - connection_WldrAutoStartAllowed(conn)) { - // case 2: We are on an AP. We enable WLDR - connection_EnableWldr((Connection *)conn); - connection_DetectLosses((Connection *)conn, message); - } - // case 3: Ignore WLDR - } else { - if (connection_HasWldr(conn) && connection_WldrAutoStartAllowed(conn)) { - // case 1: STA do not use WLDR, we disable it - connection_DisableWldr((Connection *)conn); - } - } - - messageProcessor_Receive(forwarder->processor, message); -} - -Ticks forwarder_GetTicks(const Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter must be non-null"); - return parcClock_GetTime(forwarder->clock) + forwarder->clockOffset; -} - -Ticks forwarder_NanosToTicks(uint64_t nanos) { return NSEC_TO_TICKS(nanos); } - -uint64_t forwarder_TicksToNanos(Ticks ticks) { - return (1000000000ULL) * ticks / HZ; -} - -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"); - - // we only have one message processor - bool res = - messageProcessor_AddOrUpdateRoute(forwarder->processor, control, ifidx); - - return res; -} - -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"); - - // we only have one message processor - return messageProcessor_RemoveRoute(forwarder->processor, control, ifidx); -} - -void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder, - unsigned connectionId) { - parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null"); - messageProcessor_RemoveConnectionIdFromRoutes(forwarder->processor, - connectionId); -} - -void forwarder_SetStrategy(Forwarder *forwarder, Name *prefix, - strategy_type strategy) { - parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null"); - parcAssertNotNull(prefix, "Parameter prefix must be non-null"); - - // if (strategy == NULL) { - // strategy = SET_STRATEGY_RANDOM; - // } - - processor_SetStrategy(forwarder->processor, prefix, strategy); -} - -FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder) { - return messageProcessor_GetFibEntries(forwarder->processor); -} - -void forwarder_SetContentObjectStoreSize(Forwarder *forwarder, - size_t maximumContentStoreSize) { - messageProcessor_SetContentObjectStoreSize(forwarder->processor, - maximumContentStoreSize); -} - -void forwarder_ClearCache(Forwarder *forwarder) { - messageProcessor_ClearCache(forwarder->processor); -} - -PARCClock *forwarder_GetClock(const Forwarder *forwarder) { - return forwarder->clock; -} - -hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder) { - return forwarder->hicnSocketHelper; -} - -// ======================================================= - -static void _signal_cb(int sig, PARCEventType events, void *user_data) { - Forwarder *forwarder = (Forwarder *)user_data; - - logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning, - __func__, "signal %d events %d", sig, events); - - switch ((int)sig) { - case SIGTERM: - logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning, - __func__, "Caught an terminate signal; exiting cleanly."); - dispatcher_Stop(forwarder->dispatcher); - break; - - case SIGINT: - logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning, - __func__, "Caught an interrupt signal; exiting cleanly."); - dispatcher_Stop(forwarder->dispatcher); - break; -#ifndef _WIN32 - case SIGUSR1: - // dump stats - break; -#endif - - default: - 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 -} - -#ifdef WITH_MAPME -FIB *forwarder_getFib(Forwarder *forwarder) { - return messageProcessor_getFib(forwarder->processor); -} - -void forwarder_onConnectionAdded(Forwarder *forwarder, const Connection *conn) { - mapMe_onConnectionAdded(forwarder->mapme, conn); -} - -void forwarder_onConnectionRemoved(Forwarder *forwarder, - const Connection *conn) {} - -void forwarder_ProcessMapMe(Forwarder *forwarder, uint8_t *msgBuffer, - unsigned conn_id) { - mapMe_Process(forwarder->mapme, msgBuffer, conn_id); -} - -#endif /* WITH_MAPME */ diff --git a/hicn-light/src/core/forwarder.h b/hicn-light/src/core/forwarder.h deleted file mode 100644 index de736a1f8..000000000 --- a/hicn-light/src/core/forwarder.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 methods in this header are for the non-threaded forwarder. They should - * only be called within the forwarders thread of execution. - */ - -#ifndef forwarder_h -#define forwarder_h - -#ifndef _WIN32 -#include -#endif -#include - -#include -#include -#include - -#include - -#include - -#ifdef WITH_MAPME -#include -#endif /* WITH_MAPME */ - -#include -#include -#include - -#include - -#include - -#include - -#define PORT_NUMBER 9695 -#define PORT_NUMBER_AS_STRING "9695" - -#include - -// ============================================== - -struct forwarder; -typedef struct forwarder Forwarder; - -/** - * @function forwarder_Create - * @abstract 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); - -/** - * @function forwarder_Destroy - * @abstract Destroys the forwarder, stopping all traffic and freeing all memory - */ -void forwarder_Destroy(Forwarder **ptr); - -/** - * @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 - * given port - */ -void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port); - -/** - * Configure hicn-light via a configuration file - * - * The configuration file is a set of lines, just like used in hicnLightControl. - * You need to have "add listener" lines in the file to receive connections. No - * default listeners are configured. - * - * @param [in] forwarder An alloated Forwarder - * @param [in] filename The path to the configuration file - */ -void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename); - -/** - * Returns the logger used by this forwarder - * - * If you will store the logger, you should acquire a reference to it. - * - * @param [in] forwarder An allocated hicn-light forwarder - * - * @retval non-null The logger used by hicn-light - * @retval null An error - */ -Logger *forwarder_GetLogger(const Forwarder *forwarder); - -/** - * @function forwarder_SetLogLevel - * @abstract Sets the minimum level to log - */ -void forwarder_SetLogLevel(Forwarder *forwarder, PARCLogLevel level); - -/** - * @function forwarder_GetNextConnectionId - * @abstract Get the next identifier for a new connection - */ -unsigned forwarder_GetNextConnectionId(Forwarder *forwarder); - -Messenger *forwarder_GetMessenger(Forwarder *forwarder); - -Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder); - -/** - * Returns the set of currently active listeners - * - * @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); - -/** - * Returns the forwrder's connection table - * - * @param [in] forwarder An allocated hicn-light forwarder - * - * @retval non-null The connection tabler - * @retval null An error - * - */ -ConnectionTable *forwarder_GetConnectionTable(Forwarder *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); - -/** - * 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); - -/** - * Convert nano seconds to Ticks - * - * Converts nano seconds to Ticks, based on HZ (in forwarder.c) - */ -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_Receive(Forwarder *forwarder, Message *mesage); - -/** - * @function forwarder_AddOrUpdateRoute - * @abstract Adds or updates a route on all the message processors - */ -bool forwarder_AddOrUpdateRoute(Forwarder *forwarder, - add_route_command *control, unsigned ifidx); - -/** - * @function forwarder_RemoveRoute - * @abstract Removes a route from all the message processors - */ -bool forwarder_RemoveRoute(Forwarder *forwarder, remove_route_command *control, - unsigned ifidx); - -/** - * Removes a connection id from all routes - */ -void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder, - unsigned connectionId); - -/** - * @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); - -FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder); - -/** - * Sets the maximum number of content objects in the content store - * - * Implementation dependent - may wipe the cache. - */ -void forwarder_SetContentObjectStoreSize(Forwarder *forwarder, - size_t maximumContentStoreSize); - -void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val); - -bool forwarder_GetChacheStoreFlag(Forwarder *forwarder); - -void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val); - -bool forwarder_GetChacheServeFlag(Forwarder *forwarder); - -void forwarder_ClearCache(Forwarder *forwarder); - -void forwarder_SetStrategy(Forwarder *forwarder, Name *prefix, - strategy_type strategy); - -hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder); - -#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); - -/** - * @function forwarder_onConnectionAdded - * @abstract 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. - */ -void forwarder_onConnectionAdded(Forwarder *forwarder, const Connection *conn); - -/** - * @function forwarder_onConnectionRemoved - * @abstract Callback fired upon removal of a connection through the control - * protocol. - * @param [in] forwarder - Pointer to the hICN forwarder. - * @param [in] conn - Pointer to the removed connection. - */ -void forwarder_onConnectionRemoved(Forwarder *forwarder, - const Connection *conn); - -/** - * @function forwarder_ProcessMapMe - * @abstract 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 - */ -void forwarder_ProcessMapMe(Forwarder *forwarder, uint8_t *msgBuffer, - unsigned conn_id); - -#endif /* WITH_MAPME */ - -#endif // forwarder_h diff --git a/hicn-light/src/core/logger.c b/hicn-light/src/core/logger.c deleted file mode 100644 index ebc8dc5a1..000000000 --- a/hicn-light/src/core/logger.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#endif - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#include -#include - -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 = 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/core/logger.h b/hicn-light/src/core/logger.h deleted file mode 100644 index c46a87097..000000000 --- a/hicn-light/src/core/logger.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 -#endif -#include -#include -#include -#include -#include - -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_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/core/mapMe.c b/hicn-light/src/core/mapMe.c deleted file mode 100644 index d5ed08bfb..000000000 --- a/hicn-light/src/core/mapMe.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file mapMe.c - * @brief MAP-Me : AnchorLess Producer Mobility Management. - */ - -#ifdef WITH_MAPME - -#include -#include -#include // printf - -#include -#include -#include -#include -#include // packet types -#include -#include -#include - -#include -#include -#include -#include - -#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 NOT_A_NOTIFICATION false -#define NO_INGRESS 0 -#define TIMER_NO_REPEAT false - -#define DO_DISCOVERY 1 -#define MAPME_INVALID_DICOVERY_SEQ -1 - -#define LOG_FACILITY LoggerFacility_Core - -#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) - -#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__) - -/** - * MAP-Me state data structure - */ -struct mapme { - uint32_t retx; /* ms */ - uint32_t Tu; /* ms */ - bool removeFibEntries; - - Forwarder *forwarder; -}; - -static MapMe MapMeDefault = {.retx = MAPME_DEFAULT_RETX, - .Tu = MAPME_DEFAULT_TU, - .removeFibEntries = false}; - -/******************************************************************************/ - -#include - -bool mapMe_Init(MapMe **mapme, Forwarder *forwarder) { - *mapme = malloc(sizeof(MapMe)); - if (!mapme) goto ERR_MALLOC; - - /* Internal state : set default values */ - memcpy(*mapme, &MapMeDefault, sizeof(MapMe)); - - (*mapme)->forwarder = forwarder; - - /* Install hook on Face events to onConnectionAdded */ - // see. config/configuration.c - - /* Install hook for signalization processing. See : - * - io/hicnListener.c - * - src/core/connection.{c,h} - */ - - return true; - -ERR_MALLOC: - return false; -} - -/****************************************************************************** - * TFIB - ******************************************************************************/ - -#define INVALID_SEQ 0 -#define INIT_SEQ 1 - -typedef struct { - uint32_t seq; - PARCHashMap *nexthops; - /* Update/Notification heuristic */ - Ticks lastAckedUpdate; // XXX This is only for producer !!! -} MapMeTFIB; - -static MapMeTFIB *mapMeTFIB_Create() { - MapMeTFIB *tfib; - tfib = malloc(sizeof(MapMeTFIB)); - if (!tfib) goto ERR_MALLOC; - tfib->seq = 0; - tfib->lastAckedUpdate = 0; - tfib->nexthops = parcHashMap_Create(); - if (!tfib->nexthops) goto ERR_HASHMAP; - - return tfib; - -ERR_HASHMAP: - free(tfib); -ERR_MALLOC: - return NULL; -} - -void mapMeTFIB_Release(MapMeTFIB **tfibPtr) { - MapMeTFIB *tfib = *tfibPtr; - parcHashMap_Release(&tfib->nexthops); - free(tfib); - *tfibPtr = NULL; -} - -/** - * @function mapMe_CreateTFIB - * @abstract Associate a new TFIB entry to a FIB entry. - * @param [in] - Pointer to the FIB entry. - * @return Boolean indicating the success of the operation. - */ -static void mapMe_CreateTFIB(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, tfib, (void (*)(void **))mapMeTFIB_Release); -} - -#define TFIB(fibEntry) ((MapMeTFIB *)fibEntry_getUserData(fibEntry)) - -static const PARCEventTimer *mapMeTFIB_Get(const MapMeTFIB *tfib, - unsigned conn_id) { - const PARCEventTimer *timer; - const PARCBuffer *buffer; - PARCUnsigned *cid = parcUnsigned_Create(conn_id); - buffer = parcHashMap_Get(tfib->nexthops, cid); - if (!buffer) return NULL; - PARCByteArray *array = parcBuffer_Array(buffer); - timer = *((PARCEventTimer **)parcByteArray_Array(array)); - parcUnsigned_Release(&cid); - return timer; -} - -static void mapMeTFIB_Put(MapMeTFIB *tfib, unsigned conn_id, - const PARCEventTimer *timer) { - /* NOTE: Timers are not objects (the only class not being an object in - * fact), and as such, we cannot use them as values for the HashMap. - * Just like for unsigned we needed the PARC wrapper. - * There is no wrapper for pointers, so we use Arrays, which has an ubly - * syntax... - */ - PARCUnsigned *cid = parcUnsigned_Create(conn_id); - PARCBuffer *buffer = - parcBuffer_CreateFromArray(&timer, sizeof(PARCEventTimer *)); - parcHashMap_Put(tfib->nexthops, cid, buffer); - parcUnsigned_Release(&cid); - parcBuffer_Release(&buffer); -} - -static void mapMeTFIB_Remove(MapMeTFIB *tfib, unsigned conn_id) { - // Who releases the timer ? - PARCUnsigned *cid = parcUnsigned_Create(conn_id); - parcHashMap_Remove(tfib->nexthops, cid); - parcUnsigned_Release(&cid); -} - -static PARCIterator *mapMeTFIB_CreateKeyIterator(const MapMeTFIB *tfib) { - return parcHashMap_CreateKeyIterator(tfib->nexthops); -} - -int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) { - NameBitvector *bv = name_GetContentName(name); - ip_address_t ip_address; - nameBitvector_ToIPAddress(bv, &ip_address); - - /* The name length will be equal to ip address' prefix length */ - return hicn_prefix_create_from_ip_address(&ip_address, prefix); -} - -static Message *mapMe_createMessage(const MapMe *mapme, const Name *name, - mapme_params_t *params) { - Ticks now = forwarder_GetTicks(mapme->forwarder); - Logger *logger = logger_Acquire(forwarder_GetLogger(mapme->forwarder)); - - INFO(mapme, "[MAP-Me] CreateMessage type=%d seq=%d", params->type, - params->seq); - - size_t size = (params->protocol == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN - : HICN_MAPME_V4_HDRLEN; - uint8_t *icmp_pkt = parcMemory_AllocateAndClear(size); - - 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; - } - - INFO(mapme, "[MAP-Me] Creating MAP-Me packet"); - size_t len = hicn_mapme_create_packet(icmp_pkt, &prefix, params); - if (len != 0) { - ERR(mapme, "[MAP-Me] Failed to create mapme packet through lib"); - goto ERR_CREATE; - } - - // hicn_packet_dump(icmp_pkt, MAPME_HDRLEN); - - return message_CreateFromByteArray(NO_INGRESS, icmp_pkt, - MessagePacketType_Interest, now, logger); - -ERR_CREATE: -ERR_NAME: - return NULL; -} - -static Message *mapMe_createAckMessage(const MapMe *mapme, - const uint8_t *msgBuffer, - const mapme_params_t *params) { - Ticks now = forwarder_GetTicks(mapme->forwarder); - Logger *logger = logger_Acquire(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"); - return NULL; - } - - return message_CreateFromByteArray( - NO_INGRESS, icmp_pkt, MessagePacketType_ContentObject, now, logger); -} - -struct setFacePendingArgs { - const MapMe *mapme; - const Name *name; - FibEntry *fibEntry; - unsigned conn_id; - bool send; - bool is_first; - uint32_t num_retx; -}; - -static bool mapMe_setFacePending(const MapMe *mapme, const Name *name, - FibEntry *fibEntry, unsigned conn_id, - bool send, bool is_first, uint32_t num_retx); - -static void mapMe_setFacePendingCallback(int fd, PARCEventType which_event, - void *data) { - struct setFacePendingArgs *args = (struct setFacePendingArgs *)data; - - parcAssertTrue(which_event & PARCEventType_Timeout, - "Event incorrect, expecting %X set, got %X", - PARCEventType_Timeout, which_event); - - INFO(args->mapme, "Timeout during retransmission. Re-sending"); - mapMe_setFacePending(args->mapme, args->name, args->fibEntry, args->conn_id, - args->send, args->is_first, args->num_retx); -} - -/** - * @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_first, uint32_t num_retx) { - int rc; - - INFO(mapme, "[MAP-Me] SetFacePending connection=%d prefix=XX retx=%d", - conn_id, num_retx); - - /* 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; - - // 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_first || send) { - // XXX - mapme_params_t params = { - .protocol = IPPROTO_IPV6, - .type = is_first ? mapMe_getTypeFromHeuristic(mapme, fibEntry) : UPDATE, - .seq = TFIB(fibEntry)->seq}; - Message *special_interest = mapMe_createMessage(mapme, name, ¶ms); - if (!special_interest) { - INFO(mapme, "[MAP-Me] Could not create special interest"); - return false; - } - - const ConnectionTable *table = - forwarder_GetConnectionTable(mapme->forwarder); - const Connection *conn = - connectionTable_FindById((ConnectionTable *)table, conn_id); - if (conn) { - INFO(mapme, "[MAP-Me] Sending MAP-Me packet"); - connection_ReSend(conn, special_interest, NOT_A_NOTIFICATION); - } else { - INFO(mapme, "[MAP-Me] Stopped retransmissions as face went down"); - } - - 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_first = is_first; - 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) goto ERR_TIMER; - } else { - INFO(mapme, "[MAP-Me] Last retransmission."); - timer = NULL; - } - } else { - INFO(mapme, "[MAP-Me] - not forwarding as send is False"); - timer = NULL; - } - - PARCEventTimer *oldTimer = - (PARCEventTimer *)mapMeTFIB_Get(TFIB(fibEntry), conn_id); - if (oldTimer) { - INFO(mapme, "[MAP-Me] - Found old timer, would need to cancel !"); - // parcEventTimer_Stop(oldTimer); - } - INFO(mapme, "[MAP-Me] - Putting new timer in TFIB"); - if (timer) mapMeTFIB_Put(TFIB(fibEntry), conn_id, timer); - - return true; - -ERR_MALLOC: -ERR_TIMER: - return false; -} - -/*------------------------------------------------------------------------------ - * Event handling - *----------------------------------------------------------------------------*/ - -/* - * 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; -} - -/* - * Callback called everytime a new connection is created by the control protocol - */ -void mapMe_onConnectionAdded(const MapMe *mapme, const Connection *conn_added) { - /* bool ret; */ - FibEntryList *fiblist; - - /* Ignore local connections corresponding to applications for now */ - if (connection_IsLocal(conn_added)) return; - - unsigned conn_added_id = connection_GetConnectionId(conn_added); - INFO(mapme, "[MAP-Me] New connection %d", conn_added_id); - - /* - * Iterate on FIB to find locally served prefix - * Ideally, we want to avoid a FIB scan everytime a face is added/removed - */ - fiblist = forwarder_GetFibEntries(mapme->forwarder); - for (size_t i = 0; i < fibEntryList_Length(fiblist); i++) { - FibEntry *fibEntry = (FibEntry *)fibEntryList_Get(fiblist, i); - const Name *name = fibEntry_GetPrefix(fibEntry); - - /* Skip entries that have no local connection as next hop */ - if (!mapMe_hasLocalNextHops(mapme, fibEntry)) continue; - - /* This entry corresponds to a locally served prefix, set - * Special Interest */ - if (!TFIB(fibEntry)) /* Create TFIB associated to FIB entry */ - mapMe_CreateTFIB(fibEntry); - TFIB(fibEntry)->seq++; - - char *name_str = name_ToString(name); - INFO(mapme, "[MAP-Me] sending IU/IN for name %s on connection %d", name_str, - conn_added_id); - free(name_str); - - mapMe_setFacePending(mapme, name, fibEntry, conn_added_id, true, true, 0); - } -} - -/*------------------------------------------------------------------------------ - * 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); - 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); - - /* - * Immediately send an acknowledgement back on the ingress connection - * We always ack, even duplicates. - */ - Message *ack = mapMe_createAckMessage(mapme, msgBuffer, params); - if (!ack) goto ERR_ACK_CREATE; - rv = connection_ReSend(conn_in, ack, NOT_A_NOTIFICATION); - if (!rv) goto ERR_ACK_SEND; - message_Release(&ack); - - /* EPM on FIB */ - /* only the processor has access to the FIB */ - FIB *fib = forwarder_getFib(mapme->forwarder); - - FibEntry *fibEntry = fib_Contains(fib, name); - if (!fibEntry) { - 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; - - fibEntry = fibEntry_Create(name, fwdStrategy); - fibEntry_AddNexthopByConnectionId(fibEntry, conn_in_id); - mapMe_CreateTFIB(fibEntry); - TFIB(fibEntry)->seq = seq; // INIT_SEQ; - fib_Add(fib, fibEntry); - return true; // with proper seq, we are done - - } else if (!TFIB(fibEntry)) { - /* Create TFIB associated to FIB entry */ - INFO(mapme, - "[MAP-Me] - Creating TFIB entry with default sequence number"); - mapMe_CreateTFIB(fibEntry); - } - - 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)); - 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, 0); - } - parcIterator_Release(&iterator); - } - - /* nextHops -> prevHops - * - * We add to the list of pendingUpdates the current next hops, and - * eventually forward them an IU too. - * - * Exception: nextHops -> nextHops - * Because of retransmission issues, it is possible that a second interest - * (with same of higher sequence number) is receive from a next-hop - * interface. In that case, the face remains a next hop. - */ - const NumberSet *nexthops_old = fibEntry_GetNexthops(fibEntry); - - /* We make a copy to be able to send IU _after_ updating next hops */ - NumberSet *nexthops = numberSet_Create(); - numberSet_AddSet(nexthops, nexthops_old); - - /* 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. - * - * Optimization : nextHops -> nextHops - * - no next hop to add - * - we know that inFace was not a previous hop since it was a next hop and - * this forms a partition. No need for a search - */ - - INFO(mapme, "[MAP-Me] - (3/3) next hops ~~> prev hops"); - PARCEventTimer *oldTimer = - (PARCEventTimer *)mapMeTFIB_Get(TFIB(fibEntry), conn_in_id); - if (oldTimer) { - /* This happens if we receive an IU while we are still sending - * one in the other direction - */ - INFO(mapme, "[MAP-Me] - Canceled pending timer"); - parcEventTimer_Stop(oldTimer); - mapMeTFIB_Remove(TFIB(fibEntry), conn_in_id); - } - - /* Remove all next hops */ - for (size_t k = 0; k < numberSet_Length(nexthops_old); k++) { - unsigned conn_id = numberSet_GetItem(nexthops_old, k); - INFO(mapme, "[MAP-Me] - Replaced next hops by connection %d", conn_id); - fibEntry_RemoveNexthopByConnectionId(fibEntry, conn_id); - } - fibEntry_AddNexthopByConnectionId(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; - } - - 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, 0); - complete = false; - } - - /* - * The update is completed when the IU could not be sent to any - * other next hop. - */ - if (complete) INFO(mapme, "[MAP-Me] - Update completed !"); - - numberSet_Release(&nexthops); - - } else if (seq == fibSeq) { - /* - * Multipath, multihoming, multiple producers or duplicate interest - * - * 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 - * - * It might happen that the previous AP has still a connection to the - * producer and that we received back our own IU. In that case, we just - * need to Ack and ignore it. - */ - if (mapMe_hasLocalNextHops(mapme, fibEntry)) { - INFO(mapme, "[MAP-Me] - Received original interest... Update complete"); - return true; - } - - INFO(mapme, "[MAP-Me] - Adding multipath next hop on connection %d", - conn_in_id); - fibEntry_AddNexthopByConnectionId(fibEntry, conn_in_id); - - } else { // seq < fibSeq - /* - * 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, 0); - } - - return true; - -ERR_ACK_SEND: - message_Release(&ack); -ERR_ACK_CREATE: - return false; -} - -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); - - const Name *name = - name_CreateFromPacket(msgBuffer, MessagePacketType_Interest); - - FIB *fib = forwarder_getFib(mapme->forwarder); - FibEntry *fibEntry = fib_Contains(fib, name); - 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) { - INFO(mapme, - "[MAP-Me] - Ignored special interest Ack with seq=%u, expected %u", - seq, fibSeq); - return; - } - } - - /* - * 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 - */ - 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 ?"); - return; - } - - /* Stop timer and remove entry from TFIB */ - parcEventTimer_Stop(timer); - mapMeTFIB_Remove(TFIB(fibEntry), conn_in_id); - - INFO(mapme, "[MAP-Me] - Removing TFIB entry for ack on connection %d", - conn_in_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 *msgBuffer) { - uint8_t next_header = messageHandler_NextHeaderType(msgBuffer); - - const uint8_t *icmp_ptr; - if (next_header == IPPROTO_ICMP) { - icmp_ptr = msgBuffer + IPV4_HDRLEN; - } else if (next_header == IPPROTO_ICMPV6) { - icmp_ptr = msgBuffer + IPV6_HDRLEN; - } else { - return false; - } - - uint8_t type = ((_icmp_header_t *)icmp_ptr)->type; - uint8_t code = ((_icmp_header_t *)icmp_ptr)->code; - if (HICN_IS_MAPME(type, code)) return true; - - return false; -} - -/** - * @discussion The exact type of the MapMe message is determined after - * reception. In hICN, Interest Update and Notifications look like regular - * Interest packets, and are first punted from the normal path by the forwarder, - * then treated as such in the Listener to reach this function. Acknowledgements - * are received as Content (Data) packets and will land here too. - * - * This function is in charge of abstracting the low-level implementation of - * 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) { - hicn_prefix_t prefix; - mapme_params_t params; - hicn_mapme_parse_packet(msgBuffer, &prefix, ¶ms); - - // XXX Dispatch message dependenging on type - switch (params.type) { - case UPDATE: - case NOTIFICATION: - mapMe_onSpecialInterest(mapme, msgBuffer, conn_id, &prefix, ¶ms); - break; - case UPDATE_ACK: - case NOTIFICATION_ACK: - mapMe_onSpecialInterestAck(mapme, msgBuffer, conn_id, &prefix, ¶ms); - break; - default: - printf("E:Unknown message\n"); - break; - } -} - -#endif /* WITH_MAPME */ diff --git a/hicn-light/src/core/mapMe.h b/hicn-light/src/core/mapMe.h deleted file mode 100644 index 39edd0bd7..000000000 --- a/hicn-light/src/core/mapMe.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 mapMe.h - * @brief MAP-Me : AnchorLess Producer Mobility Management - */ - -#ifndef mapMe_h -#define mapMe_h - -#ifdef WITH_MAPME - -#include -#include - -#include - -#include -#include - -struct mapme; -typedef struct mapme MapMe; - -/** - * @function MapMe_Init - * @abstract Initializes MAP-Me state in the forwarder. - * @return bool - Boolean informing about the success of MAP-Me initialization. - */ -bool mapMe_Init(MapMe **mapme, Forwarder *Forwarder); - -/** - * @function messageHandler_isMapMe - * @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 - * done through hooks defined in the Init function. - * @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); - -/** - * @function mapMe_handleMapMeMessage - * @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); - -/** - * @function mapMe_onConnectionAdded - * @abstract Callback following the addition of the face though the control - * protocol. - * @discussion This callback triggers the sending of control packets by MAP-Me. - * @param [in] mapme - Pointer to the MAP-Me data structure. - * @param [in] conn - The newly added connection. - */ -void mapMe_onConnectionAdded(const MapMe *mapme, const Connection *conn); - -/** - * @function mapMe_getNextHops - * @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); - -#endif /* WITH_MAPME */ - -#endif // mapMe_h diff --git a/hicn-light/src/core/message.c b/hicn-light/src/core/message.c deleted file mode 100644 index 9b807aebc..000000000 --- a/hicn-light/src/core/message.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include - -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); - // XXX: what about the checksum? - 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, 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); - 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/core/message.h b/hicn-light/src/core/message.h deleted file mode 100644 index 88aa32480..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -#include - -#include -#include - -#include - -#include - -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/core/messageHandler.h b/hicn-light/src/core/messageHandler.h deleted file mode 100644 index f469ac5b0..000000000 --- a/hicn-light/src/core/messageHandler.h +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 - -#include -#include - -#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 - -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; - } -} - -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((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((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 uint8_t messageHandler_GetProbePacketType( - 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 ((_icmp_header_t *)icmp_ptr)->code; -} - -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 new_path_label) { - if (!messageHandler_IsTCP(message)) return; - - uint32_t old_path_label; - int res = hicn_data_get_path_label((hicn_header_t *)message, &old_path_label); - if (res < 0) 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); - - hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit); - - messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit, - (uint16_t *)&pl_new_32bit, 2); -} - -static inline void messageHandler_ResetPathLabel(uint8_t *message) { - if (!messageHandler_IsTCP(message)) return; - - uint32_t pl_old_32bit = messageHandler_GetPathLabel(message); - uint32_t pl_new_32bit = 0; - hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit); - messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit, - (uint16_t *)&pl_new_32bit, 2); -} - -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 void messageHandler_SetProbePacket(uint8_t *message, - uint8_t probeType, - struct in6_addr *src, - struct in6_addr *dst) { - hicn_header_t *h = (hicn_header_t *)message; - *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, // this should be 1, but ... just to be safe - }, - .icmp = - { - .type = ICMP_LB_TYPE, - .code = probeType, - }, - }}; - messageHandler_SetSource_IPv6(message, src); - messageHandler_SetDestination_IPv6(message, dst); -} - -#endif // Metis_metis_MessageHandler diff --git a/hicn-light/src/core/messagePacketType.h b/hicn-light/src/core/messagePacketType.h deleted file mode 100644 index dfbb12342..000000000 --- a/hicn-light/src/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/core/name.c b/hicn-light/src/core/name.c deleted file mode 100644 index f6a452d27..000000000 --- a/hicn-light/src/core/name.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include - -#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, union commandAddr 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.ipv4, len); - } else if (addressType == ADDR_INET6) { - name->content_name = nameBitvector_CreateFromIn6Addr(&addr.ipv6, 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; -} - -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"); - - 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; - } - } -} - -bool name_StartsWith(const Name *name, const Name *prefix) { - parcAssertNotNull(name, "Parameter name must be non-null"); - parcAssertNotNull(prefix, "Parameter prefix must be non-null"); - - return nameBitvector_StartsWith(name->content_name, prefix->content_name); -} - -char *name_ToString(const Name *name) { - char *output = malloc(128); - - Address *packetAddr = nameBitvector_ToAddress(name_GetContentName(name)); - - sprintf(output, "name: %s seq: %u", addressToString(packetAddr), - name->segment); - - addressDestroy(&packetAddr); - - return output; -} - -void name_setLen(const Name *name, uint8_t len) { - nameBitvector_setLen(name->content_name, len); -} diff --git a/hicn-light/src/core/name.h b/hicn-light/src/core/name.h deleted file mode 100644 index fb4ad7a56..000000000 --- a/hicn-light/src/core/name.h +++ /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. - */ - -#ifndef name_h -#define name_h - -#include -#include - -#include -#include -#include - -#include - -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); - -/** - * 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); - -/** - * @function metsName_StartsWith - * @abstract Checks if name starts with prefix - * @discussion - * Byte-by-byte prefix comparison - * - * @return True if the name is equal to or begins with prefix - */ - -bool name_StartsWith(const Name *name, const Name *prefix); - -/** - * 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(const Name *name, uint8_t len); - -/** - * Creates a name from a Address - * - */ -Name *name_CreateFromAddress(address_type addressType, union commandAddr addr, - uint8_t len); - -#endif // name_h diff --git a/hicn-light/src/core/nameBitvector.c b/hicn-light/src/core/nameBitvector.c deleted file mode 100644 index 28ea513c4..000000000 --- a/hicn-light/src/core/nameBitvector.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include - -#define BLOCKS 2 - -const uint64_t BLOCK_SIZE = 64; -const uint64_t WIDTH = 128; -const uint64_t BLOCK_ONE = 0x1; - -// the bits are encoded in the following order: -// 00100101001---101010 00100011---110100100 -// [bits[0] (uint64_t)] [bits[1] (uint64_t)] -// ^ ^ ^ ^ -// 0 63 64 127 -// address 2200::0011 is encoded as: -// 1000 1000 0000 0010 00000 ....0100 0100 -// ^ ^ -// 0 127 - -struct name_bitvector { - uint64_t bits[BLOCKS]; - 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[1] = (bitvector->bits[1] | addr_4) << 8; - bitvector->bits[1] = (bitvector->bits[1] | addr_3) << 8; - bitvector->bits[1] = (bitvector->bits[1] | addr_2) << 8; - bitvector->bits[1] = (bitvector->bits[1] | addr_1); - bitvector->bits[1] = bitvector->bits[1] << 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[1] = (bitvector->bits[1] << 8) | addr->s6_addr[i]; - } - - for (int i = 8; i < 16; ++i) { - bitvector->bits[0] = (bitvector->bits[0] << 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; - } -} - -bool nameBitvector_StartsWith(const NameBitvector *name, - const NameBitvector *prefix) { - parcAssertNotNull(name, "name cannot be NULL"); - parcAssertNotNull(prefix, "prefix cannot be NULL"); - parcAssertTrue(prefix->len > 0, "prefix length can not be 0"); - - if (prefix->len > BLOCK_SIZE) - return (name->bits[1] == prefix->bits[1]) && - ((name->bits[0] ^ prefix->bits[0]) >> - (BLOCK_SIZE - (prefix->len - BLOCK_SIZE)) == - 0); - - return ((name->bits[1] ^ prefix->bits[1]) >> (BLOCK_SIZE - prefix->len) == 0); -} - -bool nameBitvector_testBit(const NameBitvector *name, uint8_t pos) { - if (pos == WIDTH) pos = 127; - - uint8_t final_pos = (uint8_t)(WIDTH - name->len); - - // the bit to test is inside the name/prefix len - if (pos > final_pos) { - return (name->bits[pos / BLOCK_SIZE] & (BLOCK_ONE << (pos % BLOCK_SIZE))); - } - - // the bit to test is outside the name/prefix len - if (pos < final_pos) { - return false; - } - - // pos is equal to the name/prefix len - return true; -} - -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; -} - -uint8_t nameBitvector_firstDiff(const NameBitvector *a, - const NameBitvector *b) { - uint8_t res = 0; - uint64_t diff = a->bits[1] ^ b->bits[1]; - if (diff) - res = (uint8_t)(64 + _diff_bit_log2(diff)); - else - res = (uint8_t)_diff_bit_log2(a->bits[0] ^ b->bits[0]); - - // res is computed over the bitvector which is composed by 128 bit all the - // times however the prefixes may be diffrent just because the have different - // lengths example: prefix 1: 0::/30 prefix 2: 0::/20 at this point of the - // function res would be 0 since both the bitvectors are composed by 0s but - // the function will return 127-20, which is the position at which the two - // prefix are different, since prefix 2 has only 20 bits - - uint8_t len_diff; - if (a->len < b->len) - len_diff = (uint8_t)(WIDTH - a->len); - else - len_diff = (uint8_t)(WIDTH - b->len); - - if (len_diff > res) res = len_diff; - - return res; -} - -int nameBitvector_ToIPAddress(const NameBitvector *name, - ip_address_t *ip_address) { - if (name->IPversion == IPv4_TYPE) { - struct in_addr *addr = (struct in_addr *)(&ip_address->buffer); - ip_address->family = AF_INET; - ip_address->prefix_len = IPV4_ADDR_LEN_BITS; - - uint32_t tmp_addr = name->bits[1] >> 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 *)(&ip_address->buffer); - ip_address->family = AF_INET6; - ip_address->prefix_len = name->len; // IPV6_ADDR_LEN_BITS; - - for (int i = 0; i < 8; i++) { - addr->s6_addr[i] = (uint8_t)((name->bits[1] >> 8 * (7 - i)) & 0xFF); - } - - int x = 0; - for (int i = 8; i < 16; ++i) { - addr->s6_addr[i] = (uint8_t)((name->bits[0] >> 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[1] >> 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[1] >> 8 * (7 - i)) & 0xFF); - } - - int x = 0; - for (int i = 8; i < 16; ++i) { - addr.sin6_addr.s6_addr[i] = - (uint8_t)((name->bits[0] >> 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); - - sprintf(output, "prefix: %s len: %u", addressToString(packetAddr), name->len); - - addressDestroy(&packetAddr); - - return output; -} \ No newline at end of file diff --git a/hicn-light/src/core/nameBitvector.h b/hicn-light/src/core/nameBitvector.h deleted file mode 100644 index fb94f8f1a..000000000 --- a/hicn-light/src/core/nameBitvector.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#include - -#include - -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_CreateFromAddress(const Address *prefix, - 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); - -bool nameBitvector_StartsWith(const NameBitvector *name, - const NameBitvector *prefix); - -bool nameBitvector_testBit(const NameBitvector *name, uint8_t pos); - -uint8_t nameBitvector_firstDiff(const NameBitvector *a, const NameBitvector *b); - -int nameBitvector_ToIPAddress(const NameBitvector *name, - ip_address_t *ip_address); -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/core/numberSet.c b/hicn-light/src/core/numberSet.c deleted file mode 100644 index 75fec1524..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -#include - -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/core/numberSet.h b/hicn-light/src/core/numberSet.h deleted file mode 100644 index 91a965d7b..000000000 --- a/hicn-light/src/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 -#include -#include - -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 setToAdd to destinationSet - * @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 difference = minuend - - * subtrahend, returns a new number set. - * @discussion - * minuend and subtrahend are not modified. A new - * difference set is created. - * - * Returns the elements in minuend that are not in - * subtrahend. - * - * @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/core/streamBuffer.c b/hicn-light/src/core/streamBuffer.c deleted file mode 100644 index 7aebb5edb..000000000 --- a/hicn-light/src/core/streamBuffer.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 -#include - -#include - -#include - -void streamBuffer_Destroy(PARCEventQueue **bufferPtr) { - parcAssertNotNull(bufferPtr, "Parameter must be non-null double pointer"); - parcAssertNotNull(*bufferPtr, - "Parameter must dereference to non-null pointer"); - parcEventQueue_Destroy(bufferPtr); - *bufferPtr = NULL; -} - -void streamBuffer_SetWatermark(PARCEventQueue *buffer, bool setRead, - bool setWrite, size_t low, size_t high) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - - short flags = 0; - if (setRead) { - flags |= PARCEventType_Read; - } - - if (setWrite) { - flags |= PARCEventType_Write; - } - - parcEventQueue_SetWatermark(buffer, flags, low, high); -} - -int streamBuffer_Flush(PARCEventQueue *buffer, bool flushRead, - bool flushWrite) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - - short flags = 0; - if (flushRead) { - flags |= PARCEventType_Read; - } - - if (flushWrite) { - flags |= PARCEventType_Write; - } - - return parcEventQueue_Flush(buffer, flags); -} - -int streamBuffer_FlushCheckpoint(PARCEventQueue *buffer, bool flushRead, - bool flushWrite) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - - short flags = 0; - if (flushRead) { - flags |= PARCEventType_Read; - } - - if (flushWrite) { - flags |= PARCEventType_Write; - } - - return parcEventQueue_Flush(buffer, flags); -} - -int streamBuffer_FlushFinished(PARCEventQueue *buffer, bool flushRead, - bool flushWrite) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - - short flags = 0; - if (flushRead) { - flags |= PARCEventType_Read; - } - - if (flushWrite) { - flags |= PARCEventType_Write; - } - - return parcEventQueue_Flush(buffer, flags); -} - -void streamBuffer_SetCallbacks(PARCEventQueue *buffer, - PARCEventQueue_Callback *readCallback, - PARCEventQueue_Callback *writeCallback, - PARCEventQueue_EventCallback *eventCallback, - void *user_data) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - - parcEventQueue_SetCallbacks(buffer, readCallback, writeCallback, - eventCallback, user_data); -} - -void streamBuffer_EnableCallbacks(PARCEventQueue *buffer, bool enableRead, - bool enableWrite) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - short flags = 0; - if (enableRead) { - flags |= PARCEventType_Read; - } - if (enableWrite) { - flags |= PARCEventType_Write; - } - - parcEventQueue_Enable(buffer, flags); -} - -/** - * @function StreamBuffer_DisableCallbacks - * @abstract Disables specified callbacks. Does not affect others. - * @discussion - * Disables enabled callbacks. If a callback is already disabled, has no - * effect. A "false" value does not enable it. - * - * @param <#param1#> - * @return <#return#> - */ -void streamBuffer_DisableCallbacks(PARCEventQueue *buffer, bool disableRead, - bool disableWrite) { - parcAssertNotNull(buffer, "Parameter buffer must be non-null"); - short flags = 0; - if (disableRead) { - flags |= PARCEventType_Read; - } - if (disableWrite) { - flags |= PARCEventType_Write; - } - - parcEventQueue_Disable(buffer, flags); -} diff --git a/hicn-light/src/core/streamBuffer.h b/hicn-light/src/core/streamBuffer.h deleted file mode 100644 index 27e793176..000000000 --- a/hicn-light/src/core/streamBuffer.h +++ /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. - */ - -/** - * Wrapper around event scheduler - */ - -#ifndef streamBuffer_h -#define streamBuffer_h - -#include -#include - -void streamBuffer_Destroy(PARCEventQueue **bufferPtr); - -/** - * @function streamBuffer_SetWatermark - * @abstract Sets the read and/or write watermarks - * @discussion - * For a read watermark, when there is at least low bytes - * available to read, the read callback will be fired. If the bytes in the - * buffer exceed high, the stream buffer will stop reading from the - * network. - * - * For a write watermark, when the bytes in the buffer fall below - * low, the write callback is fired. The high - * watermark limits stream filters and shapers from exceeding that threashold on - * what they write to the buffer. - * - */ -void streamBuffer_SetWatermark(PARCEventQueue *buffer, bool setRead, - bool setWrite, size_t low, size_t high); - -/** - * @function streamBuffer_Flush - * @abstract The buffer will read/write more data if available - * - * @return -1 error, 0 no more data, 1 more data - */ -int streamBuffer_Flush(PARCEventQueue *buffer, bool flushRead, bool flushWrite); - -/** - * @function streamBuffer_FlushCheckpoint - * @abstract Flushes the stream, checkpointing all data in the buffer - */ -int streamBuffer_FlushCheckpoint(PARCEventQueue *buffer, bool flushRead, - bool flushWrite); - -/** - * @function streamBuffer_FlushFinished - * @abstract Flush the stream and indicate the end of new data - */ -int streamBuffer_FlushFinished(PARCEventQueue *buffer, bool flushRead, - bool flushWrite); - -/** - * @typedef StreamBufferReadWriteCallback - * @abstract Callback when data is available or write space available - * @constant user_data opaque data passed to - * StreamBuffer_SetCallbacks() - */ -typedef void(StreamBufferReadWriteCallback)(PARCEventQueue *buffer, - void *user_data); - -/** - * @typedef StreamBufferEventCallback - * @abstract Callback on error or other event on the stream buffer - * @constant what logical or of STREAM events. STREAM_READING and - * STREAM_WRITING indicate if the error was on the read or write direction. The - * conditions may be STREAM_ERROR, STREAM_EOF, STREAM_TIMEOUT, or - * STREAM_CONNECTED. - * @constant user_data opaque data passed to - * StreamBuffer_SetCallbacks() - */ -typedef void(StreamBufferEventCallback)(PARCEventQueue *buffer, short what, - void *user_data); - -/** - * Changes the callbacks for a buffer event. - * - * @param bufev the buffer event object for which to change callbacks - * @param readcb callback to invoke when there is data to be read, or NULL if - * no callback is desired - * @param writecb callback to invoke when the file descriptor is ready for - * writing, or NULL if no callback is desired - * @param eventcb callback to invoke when there is an event on the file - * descriptor - * @param cbarg an argument that will be supplied to each of the callbacks - * (readcb, writecb, and errorcb) - * @see parcEventQueue_Create() - */ -void streamBuffer_SetCallbacks(PARCEventQueue *buffer, - PARCEventQueue_Callback *readCallback, - PARCEventQueue_Callback *writeCallback, - PARCEventQueue_EventCallback *eventCallback, - void *user_data); - -/** - * @function StreamBuffer_EnableCallbacks - * @abstract Enables specified callbacks. Does not affect others. - * @discussion - * Enables disabled callbacks. If a callback is already enabled, has no - * effect. A "false" value does not disable it. - */ -void streamBuffer_EnableCallbacks(PARCEventQueue *buffer, bool enableRead, - bool enableWrite); - -/** - * @function StreamBuffer_DisableCallbacks - * @abstract Disables specified callbacks. Does not affect others. - * @discussion - * Disables enabled callbacks. If a callback is already disabled, has no - * effect. A "false" value does not enable it. - */ -void streamBuffer_DisableCallbacks(PARCEventQueue *buffer, bool disableRead, - bool disableWrite); -#endif // streamBuffer_h diff --git a/hicn-light/src/core/system.h b/hicn-light/src/core/system.h deleted file mode 100644 index 3c5c8cba2..000000000 --- a/hicn-light/src/core/system.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 system.h - * @abstract System-level properties - * @discussion - * <#Discussion#> - * - */ - -#ifndef system_h -#define system_h - -#include -#include - -/** - * @function system_Interfaces - * @abstract The system network interfaces - */ -InterfaceSet *system_Interfaces(Forwarder *forwarder); - -/** - * Returns the MTU of the named interface - * - * @param [in] an allocated hicn-light forwarder - * @param [in] interfaceName The system interface name, e.g. "eth0" - * - * @return 0 Interface does not exist - * @return positive the MTU the kernel reports - * - */ -unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName); - -/** - * Returns the LINK address of the specified interface - * - * @param [in] an allocated hicn-light forwarder - * @param [in] interfaceName The system interface name, e.g. "eth0" - * - * @retval non-null The MAC address of the interface - * @retval null The interface does not exist - * - */ -Address *system_GetMacAddressByName(Forwarder *forwarder, - const char *interfaceName); -#endif diff --git a/hicn-light/src/core/ticks.h b/hicn-light/src/core/ticks.h deleted file mode 100644 index 8750abde5..000000000 --- a/hicn-light/src/core/ticks.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. - */ - -/** - * @brief The router periodically measures time in units of Ticks - * - * See forwarder.c HZ which specifies the tick rate. forwarder.h has functions - * to convert between ticks and milliseconds. - * - */ -#ifndef ticks_h -#define ticks_h - -#define __STDC_FORMAT_MACROS -#include - -typedef uint64_t Ticks; - -#endif // ticks_h diff --git a/hicn-light/src/core/wldr.c b/hicn-light/src/core/wldr.c deleted file mode 100644 index a3e8756dd..000000000 --- a/hicn-light/src/core/wldr.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 -#include -#include -#include -#include -#include -#include - -struct wldr_buffer { - Message *message; - uint8_t rtx_counter; -}; - -typedef struct wldr_buffer WldrBuffer; - -struct wldr_state { - uint16_t expected_label; - uint16_t next_label; - WldrBuffer *buffer[BUFFER_SIZE]; -}; - -Wldr *wldr_Init() { - Wldr *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)); - parcAssertNotNull( - entry, - "WldrBuffer init: parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(WldrBuffer)); - entry->message = NULL; - entry->rtx_counter = 0; - wldr->buffer[i] = entry; - } - return wldr; -} - -void wldr_ResetState(Wldr *wldr) { - wldr->expected_label = 1; - wldr->next_label = 1; - for (int i = 0; i < BUFFER_SIZE; i++) { - wldr->buffer[i]->message = NULL; - wldr->buffer[i]->rtx_counter = 0; - } -} - -void wldr_Destroy(Wldr **wldrPtr) { - Wldr *wldr = *wldrPtr; - for (unsigned i = 0; i < BUFFER_SIZE; i++) { - if (wldr->buffer[i]->message != NULL) { - message_Release(&(wldr->buffer[i]->message)); - parcMemory_Deallocate((void **)&(wldr->buffer[i])); - } - } - parcMemory_Deallocate((void **)&wldr); - *wldrPtr = NULL; -} - -static void _wldr_RetransmitPacket(Wldr *wldr, const Connection *conn, - uint16_t label) { - if (wldr->buffer[label % BUFFER_SIZE]->message == 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; - 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)); - } - - wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = 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); - wldr->next_label++; - connection_ReSend(conn, msg, false); - } -} - -static void _wldr_SendWldrNotificaiton(Wldr *wldr, const Connection *conn, - Message *message, 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 - // notification is the source address of the message for which we want to - // create a notification. in fact, if message is an interest the prevoius hop - // is identified by the src. if message is a data, we need to send the - // notification message with the content name has a source address in this way - // the message will be trapped by the pounting rules in the next hop We define - // the notification as an interest message so that the NAT in the send - // function will set the src address of the local connection. Notice that in - // 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); - parcAssertNotNull(notification, "Got null from CreateWldrNotification"); - connection_ReSend(conn, notification, true); -} - -void wldr_SetLabel(Wldr *wldr, Message *message) { - // in this function we send the packet for the first time - // 1) we set the wldr label - message_SetWldrLabel(message, wldr->next_label); - - // 2) we store the pointer to packet in the buffer - if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->message != NULL) { - // release an old message if necessary - message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message)); - } - - // we need to acquire the message to avoid that it gets destroyed - message_Acquire(message); - - wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = message; - 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++; -} - -void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message) { - if (message_HasWldr(message)) { - // this is a normal wldr packet - uint16_t pkt_lbl = (uint16_t)message_GetWldrLabel(message); - 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 - // a while and reconnected on this same connection, so the two nodes are - // out of synch for this reason we do not send any notification, we just - // synch the labels - - if ((pkt_lbl != 1) || (wldr->expected_label < pkt_lbl)) { - _wldr_SendWldrNotificaiton(wldr, conn, message, wldr->expected_label, - pkt_lbl); - } - - // here we always synch - wldr->expected_label = (uint16_t)(pkt_lbl + 1); - } else { - wldr->expected_label++; - if (wldr->expected_label == 0) - wldr->expected_label++; // for the next_label we want to skip 0 - } - } -} - -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); - if ((wldr->next_label - expected_lbl) > BUFFER_SIZE) { - // the packets are not in the buffer anymore - return; - } - while (expected_lbl < received_lbl) { - _wldr_RetransmitPacket(wldr, conn, expected_lbl); - expected_lbl++; - } -} diff --git a/hicn-light/src/core/wldr.h b/hicn-light/src/core/wldr.h deleted file mode 100644 index 1666b4d3f..000000000 --- a/hicn-light/src/core/wldr.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wldr_h -#define wldr_h - -#include -#include -#include - -#define BUFFER_SIZE 8192 -#define MAX_RTX 3 -#define WLDR_LBL 13 -#define WLDR_NOTIFICATION 14 -#define WLDR_UNKNOWN 15 - -// NORMAL PACKET or RETRASMISSION -// WLDR_LBL: label = window size in the TCP header -// NOTIFICATION -// WLDR_NOTIFICATION: expected_label = window size in the TCP header, -// last_received_label = urgent pointer in the TCP header -// 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; - -Wldr *wldr_Init(); - -void wldr_Destroy(Wldr **wldrPtr); - -void wldr_ResetState(Wldr *wldr); - -void wldr_SetLabel(Wldr *wldr, Message *message); - -void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message); - -void wldr_HandleWldrNotification(Wldr *wldr, const Connection *conn, - Message *message); -#endif // wldr_h diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt new file mode 100644 index 000000000..2130c1c39 --- /dev/null +++ b/hicn-light/src/hicn/CMakeLists.txt @@ -0,0 +1,51 @@ +# Define a few configuration variables that we want accessible in the software + +include(BuildMacros) +configure_file(config.h.in config.h @ONLY) + +if(NOT ANDROID_API AND NOT COMPILE_FOR_IOS) + add_subdirectory(command_line) +endif () + +add_subdirectory(config) +add_subdirectory(content_store) +add_subdirectory(core) +add_subdirectory(api) +add_subdirectory(io) +add_subdirectory(messenger) +add_subdirectory(platforms) +add_subdirectory(processor) +add_subdirectory(socket) +add_subdirectory(strategies) +add_subdirectory(utils) + +list(APPEND HEADER_FILES + ${CMAKE_CURRENT_BINARY_DIR}/config.h +) + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND ENABLE_PUNTING) + list(APPEND COMPILER_DEFINITIONS + "-DPUNTING" + ) +endif() + +list(APPEND COMPILER_DEFINITIONS + "-DWITH_MAPME -DWITH_MAPME_FIXES" +) + +list(INSERT HICN_LIGHT_INCLUDE_DIRS 0 + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + +build_library(${LIBHICN_LIGHT} + STATIC + SOURCES ${SOURCE_FILES} + INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES} + LINK_LIBRARIES ${LIBRARIES} + DEPENDS ${DEPENDENCIES} + COMPONENT ${LIBHICN_LIGHT} + INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS} + INSTALL_ROOT_DIR hicn/light + DEFINITIONS ${COMPILER_DEFINITIONS} +) + diff --git a/hicn-light/src/hicn/api/CMakeLists.txt b/hicn-light/src/hicn/api/CMakeLists.txt new file mode 100644 index 000000000..c8bf16ff3 --- /dev/null +++ b/hicn-light/src/hicn/api/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/api.h + ${CMAKE_CURRENT_SOURCE_DIR}/commands.h + ${CMAKE_CURRENT_SOURCE_DIR}/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/ip_address.h + ${CMAKE_CURRENT_SOURCE_DIR}/token.h + ${CMAKE_CURRENT_SOURCE_DIR}/types.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/api.c +) + +build_library(hicn-light-ctrl + SHARED + SOURCES ${SOURCE_FILES} + COMPONENT ${HICN_LIGHT} + INSTALL_ROOT_DIR hicn + INSTALL_HEADERS ${HEADER_FILES} + LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES} +) \ No newline at end of file diff --git a/hicn-light/src/hicn/api/api.c b/hicn-light/src/hicn/api/api.c new file mode 100644 index 000000000..291f3e6a3 --- /dev/null +++ b/hicn-light/src/hicn/api/api.c @@ -0,0 +1,1391 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file api.c + * \brief Implementation of hICN control library API + */ + +#include // assert +#include // fcntl +#include // log2 +#include // memmove, strncpy, strcasecmp +#include // socket +#include // close, fcntl + +#include // XXX debug + +#include +#include +#include +#include + +#define PORT 9695 + +#define LIBHICNCTRL_SUCCESS 1 +#define LIBHICNCTRL_FAILURE -1 +#define LIBHICNCTRL_IS_ERROR(x) (x < 0) + +/* + * list was working with all seq set to 0, but it seems hicnLightControl uses + * 1, and replies with the same seqno + */ +#define HICN_CTRL_SEND_SEQ_INIT 1 +#define HICN_CTRL_RECV_SEQ_INIT 1 + +#define MAX(x, y) ((x > y) ? x : y) + +#if 0 +static inline u32 log2(const u32 x) { + u32 y; + asm ( "\tbsr %1, %0\n" + : "=r"(y) + : "r" (x) + ); + return y; +} +#endif + +/** + * \brief Defines the default size for the allocated data arrays holding the + * results of API calls. + * + * This size should not be too small to avoid wasting memoyy, but also not too + * big to avoid unnecessary realloc's. Later on this size is doubled at each + * reallocation. + */ +#define DEFAULT_SIZE_LOG 3 + +/** + * In practise, we want to preserve enough room to store a full packet of + * average expected size (say a header + N payload elements). + */ +#define AVG_ELEMENTS (1 << DEFAULT_SIZE_LOG) +#define AVG_BUFLEN \ + sizeof(hc_msg_header_t) + AVG_ELEMENTS * sizeof(hc_msg_payload_t) + +/* + * We should at least have buffer space allowing to store one processable unit + * of data, either the header of the maximum possible payload + */ +#define MIN_BUFLEN MAX(sizeof(hc_msg_header_t), sizeof(hc_msg_payload_t)) + +static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; + +/* /!\ Please update constants in header file upon changes */ +const char *connection_type_str[] = { +#define _(x) [CONNECTION_TYPE_##x] = STRINGIZE(x), + foreach_connection_type +#undef _ +}; + +#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x) + +hc_connection_type_t connection_type_from_str(const char *str) { + if (strcasecmp(str, "TCP") == 0) + return CONNECTION_TYPE_TCP; + else if (strcasecmp(str, "UDP") == 0) + return CONNECTION_TYPE_UDP; + else if (strcasecmp(str, "HICN") == 0) + return CONNECTION_TYPE_HICN; + else + return CONNECTION_TYPE_UNDEFINED; +} + +/* + * Mandatory conversions to shield lib user from heterogeneity + */ + +#define IS_VALID_LIST_CONNECTIONS_TYPE(x) ((x >= CONN_GRE) && (x <= CONN_HICN)) + +static const hc_connection_type_t map_from_list_connections_type[] = { + [CONN_GRE] = CONNECTION_TYPE_UNDEFINED, + [CONN_TCP] = CONNECTION_TYPE_TCP, + [CONN_UDP] = CONNECTION_TYPE_UDP, + [CONN_MULTICAST] = CONNECTION_TYPE_UNDEFINED, + [CONN_L2] = CONNECTION_TYPE_UNDEFINED, + [CONN_HICN] = CONNECTION_TYPE_HICN, +}; + +typedef enum { + ENCAP_TCP, + ENCAP_UDP, + ENCAP_ETHER, + ENCAP_LOCAL, + ENCAP_HICN +} EncapType; + +#define IS_VALID_LIST_LISTENERS_TYPE(x) ((x >= ENCAP_TCP) && (x <= ENCAP_HICN)) + +static const hc_connection_type_t map_from_encap_type[] = { + [ENCAP_TCP] = CONNECTION_TYPE_TCP, + [ENCAP_UDP] = CONNECTION_TYPE_UDP, + [ENCAP_ETHER] = CONNECTION_TYPE_UNDEFINED, + [ENCAP_LOCAL] = CONNECTION_TYPE_UNDEFINED, + [ENCAP_HICN] = CONNECTION_TYPE_HICN, +}; + +static const connection_type map_to_connection_type[] = { + [CONNECTION_TYPE_TCP] = TCP_CONN, + [CONNECTION_TYPE_UDP] = UDP_CONN, + [CONNECTION_TYPE_HICN] = HICN_CONN, +}; + +static const listener_mode map_to_listener_mode[] = { + [CONNECTION_TYPE_TCP] = IP_MODE, + [CONNECTION_TYPE_UDP] = IP_MODE, + [CONNECTION_TYPE_HICN] = HICN_MODE, +}; + +#define IS_VALID_LIST_CONNECTIONS_STATE(x) \ + ((x >= IFACE_UP) && (x <= IFACE_UNKNOWN)) + +/* /!\ Please update constants in header file upon changes */ +const char *connection_state_str[] = { +#define _(x) [CONNECTION_STATE_##x] = STRINGIZE(x), + foreach_connection_state +#undef _ +}; + +/* +#define IS_VALID_CONNECTION_STATE(x) IS_VALID_ENUM_TYPE(CONNECTION_STATE, x) + +static const connection_state map_to_connection_state[] = { + [CONNECTION_STATE_UP] = IFACE_UP, + [CONNECTION_STATE_DOWN] = IFACE_DOWN, +}; + +*/ + +static const hc_connection_state_t map_from_list_connections_state[] = { + [IFACE_UP] = CONNECTION_STATE_UP, + [IFACE_DOWN] = CONNECTION_STATE_DOWN, + [IFACE_UNKNOWN] = CONNECTION_STATE_UNDEFINED, +}; + +#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX)) + +static const int map_from_addr_type[] = { + [ADDR_INET] = AF_INET, [ADDR_INET6] = AF_INET6, [ADDR_LINK] = AF_UNSPEC, + [ADDR_IFACE] = AF_UNSPEC, [ADDR_UNIX] = AF_UNSPEC, +}; + +static const address_type map_to_addr_type[] = { + [AF_INET] = ADDR_INET, + [AF_INET6] = ADDR_INET6, +}; + +/****************************************************************************** + * Message helper types and aliases + ******************************************************************************/ + +#define foreach_hc_command \ + _(add_listener) \ + _(add_connection) \ + _(list_connections) \ + _(add_route) \ + _(list_routes) \ + _(remove_connection) \ + _(remove_route) \ + _(cache_store) \ + _(cache_serve) \ + /*_(cache_clear) */ \ + _(set_strategy) \ + _(set_wldr) \ + _(add_punting) \ + _(list_listeners) \ + _(mapme_activator) \ + _(mapme_timing) + +typedef header_control_message hc_msg_header_t; + +typedef union { +#define _(x) x##_command x; + foreach_hc_command +#undef _ +} hc_msg_payload_t; + +typedef struct hc_msg_s { + hc_msg_header_t hdr; + hc_msg_payload_t payload; +} hc_msg_t; + +/****************************************************************************** + * Control Data + ******************************************************************************/ + +hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size) { + hc_data_t *data = malloc(sizeof(hc_data_t)); + if (!data) goto ERR_MALLOC; + + /* FIXME Could be NULL thanks to realloc provided size is 0 */ + data->max_size_log = DEFAULT_SIZE_LOG; + data->in_element_size = in_element_size; + data->out_element_size = out_element_size; + data->size = 0; + data->complete = 0; + data->command_id = 0; // TODO this could also be a busy mark in the socket + /* No callback needed in blocking code for instance */ + data->complete_cb = NULL; + + data->buffer = malloc((1 << data->max_size_log) * data->out_element_size); + if (!data->buffer) goto ERR_BUFFER; + + return data; + +ERR_BUFFER: + free(data); +ERR_MALLOC: + return NULL; +} + +void hc_data_free(hc_data_t *data) { + if (data->buffer) free(data->buffer); + free(data); +} + +int hc_data_ensure_available(hc_data_t *data, size_t count) { + size_t new_size_log = + (data->size + count - 1 > 0) ? log2(data->size + count - 1) + 1 : 0; + if (new_size_log > data->max_size_log) { + data->max_size_log = new_size_log; + data->buffer = + realloc(data->buffer, (1 << new_size_log) * data->out_element_size); + if (!data->buffer) return LIBHICNCTRL_FAILURE; + } + return LIBHICNCTRL_SUCCESS; +} + +int hc_data_push_many(hc_data_t *data, const void *elements, size_t count) { + if (hc_data_ensure_available(data, count) < 0) return LIBHICNCTRL_FAILURE; + + memcpy(data->buffer + data->size * data->out_element_size, elements, + count * data->out_element_size); + data->size += count; + return LIBHICNCTRL_SUCCESS; +} + +int hc_data_push(hc_data_t *data, const void *element) { + return hc_data_push_many(data, element, 1); +} + +/** + * + * NOTE: This function make sure there is enough room available in the data + * structure. + */ +u8 *hc_data_get_next(hc_data_t *data) { + if (hc_data_ensure_available(data, 1) < 0) return NULL; + + return data->buffer + data->size * data->out_element_size; +} + +int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data) { + data->complete_cb = cb; + data->complete_cb_data = cb_data; + return LIBHICNCTRL_SUCCESS; +} + +int hc_data_set_complete(hc_data_t *data) { + data->complete = true; + if (data->complete_cb) return data->complete_cb(data, data->complete_cb_data); + return LIBHICNCTRL_SUCCESS; +} + +int hc_data_reset(hc_data_t *data) { + data->size = 0; + return LIBHICNCTRL_SUCCESS; +} + +int hc_data_find(hc_data_t *data, const void *element, cmp_t cmp, + void **found) { + foreach_type(u8, x, data) { + if (cmp(x, element) == 0) { + *found = x; + return LIBHICNCTRL_SUCCESS; + } + }; + *found = NULL; /* this is optional */ + return LIBHICNCTRL_SUCCESS; +} + +/****************************************************************************** + * Control socket + ******************************************************************************/ + +/** + * \brief Parse a connection URL into a sockaddr + * \param [in] url - URL + * \param [out] sa - Resulting struct sockaddr, expected zero'ed. + * \return 0 if parsing succeeded, a negative error value otherwise. + */ +int hc_sock_parse_url(const char *url, struct sockaddr *sa) { + /* FIXME URL parsing is currently not implemented */ + assert(!url); + + /* + * A temporary solution is to inspect the sa_family fields of the passed in + * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP + * connection to localhost. + */ + switch (sa->sa_family) { + case AF_UNSPEC: + case AF_INET: { + struct sockaddr_in *sai = (struct sockaddr_in *)sa; + sai->sin_family = AF_INET; + sai->sin_port = htons(PORT); + sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + break; + } + case AF_INET6: { + struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa; + sai6->sin6_family = AF_INET6; + sai6->sin6_port = htons(PORT); + sai6->sin6_addr = loopback_addr; + break; + } + default: + return LIBHICNCTRL_FAILURE; + } + + return LIBHICNCTRL_SUCCESS; +} + +hc_sock_t *hc_sock_create_url(const char *url) { + hc_sock_t *s = malloc(sizeof(hc_sock_t)); + if (!s) goto ERR_MALLOC; + + s->url = url ? strdup(url) : NULL; + + s->fd = socket(AF_INET, SOCK_STREAM, 0); + if (s->fd < 0) goto ERR_SOCKET; + + if (hc_sock_reset(s) < 0) goto ERR_RESET; + + return s; + +ERR_RESET: + close(s->fd); +ERR_SOCKET: + free(s); +ERR_MALLOC: + return NULL; +} + +hc_sock_t *hc_sock_create(void) { return hc_sock_create_url(NULL); } + +void hc_sock_free(hc_sock_t *s) { + if (s->url) free(s->url); + close(s->fd); + free(s); +} + +int hc_sock_set_nonblocking(hc_sock_t *s) { + return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0); +} + +int hc_sock_connect(hc_sock_t *s) { + struct sockaddr_storage ss = {0}; + + if (hc_sock_parse_url(s->url, (struct sockaddr *)&ss) < 0) goto ERR_PARSE; + + size_t size = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6); + if (connect(s->fd, (struct sockaddr *)&ss, size) < + 0) // sizeof(struct sockaddr)) < 0) + goto ERR_CONNECT; + + return LIBHICNCTRL_SUCCESS; + +ERR_CONNECT: +ERR_PARSE: + return LIBHICNCTRL_FAILURE; +} + +int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen) { + return send(s->fd, msg, msglen, 0); +} + +int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size) { + *buffer = s->buf + s->woff; + *size = RECV_BUFLEN - s->woff; + + return LIBHICNCTRL_SUCCESS; +} + +int hc_sock_recv(hc_sock_t *s, hc_data_t *data) { + int rc; + + /* + * This condition should be ensured to guarantee correct processing of + * messages + */ + assert(RECV_BUFLEN - s->woff > MIN_BUFLEN); + + rc = recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0); + if (rc == 0) { + printf("connection closed\n"); + return LIBHICNCTRL_FAILURE; + /* Connection has been closed */ + // XXX + } + if (rc < 0) { + /* Error occurred */ + printf("error occurred\n"); + // XXX check for EWOULDBLOCK; + // XXX + return LIBHICNCTRL_FAILURE; + } + s->woff += rc; + return LIBHICNCTRL_SUCCESS; +} + +int hc_sock_process(hc_sock_t *s, hc_data_t *data, + int (*parse)(const u8 *src, u8 *dst)) { + int err = 0; + + /* We must have received at least one byte */ + size_t available = s->woff - s->roff; + + while (available > 0) { + if (s->remaining == 0) { + hc_msg_t *msg = (hc_msg_t *)(s->buf + s->roff); + + /* We expect a message header */ + if (available < sizeof(hc_msg_header_t)) break; + + /* Sanity checks (might instead raise warnings) */ + // TODO: sync check ? + assert((msg->hdr.messageType == RESPONSE_LIGHT) || + (msg->hdr.messageType == ACK_LIGHT) || + (msg->hdr.messageType == NACK_LIGHT)); + // assert(msg->hdr.commandID == data->command_id); // FIXME + assert(msg->hdr.seqNum == s->recv_seq++); + + s->remaining = msg->hdr.length; + if (s->remaining == 0) { + /* + * The protocol expects all sequence number to be reset after + * each transaction. We reset before running the callback in + * case it triggers new exchanges. + */ + s->send_seq = HICN_CTRL_SEND_SEQ_INIT; + s->recv_seq = HICN_CTRL_RECV_SEQ_INIT; + + // TODO : check before even sending ? + /* Complete message without payload */ + // TODO : is this correct ? no error code ? + hc_data_set_complete(data); + } + + available -= sizeof(hc_msg_header_t); + s->roff += sizeof(hc_msg_header_t); + } else { + /* We expect the complete payload, or at least a chunk of it */ + size_t num_chunks = available / data->in_element_size; + if (num_chunks == 0) break; + if (num_chunks > s->remaining) num_chunks = s->remaining; + + if (!parse) { + hc_data_push_many(data, s->buf + s->roff, num_chunks); + } else { + int rc; + rc = hc_data_ensure_available(data, num_chunks); + if (rc < 0) return LIBHICNCTRL_FAILURE; + for (int i = 0; i < num_chunks; i++) { + u8 *dst = hc_data_get_next(data); + if (!dst) return LIBHICNCTRL_FAILURE; + + rc = parse(s->buf + s->roff + i * data->in_element_size, dst); + if (rc < 0) err = -1; /* FIXME we let the loop complete (?) */ + data->size++; + } + } + + s->remaining -= num_chunks; + if (s->remaining == 0) { + /* + * The protocol expects all sequence number to be reset after + * each transaction. We reset before running the callback in + * case it triggers new exchanges. + */ + s->send_seq = HICN_CTRL_SEND_SEQ_INIT; + s->recv_seq = HICN_CTRL_RECV_SEQ_INIT; + + hc_data_set_complete(data); + } + + available -= num_chunks * data->in_element_size; + s->roff += num_chunks * data->in_element_size; + } + } + + /* Make sure there is enough remaining space in the buffer */ + if (RECV_BUFLEN - s->woff < AVG_BUFLEN) { + /* + * There should be no overlap provided a sufficiently large BUFLEN, but + * who knows. + */ + memmove(s->buf, s->buf + s->roff, s->woff - s->roff); + s->woff -= s->roff; + s->roff = 0; + } + + return err; +} + +int hc_sock_reset(hc_sock_t *s) { + s->roff = s->woff = 0; + s->send_seq = HICN_CTRL_SEND_SEQ_INIT; + s->recv_seq = HICN_CTRL_RECV_SEQ_INIT; + s->remaining = 0; + return LIBHICNCTRL_SUCCESS; +} + +/****************************************************************************** + * Command-specific structures and functions + ******************************************************************************/ + +typedef int (*HC_PARSE)(const u8 *, u8 *); + +typedef struct { + hc_action_t cmd; + command_id cmd_id; + size_t size_in; + size_t size_out; + HC_PARSE parse; +} hc_command_params_t; + +int hc_execute_command(hc_sock_t *s, hc_msg_t *msg, size_t msg_len, + hc_command_params_t *params, hc_data_t **pdata) { + /* Sanity check */ + switch (params->cmd) { + case ACTION_CREATE: + assert(params->size_in != 0); /* payload repeated */ + assert(params->size_out == 0); + assert(params->parse == NULL); + break; + case ACTION_DELETE: + assert(params->size_in != 0); /* payload repeated */ + assert(params->size_out == 0); + assert(params->parse == NULL); + break; + case ACTION_LIST: + assert(params->size_in != 0); + assert(params->size_out != 0); + assert(params->parse != NULL); + break; + case ACTION_SET: + assert(params->size_in != 0); + assert(params->size_out == 0); + assert(params->parse == NULL); + break; + default: + return LIBHICNCTRL_FAILURE; + } + + hc_sock_reset(s); + + /* XXX data will at least store the result (complete) */ + hc_data_t *data = hc_data_create(params->size_in, params->size_out); + if (!data) goto ERR_DATA; + + hc_sock_send(s, msg, msg_len); + while (!data->complete) { + if (hc_sock_recv(s, data) < 0) break; + // XXX XXX XXX Process data with no resut !!!! XXX XXX XXX + // XXX just return code + // we are receiving the exact same message we have sent with a ACK + // or NACK instead of the command ! + if (hc_sock_process(s, data, params->parse) < 0) { + // ERROR PROCESSING... RESET ? XXX + goto ERR_PROCESS; + } + } + + if (pdata) *pdata = data; + + return LIBHICNCTRL_SUCCESS; + +ERR_PROCESS: + free(data); +ERR_DATA: + return LIBHICNCTRL_FAILURE; +} + +/* /!\ Please update constants in header file upon changes */ +size_t hc_url_snprintf(char *s, size_t size, int family, + ip_address_t *ip_address, u16 port) { + char *cur = s; + int rc; + + /* Other address are currently not supported */ + assert(IS_VALID_FAMILY(family)); + + rc = snprintf(cur, s + size - cur, "inet%c://", + (family == AF_INET) ? '4' : '6'); + if (rc < 0) return rc; + cur += rc; + if (size != 0 && cur >= s + size) return cur - s; + + rc = ip_address_snprintf(cur, s + size - cur, ip_address, family); + if (rc < 0) return rc; + cur += rc; + if (size != 0 && cur >= s + size) return cur - s; + + rc = snprintf(cur, s + size - cur, ":"); + if (rc < 0) return rc; + cur += rc; + if (size != 0 && cur >= s + size) return cur - s; + + rc = snprintf(cur, s + size - cur, "%d", port); + if (rc < 0) return rc; + cur += rc; + if (size != 0 && cur >= s + size) return cur - s; + + return cur - s; +} + +/*----------------------------------------------------------------------------* + * Listeners + *----------------------------------------------------------------------------*/ + +int hc_parse_listener(void *in, hc_listener_t *listener) { + list_listeners_command *cmd = (list_listeners_command *)in; + + if (!IS_VALID_LIST_LISTENERS_TYPE(cmd->encapType)) return LIBHICNCTRL_FAILURE; + + hc_connection_type_t type = map_from_encap_type[cmd->encapType]; + if (type == CONNECTION_TYPE_UNDEFINED) return LIBHICNCTRL_FAILURE; + + if (!IS_VALID_ADDR_TYPE(cmd->addressType)) return LIBHICNCTRL_FAILURE; + + int family = map_from_addr_type[cmd->addressType]; + if (!IS_VALID_FAMILY(family)) return LIBHICNCTRL_FAILURE; + + *listener = (hc_listener_t){ + .conn_id = cmd->connid, + .type = type, + .family = family, + .local_addr = UNION_CAST(cmd->address, ip_address_t), + .local_port = ntohs(cmd->port), + }; + bzero(listener->name, NAME_LEN); + return LIBHICNCTRL_SUCCESS; +} + +typedef struct { + header_control_message hdr; + add_listener_command payload; +} hc_msg_listener_add_t; + +int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) { + if (!IS_VALID_FAMILY(listener->family)) return LIBHICNCTRL_FAILURE; + + if (!IS_VALID_CONNECTION_TYPE(listener->type)) return LIBHICNCTRL_FAILURE; + + hc_msg_listener_add_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = ADD_LISTENER, + .length = 1, + .seqNum = s->send_seq, + }, + .payload = { + .address = + { + .ipv6 = listener->local_addr.v6.as_in6addr, + }, + .port = htons(listener->local_port), + .addressType = (u8)map_to_addr_type[listener->family], + .listenerMode = (u8)map_to_listener_mode[listener->type], + .connectionType = (u8)map_to_connection_type[listener->type], + }}; + strncpy(msg.payload.symbolic, listener->name, NAME_LEN); + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = ADD_LISTENER, + .size_in = sizeof(add_listener_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL); +} + +typedef struct { + header_control_message hdr; +} hc_msg_listener_list_t; + +int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) { + hc_msg_listener_list_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = LIST_LISTENERS, + .length = 0, + .seqNum = s->send_seq, + }, + }; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = LIST_LISTENERS, + .size_in = sizeof(list_listeners_command), + .size_out = sizeof(hc_listener_t), + .parse = (HC_PARSE)hc_parse_listener, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, pdata); +} + +int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) { + return ((l1->type == l2->type) && (l1->family == l2->family) && + (memcmp(&l1->local_addr, &l2->local_addr, sizeof(ip_address_t))) && + (l1->local_port == l2->local_port)) + ? LIBHICNCTRL_SUCCESS + : LIBHICNCTRL_FAILURE; +} + +/* /!\ Please update constants in header file upon changes */ +size_t hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener) { + char local[MAXSZ_HC_URL]; + int rc; + + rc = hc_url_snprintf(local, MAXSZ_HC_URL, listener->family, + &listener->local_addr, listener->local_port); + if (rc < 0) return rc; + + return snprintf(s, size, "%s %s", local, connection_type_str[listener->type]); +} + +/*----------------------------------------------------------------------------* + * Connections + *----------------------------------------------------------------------------*/ + +int hc_parse_connection(void *in, hc_connection_t *connection) { + list_connections_command *cmd = (list_connections_command *)in; + + if (!IS_VALID_LIST_CONNECTIONS_TYPE(cmd->connectionData.connectionType)) + return LIBHICNCTRL_FAILURE; + + hc_connection_type_t type = + map_from_list_connections_type[cmd->connectionData.connectionType]; + if (type == CONNECTION_TYPE_UNDEFINED) return LIBHICNCTRL_FAILURE; + + if (!IS_VALID_LIST_CONNECTIONS_STATE(cmd->state)) return LIBHICNCTRL_FAILURE; + + hc_connection_state_t state = map_from_list_connections_state[cmd->state]; + if (state == CONNECTION_STATE_UNDEFINED) return LIBHICNCTRL_FAILURE; + + if (!IS_VALID_ADDR_TYPE(cmd->connectionData.ipType)) + return LIBHICNCTRL_FAILURE; + + int family = map_from_addr_type[cmd->connectionData.ipType]; + if (!IS_VALID_FAMILY(family)) return LIBHICNCTRL_FAILURE; + + *connection = (hc_connection_t){ + .id = cmd->connid, + .type = type, + .family = family, + .local_addr = UNION_CAST(cmd->connectionData.localIp, ip_address_t), + .local_port = ntohs(cmd->connectionData.localPort), + .remote_addr = UNION_CAST(cmd->connectionData.remoteIp, ip_address_t), + .remote_port = ntohs(cmd->connectionData.remotePort), +#ifdef WITH_POLICY + .desired_state = cmd->connectionData.desired_state, + .tags = cmd->connectionData.tags, +#endif /* WITH_POLICY */ + .state = state, + }; + strncpy(connection->name, cmd->connectionData.symbolic, NAME_LEN); + return LIBHICNCTRL_SUCCESS; +} + +typedef struct { + header_control_message hdr; + add_connection_command payload; +} hc_msg_connection_add_t; + +int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) { + if (!IS_VALID_FAMILY(connection->family)) return LIBHICNCTRL_FAILURE; + + if (!IS_VALID_CONNECTION_TYPE(connection->type)) return LIBHICNCTRL_FAILURE; + + /* TODO assert both local and remote have the right family */ + + hc_msg_connection_add_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = ADD_CONNECTION, + .length = 1, + .seqNum = s->send_seq, + }, + .payload = { + /* we use IPv6 which is the longest address */ + .remoteIp.ipv6 = connection->remote_addr.v6.as_in6addr, + .localIp.ipv6 = connection->local_addr.v6.as_in6addr, + .remotePort = htons(connection->remote_port), + .localPort = htons(connection->local_port), + .ipType = (u8)map_to_addr_type[connection->family], +#ifdef WITH_POLICY + .desired_state = connection->desired_state, + .tags = connection->tags, +#endif /* WITH_POLICY */ + .connectionType = (u8)map_to_connection_type[connection->type], + }}; + strncpy(msg.payload.symbolic, connection->name, NAME_LEN); + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = ADD_CONNECTION, + .size_in = sizeof(add_connection_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL); +} + +typedef struct { + header_control_message hdr; + remove_connection_command payload; +} hc_msg_connection_remove_t; + +int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) { + hc_msg_connection_remove_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = REMOVE_CONNECTION, + .length = 1, + .seqNum = s->send_seq, + }, + }; + strncpy(msg.payload.symbolicOrConnid, connection->name, NAME_LEN); + + hc_command_params_t params = { + .cmd = ACTION_DELETE, + .cmd_id = REMOVE_CONNECTION, + .size_in = sizeof(remove_connection_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL); +} + +#ifdef WITH_POLICY +typedef struct { + header_control_message hdr; + connection_set_state_command payload; +} hc_msg_connection_set_state_t; + +int hc_connection_set_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state) { + hc_msg_connection_set_state_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = CONNECTION_SET_STATE, + .length = 1, + .seqNum = s->send_seq, + }, + .payload = + { + .state = state, + }, + }; + strncpy(msg.payload.symbolicOrConnid, conn_id_or_name, NAME_LEN); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = CONNECTION_SET_STATE, + .size_in = sizeof(connection_set_state_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL); +} +#endif /* WITH_POLICY */ + +typedef struct { + header_control_message hdr; +} hc_msg_connection_list_t; + +int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) { + hc_msg_connection_list_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = LIST_CONNECTIONS, + .length = 0, + .seqNum = s->send_seq, + }, + }; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = LIST_CONNECTIONS, + .size_in = sizeof(list_connections_command), + .size_out = sizeof(hc_connection_t), + .parse = (HC_PARSE)hc_parse_connection, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, pdata); +} + +/* /!\ Please update constants in header file upon changes */ +size_t hc_connection_snprintf(char *s, size_t size, + hc_connection_t *connection) { + char local[MAXSZ_HC_URL]; + char remote[MAXSZ_HC_URL]; + int rc; + + // assert(connection->connection_state) + + rc = hc_url_snprintf(local, MAXSZ_HC_URL, connection->family, + &connection->local_addr, connection->local_port); + if (rc < 0) return rc; + rc = hc_url_snprintf(remote, MAXSZ_HC_URL, connection->family, + &connection->remote_addr, connection->remote_port); + if (rc < 0) return rc; + + return snprintf(s, size, "%s %s %s %s", + connection_state_str[connection->state], local, remote, + connection_type_str[connection->type]); +} + +/*----------------------------------------------------------------------------* + * Routes + *----------------------------------------------------------------------------*/ + +int hc_parse_route(void *in, hc_route_t *route) { + list_routes_command *cmd = (list_routes_command *)in; + + if (!IS_VALID_ADDR_TYPE(cmd->addressType)) return LIBHICNCTRL_FAILURE; + + int family = map_from_addr_type[cmd->addressType]; + if (!IS_VALID_FAMILY(family)) return LIBHICNCTRL_FAILURE; + + *route = (hc_route_t){ + .conn_id = cmd->connid, + .family = family, + .remote_addr = UNION_CAST(cmd->address, ip_address_t), + .len = cmd->len, + .cost = cmd->cost, + }; + bzero(route->conn_name, NAME_LEN); + return LIBHICNCTRL_SUCCESS; +} + +typedef struct { + header_control_message hdr; + add_route_command payload; +} hc_msg_route_add_t; + +int hc_route_create(hc_sock_t *s, hc_route_t *route) { + if (!IS_VALID_FAMILY(route->family)) return LIBHICNCTRL_FAILURE; + + hc_msg_route_add_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = ADD_ROUTE, + .length = 1, + .seqNum = s->send_seq, + }, + .payload = { + /* we use IPv6 which is the longest address */ + .address.ipv6 = route->remote_addr.v6.as_in6addr, + .cost = route->cost, + .addressType = (u8)map_to_addr_type[route->family], + .len = route->len, + }}; + strncpy(msg.payload.symbolicOrConnid, route->conn_name, NAME_LEN); + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = ADD_ROUTE, + .size_in = sizeof(add_route_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL); +} + +typedef struct { + header_control_message hdr; + remove_route_command payload; +} hc_msg_route_remove_t; + +int hc_route_delete(hc_sock_t *s, hc_route_t *route) { + if (!IS_VALID_FAMILY(route->family)) return LIBHICNCTRL_FAILURE; + + hc_msg_route_remove_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = REMOVE_ROUTE, + .length = 1, + .seqNum = s->send_seq, + }, + .payload = { + /* we use IPv6 which is the longest address */ + .address.ipv6 = route->remote_addr.v6.as_in6addr, + .addressType = (u8)map_to_addr_type[route->family], + .len = route->len, + }}; + strncpy(msg.payload.symbolicOrConnid, route->conn_name, NAME_LEN); + + hc_command_params_t params = { + .cmd = ACTION_DELETE, + .cmd_id = REMOVE_ROUTE, + .size_in = sizeof(remove_route_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL); +} + +typedef struct { + header_control_message hdr; +} hc_msg_route_list_t; + +int hc_route_list(hc_sock_t *s, hc_data_t **pdata) { + hc_msg_route_list_t msg = { + .hdr = + { + .messageType = REQUEST_LIGHT, + .commandID = LIST_ROUTES, + .length = 0, + .seqNum = s->send_seq, + }, + }; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = LIST_ROUTES, + .size_in = sizeof(list_routes_command), + .size_out = sizeof(hc_route_t), + .parse = (HC_PARSE)hc_parse_route, + }; + + return hc_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, pdata); +} + +/* /!\ Please update constants in header file upon changes */ +size_t hc_route_snprintf(char *s, size_t size, hc_route_t *route) { + return LIBHICNCTRL_SUCCESS; +} + +/*----------------------------------------------------------------------------* + * Face + *----------------------------------------------------------------------------*/ + +int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) { + const face_t *f = &face->face; + + switch (f->type) { + case FACE_TYPE_HICN_LISTENER: + break; + case FACE_TYPE_TCP_LISTENER: + break; + case FACE_TYPE_UDP_LISTENER: + break; + default: + return LIBHICNCTRL_FAILURE; + } + return LIBHICNCTRL_FAILURE; /* Not implemented */ +} + +int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection) { + const face_t *f = &face->face; + + switch (f->type) { + case FACE_TYPE_HICN: + /* FIXME truncations, collisions, ... */ + *connection = (hc_connection_t){ + .type = CONNECTION_TYPE_HICN, + .family = f->hicn.family, + .local_addr = f->hicn.local_addr, + .local_port = 0, + .remote_addr = f->hicn.remote_addr, + .remote_port = 0, + }; + snprintf(connection->name, NAME_LEN, "%s", f->hicn.netdevice.name); + break; + case FACE_TYPE_TCP: + *connection = (hc_connection_t){ + .type = CONNECTION_TYPE_TCP, + .family = f->hicn.family, + .local_addr = f->tunnel.local_addr, + .local_port = f->tunnel.local_port, + .remote_addr = f->tunnel.remote_addr, + .remote_port = f->tunnel.remote_port, + }; +#ifdef __APPLE__ + snprintf(connection->name, NAME_LEN, "tcp%d", arc4random() & 0xFF); +#else + snprintf(connection->name, NAME_LEN, "tcp%ld", random() & 0xFF); +#endif + break; + case FACE_TYPE_UDP: + *connection = (hc_connection_t){ + .type = CONNECTION_TYPE_UDP, + .family = AF_INET, + .local_addr = f->tunnel.local_addr, + .local_port = f->tunnel.local_port, + .remote_addr = f->tunnel.remote_addr, + .remote_port = f->tunnel.remote_port, + }; +#ifdef __APPLE__ + snprintf(connection->name, NAME_LEN, "udp%d", arc4random() & 0xFF); +#else + snprintf(connection->name, NAME_LEN, "udp%ld", random() & 0xFF); +#endif + printf("Created f %s !\n", connection->name); + break; + default: + return LIBHICNCTRL_FAILURE; + } + + return LIBHICNCTRL_SUCCESS; +} + +int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face) { + switch (connection->type) { + case CONNECTION_TYPE_TCP: + *face = (hc_face_t){ + .id = connection->id, + .face = + { + .type = FACE_TYPE_TCP, + .tunnel = + { + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + .remote_addr = connection->remote_addr, + .remote_port = connection->remote_port, + }, + }, + }; + break; + case CONNECTION_TYPE_UDP: + *face = (hc_face_t){ + .id = connection->id, + .face = + { + .type = FACE_TYPE_UDP, + .tunnel = + { + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + .remote_addr = connection->remote_addr, + .remote_port = connection->remote_port, + }, + }, + }; + break; + case CONNECTION_TYPE_HICN: + *face = (hc_face_t){ + .id = connection->id, + .face = + { + .type = FACE_TYPE_HICN, + .hicn = + { + .family = connection->family, + .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX + .local_addr = connection->local_addr, + .remote_addr = connection->remote_addr, + }, + }, + }; + break; + default: + return LIBHICNCTRL_FAILURE; + } + strncpy(face->name, connection->name, NAME_LEN); + return LIBHICNCTRL_SUCCESS; +} + +int hc_connection_to_local_listener(const hc_connection_t *connection, + hc_listener_t *listener) { + *listener = (hc_listener_t){ + .conn_id = ~0, + .type = connection->type, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + }; + return LIBHICNCTRL_SUCCESS; +} + +int hc_face_create(hc_sock_t *s, hc_face_t *face) { + hc_connection_t connection; + hc_data_t *listeners; + hc_listener_t listener; + hc_listener_t *found; + + switch (face->face.type) { + case FACE_TYPE_HICN: + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + if (hc_face_to_connection(face, &connection) < 0) + return LIBHICNCTRL_FAILURE; + + /* Ensure we have a corresponding local listener */ + if (hc_connection_to_local_listener(&connection, &listener) < 0) + return LIBHICNCTRL_FAILURE; + + /* We might cache results for faster future lookups (at least to + * test existence) */ + if (hc_listener_list(s, &listeners) < 0) return LIBHICNCTRL_FAILURE; + + /* Test */ + if (hc_data_find(listeners, &listener, (cmp_t)hc_listener_cmp, + (void **)&found) < 0) + return LIBHICNCTRL_FAILURE; + + hc_data_free(listeners); + + if (!found) { + /* We need to create the listener if it does not exists */ + if (hc_listener_create(s, &listener) < 0) return LIBHICNCTRL_FAILURE; + } + + if (hc_connection_create(s, &connection) < 0) return LIBHICNCTRL_FAILURE; + + break; + + case FACE_TYPE_HICN_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + if (hc_face_to_listener(face, &listener) < 0) return LIBHICNCTRL_FAILURE; + if (hc_listener_create(s, &listener) < 0) return LIBHICNCTRL_FAILURE; + return LIBHICNCTRL_FAILURE; + break; + default: + return LIBHICNCTRL_FAILURE; + }; + return LIBHICNCTRL_SUCCESS; +} + +int hc_face_delete(hc_sock_t *s, hc_face_t *face) { + /* We currently do not delete the listener */ + hc_connection_t connection; + if (hc_face_to_connection(face, &connection) < 0) return LIBHICNCTRL_FAILURE; + return hc_connection_delete(s, &connection); +} + +int hc_face_list(hc_sock_t *s, hc_data_t **pdata) { + hc_data_t *connection_data; + hc_face_t face; + + if (hc_connection_list(s, &connection_data) < 0) return LIBHICNCTRL_FAILURE; + + hc_data_t *face_data = + hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t)); + foreach_connection(c, connection_data) { + if (hc_connection_to_face(c, &face) < 0) goto ERR; + hc_data_push(face_data, &face); + } + + *pdata = face_data; + hc_data_free(connection_data); + return LIBHICNCTRL_SUCCESS; + +ERR: + hc_data_free(connection_data); + return LIBHICNCTRL_FAILURE; +} + +#ifdef WITH_POLICY +int hc_face_set_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state) { + return hc_connection_set_state(s, conn_id_or_name, state); +} +#endif /* WITH_POLICY */ +/* /!\ Please update constants in header file upon changes */ +size_t hc_face_snprintf(char *s, size_t size, hc_face_t *face) { + return LIBHICNCTRL_SUCCESS; +} + +/*----------------------------------------------------------------------------* + * Cache + *----------------------------------------------------------------------------*/ + +int hc_cache_set_store(hc_sock_t *s, int enabled) { + return LIBHICNCTRL_SUCCESS; +} + +int hc_cache_set_serve(hc_sock_t *s, int enabled) { + return LIBHICNCTRL_SUCCESS; +} + +/*----------------------------------------------------------------------------* + * Punting + *----------------------------------------------------------------------------*/ + +int hc_punting_create(hc_sock_t *s /* XXX */) { return LIBHICNCTRL_SUCCESS; } + +/*----------------------------------------------------------------------------* + * Strategy + *----------------------------------------------------------------------------*/ + +// per prefix +int hc_strategy_set(hc_sock_t *s /* XXX */) { return LIBHICNCTRL_SUCCESS; } + +/*----------------------------------------------------------------------------* + * FIB + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------* + * PIT + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------* + * WLDR + *----------------------------------------------------------------------------*/ + +// per connection +int hc_wldr_set(hc_sock_t *s /* XXX */) { return LIBHICNCTRL_SUCCESS; } + +/*----------------------------------------------------------------------------* + * MAP-Me + *----------------------------------------------------------------------------*/ + +int hc_mapme_set(hc_sock_t *s, int enabled) { return LIBHICNCTRL_SUCCESS; } + +int hc_mapme_set_discovery(hc_sock_t *s, int enabled) { + return LIBHICNCTRL_SUCCESS; +} + +int hc_mapme_set_timescale(hc_sock_t *s, double timescale) { + return LIBHICNCTRL_SUCCESS; +} + +int hc_mapme_set_retx(hc_sock_t *s, double timescale) { + return LIBHICNCTRL_SUCCESS; +} diff --git a/hicn-light/src/hicn/api/api.h b/hicn-light/src/hicn/api/api.h new file mode 100644 index 000000000..e2358167c --- /dev/null +++ b/hicn-light/src/hicn/api/api.h @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file api.h + * \brief hICN control library API + */ + +#ifndef HICNTRL_API +#define HICNTRL_API + +#include +#include + +#include + +/** + * This allows to selectively define convenience types to avoid any collision + * when using the library in conjunction with other frameworks including similar + * defines + */ +#ifdef _HICNTRL_NO_DEFS +#define _HICNTRL_NO_DEF_TYPES +#define _HICNTRL_NO_DEF_IPADDR +#define _HICNTRL_NO_DEF_UNIONCAST +#endif + +#ifndef _HICNTRL_NO_DEF_TYPES +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +#endif /* _HICNTRL_NO_DEF_TYPES */ + +#ifndef _HICNTRL_NO_DEF_IPADDR +#include +#endif /* _HICNTRL_NO_DEF_IPADDR */ + +#ifndef _HICNTRL_NO_DEF_UNIONCAST +/* Helper for avoiding warnings about type-punning */ +#define UNION_CAST(x, destType) \ + (((union { \ + __typeof__(x) a; \ + destType b; \ + })x) \ + .b) +#endif /* _HICNTRL_NO_DEF_UNIONCAST */ + +/****************************************************************************** + * Message helper types and aliases + ******************************************************************************/ + +#define foreach_command \ + _(UNDEFINED) \ + _(CREATE) \ + _(DELETE) \ + _(LIST) \ + _(SET) \ + _(N) + +typedef enum { +#define _(x) ACTION_##x, + foreach_command +#undef _ +} hc_action_t; + +/** + * \brief hICN control message header + */ +typedef struct hc_msg_s hc_msg_t; + +/****************************************************************************** + * Control Data + ******************************************************************************/ + +struct hc_data_s; +typedef int (*data_callback_t)(struct hc_data_s *, void *); + +/** + * \brief Holds the results of an hICN control request + */ +typedef struct hc_data_s { + size_t size; + size_t max_size_log; + size_t in_element_size; + size_t out_element_size; + u8 command_id; /**< Expected message type (should give element size) */ + u8 *buffer; + bool complete; + + /* Callbacks */ + data_callback_t + complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data); + void *complete_cb_data; +} hc_data_t; + +/** + * Create a structure holding the results of an hICN control request. + * \result The newly create data structure. + */ +hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size); + +/** + * Free a structure holding the results of an hICN control request. + * \param [in] data - The data structure to free. + */ +void hc_data_free(hc_data_t *data); + +/** + * \brief Adds many new results at the end of the data structure, eventually + * allocating buffer space for it. + * \param [in] data - The data structure to which to add elements. + * \param [in] elements - The array of elements to add. + * \param [in] count - The number of elements to add. + * \return Error code + * + * NOTE: The size of the element should match the one declared at structure + * initialization. + */ +int hc_data_push_many(hc_data_t *data, const void *elements, size_t count); + +/** + * \brief Adds a new result at the end of the data structure, eventually + * allocating buffer space for it. + * \param [in] data - The data structure to which to add an element. + * \param [in] element - The element to add + * \return Error code + * + * NOTE: The size of the element should match the one declared at structure + * initialization. + */ +int hc_data_push(hc_data_t *data, const void *element); + +/** + * \brief Configure a callback (along with private data) to be called upon + * completion of a request + * \param [in] data - hICN control data + * \param [in] cb - Callback function + * \param [in] cb_data - Callback private data + */ +int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data); + +/** + * \brief Mark the data structure as complete. + * \param [in] data - The data structure to which to add an element. + * \return The error code resulting from callback execution if any. 0 is + * returned if the callback executed successfully, or if no callback were + * defined. + */ +int hc_data_set_complete(hc_data_t *data); + +/** + * \brief Reset the data structure holding control data + * \param [in] data - hICN control data + * \return Error code + */ +int hc_data_reset(hc_data_t *data); + +/** + * \brief Find en element in the data structure + * \param [in] data - The data structure in which to find + * \param [in] element - The element to find + * \param [in] cmp - The element compare function + * \param [out] found - A pointer to the element, or NULL if not found. + * \return Error code + */ +int hc_data_find(hc_data_t *data, const void *element, cmp_t cmp, void **found); + +/****************************************************************************** + * Control socket + ******************************************************************************/ + +/* This should be at least equal to the maximum packet size */ +#define RECV_BUFLEN 8192 + +/** + * \brief Holds the state of an hICN control socket + */ +typedef struct { + char *url; + int fd; + u32 seq; + + /* Partial receive buffer */ + u8 buf[RECV_BUFLEN]; + size_t roff; /**< Read offset */ + size_t woff; /**< Write offset */ + + /* + * Because received messages are potentially unbounded in size, we might not + * guarantee that we can store a full packet before processing it. We must + * implement a very simple state machine remembering the current parsing + * status in order to partially process the packet. + */ + size_t remaining; + u32 send_id; + u32 send_seq; + u32 recv_seq; +} hc_sock_t; + +/** + * \brief Create an hICN control socket using the specified URL. + * \param [in] url - The URL to connect to. + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create_url(const char *url); + +/** + * \brief Create an hICN control socket using the default connection type. + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create(void); + +/** + * \brief Frees an hICN control socket + */ +void hc_sock_free(hc_sock_t *s); + +/** + * \brief Sets the socket as non-blocking + * \return Error code + */ +int hc_sock_set_nonblocking(hc_sock_t *s); + +/** + * \brief Connect the socket + * \return Error code + */ +int hc_sock_connect(hc_sock_t *s); + +/** + * \brief Return the offset and size of available buffer space + * \param [in] sock - hICN control socket + * \param [out] buffer - Offset in buffer + * \param [out] size - Remaining size + * \return Error code + */ +int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size); + +/** + * \brief Write/read iexchance on the control socket (internal helper function) + * \param [in] sock - hICN control socket + * \param [in] msg - Message to send + * \param [in] msglen - Length of the message to send + * \return Error code + */ +int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen); + +/** + * \brief Helper for reading socket contents + * \param [in] sock - hICN control socket + * \param [in] data - Result data buffer + * \param [in] parse - Parse function to convert remote types into lib native + * types, or NULL not to perform any translation. + * \return Error code + */ +int hc_sock_recv(hc_sock_t *s, hc_data_t *data); + +/** + * \brief Processing data received by socket + * \param [in] sock - hICN control socket + * \param [in] data - Result data buffer + * \param [in] parse - Parse function to convert remote types into lib native + * types, or NULL not to perform any translation. + * \return Error code + */ +int hc_sock_process(hc_sock_t *s, hc_data_t *data, + int (*parse)(const u8 *src, u8 *dst)); + +/** + * \brief Reset the state of the sock (eg. to handle a reconnecton) + * \param [in] sock - hICN control socket + * \return Error code + */ +int hc_sock_reset(hc_sock_t *s); + +/****************************************************************************** + * Command-specific structures and functions + ******************************************************************************/ + +/* + * The following definitions are organized by sections each dealing with a + * specific object being manipulated. All follow a similar structure. + * + * TYPE DEFINITIONS AND ALIASES + * + * We redefine command struct: + * - for uniformization + * - to use enum instead of type specifiers more appropriate for packet format + * - to use more flexible types such as for manipulating IP addresses + * - host endianness + * - more intuitive field name, ordering, consistency, and hierarchy removal + * - to have command types in between add/list/... commands + * + * COMMAND IMPLEMENTATION + * + * All commands return information in a common format + * + * TODO describe + explain for commands with only return code. + * + * RETURN DATA FIXME + * + * \param [out] pdata - Pointer to the structure storing the results of the call + * (NULL if no data has been received). If the pointer is NULL, no result will + * be stored and only the error code will be exposed to the caller. It is + * expected that the caller frees this structure using hc_data_free() after + * usage. + * \see hc_data_free. + * + * PARSING + * + * While this is not made mandatory by the library, the returned data can be + * converted to the library's own data structures as described before. + * + * ITERATORS + * + * Macros are defined to facilitate iteration on the returned data structures. + */ + +#ifndef SPACES +#define SPACES(x) x +#endif +#ifndef SPACE +#define SPACE SPACES(1) +#endif +#ifndef NULLTERM +#define NULLTERM 1 +#endif + +#define NAME_LEN 16 /* NULL-terminated right ? */ +#define MAXSZ_HC_NAME_ NAME_LEN +#define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM + +#define MAXSZ_HC_ID_ 10 /* Number of digits for MAX_INT */ +#define MAXSZ_HC_ID MAXSZ_HC_ID_ + NULLTERM + +#define MAXSZ_HC_PROTO_ 8 /* inetX:// */ +#define MAXSZ_HC_PROTO MAXSZ_HC_PROTO_ + NULLTERM + +#define MAXSZ_HC_URL4_ MAXSZ_HC_PROTO_ + MAXSZ_IP4_ADDRESS_ + MAXSZ_PORT_ +#define MAXSZ_HC_URL6_ MAXSZ_HC_PROTO_ + MAXSZ_IP6_ADDRESS_ + MAXSZ_PORT_ +#define MAXSZ_HC_URL_ MAXSZ_HC_URL6_ +#define MAXSZ_HC_URL4 MAXSZ_HC_URL4_ + NULLTERM +#define MAXSZ_HC_URL6 MAXSZ_HC_URL6_ + NULLTERM +#define MAXSZ_HC_URL MAXSZ_HC_URL_ + NULLTERM + +size_t hc_url_snprintf(char *s, size_t size, int family, + ip_address_t *ip_address, u16 port); + +#define foreach_type(TYPE, VAR, data) \ + for (TYPE *VAR = (TYPE *)data->buffer; \ + VAR < (TYPE *)(data->buffer + data->size * data->out_element_size); \ + VAR++) + +/** + * New type is defined to reconciliate different enum for add and list. + * Also, values not implemented have been removed for clarity. + */ +#define foreach_connection_type \ + _(UNDEFINED) \ + _(TCP) \ + _(UDP) \ + _(HICN) \ + _(N) + +typedef enum { +#define _(x) CONNECTION_TYPE_##x, + foreach_connection_type +#undef _ +} hc_connection_type_t; + +#define MAXSZ_HC_CONNECTION_TYPE_ 9 +#define MAXSZ_HC_CONNECTION_TYPE MAXSZ_HC_CONNECTION_TYPE_ + NULLTERM + +extern const char *connection_type_str[]; + +hc_connection_type_t connection_type_from_str(const char *str); + +#define foreach_connection_state \ + _(UNDEFINED) \ + _(UP) \ + _(DOWN) \ + _(N) + +typedef enum { +#define _(x) CONNECTION_STATE_##x, + foreach_connection_state +#undef _ +} hc_connection_state_t; + +#define MAXSZ_HC_CONNECTION_STATE_ 9 +#define MAXSZ_HC_CONNECTION_STATE MAXSZ_HC_CONNECTION_STATE_ + NULLTERM + +extern const char *connection_state_str[]; + +typedef int (*HC_PARSE)(const u8 *, u8 *); + +/*----------------------------------------------------------------------------* + * Listeners + *----------------------------------------------------------------------------*/ + +typedef struct { + char name[NAME_LEN]; /* K.w */ // XXX clarify what used for + u32 conn_id; /* Kr. */ + hc_connection_type_t type; /* .rw */ + int family; /* .rw */ + ip_address_t local_addr; /* .rw */ + u16 local_port; /* .rw */ +} hc_listener_t; + +int hc_parse_listener(void *in, hc_listener_t *listener); + +int hc_listener_create(hc_sock_t *s, hc_listener_t *listener); +// XXX int hc_listener_delete(hc_sock_t * s, hc_listener_t * listener); +int hc_listener_list(hc_sock_t *s, hc_data_t **pdata); + +#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data) + +#define MAXSZ_HC_LISTENER_ MAXSZ_HC_URL_ + SPACE + MAXSZ_HC_CONNECTION_TYPE_ +#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM + +int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2); + +size_t hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener); + +/*----------------------------------------------------------------------------* + * Connections + *----------------------------------------------------------------------------*/ + +typedef struct { + u32 id; /* Kr. */ + char name[NAME_LEN]; /* K.w */ + hc_connection_type_t type; /* .rw */ + int family; /* .rw */ + ip_address_t local_addr; /* .rw */ + u16 local_port; /* .rw */ + ip_address_t remote_addr; /* .rw */ + u16 remote_port; /* .rw */ +#ifdef WITH_POLICY + face_state_t desired_state; /* .rw */ + face_tags_t tags; /* .rw */ +#endif /* WITH_POLICY */ + hc_connection_state_t state; /* .r. */ +} hc_connection_t; + +int hc_parse_connection(void *in, hc_connection_t *connection); + +int hc_connection_create(hc_sock_t *s, hc_connection_t *connection); +int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection); +/* +int hc_connection_remove_by_id(hc_sock_t * s, char * name); +int hc_connection_remove_by_name(hc_sock_t * s, char * name); +*/ +#ifdef WITH_POLICY +int hc_connection_set_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state); +#endif /* WITH_POLICY */ +int hc_connection_list(hc_sock_t *s, hc_data_t **pdata); + +#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data) + +#define MAXSZ_HC_CONNECTION_ \ + MAXSZ_HC_CONNECTION_STATE_ + 2 * MAXSZ_HC_URL_ + MAXSZ_HC_CONNECTION_TYPE_ + \ + SPACES(3) +#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM + +size_t hc_connection_snprintf(char *s, size_t size, + hc_connection_t *connection); + +/*----------------------------------------------------------------------------* + * Routes + *----------------------------------------------------------------------------*/ + +typedef struct { + u8 conn_id; /* Kr. */ + char conn_name[NAME_LEN]; /* K.w */ + int family; /* Krw */ + ip_address_t remote_addr; /* krw */ + u8 len; /* krw */ + u16 cost; /* .rw */ +} hc_route_t; + +int hc_parse_route(void *in, hc_route_t *route); + +int hc_route_create(hc_sock_t *s, hc_route_t *route); +int hc_route_delete(hc_sock_t *s, hc_route_t *route); +int hc_route_list(hc_sock_t *s, hc_data_t **pdata); + +#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data) + +#define MAXSZ_HC_ROUTE_ 0 +#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM + +size_t hc_route_snprintf(char *s, size_t size, hc_route_t *route); + +/*----------------------------------------------------------------------------* + * Faces + * + * A face is an abstraction introduced by the control library to abstract the + * forwarder implementation details. It encompasses connections and listeners + * and ensures the right dependencies are enforced, eg that we always have a + * listener when a connection is created. + * + *----------------------------------------------------------------------------*/ + +typedef struct { + u32 id; + char name[NAME_LEN]; + face_t face; // or embed ? + // face_id_t parent; /* Pointer from connection to listener */ +} hc_face_t; + +int hc_face_create(hc_sock_t *s, hc_face_t *face); +int hc_face_delete(hc_sock_t *s, hc_face_t *face); +int hc_face_list(hc_sock_t *s, hc_data_t **pdata); + +#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data) + +#define MAXSZ_HC_FACE_ 0 +#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM + +size_t hc_face_snprintf(char *s, size_t size, hc_face_t *face); + +/*----------------------------------------------------------------------------* + * Cache + *----------------------------------------------------------------------------*/ + +int hc_cache_set_store(hc_sock_t *s, int enabled); +int hc_cache_set_serve(hc_sock_t *s, int enabled); + +/*----------------------------------------------------------------------------* + * Punting + *----------------------------------------------------------------------------*/ + +int hc_punting_create(hc_sock_t *s /* XXX */); + +/*----------------------------------------------------------------------------* + * Strategy + *----------------------------------------------------------------------------*/ + +// per prefix +int hc_strategy_set(hc_sock_t *s /* XXX */); + +/*----------------------------------------------------------------------------* + * FIB + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------* + * PIT + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------* + * WLDR + *----------------------------------------------------------------------------*/ + +// per connection +int hc_wldr_set(hc_sock_t *s /* XXX */); + +/*----------------------------------------------------------------------------* + * MAP-Me + *----------------------------------------------------------------------------*/ + +int hc_mapme_set(hc_sock_t *s, int enabled); +int hc_mapme_set_discovery(hc_sock_t *s, int enabled); +int hc_mapme_set_timescale(hc_sock_t *s, double timescale); +int hc_mapme_set_retx(hc_sock_t *s, double timescale); + +#endif /* HICNTRL_API */ diff --git a/hicn-light/src/hicn/api/commands.h b/hicn-light/src/hicn/api/commands.h new file mode 100644 index 000000000..c26ac0172 --- /dev/null +++ b/hicn-light/src/hicn/api/commands.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#endif + +#include +#include + +#ifdef WITH_POLICY +#include +#endif /* WITH_POLICY */ + +typedef struct in6_addr ipv6_addr_t; +typedef uint32_t ipv4_addr_t; + +union commandAddr { + ipv4_addr_t ipv4; + ipv6_addr_t ipv6; +}; + +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_ROUTE, + CACHE_STORE, + CACHE_SERVE, + CACHE_CLEAR, + SET_STRATEGY, + SET_WLDR, + ADD_PUNTING, + LIST_LISTENERS, + MAPME_ENABLE, + MAPME_DISCOVERY, + MAPME_TIMESCALE, + MAPME_RETX, +#ifdef WITH_POLICY + CONNECTION_SET_STATE, +#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[16]; + // char interfaceName[16]; + union commandAddr address; + uint16_t port; + // uint16_t etherType; + uint8_t addressType; + uint8_t listenerMode; + uint8_t connectionType; +} add_listener_command; + +// SIZE=40 + +//========== [01] ADD CONNECTION ========== + +typedef struct { + char symbolic[16]; + union commandAddr remoteIp; + union commandAddr localIp; + uint16_t remotePort; + uint16_t localPort; + uint8_t ipType; + uint8_t connectionType; +#ifdef WITH_POLICY + face_state_t + desired_state; /* This is the desired state, not the actual state */ + face_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; +} list_connections_command; + +// SIZE=64 + +//========== [03] ADD ROUTE ========== + +typedef struct { + char symbolicOrConnid[16]; + union commandAddr address; + uint16_t cost; + uint8_t addressType; + uint8_t len; +} add_route_command; + +// SIZE=36 + +//========== [04] LIST ROUTE ========== + +typedef struct { + union commandAddr 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[16]; +} remove_connection_command; + +// SIZE=16 + +//========== [06] REMOVE ROUTE ========== + +typedef struct { + char symbolicOrConnid[16]; + union commandAddr address; + uint8_t addressType; + uint8_t len; +} remove_route_command; + +// SIZE=36 + +//========== [07] CACHE STORE ========== + +typedef struct { + uint8_t activate; +} cache_store_command; + +// SIZE=1 + +//========== [08] CACHE SERVE ========== + +typedef struct { + uint8_t activate; +} cache_serve_command; + +// SIZE=1 + +//========== [09] SET STRATEGY ========== + +typedef enum { + SET_STRATEGY_LOADBALANCER, + SET_STRATEGY_RANDOM, + SET_STRATEGY_RANDOM_PER_DASH_SEGMENT, + SET_STRATEGY_LOADBALANCER_WITH_DELAY, + SET_STRATEGY_LOADBALANCER_BY_RATE, + SET_STRATEGY_LOADBALANCER_BEST_ROUTE, + LAST_STRATEGY_VALUE +} strategy_type; + +typedef struct { + union commandAddr address; + uint8_t strategyType; + uint8_t addressType; + uint8_t len; +} set_strategy_command; + +// SIZE=20 + +//========== [11] SET WLDR ========== + +typedef struct { + char symbolicOrConnid[16]; + uint8_t activate; +} set_wldr_command; + +// SIZE=17 + +//========== [12] ADD PUNTING ========== + +typedef struct { + char symbolicOrConnid[16]; + union commandAddr address; + uint8_t addressType; + uint8_t len; +} add_punting_command; + +// SIZE=36 + +//========== [13] LIST LISTENER ========== + +typedef struct { + union commandAddr address; + uint32_t connid; + uint16_t port; + uint8_t addressType; + uint8_t encapType; +} list_listeners_command; + +// SIZE=24 + +//========== [14] MAPME ========== + +// (enable/discovery/timescale/retx) + +typedef struct { + uint8_t activate; +} mapme_activator_command; + +// SIZE=1 + +typedef struct { + uint32_t timePeriod; +} mapme_timing_command; + +// SIZE=1 + +//========== POLICY-RELATED FUNCTIONS ========== + +#ifdef WITH_POLICY +typedef struct { + char symbolicOrConnid[16]; + face_state_t state; +} connection_set_state_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_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); +#ifdef WITH_POLICY + case CONNECTION_SET_STATE: + return sizeof(connection_set_state_command); +#endif /* WITH_POLICY */ + case LAST_COMMAND_VALUE: + return 0; + default: + return 0; + } +} +#endif diff --git a/hicn-light/src/hicn/api/face.h b/hicn-light/src/hicn/api/face.h new file mode 100644 index 000000000..6caf8b9f7 --- /dev/null +++ b/hicn-light/src/hicn/api/face.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file face.h + * \brief Face abstraction + */ +#ifndef HICN_FACE_H +#define HICN_FACE_H + +#ifndef SPACES +#define SPACES(x) x +#endif +#ifndef SPACE +#define SPACE 1 +#endif +#ifndef NULLTERM +#define NULLTERM 1 +#endif + +#include +#include + +/* Netdevice type */ + +#include // IFNAMSIZ + +#define foreach_netdevice_type \ + _(UNDEFINED) \ + _(WIRED) \ + _(WIFI) \ + _(CELLULAR) \ + _(VPN) \ + _(N) + +#define MAXSZ_NETDEVICE_TYPE_ 9 +#define MAXSZ_NETDEVICE_TYPE MAXSZ_NETDEVICE_TYPE_ + NULLTERM + +typedef enum { +#define _(x) x, + foreach_netdevice_type +#undef _ +} netdevice_type_t; + +extern const char* netdevice_type_str[]; + +/* Netdevice */ + +typedef struct { + u32 index; + char name[IFNAMSIZ]; +} netdevice_t; + +#define NETDEVICE_UNDEFINED_INDEX 0 + +/* Face state */ + +#define foreach_face_state \ + _(UNDEFINED) \ + _(PENDING_UP) \ + _(UP) \ + _(PENDING_DOWN) \ + _(DOWN) \ + _(ERROR) \ + _(N) + +#define MAXSZ_FACE_STATE_ 12 +#define MAXSZ_FACE_STATE MAXSZ_FACE_STATE_ + 1 + +typedef enum { +#define _(x) FACE_STATE_##x, + foreach_face_state +#undef _ +} face_state_t; + +extern const char* face_state_str[]; + +/* Face type */ + +#define foreach_face_type \ + _(UNDEFINED) \ + _(HICN) \ + _(HICN_LISTENER) \ + _(TCP) \ + _(TCP_LISTENER) \ + _(UDP) \ + _(UDP_LISTENER) \ + _(N) + +#define MAXSZ_FACE_TYPE_ 13 +#define MAXSZ_FACE_TYPE MAXSZ_FACE_TYPE_ + 1 + +typedef enum { +#define _(x) FACE_TYPE_##x, + foreach_face_type +#undef _ +} face_type_t; + +extern const char* face_type_str[]; + +#define MAXSZ_FACE_ MAXSZ_FACE_TYPE_ + 2 * MAXSZ_IP_ADDRESS + 2 * MAXSZ_PORT + 9 +#define MAXSZ_FACE MAXSZ_FACE_ + 1 + +/* Face tag */ + +/** + * \brief Tags associated to faces, useful to implement policies. + * + * NOTE + * - These tags should be shared with the forwarder, and might in fact be + * defined in a common library. + * - We start with a very simple implementation where all tags are not + * categorized and stored within the same bitfield. + */ +#define foreach_face_tag \ + _(UNDEFINED) \ + /* Connection type */ \ + _(WIRED) \ + _(WIFI) \ + _(LTE) \ + _(VPN) \ + /* Connection security */ \ + _(TRUSTED_NETWORK) \ + _(UNTRUSTED_NETWORK) \ + _(N) + +#define MAXSZ_FACE_TAG_ 17 +#define MAXSZ_FACE_TAG MAXSZ_FACE_TAG_ + 1 + +typedef enum { +#define _(x) FACE_TAG_##x, + foreach_face_tag +#undef _ +} face_tag_t; + +extern const char* face_tag_str[]; + +typedef int face_tags_t; + +static inline void face_tags_add(face_tags_t* tags, face_tag_t tag) { + *tags |= tag; +} + +static inline void face_tags_remove(face_tags_t* tags, face_tag_t tag) { + *tags &= ~tag; +} + +static inline int face_tags_has(face_tags_t tags, face_tag_t tag) { + return tags & tag; +} + +#define FACE_TAGS_EMPTY 0 + +/* Face */ + +typedef struct { + face_type_t type; + union { + struct { + int family; + netdevice_t netdevice; + ip_address_t local_addr; + ip_address_t remote_addr; + } hicn; + struct { + int family; + ip_address_t local_addr; + u16 local_port; + ip_address_t remote_addr; + u16 remote_port; + } tunnel; + }; + int tags; /**< \see face_tag_t */ +} face_t; + +int face_initialize(face_t* face); +int face_initialize_udp(face_t* face, const ip_address_t* local_addr, + u16 local_port, const ip_address_t* remote_addr, + u16 remote_port, int family); +face_t* face_initialize_udp_sa(face_t* face, const struct sockaddr* local_addr, + const struct sockaddr* remote_addr); + +face_t* face_create(); +face_t* face_create_udp(const ip_address_t* local_addr, u16 local_port, + const ip_address_t* remote_addr, u16 remote_port, + int family); +face_t* face_create_udp_sa(const struct sockaddr* local_addr, + const struct sockaddr* remote_addr); + +int face_finalize(face_t* face); + +void face_free(face_t* face); + +typedef bool (*face_cmp_t)(const face_t* f1, const face_t* f2); + +bool face_cmp(const face_t* f1, const face_t* f2); +hash_t face_hash(const face_t* face); + +size_t face_snprintf(char* s, size_t size, const face_t* face); + +#endif /* HICN_FACE_H */ diff --git a/hicn-light/src/hicn/api/fib_policy.h b/hicn-light/src/hicn/api/fib_policy.h new file mode 100644 index 000000000..f5f82295d --- /dev/null +++ b/hicn-light/src/hicn/api/fib_policy.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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_policy.h + * \brief FIB policy description to be stored in FIB entries. + */ +#ifndef HICN_FIB_POLICY_H +#define HICN_FIB_POLICY_H + +#include + +typedef struct { + face_tags_t allow; + face_tags_t prohibit; + face_tags_t prefer; + face_tags_t avoid; +} fib_policy_t; + +static const fib_policy_t FIB_POLICY_NONE = { + .allow = FACE_TAGS_EMPTY, + .prohibit = FACE_TAGS_EMPTY, + .prefer = FACE_TAGS_EMPTY, + .avoid = FACE_TAGS_EMPTY, +}; + +#endif /* HICN_FIB_POLICY_H */ diff --git a/hicn-light/src/hicn/api/ip_address.h b/hicn-light/src/hicn/api/ip_address.h new file mode 100644 index 000000000..b58981d85 --- /dev/null +++ b/hicn-light/src/hicn/api/ip_address.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file ip_address.h + * \brief IP address type support + */ +#ifndef IP_ADDRESS_H +#define IP_ADDRESS_H + +#include // inet_ntop +#ifdef __APPLE__ +#include +#define __bswap_constant_32(x) OSSwapInt32(x) +#include +#else +#include +#endif +#include +#include // struct addrinfo +#include // INET*_ADDRSTRLEN, IN*ADDR_LOOPBACK +#include +#include // memset + +#include + +#define bytes_to_bits(x) (x * 8) +#define IPV6_ADDR_LEN 16 /* bytes */ +#define IPV4_ADDR_LEN 4 /* bytes */ +#define IPV6_ADDR_LEN_BITS bytes_to_bits(IPV6_ADDR_LEN) +#define IPV4_ADDR_LEN_BITS bytes_to_bits(IPV4_ADDR_LEN) + +#define IP_MAX_ADDR_LEN IPV6_ADDR_LEN + +#define DUMMY_PORT 1234 + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef union { + union { + struct in_addr as_inaddr; + u8 as_u8[4]; + u16 as_u16[2]; + u32 as_u32; + } v4; + union { + struct in6_addr as_in6addr; + u8 as_u8[16]; + u16 as_u16[8]; + u32 as_u32[4]; + u64 as_u64[2]; + } v6; + u8 buffer[IP_MAX_ADDR_LEN]; + u8 as_u8[IP_MAX_ADDR_LEN]; + u16 as_u16[IP_MAX_ADDR_LEN >> 1]; + u32 as_u32[IP_MAX_ADDR_LEN >> 2]; + u64 as_u64[IP_MAX_ADDR_LEN >> 3]; +} ip_address_t; + +#define MAXSZ_IP4_ADDRESS_ INET_ADDRSTRLEN - 1 +#define MAXSZ_IP6_ADDRESS_ INET6_ADDRSTRLEN - 1 +#define MAXSZ_IP_ADDRESS_ MAXSZ_IP6_ADDRESS_ +#define MAXSZ_IP4_ADDRESS MAXSZ_IP4_ADDRESS_ + 1 +#define MAXSZ_IP6_ADDRESS MAXSZ_IP6_ADDRESS_ + 1 +#define MAXSZ_IP_ADDRESS MAXSZ_IP_ADDRESS_ + 1 + +/* No htonl() with const */ +static const ip_address_t IPV4_LOOPBACK = { +#if __BYTE_ORDER == __LITTLE_ENDIAN + .v4.as_inaddr.s_addr = __bswap_constant_32(INADDR_LOOPBACK), +#else + .v4.as_inaddr.s_addr = INADDR_LOOPBACK, +#endif +}; + +static const ip_address_t IPV6_LOOPBACK = { + .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT, +}; + +#define MAX_PORT 1 << (8 * sizeof(u16)) +#define IS_VALID_PORT(x) ((x > 0) && (x < MAX_PORT)) + +#define MAXSZ_PORT_ 5 +#define MAXSZ_PORT MAXSZ_PORT_ + 1 + +#define IS_VALID_FAMILY(x) ((x == AF_INET) || (x == AF_INET6)) + +static inline int ip_address_get_family(const char *ip_address) { + struct addrinfo hint, *res = NULL; + int rc; + + memset(&hint, '\0', sizeof hint); + + hint.ai_family = PF_UNSPEC; + hint.ai_flags = AI_NUMERICHOST; + + rc = getaddrinfo(ip_address, NULL, &hint, &res); + if (rc) { + return -1; + } + rc = res->ai_family; + freeaddrinfo(res); + return rc; +} + +static inline int ip_address_len(const ip_address_t *ip_address, int family) { + return (family == AF_INET6) ? IPV6_ADDR_LEN + : (family == AF_INET) ? IPV4_ADDR_LEN : 0; +} + +static inline int ip_address_ntop(const ip_address_t *ip_address, char *dst, + const size_t len, int family) { + const char *s = inet_ntop(family, ip_address->buffer, dst, len); + return (s ? 1 : -1); +} + +/* + * Parse ip addresses in presentation format, or prefixes (in bits, separated by + * a slash) + */ +static inline int ip_address_pton(const char *ip_address_str, + ip_address_t *ip_address) { + int pton_fd; +#ifdef IP_ADDRESS_PREFIX + char *p; + char *eptr; + u32 dst_len; +#endif /* IP_ADDRESS_PREFIX */ + char *addr = strdup(ip_address_str); + int family; + +#ifdef IP_ADDRESS_PREFIX + p = strchr(addr, '/'); + if (!p) { + dst_len = 0; // until we get the ip address family + } else { + dst_len = strtoul(p + 1, &eptr, 10); + *p = 0; + } +#endif /* IP_ADDRESS_PREFIX */ + + family = ip_address_get_family(addr); + + switch (family) { + case AF_INET6: +#ifdef IP_ADDRESS_PREFIX + if (dst_len > IPV6_ADDR_LEN_BITS) goto ERR; +#endif /* IP_ADDRESS_PREFIX */ + pton_fd = inet_pton(AF_INET6, addr, &ip_address->buffer); + break; + case AF_INET: +#ifdef IP_ADDRESS_PREFIX + if (dst_len > IPV4_ADDR_LEN_BITS) goto ERR; +#endif /* IP_ADDRESS_PREFIX */ + pton_fd = inet_pton(AF_INET, addr, &ip_address->buffer); + break; + default: + goto ERR; + } + + // 0 = not in presentation format + // < 0 = other error (use perror) + if (pton_fd <= 0) { + goto ERR; + } + + return 1; +ERR: + free(addr); + return -1; +} + +static inline int ip_address_snprintf(char *s, size_t size, + const ip_address_t *ip_address, + int family) { + size_t len = family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; + const char *rc = inet_ntop(family, ip_address->buffer, s, len); + return rc ? strlen(rc) : -1; +} + +static inline int ip_address_to_sockaddr(const ip_address_t *ip_address, + struct sockaddr *sockaddr_address, + int family) { + struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)sockaddr_address; + struct sockaddr_in *tmp4 = (struct sockaddr_in *)sockaddr_address; + + switch (family) { + case AF_INET6: + tmp6->sin6_family = AF_INET6; + tmp6->sin6_port = DUMMY_PORT; + tmp6->sin6_scope_id = 0; + memcpy(&tmp6->sin6_addr, ip_address->buffer, IPV6_ADDR_LEN); + break; + case AF_INET: + tmp4->sin_family = AF_INET; + tmp4->sin_port = DUMMY_PORT; + memcpy(&tmp4->sin_addr, ip_address->buffer, IPV4_ADDR_LEN); + break; + default: + return -1; + } + + return 1; +} + +#endif /* IP_ADDRESS_H */ diff --git a/hicn-light/src/hicn/api/token.h b/hicn-light/src/hicn/api/token.h new file mode 100644 index 000000000..0c5541ba8 --- /dev/null +++ b/hicn-light/src/hicn/api/token.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Token concatenation */ + +/* + * 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 + +/* + * Concatenate preprocessor tokens A and B after macro-expanding them. + */ +#define PPCAT(A, B) PPCAT_NX(A, B) + +/* Token stringification */ + +/* + * Turn A into a string literal without expanding macro definitions + * (however, if invoked from a macro, macro arguments are expanded). + */ +#define STRINGIZE_NX(A) #A + +/* + * Turn A into a string literal after macro-expanding it. + */ +#define STRINGIZE(A) STRINGIZE_NX(A) diff --git a/hicn-light/src/hicn/api/types.h b/hicn-light/src/hicn/api/types.h new file mode 100644 index 000000000..1efab5e77 --- /dev/null +++ b/hicn-light/src/hicn/api/types.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 TYPES +#define TYPES + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +/* Helper for avoiding warnings about type-punning */ +#define UNION_CAST(x, destType) \ + (((union { \ + __typeof__(x) a; \ + destType b; \ + })x) \ + .b) + +typedef unsigned int hash_t; + +typedef int (*cmp_t)(const void *, const void *); + +/* Enums */ + +#define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME##_UNDEFINED) && (x < NAME##_N)) + +#endif /* TYPES */ diff --git a/hicn-light/src/hicn/command_line/CMakeLists.txt b/hicn-light/src/hicn/command_line/CMakeLists.txt new file mode 100644 index 000000000..16c23dc5c --- /dev/null +++ b/hicn-light/src/hicn/command_line/CMakeLists.txt @@ -0,0 +1,2 @@ +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 new file mode 100644 index 000000000..b53e610a1 --- /dev/null +++ b/hicn-light/src/hicn/command_line/controller/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 +) + +build_executable(${HICN_LIGHT_CONTROL} + SOURCES ${CONTROLLER_SRC} + LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES} + DEPENDS hicn-light + COMPONENT hicn-light +) diff --git a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c new file mode 100644 index 000000000..9ba155ede --- /dev/null +++ b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +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_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)}; + +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 **keystorePath, + char **keystorePassword, PARCList *commandList) { + static struct option longFormOptions[] = { + {"help", no_argument, 0, 'h'}, + {"keystore", required_argument, 0, 'k'}, + {"password", 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, "hk:p:", longFormOptions, &optionIndex); + + // Detect the end of the options. + if (c == -1) { + break; + } + + switch (c) { + case 'k': + *keystorePath = optarg; + break; + + case 'p': + *keystorePassword = optarg; + break; + + case 'h': + default: + _displayUsage(argv[0]); + return 0; + } + } + + // Any remaining parameters get put in the command list. + 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); + + if (!_parseArgs(argc, argv, NULL, NULL, commands)) { + parcList_Release(&commands); + exit(EXIT_FAILURE); + } + + ControlMainState mainState; + mainState.controlState = + controlState_Create(&mainState, _writeAndReadMessage, true); + + 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); + controlState_DispatchCommand(mainState.controlState, commands); + char **commandOutputMain = + controlState_GetCommandOutput(mainState.controlState); + if (commandOutputMain != NULL && commandOutputLen > 0) { + for (size_t j = 0; j < commandOutputLen; j++) { + printf("Output %zu: %s \n", j, commandOutputMain[j]); + } + 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/CMakeLists.txt b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt new file mode 100644 index 000000000..fd6cc9310 --- /dev/null +++ b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 DAEMON_SRC + hicnLightDaemon_main.c +) + +build_executable(${HICN_LIGHT_DAEMON} + SOURCES ${DAEMON_SRC} + LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES} + DEPENDS hicn-light + COMPONENT hicn-light +) \ No newline at end of file diff --git a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c new file mode 100644 index 000000000..f1841274b --- /dev/null +++ b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +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 */ + for (int i = getdtablesize(); i >= 0; --i) { + close(i); + } + + // 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?"); + 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 new file mode 100644 index 000000000..90ab8e83f --- /dev/null +++ b/hicn-light/src/hicn/config.h.in @@ -0,0 +1,9 @@ +/* CPU Cache line size */ +#define LEVEL1_DCACHE_LINESIZE @LEVEL1_DCACHE_LINESIZE@ + +#ifndef _WIN32 +#define _GNU_SOURCE +#else +#include +#endif + diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt new file mode 100644 index 000000000..5ce680bfc --- /dev/null +++ b/hicn-light/src/hicn/config/CMakeLists.txt @@ -0,0 +1,97 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +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}/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}/controlQuit.h + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.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 +) + +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}/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}/controlQuit.c + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c + ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.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 +) + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/config/commandOps.c b/hicn-light/src/hicn/config/commandOps.c new file mode 100644 index 000000000..2081782bc --- /dev/null +++ b/hicn-light/src/hicn/config/commandOps.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#ifndef __ANDROID__ +#ifdef HAVE_ERRNO_H +#include +#else +#ifndef _WIN32 +extern int errno; +#endif +#endif +#endif + +#include +#include +#include +#include + +CommandOps *commandOps_Create(void *closure, const char *command, + void (*init)(CommandParser *parser, + CommandOps *ops), + CommandReturn (*execute)(CommandParser *parser, + CommandOps *ops, + PARCList *args), + 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 new file mode 100644 index 000000000..0d685f1b8 --- /dev/null +++ b/hicn-light/src/hicn/config/commandOps.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +#include + +// 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); + 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), + 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 new file mode 100644 index 000000000..38b017835 --- /dev/null +++ b/hicn-light/src/hicn/config/commandParser.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#ifndef __ANDROID__ +#ifdef HAVE_ERRNO_H +#include +#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) { + CommandOps *ops = commandParser_MatchCommand(state, args); + + if (ops == NULL) { + printf("Command not found.\n"); + return CommandReturn_Failure; + } else { + return ops->execute(state, ops, args); + } +} + +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 new file mode 100644 index 000000000..0bd2ee7b0 --- /dev/null +++ b/hicn-light/src/hicn/config/commandParser.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include + +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 + * + * @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); + +/** + * 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 new file mode 100644 index 000000000..16ee93db1 --- /dev/null +++ b/hicn-light/src/hicn/config/commandReturn.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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/configuration.c b/hicn-light/src/hicn/config/configuration.c new file mode 100644 index 000000000..6c64fb1c1 --- /dev/null +++ b/hicn-light/src/hicn/config/configuration.c @@ -0,0 +1,1089 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#ifdef WITH_MAPME +#include +#endif /* WITH_MAPME */ + +#include + +#include +#include +#include + +#include +#include //the listener list +#include // needed to print +#include +#include + +#include + +#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; +}; + +// ======================================================================================== + +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 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) > 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.ipv4 = tmpAddr.sin_addr.s_addr; + } else if (addressGetType(addressEntry) == ADDR_INET6) { + addressGetInet6(addressEntry, &tmpAddr6); + listRouteCommand->addressType = ADDR_INET6; + listRouteCommand->address.ipv6 = tmpAddr6.sin6_addr; + } + listRouteCommand->connid = numberSet_GetItem(nexthops, j); + listRouteCommand->len = nameBitvector_GetLength(prefix); + listRouteCommand->cost = 1; // cost + + pointerLocation++; + 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_routes_command) * 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_SendCommandResponse(conn, msg); + // IoOperations *ops = connection_GetIoOperations(conn); + // streamState_SendCommandResponse(ops, msg); +} + +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; + bool exists = true; + + const char *symbolicName = control->symbolic; + + Address *source = NULL; + Address *destination = NULL; + + if (!symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) { + if (control->ipType == ADDR_INET) { + source = + addressFromInaddr4Port(&control->localIp.ipv4, &control->localPort); + destination = + addressFromInaddr4Port(&control->remoteIp.ipv4, &control->remotePort); + } else if (control->ipType == ADDR_INET6) { + source = + addressFromInaddr6Port(&control->localIp.ipv6, &control->localPort); + destination = + addressFromInaddr6Port(&control->remoteIp.ipv6, &control->remotePort); + } else { + printf("Invalid IP type.\n"); // will generate a Nack + } + + AddressPair *pair = addressPair_Create(source, destination); + const Connection *conn = connectionTable_FindByAddressPair( + forwarder_GetConnectionTable(config->forwarder), pair); + + addressPair_Release(&pair); + + if (conn == NULL) { + // the connection does not exists (even without a name) + exists = false; + } + } + + if (!exists) { + 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); + + connectionTable_Add(forwarder_GetConnectionTable(config->forwarder), + conn); + symbolicNameTable_Add(config->symbolicNameTable, symbolicName, + connection_GetConnectionId(conn)); + + success = true; + + } else { + printf("failed, could not create IoOperations"); + } + + } else { + printf("failed, symbolic name or connextion already exist\n"); + } + + addressDestroy(&source); + addressDestroy(&destination); + + // generate ACK/NACK + struct iovec *response; + + if (success) { // ACK + response = utils_CreateAck(header, control, sizeof(add_connection_command)); + } else { // NACK + response = + utils_CreateNack(header, control, sizeof(add_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); + 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); + + 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); + 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; +} + +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); + listConnectionsCommand->state = + connection_IsUp(original) ? IFACE_UP : IFACE_DOWN; + listConnectionsCommand->connectionData.connectionType = + ioOperations_GetConnectionType(connection_GetIoOperations(original)); + + 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.ipv4 = + tmpAddr.sin_addr.s_addr; + memset(&tmpAddr, 0, sizeof(tmpAddr)); + // get remote port/address + addressGetInet(remoteAddress, &tmpAddr); + listConnectionsCommand->connectionData.remotePort = tmpAddr.sin_port; + listConnectionsCommand->connectionData.remoteIp.ipv4 = + tmpAddr.sin_addr.s_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.ipv6 = tmpAddr6.sin6_addr; + memset(&tmpAddr6, 0, sizeof(tmpAddr6)); + // get remote port/address + addressGetInet6(remoteAddress, &tmpAddr6); + listConnectionsCommand->connectionData.remotePort = tmpAddr6.sin6_port; + listConnectionsCommand->connectionData.remoteIp.ipv6 = 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.ipv4 = tmpAddr.sin_addr.s_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.ipv6 = tmpAddr6.sin6_addr; + listListenersCommand->port = tmpAddr6.sin6_port; + } + } + + // send response + header_control_message *header = request[0].iov_base; + header->messageType = RESPONSE_LIGHT; + header->length = (uint16_t)listenerSet_Length(listenerList); + + struct iovec *response = + parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); + + response[0].iov_base = header; + response[0].iov_len = sizeof(header_control_message); + response[1].iov_base = payloadResponse; + response[1].iov_len = + sizeof(list_listeners_command) * listenerSet_Length(listenerList); + + return response; +} + +struct iovec *configuration_ProcessCacheStore(Configuration *config, + struct iovec *request) { + header_control_message *header = request[0].iov_base; + ; + cache_store_command *control = request[1].iov_base; + ; + + bool success = false; + + switch (control->activate) { + case ACTIVATE_ON: + forwarder_SetChacheStoreFlag(config->forwarder, true); + if (forwarder_GetChacheStoreFlag(config->forwarder)) { + success = true; + } + break; + + case ACTIVATE_OFF: + forwarder_SetChacheStoreFlag(config->forwarder, false); + if (!forwarder_GetChacheStoreFlag(config->forwarder)) { + success = true; + } + break; + + default: + break; + } + + struct iovec *response; + if (success) { // ACK + response = utils_CreateAck(header, control, sizeof(cache_store_command)); + } else { // NACK + response = utils_CreateNack(header, control, sizeof(cache_store_command)); + } + + return response; +} + +struct iovec *configuration_ProcessCacheServe(Configuration *config, + struct iovec *request) { + header_control_message *header = request[0].iov_base; + cache_serve_command *control = request[1].iov_base; + + bool success = false; + + switch (control->activate) { + case ACTIVATE_ON: + forwarder_SetChacheServeFlag(config->forwarder, true); + if (forwarder_GetChacheServeFlag(config->forwarder)) { + success = true; + } + break; + + case ACTIVATE_OFF: + forwarder_SetChacheServeFlag(config->forwarder, false); + if (!forwarder_GetChacheServeFlag(config->forwarder)) { + success = true; + } + break; + + default: + break; + } + + struct iovec *response; + if (success) { // ACK + response = utils_CreateAck(header, control, sizeof(cache_store_command)); + } else { // NACK + response = utils_CreateNack(header, control, sizeof(cache_store_command)); + } + + return response; +} + +struct iovec *configuration_ProcessCacheClear(Configuration *config, + struct iovec *request) { + header_control_message *header = request[0].iov_base; + + forwarder_ClearCache(config->forwarder); + + struct iovec *response = utils_CreateAck(header, NULL, 0); + return response; +} + +size_t configuration_GetObjectStoreSize(Configuration *config) { + return config->maximumContentObjectStoreSize; +} + +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); +} + +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; +} + +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; + } +} + +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); + forwarder_SetStrategy(config->forwarder, hicnPrefix, strategy); + name_Release(&hicnPrefix); + } + + struct iovec *response = + utils_CreateAck(header, control, sizeof(set_strategy_command)); + + return response; +} + +void configuration_SetObjectStoreSize(Configuration *config, + size_t maximumObjectCount) { + config->maximumContentObjectStoreSize = maximumObjectCount; + + forwarder_SetContentObjectStoreSize(config->forwarder, + config->maximumContentObjectStoreSize); +} + +Forwarder *configuration_GetForwarder(const Configuration *config) { + return config->forwarder; +} + +Logger *configuration_GetLogger(const Configuration *config) { + return config->logger; +} + +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); + + struct iovec *response = + utils_CreateAck(header, control, sizeof(mapme_activator_command)); + + return response; +} + +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); + + struct iovec *response = + utils_CreateAck(header, control, sizeof(mapme_activator_command)); + + return response; +} + +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); + + struct iovec *response = + utils_CreateAck(header, control, sizeof(mapme_timing_command)); + + return response; +} + +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); + + struct iovec *response = + utils_CreateAck(header, control, sizeof(mapme_timing_command)); + + return response; +} + +// =========================== +// 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_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; + + default: + break; + } + + return response; +} + +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); + + switch (command) { + case LIST_CONNECTIONS: + case LIST_ROUTES: // case LIST_INTERFACES: case ETC...: + parcMemory_Deallocate( + &response[1] + .iov_base); // deallocate payload only if generated at fwd side + break; + default: + break; + } + + // deallocate received request. It coincides with response[0].iov_base memory + // parcMemory_Deallocate(&request); //deallocate header and payload (if + // same sent by controller) + parcMemory_Deallocate(&response); // deallocate iovec pointer +} diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h new file mode 100644 index 000000000..5090f1413 --- /dev/null +++ b/hicn-light/src/hicn/config/configuration.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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.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 configuration_h +#define configuration_h + +#include +#include + +struct configuration; +typedef struct configuration Configuration; + +struct forwarder; +typedef struct forwarder Forwarder; + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @retval <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +Configuration *configuration_Create(Forwarder *forwarder); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @retval <#value#> <#explanation#> + * + * Example: + * @code + * <#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); + +/** + * Returns the configured size of the content store + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @retval <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +size_t configuration_GetObjectStoreSize(Configuration *config); + +/** + * Sets the size of the content store (in objects, not bytes) + * + * Must be set before starting the forwarder + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +void configuration_SetObjectStoreSize(Configuration *config, + size_t maximumContentObjectCount); + +strategy_type configuration_GetForwardingStrategy(Configuration *config, + const char *prefix); + +/** + * 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); + +/** + * 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); + +struct iovec *configuration_DispatchCommand(Configuration *config, + command_id command, + struct iovec *control, + unsigned ingressId); + +#endif // configuration_h diff --git a/hicn-light/src/hicn/config/configurationFile.c b/hicn-light/src/hicn/config/configurationFile.c new file mode 100644 index 000000000..f1991897f --- /dev/null +++ b/hicn-light/src/hicn/config/configurationFile.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); + + // 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); + CommandReturn result = + controlState_DispatchCommand(configFile->controlState, args); + + // 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; + } + parcList_Release(&args); + parcMemory_Deallocate((void **)©); + } + } + } + + 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 new file mode 100644 index 000000000..b748dfc15 --- /dev/null +++ b/hicn-light/src/hicn/config/configurationFile.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 new file mode 100644 index 000000000..a8dc09201 --- /dev/null +++ b/hicn-light/src/hicn/config/configurationListeners.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#endif +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +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] addr4 The ipv4 address in network byte order + * @param [in] port The port number in network byte order + * + * return true if success, false otherwise + */ +static bool _setupTcpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4, + uint16_t *port) { + 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, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add TCP listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + return success; +} + +/* + * Create a new IPV4/UDP listener. + * + * @param [in,out] forwarder The hicn-light forwarder instance + * @param [in] addr4 The ipv4 address in network byte order + * @param [in] port The port number in network byte order + * + * return true if success, false otherwise + */ +static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4, + uint16_t *port) { + 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, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add UDP listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + 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 + * + * return true if success, false otherwise + */ +static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, + ipv6_addr_t *addr6, uint16_t *port, + 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, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add TCP6 listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + return success; +} + +/* + * Create a new IPV6/UDP 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 + * + * return true if success, false otherwise + */ +static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder, + ipv6_addr_t *addr6, uint16_t *port) { + 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, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add UDP6 listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + 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.ipv4, &control->port); + success = _setupHicnListenerOnInet4(configuration_GetForwarder(config), + symbolic, localAddress); + break; + } + + case ADDR_INET6: { + localAddress = + addressFromInaddr6Port(&control->address.ipv6, &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)) { + logger_Log(configuration_GetLogger(config), LoggerFacility_Config, + PARCLogLevel_Info, __func__, + "Setup hicn listener on address %s", + addressToString(localAddress)); + } + } + + addressDestroy(&localAddress); + + return success; +} + +bool _addIP(Configuration *config, add_listener_command *control, + unsigned ingressId) { + bool success = false; + + switch (control->addressType) { + case ADDR_INET: { + if (control->connectionType == UDP_CONN) { + success = + _setupUdpListenerOnInet(configuration_GetForwarder(config), + &control->address.ipv4, &control->port); + } else if (control->connectionType == TCP_CONN) { + success = + _setupTcpListenerOnInet(configuration_GetForwarder(config), + &control->address.ipv4, &control->port); + } + break; + } + + case ADDR_INET6: { + if (control->connectionType == UDP_CONN) { + success = _setupUdpListenerOnInet6Light( + configuration_GetForwarder(config), &control->address.ipv6, + &control->port); + } else if (control->connectionType == TCP_CONN) { + success = _setupTcpListenerOnInet6Light( + configuration_GetForwarder(config), &control->address.ipv6, + &control->port, 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; + + 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.ipv4, &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.ipv6, &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, + const Address *address, uint16_t port, + const char *interfaceName) { + address_type type = addressGetType(address); + switch (type) { + case ADDR_INET: { + struct sockaddr_in tmp; + addressGetInet(address, &tmp); + _setupTcpListenerOnInet(forwarder, &tmp.sin_addr.s_addr, &port); + break; + } + + case ADDR_INET6: { + struct sockaddr_in6 tmp; + addressGetInet6(address, &tmp); + _setupTcpListenerOnInet6Light(forwarder, &tmp.sin6_addr, &port, + 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 + if (addressGetType(address) != ADDR_LINK) { + _setupListenersOnAddress(forwarder, address, port, + 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); + + _setupUdpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr), + &network_byte_order_port); + _setupTcpListenerOnInet(forwarder, (ipv4_addr_t *)&(addr), + &network_byte_order_port); +} diff --git a/hicn-light/src/hicn/config/configurationListeners.h b/hicn-light/src/hicn/config/configurationListeners.h new file mode 100644 index 000000000..b09ad5167 --- /dev/null +++ b/hicn-light/src/hicn/config/configurationListeners.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include + +#include + +/** + * 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/controlAdd.c b/hicn-light/src/hicn/config/controlAdd.c new file mode 100644 index 000000000..f77897dc4 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAdd.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +// =================================================== + +static void _controlAdd_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlAdd_Execute(CommandParser *parser, CommandOps *ops, + PARCList *args); +static CommandReturn _controlAdd_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +// =================================================== + +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) { + 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); + + printf("Available commands:\n"); + printf(" %s\n", ops_add_connection->command); + printf(" %s\n", ops_add_route->command); + printf(" %s\n", ops_add_punting->command); + printf(" %s\n", ops_add_listener->command); + printf("\n"); + + commandOps_Destroy(&ops_add_connection); + commandOps_Destroy(&ops_add_route); + commandOps_Destroy(&ops_add_punting); + commandOps_Destroy(&ops_add_listener); + 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)); +} + +static CommandReturn _controlAdd_Execute(CommandParser *parser, CommandOps *ops, + PARCList *args) { + return _controlAdd_HelpExecute(parser, ops, args); +} diff --git a/hicn-light/src/hicn/config/controlAdd.h b/hicn-light/src/hicn/config/controlAdd.h new file mode 100644 index 000000000..7c160b5f7 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAdd.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 new file mode 100644 index 000000000..813c40929 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddConnection.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +// =================================================== + +static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlAddConnection_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlAddConnection_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +// =================================================== + +static CommandReturn _controlAddConnection_HicnHelpExecute( + CommandParser *parser, CommandOps *ops, PARCList *args); +static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +static CommandReturn _controlAddConnection_TcpHelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +// =================================================== + +static const char *_commandAddConnection = "add connection"; +static const char *_commandAddConnectionHicn = "add connection hicn"; +static const char *_commandAddConnectionUdp = "add connection udp"; +static const char *_commandAddConnectionTcp = "add connection tcp"; +static const char *_commandAddConnectionHelp = "help add connection"; +static const char *_commandAddConnectionHicnHelp = "help add connection hicn"; +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); +} + +// =================================================== + +static CommandOps *_controlAddConnection_HicnCreate(ControlState *state) { + return commandOps_Create(state, _commandAddConnectionHicn, NULL, + _controlAddConnection_HicnExecute, + commandOps_Destroy); +} + +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); +} + +// =================================================== + +static CommandOps *_controlAddConnection_HicnHelpCreate(ControlState *state) { + return commandOps_Create(state, _commandAddConnectionHicnHelp, NULL, + _controlAddConnection_HicnHelpExecute, + commandOps_Destroy); +} + +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) { + printf("Available commands:\n"); + printf(" %s\n", _commandAddConnectionHicn); + printf(" %s\n", _commandAddConnectionUdp); + printf(" %s\n", _commandAddConnectionTcp); + printf("\n"); + return CommandReturn_Success; +} + +static void _controlAddConnection_Init(CommandParser *parser, CommandOps *ops) { + ControlState *state = ops->closure; + controlState_RegisterCommand(state, + _controlAddConnection_HicnHelpCreate(state)); + controlState_RegisterCommand(state, + _controlAddConnection_UdpHelpCreate(state)); + controlState_RegisterCommand(state, + _controlAddConnection_TcpHelpCreate(state)); + + controlState_RegisterCommand(state, _controlAddConnection_HicnCreate(state)); + controlState_RegisterCommand(state, _controlAddConnection_UdpCreate(state)); + controlState_RegisterCommand(state, _controlAddConnection_TcpCreate(state)); +} + +static CommandReturn _controlAddConnection_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + return _controlAddConnection_HelpExecute(parser, ops, args); +} + +// =================================================== +// 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) + * + * @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) { + 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.ipv4) == + 1 && + inet_pton(AF_INET, local_ip, &addConnectionCommand->localIp.ipv4) == 1) { + addConnectionCommand->ipType = ADDR_INET; + + } else if (inet_pton(AF_INET6, remote_ip, + &addConnectionCommand->remoteIp.ipv6) == 1 && + inet_pton(AF_INET6, local_ip, + &addConnectionCommand->localIp.ipv6) == 1) { + addConnectionCommand->ipType = ADDR_INET6; + + } else { + printf("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) { + printf("add connection hicn \n"); + printf( + "add connection udp \n"); + printf( + " : symbolic name, e.g. 'conn1' (must be " + "unique, start with alpha)\n"); + printf( + " : the IPv4 or IPv6 or hostname of the remote system\n"); + printf(" : optional local IP address to bind to\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlAddConnection_HicnHelpExecute( + CommandParser *parser, CommandOps *ops, PARCList *args) { + _controlAddConnection_IpHelp(parser, ops, args, "hicn"); + + return CommandReturn_Success; +} + +static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + 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); + return CommandReturn_Failure; + } + + char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); + + if (!utils_ValidateSymbolicName(symbolic)) { + printf( + "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); +} + +static CommandReturn _controlAddConnection_UdpHelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + _controlAddConnection_IpHelp(parser, ops, args, "udp"); + + return CommandReturn_Success; +} + +static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + 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); + return CommandReturn_Failure; + } + + char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); + + if (!utils_ValidateSymbolicName(symbolic)) { + printf( + "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); +} + +static CommandReturn _controlAddConnection_TcpHelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + _controlAddConnection_IpHelp(parser, ops, args, "tcp"); + + return CommandReturn_Success; +} + +static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + 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); + return CommandReturn_Failure; + } + + char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); + + if (!utils_ValidateSymbolicName(symbolic)) { + printf( + "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); +} diff --git a/hicn-light/src/hicn/config/controlAddConnection.h b/hicn-light/src/hicn/config/controlAddConnection.h new file mode 100644 index 000000000..546388efc --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddConnection.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..48ea02e68 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddListener.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +static CommandReturn _controlAddListener_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlAddListener_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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 CommandReturn _controlAddListener_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + printf("commands:\n"); + printf(" add listener hicn \n"); + printf(" add listener udp \n"); + printf(" add listener tcp \n"); + printf("\n"); + printf( + " symbolic: User defined name for listener, must start with " + "alpha and be alphanum\n"); + printf(" protocol: hicn | udp\n"); + printf( + " localAddress: IPv4 or IPv6 address (or prefix protocol = hicn) " + "assigend to the local interface\n"); + printf(" port: Udp port\n"); + printf("\n"); + printf("Notes:\n"); + printf(" The symblic name must be unique or the source will reject it.\n"); + printf( + " If protocol = hinc: the address 0::0 indicates the main listern, " + "for which we can set punting rules.\n"); + return CommandReturn_Success; +} + +static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops, + const char *symbolic, const char *addr, + const char *port, listener_mode mode, + connection_type type) { + 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.ipv4) == 1) { + addListenerCommand->addressType = ADDR_INET; + + } else if (inet_pton(AF_INET6, addr, &addListenerCommand->address.ipv6) == + 1) { + addListenerCommand->addressType = ADDR_INET6; + + } else { + printf("Error: %s is not a valid network address \n", addr); + parcMemory_Deallocate(&addListenerCommand); + return CommandReturn_Failure; + } + + // Fill remaining payload fields + 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) { + if (parcList_Size(args) != 5 && parcList_Size(args) != 6) { + _controlAddListener_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + CommandReturn result = CommandReturn_Failure; + + const char *symbolic = parcList_GetAtIndex(args, _indexSymbolic); + + if (!utils_ValidateSymbolicName(symbolic)) { + printf( + "Error: symbolic name must begin with an alpha and be alphanum " + "after\n"); + return result; + } + + const char *host = parcList_GetAtIndex(args, _indexAddress); + const char *protocol = parcList_GetAtIndex(args, _indexProtocol); + + 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_MODE, + HICN_CONN); + } + + const char *port = parcList_GetAtIndex(args, _indexPort); + + if ((strcasecmp("udp", protocol) == 0)) { + return _CreateListener(parser, ops, symbolic, host, port, IP_MODE, + UDP_CONN); + } else if ((strcasecmp("tcp", protocol) == 0)) { + return _CreateListener(parser, ops, symbolic, host, port, IP_MODE, + TCP_CONN); + } else { + _controlAddListener_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + if (result == CommandReturn_Failure) printf("creation failed\n"); + + return result; +} diff --git a/hicn-light/src/hicn/config/controlAddListener.h b/hicn-light/src/hicn/config/controlAddListener.h new file mode 100644 index 000000000..6516d1779 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddListener.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +CommandOps *controlAddListener_Create(ControlState *state); +CommandOps *controlAddListener_HelpCreate(ControlState *state); +#endif // Control_AddListener_h diff --git a/hicn-light/src/hicn/config/controlAddPunting.c b/hicn-light/src/hicn/config/controlAddPunting.c new file mode 100644 index 000000000..c86901089 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddPunting.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +static CommandReturn _controlAddPunting_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlAddPunting_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("add punting \n"); + printf(" : listener symbolic name\n"); + printf( + "
: prefix to add as a punting rule. (example " + "1234::0/64)\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlAddPunting_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 4) { + _controlAddPunting_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + const char *symbolicOrConnid = parcList_GetAtIndex(args, _indexSymbolic); + + if (!utils_ValidateSymbolicName(symbolicOrConnid) && + !utils_IsNumber(symbolicOrConnid)) { + printf( + "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'; + } + + if (len == 0) { + printf("ERROR: a prefix can not be of length 0\n"); + free(addr); + return CommandReturn_Failure; + } + + // 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.ipv4) == 1) { + if (len > 32) { + printf("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.ipv6) == 1) { + if (len > 128) { + printf("ERROR: exceeded INET6 mask length, max=128\n"); + parcMemory_Deallocate(&addPuntingCommand); + free(addr); + return CommandReturn_Failure; + } + addPuntingCommand->addressType = ADDR_INET6; + } else { + printf("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 new file mode 100644 index 000000000..9cab76359 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddPunting.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..f1c85e29a --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddRoute.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +static CommandReturn _controlAddRoute_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlAddRoute_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("commands:\n"); + printf(" add route \n"); + printf("\n"); + printf(" symbolic: The symbolic name for an exgress\n"); + printf( + " connid: The egress connection id (see 'help list connections')\n"); + printf( + " prefix: The hicn name as IPv4 or IPv6 address (e.g 1234::0/64)\n"); + printf(" cost: positive integer representing cost\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlAddRoute_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 5) { + _controlAddRoute_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + const char *symbolicOrConnid = parcList_GetAtIndex(args, 2); + + if (!utils_ValidateSymbolicName(symbolicOrConnid) && + !utils_IsNumber(symbolicOrConnid)) { + printf( + "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) { + printf("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'; + } + + if (len == 0) { + printf("ERROR: a prefix can not be of length 0\n"); + free(addr); + return CommandReturn_Failure; + } + + // 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.ipv4) == 1) { + if (len > 32) { + printf("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.ipv6) == 1) { + if (len > 128) { + printf("ERROR: exceeded INET6 mask length, max=128\n"); + parcMemory_Deallocate(&addRouteCommand); + free(addr); + return CommandReturn_Failure; + } + addRouteCommand->addressType = ADDR_INET6; + } else { + printf("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 new file mode 100644 index 000000000..9588c0f42 --- /dev/null +++ b/hicn-light/src/hicn/config/controlAddRoute.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..fa228994c --- /dev/null +++ b/hicn-light/src/hicn/config/controlCache.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +static void _controlCache_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlCache_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlCache_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + CommandOps *ops_cache_serve = controlCacheServe_HelpCreate(NULL); + CommandOps *ops_cache_store = controlCacheStore_HelpCreate(NULL); + CommandOps *ops_cache_clear = controlCacheClear_HelpCreate(NULL); + + printf("Available commands:\n"); + printf(" %s\n", ops_cache_serve->command); + printf(" %s\n", ops_cache_store->command); + printf(" %s\n", ops_cache_clear->command); + printf("\n"); + + 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) { + return _controlCache_HelpExecute(parser, ops, args); +} + +// ====================================================================== diff --git a/hicn-light/src/hicn/config/controlCache.h b/hicn-light/src/hicn/config/controlCache.h new file mode 100644 index 000000000..c2f2402f1 --- /dev/null +++ b/hicn-light/src/hicn/config/controlCache.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..be9a4ac38 --- /dev/null +++ b/hicn-light/src/hicn/config/controlCacheClear.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +static CommandReturn _controlCacheClear_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlCacheClear_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("cache clear\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlCacheClear_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 2) { + _controlCacheClear_HelpExecute(parser, ops, args); + 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 new file mode 100644 index 000000000..025758c34 --- /dev/null +++ b/hicn-light/src/hicn/config/controlCacheClear.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..e0c1c20eb --- /dev/null +++ b/hicn-light/src/hicn/config/controlCacheServe.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +static CommandReturn _controlCacheServe_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlCacheServe_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("cache serve [on|off]\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlCacheServe_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 3) { + _controlCacheServe_HelpExecute(parser, ops, args); + 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); + 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 new file mode 100644 index 000000000..afebc0601 --- /dev/null +++ b/hicn-light/src/hicn/config/controlCacheServe.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..6f21f912b --- /dev/null +++ b/hicn-light/src/hicn/config/controlCacheStore.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +static CommandReturn _controlCacheStore_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlCacheStore_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("cache store [on|off]\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlCacheStore_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 3) { + _controlCacheStore_HelpExecute(parser, ops, args); + 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); + 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 new file mode 100644 index 000000000..e32bf5663 --- /dev/null +++ b/hicn-light/src/hicn/config/controlCacheStore.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..8c1b2e125 --- /dev/null +++ b/hicn-light/src/hicn/config/controlList.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +//#include +#include +#include + +static void _controlList_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlList_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlList_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + 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); + + printf("Available commands:\n"); + printf(" %s\n", ops_list_connections->command); + // printf(" %s\n", ops_list_interfaces->command); + printf(" %s\n", ops_list_routes->command); + printf(" %s\n", ops_list_listeners->command); + printf("\n"); + + commandOps_Destroy(&ops_list_connections); + // commandOps_Destroy(&ops_list_interfaces); + commandOps_Destroy(&ops_list_routes); + commandOps_Destroy(&ops_list_listeners); + + 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)); +} + +static CommandReturn _controlList_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + return _controlList_HelpExecute(parser, ops, args); +} + +// ====================================================================== diff --git a/hicn-light/src/hicn/config/controlList.h b/hicn-light/src/hicn/config/controlList.h new file mode 100644 index 000000000..d497e5179 --- /dev/null +++ b/hicn-light/src/hicn/config/controlList.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..feed36d2a --- /dev/null +++ b/hicn-light/src/hicn/config/controlListConnections.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +static CommandReturn _controlListConnections_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlListConnections_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("list connections: displays a 1-line summary of each connection\n"); + printf("\n"); + printf("The columns are:\n"); + printf(" connection id : an integer index for the connection\n"); + printf(" state : UP or DOWN\n"); + printf( + " local address : the local network address associated with the " + "connection\n"); + printf( + " remote address: the remote network address associated with the " + "connection\n"); + printf( + " protocol : the network protocol (tcp, udp, gre, mcast, " + "ether)\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlListConnections_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 2) { + _controlListConnections_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + 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) * 128); + } + } + + // 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(); + + parcBufferComposer_Format( + composer, "%5d %4s %s %s %s", listConnectionsCommand->connid, + stateString[listConnectionsCommand->state], sourceString, + destinationString, + connTypeString[listConnectionsCommand->connectionData.connectionType]); + + 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); + } + + 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 new file mode 100644 index 000000000..cd5c21cec --- /dev/null +++ b/hicn-light/src/hicn/config/controlListConnections.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..0b8c3d7bb --- /dev/null +++ b/hicn-light/src/hicn/config/controlListInterfaces.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +static CommandReturn _controlListInterfaces_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlListInterfaces_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("list interfaces\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlListInterfaces_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 2) { + _controlListInterfaces_HelpExecute(parser, ops, args); + 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 new file mode 100644 index 000000000..f885835ed --- /dev/null +++ b/hicn-light/src/hicn/config/controlListInterfaces.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..735be6acb --- /dev/null +++ b/hicn-light/src/hicn/config/controlListListeners.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +static CommandReturn _controlListListeners_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlListListeners_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("list listeners\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlListListeners_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 2) { + _controlListListeners_HelpExecute(parser, ops, args); + 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; + if (receivedHeader->length > 0) { + printf("%6.6s %50.70s %s\n", "iface", "address", "type"); + } else { + printf(" --- 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(); + + parcBufferComposer_Format(composer, "%6u %50.70s %3s", + listListenersCommand->connid, addrString, + listenerType[listListenersCommand->encapType]); + + 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); + } + + 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 new file mode 100644 index 000000000..11ec07579 --- /dev/null +++ b/hicn-light/src/hicn/config/controlListListeners.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +CommandOps *controlListListeners_Create(ControlState *state); +CommandOps *controlListListeners_HelpCreate(ControlState *state); +#endif // Control_ListListeners_h diff --git a/hicn-light/src/hicn/config/controlListRoutes.c b/hicn-light/src/hicn/config/controlListRoutes.c new file mode 100644 index 000000000..97e7c2f5c --- /dev/null +++ b/hicn-light/src/hicn/config/controlListRoutes.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +static CommandReturn _controlListRoutes_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlListRoutes_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("command: list routes\n"); + printf("\n"); + printf( + "This command will fetch the prefix routing table. For each route, it " + "will list:\n"); + printf(" iface: interface\n"); + printf( + " protocol: the routing protocol, such as STATIC, CONNECTED, etc.\n"); + printf( + " type: LMP or EXACT (longest matching prefix or exact match)\n"); + printf(" cost: The route cost, lower being preferred\n"); + printf(" next: List of next hops by interface id\n"); + printf(" prefix: name prefix\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlListRoutes_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 2) { + _controlListRoutes_HelpExecute(parser, ops, args); + 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 + + if (receivedHeader->length > 0) { + printf("%6.6s %8.8s %70.70s %s\n", "iface", "cost", "prefix", "len"); + } else { + printf(" --- 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); + } + + puts(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 new file mode 100644 index 000000000..341552add --- /dev/null +++ b/hicn-light/src/hicn/config/controlListRoutes.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..896f53b8a --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMe.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +static void _controlMapMe_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlMapMe_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlMapMe_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + 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); + + printf("Available commands:\n"); + printf(" %s\n", ops_mapme_enable->command); + printf(" %s\n", ops_mapme_discovery->command); + printf(" %s\n", ops_mapme_timescale->command); + printf(" %s\n", ops_mapme_retx->command); + printf("\n"); + + 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) { + return _controlMapMe_HelpExecute(parser, ops, args); +} + +// ====================================================================== diff --git a/hicn-light/src/hicn/config/controlMapMe.h b/hicn-light/src/hicn/config/controlMapMe.h new file mode 100644 index 000000000..3edd78989 --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMe.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..a4815c08b --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeDiscovery.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static CommandReturn _controlMapMeDiscovery_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlMapMeDiscovery_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("mapme discovery [on|off]\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlMapMeDiscovery_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 3) { + _controlMapMeDiscovery_HelpExecute(parser, ops, args); + 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); + 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 new file mode 100644 index 000000000..c2832632a --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeDiscovery.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..04b103a54 --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeEnable.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static CommandReturn _controlMapMeEnable_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlMapMeEnable_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("mapme enable [on|off]\n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlMapMeEnable_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 3) { + _controlMapMeEnable_HelpExecute(parser, ops, args); + 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); + 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 new file mode 100644 index 000000000..0ce4970f3 --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeEnable.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..5546ded9a --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeRetx.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static CommandReturn _controlMapMeRetx_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlMapMeRetx_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("mapme retx n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlMapMeRetx_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 3) { + _controlMapMeRetx_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + const char *rtx = parcList_GetAtIndex(args, 2); + if (!utils_IsNumber(rtx)) { + printf( + "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 new file mode 100644 index 000000000..3e3b2de15 --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeRetx.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..d621cdfed --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeTimescale.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static CommandReturn _controlMapMeTimescale_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlMapMeTimescale_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("mapme timescale n"); + printf("\n"); + + return CommandReturn_Success; +} + +static CommandReturn _controlMapMeTimescale_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 3) { + _controlMapMeTimescale_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + const char *ts = parcList_GetAtIndex(args, 2); + if (!utils_IsNumber(ts)) { + printf( + "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 new file mode 100644 index 000000000..947d00a5d --- /dev/null +++ b/hicn-light/src/hicn/config/controlMapMeTimescale.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..ddea256b2 --- /dev/null +++ b/hicn-light/src/hicn/config/controlQuit.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +static CommandReturn _controlQuit_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlQuit_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + printf("Exits the interactive control program\n\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlQuit_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + printf("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 new file mode 100644 index 000000000..b45d5e215 --- /dev/null +++ b/hicn-light/src/hicn/config/controlQuit.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..1768b7651 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemove.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +static void _controlRemove_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlRemove_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlRemove_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + CommandOps *ops_remove_connection = controlRemoveConnection_Create(NULL); + CommandOps *ops_remove_route = controlRemoveRoute_Create(NULL); + CommandOps *ops_remove_punting = controlRemovePunting_Create(NULL); + + printf("Available commands:\n"); + printf(" %s\n", ops_remove_connection->command); + printf(" %s\n", ops_remove_route->command); + printf(" %s\n", ops_remove_punting->command); + printf("\n"); + + commandOps_Destroy(&ops_remove_connection); + commandOps_Destroy(&ops_remove_route); + commandOps_Destroy(&ops_remove_punting); + return CommandReturn_Success; +} + +static void _controlRemove_Init(CommandParser *parser, CommandOps *ops) { + ControlState *state = ops->closure; + controlState_RegisterCommand(state, + controlRemoveConnection_HelpCreate(state)); + controlState_RegisterCommand(state, controlRemoveRoute_HelpCreate(state)); + controlState_RegisterCommand(state, controlRemoveConnection_Create(state)); + controlState_RegisterCommand(state, controlRemoveRoute_Create(state)); + controlState_RegisterCommand(state, controlRemovePunting_Create(state)); + controlState_RegisterCommand(state, controlRemovePunting_HelpCreate(state)); +} + +static CommandReturn _controlRemove_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + return _controlRemove_HelpExecute(parser, ops, args); +} diff --git a/hicn-light/src/hicn/config/controlRemove.h b/hicn-light/src/hicn/config/controlRemove.h new file mode 100644 index 000000000..863555728 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemove.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..0f2d315c3 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemoveConnection.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +static CommandReturn _controlRemoveConnection_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlRemoveConnection_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +// =================================================== + +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) { + printf("command:\n"); + printf(" remove connection \n"); + return CommandReturn_Success; +} + +static CommandReturn _controlRemoveConnection_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 3) { + _controlRemoveConnection_HelpExecute(parser, ops, args); + return false; + } + + if ((strcmp(parcList_GetAtIndex(args, 0), "remove") != 0) || + (strcmp(parcList_GetAtIndex(args, 1), "connection") != 0)) { + _controlRemoveConnection_HelpExecute(parser, ops, args); + return false; + } + + const char *symbolicOrConnid = parcList_GetAtIndex(args, 2); + + if (!utils_ValidateSymbolicName(symbolicOrConnid) && + !utils_IsNumber(symbolicOrConnid)) { + printf( + "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 new file mode 100644 index 000000000..51d3a52a8 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemoveConnection.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +CommandOps *controlRemoveConnection_Create(ControlState *state); +CommandOps *controlRemoveConnection_HelpCreate(ControlState *state); +#endif // Control_RemoveConnection_h diff --git a/hicn-light/src/hicn/config/controlRemovePunting.c b/hicn-light/src/hicn/config/controlRemovePunting.c new file mode 100644 index 000000000..b105449ee --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemovePunting.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +static CommandReturn _controlRemovePunting_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlRemovePunting_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +// =================================================== + +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) { + printf("remove punting \n"); + return CommandReturn_Success; +} + +static CommandReturn _controlRemovePunting_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + printf("command not implemented\n"); + return _controlRemovePunting_HelpExecute(parser, ops, args); +} + +// ================================================== diff --git a/hicn-light/src/hicn/config/controlRemovePunting.h b/hicn-light/src/hicn/config/controlRemovePunting.h new file mode 100644 index 000000000..858d6f969 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemovePunting.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..6bfe12674 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemoveRoute.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlRemoveRoute_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +// =================================================== + +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) { + printf("commands:\n"); + printf(" remove route \n"); + return CommandReturn_Success; +} + +static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 4) { + _controlRemoveRoute_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + const char *symbolicOrConnid = parcList_GetAtIndex(args, 2); + + if (!utils_ValidateSymbolicName(symbolicOrConnid) && + !utils_IsNumber(symbolicOrConnid)) { + printf( + "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'; + } + + if (len == 0) { + printf("ERROR: a prefix can not be of length 0\n"); + free(addr); + return CommandReturn_Failure; + } + + // 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.ipv4) == 1) { + if (len > 32) { + printf("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.ipv6) == + 1) { + if (len > 128) { + printf("ERROR: exceeded INET6 mask length, max=128\n"); + parcMemory_Deallocate(&removeRouteCommand); + free(addr); + return CommandReturn_Failure; + } + removeRouteCommand->addressType = ADDR_INET6; + } else { + printf("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 new file mode 100644 index 000000000..5e152b2fd --- /dev/null +++ b/hicn-light/src/hicn/config/controlRemoveRoute.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..38a371e73 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRoot.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void _controlRoot_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlRoot_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlRoot_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + printf("Command-line execution:\n"); + printf( + " controller [--keystore ] [--password ] " + "command\n"); + printf("\n"); + printf("Interactive execution:\n"); + printf(" controller [--keystore ] [--password ]\n"); + printf("\n"); + printf( + "If the keystore is not specified, the default path is used. Keystore " + "must exist prior to running program.\n"); + printf("If the password is not specified, the user will be prompted.\n"); + printf("\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); + + printf("Available commands:\n"); + printf(" %s\n", ops_help_add->command); + printf(" %s\n", ops_help_list->command); + printf(" %s\n", ops_help_quit->command); + printf(" %s\n", ops_help_remove->command); + printf(" %s\n", ops_help_set->command); + printf(" %s\n", ops_help_unset->command); + printf(" %s\n", ops_help_cache->command); + printf(" %s\n", ops_help_mapme->command); + printf("\n"); + + 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); + + 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)); + + 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)); +} + +static CommandReturn _controlRoot_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + return CommandReturn_Success; +} + +// ====================================================================== diff --git a/hicn-light/src/hicn/config/controlRoot.h b/hicn-light/src/hicn/config/controlRoot.h new file mode 100644 index 000000000..154b81a80 --- /dev/null +++ b/hicn-light/src/hicn/config/controlRoot.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..4c94893dc --- /dev/null +++ b/hicn-light/src/hicn/config/controlSet.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +static void _controlSet_Init(CommandParser *parser, CommandOps *ops); +static CommandReturn _controlSet_Execute(CommandParser *parser, CommandOps *ops, + PARCList *args); +static CommandReturn _controlSet_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + CommandOps *ops_help_set_debug = controlSetDebug_HelpCreate(NULL); + CommandOps *ops_help_set_strategy = controlSetStrategy_HelpCreate(NULL); + CommandOps *ops_help_set_wldr = controlSetWldr_HelpCreate(NULL); + + printf("Available commands:\n"); + printf(" %s\n", ops_help_set_debug->command); + printf(" %s\n", ops_help_set_strategy->command); + printf(" %s\n", ops_help_set_wldr->command); + printf("\n"); + + 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) { + return _controlSet_HelpExecute(parser, ops, args); +} diff --git a/hicn-light/src/hicn/config/controlSet.h b/hicn-light/src/hicn/config/controlSet.h new file mode 100644 index 000000000..abe2a611d --- /dev/null +++ b/hicn-light/src/hicn/config/controlSet.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..a18c860af --- /dev/null +++ b/hicn-light/src/hicn/config/controlSetDebug.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +static CommandReturn _controlSetDebug_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlSetDebug_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("set debug: will enable the debug flag for more verbose output\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlSetDebug_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + if (parcList_Size(args) != 2) { + _controlSetDebug_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + ControlState *state = ops->closure; + controlState_SetDebug(state, true); + printf("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 new file mode 100644 index 000000000..fabeb6952 --- /dev/null +++ b/hicn-light/src/hicn/config/controlSetDebug.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..c7909bbb7 --- /dev/null +++ b/hicn-light/src/hicn/config/controlSetStrategy.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +static CommandReturn _controlSetStrategy_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +static const char *_commandSetStrategy = "set strategy"; +static const char *_commandSetStrategyHelp = "help set strategy"; + +static const char *_commandSetStrategyOptions[LAST_STRATEGY_VALUE] = { + "loadbalancer", + "random", + "random_per_dash_segment", + "loadbalancer_with_delay", + "loadbalancer_by_rate", + "loadbalancer_best_route"}; + +// ==================================================== + +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 CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + printf("set strategy \n"); + printf("prefix: ipv4/ipv6 address (ex: 1234::/64)\n"); + printf("strategy: strategy identifier\n"); + printf("available strategies:\n"); + printf(" random\n"); + printf(" loadbalancer\n"); + printf(" random_per_dash_segment\n"); + printf(" loadbalancer_with_delay\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlSetStrategy_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 4) { + _controlSetStrategy_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + if (((strcmp(parcList_GetAtIndex(args, 0), "set") != 0) || + (strcmp(parcList_GetAtIndex(args, 1), "strategy") != 0))) { + _controlSetStrategy_HelpExecute(parser, ops, args); + 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 = UINT32_MAX; + strcpy(addr, prefixStr); + slash = strrchr(addr, '/'); + if (slash != NULL) { + len = atoi(slash + 1); + *slash = '\0'; + } + if (len == 0) { + printf("ERROR: a prefix can not be of length 0\n"); + free(addr); + return CommandReturn_Failure; + } + + // allocate command payload + set_strategy_command *setStrategyCommand = + parcMemory_AllocateAndClear(sizeof(set_strategy_command)); + + // check and set IP address + if (inet_pton(AF_INET, addr, &setStrategyCommand->address.ipv4) == 1) { + if (len == UINT32_MAX) { + printf("Netmask not specified: set to 32 by default\n"); + len = 32; + } else if (len > 32) { + printf("ERROR: exceeded INET mask length, max=32\n"); + parcMemory_Deallocate(&setStrategyCommand); + free(addr); + return CommandReturn_Failure; + } + setStrategyCommand->addressType = ADDR_INET; + } else if (inet_pton(AF_INET6, addr, &setStrategyCommand->address.ipv6) == + 1) { + if (len == UINT32_MAX) { + printf("Netmask not specified: set to 128 by default\n"); + len = 128; + } else if (len > 128) { + printf("ERROR: exceeded INET6 mask length, max=128\n"); + parcMemory_Deallocate(&setStrategyCommand); + free(addr); + return CommandReturn_Failure; + } + setStrategyCommand->addressType = ADDR_INET6; + } else { + printf("Error: %s is not a valid network address \n", addr); + parcMemory_Deallocate(&setStrategyCommand); + return CommandReturn_Failure; + } + + const char *strategyStr = parcList_GetAtIndex(args, 3); + // check valid strategy + strategy_type strategy; + if ((strategy = _validStrategy(strategyStr)) == LAST_STRATEGY_VALUE) { + printf("Error: invalid strategy \n"); + parcMemory_Deallocate(&setStrategyCommand); + _controlSetStrategy_HelpExecute(parser, ops, args); + free(addr); + return CommandReturn_Failure; + } + + free(addr); + + // Fill remaining payload fields + setStrategyCommand->len = len; + setStrategyCommand->strategyType = strategy; + + // 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 new file mode 100644 index 000000000..7ad56ccba --- /dev/null +++ b/hicn-light/src/hicn/config/controlSetStrategy.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..22729705a --- /dev/null +++ b/hicn-light/src/hicn/config/controlSetWldr.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +static CommandReturn _controlSetWldr_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlSetWldr_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("set wldr \n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlSetWldr_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + ControlState *state = ops->closure; + + if (parcList_Size(args) != 4) { + _controlSetWldr_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + if (((strcmp(parcList_GetAtIndex(args, 0), "set") != 0) || + (strcmp(parcList_GetAtIndex(args, 1), "wldr") != 0))) { + _controlSetWldr_HelpExecute(parser, ops, args); + 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); + return CommandReturn_Failure; + } + + // check if valid connid + const char *symbolicOrConnid = parcList_GetAtIndex(args, 3); + + if (!utils_ValidateSymbolicName(symbolicOrConnid) && + !utils_IsNumber(symbolicOrConnid)) { + printf( + "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 new file mode 100644 index 000000000..3c01110e4 --- /dev/null +++ b/hicn-light/src/hicn/config/controlSetWldr.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +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 new file mode 100644 index 000000000..ad26c1bab --- /dev/null +++ b/hicn-light/src/hicn/config/controlState.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define SRV_IP "127.0.0.1" +#define PORT 9695 + +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() { + int sockfd; + struct sockaddr_in servaddr; + + if ((sockfd = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("\nSocket Creation Failed \n"); + exit(EXIT_FAILURE); + } + + memset(&servaddr, 0, sizeof(servaddr)); + + // Filling server information + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(PORT); + inet_pton(AF_INET, SRV_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"); + exit(EXIT_FAILURE); + } + + return sockfd; +} + +ControlState *controlState_Create( + void *userdata, + struct iovec *(*writeRead)(ControlState *state, struct iovec *msg), + bool openControllerConnetion) { + 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(); + } 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) { + parcAssertNotNull(state, "Parameter state must be non-null"); + return commandParser_DispatchCommand(state->parser, args); +} + +int controlState_Interactive(ControlState *state) { + parcAssertNotNull(state, "Parameter state must be non-null"); + char *line = NULL; + size_t linecap = 0; + CommandReturn controlReturn = CommandReturn_Success; + + 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); + // 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; + } +} \ No newline at end of file diff --git a/hicn-light/src/hicn/config/controlState.h b/hicn-light/src/hicn/config/controlState.h new file mode 100644 index 000000000..25542657f --- /dev/null +++ b/hicn-light/src/hicn/config/controlState.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include + +#include + +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); + +/** + * 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 + * + * @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); + +/** + * 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 new file mode 100644 index 000000000..b0950c141 --- /dev/null +++ b/hicn-light/src/hicn/config/controlUnset.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +static void _controlUnset_Init(CommandParser *parser, CommandOps *ops); + +static CommandReturn _controlUnset_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args); +static CommandReturn _controlUnset_HelpExecute(CommandParser *parser, + CommandOps *ops, PARCList *args); + +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) { + CommandOps *ops_help_unset_debug = controlUnsetDebug_HelpCreate(NULL); + + printf("Available commands:\n"); + printf(" %s\n", ops_help_unset_debug->command); + printf("\n"); + + commandOps_Destroy(&ops_help_unset_debug); + return CommandReturn_Success; +} + +static CommandReturn _controlUnset_Execute(CommandParser *parser, + CommandOps *ops, PARCList *args) { + return _controlUnset_HelpExecute(parser, ops, args); +} diff --git a/hicn-light/src/hicn/config/controlUnset.h b/hicn-light/src/hicn/config/controlUnset.h new file mode 100644 index 000000000..9d9cb5c44 --- /dev/null +++ b/hicn-light/src/hicn/config/controlUnset.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +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 new file mode 100644 index 000000000..87ad24fce --- /dev/null +++ b/hicn-light/src/hicn/config/controlUnsetDebug.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +static CommandReturn _controlUnsetDebug_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args); +static CommandReturn _controlUnsetDebug_HelpExecute(CommandParser *parser, + CommandOps *ops, + PARCList *args); + +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) { + printf("unset debug: will disable the debug flag\n"); + printf("\n"); + return CommandReturn_Success; +} + +static CommandReturn _controlUnsetDebug_Execute(CommandParser *parser, + CommandOps *ops, + PARCList *args) { + if (parcList_Size(args) != 2) { + _controlUnsetDebug_HelpExecute(parser, ops, args); + return CommandReturn_Failure; + } + + ControlState *state = ops->closure; + controlState_SetDebug(state, false); + printf("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 new file mode 100644 index 000000000..c76ba8c98 --- /dev/null +++ b/hicn-light/src/hicn/config/controlUnsetDebug.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +CommandOps *controlUnsetDebug_Create(ControlState *state); +CommandOps *controlUnsetDebug_HelpCreate(ControlState *state); +#endif // Control_UnsetDebug_h diff --git a/hicn-light/src/hicn/config/symbolicNameTable.c b/hicn-light/src/hicn/config/symbolicNameTable.c new file mode 100644 index 000000000..7ddb20668 --- /dev/null +++ b/hicn-light/src/hicn/config/symbolicNameTable.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +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 *key = _createKey(symbolicName); + + uint32_t *value = parcMemory_Allocate(sizeof(uint32_t)); + *value = connid; + + bool success = parcHashCodeTable_Add(table->symbolicNameTable, key, value); + success = parcHashCodeTable_Add(table->indexToNameTable, value, key); + if (!success) { + parcMemory_Deallocate((void **)&key); + parcMemory_Deallocate((void **)&value); + } + + 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 new file mode 100644 index 000000000..69919cf00 --- /dev/null +++ b/hicn-light/src/hicn/config/symbolicNameTable.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +/** + * 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 new file mode 100644 index 000000000..85643cf5e --- /dev/null +++ b/hicn-light/src/hicn/content_store/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +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 +) + +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 +) + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/content_store/contentStoreEntry.c b/hicn-light/src/hicn/content_store/contentStoreEntry.c new file mode 100644 index 000000000..1e03f42b6 --- /dev/null +++ b/hicn-light/src/hicn/content_store/contentStoreEntry.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include + +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 new file mode 100644 index 000000000..4f0fd19c1 --- /dev/null +++ b/hicn-light/src/hicn/content_store/contentStoreEntry.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include + +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 + * contentStoreEntry_Destroy() 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 new file mode 100644 index 000000000..b82fa906e --- /dev/null +++ b/hicn-light/src/hicn/content_store/contentStoreInterface.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +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 new file mode 100644 index 000000000..b2bc3f919 --- /dev/null +++ b/hicn-light/src/hicn/content_store/contentStoreInterface.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +#include + +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 new file mode 100644 index 000000000..6add33d78 --- /dev/null +++ b/hicn-light/src/hicn/content_store/contentStoreLRU.c @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +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; + } + + 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 new file mode 100644 index 000000000..94ec4d6b2 --- /dev/null +++ b/hicn-light/src/hicn/content_store/contentStoreLRU.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +/** + * 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 new file mode 100644 index 000000000..0a75c01a1 --- /dev/null +++ b/hicn-light/src/hicn/content_store/listLRU.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include +#include +#include + +#include +#include +#include + +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 new file mode 100644 index 000000000..75f698b61 --- /dev/null +++ b/hicn-light/src/hicn/content_store/listLRU.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 LruEntry_Destroy() 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 new file mode 100644 index 000000000..33808349b --- /dev/null +++ b/hicn-light/src/hicn/content_store/listTimeOrdered.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include + +/** + * 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 new file mode 100644 index 000000000..325e7c0d4 --- /dev/null +++ b/hicn-light/src/hicn/content_store/listTimeOrdered.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include + +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/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt new file mode 100644 index 000000000..1d7dc03e9 --- /dev/null +++ b/hicn-light/src/hicn/core/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.h + ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h + ${CMAKE_CURRENT_SOURCE_DIR}/connectionList.h + ${CMAKE_CURRENT_SOURCE_DIR}/connectionTable.h + ${CMAKE_CURRENT_SOURCE_DIR}/connection.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}/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 +) + +list(APPEND SOURCE_FILES + ${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}/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}/mapMe.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) \ No newline at end of file diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c new file mode 100644 index 000000000..36fb20ec9 --- /dev/null +++ b/hicn-light/src/hicn/core/connection.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct connection { + const AddressPair *addressPair; + IoOperations *ops; + + unsigned refCount; + + bool probing_active; + unsigned probing_interval; + unsigned counter; + Ticks last_sent; + Ticks delay; + + bool wldrAutoStart; // if true, wldr can be set automatically + // by default this value is set to true. + // if wldr is activated using a command (config + // file/hicnLightControl) this value is set to false so + // that a base station can not disable wldr at the client + Wldr *wldr; +}; + +Connection *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; + conn->probing_active = false; + + conn->wldrAutoStart = true; + conn->probing_interval = 0; + conn->counter = 0; + conn->last_sent = 0; + conn->delay = INT_MAX; + return conn; +} + +Connection *connection_Acquire(Connection *connection) { + parcAssertNotNull(connection, "Parameter conn must be non-null"); + connection->refCount++; + return connection; +} + +void connection_Release(Connection **connectionPtr) { + parcAssertNotNull(connectionPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*connectionPtr, + "Parameter must dereference to non-null pointer"); + Connection *conn = *connectionPtr; + + parcAssertTrue( + conn->refCount > 0, + "Invalid state, connection reference count should be positive, got 0."); + conn->refCount--; + if (conn->refCount == 0) { + // don't destroy addressPair, its part of ops. + ioOperations_Release(&conn->ops); + if (conn->wldr != NULL) { + wldr_Destroy(&(conn->wldr)); + } + parcMemory_Deallocate((void **)&conn); + } + *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 (conn->wldr != NULL) { + wldr_SetLabel(conn->wldr, message); + } else { + message_ResetWldrLabel(message); + } + return ioOperations_Send(conn->ops, NULL, message); + } + return false; +} + +bool connection_SendCommandResponse(const Connection *conn, struct iovec *msg){ + parcAssertNotNull(conn, "Parameter conn must be non-null"); + parcAssertNotNull(msg, "Parameter message must be non-null"); + + return ioOperations_SendCommandResponse(conn->ops, msg); +} + +static void _sendProbe(Connection *conn, unsigned probeType, uint8_t *message) { + parcAssertNotNull(conn, "Parameter conn must be non-null"); + + if (probeType == PACKET_TYPE_PROBE_REQUEST) { + Ticks now = ioOperations_SendProbe(conn->ops, probeType, message); + if (now != 0) { + conn->last_sent = now; + } + } else { + ioOperations_SendProbe(conn->ops, probeType, message); + } +} + +void connection_Probe(Connection *conn) { + _sendProbe(conn, PACKET_TYPE_PROBE_REQUEST, NULL); +} + +void connection_HandleProbe(Connection *conn, uint8_t *probe, + Ticks actualTime) { + parcAssertNotNull(conn, "Parameter conn must be non-null"); + parcAssertNotNull(probe, "Parameter pkt must be non-null"); + + uint8_t probeType = messageHandler_GetProbePacketType(probe); + if (probeType == PACKET_TYPE_PROBE_REQUEST) { + _sendProbe(conn, PACKET_TYPE_PROBE_REPLY, probe); + } else if (probeType == PACKET_TYPE_PROBE_REPLY) { + Ticks delay = actualTime - conn->last_sent; + if (delay == 0) { + delay = 1; + } + if (delay < conn->delay) { + conn->delay = delay; + } + } else { + printf("receivde unkwon probe type\n"); + } +} + +uint64_t connection_GetDelay(Connection *conn) { return (uint64_t)conn->delay; } + +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); +} + +const void *connection_Class(const Connection *conn) { + parcAssertNotNull(conn, "Parameter conn must be non-null"); + return ioOperations_Class(conn->ops); +} + +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); + } + } + + if (notification) { + // the notification is never destroyed + message_Release(&message); + } + + return res; +} + +void connection_AllowWldrAutoStart(Connection *conn, bool allow) { + conn->wldrAutoStart = allow; +} + +void connection_EnableWldr(Connection *conn) { + if (!connection_IsLocal(conn)) { + if (conn->wldr == NULL) { + printf("----------------- enable wldr\n"); + conn->wldr = wldr_Init(); + } + } +} + +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_HasWldr(const Connection *conn) { + if (conn->wldr == NULL) { + return false; + } else { + return true; + } +} + +bool connection_WldrAutoStartAllowed(const Connection *conn) { + return conn->wldrAutoStart; +} + +void connection_DetectLosses(Connection *conn, Message *message) { + if (conn->wldr != NULL) wldr_DetectLosses(conn->wldr, conn, message); +} + +void connection_HandleWldrNotification(Connection *conn, Message *message) { + if (conn->wldr != NULL) + wldr_HandleWldrNotification(conn->wldr, conn, message); +} diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h new file mode 100644 index 000000000..efe8a66b9 --- /dev/null +++ b/hicn-light/src/hicn/core/connection.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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.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. + * + */ + +#ifndef connection_h +#define connection_h +#include +#include +#include + +// packet types for probing +#define PACKET_TYPE_PROBE_REQUEST 5 +#define PACKET_TYPE_PROBE_REPLY 6 + +struct connection; +typedef struct connection Connection; + +/** + * Creates a connection object. + */ +Connection *connection_Create(IoOperations *ops); + +/** + * @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); + +/** + * @function connection_Acquire + * @abstract A reference counted copy. + * @discussion + * A shallow copy, they share the same memory. + */ +Connection *connection_Acquire(Connection *connection); + +/** + * @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); + +/** + * @function connection_SendCommandResponse + * @abstract Sends a response (ack/nack) for a command + */ +bool connection_SendCommandResponse(const Connection *conn, struct iovec *msg); + +/** + * 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); + +/** + * 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); + +/** + * 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); + +/** + * 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); + +/** + * 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); + +/** + * 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); + +bool connection_ReSend(const Connection *conn, Message *message, + bool notification); + +void connection_Probe(Connection *conn); + +void connection_HandleProbe(Connection *conn, uint8_t *message, + Ticks actualTime); + +uint64_t connection_GetDelay(Connection *conn); + +void connection_AllowWldrAutoStart(Connection *conn, bool allow); + +void connection_EnableWldr(Connection *conn); + +void connection_DisableWldr(Connection *conn); + +bool connection_HasWldr(const Connection *conn); + +bool connection_WldrAutoStartAllowed(const Connection *conn); + +void connection_DetectLosses(Connection *conn, Message *message); + +void connection_HandleWldrNotification(Connection *conn, Message *message); +#endif // connection_h diff --git a/hicn-light/src/hicn/core/connectionList.c b/hicn-light/src/hicn/core/connectionList.c new file mode 100644 index 000000000..cc76f84de --- /dev/null +++ b/hicn-light/src/hicn/core/connectionList.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include +#include + +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 new file mode 100644 index 000000000..fbba9f6d8 --- /dev/null +++ b/hicn-light/src/hicn/core/connectionList.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +/** + * 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 new file mode 100644 index 000000000..0b2c51f9c --- /dev/null +++ b/hicn-light/src/hicn/core/connectionManager.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include +#include +#include + +#include + +#include + +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 new file mode 100644 index 000000000..34fee8717 --- /dev/null +++ b/hicn-light/src/hicn/core/connectionManager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 new file mode 100644 index 000000000..b0f717bc6 --- /dev/null +++ b/hicn-light/src/hicn/core/connectionTable.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +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(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 new file mode 100644 index 000000000..bd8f553c2 --- /dev/null +++ b/hicn-light/src/hicn/core/connectionTable.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include + +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(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/dispatcher.c b/hicn-light/src/hicn/core/dispatcher.c new file mode 100644 index 000000000..8d39e651a --- /dev/null +++ b/hicn-light/src/hicn/core/dispatcher.c @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#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 new file mode 100644 index 000000000..e5c2df336 --- /dev/null +++ b/hicn-light/src/hicn/core/dispatcher.h @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include + +struct dispatcher; +typedef struct dispatcher Dispatcher; + +#include +#include +#include +#include +#include +#include +#include + +#include + +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 dispatcher_WaitForStopped() 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 dispatcher_Stop() 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 forwarder_NewBind() + * that received the client connection + * @constant client_socket is the client socket + * @constant user_data is the user_data passed to + * forwarder_NewBind() + * @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 + * Forwarder_CreateEvent() + */ +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 + * forwarder_StartTimer() + * + * @param isPeriodic means the timer will fire repeatidly, otherwise it is a + * one-shot and needs to be set again with dispatcher_StartTimer() + */ +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 + * forwarder_StartNetworkEvent() + * + * @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 + * forwarder_StartSignalEvent() + * + * @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 +#include + +/** + * @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/forwarder.c b/hicn-light/src/hicn/core/forwarder.c new file mode 100644 index 000000000..9b05304e8 --- /dev/null +++ b/hicn-light/src/hicn/core/forwarder.c @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Event based router + * + * This module is the glue around the event scheduler. + * Its the packet i/o module. + * + * Packet processing is done in dispatcher.c, which is the actual wrapper around + * the event scheduler + */ + +#ifndef _WIN32 +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __STDC_FORMAT_MACROS +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef WITH_MAPME +#include +#endif /* WITH_MAPME */ +#include +#include +#include +#include + +#include + +#include + +// the router's clock frequency (we now use the monotonic clock) +#define HZ 1000 + +// these will all be a little off because its all integer division +#define MSEC_PER_TICK (1000 / HZ) +#define USEC_PER_TICK (1000000 / HZ) +#define NSEC_PER_TICK ((1000000000ULL) / HZ) +#define MSEC_TO_TICKS(msec) \ + ((msec < FC_MSEC_PER_TICK) ? 1 : msec / FC_MSEC_PER_TICK) +#define NSEC_TO_TICKS(nsec) ((nsec < NSEC_PER_TICK) ? 1 : nsec / NSEC_PER_TICK) + +struct forwarder { + Dispatcher *dispatcher; + + uint16_t server_port; + + PARCEventSignal *signal_int; + PARCEventSignal *signal_term; +#ifndef _WIN32 + PARCEventSignal *signal_usr1; +#endif + PARCEventTimer *keepalive_event; + + // will skew the virtual clock forward. In normal operaiton, it is 0. + Ticks clockOffset; + + unsigned nextConnectionid; + Messenger *messenger; + ConnectionManager *connectionManager; + ConnectionTable *connectionTable; + ListenerSet *listenerSet; + Configuration *config; + + // we'll eventually want to setup a threadpool of these + MessageProcessor *processor; + + Logger *logger; + + PARCClock *clock; + + hicn_socket_helper_t + *hicnSocketHelper; // state required to manage hicn connections + + // used by seed48 and nrand48 + unsigned short seed[3]; + +#ifdef WITH_MAPME + MapMe *mapme; +#endif /* WITH_MAPME */ +}; + +// 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) { +#ifndef _WIN32 + int fd; + ssize_t res; + + res = -1; + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + res = read(fd, forwarder->seed, sizeof(forwarder->seed)); + close(fd); + } + if (res != sizeof(forwarder->seed)) { + forwarder->seed[1] = (unsigned short)getpid(); /* better than no entropy */ + forwarder->seed[2] = (unsigned short)time(NULL); + } + /* + * The call to seed48 is needed by cygwin, and should be harmless + * on other platforms. + */ + seed48(forwarder->seed); +#else + forwarder->seed[1] = (unsigned short)getpid(); /* better than no entropy */ + forwarder->seed[2] = (unsigned short)time(NULL); +#endif +} + +Logger *forwarder_GetLogger(const Forwarder *forwarder) { + return forwarder->logger; +} + +// ============================================================================ +// Setup and destroy section + +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->clock = parcClock_Monotonic(); + forwarder->clockOffset = 0; + + 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->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 + +#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING) + forwarder->hicnSocketHelper = hicn_create(); + if (forwarder->hicnSocketHelper == NULL) return NULL; +#endif /* __APPLE__ */ + /* ignore child */ +#ifndef _WIN32 + signal(SIGCHLD, SIG_IGN); + + /* ignore tty signals */ + signal(SIGTSTP, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); +#endif + + // We no longer use this for ticks, but we need to have at least one event + // schedule to keep Libevent happy. + + struct timeval wtnow_timeout; + timerclear(&wtnow_timeout); + + wtnow_timeout.tv_sec = 0; + wtnow_timeout.tv_usec = 50000; // 20 Hz keepalive + +#ifdef WITH_MAPME + if (!(mapMe_Init(&forwarder->mapme, forwarder))) return NULL; +#endif /* WITH_MAPME */ + + 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); + + return forwarder; +} + +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_destroy(); +#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)); + + // the messenger is used by many of the other pieces, so destroy it last + 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); + *ptr = NULL; +} + +void forwarder_SetupAllListeners(Forwarder *forwarder, uint16_t port, + const char *localPath) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + + configurationListeners_SetupAll(forwarder->config, port, localPath); +} + +void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + configurationListeners_SetutpLocalIPv4(forwarder->config, port); +} + +void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename) { + ConfigurationFile *configFile = configurationFile_Create(forwarder, filename); + if (configFile) { + configurationFile_Process(configFile); + configurationFile_Release(&configFile); + } +} + +Configuration *forwarder_GetConfiguration(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return forwarder->config; +} + +// ============================================================================ + +unsigned forwarder_GetNextConnectionId(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return forwarder->nextConnectionid++; +} + +Messenger *forwarder_GetMessenger(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return forwarder->messenger; +} + +Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return forwarder->dispatcher; +} + +ConnectionTable *forwarder_GetConnectionTable(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return forwarder->connectionTable; +} + +ListenerSet *forwarder_GetListenerSet(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return forwarder->listenerSet; +} + +void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + messageProcessor_SetCacheStoreFlag(forwarder->processor, val); +} + +bool forwarder_GetChacheStoreFlag(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return messageProcessor_GetCacheStoreFlag(forwarder->processor); +} + +void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + messageProcessor_SetCacheServeFlag(forwarder->processor, val); +} + +bool forwarder_GetChacheServeFlag(Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return messageProcessor_GetCacheServeFlag(forwarder->processor); +} + +void forwarder_ReceiveCommand(Forwarder *forwarder, command_id command, + struct iovec *message, unsigned ingressId) { + configuration_ReceiveCommand(forwarder->config, command, message, ingressId); +} + +void forwarder_Receive(Forwarder *forwarder, Message *message) { + parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null"); + parcAssertNotNull(message, "Parameter message must be non-null"); + + // this takes ownership of the message, so we're done here + + // 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)); + + if (!conn) { + return; + } + + if (message_HasWldr(message)) { + if (connection_HasWldr(conn)) { + // case 1: WLDR is enabled + connection_DetectLosses((Connection *)conn, message); + } else if (!connection_HasWldr(conn) && + connection_WldrAutoStartAllowed(conn)) { + // case 2: We are on an AP. We enable WLDR + connection_EnableWldr((Connection *)conn); + connection_DetectLosses((Connection *)conn, message); + } + // case 3: Ignore WLDR + } else { + if (connection_HasWldr(conn) && connection_WldrAutoStartAllowed(conn)) { + // case 1: STA do not use WLDR, we disable it + connection_DisableWldr((Connection *)conn); + } + } + + messageProcessor_Receive(forwarder->processor, message); +} + +Ticks forwarder_GetTicks(const Forwarder *forwarder) { + parcAssertNotNull(forwarder, "Parameter must be non-null"); + return parcClock_GetTime(forwarder->clock) + forwarder->clockOffset; +} + +Ticks forwarder_NanosToTicks(uint64_t nanos) { return NSEC_TO_TICKS(nanos); } + +uint64_t forwarder_TicksToNanos(Ticks ticks) { + return (1000000000ULL) * ticks / HZ; +} + +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"); + + // we only have one message processor + bool res = + messageProcessor_AddOrUpdateRoute(forwarder->processor, control, ifidx); + + return res; +} + +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"); + + // we only have one message processor + return messageProcessor_RemoveRoute(forwarder->processor, control, ifidx); +} + +void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder, + unsigned connectionId) { + parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null"); + messageProcessor_RemoveConnectionIdFromRoutes(forwarder->processor, + connectionId); +} + +void forwarder_SetStrategy(Forwarder *forwarder, Name *prefix, + strategy_type strategy) { + parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null"); + parcAssertNotNull(prefix, "Parameter prefix must be non-null"); + + // if (strategy == NULL) { + // strategy = SET_STRATEGY_RANDOM; + // } + + processor_SetStrategy(forwarder->processor, prefix, strategy); +} + +FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder) { + return messageProcessor_GetFibEntries(forwarder->processor); +} + +void forwarder_SetContentObjectStoreSize(Forwarder *forwarder, + size_t maximumContentStoreSize) { + messageProcessor_SetContentObjectStoreSize(forwarder->processor, + maximumContentStoreSize); +} + +void forwarder_ClearCache(Forwarder *forwarder) { + messageProcessor_ClearCache(forwarder->processor); +} + +PARCClock *forwarder_GetClock(const Forwarder *forwarder) { + return forwarder->clock; +} + +hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder) { + return forwarder->hicnSocketHelper; +} + +// ======================================================= + +static void _signal_cb(int sig, PARCEventType events, void *user_data) { + Forwarder *forwarder = (Forwarder *)user_data; + + logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning, + __func__, "signal %d events %d", sig, events); + + switch ((int)sig) { + case SIGTERM: + logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning, + __func__, "Caught an terminate signal; exiting cleanly."); + dispatcher_Stop(forwarder->dispatcher); + break; + + case SIGINT: + logger_Log(forwarder->logger, LoggerFacility_Core, PARCLogLevel_Warning, + __func__, "Caught an interrupt signal; exiting cleanly."); + dispatcher_Stop(forwarder->dispatcher); + break; +#ifndef _WIN32 + case SIGUSR1: + // dump stats + break; +#endif + + default: + 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 +} + +#ifdef WITH_MAPME +FIB *forwarder_getFib(Forwarder *forwarder) { + return messageProcessor_getFib(forwarder->processor); +} + +void forwarder_onConnectionAdded(Forwarder *forwarder, const Connection *conn) { + mapMe_onConnectionAdded(forwarder->mapme, conn); +} + +void forwarder_onConnectionRemoved(Forwarder *forwarder, + const Connection *conn) {} + +void forwarder_ProcessMapMe(Forwarder *forwarder, uint8_t *msgBuffer, + unsigned conn_id) { + mapMe_Process(forwarder->mapme, msgBuffer, conn_id); +} + +#endif /* WITH_MAPME */ diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h new file mode 100644 index 000000000..c1b279d2e --- /dev/null +++ b/hicn-light/src/hicn/core/forwarder.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 methods in this header are for the non-threaded forwarder. They should + * only be called within the forwarders thread of execution. + */ + +#ifndef forwarder_h +#define forwarder_h + +#ifndef _WIN32 +#include +#endif +#include + +#include +#include +#include + +#include + +#include + +#ifdef WITH_MAPME +#include +#endif /* WITH_MAPME */ + +#include +#include +#include + +#include + +#include + +#include + +#define PORT_NUMBER 9695 +#define PORT_NUMBER_AS_STRING "9695" + +#include + +// ============================================== + +struct forwarder; +typedef struct forwarder Forwarder; + +/** + * @function forwarder_Create + * @abstract 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); + +/** + * @function forwarder_Destroy + * @abstract Destroys the forwarder, stopping all traffic and freeing all memory + */ +void forwarder_Destroy(Forwarder **ptr); + +/** + * @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 + * given port + */ +void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port); + +/** + * Configure hicn-light via a configuration file + * + * The configuration file is a set of lines, just like used in hicnLightControl. + * You need to have "add listener" lines in the file to receive connections. No + * default listeners are configured. + * + * @param [in] forwarder An alloated Forwarder + * @param [in] filename The path to the configuration file + */ +void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename); + +/** + * Returns the logger used by this forwarder + * + * If you will store the logger, you should acquire a reference to it. + * + * @param [in] forwarder An allocated hicn-light forwarder + * + * @retval non-null The logger used by hicn-light + * @retval null An error + */ +Logger *forwarder_GetLogger(const Forwarder *forwarder); + +/** + * @function forwarder_SetLogLevel + * @abstract Sets the minimum level to log + */ +void forwarder_SetLogLevel(Forwarder *forwarder, PARCLogLevel level); + +/** + * @function forwarder_GetNextConnectionId + * @abstract Get the next identifier for a new connection + */ +unsigned forwarder_GetNextConnectionId(Forwarder *forwarder); + +Messenger *forwarder_GetMessenger(Forwarder *forwarder); + +Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder); + +/** + * Returns the set of currently active listeners + * + * @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); + +/** + * Returns the forwrder's connection table + * + * @param [in] forwarder An allocated hicn-light forwarder + * + * @retval non-null The connection tabler + * @retval null An error + * + */ +ConnectionTable *forwarder_GetConnectionTable(Forwarder *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); + +/** + * 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); + +/** + * Convert nano seconds to Ticks + * + * Converts nano seconds to Ticks, based on HZ (in forwarder.c) + */ +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_Receive(Forwarder *forwarder, Message *mesage); + +/** + * @function forwarder_AddOrUpdateRoute + * @abstract Adds or updates a route on all the message processors + */ +bool forwarder_AddOrUpdateRoute(Forwarder *forwarder, + add_route_command *control, unsigned ifidx); + +/** + * @function forwarder_RemoveRoute + * @abstract Removes a route from all the message processors + */ +bool forwarder_RemoveRoute(Forwarder *forwarder, remove_route_command *control, + unsigned ifidx); + +/** + * Removes a connection id from all routes + */ +void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder, + unsigned connectionId); + +/** + * @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); + +FibEntryList *forwarder_GetFibEntries(Forwarder *forwarder); + +/** + * Sets the maximum number of content objects in the content store + * + * Implementation dependent - may wipe the cache. + */ +void forwarder_SetContentObjectStoreSize(Forwarder *forwarder, + size_t maximumContentStoreSize); + +void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val); + +bool forwarder_GetChacheStoreFlag(Forwarder *forwarder); + +void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val); + +bool forwarder_GetChacheServeFlag(Forwarder *forwarder); + +void forwarder_ClearCache(Forwarder *forwarder); + +void forwarder_SetStrategy(Forwarder *forwarder, Name *prefix, + strategy_type strategy); + +hicn_socket_helper_t *forwarder_GetHicnSocketHelper(Forwarder *forwarder); + +#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); + +/** + * @function forwarder_onConnectionAdded + * @abstract 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. + */ +void forwarder_onConnectionAdded(Forwarder *forwarder, const Connection *conn); + +/** + * @function forwarder_onConnectionRemoved + * @abstract Callback fired upon removal of a connection through the control + * protocol. + * @param [in] forwarder - Pointer to the hICN forwarder. + * @param [in] conn - Pointer to the removed connection. + */ +void forwarder_onConnectionRemoved(Forwarder *forwarder, + const Connection *conn); + +/** + * @function forwarder_ProcessMapMe + * @abstract 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 + */ +void forwarder_ProcessMapMe(Forwarder *forwarder, uint8_t *msgBuffer, + unsigned conn_id); + +#endif /* WITH_MAPME */ + +#endif // forwarder_h diff --git a/hicn-light/src/hicn/core/logger.c b/hicn-light/src/hicn/core/logger.c new file mode 100644 index 000000000..9399b9857 --- /dev/null +++ b/hicn-light/src/hicn/core/logger.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +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 = 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 new file mode 100644 index 000000000..c46a87097 --- /dev/null +++ b/hicn-light/src/hicn/core/logger.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#endif +#include +#include +#include +#include +#include + +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_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 new file mode 100644 index 000000000..74ff1ed96 --- /dev/null +++ b/hicn-light/src/hicn/core/mapMe.c @@ -0,0 +1,813 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file mapMe.c + * @brief MAP-Me : AnchorLess Producer Mobility Management. + */ + +#ifdef WITH_MAPME + +#include +#include +#include // printf + +#include +#include +#include +#include +#include // packet types +#include +#include +#include + +#include +#include +#include +#include + +#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 NOT_A_NOTIFICATION false +#define NO_INGRESS 0 +#define TIMER_NO_REPEAT false + +#define DO_DISCOVERY 1 +#define MAPME_INVALID_DICOVERY_SEQ -1 + +#define LOG_FACILITY LoggerFacility_Core + +#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) + +#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__) + +/** + * MAP-Me state data structure + */ +struct mapme { + uint32_t retx; /* ms */ + uint32_t Tu; /* ms */ + bool removeFibEntries; + + Forwarder *forwarder; +}; + +static MapMe MapMeDefault = {.retx = MAPME_DEFAULT_RETX, + .Tu = MAPME_DEFAULT_TU, + .removeFibEntries = false}; + +/******************************************************************************/ + +#include + +bool mapMe_Init(MapMe **mapme, Forwarder *forwarder) { + *mapme = malloc(sizeof(MapMe)); + if (!mapme) goto ERR_MALLOC; + + /* Internal state : set default values */ + memcpy(*mapme, &MapMeDefault, sizeof(MapMe)); + + (*mapme)->forwarder = forwarder; + + /* Install hook on Face events to onConnectionAdded */ + // see. config/configuration.c + + /* Install hook for signalization processing. See : + * - io/hicnListener.c + * - src/core/connection.{c,h} + */ + + return true; + +ERR_MALLOC: + return false; +} + +/****************************************************************************** + * TFIB + ******************************************************************************/ + +#define INVALID_SEQ 0 +#define INIT_SEQ 1 + +typedef struct { + uint32_t seq; + PARCHashMap *nexthops; + /* Update/Notification heuristic */ + Ticks lastAckedUpdate; // XXX This is only for producer !!! +} MapMeTFIB; + +static MapMeTFIB *mapMeTFIB_Create() { + MapMeTFIB *tfib; + tfib = malloc(sizeof(MapMeTFIB)); + if (!tfib) goto ERR_MALLOC; + tfib->seq = 0; + tfib->lastAckedUpdate = 0; + tfib->nexthops = parcHashMap_Create(); + if (!tfib->nexthops) goto ERR_HASHMAP; + + return tfib; + +ERR_HASHMAP: + free(tfib); +ERR_MALLOC: + return NULL; +} + +void mapMeTFIB_Release(MapMeTFIB **tfibPtr) { + MapMeTFIB *tfib = *tfibPtr; + parcHashMap_Release(&tfib->nexthops); + free(tfib); + *tfibPtr = NULL; +} + +/** + * @function mapMe_CreateTFIB + * @abstract Associate a new TFIB entry to a FIB entry. + * @param [in] - Pointer to the FIB entry. + * @return Boolean indicating the success of the operation. + */ +static void mapMe_CreateTFIB(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, tfib, (void (*)(void **))mapMeTFIB_Release); +} + +#define TFIB(fibEntry) ((MapMeTFIB *)fibEntry_getUserData(fibEntry)) + +static const PARCEventTimer *mapMeTFIB_Get(const MapMeTFIB *tfib, + unsigned conn_id) { + const PARCEventTimer *timer; + const PARCBuffer *buffer; + PARCUnsigned *cid = parcUnsigned_Create(conn_id); + buffer = parcHashMap_Get(tfib->nexthops, cid); + if (!buffer) return NULL; + PARCByteArray *array = parcBuffer_Array(buffer); + timer = *((PARCEventTimer **)parcByteArray_Array(array)); + parcUnsigned_Release(&cid); + return timer; +} + +static void mapMeTFIB_Put(MapMeTFIB *tfib, unsigned conn_id, + const PARCEventTimer *timer) { + /* NOTE: Timers are not objects (the only class not being an object in + * fact), and as such, we cannot use them as values for the HashMap. + * Just like for unsigned we needed the PARC wrapper. + * There is no wrapper for pointers, so we use Arrays, which has an ubly + * syntax... + */ + PARCUnsigned *cid = parcUnsigned_Create(conn_id); + PARCBuffer *buffer = + parcBuffer_CreateFromArray(&timer, sizeof(PARCEventTimer *)); + parcHashMap_Put(tfib->nexthops, cid, buffer); + parcUnsigned_Release(&cid); + parcBuffer_Release(&buffer); +} + +static void mapMeTFIB_Remove(MapMeTFIB *tfib, unsigned conn_id) { + // Who releases the timer ? + PARCUnsigned *cid = parcUnsigned_Create(conn_id); + parcHashMap_Remove(tfib->nexthops, cid); + parcUnsigned_Release(&cid); +} + +static PARCIterator *mapMeTFIB_CreateKeyIterator(const MapMeTFIB *tfib) { + return parcHashMap_CreateKeyIterator(tfib->nexthops); +} + +int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) { + NameBitvector *bv = name_GetContentName(name); + ip_address_t ip_address; + nameBitvector_ToIPAddress(bv, &ip_address); + + /* The name length will be equal to ip address' prefix length */ + return hicn_prefix_create_from_ip_address(&ip_address, prefix); +} + +static Message *mapMe_createMessage(const MapMe *mapme, const Name *name, + mapme_params_t *params) { + Ticks now = forwarder_GetTicks(mapme->forwarder); + Logger *logger = logger_Acquire(forwarder_GetLogger(mapme->forwarder)); + + INFO(mapme, "[MAP-Me] CreateMessage type=%d seq=%d", params->type, + params->seq); + + size_t size = (params->protocol == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN + : HICN_MAPME_V4_HDRLEN; + uint8_t *icmp_pkt = parcMemory_AllocateAndClear(size); + + 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; + } + + INFO(mapme, "[MAP-Me] Creating MAP-Me packet"); + size_t len = hicn_mapme_create_packet(icmp_pkt, &prefix, params); + if (len != 0) { + ERR(mapme, "[MAP-Me] Failed to create mapme packet through lib"); + goto ERR_CREATE; + } + + // hicn_packet_dump(icmp_pkt, MAPME_HDRLEN); + + return message_CreateFromByteArray(NO_INGRESS, icmp_pkt, + MessagePacketType_Interest, now, logger); + +ERR_CREATE: +ERR_NAME: + return NULL; +} + +static Message *mapMe_createAckMessage(const MapMe *mapme, + const uint8_t *msgBuffer, + const mapme_params_t *params) { + Ticks now = forwarder_GetTicks(mapme->forwarder); + Logger *logger = logger_Acquire(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"); + return NULL; + } + + return message_CreateFromByteArray( + NO_INGRESS, icmp_pkt, MessagePacketType_ContentObject, now, logger); +} + +struct setFacePendingArgs { + const MapMe *mapme; + const Name *name; + FibEntry *fibEntry; + unsigned conn_id; + bool send; + bool is_first; + uint32_t num_retx; +}; + +static bool mapMe_setFacePending(const MapMe *mapme, const Name *name, + FibEntry *fibEntry, unsigned conn_id, + bool send, bool is_first, uint32_t num_retx); + +static void mapMe_setFacePendingCallback(int fd, PARCEventType which_event, + void *data) { + struct setFacePendingArgs *args = (struct setFacePendingArgs *)data; + + parcAssertTrue(which_event & PARCEventType_Timeout, + "Event incorrect, expecting %X set, got %X", + PARCEventType_Timeout, which_event); + + INFO(args->mapme, "Timeout during retransmission. Re-sending"); + mapMe_setFacePending(args->mapme, args->name, args->fibEntry, args->conn_id, + args->send, args->is_first, args->num_retx); +} + +/** + * @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_first, uint32_t num_retx) { + int rc; + + INFO(mapme, "[MAP-Me] SetFacePending connection=%d prefix=XX retx=%d", + conn_id, num_retx); + + /* 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; + + // 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_first || send) { + // XXX + mapme_params_t params = { + .protocol = IPPROTO_IPV6, + .type = is_first ? mapMe_getTypeFromHeuristic(mapme, fibEntry) : UPDATE, + .seq = TFIB(fibEntry)->seq}; + Message *special_interest = mapMe_createMessage(mapme, name, ¶ms); + if (!special_interest) { + INFO(mapme, "[MAP-Me] Could not create special interest"); + return false; + } + + const ConnectionTable *table = + forwarder_GetConnectionTable(mapme->forwarder); + const Connection *conn = + connectionTable_FindById((ConnectionTable *)table, conn_id); + if (conn) { + INFO(mapme, "[MAP-Me] Sending MAP-Me packet"); + connection_ReSend(conn, special_interest, NOT_A_NOTIFICATION); + } else { + INFO(mapme, "[MAP-Me] Stopped retransmissions as face went down"); + } + + 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_first = is_first; + 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) goto ERR_TIMER; + } else { + INFO(mapme, "[MAP-Me] Last retransmission."); + timer = NULL; + } + } else { + INFO(mapme, "[MAP-Me] - not forwarding as send is False"); + timer = NULL; + } + + PARCEventTimer *oldTimer = + (PARCEventTimer *)mapMeTFIB_Get(TFIB(fibEntry), conn_id); + if (oldTimer) { + INFO(mapme, "[MAP-Me] - Found old timer, would need to cancel !"); + // parcEventTimer_Stop(oldTimer); + } + INFO(mapme, "[MAP-Me] - Putting new timer in TFIB"); + if (timer) mapMeTFIB_Put(TFIB(fibEntry), conn_id, timer); + + return true; + +ERR_MALLOC: +ERR_TIMER: + return false; +} + +/*------------------------------------------------------------------------------ + * Event handling + *----------------------------------------------------------------------------*/ + +/* + * 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; +} + +/* + * Callback called everytime a new connection is created by the control protocol + */ +void mapMe_onConnectionAdded(const MapMe *mapme, const Connection *conn_added) { + /* bool ret; */ + FibEntryList *fiblist; + + /* Ignore local connections corresponding to applications for now */ + if (connection_IsLocal(conn_added)) return; + + unsigned conn_added_id = connection_GetConnectionId(conn_added); + INFO(mapme, "[MAP-Me] New connection %d", conn_added_id); + + /* + * Iterate on FIB to find locally served prefix + * Ideally, we want to avoid a FIB scan everytime a face is added/removed + */ + fiblist = forwarder_GetFibEntries(mapme->forwarder); + for (size_t i = 0; i < fibEntryList_Length(fiblist); i++) { + FibEntry *fibEntry = (FibEntry *)fibEntryList_Get(fiblist, i); + const Name *name = fibEntry_GetPrefix(fibEntry); + + /* Skip entries that have no local connection as next hop */ + if (!mapMe_hasLocalNextHops(mapme, fibEntry)) continue; + + /* This entry corresponds to a locally served prefix, set + * Special Interest */ + if (!TFIB(fibEntry)) /* Create TFIB associated to FIB entry */ + mapMe_CreateTFIB(fibEntry); + TFIB(fibEntry)->seq++; + + char *name_str = name_ToString(name); + INFO(mapme, "[MAP-Me] sending IU/IN for name %s on connection %d", name_str, + conn_added_id); + free(name_str); + + mapMe_setFacePending(mapme, name, fibEntry, conn_added_id, true, true, 0); + } +} + +/*------------------------------------------------------------------------------ + * 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); + 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); + + /* + * Immediately send an acknowledgement back on the ingress connection + * We always ack, even duplicates. + */ + Message *ack = mapMe_createAckMessage(mapme, msgBuffer, params); + if (!ack) goto ERR_ACK_CREATE; + rv = connection_ReSend(conn_in, ack, NOT_A_NOTIFICATION); + if (!rv) goto ERR_ACK_SEND; + message_Release(&ack); + + /* EPM on FIB */ + /* only the processor has access to the FIB */ + FIB *fib = forwarder_getFib(mapme->forwarder); + + FibEntry *fibEntry = fib_Contains(fib, name); + if (!fibEntry) { + 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; + + fibEntry = fibEntry_Create(name, fwdStrategy); + fibEntry_AddNexthopByConnectionId(fibEntry, conn_in_id); + mapMe_CreateTFIB(fibEntry); + TFIB(fibEntry)->seq = seq; // INIT_SEQ; + fib_Add(fib, fibEntry); + return true; // with proper seq, we are done + + } else if (!TFIB(fibEntry)) { + /* Create TFIB associated to FIB entry */ + INFO(mapme, + "[MAP-Me] - Creating TFIB entry with default sequence number"); + mapMe_CreateTFIB(fibEntry); + } + + 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)); + 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, 0); + } + parcIterator_Release(&iterator); + } + + /* nextHops -> prevHops + * + * We add to the list of pendingUpdates the current next hops, and + * eventually forward them an IU too. + * + * Exception: nextHops -> nextHops + * Because of retransmission issues, it is possible that a second interest + * (with same of higher sequence number) is receive from a next-hop + * interface. In that case, the face remains a next hop. + */ + const NumberSet *nexthops_old = fibEntry_GetNexthops(fibEntry); + + /* We make a copy to be able to send IU _after_ updating next hops */ + NumberSet *nexthops = numberSet_Create(); + numberSet_AddSet(nexthops, nexthops_old); + + /* 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. + * + * Optimization : nextHops -> nextHops + * - no next hop to add + * - we know that inFace was not a previous hop since it was a next hop and + * this forms a partition. No need for a search + */ + + INFO(mapme, "[MAP-Me] - (3/3) next hops ~~> prev hops"); + PARCEventTimer *oldTimer = + (PARCEventTimer *)mapMeTFIB_Get(TFIB(fibEntry), conn_in_id); + if (oldTimer) { + /* This happens if we receive an IU while we are still sending + * one in the other direction + */ + INFO(mapme, "[MAP-Me] - Canceled pending timer"); + parcEventTimer_Stop(oldTimer); + mapMeTFIB_Remove(TFIB(fibEntry), conn_in_id); + } + + /* Remove all next hops */ + for (size_t k = 0; k < numberSet_Length(nexthops_old); k++) { + unsigned conn_id = numberSet_GetItem(nexthops_old, k); + INFO(mapme, "[MAP-Me] - Replaced next hops by connection %d", conn_id); + fibEntry_RemoveNexthopByConnectionId(fibEntry, conn_id); + } + fibEntry_AddNexthopByConnectionId(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; + } + + 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, 0); + complete = false; + } + + /* + * The update is completed when the IU could not be sent to any + * other next hop. + */ + if (complete) INFO(mapme, "[MAP-Me] - Update completed !"); + + numberSet_Release(&nexthops); + + } else if (seq == fibSeq) { + /* + * Multipath, multihoming, multiple producers or duplicate interest + * + * 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 + * + * It might happen that the previous AP has still a connection to the + * producer and that we received back our own IU. In that case, we just + * need to Ack and ignore it. + */ + if (mapMe_hasLocalNextHops(mapme, fibEntry)) { + INFO(mapme, "[MAP-Me] - Received original interest... Update complete"); + return true; + } + + INFO(mapme, "[MAP-Me] - Adding multipath next hop on connection %d", + conn_in_id); + fibEntry_AddNexthopByConnectionId(fibEntry, conn_in_id); + + } else { // seq < fibSeq + /* + * 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, 0); + } + + return true; + +ERR_ACK_SEND: + message_Release(&ack); +ERR_ACK_CREATE: + return false; +} + +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); + + const Name *name = + name_CreateFromPacket(msgBuffer, MessagePacketType_Interest); + + FIB *fib = forwarder_getFib(mapme->forwarder); + FibEntry *fibEntry = fib_Contains(fib, name); + 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) { + INFO(mapme, + "[MAP-Me] - Ignored special interest Ack with seq=%u, expected %u", + seq, fibSeq); + return; + } + } + + /* + * 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 + */ + 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 ?"); + return; + } + + /* Stop timer and remove entry from TFIB */ + parcEventTimer_Stop(timer); + mapMeTFIB_Remove(TFIB(fibEntry), conn_in_id); + + INFO(mapme, "[MAP-Me] - Removing TFIB entry for ack on connection %d", + conn_in_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 *msgBuffer) { + uint8_t next_header = messageHandler_NextHeaderType(msgBuffer); + + const uint8_t *icmp_ptr; + if (next_header == IPPROTO_ICMP) { + icmp_ptr = msgBuffer + IPV4_HDRLEN; + } else if (next_header == IPPROTO_ICMPV6) { + icmp_ptr = msgBuffer + IPV6_HDRLEN; + } else { + return false; + } + + uint8_t type = ((_icmp_header_t *)icmp_ptr)->type; + uint8_t code = ((_icmp_header_t *)icmp_ptr)->code; + if (HICN_IS_MAPME(type, code)) return true; + + return false; +} + +/** + * @discussion The exact type of the MapMe message is determined after + * reception. In hICN, Interest Update and Notifications look like regular + * Interest packets, and are first punted from the normal path by the forwarder, + * then treated as such in the Listener to reach this function. Acknowledgements + * are received as Content (Data) packets and will land here too. + * + * This function is in charge of abstracting the low-level implementation of + * 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) { + hicn_prefix_t prefix; + mapme_params_t params; + hicn_mapme_parse_packet(msgBuffer, &prefix, ¶ms); + + // XXX Dispatch message dependenging on type + switch (params.type) { + case UPDATE: + case NOTIFICATION: + mapMe_onSpecialInterest(mapme, msgBuffer, conn_id, &prefix, ¶ms); + break; + case UPDATE_ACK: + case NOTIFICATION_ACK: + mapMe_onSpecialInterestAck(mapme, msgBuffer, conn_id, &prefix, ¶ms); + break; + default: + printf("E:Unknown message\n"); + break; + } +} + +#endif /* WITH_MAPME */ diff --git a/hicn-light/src/hicn/core/mapMe.h b/hicn-light/src/hicn/core/mapMe.h new file mode 100644 index 000000000..a99d4710b --- /dev/null +++ b/hicn-light/src/hicn/core/mapMe.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file mapMe.h + * @brief MAP-Me : AnchorLess Producer Mobility Management + */ + +#ifndef mapMe_h +#define mapMe_h + +#ifdef WITH_MAPME + +#include +#include + +#include + +#include +#include + +struct mapme; +typedef struct mapme MapMe; + +/** + * @function MapMe_Init + * @abstract Initializes MAP-Me state in the forwarder. + * @return bool - Boolean informing about the success of MAP-Me initialization. + */ +bool mapMe_Init(MapMe **mapme, Forwarder *Forwarder); + +/** + * @function messageHandler_isMapMe + * @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 + * done through hooks defined in the Init function. + * @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); + +/** + * @function mapMe_handleMapMeMessage + * @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); + +/** + * @function mapMe_onConnectionAdded + * @abstract Callback following the addition of the face though the control + * protocol. + * @discussion This callback triggers the sending of control packets by MAP-Me. + * @param [in] mapme - Pointer to the MAP-Me data structure. + * @param [in] conn - The newly added connection. + */ +void mapMe_onConnectionAdded(const MapMe *mapme, const Connection *conn); + +/** + * @function mapMe_getNextHops + * @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); + +#endif /* WITH_MAPME */ + +#endif // mapMe_h diff --git a/hicn-light/src/hicn/core/message.c b/hicn-light/src/hicn/core/message.c new file mode 100644 index 000000000..423241084 --- /dev/null +++ b/hicn-light/src/hicn/core/message.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +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); + // XXX: what about the checksum? + 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, 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); + 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 new file mode 100644 index 000000000..9e5e125c6 --- /dev/null +++ b/hicn-light/src/hicn/core/message.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +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 new file mode 100644 index 000000000..56f75c113 --- /dev/null +++ b/hicn-light/src/hicn/core/messageHandler.h @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +#include +#include + +#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 + +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; + } +} + +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((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((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 uint8_t messageHandler_GetProbePacketType( + 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 ((_icmp_header_t *)icmp_ptr)->code; +} + +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 new_path_label) { + if (!messageHandler_IsTCP(message)) return; + + uint32_t old_path_label; + int res = hicn_data_get_path_label((hicn_header_t *)message, &old_path_label); + if (res < 0) 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); + + hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit); + + messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit, + (uint16_t *)&pl_new_32bit, 2); +} + +static inline void messageHandler_ResetPathLabel(uint8_t *message) { + if (!messageHandler_IsTCP(message)) return; + + uint32_t pl_old_32bit = messageHandler_GetPathLabel(message); + uint32_t pl_new_32bit = 0; + hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit); + messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit, + (uint16_t *)&pl_new_32bit, 2); +} + +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 void messageHandler_SetProbePacket(uint8_t *message, + uint8_t probeType, + struct in6_addr *src, + struct in6_addr *dst) { + hicn_header_t *h = (hicn_header_t *)message; + *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, // this should be 1, but ... just to be safe + }, + .icmp = + { + .type = ICMP_LB_TYPE, + .code = probeType, + }, + }}; + messageHandler_SetSource_IPv6(message, src); + messageHandler_SetDestination_IPv6(message, dst); +} + +#endif // Metis_metis_MessageHandler diff --git a/hicn-light/src/hicn/core/messagePacketType.h b/hicn-light/src/hicn/core/messagePacketType.h new file mode 100644 index 000000000..dfbb12342 --- /dev/null +++ b/hicn-light/src/hicn/core/messagePacketType.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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/name.c b/hicn-light/src/hicn/core/name.c new file mode 100644 index 000000000..91652b887 --- /dev/null +++ b/hicn-light/src/hicn/core/name.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#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, union commandAddr 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.ipv4, len); + } else if (addressType == ADDR_INET6) { + name->content_name = nameBitvector_CreateFromIn6Addr(&addr.ipv6, 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; +} + +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"); + + 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; + } + } +} + +bool name_StartsWith(const Name *name, const Name *prefix) { + parcAssertNotNull(name, "Parameter name must be non-null"); + parcAssertNotNull(prefix, "Parameter prefix must be non-null"); + + return nameBitvector_StartsWith(name->content_name, prefix->content_name); +} + +char *name_ToString(const Name *name) { + char *output = malloc(128); + + Address *packetAddr = nameBitvector_ToAddress(name_GetContentName(name)); + + sprintf(output, "name: %s seq: %u", addressToString(packetAddr), + name->segment); + + addressDestroy(&packetAddr); + + return output; +} + +void name_setLen(const Name *name, uint8_t len) { + nameBitvector_setLen(name->content_name, len); +} diff --git a/hicn-light/src/hicn/core/name.h b/hicn-light/src/hicn/core/name.h new file mode 100644 index 000000000..8ab75cf05 --- /dev/null +++ b/hicn-light/src/hicn/core/name.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include + +#include +#include +#include + +#include + +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); + +/** + * 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); + +/** + * @function metsName_StartsWith + * @abstract Checks if name starts with prefix + * @discussion + * Byte-by-byte prefix comparison + * + * @return True if the name is equal to or begins with prefix + */ + +bool name_StartsWith(const Name *name, const Name *prefix); + +/** + * 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(const Name *name, uint8_t len); + +/** + * Creates a name from a Address + * + */ +Name *name_CreateFromAddress(address_type addressType, union commandAddr addr, + uint8_t len); + +#endif // name_h diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c new file mode 100644 index 000000000..8078778e3 --- /dev/null +++ b/hicn-light/src/hicn/core/nameBitvector.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#define BLOCKS 2 + +const uint64_t BLOCK_SIZE = 64; +const uint64_t WIDTH = 128; +const uint64_t BLOCK_ONE = 0x1; + +// the bits are encoded in the following order: +// 00100101001---101010 00100011---110100100 +// [bits[0] (uint64_t)] [bits[1] (uint64_t)] +// ^ ^ ^ ^ +// 0 63 64 127 +// address 2200::0011 is encoded as: +// 1000 1000 0000 0010 00000 ....0100 0100 +// ^ ^ +// 0 127 + +struct name_bitvector { + uint64_t bits[BLOCKS]; + 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[1] = (bitvector->bits[1] | addr_4) << 8; + bitvector->bits[1] = (bitvector->bits[1] | addr_3) << 8; + bitvector->bits[1] = (bitvector->bits[1] | addr_2) << 8; + bitvector->bits[1] = (bitvector->bits[1] | addr_1); + bitvector->bits[1] = bitvector->bits[1] << 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[1] = (bitvector->bits[1] << 8) | addr->s6_addr[i]; + } + + for (int i = 8; i < 16; ++i) { + bitvector->bits[0] = (bitvector->bits[0] << 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; + } +} + +bool nameBitvector_StartsWith(const NameBitvector *name, + const NameBitvector *prefix) { + parcAssertNotNull(name, "name cannot be NULL"); + parcAssertNotNull(prefix, "prefix cannot be NULL"); + parcAssertTrue(prefix->len > 0, "prefix length can not be 0"); + + if (prefix->len > BLOCK_SIZE) + return (name->bits[1] == prefix->bits[1]) && + ((name->bits[0] ^ prefix->bits[0]) >> + (BLOCK_SIZE - (prefix->len - BLOCK_SIZE)) == + 0); + + return ((name->bits[1] ^ prefix->bits[1]) >> (BLOCK_SIZE - prefix->len) == 0); +} + +bool nameBitvector_testBit(const NameBitvector *name, uint8_t pos) { + if (pos == WIDTH) pos = 127; + + uint8_t final_pos = (uint8_t)(WIDTH - name->len); + + // the bit to test is inside the name/prefix len + if (pos > final_pos) { + return (name->bits[pos / BLOCK_SIZE] & (BLOCK_ONE << (pos % BLOCK_SIZE))); + } + + // the bit to test is outside the name/prefix len + if (pos < final_pos) { + return false; + } + + // pos is equal to the name/prefix len + return true; +} + +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; +} + +uint8_t nameBitvector_firstDiff(const NameBitvector *a, + const NameBitvector *b) { + uint8_t res = 0; + uint64_t diff = a->bits[1] ^ b->bits[1]; + if (diff) + res = (uint8_t)(64 + _diff_bit_log2(diff)); + else + res = (uint8_t)_diff_bit_log2(a->bits[0] ^ b->bits[0]); + + // res is computed over the bitvector which is composed by 128 bit all the + // times however the prefixes may be diffrent just because the have different + // lengths example: prefix 1: 0::/30 prefix 2: 0::/20 at this point of the + // function res would be 0 since both the bitvectors are composed by 0s but + // the function will return 127-20, which is the position at which the two + // prefix are different, since prefix 2 has only 20 bits + + uint8_t len_diff; + if (a->len < b->len) + len_diff = (uint8_t)(WIDTH - a->len); + else + len_diff = (uint8_t)(WIDTH - b->len); + + if (len_diff > res) res = len_diff; + + return res; +} + +int nameBitvector_ToIPAddress(const NameBitvector *name, + ip_address_t *ip_address) { + if (name->IPversion == IPv4_TYPE) { + struct in_addr *addr = (struct in_addr *)(&ip_address->buffer); + ip_address->family = AF_INET; + ip_address->prefix_len = IPV4_ADDR_LEN_BITS; + + uint32_t tmp_addr = name->bits[1] >> 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 *)(&ip_address->buffer); + ip_address->family = AF_INET6; + ip_address->prefix_len = name->len; // IPV6_ADDR_LEN_BITS; + + for (int i = 0; i < 8; i++) { + addr->s6_addr[i] = (uint8_t)((name->bits[1] >> 8 * (7 - i)) & 0xFF); + } + + int x = 0; + for (int i = 8; i < 16; ++i) { + addr->s6_addr[i] = (uint8_t)((name->bits[0] >> 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[1] >> 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[1] >> 8 * (7 - i)) & 0xFF); + } + + int x = 0; + for (int i = 8; i < 16; ++i) { + addr.sin6_addr.s6_addr[i] = + (uint8_t)((name->bits[0] >> 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); + + sprintf(output, "prefix: %s len: %u", addressToString(packetAddr), name->len); + + addressDestroy(&packetAddr); + + return output; +} \ No newline at end of file diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h new file mode 100644 index 000000000..6ff859e3b --- /dev/null +++ b/hicn-light/src/hicn/core/nameBitvector.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +#include + +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_CreateFromAddress(const Address *prefix, + 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); + +bool nameBitvector_StartsWith(const NameBitvector *name, + const NameBitvector *prefix); + +bool nameBitvector_testBit(const NameBitvector *name, uint8_t pos); + +uint8_t nameBitvector_firstDiff(const NameBitvector *a, const NameBitvector *b); + +int nameBitvector_ToIPAddress(const NameBitvector *name, + ip_address_t *ip_address); +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/numberSet.c b/hicn-light/src/hicn/core/numberSet.c new file mode 100644 index 000000000..9788a29c5 --- /dev/null +++ b/hicn-light/src/hicn/core/numberSet.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +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 new file mode 100644 index 000000000..91a965d7b --- /dev/null +++ b/hicn-light/src/hicn/core/numberSet.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +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 setToAdd to destinationSet + * @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 difference = minuend - + * subtrahend, returns a new number set. + * @discussion + * minuend and subtrahend are not modified. A new + * difference set is created. + * + * Returns the elements in minuend that are not in + * subtrahend. + * + * @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/streamBuffer.c b/hicn-light/src/hicn/core/streamBuffer.c new file mode 100644 index 000000000..6efc82004 --- /dev/null +++ b/hicn-light/src/hicn/core/streamBuffer.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include + +void streamBuffer_Destroy(PARCEventQueue **bufferPtr) { + parcAssertNotNull(bufferPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*bufferPtr, + "Parameter must dereference to non-null pointer"); + parcEventQueue_Destroy(bufferPtr); + *bufferPtr = NULL; +} + +void streamBuffer_SetWatermark(PARCEventQueue *buffer, bool setRead, + bool setWrite, size_t low, size_t high) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + + short flags = 0; + if (setRead) { + flags |= PARCEventType_Read; + } + + if (setWrite) { + flags |= PARCEventType_Write; + } + + parcEventQueue_SetWatermark(buffer, flags, low, high); +} + +int streamBuffer_Flush(PARCEventQueue *buffer, bool flushRead, + bool flushWrite) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + + short flags = 0; + if (flushRead) { + flags |= PARCEventType_Read; + } + + if (flushWrite) { + flags |= PARCEventType_Write; + } + + return parcEventQueue_Flush(buffer, flags); +} + +int streamBuffer_FlushCheckpoint(PARCEventQueue *buffer, bool flushRead, + bool flushWrite) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + + short flags = 0; + if (flushRead) { + flags |= PARCEventType_Read; + } + + if (flushWrite) { + flags |= PARCEventType_Write; + } + + return parcEventQueue_Flush(buffer, flags); +} + +int streamBuffer_FlushFinished(PARCEventQueue *buffer, bool flushRead, + bool flushWrite) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + + short flags = 0; + if (flushRead) { + flags |= PARCEventType_Read; + } + + if (flushWrite) { + flags |= PARCEventType_Write; + } + + return parcEventQueue_Flush(buffer, flags); +} + +void streamBuffer_SetCallbacks(PARCEventQueue *buffer, + PARCEventQueue_Callback *readCallback, + PARCEventQueue_Callback *writeCallback, + PARCEventQueue_EventCallback *eventCallback, + void *user_data) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + + parcEventQueue_SetCallbacks(buffer, readCallback, writeCallback, + eventCallback, user_data); +} + +void streamBuffer_EnableCallbacks(PARCEventQueue *buffer, bool enableRead, + bool enableWrite) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + short flags = 0; + if (enableRead) { + flags |= PARCEventType_Read; + } + if (enableWrite) { + flags |= PARCEventType_Write; + } + + parcEventQueue_Enable(buffer, flags); +} + +/** + * @function StreamBuffer_DisableCallbacks + * @abstract Disables specified callbacks. Does not affect others. + * @discussion + * Disables enabled callbacks. If a callback is already disabled, has no + * effect. A "false" value does not enable it. + * + * @param <#param1#> + * @return <#return#> + */ +void streamBuffer_DisableCallbacks(PARCEventQueue *buffer, bool disableRead, + bool disableWrite) { + parcAssertNotNull(buffer, "Parameter buffer must be non-null"); + short flags = 0; + if (disableRead) { + flags |= PARCEventType_Read; + } + if (disableWrite) { + flags |= PARCEventType_Write; + } + + parcEventQueue_Disable(buffer, flags); +} diff --git a/hicn-light/src/hicn/core/streamBuffer.h b/hicn-light/src/hicn/core/streamBuffer.h new file mode 100644 index 000000000..27e793176 --- /dev/null +++ b/hicn-light/src/hicn/core/streamBuffer.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Wrapper around event scheduler + */ + +#ifndef streamBuffer_h +#define streamBuffer_h + +#include +#include + +void streamBuffer_Destroy(PARCEventQueue **bufferPtr); + +/** + * @function streamBuffer_SetWatermark + * @abstract Sets the read and/or write watermarks + * @discussion + * For a read watermark, when there is at least low bytes + * available to read, the read callback will be fired. If the bytes in the + * buffer exceed high, the stream buffer will stop reading from the + * network. + * + * For a write watermark, when the bytes in the buffer fall below + * low, the write callback is fired. The high + * watermark limits stream filters and shapers from exceeding that threashold on + * what they write to the buffer. + * + */ +void streamBuffer_SetWatermark(PARCEventQueue *buffer, bool setRead, + bool setWrite, size_t low, size_t high); + +/** + * @function streamBuffer_Flush + * @abstract The buffer will read/write more data if available + * + * @return -1 error, 0 no more data, 1 more data + */ +int streamBuffer_Flush(PARCEventQueue *buffer, bool flushRead, bool flushWrite); + +/** + * @function streamBuffer_FlushCheckpoint + * @abstract Flushes the stream, checkpointing all data in the buffer + */ +int streamBuffer_FlushCheckpoint(PARCEventQueue *buffer, bool flushRead, + bool flushWrite); + +/** + * @function streamBuffer_FlushFinished + * @abstract Flush the stream and indicate the end of new data + */ +int streamBuffer_FlushFinished(PARCEventQueue *buffer, bool flushRead, + bool flushWrite); + +/** + * @typedef StreamBufferReadWriteCallback + * @abstract Callback when data is available or write space available + * @constant user_data opaque data passed to + * StreamBuffer_SetCallbacks() + */ +typedef void(StreamBufferReadWriteCallback)(PARCEventQueue *buffer, + void *user_data); + +/** + * @typedef StreamBufferEventCallback + * @abstract Callback on error or other event on the stream buffer + * @constant what logical or of STREAM events. STREAM_READING and + * STREAM_WRITING indicate if the error was on the read or write direction. The + * conditions may be STREAM_ERROR, STREAM_EOF, STREAM_TIMEOUT, or + * STREAM_CONNECTED. + * @constant user_data opaque data passed to + * StreamBuffer_SetCallbacks() + */ +typedef void(StreamBufferEventCallback)(PARCEventQueue *buffer, short what, + void *user_data); + +/** + * Changes the callbacks for a buffer event. + * + * @param bufev the buffer event object for which to change callbacks + * @param readcb callback to invoke when there is data to be read, or NULL if + * no callback is desired + * @param writecb callback to invoke when the file descriptor is ready for + * writing, or NULL if no callback is desired + * @param eventcb callback to invoke when there is an event on the file + * descriptor + * @param cbarg an argument that will be supplied to each of the callbacks + * (readcb, writecb, and errorcb) + * @see parcEventQueue_Create() + */ +void streamBuffer_SetCallbacks(PARCEventQueue *buffer, + PARCEventQueue_Callback *readCallback, + PARCEventQueue_Callback *writeCallback, + PARCEventQueue_EventCallback *eventCallback, + void *user_data); + +/** + * @function StreamBuffer_EnableCallbacks + * @abstract Enables specified callbacks. Does not affect others. + * @discussion + * Enables disabled callbacks. If a callback is already enabled, has no + * effect. A "false" value does not disable it. + */ +void streamBuffer_EnableCallbacks(PARCEventQueue *buffer, bool enableRead, + bool enableWrite); + +/** + * @function StreamBuffer_DisableCallbacks + * @abstract Disables specified callbacks. Does not affect others. + * @discussion + * Disables enabled callbacks. If a callback is already disabled, has no + * effect. A "false" value does not enable it. + */ +void streamBuffer_DisableCallbacks(PARCEventQueue *buffer, bool disableRead, + bool disableWrite); +#endif // streamBuffer_h diff --git a/hicn-light/src/hicn/core/system.h b/hicn-light/src/hicn/core/system.h new file mode 100644 index 000000000..be6c3e7cf --- /dev/null +++ b/hicn-light/src/hicn/core/system.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 system.h + * @abstract System-level properties + * @discussion + * <#Discussion#> + * + */ + +#ifndef system_h +#define system_h + +#include +#include + +/** + * @function system_Interfaces + * @abstract The system network interfaces + */ +InterfaceSet *system_Interfaces(Forwarder *forwarder); + +/** + * Returns the MTU of the named interface + * + * @param [in] an allocated hicn-light forwarder + * @param [in] interfaceName The system interface name, e.g. "eth0" + * + * @return 0 Interface does not exist + * @return positive the MTU the kernel reports + * + */ +unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName); + +/** + * Returns the LINK address of the specified interface + * + * @param [in] an allocated hicn-light forwarder + * @param [in] interfaceName The system interface name, e.g. "eth0" + * + * @retval non-null The MAC address of the interface + * @retval null The interface does not exist + * + */ +Address *system_GetMacAddressByName(Forwarder *forwarder, + const char *interfaceName); +#endif diff --git a/hicn-light/src/hicn/core/ticks.h b/hicn-light/src/hicn/core/ticks.h new file mode 100644 index 000000000..8750abde5 --- /dev/null +++ b/hicn-light/src/hicn/core/ticks.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 The router periodically measures time in units of Ticks + * + * See forwarder.c HZ which specifies the tick rate. forwarder.h has functions + * to convert between ticks and milliseconds. + * + */ +#ifndef ticks_h +#define ticks_h + +#define __STDC_FORMAT_MACROS +#include + +typedef uint64_t Ticks; + +#endif // ticks_h diff --git a/hicn-light/src/hicn/core/wldr.c b/hicn-light/src/hicn/core/wldr.c new file mode 100644 index 000000000..ad3663d0d --- /dev/null +++ b/hicn-light/src/hicn/core/wldr.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct wldr_buffer { + Message *message; + uint8_t rtx_counter; +}; + +typedef struct wldr_buffer WldrBuffer; + +struct wldr_state { + uint16_t expected_label; + uint16_t next_label; + WldrBuffer *buffer[BUFFER_SIZE]; +}; + +Wldr *wldr_Init() { + Wldr *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)); + parcAssertNotNull( + entry, + "WldrBuffer init: parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(WldrBuffer)); + entry->message = NULL; + entry->rtx_counter = 0; + wldr->buffer[i] = entry; + } + return wldr; +} + +void wldr_ResetState(Wldr *wldr) { + wldr->expected_label = 1; + wldr->next_label = 1; + for (int i = 0; i < BUFFER_SIZE; i++) { + wldr->buffer[i]->message = NULL; + wldr->buffer[i]->rtx_counter = 0; + } +} + +void wldr_Destroy(Wldr **wldrPtr) { + Wldr *wldr = *wldrPtr; + for (unsigned i = 0; i < BUFFER_SIZE; i++) { + if (wldr->buffer[i]->message != NULL) { + message_Release(&(wldr->buffer[i]->message)); + parcMemory_Deallocate((void **)&(wldr->buffer[i])); + } + } + parcMemory_Deallocate((void **)&wldr); + *wldrPtr = NULL; +} + +static void _wldr_RetransmitPacket(Wldr *wldr, const Connection *conn, + uint16_t label) { + if (wldr->buffer[label % BUFFER_SIZE]->message == 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; + 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)); + } + + wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = 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); + wldr->next_label++; + connection_ReSend(conn, msg, false); + } +} + +static void _wldr_SendWldrNotificaiton(Wldr *wldr, const Connection *conn, + Message *message, 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 + // notification is the source address of the message for which we want to + // create a notification. in fact, if message is an interest the prevoius hop + // is identified by the src. if message is a data, we need to send the + // notification message with the content name has a source address in this way + // the message will be trapped by the pounting rules in the next hop We define + // the notification as an interest message so that the NAT in the send + // function will set the src address of the local connection. Notice that in + // 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); + parcAssertNotNull(notification, "Got null from CreateWldrNotification"); + connection_ReSend(conn, notification, true); +} + +void wldr_SetLabel(Wldr *wldr, Message *message) { + // in this function we send the packet for the first time + // 1) we set the wldr label + message_SetWldrLabel(message, wldr->next_label); + + // 2) we store the pointer to packet in the buffer + if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->message != NULL) { + // release an old message if necessary + message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message)); + } + + // we need to acquire the message to avoid that it gets destroyed + message_Acquire(message); + + wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = message; + 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++; +} + +void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message) { + if (message_HasWldr(message)) { + // this is a normal wldr packet + uint16_t pkt_lbl = (uint16_t)message_GetWldrLabel(message); + 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 + // a while and reconnected on this same connection, so the two nodes are + // out of synch for this reason we do not send any notification, we just + // synch the labels + + if ((pkt_lbl != 1) || (wldr->expected_label < pkt_lbl)) { + _wldr_SendWldrNotificaiton(wldr, conn, message, wldr->expected_label, + pkt_lbl); + } + + // here we always synch + wldr->expected_label = (uint16_t)(pkt_lbl + 1); + } else { + wldr->expected_label++; + if (wldr->expected_label == 0) + wldr->expected_label++; // for the next_label we want to skip 0 + } + } +} + +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); + if ((wldr->next_label - expected_lbl) > BUFFER_SIZE) { + // the packets are not in the buffer anymore + return; + } + while (expected_lbl < received_lbl) { + _wldr_RetransmitPacket(wldr, conn, expected_lbl); + expected_lbl++; + } +} diff --git a/hicn-light/src/hicn/core/wldr.h b/hicn-light/src/hicn/core/wldr.h new file mode 100644 index 000000000..0e63fe7e7 --- /dev/null +++ b/hicn-light/src/hicn/core/wldr.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 wldr_h +#define wldr_h + +#include +#include +#include + +#define BUFFER_SIZE 8192 +#define MAX_RTX 3 +#define WLDR_LBL 13 +#define WLDR_NOTIFICATION 14 +#define WLDR_UNKNOWN 15 + +// NORMAL PACKET or RETRASMISSION +// WLDR_LBL: label = window size in the TCP header +// NOTIFICATION +// WLDR_NOTIFICATION: expected_label = window size in the TCP header, +// last_received_label = urgent pointer in the TCP header +// 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; + +Wldr *wldr_Init(); + +void wldr_Destroy(Wldr **wldrPtr); + +void wldr_ResetState(Wldr *wldr); + +void wldr_SetLabel(Wldr *wldr, Message *message); + +void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message); + +void wldr_HandleWldrNotification(Wldr *wldr, const Connection *conn, + Message *message); +#endif // wldr_h diff --git a/hicn-light/src/hicn/io/CMakeLists.txt b/hicn-light/src/hicn/io/CMakeLists.txt new file mode 100644 index 000000000..f65f0b580 --- /dev/null +++ b/hicn-light/src/hicn/io/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +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(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/io/addressPair.c b/hicn-light/src/hicn/io/addressPair.c new file mode 100644 index 000000000..9dfd8f507 --- /dev/null +++ b/hicn-light/src/hicn/io/addressPair.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include + +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 new file mode 100644 index 000000000..f1b72e0dc --- /dev/null +++ b/hicn-light/src/hicn/io/addressPair.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +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/hicnConnection.c b/hicn-light/src/hicn/io/hicnConnection.c new file mode 100644 index 000000000..d9797786a --- /dev/null +++ b/hicn-light/src/hicn/io/hicnConnection.c @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +typedef struct hicn_state { + Forwarder *forwarder; + 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; + + // this address contains one of the content names reachable + // throught the connection peer. We need this address beacuse it is + // the only way we have to conntact the next hop, since the main tun + // does not have address. Notice that a connection that sends probes + // is a connection that sends interest. In a "data" connection this + // value will remain NULL. We refresh the content address every time + // we send a probe, in this way we don't need to waste to much time in + // copy the address, but we can also react to the routing changes + struct sockaddr *probeDestAddress; + socklen_t probeDestAddressLength; + bool refreshProbeDestAddress; + + bool isLocal; + bool isUp; + unsigned id; + + unsigned delay; +} _HicnState; + +// Prototypes +static bool _send(IoOperations *ops, const Address *nexthop, Message *message); +static bool _sendCommandResponse(IoOperations *ops, struct iovec *message); +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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message); + +/* + * 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, + .sendCommandResponse = &_sendCommandResponse, + .getRemoteAddress = &_getRemoteAddress, + .getAddressPair = &_getAddressPair, + .getConnectionId = &_getConnectionId, + .isUp = &_isUp, + .isLocal = &_isLocal, + .destroy = &_destroy, + .class = &_streamConnection_Class, + .getConnectionType = &_getConnectionType, + .sendProbe = &_sendProbe}; + +// ================================================================= + +static void _setConnectionState(_HicnState *Hicn, bool isUp); +static bool _saveSockaddr(_HicnState *hicnConnState, const AddressPair *pair); +static void _refreshProbeDestAddress(_HicnState *hicnConnState, + const uint8_t *message); + +IoOperations *hicnConnection_Create(Forwarder *forwarder, 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->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); + + 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); + 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)); + if (hicnConnState->probeDestAddress != NULL) + parcMemory_Deallocate((void **)&(hicnConnState->probeDestAddress)); + + 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); + } + + // XXX + // do not close hicListenerSocket, the listener will close + // that when its done + // should I say something to libhicn? + + logger_Release(&hicnConnState->logger); + 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 + // XXX + 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)); + } + + // only in this case we may need to set the probeDestAddress + if (hicnConnState->refreshProbeDestAddress) { + _refreshProbeDestAddress(hicnConnState, message_FixedHeader(message)); + } + + } 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 _sendCommandResponse(IoOperations *ops, struct iovec *message) { + //XXX this should be nerver called since we do not handle control messages + //with hicn connections, so nothing to do here! + return false; +} + +static list_connections_type _getConnectionType(const IoOperations *ops) { + return CONN_HICN; +} + +static Ticks _sendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message) { + parcAssertNotNull(ops, "Parameter ops must be non-null"); + _HicnState *hicnConnState = (_HicnState *)ioOperations_GetClosure(ops); + + if ((hicnConnState->peerAddressLength == sizeof(struct sockaddr_in)) || + (hicnConnState->localAddressLength == sizeof(struct sockaddr_in))) + return false; + + if (hicnConnState->probeDestAddress == NULL && + probeType == PACKET_TYPE_PROBE_REPLY) { + uint8_t *pkt = parcMemory_AllocateAndClear( + messageHandler_GetICMPPacketSize(IPv6_TYPE)); + messageHandler_SetProbePacket( + pkt, probeType, + (struct in6_addr *)messageHandler_GetDestination(message), + (struct in6_addr *)messageHandler_GetSource(message)); + + ssize_t writeLength = write(hicnConnState->hicnListenerSocket, pkt, + messageHandler_GetICMPPacketSize(IPv6_TYPE)); + + parcMemory_Deallocate((void **)&pkt); + + if (writeLength < 0) { + return 0; + } + + } else if (hicnConnState->probeDestAddress != NULL && + probeType == PACKET_TYPE_PROBE_REQUEST) { + hicnConnState->refreshProbeDestAddress = true; + + uint8_t *pkt = parcMemory_AllocateAndClear( + messageHandler_GetICMPPacketSize(IPv6_TYPE)); + messageHandler_SetProbePacket( + pkt, probeType, + &((struct sockaddr_in6 *)hicnConnState->localAddress)->sin6_addr, + &((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_addr); + + ssize_t writeLength = write(hicnConnState->hicnListenerSocket, pkt, + messageHandler_GetICMPPacketSize(IPv6_TYPE)); + + parcMemory_Deallocate((void **)&pkt); + + if (writeLength < 0) { + return 0; + } + + } else { + if (hicnConnState->probeDestAddress == NULL && + probeType == PACKET_TYPE_PROBE_REQUEST) { + // this happen for the first probe + hicnConnState->refreshProbeDestAddress = true; + } + // do nothing + return 0; + } + + return forwarder_GetTicks(hicnConnState->forwarder); +} + +// ================================================================= +// 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; + + hicnConnState->probeDestAddress = NULL; + hicnConnState->probeDestAddressLength = (socklen_t)bytes; + hicnConnState->refreshProbeDestAddress = false; + + 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; + + hicnConnState->probeDestAddress = NULL; + hicnConnState->probeDestAddressLength = (socklen_t)bytes; + hicnConnState->refreshProbeDestAddress = false; + + 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 _refreshProbeDestAddress(_HicnState *hicnConnState, + const uint8_t *message) { + if ((hicnConnState->peerAddressLength == sizeof(struct sockaddr_in)) || + (hicnConnState->localAddressLength == sizeof(struct sockaddr_in))) + return; + + if (hicnConnState->probeDestAddress == NULL) { + hicnConnState->probeDestAddress = + parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6)); + parcAssertNotNull(hicnConnState->probeDestAddress, + "parcMemory_Allocate(%zu) returned NULL", + sizeof(struct sockaddr_in6)); + } + + ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_family = + AF_INET6; + ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_port = + htons(1234); + ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_scope_id = 0; + ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_flowinfo = 0; + ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_addr = + *((struct in6_addr *)messageHandler_GetDestination(message)); + hicnConnState->refreshProbeDestAddress = false; +} + +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; + } +} diff --git a/hicn-light/src/hicn/io/hicnConnection.h b/hicn-light/src/hicn/io/hicnConnection.h new file mode 100644 index 000000000..a14024a4e --- /dev/null +++ b/hicn-light/src/hicn/io/hicnConnection.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +/** + * 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, 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 new file mode 100644 index 000000000..3f6cab94e --- /dev/null +++ b/hicn-light/src/hicn/io/hicnListener.c @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#ifdef WITH_MAPME +#include +#include +#include +#include +#endif /* WITH_MAPME */ +#include +#include +#include +#include +#include +#include +#include + +#define IPv6 6 +#define IPv4 4 +#define MTU_SIZE 1500 // bytes +#define MAX_HICN_RETRY 5 + +struct hicn_listener { + 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 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 ListenerOps _hicnTemplate = {.context = NULL, + .destroy = &_destroy, + .getInterfaceIndex = &_getInterfaceIndex, + .getListenAddress = &_getListenAddress, + .getEncapType = &_getEncapType, + .getSocket = &_getSocket}; + +static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid); + +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 bool _isEmptyAddressIPv4(Address *address) { + bool res = false; + + if (strcmp("inet4://0.0.0.0:1234", addressToString(address)) == 0) res = true; + 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->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + + hicn->conn_id = forwarder_GetNextConnectionId(forwarder); + hicn->localAddress = addressCopy(address); + + 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); + 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); + + hicn->hicn_event = dispatcher_CreateNetworkEvent( + forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb, + (void *)hicn, hicn->hicn_fd); + dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), + hicn->hicn_event); + + ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + + memcpy(ops, &_hicnTemplate, sizeof(ListenerOps)); + ops->context = hicn; + + 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->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); + 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); + + hicn->hicn_event = dispatcher_CreateNetworkEvent( + forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb, + (void *)hicn, hicn->hicn_fd); + dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), + hicn->hicn_event); + + ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + + memcpy(ops, &_hicnTemplate, sizeof(ListenerOps)); + ops->context = hicn; + + 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_bild 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_bild 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; + + // close(hicn->hicn_fd); //XXX close the fd in the hicnlib (detroy listener?) + 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 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) { + printf("Error trying to discard frame from fd %d: (%d) %s", fd, errno, + strerror(errno)); + 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(HicnListener *hicn, int fd, + const AddressPair *pair) { + bool isLocal = false; + + // udpConnection_Create takes ownership of the pair + IoOperations *ops = hicnConnection_Create(hicn->forwarder, fd, pair, isLocal); + Connection *conn = connection_Create(ops); + + connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), conn); + unsigned connid = ioOperations_GetConnectionId(ops); + + return connid; +} + +const Connection *_findConnectionFromPacket(HicnListener *hicn, + Address *packetSourceAddress) { + 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 _handleProbeMessage(HicnListener *hicn, uint8_t *msgBuffer) { + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + if (packetAddr != NULL) { + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + if (conn != NULL) { + // we drop all the probes for a connection that does not exists + connection_HandleProbe((Connection *)conn, msgBuffer, + forwarder_GetTicks(hicn->forwarder)); + } + } + + addressDestroy(&packetAddr); + parcMemory_Deallocate((void **)&msgBuffer); +} + +static void _handleWldrNotification(HicnListener *hicn, uint8_t *msgBuffer) { + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + if (packetAddr == NULL) { + parcMemory_Deallocate((void **)&msgBuffer); + return; + } + + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + if (conn == NULL) { + addressDestroy(&packetAddr); + return; + } + + addressDestroy(&packetAddr); + + 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); +} + +#ifdef WITH_MAPME +static void _handleMapMe(HicnListener *hicn, int fd, uint8_t *msgBuffer) { + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + if (packetAddr == NULL) { + parcMemory_Deallocate((void **)&msgBuffer); + return; + } + + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + unsigned conn_id; + if (conn == NULL) { + /* Unlike the interest path, we don't create virtual connections bound + * on the listener, whose only interest is to send data, but full + * tunnels to be able to route interests + * + * packetAddr is the remote address, we need to ask the lib for our + * local address + * hicn->localAddress is None as the interest is received by the main + * listener. + */ + printf("MapMe, connection did not exist, creating\n"); + + /* Populate remote_address through packetAddr */ + struct sockaddr_in6 sockaddr; // XXX IPv6 only + addressGetInet6(packetAddr, &sockaddr); + ip_address_t remote_address = {.family = AF_INET6, + .prefix_len = IPV6_ADDR_LEN_BITS}; + memcpy(&remote_address.buffer, &sockaddr.sin6_addr, + ip_address_len(&remote_address)); + + /* Get local address through libhicn */ + ip_address_t local_address; + int rc = hicn_get_local_address(&remote_address, &local_address); + if (rc < 0) { + printf("Error getting local address. Discarded mapme packet.\n"); + return; + } + + 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 *)&(local_address.buffer), 16); + + Address *localAddr = addressCreateFromInet6(&addr_in6); + IoOperations *ops = + hicnTunnel_Create(hicn->forwarder, localAddr, packetAddr); + + if (!ops) { + printf("Error creating tunnel. Discarded mapme packet.\n"); + return; + } + + conn = connection_Create(ops); + + connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), + (Connection *)conn); + } + conn_id = connection_GetConnectionId(conn); + + addressDestroy(&packetAddr); + + forwarder_ProcessMapMe(hicn->forwarder, msgBuffer, conn_id); +} +#endif /* WITH_MAPME */ + +static Message *_readMessage(HicnListener *hicn, int fd, uint8_t *msgBuffer) { + 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); + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + + if (conn == NULL) { + AddressPair *pair = addressPair_Create(hicn->localAddress, packetAddr); + connid = _createNewConnection(hicn, 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(hicn, msgBuffer); + } else if (messageHandler_IsLoadBalancerProbe(msgBuffer)) { + _handleProbeMessage(hicn, msgBuffer); + } +#ifdef WITH_MAPME + else if (mapMe_isMapMe(msgBuffer)) { + /* This function triggers the handling of the MAP-Me message, and we + * will return NULL so as to terminate the processing of this + * msgBuffer. */ + _handleMapMe(hicn, fd, msgBuffer); + } +#endif /* WITH_MAPME */ + + return message; +} + +static void _receivePacket(HicnListener *hicn, int fd) { + Message *msg = NULL; + uint8_t *msgBuffer = parcMemory_AllocateAndClear(MTU_SIZE); + msg = _readMessage(hicn, fd, msgBuffer); + + if (msg) { + forwarder_Receive(hicn->forwarder, msg); + } +} + +static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid) { + HicnListener *hicn = (HicnListener *)hicnVoid; + + if (hicn->inetFamily == IPv4 || hicn->inetFamily == IPv6) { + if (what & PARCEventType_Read) { + _receivePacket(hicn, fd); + } + } else { + _readFrameToDiscard(hicn, fd); + } +} diff --git a/hicn-light/src/hicn/io/hicnListener.h b/hicn-light/src/hicn/io/hicnListener.h new file mode 100644 index 000000000..faf6ad6b8 --- /dev/null +++ b/hicn-light/src/hicn/io/hicnListener.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +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 new file mode 100644 index 000000000..f22c731c3 --- /dev/null +++ b/hicn-light/src/hicn/io/hicnTunnel.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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, 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 new file mode 100644 index 000000000..1fe0b413c --- /dev/null +++ b/hicn-light/src/hicn/io/hicnTunnel.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +/** + * 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 new file mode 100644 index 000000000..53adc47c5 --- /dev/null +++ b/hicn-light/src/hicn/io/ioOperations.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +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_SendCommandResponse(IoOperations *ops, + struct iovec *message) { + return ops->sendCommandResponse(ops, message); +} + + +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); +} + +Ticks ioOperations_SendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message) { + return ops->sendProbe(ops, probeType, message); +} diff --git a/hicn-light/src/hicn/io/ioOperations.h b/hicn-light/src/hicn/io/ioOperations.h new file mode 100644 index 000000000..115b017dc --- /dev/null +++ b/hicn-light/src/hicn/io/ioOperations.h @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include + +// 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. + * @discussion <#Discussion#> + */ +struct io_ops { + void *closure; + bool (*send)(IoOperations *ops, const Address *nexthop, Message *message); + bool (*sendCommandResponse)(IoOperations *ops, struct iovec *message); + 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); + Ticks (*sendProbe)(IoOperations *ops, unsigned probeType, uint8_t *message); +}; + +/** + * 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_SendCommandResponse(IoOperations *ops, + struct iovec *message); + +/** + * 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); + +Ticks ioOperations_SendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message); +#endif // io_h diff --git a/hicn-light/src/hicn/io/listener.h b/hicn-light/src/hicn/io/listener.h new file mode 100644 index 000000000..3d195ee88 --- /dev/null +++ b/hicn-light/src/hicn/io/listener.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 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 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); +}; +#endif // listener_h diff --git a/hicn-light/src/hicn/io/listenerSet.c b/hicn-light/src/hicn/io/listenerSet.c new file mode 100644 index 000000000..102496877 --- /dev/null +++ b/hicn-light/src/hicn/io/listenerSet.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +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; +} diff --git a/hicn-light/src/hicn/io/listenerSet.h b/hicn-light/src/hicn/io/listenerSet.h new file mode 100644 index 000000000..8d15a2736 --- /dev/null +++ b/hicn-light/src/hicn/io/listenerSet.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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); +#endif diff --git a/hicn-light/src/hicn/io/streamConnection.c b/hicn-light/src/hicn/io/streamConnection.c new file mode 100644 index 000000000..d9ba5a355 --- /dev/null +++ b/hicn-light/src/hicn/io/streamConnection.c @@ -0,0 +1,692 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +// 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; + Logger *logger; + + int fd; + + AddressPair *addressPair; + PARCEventQueue *bufferEventVector; + + bool isLocal; + bool isUp; + bool isClosed; + unsigned id; + + size_t nextMessageLength; +} _StreamState; + +// Prototypes +static bool _streamConnection_Send(IoOperations *ops, const Address *nexthop, + Message *message); +static bool _streamConnection_SendCommandResponse(IoOperations *ops, + struct iovec *msg); +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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message); + +/* + * 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, + .sendCommandResponse = &_streamConnection_SendCommandResponse, + .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, +}; + +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->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + stream->fd = fd; + 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); + + 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->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_SendCommandResponse(IoOperations *ops, + struct iovec *response) { + parcAssertNotNull(ops, "Parameter ops must be non-null"); + parcAssertNotNull(response, "Parameter message must be non-null"); + _StreamState *conn = (_StreamState *)ioOperations_GetClosure(ops); + + bool success = false; + if (conn->isUp) { + 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_Debug)) { + logger_Log( + conn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "connid %u Writing %zu bytes to buffer with backlog %zu bytes", + conn->id, + (response[0].iov_len + + response[1].iov_len), // NEW: take total lenght + buffer_backlog); + } + + // NEW: write directly ino the parcEventQueue without passing through + // message + int failure = + parcEventQueue_Write(conn->bufferEventVector, response[0].iov_base, + response[0].iov_len) + + parcEventQueue_Write(conn->bufferEventVector, response[1].iov_base, + response[1].iov_len); + + if (failure == 0) { + success = true; + } + } else { + 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); + } + } + } else { + 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 success; +} + +/** + * @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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message) { + // we don't need to implemet this here, it is a local connection + return 0; +} + +// ================================================================= +// 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); + 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) malformend 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 */ +} diff --git a/hicn-light/src/hicn/io/streamConnection.h b/hicn-light/src/hicn/io/streamConnection.h new file mode 100644 index 000000000..2b312e771 --- /dev/null +++ b/hicn-light/src/hicn/io/streamConnection.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include + +/** + * @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_SendCommandResponse(IoOperations *ops, struct iovec *response); + +#endif // streamConnection_h diff --git a/hicn-light/src/hicn/io/tcpListener.c b/hicn-light/src/hicn/io/tcpListener.c new file mode 100644 index 000000000..7a89248cf --- /dev/null +++ b/hicn-light/src/hicn/io/tcpListener.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef struct tcp_listener { + Forwarder *forwarder; + Logger *logger; + + PARCEventSocket *listener; + + Address *localAddress; + + unsigned id; + + // 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 unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops); +static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops); +static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops); + +static ListenerOps _tcpTemplate = { + .context = NULL, + .destroy = &_tcpListener_OpsDestroy, + .getInterfaceIndex = &_tcpListener_OpsGetInterfaceIndex, + .getListenAddress = &_tcpListener_OpsGetListenAddress, + .getEncapType = &_tcpListener_OpsGetEncapType, + .getSocket = NULL}; + +// STREAM daemon listener callback +static void _tcpListener_Listen(int, struct sockaddr *, int socklen, + void *tcpVoid); + +ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, + struct sockaddr_in6 sin6) { + _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); + parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(_TcpListener)); + + tcp->forwarder = forwarder; + tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + + 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, + struct sockaddr_in sin) { + _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); + parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(_TcpListener)); + + tcp->forwarder = forwarder; + tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + 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); + } + + logger_Release(&tcp->logger); + dispatcher_DestroyListener(forwarder_GetDispatcher(tcp->forwarder), + &tcp->listener); + addressDestroy(&tcp->localAddress); + parcMemory_Deallocate((void **)&tcp); + *listenerPtr = NULL; +} + +// ================================================== + +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 new file mode 100644 index 000000000..df0bbea1e --- /dev/null +++ b/hicn-light/src/hicn/io/tcpListener.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#endif + +#include +#include +#include + +ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, + struct sockaddr_in6 sin6); +ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, + struct sockaddr_in sin); +#endif // tcpListener_h diff --git a/hicn-light/src/hicn/io/tcpTunnel.c b/hicn-light/src/hicn/io/tcpTunnel.c new file mode 100644 index 000000000..710b88f5b --- /dev/null +++ b/hicn-light/src/hicn/io/tcpTunnel.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 new file mode 100644 index 000000000..d1d2a8524 --- /dev/null +++ b/hicn-light/src/hicn/io/tcpTunnel.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +/** + */ +// 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/udpConnection.c b/hicn-light/src/hicn/io/udpConnection.c new file mode 100644 index 000000000..b057f03ff --- /dev/null +++ b/hicn-light/src/hicn/io/udpConnection.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef struct udp_state { + Forwarder *forwarder; + 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; +} _UdpState; + +// Prototypes +static bool _send(IoOperations *ops, const Address *nexthop, Message *message); +static bool _sendCommandResponse(IoOperations *ops, struct iovec *message); +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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message); +/* + * 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, + .sendCommandResponse = &_sendCommandResponse, + .getRemoteAddress = &_getRemoteAddress, + .getAddressPair = &_getAddressPair, + .getConnectionId = &_getConnectionId, + .isUp = &_isUp, + .isLocal = &_isLocal, + .destroy = &_destroy, + .class = &_streamConnection_Class, + .getConnectionType = &_getConnectionType, + .sendProbe = &_sendProbe}; + +// ================================================================= + +static void _setConnectionState(_UdpState *Udp, bool isUp); +static bool _saveSockaddr(_UdpState *udpConnState, const AddressPair *pair); + +IoOperations *udpConnection_Create(Forwarder *forwarder, 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->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); + + 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); + 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); + 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 _sendCommandResponse(IoOperations *ops, struct iovec *message){ + 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, 2); + + 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[2]; + DWORD BytesSent = 0; + + for (int i = 0; i < 2; i++) { + dataBuf[i].buf = message[i].iov_base; + dataBuf[i].len = (ULONG)message[i].iov_len; + } + + int rc = WSASendTo(udpConnState->udpListenerSocket, dataBuf, 2, + &BytesSent, 0, (SOCKADDR *)udpConnState->peerAddress, + udpConnState->peerAddressLength, NULL, NULL); + + if (rc == SOCKET_ERROR) { + return false; + } +#endif + return true; +} + +static list_connections_type _getConnectionType(const IoOperations *ops) { + return CONN_UDP; +} + +static Ticks _sendProbe(IoOperations *ops, unsigned probeType, + uint8_t *message) { + //TODO + return 0; +} + +// ================================================================= +// 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; + } +} diff --git a/hicn-light/src/hicn/io/udpConnection.h b/hicn-light/src/hicn/io/udpConnection.h new file mode 100644 index 000000000..07c4da9bd --- /dev/null +++ b/hicn-light/src/hicn/io/udpConnection.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +/** + * 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, 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 new file mode 100644 index 000000000..e73896372 --- /dev/null +++ b/hicn-light/src/hicn/io/udpListener.c @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#endif +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef WITH_MAPME +#include +#endif /* WITH_MAPME */ + +#define IPv4 4 +#define IPv6 6 + +struct udp_listener { + Forwarder *forwarder; + Logger *logger; + + PARCEvent *udp_event; + SocketType udp_socket; + uint16_t port; + + unsigned id; + Address *localAddress; +}; + +static void _destroy(ListenerOps **listenerOpsPtr); +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 ListenerOps udpTemplate = {.context = NULL, + .destroy = &_destroy, + .getInterfaceIndex = &_getInterfaceIndex, + .getListenAddress = &_getListenAddress, + .getEncapType = &_getEncapType, + .getSocket = &_getSocket}; + +static void _readcb(int fd, PARCEventType what, void *udpVoid); + +ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, + struct sockaddr_in6 sin6) { + ListenerOps *ops = NULL; + + UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener)); + parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(UdpListener)); + udp->forwarder = forwarder; + 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) { + udp->udp_event = + dispatcher_CreateNetworkEvent(forwarder_GetDispatcher(forwarder), true, + _readcb, (void *)udp, udp->udp_socket); + dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), + udp->udp_event); + + ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + memcpy(ops, &udpTemplate, sizeof(ListenerOps)); + ops->context = udp; + + 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); + } +#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, + struct sockaddr_in sin) { + ListenerOps *ops = NULL; + + UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener)); + parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(UdpListener)); + udp->forwarder = forwarder; + 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) { + udp->udp_event = + dispatcher_CreateNetworkEvent(forwarder_GetDispatcher(forwarder), true, + _readcb, (void *)udp, udp->udp_socket); + dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), + udp->udp_event); + + ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + memcpy(ops, &udpTemplate, sizeof(ListenerOps)); + ops->context = udp; + + 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); + } + + close(udp->udp_socket); + 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); + } + +#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 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; +} + +/** + * @function _lookupConnectionId + * @abstract Lookup a connection in the connection table + * @discussion + * Looks up the connection in the connection table and returns the connection + * id if it exists. + * + * @param outputConnectionIdPtr is the output parameter + * @return true if connection found and outputConnectionIdPtr set + */ +static bool _lookupConnectionId(UdpListener *udp, AddressPair *pair, + unsigned *outputConnectionIdPtr) { + ConnectionTable *connTable = forwarder_GetConnectionTable(udp->forwarder); + + const Connection *conn = connectionTable_FindByAddressPair(connTable, pair); + if (conn) { + *outputConnectionIdPtr = connection_GetConnectionId(conn); + return true; + } else { + *outputConnectionIdPtr = 0; + return false; + } +} + +/** + * @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(UdpListener *udp, int fd, + const AddressPair *pair) { + //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, 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 _handleProbeMessage(UdpListener *udp, uint8_t *msgBuffer) { + // TODO + parcMemory_Deallocate((void **)&msgBuffer); +} + +static void _handleWldrNotification(UdpListener *udp, unsigned connId, + uint8_t *msgBuffer) { + const Connection *conn = connectionTable_FindById( + forwarder_GetConnectionTable(udp->forwarder), connId); + if (conn == NULL) { + 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(UdpListener *udp, int fd, + AddressPair *pair, uint8_t * packet, bool * processed) { + + Message *message = NULL; + + unsigned connid = 0; + bool foundConnection = _lookupConnectionId(udp, pair, &connid); + + 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(udp, 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 if (messageHandler_IsLoadBalancerProbe(packet)) { + *processed = true; + _handleProbeMessage(udp, packet); + } +#ifdef WITH_MAPME + else if (mapMe_isMapMe(packet)) { + *processed = true; + forwarder_ProcessMapMe(udp->forwarder, packet, connid); + } +#endif /* WITH_MAPME */ + + return message; +} + +static void _readCommand(UdpListener *udp, int fd, + AddressPair *pair, + uint8_t * command) { + + if (*command != REQUEST_LIGHT){ + printf("the message received is not a command, drop\n"); + return; + } + + command_id id = *(command + 1); + + if (id >= LAST_COMMAND_VALUE){ + printf("the message received is not a valid command, drop\n"); + return; + } + + unsigned connid = 0; + bool foundConnection = _lookupConnectionId(udp, pair, &connid); + if(!foundConnection){ + connid = _createNewConnection(udp, 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(UdpListener *udp, int fd, + AddressPair *pair, + uint8_t * packet) { + bool processed = false; + Message *message = _readMessage(udp, fd, pair, + packet, &processed); + if (message) { + forwarder_Receive(udp->forwarder, message); + } + return processed; +} + +static void _readcb(int fd, PARCEventType what, void *udpVoid) { + UdpListener *udp = (UdpListener *)udpVoid; + + 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" : "", udpVoid); + } + + 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"); + return; + } + + AddressPair *pair = _constructAddressPair( + udp, (struct sockaddr *)&peerIpAddress, peerIpAddressLength); + + bool done = _receivePacket(udp, fd, pair, packet); + if(!done){ + _readCommand(udp, fd, pair, packet); + } + + addressPair_Release(&pair); + } +} diff --git a/hicn-light/src/hicn/io/udpListener.h b/hicn-light/src/hicn/io/udpListener.h new file mode 100644 index 000000000..1ad3f77fe --- /dev/null +++ b/hicn-light/src/hicn/io/udpListener.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#endif + +#include +#include +#include + +struct udp_listener; +typedef struct udp_listener UdpListener; + +ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, + struct sockaddr_in6 sin6); +ListenerOps *udpListener_CreateInet(Forwarder *forwarder, + struct sockaddr_in sin); +// 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 new file mode 100644 index 000000000..79a15de41 --- /dev/null +++ b/hicn-light/src/hicn/io/udpTunnel.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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, 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 new file mode 100644 index 000000000..dacfdbb01 --- /dev/null +++ b/hicn-light/src/hicn/io/udpTunnel.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +/** + */ +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/CMakeLists.txt b/hicn-light/src/hicn/messenger/CMakeLists.txt new file mode 100644 index 000000000..92bc13b5b --- /dev/null +++ b/hicn-light/src/hicn/messenger/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +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 +) + +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 +) + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/messenger/messenger.c b/hicn-light/src/hicn/messenger/messenger.c new file mode 100644 index 000000000..201969ae2 --- /dev/null +++ b/hicn-light/src/hicn/messenger/messenger.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +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 new file mode 100644 index 000000000..79d65cda6 --- /dev/null +++ b/hicn-light/src/hicn/messenger/messenger.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +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 new file mode 100644 index 000000000..684eebd6c --- /dev/null +++ b/hicn-light/src/hicn/messenger/messengerRecipient.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +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 new file mode 100644 index 000000000..cb5705b3a --- /dev/null +++ b/hicn-light/src/hicn/messenger/messengerRecipient.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 new file mode 100644 index 000000000..8d332d96b --- /dev/null +++ b/hicn-light/src/hicn/messenger/missive.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +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 new file mode 100644 index 000000000..fdeddce83 --- /dev/null +++ b/hicn-light/src/hicn/messenger/missive.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 new file mode 100644 index 000000000..c659d8685 --- /dev/null +++ b/hicn-light/src/hicn/messenger/missiveDeque.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include +#include + +#include +#include + +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 new file mode 100644 index 000000000..c6f955ce0 --- /dev/null +++ b/hicn-light/src/hicn/messenger/missiveDeque.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 new file mode 100644 index 000000000..b0d9c7704 --- /dev/null +++ b/hicn-light/src/hicn/messenger/missiveType.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 new file mode 100644 index 000000000..191a72213 --- /dev/null +++ b/hicn-light/src/hicn/platforms/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") + list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/android/system.c + ) +elseif(APPLE) + list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/darwin/system.c + ) +elseif( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) + list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/linux/system.c + ) +elseif( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" ) + list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/windows/system.c + ${CMAKE_CURRENT_SOURCE_DIR}/windows/win_portability.c + ) + list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/windows/win_portability.h + ) + +endif() + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/platforms/README.txt b/hicn-light/src/hicn/platforms/README.txt new file mode 100644 index 000000000..a1293944c --- /dev/null +++ b/hicn-light/src/hicn/platforms/README.txt @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Operating system dependent modules. + diff --git a/hicn-light/src/hicn/platforms/android/system.c b/hicn-light/src/hicn/platforms/android/system.c new file mode 100644 index 000000000..0cbe05b9c --- /dev/null +++ b/hicn-light/src/hicn/platforms/android/system.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +//#define __USE_MISC +#include + +// to get the list of arp types +#include + +// for the mac address +#include + +#include +#include + +#include + +#include "ifaddrs.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) { + struct ifreq ifr; + int fd; + + fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + + strcpy(ifr.ifr_name, ifname); + ioctl(fd, SIOCGIFMTU, &ifr); + + close(fd); + return ifr.ifr_mtu; +} + +InterfaceSet *system_Interfaces(Forwarder *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); + parcAssertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); + + struct ifaddrs *next; + for (next = ifaddr; next != NULL; next = next->ifa_next) { + if ((next->ifa_addr == NULL) || ((next->ifa_flags & IFF_UP) == 0)) { + continue; + } + + Interface *iface = interfaceSetGetByName(set, next->ifa_name); + if (iface == NULL) { + unsigned mtu = (unsigned)getMtu(next->ifa_name); + + iface = interfaceCreate( + next->ifa_name, forwarder_GetNextConnectionId(forwarder), + next->ifa_flags & IFF_LOOPBACK, next->ifa_flags & IFF_MULTICAST, mtu); + + 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; + } + } + } + + freeifaddrs(ifaddr); + return set; +} + +Address *system_GetMacAddressByName(Forwarder *forwarder, + const char *interfaceName) { + Address *linkAddress = NULL; + + InterfaceSet *interfaceSet = system_Interfaces(forwarder); + Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); + + if (interface) { + const AddressList *addressList = interfaceGetAddresses(interface); + + size_t length = addressListLength(addressList); + for (size_t i = 0; i < length && !linkAddress; i++) { + const Address *a = addressListGetItem(addressList, i); + if (addressGetType(a) == ADDR_LINK) { + linkAddress = addressCopy(a); + } + } + } + + interfaceSetDestroy(&interfaceSet); + + return linkAddress; +} + +unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) { + unsigned mtu = 0; + + InterfaceSet *interfaceSet = system_Interfaces(forwarder); + Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); + + if (interface) { + mtu = interfaceGetMTU(interface); + } + + interfaceSetDestroy(&interfaceSet); + + return mtu; +} diff --git a/hicn-light/src/hicn/platforms/darwin/system.c b/hicn-light/src/hicn/platforms/darwin/system.c new file mode 100644 index 000000000..591e0507b --- /dev/null +++ b/hicn-light/src/hicn/platforms/darwin/system.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +InterfaceSet *system_Interfaces(Forwarder *forwarder) { + InterfaceSet *set = interfaceSetCreate(); + + // this is the dynamically allocated head of the list + struct ifaddrs *ifaddr; + int failure = getifaddrs(&ifaddr); + parcAssertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); + + struct ifaddrs *next; + for (next = ifaddr; next != NULL; next = next->ifa_next) { + if ((next->ifa_addr == NULL) || ((next->ifa_flags & IFF_UP) == 0)) { + continue; + } + + // This assumes the LINK address comes first so we can get the MTU + // when the interface is created. + + Interface *iface = interfaceSetGetByName(set, next->ifa_name); + if (iface == NULL) { + unsigned mtu = 0; + + if (next->ifa_data != NULL) { + struct if_data *ifdata = (struct if_data *)next->ifa_data; + mtu = ifdata->ifi_mtu; + } + + iface = interfaceCreate( + next->ifa_name, forwarder_GetNextConnectionId(forwarder), + next->ifa_flags & IFF_LOOPBACK, next->ifa_flags & IFF_MULTICAST, mtu); + + 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_LINK: { + struct sockaddr_dl *addr_dl = (struct sockaddr_dl *)next->ifa_addr; + + // skip links with 0-length address + if (addr_dl->sdl_alen > 0) { + // addr_dl->sdl_data[12] contains the interface name followed by the + // MAC address, so need to offset in to the array past the interface + // name. + Address *address = addressCreateFromLink( + (uint8_t *)&addr_dl->sdl_data[addr_dl->sdl_nlen], + addr_dl->sdl_alen); + interfaceAddAddress(iface, address); + } + break; + } + } + } + + freeifaddrs(ifaddr); + + return set; +} + +Address *system_GetMacAddressByName(Forwarder *forwarder, + const char *interfaceName) { + Address *linkAddress = NULL; + + InterfaceSet *interfaceSet = system_Interfaces(forwarder); + Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); + + if (interface) { + const AddressList *addressList = interfaceGetAddresses(interface); + + size_t length = addressListLength(addressList); + for (size_t i = 0; i < length && !linkAddress; i++) { + const Address *a = addressListGetItem(addressList, i); + if (addressGetType(a) == ADDR_LINK) { + linkAddress = addressCopy(a); + } + } + } + + interfaceSetDestroy(&interfaceSet); + + return linkAddress; +} + +unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) { + unsigned mtu = 0; + + if (interfaceName) { + InterfaceSet *interfaceSet = system_Interfaces(forwarder); + Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); + + if (interface) { + mtu = interfaceGetMTU(interface); + } + + interfaceSetDestroy(&interfaceSet); + } + return mtu; +} diff --git a/hicn-light/src/hicn/platforms/linux/system.c b/hicn-light/src/hicn/platforms/linux/system.c new file mode 100644 index 000000000..996660dbf --- /dev/null +++ b/hicn-light/src/hicn/platforms/linux/system.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define __USE_MISC +#include + +// to get the list of arp types +#include + +// for the mac address +#include + +#include +#include + +#include + +#include + +/** + * 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) { + struct ifreq ifr; + int fd; + + fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + + strcpy(ifr.ifr_name, ifname); + ioctl(fd, SIOCGIFMTU, &ifr); + + close(fd); + return ifr.ifr_mtu; +} + +InterfaceSet *system_Interfaces(Forwarder *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); + parcAssertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); + + struct ifaddrs *next; + for (next = ifaddr; next != NULL; next = next->ifa_next) { + if ((next->ifa_addr == NULL) || ((next->ifa_flags & IFF_UP) == 0)) { + continue; + } + + Interface *iface = interfaceSetGetByName(set, next->ifa_name); + if (iface == NULL) { + unsigned mtu = (unsigned)getMtu(next->ifa_name); + + iface = interfaceCreate( + next->ifa_name, forwarder_GetNextConnectionId(forwarder), + next->ifa_flags & IFF_LOOPBACK, next->ifa_flags & IFF_MULTICAST, mtu); + + 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; + } + } + } + + freeifaddrs(ifaddr); + return set; +} + +Address *system_GetMacAddressByName(Forwarder *forwarder, + const char *interfaceName) { + Address *linkAddress = NULL; + + InterfaceSet *interfaceSet = system_Interfaces(forwarder); + Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); + + if (interface) { + const AddressList *addressList = interfaceGetAddresses(interface); + + size_t length = addressListLength(addressList); + for (size_t i = 0; i < length && !linkAddress; i++) { + const Address *a = addressListGetItem(addressList, i); + if (addressGetType(a) == ADDR_LINK) { + linkAddress = addressCopy(a); + } + } + } + + interfaceSetDestroy(&interfaceSet); + + return linkAddress; +} + +unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) { + unsigned mtu = 0; + + InterfaceSet *interfaceSet = system_Interfaces(forwarder); + Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); + + if (interface) { + mtu = interfaceGetMTU(interface); + } + + interfaceSetDestroy(&interfaceSet); + + return mtu; +} diff --git a/hicn-light/src/hicn/platforms/windows/system.c b/hicn-light/src/hicn/platforms/windows/system.c new file mode 100644 index 000000000..df2a014a6 --- /dev/null +++ b/hicn-light/src/hicn/platforms/windows/system.c @@ -0,0 +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 +#include + +#include +#include + +#include + +#include +#include + +#define WORKING_BUFFER_SIZE 15000 +#define MAX_TRIES 3 + +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + +#include +#include + +#include + +/** + * 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 new file mode 100644 index 000000000..3138640dd --- /dev/null +++ b/hicn-light/src/hicn/platforms/windows/win_portability.c @@ -0,0 +1,50 @@ +/* + * 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 + +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); +} \ 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 new file mode 100644 index 000000000..5c25f4bb2 --- /dev/null +++ b/hicn-light/src/hicn/platforms/windows/win_portability.h @@ -0,0 +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 +#include +#include +#include +#include +#include +#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 new file mode 100644 index 000000000..b7eeabe3b --- /dev/null +++ b/hicn-light/src/hicn/processor/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +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 new file mode 100644 index 000000000..e7a680f9c --- /dev/null +++ b/hicn-light/src/hicn/processor/fib.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include +#include + +#include + +#define NULL_POS 128 +#define MSB_POS 127 + +struct node; +typedef struct node FibNode; + +struct node { + FibNode *left; + FibNode *right; + FibEntry *entry; + unsigned pos; +}; + +struct fib { + FibNode *root; + unsigned size; +}; + +// ===================================================== +// Public API + +FibNode *_createNode(FibNode *left, FibNode *right, FibEntry *entry, + unsigned pos) { + 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->pos = pos; + + return n; +} + +FIB *fib_Create() { + FIB *hicnFib = parcMemory_AllocateAndClear(sizeof(FIB)); + parcAssertNotNull(hicnFib, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(FIB)); + + hicnFib->root = + _createNode(NULL, NULL, NULL, + NULL_POS); // the pos will decrease going down in the trie + hicnFib->root->left = hicnFib->root; + hicnFib->root->right = hicnFib->root; + + hicnFib->size = 0; + + return hicnFib; +} + +void _destroyNode(FibNode *n) { + fibEntry_Release(&n->entry); + parcMemory_Deallocate((void **)&n); + n = NULL; +} + +void _destroyFib(FIB *fib) { + // XXX + // to be done + return; +} + +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); + 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 *name = name_GetContentName(fibEntry_GetPrefix(entry)); + + // search the name + FibNode *prev = fib->root; + FibNode *curr; + + if (nameBitvector_testBit(name, MSB_POS)) { + curr = fib->root->right; + } else { + curr = fib->root->left; + } + + while (prev->pos > curr->pos) { + prev = curr; + if (nameBitvector_testBit(name, curr->pos)) { + curr = curr->right; + } else { + curr = curr->left; + } + } + + if (curr->entry != NULL && + nameBitvector_Equals( + name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) { + // there is already an entry with this name + // do nothing. Before call ADD we should check + // if the node exists, and, in that case update it + return; + } + + // if the name is not in the FIB search for the first different bit between + // the new name to add and the node found in the trie + uint8_t pos = MSB_POS; + if (curr->entry != NULL) + pos = nameBitvector_firstDiff( + name, name_GetContentName(fibEntry_GetPrefix(curr->entry))); + + // reset pointer and search the insertion point + prev = fib->root; + if (nameBitvector_testBit(name, MSB_POS)) + curr = fib->root->right; + else + curr = fib->root->left; + + while (prev->pos > curr->pos && curr->pos > pos) { + prev = curr; + if (nameBitvector_testBit(name, curr->pos)) { + curr = curr->right; + } else { + curr = curr->left; + } + } + + // insert the node + fib->size++; + FibNode *n = _createNode(NULL, NULL, entry, pos); + + if (nameBitvector_testBit(name, pos)) { + n->left = curr; + n->right = n; + } else { + n->left = n; + n->right = curr; + } + + uint8_t new_pos = prev->pos; + if (new_pos == NULL_POS) new_pos = MSB_POS; + + if (nameBitvector_testBit(name, new_pos)) { + prev->right = n; + } else { + prev->left = n; + } +} + +FibEntry *fib_Contains(const FIB *fib, const Name *prefix) { + parcAssertNotNull(fib, "Parameter must be non-null"); + parcAssertNotNull(prefix, "Parameter must be non-null"); + + NameBitvector *name = name_GetContentName(prefix); + + // this is the same as the first part of the add function + // we cannnot call this function inside the add because + // we need the pointer prev and curr for the insertion + + FibNode *prev = fib->root; + FibNode *curr; + + if (nameBitvector_testBit(name, MSB_POS)) + curr = fib->root->right; + else + curr = fib->root->left; + + while (prev->pos > curr->pos) { + prev = curr; + + if (nameBitvector_testBit(name, curr->pos)) { + curr = curr->right; + } else { + curr = curr->left; + } + } + + if (curr->entry != NULL && + nameBitvector_Equals( + name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) { + return curr->entry; + } else { + return NULL; + } +} + +void _removeNode(FIB *fib, const Name *prefix) { + parcAssertNotNull(fib, "Parameter must be non-null"); + parcAssertNotNull(prefix, "Parameter must be non-null"); + + FibNode *grand = NULL; // grandparent + FibNode *prev = + fib->root; // parent: it will points to curr of the next hop in the trie + FibNode *curr; // current node: the node to remove + + NameBitvector *name = name_GetContentName(prefix); + + if (nameBitvector_testBit(name, MSB_POS)) { + curr = fib->root->right; + } else { + curr = fib->root->left; + } + + // in the first loop we always search the node to remove + while (prev->pos > curr->pos) { + grand = prev; + prev = curr; + + if (nameBitvector_testBit(name, curr->pos)) { + curr = curr->right; + } else { + curr = curr->left; + } + } + + if (!nameBitvector_Equals( + name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) { + // the node does not exists + return; + } + + // search for the real parent of curr (*tmpPrev) + // prev points to curr or next node in the trie + // this is because of the loopback links + + FibNode *tmpPrev = fib->root; + FibNode *tmpCurr; + + if (nameBitvector_testBit(name, MSB_POS)) { + tmpCurr = fib->root->right; + } else { + tmpCurr = fib->root->left; + } + + // here we compare pointer so we are sure to stop at the right potion + while (tmpCurr != curr) { + tmpPrev = tmpCurr; + + if (nameBitvector_testBit(name, tmpCurr->pos)) { + tmpCurr = tmpCurr->right; + } else { + tmpCurr = tmpCurr->left; + } + } + + // now curr is the node to remove and tmpPrev is the real parent of curr + + if (curr == prev) { + // this is the case where curr is a leaf node + FibNode *next; // child of curr (the loopback) + + if (nameBitvector_testBit(name, curr->pos)) { + next = curr->left; + } else { + next = curr->right; + } + + if (nameBitvector_testBit(name, tmpPrev->pos)) { + tmpPrev->right = next; + } else { + tmpPrev->left = next; + } + + } else { + // curr is an internal node + FibNode *next; // child of prev (loopback) + + if (nameBitvector_testBit(name, prev->pos)) { + next = prev->left; + } else { + next = prev->right; + } + + if (nameBitvector_testBit(name, grand->pos)) { + grand->right = next; + } else { + grand->left = next; + } + + if (nameBitvector_testBit(name, tmpPrev->pos)) { + tmpPrev->right = prev; + } else { + tmpPrev->left = prev; + } + + prev->left = curr->left; + prev->right = curr->right; + prev->pos = curr->pos; + } + + fib->size--; + _destroyNode(curr); +} + +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); + if (fibEntry_NexthopCount(entry) == 0) { + _removeNode(fib, name); + } +} + +void _removeConnectionId(FibNode *n, unsigned pos, unsigned connectionId, + FibEntryList *list) { + if (n->pos < pos) { + fibEntry_RemoveNexthopByConnectionId(n->entry, connectionId); + if (fibEntry_NexthopCount(n->entry) == 0) { + fibEntryList_Append(list, n->entry); + } + _removeConnectionId(n->left, n->pos, connectionId, list); + _removeConnectionId(n->right, n->pos, connectionId, list); + } +} + +void fib_RemoveConnectionId(FIB *fib, unsigned connectionId) { + parcAssertNotNull(fib, "Parameter must be non-null"); + + // 1 - we vist the tree to remove the connection id + // 2 - during the visit we collect the fib entry with 0 nexthop + // 3 - after the visit we remove this entries + + FibEntryList *list = fibEntryList_Create(); + + _removeConnectionId(fib->root->left, fib->root->pos, connectionId, list); + _removeConnectionId(fib->root->right, fib->root->pos, 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_Match(const FIB *fib, const Message *interestMessage) { + parcAssertNotNull(fib, "Parameter must be non-null"); + parcAssertNotNull(interestMessage, "Parameter must be non-null"); + + NameBitvector *name = name_GetContentName(message_GetName(interestMessage)); + + FibNode *prev = fib->root; + FibNode *curr; + + FibNode *match = NULL; + unsigned len = 0; + + if (nameBitvector_testBit(name, MSB_POS)) + curr = fib->root->right; + else + curr = fib->root->left; + + while (prev->pos > curr->pos) { + prev = curr; + + if (curr->entry != NULL) { + if (nameBitvector_StartsWith( + name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) && + nameBitvector_GetLength( + name_GetContentName(fibEntry_GetPrefix(curr->entry))) > len) { + match = curr; + len = nameBitvector_GetLength( + name_GetContentName(fibEntry_GetPrefix(curr->entry))); + } + } + + if (nameBitvector_testBit(name, curr->pos)) + curr = curr->right; + else + curr = curr->left; + } + + if (curr->entry != NULL) { + if (nameBitvector_StartsWith( + name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) && + nameBitvector_GetLength( + name_GetContentName(fibEntry_GetPrefix(curr->entry))) > len) { + match = curr; + len = nameBitvector_GetLength( + name_GetContentName(fibEntry_GetPrefix(curr->entry))); + } + } + + if (match != NULL && match->entry != NULL) { + return match->entry; + } else { + return NULL; + } +} + +void _collectFibEntries(FibNode *n, int pos, FibEntryList *list) { + if (n->pos < (unsigned)pos) { + fibEntryList_Append(list, n->entry); + _collectFibEntries(n->left, n->pos, list); + _collectFibEntries(n->right, n->pos, list); + } +} + +FibEntryList *fib_GetEntries(const FIB *fib) { + parcAssertNotNull(fib, "Parameter must be non-null"); + + FibEntryList *list = fibEntryList_Create(); + + _collectFibEntries(fib->root->left, fib->root->pos, list); + _collectFibEntries(fib->root->right, fib->root->pos, list); + + return list; +} diff --git a/hicn-light/src/hicn/processor/fib.h b/hicn-light/src/hicn/processor/fib.h new file mode 100644 index 000000000..28ea19a0d --- /dev/null +++ b/hicn-light/src/hicn/processor/fib.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include +#include + +struct fib; +typedef struct fib FIB; + +FIB *fib_Create(); + +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_Match(const FIB *fib, const Message *interestMessage); + +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 new file mode 100644 index 000000000..e32a1448c --- /dev/null +++ b/hicn-light/src/hicn/processor/fibEntry.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#ifdef WITH_MAPME +#include +#include +#endif /* WITH_MAPME */ + +#include +#include + +#include + +struct fib_entry { + Name *name; + unsigned refcount; + StrategyImpl *fwdStrategy; +#ifdef WITH_MAPME + void *userData; + void (*userDataRelease)(void **userData); +#endif /* WITH_MAPME */ +}; + +FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy) { + FibEntry *fibEntry = parcMemory_AllocateAndClear(sizeof(FibEntry)); + parcAssertNotNull(fibEntry, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(FibEntry)); + fibEntry->name = name_Acquire(name); + + if (fwdStrategy) { + switch (fwdStrategy) { + case SET_STRATEGY_LOADBALANCER: + fibEntry->fwdStrategy = strategyLoadBalancer_Create(); + break; + + case SET_STRATEGY_RANDOM_PER_DASH_SEGMENT: + fibEntry->fwdStrategy = strategyRndSegment_Create(); + break; + + case SET_STRATEGY_LOADBALANCER_WITH_DELAY: + fibEntry->fwdStrategy = strategyLoadBalancerWithPD_Create(); + break; + + default: + // LB is the defualt strategy + fibEntry->fwdStrategy = strategyLoadBalancer_Create(); + // the LB strategy is the default one + // other strategies can be set using the appropiate function + break; + } + + } else { + fibEntry->fwdStrategy = strategyLoadBalancer_Create(); + } + + fibEntry->refcount = 1; + +#ifdef WITH_MAPME + fibEntry->userData = NULL; + fibEntry->userDataRelease = NULL; +#endif /* WITH_MAPME */ + + 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->userData); + } +#endif /* WITH_MAPME */ + parcMemory_Deallocate((void **)&fibEntry); + } + *fibEntryPtr = NULL; +} + +void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy) { + StrategyImpl *fwdStrategyImpl; + + switch (strategy) { + case SET_STRATEGY_LOADBALANCER: + fwdStrategyImpl = strategyLoadBalancer_Create(); + break; + + case SET_STRATEGY_RANDOM_PER_DASH_SEGMENT: + fwdStrategyImpl = strategyRndSegment_Create(); + break; + + case SET_STRATEGY_LOADBALANCER_WITH_DELAY: + fwdStrategyImpl = strategyLoadBalancerWithPD_Create(); + break; + + default: + // LB is the defualt strategy + fwdStrategyImpl = strategyLoadBalancer_Create(); + // the LB strategy is the default one + // other strategies can be set using the appropiate function + break; + } + + 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; +} +void fibEntry_AddNexthop(FibEntry *fibEntry, unsigned connectionId) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId); +} + +void fibEntry_RemoveNexthopByConnectionId(FibEntry *fibEntry, + unsigned connectionId) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + fibEntry->fwdStrategy->removeNexthop(fibEntry->fwdStrategy, connectionId); +} + +size_t fibEntry_NexthopCount(const FibEntry *fibEntry) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + return fibEntry->fwdStrategy->countNexthops(fibEntry->fwdStrategy); +} + +const NumberSet *fibEntry_GetNexthops(const FibEntry *fibEntry) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + return fibEntry->fwdStrategy->returnNexthops(fibEntry->fwdStrategy); +} + +const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy( + const FibEntry *fibEntry, const Message *interestMessage) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + return fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy, + interestMessage); +} + +void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry, + const NumberSet *egressId, + const Message *objectMessage, Ticks rtt) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + fibEntry->fwdStrategy->receiveObject(fibEntry->fwdStrategy, egressId, + objectMessage, rtt); +} + +void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + fibEntry->fwdStrategy->onTimeout(fibEntry->fwdStrategy, egressId); +} + +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_AddNexthopByConnectionId(FibEntry *fibEntry, + unsigned connectionId) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId); +} + +void *fibEntry_getUserData(const FibEntry *fibEntry) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + return fibEntry->userData; +} + +void fibEntry_setUserData(FibEntry *fibEntry, const void *userData, + void (*userDataRelease)(void **)) { + parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); + 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 new file mode 100644 index 000000000..d677ae998 --- /dev/null +++ b/hicn-light/src/hicn/processor/fibEntry.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include + +#ifdef WITH_MAPME +#include +#include +#endif /* WITH_MAPME */ + +struct fib_entry; +typedef struct fib_entry FibEntry; + +FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy); + +/** + * 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); + +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); + +const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy( + const FibEntry *fibEntry, const Message *interestMessage); + +void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry, + const NumberSet *egressId, + const Message *objectMessage, Ticks rtt); + +void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId); + +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_AddNexthopByConnectionId + * @abstract Adds a next hop directly from the connection id. + * @param [in] fibEntry - Pointer to the FIB entry. + * @return The sequence number stored in the FIB entry. + */ +void fibEntry_AddNexthopByConnectionId(FibEntry *fibEntry, + unsigned connectionId); + +/** + * @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 *userData, + void (*userDataRelease)(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 new file mode 100644 index 000000000..1b9257bbc --- /dev/null +++ b/hicn-light/src/hicn/processor/fibEntryList.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include + +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 new file mode 100644 index 000000000..072a1b369 --- /dev/null +++ b/hicn-light/src/hicn/processor/fibEntryList.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +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 fibEntry. + * + * @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 new file mode 100644 index 000000000..2272f0ede --- /dev/null +++ b/hicn-light/src/hicn/processor/hashTableFunction.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +// ====================================================================== +// 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 new file mode 100644 index 000000000..eb9989086 --- /dev/null +++ b/hicn-light/src/hicn/processor/hashTableFunction.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +// ========================================================== +// 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 new file mode 100644 index 000000000..a035f5890 --- /dev/null +++ b/hicn-light/src/hicn/processor/matchingRulesTable.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include +#include +#include + +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 new file mode 100644 index 000000000..64a57d854 --- /dev/null +++ b/hicn-light/src/hicn/processor/matchingRulesTable.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + * matchingRulesTable_AddToBestTable() to add an interest to the + * "best" (i.e. most restrictive match) table, then calls + * matchingRulesTable_GetUnion() on a content object to match + * against all of them. + * + * When used in a ContentStore, one calls + * matchingRulesTable_AddToAllTables() to index a Content Object in + * all the tables. one then calls matchingRulesTable_Get() 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 +#include +#include + +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 new file mode 100644 index 000000000..f4c71a0b6 --- /dev/null +++ b/hicn-light/src/hicn/processor/messageProcessor.c @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; +}; + +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 + +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(); + + 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; + + 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); + + 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); + + const char *prefixStr = utils_PrefixLenToString( + control->addressType, &control->address, &control->len); + strategy_type fwdStrategy = + configuration_GetForwardingStrategy(config, prefixStr); + if (fwdStrategy == LAST_STRATEGY_VALUE) { + fwdStrategy = SET_STRATEGY_LOADBALANCER; + } + + Name *prefix = name_CreateFromAddress(control->addressType, control->address, + control->len); + FibEntry *entry = fib_Contains(processor->fib, prefix); + bool newEntry = false; + if (entry != NULL) { + fibEntry_AddNexthop(entry, ifidx); + } else { + newEntry = true; + entry = fibEntry_Create(prefix, fwdStrategy); + fibEntry_AddNexthop(entry, ifidx); + fib_Add(processor->fib, entry); + } + + name_Release(&prefix); + if (newEntry && (fwdStrategy == SET_STRATEGY_LOADBALANCER_WITH_DELAY)) { + strategyLoadBalancerWithPD_SetConnectionTable( + fibEntry_GetFwdStrategy(entry), + forwarder_GetConnectionTable(processor->forwarder)); + } + + 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; +} + +void messageProcessor_RemoveConnectionIdFromRoutes(MessageProcessor *processor, + unsigned connectionId) { + fib_RemoveConnectionId(processor->fib, connectionId); +} + +void processor_SetStrategy(MessageProcessor *processor, Name *prefix, + strategy_type strategy) { + FibEntry *entry = fib_Contains(processor->fib, prefix); + if (entry != NULL) { + fibEntry_SetStrategy(entry, strategy); + if (strategy == SET_STRATEGY_LOADBALANCER_WITH_DELAY) { + strategyLoadBalancerWithPD_SetConnectionTable( + fibEntry_GetFwdStrategy(entry), + forwarder_GetConnectionTable(processor->forwarder)); + } + } +} + +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 + * messageProcessor_Receive(), 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. + */ +static bool messageProcessor_AggregateInterestInPit(MessageProcessor *processor, + Message *interestMessage) { + 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 messageProcessor_ForwardToNexthops(), 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 + * interestMessage 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 + */ +static bool messageProcessor_ForwardViaFib(MessageProcessor *processor, + Message *interestMessage) { + FibEntry *fibEntry = fib_Match(processor->fib, interestMessage); + if (fibEntry == NULL) { + return false; + } + + PitEntry *pitEntry = pit_GetPitEntry(processor->pit, interestMessage); + if (pitEntry == NULL) { + return false; + } + + pitEntry_AddFibEntry(pitEntry, fibEntry); + + NumberSet *nexthops = (NumberSet *)fibEntry_GetNexthopsFromForwardingStrategy( + fibEntry, interestMessage); + // 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); + } + } + + 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 + if (messageProcessor_AggregateInterestInPit(processor, interestMessage)) { + // done + return; + } + + // 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 + if (messageProcessor_ForwardViaFib(processor, interestMessage)) { + // 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); + } + + // 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 new file mode 100644 index 000000000..64b08272d --- /dev/null +++ b/hicn-light/src/hicn/processor/messageProcessor.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include + +#include + +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); + +/** + * 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); + +#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 new file mode 100644 index 000000000..948291286 --- /dev/null +++ b/hicn-light/src/hicn/processor/pit.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +#include + +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 new file mode 100644 index 000000000..63a9b20e4 --- /dev/null +++ b/hicn-light/src/hicn/processor/pit.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include +#include + +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 + * pitEntry_Destory() 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 new file mode 100644 index 000000000..abc1dbcff --- /dev/null +++ b/hicn-light/src/hicn/processor/pitEntry.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include + +#include + +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 new file mode 100644 index 000000000..3cd5821bc --- /dev/null +++ b/hicn-light/src/hicn/processor/pitEntry.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#include +#include + +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 message_Release() + * 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 pitEntry_Release() 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 Message_Release() on it. + * + * @return A reference counted copy, call Message_Release() 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 new file mode 100644 index 000000000..1574f70ab --- /dev/null +++ b/hicn-light/src/hicn/processor/pitStandard.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include + +#define __STDC_FORMAT_MACROS +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +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)); + } + + return PITVerdict_Forward; + } + + // 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) { + // this is a rough estimation of the residual RTT + Ticks rtt = forwarder_GetTicks(pit->forwarder) - + pitEntry_GetCreationTime(pitEntry); + fibEntry_ReceiveObjectMessage(fibEntry, pitEntry_GetEgressSet(pitEntry), + objectMessage, + rtt); // need to implement RTT + } + 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 new file mode 100644 index 000000000..9d7ce6a23 --- /dev/null +++ b/hicn-light/src/hicn/processor/pitStandard.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + +/** + * 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 new file mode 100644 index 000000000..16631fa51 --- /dev/null +++ b/hicn-light/src/hicn/processor/pitVerdict.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 + */ +typedef enum { PITVerdict_Forward, PITVerdict_Aggregate } PITVerdict; +#endif // pitVerdict_h diff --git a/hicn-light/src/hicn/socket/CMakeLists.txt b/hicn-light/src/hicn/socket/CMakeLists.txt new file mode 100644 index 000000000..6ea94dcfa --- /dev/null +++ b/hicn-light/src/hicn/socket/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +if (UNIX AND NOT APPLE AND NOT ANDROID_API) + list(APPEND HEADER_FILES + socket/api.h + socket/error.h + socket/ops.h + ) + + list(APPEND SOURCE_FILES + socket/api.c + socket/error.c + socket/ops_linux.c + ) +endif() + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/socket/api.c b/hicn-light/src/hicn/socket/api.c new file mode 100644 index 000000000..aede01efe --- /dev/null +++ b/hicn-light/src/hicn/socket/api.c @@ -0,0 +1,604 @@ +#include // inet_ntop +#include // '' +#include // tfind(), tdestroy(), twalk(), preorder... +#include +#include // perror +#include // calloc +#include // memcpy +#include // '' +#include // getaddrinfo +#include // close + +#include "api.h" +#include "error.h" +#include "ops.h" + +#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN + +#define IF_NAMESIZE 16 +#define MAX_TABLES 256 + +#define DEFAULT_INTERVAL 1000 +#define DEFAULT_IDENTIFIER "hicn" +#define DEFAULT_SOCKET_IDENTIFIER "main" +#define LOCAL_IPV6_PREFIX "fe80" + +#define LOCAL_PRIORITY 32000 + +extern hicn_socket_ops_t ops; + +/* Configuration stored as a global variable to allow access from signal + * handlers for instance */ + +static hicn_conf_t hicn_default_conf = { + .identifier = DEFAULT_IDENTIFIER, + //.format = HF_INET6_TCP +}; + +/* Global state */ +// FIXME move into helper state ? + +struct ip_rule_state_ { + char tun_name[IF_NAMESIZE]; + ip_address_t ip_address; + uint32_t table_id; + uint8_t priority; + uint8_t address_family; +}; + +struct ip_route_state_ { + char remote_ip_address[128]; // this is to big, but it is fine for now + uint8_t address_family; + uint32_t table_id; +}; + +typedef struct ip_rule_state_ ip_rule_state; +typedef struct ip_route_state_ ip_route_state; + +int punting_table_id; +uint16_t rules_counter; +uint16_t routes_counter; +static ip_rule_state rules_to_remove[MAX_TABLES]; +static ip_route_state routes_to_remove[MAX_TABLES]; + +// END FIXME + +hicn_socket_helper_t *hicn_create() { + int rc; + + punting_table_id = -1; + rules_counter = 0; + + hicn_socket_helper_t *hicn = malloc(sizeof(hicn_socket_helper_t)); + if (!hicn) { + goto ERR_MALLOC; + } + + hicn->conf = malloc(sizeof(hicn_conf_t)); + if (hicn->conf < 0) goto ERR_CONF; + memcpy(hicn->conf, &hicn_default_conf, sizeof(hicn_conf_t)); + + /* Initialize socket tree to empty */ + hicn->socket_root = NULL; + + // enable forwarding globally. Per-interface forwarding will be enabled when + // interfaces are created (TODO) + rc = ops.enable_v6_forwarding(NULL); + if (rc < 0) { + goto ERR_FW; + } + + rc = ops.enable_v4_forwarding(); + if (rc < 0) { + goto ERR_FW; + } + + // modify priority of table local + /* ip -6 rule del from all prio 0 table local */ + /* ip -6 rule add from all prio 32000 table local */ + + rc = ops.del_lo_prio_rule(NULL, AF_INET6, 0); + if (rc < 0) { + goto ERR_FW; + } + + rc = ops.del_lo_prio_rule(NULL, AF_INET, 0); + if (rc < 0) { + goto ERR_FW; + } + + rc = ops.add_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY); + if (rc < 0) { + goto ERR_FW; + } + + rc = ops.add_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY); + if (rc < 0) { + goto ERR_FW; + } + + return hicn; + +ERR_FW: + free(hicn->conf); +ERR_CONF: + free(hicn); +ERR_MALLOC: + return NULL; +} + +void hicn_destroy() { + int rc; + uint16_t i; + + /* Restore default rules */ + printf("Restoring default configuration.\n"); + rc = ops.del_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY); + if (rc < 0) { + goto ERR; + } + + rc = ops.del_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY); + if (rc < 0) { + goto ERR; + } + + rc = ops.add_lo_prio_rule(NULL, AF_INET6, 0); + if (rc < 0) { + goto ERR; + } + + rc = ops.add_lo_prio_rule(NULL, AF_INET, 0); + if (rc < 0) { + goto ERR; + } + + for (i = 0; i < rules_counter; i++) { + if (strcmp(rules_to_remove[i].tun_name, "NONE") != 0) { + rc = ops.del_rule(rules_to_remove[i].tun_name, + rules_to_remove[i].address_family, + rules_to_remove[i].table_id); + if (rc < 0) { + goto ERR; + } + } else { + rc = ops.del_prio_rule( + &rules_to_remove[i].ip_address, rules_to_remove[i].address_family, + rules_to_remove[i].priority, rules_to_remove[i].table_id); + if (rc < 0) { + goto ERR; + } + } + } + + 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) { + goto ERR; + } + } + +ERR: + if (rc < 0) printf("Unexpected exit. Some state may not be deleted.\n"); + return; +} + +void hicn_free(hicn_socket_helper_t *hicn) { + // close tun ? + free(hicn); +} + +hicn_socket_t *hicn_socket_create() { + hicn_socket_t *socket = calloc(1, sizeof(hicn_socket_t)); + if (!socket) { + goto ERR_SOCKET; + } + socket->type = HS_UNSPEC; + + return socket; + +ERR_SOCKET: + return NULL; +} + +int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) { + return b->fd - a->fd; +} + +ip_address_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { + if (socket->type != HS_CONNECTION) { + return NULL; + } + return &socket->connection.tun_ip_address; +} + +typedef int (*cmp_t)(const void *, const void *); + +int hicn_socket_add(hicn_socket_helper_t *hicn, hicn_socket_t *socket) { + if (!(tsearch(socket, &hicn->socket_root, (cmp_t)hicn_socket_cmp))) { + // ERROR("Could not insert field id into index"); + return -1; + } + return 0; +} + +hicn_socket_t *hicn_socket_find(hicn_socket_helper_t *hicn, int fd) { + hicn_socket_t search = { + .fd = fd, + }; + hicn_socket_t **socket = + tfind(&search, &hicn->socket_root, (cmp_t)hicn_socket_cmp); + return socket ? *socket : NULL; +} + +/******************************************************************************* + * New API + *******************************************************************************/ + +int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address, + bool allow_null) { + int rc = HICN_SOCKET_ERROR_NONE; + + if (!local_ip_address) { + if (!allow_null) { + rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_NULL_ADDRESS; + } + goto end; + } + + /* local_ip_address should be a prefix with global scope in which to pick + * the locator address to use as the source. + * If we expect to pick another IP for the tun, then it needs to be of size + * less than 128. + */ + + /* Copy the local IP address inside the connection */ + rc = hicn_ip_pton(local_ip_address, &socket->connection.tun_ip_address); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR; + goto end; + } + +end: + return rc; +} + +// XXX This could be used by hicn_set_remote_endpoint +// XXX This has been introduced for mapme +int hicn_get_local_address(const ip_address_t *remote_address, + ip_address_t *local_address) { + int rc = 0; + uint32_t interface_id; + char remote_address_str[INET_MAX_ADDRSTRLEN]; + + rc = hicn_ip_ntop(remote_address, remote_address_str, + sizeof(remote_address_str)); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; + goto ERR; + } + + rc = ops.get_output_ifid(remote_address_str, remote_address->family, + &interface_id); + if (rc < 0 || interface_id == 0) { + rc = HICN_SOCKET_ERROR_BIND_REMOTE_INTERFACE; + goto ERR; + } + + /* Local ip */ + rc = ops.get_ip_addr(interface_id, remote_address->family, local_address); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_REMOTE_NETMASK; + goto ERR; + } + +ERR: + return rc; +} + +/** + * + * sets socket->interface_id + */ +int hicn_set_remote_endpoint(hicn_socket_t *socket, + const char *remote_ip_address) { + int af, rc = HICN_SOCKET_ERROR_NONE; + ip_address_t addr; + + af = get_addr_family(remote_ip_address); + if ((af != AF_INET6) && (af != AF_INET)) { + return HICN_SOCKET_ERROR_INVALID_IP_ADDRESS; + } + + /* Bind local endpoint if not done yet */ + if (ip_address_empty(&socket->connection.tun_ip_address)) { + char local_ip_address[INET_MAX_ADDRSTRLEN]; + + /* Local interface id */ + // INFO("Getting interface_id from gateway IP address %s", + // remote_ip_address); + ///// + int addr_family = get_addr_family(remote_ip_address); + if (addr_family < 0) { + rc = addr_family; + goto ERR; + } + + rc = ops.get_output_ifid(remote_ip_address, (uint8_t)addr_family, + &socket->connection.interface_id); + if (rc < 0 || socket->connection.interface_id == 0) { + rc = HICN_SOCKET_ERROR_BIND_REMOTE_INTERFACE; + goto ERR; + } + + /* Local ip */ + rc = ops.get_ip_addr(socket->connection.interface_id, (uint8_t)addr_family, + &addr); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_REMOTE_NETMASK; + goto ERR; + } + ///// + + /* Convert to representation format */ + rc = hicn_ip_ntop(&addr, local_ip_address, sizeof(local_ip_address)); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; + goto ERR; + } + + rc = hicn_set_local_endpoint(socket, local_ip_address, true); + if (rc < 0) { + switch (rc) { + case HICN_SOCKET_ERROR_SOCKET_LOCAL_NULL_ADDRESS: + rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_NULL_ADDR; + break; + case HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR: + rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_REPR; + break; + case HICN_SOCKET_ERROR_SOCKET_LOCAL_HEURISTIC: + rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_HEURISTIC; + break; + case HICN_SOCKET_ERROR_SOCKET_LOCAL_SET_TUN_IP: + rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_SET_TUN_IP; + break; + } + goto ERR; + } + } + return HICN_SOCKET_ERROR_NONE; + +ERR: + return rc; +} + +/** + * + * We need at least an identifier. + */ +int hicn_socket(hicn_socket_helper_t *hicn, const char *identifier, + const char *local_ip_address) { + int rc; + + hicn_socket_t *socket = hicn_socket_create(); + if (!socket) { + rc = -5; + goto ERR_SOCKET; + } + + ops.get_tun_name(hicn->conf->identifier, identifier, socket->tun_name); + + // register the hicn face on which to bind prefixes, create the in/out TUN + // device + socket->fd = ops.tun_create(socket->tun_name); + if (socket->fd <= 0) { + rc = -2; + goto ERR_TUN; + } + + // INFO("Successfully created listener on TUN device %s", socket->tun_name); + + /* Retrieve interface id */ + socket->tun_id = ops.get_ifid(socket->tun_name); + if (socket->tun_id < 0) { + rc = -3; + goto ERR_TUNIFID; + } + // INFO("Interface id=%d", socket->tun_id); + + // WARN("Need to set offload"); + + // INFO("Setting interface up"); + rc = ops.up_if(socket->tun_id); + if (rc < 0) { + rc = -4; + goto ERR_UP; + } + + /* Update state */ + rc = hicn_socket_add(hicn, socket); + if (rc < 0) { + rc = -5; + goto ERR_ADD; + } + + rc = hicn_set_local_endpoint(socket, local_ip_address, true); + if (rc < 0) { + rc = -6; + goto ERR_ADJACENCY; + } + + return socket->fd; + +ERR_ADJACENCY: +ERR_ADD: +ERR_UP: +ERR_TUNIFID: +ERR_TUN: + free(socket); +ERR_SOCKET: + // ERR_PARAMS: + return rc; +} + +int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { + int rc; + hicn_socket_t *socket = hicn_socket_find(hicn, fd); + if (!socket) { + return -1; + } + + /* Check socket is not a connection */ + if (socket->type == HS_CONNECTION) { + return -1; + } + + rc = ops.add_in_route_s(prefix, socket->tun_id); + if (rc < 0) { + return rc; + } + + ip_address_t ip_address; + rc = hicn_ip_pton(prefix, &ip_address); + if (rc < 0) { + return rc; + } + + // ip -6 rule add from b001::/16 prio 0 table 100 + socket->connection.table_id = + socket->tun_id % MAX_TABLES; // this table should be unused + + if (punting_table_id == -1) punting_table_id = socket->connection.table_id; + + rc = ops.add_prio_rule(&ip_address, ip_address.family, 0, + socket->connection.table_id); + if (rc < 0) { + return rc; + } + + strcpy(rules_to_remove[rules_counter].tun_name, "NONE"); + + rules_to_remove[rules_counter].ip_address = ip_address; + rules_to_remove[rules_counter].address_family = ip_address.family; + rules_to_remove[rules_counter].table_id = socket->connection.table_id; + rules_to_remove[rules_counter].priority = 0; + ++rules_counter; + + /* Update socket upon success */ + socket->type = HS_LISTENER; + + return 0; +} + +/** + * + * We can pass all adjacency parameters but identifier + */ +int hicn_bind(hicn_socket_helper_t *hicn, int fd, + const char *remote_ip_address) { + // uint32_t interface_id; + int rc = HICN_SOCKET_ERROR_NONE; + + hicn_socket_t *socket = hicn_socket_find(hicn, fd); + if (!socket) { + rc = HICN_SOCKET_ERROR_BIND_SOCKET_NOT_FOUND; + goto ERR; + } + + /* We allow reuse */ + if (socket->type == HS_CONNECTION) return rc; + + /* Check socket is not a connection */ + if (socket->type != HS_UNSPEC) { + rc = HICN_SOCKET_ERROR_BIND_SOCKET_ALREADY_BOUND; + goto ERR; + } + socket->type = HS_CONNECTION; + + // each connection is associated a table id, let's take it equal to the + // tun ID by default (% MAX_TABLES, assuming TUN IDs do not overlap modulo + // 256...). + // XXX we need to make sure the corresponding table is flushed. + socket->connection.table_id = + socket->tun_id % MAX_TABLES; // interface_id; // ops.get_free_table_id(); + + // XXX use IP address + rc = hicn_set_remote_endpoint(socket, remote_ip_address); + if (rc < 0) { + goto ERR; + } + + // rule + // ip -6 rule from all iif eth0 lookup 200 + // INFO("Adding output rule for %s in table %d", socket->tun_name, + // socket->connection.table_id); + int addr_family = get_addr_family(remote_ip_address); + if (addr_family < 0) { + rc = addr_family; + goto ERR; + } + + rc = ops.add_rule(socket->tun_name, (uint8_t)addr_family, + socket->connection.table_id); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_RULE; + goto ERR; + } + + strcpy(rules_to_remove[rules_counter].tun_name, socket->tun_name); + rules_to_remove[rules_counter].address_family = addr_family; + rules_to_remove[rules_counter].table_id = socket->connection.table_id; + ++rules_counter; + + // route + // ip -6 route add default via 2002::2 table 28 + // INFO("Adding output route in table %d via gateway %s", + // socket->connection.table_id, + // remote_ip_address); + + // if the address is an IPv6 and start with fe80 we need to specify the device + // in the route + u32 default_interface = ~0; + if (addr_family == AF_INET6 && strncmp(LOCAL_IPV6_PREFIX, remote_ip_address, + strlen(LOCAL_IPV6_PREFIX)) == 0) { + rc = ops.get_output_ifid(remote_ip_address, (uint8_t)addr_family, + &default_interface); + if (rc < 0) { + goto ERR; + } + } + + rc = ops.add_out_route(remote_ip_address, (uint8_t)addr_family, + socket->connection.table_id, default_interface); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_ROUTE; + goto ERR; + } + + strcpy(routes_to_remove[routes_counter].remote_ip_address, remote_ip_address); + routes_to_remove[routes_counter].table_id = socket->connection.table_id; + routes_to_remove[routes_counter].address_family = (uint8_t)addr_family; + ++routes_counter; + + // add route for data + // ip -6 route add 0:1::/64 dev hicn-if0 table 100 + // this routes are deleted by removing the tun interfaces + + if (punting_table_id == -1) { + // the punting_table_id was not initialized beacause no main-tun was created + // we use as an id (socket->tun_id - 1) % MAX_TABLES, so that we will hava a + // collision only after 255 new interfaces + punting_table_id = (socket->tun_id - 1) % MAX_TABLES; + } + rc = ops.add_in_route_table(&socket->connection.tun_ip_address, + socket->tun_id, punting_table_id); + if (rc < 0) { + rc = HICN_SOCKET_ERROR_BIND_ROUTE; + goto ERR; + } + +ERR: + return rc; +} diff --git a/hicn-light/src/hicn/socket/api.h b/hicn-light/src/hicn/socket/api.h new file mode 100644 index 000000000..3a1ae92b4 --- /dev/null +++ b/hicn-light/src/hicn/socket/api.h @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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_face.h + * @brief hICN socket library + * + * This module provides an interface to managing so-called hICN sockets, + * realizing punting of interest and data packets using a TUN device. + */ + +#ifndef HICN_SOCKET_API_H +#define HICN_SOCKET_API_H + +#include // uint*_t +#include + +#include +#include "error.h" + +#define BUFSIZE 4096 +#define MAX_CONNECTIONS \ + 255 // We currently limit the number of connections we can establish +#ifndef IF_NAMESIZE +#define IF_NAMESIZE 16 +#endif +/* hICN socket helper */ + +/** hICN configuration options */ +typedef struct { + // uint32_t interval; + + /* Identifier used to name hICN TUN interfaces (should be unique) */ + char *identifier; + // hicn_format_t format; + +} hicn_conf_t; + +/** + * hICN adjacency + */ +typedef struct { + char *local_ip_address; + char *gateway_ip_address; +} hicn_adjacency_t; + +#define EMPTY_HICN_ADJACENCY \ + (hicn_adjacency_t) { 0, 0 } + +/* hICN socket operations */ + +typedef struct { + uint8_t pkbuf[BUFSIZE]; + uint32_t rb_pkbuf_r; + uint32_t rb_pkbuf_w; +} hicn_buffer_t; + +typedef enum { HS_UNSPEC, HS_LISTENER, HS_CONNECTION } hicn_socket_type_t; + +typedef struct hicn_socket_s { + hicn_socket_type_t type; + int fd; + + /* Implementation specific state follows */ + char tun_name[IF_NAMESIZE]; + uint32_t tun_id; + + hicn_buffer_t buffer; + void (*cb)(struct hicn_socket_s *, void *, uint8_t *, size_t); + void *cb_data; + + union { + struct { + ip_address_t tun_ip_address; + uint32_t interface_id; + + /* ID of the corresponding table : avoid default values of 0, 32766 and + * 32767 */ + uint8_t table_id; + } connection; + }; +} hicn_socket_t; + +/** + * hICN global state + */ +typedef struct { + /* Configuration data */ + hicn_conf_t *conf; + + // We need state associate to each FD, to know what type of socket it is and + // its state. + void *socket_root; /**< A tree of socket indexed by their fd */ + +} hicn_socket_helper_t; + +/** + * Create an hICN instance. + * + * This is used to configure the state of an hICN router consistently between + * a listener and the different connections. It also regroups all the state + * related to hICN functionalities. + * + * @return A pointer to an hICN instance. + */ +hicn_socket_helper_t *hicn_create(); + +void hicn_destroy(); + +/** + * Retrieve hICN configuration. + * + * Gets the current configuration of an hICN instance for information purposes, + * or later update it. + * + * TODO + * - We might want to prevent configuration updates while the hICN instance is + * running. Define running... + * + * @param [in] hicn Pointer to hICN instance. + * @return Pointer to an hICN configuration data structure. + * + * @see hicn_set_conf + */ +hicn_conf_t *hicn_get_conf(hicn_socket_helper_t *hicn); + +/** + * Update hICN configuration. + * + * @param [in] hicn Pointer to an hICN instance. + * @param [in] hicn_conf Pointer to an hICN configuration data structure. + * @return 0 in case of success, -1 otherwise. + * + * @see hicn_get_conf + */ +int hicn_set_conf(hicn_socket_helper_t *hicn, hicn_conf_t *hicn_conf); + +/** + * Release hICN state. + * + * @param [in] hicn Pointer to an hICN instance. + */ +void hicn_free(hicn_socket_helper_t *hicn); + +// FIXME doc +int hicn_get_local_address(const ip_address_t *remote_address, + ip_address_t *local_address); + +/* hICN socket */ + +/** + * Create an hICN socket. + * + * An hICN socket abstracts the underlying implementation and allows hICN + * packets to be sent and received independently of the underlying + * implementation. + * + * It is possible to further specialize the socket in a listener socket, and a + * connection socket. + * + * @param [in] hicn Pointer to an hICN instance. + * @param [in] identifier Unique identifier for this socket, used to named the + * TUN device + * @param [in] local_ip_address IP address used locally by the socket (or NULL + * for letting the library decide automatically). + * @return File descriptor (>0) in case of success, -1 otherwise. + * + * @see hicn_listen + * @see hicn_bind + */ +int hicn_socket(hicn_socket_helper_t *hicn, const char *identifier, + const char *local_ip_address); + +/** + * Packet punting. + * + * Note that we cannot listen on a socket that is already bound. + * + * @param [in] hicn Pointer to an hICN instance. + * @param [in] fd File descriptor identifying the hICN socket. + * @param [in] prefix Prefix (IPv4 or IPv6) to be bound to hICN in + * RFC-compliant presentation format. + * @return 0 in case of success, -1 otherwise. + * + * @see hicn_socket + */ +int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix); + +/** + * Packet forwarding + * @param [in] hicn Pointer to an hICN instance. + * @param [in] fd File descriptor identifying the hICN socket. + * @param [in] prefix Prefix (IPv4 or IPv6) to be bound to hICN in + * RFC-compliant presentation format. + * @return 0 in case of success, -1 otherwise. + * + * XXX adjacency does not perform any copy heresofar + * + * @see hicn_socket + */ +int hicn_bind(hicn_socket_helper_t *hicn, int fd, + const char *remote_ip_address); + +#endif /* HICN_SOCKET_API_H */ diff --git a/hicn-light/src/hicn/socket/error.c b/hicn-light/src/hicn/socket/error.c new file mode 100644 index 000000000..3dafec8cf --- /dev/null +++ b/hicn-light/src/hicn/socket/error.c @@ -0,0 +1,7 @@ +#include "error.h" + +const char* HICN_SOCKET_ERROR_STRING[] = { +#define _(a, b, c) [b] = c, + foreach_hicn_socket_error +#undef _ +}; diff --git a/hicn-light/src/hicn/socket/error.h b/hicn-light/src/hicn/socket/error.h new file mode 100644 index 000000000..8195efd84 --- /dev/null +++ b/hicn-light/src/hicn/socket/error.h @@ -0,0 +1,46 @@ +#ifndef HICN_SOCKET_ERROR_H +#define HICN_SOCKET_ERROR_H + +// FIXME remove unused errors +#define foreach_hicn_socket_error \ + _(NONE, 0, "OK") \ + _(UNSPEC, 1, "unspecified error") \ + _(NOT_HICN, 2, "not a hICN paclet") \ + _(UNKNOWN_ADDRESS, 10, "unknown address") \ + _(INVALID_PARAMETER, 20, "invalid parameter") \ + _(INVALID_IP_ADDRESS, 21, "invalid IP address") \ + _(CORRUPTED_PACKET, 22, "corrupted packet") \ + _(UNEXPECTED, 98, "unexpected error") \ + _(NOT_IMPLEMENTED, 99, "not implemented") \ + _(SOCKET_LOCAL_NULL_ADDRESS, 101, "empty local address") \ + _(SOCKET_LOCAL_REPR, 102, "cannot represent local address") \ + _(SOCKET_LOCAL_HEURISTIC, 103, "error finding local address") \ + _(SOCKET_LOCAL_SET_TUN_IP, 104, "cannot set local IP to TUN") \ + _(BIND_SOCKET_NOT_FOUND, 301, "bind: socket not found") \ + _(BIND_SOCKET_ALREADY_BOUND, 302, "bind: socket already bound") \ + _(BIND_REMOTE_INTERFACE, 303, "bind: no interface towards gateway") \ + _(BIND_REMOTE_NETMASK, 304, "bind: no local IP with netmask < 128") \ + _(BIND_REMOTE_REPR, 305, "bind: error representing local IP") \ + _(BIND_REMOTE_LOCAL_NULL_ADDR, 306, "bind: could not set local endpoint") \ + _(BIND_REMOTE_LOCAL_REPR, 307, "bind: error representing remote IP") \ + _(BIND_REMOTE_LOCAL_HEURISTIC, 308, "bind: could not apply heuristic") \ + _(BIND_REMOTE_LOCAL_SET_TUN_IP, 309, "bind: error setting local IP to TUN") \ + _(BIND_NDP, 310, "bind: could not enable NDP proxy") \ + _(BIND_NEIGH_PROXY, 311, "bind: could not neighbour") \ + _(BIND_REPR, 312, "bind: error represeting IP") \ + _(BIND_LO, 313, "bind: could not remove local route") \ + _(BIND_RULE, 314, "bind: could not add rule") \ + _(BIND_ROUTE, 315, "bind: could not add output route") + +typedef enum { +#define _(a, b, c) HICN_SOCKET_ERROR_##a = (-b), + foreach_hicn_socket_error +#undef _ + HICN_SOCKET_N_ERROR, +} hicn_socket_error_t; + +extern const char *HICN_SOCKET_ERROR_STRING[]; + +#define hicn_socket_strerror(errno) (char *)(HICN_SOCKET_ERROR_STRING[-errno]) + +#endif /* HICN_SOCKET_ERROR_H */ diff --git a/hicn-light/src/hicn/socket/ops.h b/hicn-light/src/hicn/socket/ops.h new file mode 100644 index 000000000..249caf87a --- /dev/null +++ b/hicn-light/src/hicn/socket/ops.h @@ -0,0 +1,54 @@ +#ifndef HICN_SOCKET_OPS_H +#define HICN_SOCKET_OPS_H + +#include +#include + +typedef struct { + char *arch; + int (*tun_create)(char *name); + int (*get_tun_name)(const char *prefix, const char *identifier, + char *tun_name); + int (*enable_v6_forwarding)(char *interface_name); + int (*enable_v4_forwarding)(); + int (*enable_ndp_proxy)(); + + uint32_t (*get_ifid)(const char *ifname); + 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_address_t *ip_address); + int (*set_ip_addr)(uint32_t interface_id, ip_address_t *ip_address); + int (*up_if)(uint32_t interface_id); + int (*add_in_route_table)(const ip_address_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, + const uint8_t table_id); + int (*add_in_route_s)(const char *prefix, const uint32_t interface_id); + int (*add_out_route)(const char *gateway, const uint8_t address_family, + 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_address_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_address_t *ip_address, + const uint32_t interface_id); + int (*add_prio_rule)(const ip_address_t *ip_address, + const uint8_t address_family, const uint32_t priority, + const uint8_t table_id); + int (*add_lo_prio_rule)(const ip_address_t *ip_address, + const uint8_t address_family, + const uint32_t priority); + int (*del_prio_rule)(const ip_address_t *ip_address, + const uint8_t address_family, const uint32_t priority, + const uint8_t table_id); + int (*del_lo_prio_rule)(const ip_address_t *ip_address, + const uint8_t address_family, + const uint32_t priority); +} hicn_socket_ops_t; + +#endif /* HICN_SOCKET_OPS_H */ diff --git a/hicn-light/src/hicn/socket/ops_linux.c b/hicn-light/src/hicn/socket/ops_linux.c new file mode 100644 index 000000000..d085f0d3d --- /dev/null +++ b/hicn-light/src/hicn/socket/ops_linux.c @@ -0,0 +1,1723 @@ +#include // ioctl +#include // needed by linux/if.h +//#include +#include +#include // '' +#include +#include // PATH_MAX +#include // fprintf +#include // memset +#include // open +#include // writev +#include // close + +#include "error.h" +#include "ops.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) + +/****************************************************************************** + * netlink.h + ******************************************************************************/ + +#ifndef HICN_NETLINK_H +#define HICN_NETLINK_H + +#include +#include + +// DEPRECATED|/* Socket */ +// DEPRECATED|int _nl_get_socket(); +// DEPRECATED|int _nl_send(int s, uint8_t * buffer, size_t len); +// DEPRECATED|size_t _nl_receive(uint8_t * buffer, size_t len); +// DEPRECATED| +// DEPRECATED|/* Netlink packet format */ +// DEPRECATED|int _nl_header(int request, uint8_t * buffer, size_t len, uint32_t +// flags); DEPRECATED|int _nl_payload_rule(uint8_t table_id, uint8_t * buffer, +// size_t len); DEPRECATED|int _nl_payload_link(uint32_t ifindex, uint8_t * +// buffer, size_t len); DEPRECATED|int _nl_payload_route(uint8_t table_id, +// uint8_t dst_len, uint8_t * buffer, size_t len); DEPRECATED| DEPRECATED|int +// _nl_parse(uint8_t * buffer, size_t len); DEPRECATED|int _nl_parse_ret(uint8_t +// * buffer, size_t len); DEPRECATED|int _nl_parse_link_ifid(uint8_t * buffer, +// size_t len, uint32_t * interface_id); DEPRECATED|int +// _nl_parse_link_ip_addr(uint8_t * buffer, size_t len, struct in6_addr * addr); + +/* Public interface */ + +/** + * Get the interface ID of an interface by its name + * + * @return 32-bit interface identifier in case of success, or 0. + * + * @see if_nametoindex + * + */ +uint32_t _nl_get_ifid(const char *ifname); + +/** + * Retrieve the output interface corresponding to the specified IP address. + * + * @param [in] addr IP(v6) address in presentation form. + * @param [out] Identifier of the corresponding output interface. + * @return int 0 in case of success, -1 otherwise + */ +int _nl_get_output_ifid(const char *ip_address, uint8_t address_family, + uint32_t *interface_id); + +/** + * Retrieve the first IP address of an interface (identified by its id) which + * has a netmask < 128. + * + * @param [in] s File descriptor of the netlink socket (deprecated). + * @param [in] interface_id Identifier of the interface for which to retrieve + * the IP address. + * @param [out] addr IP(v6) address in binary form. + * @return int 0 in case of success, -1 otherwise + * + * @see getifaddrs + */ +int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, + ip_address_t *ip_address); + +int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address); + +int _nl_up_if(uint32_t interface_id); + +int _nl_add_in_route_table(const ip_address_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); +int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id); + +int _nl_add_out_route(const char *gateway, const uint8_t address_family, + const uint8_t table_idi, int default_route); +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_address_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_address_t *ip_address, + const uint32_t interface_id); + +int _nl_add_prio_rule(const ip_address_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_address_t *ip_address, + const uint8_t address_family, const uint32_t priority); +int _nl_del_prio_rule(const ip_address_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_address_t *ip_address, + const uint8_t address_family, const uint32_t priority); + +#endif /* HICN_NETLINK_H */ + +/****************************************************************************** + * netlink.c + ******************************************************************************/ + +/* + * This module offers an interface to the Netlink API appropriate for + * implementing punting as required by hICN (1). + * + * More specifically, it consists of the following functionalities: + * - LINK + . map interface name to ID + . set and interface up + * - ADDR + . get and set ip addresses on a given interface ID + * - ROUTE + . get output interface id towards IP (ip route get IP > interface_id) + . add input route (ip route add PREFIX dev INTERFACE) for punting + interests . add output route (ip route add default GATEWAY table TABLE) for + routing interests (2, 3) . delete local route towards IP (ip route del IP table + local) for ??? + /!\ could this be avoided by removing the local attribute in the + netlink call ? + * - RULE + * . add output rule (ip rule add iif interface table TABLE) for routing + interests (2, 3) + * - ND PROXY + * . enable NDP proxy functionality for IP on interface ID (ip -6 neigh add + proxy IP dev INTERFACE) + * for allowing the TUN to be reachable on the reverse data path + * + * Implementation notes: + * (1) We have not been using the libnl library because it requires + * manipulating too many function and data structures for a simple purpose. + * Currently, many parts of the code are somehow repetitive, but this might + * be improved by a proper API in a future release. + * (2) allows load balancing over different interfaces = multihoming. Please + * note that it is not possible to have load balancing over two faces using + * the same output interface as we are using the underlying IP network ! + * This might be mitigated with the use of SR however. + * (3) The implementation of punting heavily uses the policy routing + * functionalities, as we need to hook through a TUN into user space a + * whole prefix used as a destination (for interests) or source (for data + * packets). We thus combine the use of rules to assign routing table IDs, + * and routes inside those tables. As there is no easy way to allocate + * which routing tables we use, we made the choice to index them by the ID + * of the interface, assuming there is no external conflict. This might be + * improved in the future. + * + * This hICN implementation uses TUNs in two different ways: + * - a main TUN interface, which receives all punted interests, + * demultiplex them before assigning them an input face (eventually + * dynamically creating it); + * - a set of output TUN interfaces, aka faces, used for routing of + * interests, and for receiving the corresponding data packets on the way + * back. Punting of data packets if based of their destination IP, which + * is the IP of the physical output interface used for the interest, which + * is unique (cf (2)). + * + * The corresponding routing tables IDs are : + * MAIN_TUN_ID -> used for punting of data packets + * OUTPUT_TUN_ID_i -> used for routing of interests towards next hop + * (bypassing local IP routing table) + * + * Note that punting of interests is done just through a route, and routing + * of data packets is done just through the regular IP routing table on the + * note after the address translation done in the forwarder. + * + * - Forging netlink packets + * + * A previous implementation used function calls with pointers to populate + * the various header parts in a buffer in order to build a netlink packet. + * A newer implementation uses nested structs and iovecs to build the whole + * packet in a single write call. This should allow a simpler evolution + * towards a cleaner API. + */ + +#include // inet_pton +#include // errno +#include // fib_rule_hdr, FRA_* +#include +#include +#include // IFF_UP +#include // in6addr +#include // perror +#include +#include // '' +#include // socket +#include // read + +#include // '' +#include // send, recv + +//#include "../../hicn.h" +//#include "../../hicn_util.h" // ARRAY_SIZE, hicn_packet_dump_iov + +#define BUFSIZE 4096 +#define FLAGS_CREATE NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK +// ?? +#define FLAGS_CREATE_MATCH \ + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_MATCH + +// XXX putting ACK poses a prolem for the value received by get_if_id. +#define FLAGS_GET NLM_F_REQUEST +#define FLAGS_GET_ROOT (NLM_F_REQUEST | NLM_F_ROOT) + +#define FLAGS_LIST NLM_F_REQUEST | NLM_F_DUMP + +#define IF_NAMESIZE 16 +#define FR_ACT_TO_TBL 1 +#define NLMSG_BOTTOM(nlmsg) \ + ((struct rtattr *)(((void *)(nlmsg)) + NLMSG_ALIGN((nlmsg)->nlmsg_len))) + +int seq = 1; + +static inline size_t iov_length(const struct iovec *iov, + unsigned long nr_segs) { + unsigned long seg; + size_t ret = 0; + + for (seg = 0; seg < nr_segs; seg++) ret += iov[seg].iov_len; + return ret; +} + +typedef struct { + struct nlmsghdr hdr; + struct nlmsgerr payload; +} nl_err_hdr_t; + +/* Low level : nl header */ + +int _nl_get_socket() { return socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); } + +int _nl_header(int request, uint8_t *buffer, size_t len, uint32_t flags) { + struct nlmsghdr *nl = (struct nlmsghdr *)buffer; + + nl->nlmsg_len = 0; // NLMSG_LENGTH(sizeof(struct ifinfomsg)); + nl->nlmsg_type = request; + nl->nlmsg_flags = flags; + nl->nlmsg_seq = seq++; // + nl->nlmsg_pid = 0; // getpid(); + + return 0; +} + +/* Low level : nl protocols */ + +/* Low level : attributes */ + +int addAttr(struct nlmsghdr *nl, int maxlen, int type, void *data, + int attr_len) { + struct rtattr *rta; + int len = RTA_LENGTH(attr_len); + + if (NLMSG_ALIGN(nl->nlmsg_len) + len > maxlen) { + exit(EXIT_FAILURE); + } + + rta = (struct rtattr *)((char *)nl + NLMSG_ALIGN(nl->nlmsg_len)); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, attr_len); + nl->nlmsg_len = NLMSG_ALIGN(nl->nlmsg_len) + len; + return 0; +} + +int _nl_payload_rule(uint8_t table_id, uint8_t address_family, uint8_t *buffer, + size_t len) { + struct nlmsghdr *nl = (struct nlmsghdr *)buffer; + struct fib_rule_hdr *frh = (struct fib_rule_hdr *)(NLMSG_DATA(buffer)); + + memset(frh, 0, sizeof(struct fib_rule_hdr)); + frh->family = address_family; + frh->table = table_id; + frh->action = FR_ACT_TO_TBL, + frh->flags = NLM_F_REPLACE; // 0 + frh->tos = 0; + + nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct fib_rule_hdr)); + + return 0; +} + +int _nl_payload_link(uint32_t ifindex, uint8_t *buffer, size_t len) { + struct nlmsghdr *nl = (struct nlmsghdr *)buffer; + struct ifinfomsg *ifi = (struct ifinfomsg *)(NLMSG_DATA(buffer)); + + memset(ifi, 0, sizeof(struct ifinfomsg)); + ifi->ifi_family = AF_UNSPEC; + // ifi->ifi_type = 0; + ifi->ifi_index = + ifindex; // new interface, could be specified since linux 3.7 + ifi->ifi_flags = 0; + // ifi->ifi_change = 0xffffffff; + + nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct ifinfomsg)); + + return 0; +} + +int _nl_payload_addr(uint32_t ifindex, uint8_t *buffer, size_t len) { + struct nlmsghdr *nl = (struct nlmsghdr *)buffer; + struct ifaddrmsg *addr = (struct ifaddrmsg *)(NLMSG_DATA(buffer)); + + memset(addr, 0, sizeof(struct ifaddrmsg)); + addr->ifa_family = AF_UNSPEC; // INET6; + /* + addr->ifa_prefixlen = 128; + addr->ifa_flags = 0; + addr->ifa_scope = RT_SCOPE_LINK; //IFA_ADDRESS; + addr->ifa_index = ifindex; + */ + + nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct ifaddrmsg)) - 4; + + return 0; +} + +int _nl_payload_route(uint8_t table_id, uint8_t addr_family, uint8_t dst_len, + uint8_t *buffer, size_t len) { + struct nlmsghdr *nl = (struct nlmsghdr *)buffer; + struct rtmsg *raddr = (struct rtmsg *)(NLMSG_DATA(buffer)); + + raddr->rtm_family = addr_family; + raddr->rtm_dst_len = dst_len; + raddr->rtm_src_len = 0; + raddr->rtm_tos = 0; + + raddr->rtm_table = table_id; + raddr->rtm_protocol = RTPROT_BOOT; + raddr->rtm_scope = RT_SCOPE_UNIVERSE; + raddr->rtm_type = RTN_UNICAST; + + raddr->rtm_flags = 0; + + nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct rtmsg)); + + return 0; +} + +uint32_t _nl_get_ifid(const char *interface_name) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + size_t len = interface_name ? strlen(interface_name) + 1 : 0; + uint8_t padding[RTA_ALIGNTO] = {0, 0, 0, 0}; + + if (len == 0) { + goto ERR_IF; + } + + struct { + struct nlmsghdr hdr; + struct ifinfomsg payload; + } msg = {//.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + .hdr.nlmsg_type = RTM_GETLINK, + .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 iovec iov[] = {{&msg, sizeof(msg)}, + {&a_ifname, sizeof(a_ifname)}, + {(char *)interface_name, len}, + {padding, RTA_SPACE(len) - RTA_LENGTH(len)}}; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; /* Unexpected */ + } + + for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { + struct ifinfomsg *payload = (struct ifinfomsg *)NLMSG_DATA(hdr); + return payload->ifi_index; + } + return 0; + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: +ERR_IF: + return 0; +} + +int _nl_get_output_ifid(const char *ip_address, uint8_t family_address, + uint32_t *interface_id) { + int rc; + + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR; + } + + if (family_address == AF_INET6) { + struct in6_addr addr; // V6SPECIFIC + + struct { + struct nlmsghdr hdr; + struct rtmsg payload; + } msg = { + .hdr.nlmsg_type = RTM_GETROUTE, + .hdr.nlmsg_flags = NLM_F_REQUEST, + .hdr.nlmsg_seq = seq++, + .payload.rtm_family = AF_INET6, + .payload.rtm_dst_len = IPV6_ADDR_LEN_BITS, + .payload.rtm_src_len = 0, + .payload.rtm_tos = 0, + .payload.rtm_table = RT_TABLE_UNSPEC, + .payload.rtm_protocol = RTPROT_UNSPEC, + .payload.rtm_scope = RT_SCOPE_UNIVERSE, + .payload.rtm_type = RTN_UNSPEC, + .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' + }; + + /* Convert the IP address to binary form */ + rc = inet_pton(AF_INET6, ip_address, &addr); + if (rc <= 0) { + goto ERR; + } + + /* Set attribute = length/type/value */ + struct rtattr a_dst = {RTA_LENGTH(16), RTA_DST}; + struct iovec iov[] = { + {&msg, sizeof(msg)}, + {&a_dst, sizeof(a_dst)}, // attribute + {&addr, sizeof(addr)} // value + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + } else if (family_address == AF_INET) { + struct in_addr addr; + + struct { + struct nlmsghdr hdr; + struct rtmsg payload; + } msg = { + .hdr.nlmsg_type = RTM_GETROUTE, + .hdr.nlmsg_flags = NLM_F_REQUEST, + .hdr.nlmsg_seq = seq++, + .payload.rtm_family = AF_INET, + .payload.rtm_dst_len = IPV4_ADDR_LEN_BITS, + .payload.rtm_src_len = 0, + .payload.rtm_tos = 0, + .payload.rtm_table = RT_TABLE_UNSPEC, + .payload.rtm_protocol = RTPROT_UNSPEC, + .payload.rtm_scope = RT_SCOPE_UNIVERSE, + .payload.rtm_type = RTN_UNSPEC, + .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' + }; + + /* Convert the IP address to binary form */ + rc = inet_pton(AF_INET, ip_address, &addr); + if (rc <= 0) { + goto ERR; + } + + /* Set attribute = length/type/value */ + struct rtattr a_dst = {RTA_LENGTH(4), RTA_DST}; + struct iovec iov[] = { + {&msg, sizeof(msg)}, + {&a_dst, sizeof(a_dst)}, // attribute + {&addr, sizeof(addr)} // value + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + } else { + goto ERR; + } + + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR; + } + return HICN_SOCKET_ERROR_UNEXPECTED; /* Unexpected */ + } + + for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { + struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(hdr); + int attrlen = RTM_PAYLOAD(hdr); + struct rtattr *rta; + for (rta = RTM_RTA(rtm); RTA_OK(rta, attrlen); + rta = RTA_NEXT(rta, attrlen)) { + if (rta->rta_type == RTA_OIF) { + *interface_id = *(uint32_t *)RTA_DATA(rta); + return HICN_SOCKET_ERROR_NONE; + } + } + } + + return HICN_SOCKET_ERROR_NONE; + +ERR: + return HICN_SOCKET_ERROR_UNSPEC; +} + +int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, + ip_address_t *ip_address) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + struct { + struct nlmsghdr hdr; + struct ifaddrmsg payload; + } msg = {.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), + .hdr.nlmsg_type = RTM_GETADDR, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT, // | NLM_F_MATCH, + .payload.ifa_family = address_family, + .payload.ifa_index = 0}; + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + n = send(fd, &msg, sizeof(msg), 0); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return -99; /* Unexpected */ + } + + for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { + struct ifaddrmsg *payload = (struct ifaddrmsg *)NLMSG_DATA(hdr); + + if (address_family == AF_INET6) { + if ((payload->ifa_index == interface_id) && + (payload->ifa_prefixlen < IPV6_ADDR_LEN * 8)) { + printf("got ip address\n"); + memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV6_ADDR_LEN); + ip_address->family = AF_INET6; + ip_address->prefix_len = IPV6_ADDR_LEN_BITS; + printf("returning %d\n", HICN_SOCKET_ERROR_NONE); + return HICN_SOCKET_ERROR_NONE; + } + } else if (address_family == AF_INET) { + if ((payload->ifa_index == interface_id) && + (payload->ifa_prefixlen < IPV4_ADDR_LEN * 8)) { + printf("got ip address\n"); + memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV4_ADDR_LEN); + ip_address->family = AF_INET; + ip_address->prefix_len = IPV4_ADDR_LEN_BITS; + printf("returning %d\n", HICN_SOCKET_ERROR_NONE); + return HICN_SOCKET_ERROR_NONE; + } + } else { + return -99; + } + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + printf("error getting ip address\n"); + return HICN_SOCKET_ERROR_UNSPEC; +} + +int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + struct { + struct nlmsghdr hdr; + struct ifaddrmsg payload; + } msg = { + .hdr.nlmsg_type = RTM_NEWADDR, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC, + .hdr.nlmsg_seq = seq++, + .payload.ifa_family = ip_address->family, + .payload.ifa_prefixlen = ip_address->prefix_len, + .payload.ifa_flags = 0, + .payload.ifa_scope = RT_SCOPE_UNIVERSE, + .payload.ifa_index = interface_id}; + + /* Set attributes = length/type/value */ + struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(ip_address)), + IFA_ADDRESS}; + // XXX maybe the reason why we have a local route ? + // struct rtattr ifa_local = { RTA_LENGTH(ip_address_len(ip_address)), + // IFA_LOCAL }; + struct iovec iov[] = { + {&msg, sizeof(msg)}, + {&ifa_address, sizeof(ifa_address)}, + {(void *)&ip_address->buffer, sizeof(ip_address->buffer)}, + // { &ifa_local, sizeof(ifa_local) }, + // { (void*)&ip_address->buffer, sizeof(ip_address->buffer) }, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + // hicn_packet_dump_iov(iov, ARRAY_SIZE(iov)); + + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + } + + return 0; + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; +} + +int _nl_up_if(uint32_t interface_id) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + struct { + struct nlmsghdr hdr; + struct ifinfomsg payload; + } msg = { + .hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + .hdr.nlmsg_type = RTM_NEWLINK, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .payload.ifi_family = AF_UNSPEC, + .payload.ifi_index = interface_id, + .payload.ifi_flags = IFF_UP, + .payload.ifi_change = IFF_UP // 0xffffffff + }; + + n = send(fd, &msg, sizeof(msg), 0); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; +} + +struct route_info { + char *dst_addr; + char *src_addr; + char *gateway; + char ifName[IF_NAMESIZE]; +}; + +/* + * ip -6 route add PREFIX dev INTERFACE_NAME + */ +#if 0 +int _nl_add_in_route(const char * prefix, const uint32_t interface_id) +{ + char buffer[BUFSIZE]; + struct nlmsghdr * hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + int pton_fd; + unsigned char dst[sizeof(struct in6_addr)]; + char * p; + char * eptr; + char addr[strlen(prefix)]; + uint32_t dst_len; + + strncpy(addr, prefix, strlen(prefix)); + + p = strchr(addr, '/'); + if (!p) { + dst_len = IPV6_ADDR_LEN; + } else { + dst_len = strtoul(p + 1, &eptr, 10); + if (dst_len > IPV6_ADDR_LEN * 8) { + printf("E: Netmask > IPV6_ADDR_LEN"); + return -1; + } + *p = 0; + } + + pton_fd = inet_pton(AF_INET6, addr, dst); + if (pton_fd <= 0) { + if (pton_fd == 0) + ;//ERROR("Not in presentation format"); + else + perror("inet_pton"); + return -2; + } + + _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE_MATCH); + _nl_payload_route(RT_TABLE_MAIN, dst_len, (uint8_t *)buffer, BUFSIZE); + + addAttr(hdr, BUFSIZE, RTA_DST, dst, IPV6_ADDR_LEN); + addAttr(hdr, BUFSIZE, RTA_OIF, (void*)&interface_id, sizeof(uint32_t)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + n = send(fd, buffer, hdr->nlmsg_len, 0); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr * err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; + +} +#endif + +/* + * ip -6 route add local default via GATEWAY_IP table TABLE_ID + */ +int _nl_add_out_route(const char *gateway, uint8_t address_family, + const uint8_t table_id, int default_route) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + int pton_fd; + + if (address_family == AF_INET) { + struct in_addr gw; + + pton_fd = inet_pton(AF_INET, gateway, (struct in_addr *)&gw); + if (pton_fd < 0) { + return -1; + } + + _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, + NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); + _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); + + /* gw */ + addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); + + } else if (address_family == AF_INET6) { + struct in6_addr gw; + + pton_fd = inet_pton(AF_INET6, gateway, (struct in6_addr *)&gw); + if (pton_fd < 0) { + return -1; + } + + _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, + NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); + _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); + + /* gw */ + addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); + if (default_route != -1) { + addAttr(hdr, BUFSIZE, RTA_OIF, &default_route, sizeof(default_route)); + } + + } else { + return -1; + } + + // For more than 255 tables + // addAttr(msg, BUFSIZE, RTA_TABLE, &table_id, sizeof(uint32_t)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + n = send(fd, buffer, hdr->nlmsg_len, 0); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; +} + +/* + * ip -6 route del local default via GATEWAY_IP table TABLE_ID + */ +int _nl_del_out_route(const char *gateway, const uint8_t address_family, + const uint8_t table_id) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + int pton_fd; + + if (address_family == AF_INET) { + struct in_addr gw; + + pton_fd = inet_pton(AF_INET, gateway, (struct in_addr *)&gw); + if (pton_fd < 0) { + return -1; + } + + _nl_header(RTM_DELROUTE, (uint8_t *)buffer, BUFSIZE, + NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); + _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); + + /* gw */ + addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); + + } else if (address_family == AF_INET6) { + struct in6_addr gw; + + pton_fd = inet_pton(AF_INET6, gateway, (struct in6_addr *)&gw); + if (pton_fd < 0) { + return -1; + } + + _nl_header(RTM_DELROUTE, (uint8_t *)buffer, BUFSIZE, + NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); + _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); + + /* gw */ + addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); + + } else { + return -1; + } + + // For more than 255 tables + // addAttr(msg, BUFSIZE, RTA_TABLE, &table_id, sizeof(uint32_t)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + n = send(fd, buffer, hdr->nlmsg_len, 0); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; +} + +/* + * ip route del 1:2::2 dev lo table local + * + */ +int _nl_del_lo_route(const ip_address_t *ip_address) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + struct { + struct nlmsghdr hdr; + struct rtmsg payload; + } msg = { + .hdr.nlmsg_type = RTM_DELROUTE, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .hdr.nlmsg_seq = seq++, + .payload.rtm_family = ip_address->family, + .payload.rtm_dst_len = ip_address->prefix_len, + .payload.rtm_src_len = 0, + .payload.rtm_tos = 0, + .payload.rtm_table = RT_TABLE_LOCAL, + .payload.rtm_protocol = RTPROT_UNSPEC, + .payload.rtm_scope = RT_SCOPE_UNIVERSE, + .payload.rtm_type = RTN_UNSPEC, + .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' + }; + + /* Set attribute = length/type/value */ + uint32_t one = 1; + struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), RTA_DST}; + struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Ip address */ + {&a_dst, sizeof(a_dst)}, + {(void *)&ip_address->buffer, ip_address_len(ip_address)}, + /* Interface id */ + {&a_ifid_lo, sizeof(a_ifid_lo)}, + {&one, sizeof(one)}}; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR; + } + + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR; + } + return 0; + } + + return HICN_SOCKET_ERROR_NONE; +ERR: + return HICN_SOCKET_ERROR_UNSPEC; +} + +/* + * ip -6 rule add iif INTERFACE_NAME lookup TABLE_ID + */ +int _nl_add_rule(const char *interface_name, uint8_t address_family, + const uint8_t table_id) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + _nl_header(RTM_NEWRULE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE); + _nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE); + + /* XXX iif */ + addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name, + strlen(interface_name)); + // attr1 = addNestedAttr(hdr, IFLA_LINKINFO); + // endNestedAttr(hdr, attr1); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + n = send(fd, buffer, hdr->nlmsg_len, 0); + if (n == -1) { + goto ERR_SEND; + } + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; +} + +/* + * ip -6 rule del iif INTERFACE_NAME //lookup TABLE_ID + */ +int _nl_del_rule(const char *interface_name, uint8_t address_family, + const uint8_t table_id) { + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + size_t n; + int fd; + + _nl_header(RTM_DELRULE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE); + _nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE); + + /* XXX iif */ + addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name, + strlen(interface_name)); + + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR_SOCKET; + } + + n = send(fd, buffer, hdr->nlmsg_len, 0); + if (n == -1) { + goto ERR_SEND; + } + + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR_RECV; + } + + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR_NL; + } + return 0; + } + +ERR_NL: +ERR_RECV: +ERR_SEND: +ERR_SOCKET: + return -1; +} + +/* + * ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei + * + */ +int _nl_add_neigh_proxy(const ip_address_t *ip_address, + const uint32_t interface_id) { + /* Buffer for holding the response, with appropriate casting on the header */ + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + + /* Used for send and receive operations on netlink socket */ + int fd; + size_t n; + + /* Packet header */ + struct { + struct nlmsghdr hdr; + struct ndmsg payload; + } msg = { + .hdr.nlmsg_type = RTM_NEWNEIGH, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, + .hdr.nlmsg_seq = seq++, + .payload.ndm_family = ip_address->family, + .payload.ndm_ifindex = interface_id, + .payload.ndm_state = NUD_PERMANENT, + .payload.ndm_flags = NTF_PROXY, + }; + + /* Message attributes = length/type/value */ + struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), NDA_DST}; + + /* Iovec describing the packets */ + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Ip address */ + {&a_dst, sizeof(a_dst)}, + {(void *)&ip_address->buffer, sizeof(ip_address->buffer)}, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + /* Open netlink socket */ + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR; + } + + /* Send packet */ + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + + /* Receive answer */ + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR; + } + + /* Parse answer */ + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR; + } + } + + return HICN_SOCKET_ERROR_NONE; +ERR: + return HICN_SOCKET_ERROR_UNSPEC; +} + +/* 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_address_t *prefix, + const uint32_t interface_id, + const uint8_t table_id) { + /* Buffer for holding the response, with appropriate casting on the header */ + char buffer[BUFSIZE]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + + /* Used for send and receive operations on netlink socket */ + int fd; + size_t n; + + /* Packet header */ + struct { + struct nlmsghdr hdr; + struct rtmsg payload; + } msg = { + .hdr.nlmsg_type = RTM_NEWROUTE, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, + .hdr.nlmsg_seq = seq++, + .payload.rtm_family = prefix->family, + .payload.rtm_dst_len = prefix->prefix_len, // XXX ? XXX dst_len, + .payload.rtm_src_len = 0, + .payload.rtm_tos = 0, + .payload.rtm_table = table_id, /* RT_TABLE_MAIN, etc. */ + .payload.rtm_protocol = RTPROT_BOOT, + .payload.rtm_scope = + prefix->family == AF_INET6 ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, + .payload.rtm_type = RTN_UNICAST, + .payload.rtm_flags = 0, + }; + + /* Message attributes = length/type/value */ + // XXX This could be put directly inside the iovec maybe ? XXX + struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix)), RTA_DST}; + struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; + + /* Iovec describing the packets */ + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Destination prefix / ip address */ + {&a_dst, sizeof(a_dst)}, + {(void *)&prefix->buffer, ip_address_len(prefix)}, + /* Output interface */ + {&a_oif, sizeof(a_oif)}, + {(void *)&interface_id, sizeof(uint32_t)}, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + /* Open netlink socket */ + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR; + } + + /* Send packet */ + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + + /* Receive answer */ + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR; + } + + /* Parse answer */ + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR; + } + } + + return HICN_SOCKET_ERROR_NONE; +ERR: + return HICN_SOCKET_ERROR_UNSPEC; +} + +/* Additional helper functions */ + +int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, + const uint8_t table_id) { + int rc; + ip_address_t ip_address; + + rc = hicn_ip_pton(prefix, &ip_address); + if (rc < 0) { + return rc; + } + + return _nl_add_in_route_table(&ip_address, interface_id, table_id); +} + +int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) { + return _nl_add_in_route_table_s(prefix, interface_id, RT_TABLE_MAIN); +} + +////////* ip -6 rule add from all prio 10 table local */ +/* ip -6 rule add from b001::/16 prio 0 table 100 */ +int _nl_add_prio_rule(const ip_address_t *ip_address, 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]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + + /* Used for send and receive operations on netlink socket */ + int fd; + size_t n; + + /* Packet header */ + struct { + struct nlmsghdr hdr; + struct fib_rule_hdr payload; + } msg = { + .hdr.nlmsg_type = RTM_NEWRULE, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, + .hdr.nlmsg_seq = seq++, + .payload.family = address_family, + //.payload.dst_len = , + .payload.src_len = ip_address ? ip_address->prefix_len : 0, + .payload.tos = 0, + .payload.table = table_id, + .payload.action = FR_ACT_TO_TBL, + .payload.flags = NLM_F_REPLACE, // 0 + }; + + /* Open netlink socket */ + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR; + } + + if (ip_address) { + /* Message attributes = length/type/value */ + struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC}; + struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; + + /* Iovec describing the packets */ + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Source prefix / ip_address */ + {&a_src, sizeof(a_src)}, + {(void *)&ip_address->buffer, ip_address_len(ip_address)}, + /* Priority */ + {&a_prio, sizeof(a_prio)}, + {(void *)&priority, sizeof(uint32_t)}, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + /* Send packet */ + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + } else { + struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; + + /* Iovec describing the packets */ + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Priority */ + {&a_prio, sizeof(a_prio)}, + {(void *)&priority, sizeof(uint32_t)}, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + /* Send packet */ + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + } + + /* Receive answer */ + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR; + } + + /* Parse answer */ + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0) { + errno = -err->error; + goto ERR; + } + } + + return HICN_SOCKET_ERROR_NONE; +ERR: + return HICN_SOCKET_ERROR_UNSPEC; +} + +int _nl_add_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family, + const uint32_t priority) { + return _nl_add_prio_rule(ip_address, address_family, priority, + RT_TABLE_LOCAL); +} + +/* ip -6 rule del from all prio 0 table local */ +int _nl_del_prio_rule(const ip_address_t *ip_address, 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]; + struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; + + /* Used for send and receive operations on netlink socket */ + int fd; + size_t n; + + /* Packet header */ + struct { + struct nlmsghdr hdr; + struct fib_rule_hdr payload; + } msg = { + .hdr.nlmsg_type = RTM_DELRULE, + .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, + .hdr.nlmsg_seq = seq++, + .payload.family = address_family, + //.payload.dst_len = , + .payload.src_len = ip_address ? ip_address->prefix_len : 0, + .payload.tos = 0, + .payload.table = table_id, + .payload.action = FR_ACT_TO_TBL, + .payload.flags = NLM_F_REPLACE, // 0 + }; + + /* Open netlink socket */ + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (fd < 0) { + goto ERR; + } + + /* Message attributes = length/type/value */ + if (ip_address) { + struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC}; + struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; + + /* Iovec describing the packets */ + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Source prefix / ip_address */ + {&a_src, sizeof(a_src)}, + {(void *)&ip_address->buffer, ip_address_len(ip_address)}, + /* Priority */ + {&a_prio, sizeof(a_prio)}, + {(void *)&priority, sizeof(uint32_t)}, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + /* Send packet */ + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + + } else { + struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; + + /* Iovec describing the packets */ + struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Priority */ + {&a_prio, sizeof(a_prio)}, + {(void *)&priority, sizeof(uint32_t)}, + }; + msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); + + /* Send packet */ + n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); + if (n == -1) { + goto ERR; + } + } + + /* Receive answer */ + n = recv(fd, buffer, BUFSIZE, 0); + if (n == -1) { + goto ERR; + } + + /* Parse answer */ + if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); + if (err->error < 0 && + err->error != -2) { //-2 is not such file or directory + errno = -err->error; + goto ERR; + } + } + + return HICN_SOCKET_ERROR_NONE; +ERR: + return HICN_SOCKET_ERROR_UNSPEC; +} + +int _nl_del_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family, + const uint32_t priority) { + return _nl_del_prio_rule(ip_address, address_family, priority, + RT_TABLE_LOCAL); +} + +/******************************************************************************/ + +// #include +// duplicate declarations, in the meantime +#define IF_NAMESIZE 16 + +//#define WITH_TUN_PI 1 + +#ifdef WITH_TUN_PI +#define TUN_FLAGS IFF_TUN +#else +#define TUN_FLAGS IFF_TUN | IFF_NO_PI +#endif + +/* + * Taken from Kernel Documentation/networking/tuntap.txt + */ + +int tun_alloc(char *dev, int flags) { + struct ifreq ifr; + int fd, err; + char *clonedev = "/dev/net/tun"; + + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + + /* open the clone device */ + if ((fd = open(clonedev, O_RDWR)) < 0) { + return fd; + } + + /* preparation of the struct ifr, of type "struct ifreq" */ + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = flags; + + if (*dev) { + /* 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); + } + + /* try to create the device */ + if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * 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); + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} + +int linux_get_tun_name(const char *prefix, const char *identifier, + char *tun_name) { + snprintf(tun_name, IF_NAMESIZE, "%s-%s", prefix, + identifier ? identifier : "main"); + return 0; +} + +int linux_tun_enable_offload(int fd) { + unsigned int offload = 0, tso4 = 1, tso6 = 1, ecn = 1, ufo = 1, csum = 1; + + /* Check if our kernel supports TUNSETOFFLOAD */ + if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) { + goto ERR_TUN; + } + + if (csum) { + offload |= TUN_F_CSUM; + if (tso4) offload |= TUN_F_TSO4; + if (tso6) offload |= TUN_F_TSO6; + if ((tso4 || tso6) && ecn) offload |= TUN_F_TSO_ECN; + if (ufo) offload |= TUN_F_UFO; + } + + if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { + offload &= ~TUN_F_UFO; + if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { + fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", strerror(errno)); + } + } + + return 0; + +ERR_TUN: + return -1; +} + +int linux_tun_create(char *name) { + int fd, rc; + + fd = tun_alloc(name, TUN_FLAGS); + if (fd < 0) { + // ERROR("Error connecting to tun/tap interface %s!", name); + errno = -2; + goto ERR_TUN; + } + + rc = linux_tun_enable_offload(fd); + if (rc < 0) { + // WARN("Could not enable hardware offload on TUN device"); + } else { + // INFO("Enabled hardware offload on TUN device"); + } + + return fd; + +ERR_TUN: + return -1; +} + +/* + * + * interface name can be NULL for all interfaces + */ +int linux_enable_proc(char *path) { + int ret = 0; + int fd; + + fd = open(path, O_WRONLY); + if (fd < 0) { + return -1; + } + + if (write(fd, "1", 1) != 1) { + ret = -2; + } + + close(fd); + return ret; +} + +int linux_enable_v4_forwarding() { + return linux_enable_proc("/proc/sys/net/ipv4/ip_forward"); +} + +int linux_enable_v6_forwarding(char *interface_name) { + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "/proc/sys/net/ipv6/conf/%s/forwarding", + (interface_name) ? interface_name : "all"); + + return linux_enable_proc(path); +} + +int linux_enable_ndp_proxy() { + return linux_enable_proc("/proc/sys/net/ipv6/conf/all/proxy_ndp"); +} + +const hicn_socket_ops_t ops = { + .arch = "linux", + .get_tun_name = linux_get_tun_name, + .tun_create = linux_tun_create, + .enable_v4_forwarding = linux_enable_v4_forwarding, + .enable_v6_forwarding = linux_enable_v6_forwarding, + .enable_ndp_proxy = linux_enable_ndp_proxy, + .get_ifid = _nl_get_ifid, + .get_output_ifid = _nl_get_output_ifid, + .get_ip_addr = _nl_get_ip_addr, + .set_ip_addr = _nl_set_ip_addr, + .up_if = _nl_up_if, + .add_in_route_table = _nl_add_in_route_table, + .add_in_route_table_s = _nl_add_in_route_table_s, + .add_in_route_s = _nl_add_in_route_s, + .add_out_route = _nl_add_out_route, + .del_out_route = _nl_del_out_route, + .del_lo_route = _nl_del_lo_route, + .add_rule = _nl_add_rule, + .del_rule = _nl_del_rule, + .add_neigh_proxy = _nl_add_neigh_proxy, + .add_prio_rule = _nl_add_prio_rule, + .add_lo_prio_rule = _nl_add_lo_prio_rule, + .del_prio_rule = _nl_del_prio_rule, + .del_lo_prio_rule = _nl_del_lo_prio_rule, +}; diff --git a/hicn-light/src/hicn/strategies/CMakeLists.txt b/hicn-light/src/hicn/strategies/CMakeLists.txt new file mode 100644 index 000000000..7f0730b2f --- /dev/null +++ b/hicn-light/src/hicn/strategies/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/strategyImpl.h + ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.h + ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancerWithPD.h + ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.h + ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateWithPD.h + ${CMAKE_CURRENT_SOURCE_DIR}/rnd.h + ${CMAKE_CURRENT_SOURCE_DIR}/rndSegment.h +) + +list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.c + ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancerWithPD.c + ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.c + ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateWithPD.c + ${CMAKE_CURRENT_SOURCE_DIR}/rnd.c + ${CMAKE_CURRENT_SOURCE_DIR}/rndSegment.c +) + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) diff --git a/hicn-light/src/hicn/strategies/loadBalancer.c b/hicn-light/src/hicn/strategies/loadBalancer.c new file mode 100644 index 000000000..cdf4f5165 --- /dev/null +++ b/hicn-light/src/hicn/strategies/loadBalancer.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy, + const NumberSet *egressId, + const Message *objectMessage, + Ticks rtt); +static void _strategyLoadBalancer_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId); +static NumberSet *_strategyLoadBalancer_LookupNexthop( + StrategyImpl *strategy, const Message *interestMessage); +static NumberSet *_strategyLoadBalancer_ReturnNexthops(StrategyImpl *strategy); +static unsigned _strategyLoadBalancer_CountNexthops(StrategyImpl *strategy); +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, + .returnNexthops = &_strategyLoadBalancer_ReturnNexthops, + .countNexthops = &_strategyLoadBalancer_CountNexthops, + .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 { + double weights_sum; + // hash map from connectionId to StrategyNexthopState + PARCHashMap *strategy_state; + NumberSet *nexthops; +}; + +StrategyImpl *strategyLoadBalancer_Create() { + StrategyLoadBalancer *strategy = + parcMemory_AllocateAndClear(sizeof(StrategyLoadBalancer)); + parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(StrategyLoadBalancer)); + + strategy->weights_sum = 0.0; + strategy->strategy_state = parcHashMap_Create(); + strategy->nexthops = numberSet_Create(); + 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; + double w = strategyNexthopState_GetWeight(state); + strategy->weights_sum -= w; + w = strategyNexthopState_UpdateState(state, inc, ALPHA); + strategy->weights_sum += w; +} + +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; +} + +static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy, + const NumberSet *egressId, + const Message *objectMessage, + Ticks rtt) { + _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, const Message *interestMessage) { + StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; + + unsigned in_connection = message_GetIngressConnectionId(interestMessage); + PARCUnsigned *in = parcUnsigned_Create(in_connection); + + unsigned mapSize = (unsigned)parcHashMap_Size(lb->strategy_state); + NumberSet *outList = numberSet_Create(); + + 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); + return outList; +} + +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); +} + +static void _strategyLoadBalancer_resetState(StrategyImpl *strategy) { + StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; + lb->weights_sum = 0.0; + 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); + lb->weights_sum += strategyNexthopState_GetWeight(elem); + } + + parcIterator_Release(&it); +} + +static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyNexthopState *state = strategyNexthopState_Create(); + + PARCUnsigned *cid = parcUnsigned_Create(connectionId); + + StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; + + if (!parcHashMap_Contains(lb->strategy_state, cid)) { + parcHashMap_Put(lb->strategy_state, cid, state); + numberSet_Add(lb->nexthops, connectionId); + _strategyLoadBalancer_resetState(strategy); + } +} + +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)) { + parcHashMap_Remove(lb->strategy_state, cid); + numberSet_Remove(lb->nexthops, connectionId); + _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; + + parcHashMap_Release(&(strategy->strategy_state)); + numberSet_Release(&(strategy->nexthops)); + + parcMemory_Deallocate((void **)&strategy); + parcMemory_Deallocate((void **)&impl); + *strategyPtr = NULL; +} diff --git a/hicn-light/src/hicn/strategies/loadBalancer.h b/hicn-light/src/hicn/strategies/loadBalancer.h new file mode 100644 index 000000000..d0f4faece --- /dev/null +++ b/hicn-light/src/hicn/strategies/loadBalancer.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 less loaded path + */ + +#ifndef loadBalancer_h +#define loadBalancer_h + +#include + +StrategyImpl *strategyLoadBalancer_Create(); +#endif // loadBalancer_h diff --git a/hicn-light/src/hicn/strategies/loadBalancerWithPD.c b/hicn-light/src/hicn/strategies/loadBalancerWithPD.c new file mode 100644 index 000000000..acd466866 --- /dev/null +++ b/hicn-light/src/hicn/strategies/loadBalancerWithPD.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +const unsigned PROBE_FREQUENCY = 1024; + +static void _strategyLoadBalancerWithPD_ReceiveObject( + StrategyImpl *strategy, const NumberSet *egressId, + const Message *objectMessage, Ticks rtt); +static void _strategyLoadBalancerWithPD_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId); +static NumberSet *_strategyLoadBalancerWithPD_LookupNexthop( + StrategyImpl *strategy, const Message *interestMessage); +static NumberSet *_strategyLoadBalancerWithPD_ReturnNexthops( + StrategyImpl *strategy); +static unsigned _strategyLoadBalancerWithPD_CountNexthops( + StrategyImpl *strategy); +static void _strategyLoadBalancerWithPD_AddNexthop(StrategyImpl *strategy, + unsigned connectionId); +static void _strategyLoadBalancerWithPD_RemoveNexthop(StrategyImpl *strategy, + unsigned connectionId); +static void _strategyLoadBalancerWithPD_ImplDestroy(StrategyImpl **strategyPtr); +static strategy_type _strategyLoadBalancerWithPD_GetStrategy( + StrategyImpl *strategy); + +static StrategyImpl _template = { + .context = NULL, + .receiveObject = &_strategyLoadBalancerWithPD_ReceiveObject, + .onTimeout = &_strategyLoadBalancerWithPD_OnTimeout, + .lookupNexthop = &_strategyLoadBalancerWithPD_LookupNexthop, + .returnNexthops = &_strategyLoadBalancerWithPD_ReturnNexthops, + .countNexthops = &_strategyLoadBalancerWithPD_CountNexthops, + .addNexthop = &_strategyLoadBalancerWithPD_AddNexthop, + .removeNexthop = &_strategyLoadBalancerWithPD_RemoveNexthop, + .destroy = &_strategyLoadBalancerWithPD_ImplDestroy, + .getStrategy = &_strategyLoadBalancerWithPD_GetStrategy, +}; + +struct strategy_load_balancer_with_pd; +typedef struct strategy_load_balancer_with_pd StrategyLoadBalancerWithPD; + +struct strategy_load_balancer_with_pd { + double weights_sum; + unsigned min_delay; + // hash map from connectionId to StrategyNexthopState + PARCHashMap *strategy_state; + NumberSet *nexthops; + ConnectionTable *connTable; + bool toInit; + unsigned int fwdPackets; +}; + +StrategyImpl *strategyLoadBalancerWithPD_Create() { + StrategyLoadBalancerWithPD *strategy = + parcMemory_AllocateAndClear(sizeof(StrategyLoadBalancerWithPD)); + parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(StrategyLoadBalancerWithPD)); + + strategy->weights_sum = 0.0; + strategy->min_delay = INT_MAX; + strategy->strategy_state = parcHashMap_Create(); + strategy->nexthops = numberSet_Create(); + 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; + strategy->connTable = NULL; + strategy->fwdPackets = 0; + strategy->toInit = true; + + return impl; +} + +void strategyLoadBalancerWithPD_SetConnectionTable(StrategyImpl *strategy, + ConnectionTable *connTable) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + lb->connTable = connTable; +} + +// ======================================================= +// Dispatch API + +strategy_type _strategyLoadBalancerWithPD_GetStrategy(StrategyImpl *strategy) { + return SET_STRATEGY_LOADBALANCER_WITH_DELAY; +} + +static void _update_Stats(StrategyLoadBalancerWithPD *strategy, + StrategyNexthopStateWithPD *state, bool inc, + Ticks rtt) { + const double ALPHA = 0.9; + double w = strategyNexthopStateWithPD_GetWeight(state); + strategy->weights_sum -= w; + w = strategyNexthopStateWithPD_UpdateState(state, inc, strategy->min_delay, + ALPHA); + strategy->weights_sum += w; +} + +static void _sendProbes(StrategyLoadBalancerWithPD *strategy) { + unsigned size = (unsigned)numberSet_Length(strategy->nexthops); + for (unsigned i = 0; i < size; i++) { + unsigned nhop = numberSet_GetItem(strategy->nexthops, i); + Connection *conn = + (Connection *)connectionTable_FindById(strategy->connTable, nhop); + if (conn != NULL) { + connection_Probe(conn); + unsigned delay = (unsigned)connection_GetDelay(conn); + PARCUnsigned *cid = parcUnsigned_Create(nhop); + StrategyNexthopStateWithPD *elem = + (StrategyNexthopStateWithPD *)parcHashMap_Get( + strategy->strategy_state, cid); + strategyNexthopStateWithPD_SetDelay(elem, delay); + if (delay < strategy->min_delay && delay != 0) { + strategy->min_delay = delay; + } + + parcUnsigned_Release(&cid); + } + } +} + +static unsigned _select_Nexthop(StrategyLoadBalancerWithPD *strategy) { + strategy->fwdPackets++; + if (strategy->toInit || strategy->fwdPackets == PROBE_FREQUENCY) { + strategy->toInit = false; + strategy->fwdPackets = 0; + _sendProbes(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 StrategyNexthopStateWithPD *elem = + parcHashMap_Get(strategy->strategy_state, cid); + + double w = strategyNexthopStateWithPD_GetWeight(elem); + + // printf("next = %u .. pi %u avgpi %f w %f avgrtt + // %f\n",parcUnsigned_GetUnsigned(cid), + // strategyNexthopStateWithPD_GetPI(elem), + // strategyNexthopStateWithPD_GetWeight(elem), + // strategyNexthopStateWithPD_GetWeight(elem), + // strategyNexthopStateWithPD_GetAvgRTT(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; +} + +static void _strategyLoadBalancerWithPD_ReceiveObject( + StrategyImpl *strategy, const NumberSet *egressId, + const Message *objectMessage, Ticks rtt) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + + for (unsigned i = 0; i < numberSet_Length(egressId); i++) { + unsigned outId = numberSet_GetItem(egressId, i); + PARCUnsigned *cid = parcUnsigned_Create(outId); + + const StrategyNexthopStateWithPD *state = + parcHashMap_Get(lb->strategy_state, cid); + if (state != NULL) { + _update_Stats(lb, (StrategyNexthopStateWithPD *)state, false, 0); + } else { + // this may happen if we remove a face/route while downloading a file + // we should ignore this timeout + } + parcUnsigned_Release(&cid); + } +} + +static void _strategyLoadBalancerWithPD_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + + for (unsigned i = 0; i < numberSet_Length(egressId); i++) { + unsigned outId = numberSet_GetItem(egressId, i); + PARCUnsigned *cid = parcUnsigned_Create(outId); + + const StrategyNexthopStateWithPD *state = + parcHashMap_Get(lb->strategy_state, cid); + if (state != NULL) { + _update_Stats(lb, (StrategyNexthopStateWithPD *)state, false, 0); + } else { + // this may happen if we remove a face/route while downloading a file + // we should ignore this timeout + } + parcUnsigned_Release(&cid); + } +} + +// ATTENTION!! This interface force us to create a NumberSet which need to be +// delited somewhere The specification in the interface requires that this +// function never returns NULL. in case we have no output face we need to return +// an empty NumberSet +static NumberSet *_strategyLoadBalancerWithPD_LookupNexthop( + StrategyImpl *strategy, const Message *interestMessage) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + + unsigned in_connection = message_GetIngressConnectionId(interestMessage); + PARCUnsigned *in = parcUnsigned_Create(in_connection); + + unsigned mapSize = (unsigned)parcHashMap_Size(lb->strategy_state); + NumberSet *outList = numberSet_Create(); + + 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 StrategyNexthopStateWithPD *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, (StrategyNexthopStateWithPD *)state, true, 0); + + parcUnsigned_Release(&in); + parcUnsigned_Release(&out); + + numberSet_Add(outList, out_connection); + return outList; +} + +static NumberSet *_strategyLoadBalancerWithPD_ReturnNexthops( + StrategyImpl *strategy) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + return lb->nexthops; +} + +unsigned _strategyLoadBalancerWithPD_CountNexthops(StrategyImpl *strategy) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + return (unsigned)numberSet_Length(lb->nexthops); +} + +static void _strategyLoadBalancerWithPD_resetState(StrategyImpl *strategy) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + lb->weights_sum = 0.0; + lb->min_delay = INT_MAX; + lb->toInit = true; + PARCIterator *it = parcHashMap_CreateKeyIterator(lb->strategy_state); + + while (parcIterator_HasNext(it)) { + PARCUnsigned *cid = parcIterator_Next(it); + StrategyNexthopStateWithPD *elem = + (StrategyNexthopStateWithPD *)parcHashMap_Get(lb->strategy_state, cid); + + strategyNexthopStateWithPD_Reset(elem); + lb->weights_sum += strategyNexthopStateWithPD_GetWeight(elem); + } + + parcIterator_Release(&it); +} + +static void _strategyLoadBalancerWithPD_AddNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyNexthopStateWithPD *state = strategyNexthopStateWithPD_Create(); + + PARCUnsigned *cid = parcUnsigned_Create(connectionId); + + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + + if (!parcHashMap_Contains(lb->strategy_state, cid)) { + parcHashMap_Put(lb->strategy_state, cid, state); + numberSet_Add(lb->nexthops, connectionId); + _strategyLoadBalancerWithPD_resetState(strategy); + } +} + +static void _strategyLoadBalancerWithPD_RemoveNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyLoadBalancerWithPD *lb = + (StrategyLoadBalancerWithPD *)strategy->context; + + PARCUnsigned *cid = parcUnsigned_Create(connectionId); + + if (parcHashMap_Contains(lb->strategy_state, cid)) { + parcHashMap_Remove(lb->strategy_state, cid); + numberSet_Remove(lb->nexthops, connectionId); + _strategyLoadBalancerWithPD_resetState(strategy); + } + + parcUnsigned_Release(&cid); +} + +static void _strategyLoadBalancerWithPD_ImplDestroy( + StrategyImpl **strategyPtr) { + parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*strategyPtr, + "Parameter must dereference to non-null pointer"); + + StrategyImpl *impl = *strategyPtr; + StrategyLoadBalancerWithPD *strategy = + (StrategyLoadBalancerWithPD *)impl->context; + + parcHashMap_Release(&(strategy->strategy_state)); + numberSet_Release(&(strategy->nexthops)); + + parcMemory_Deallocate((void **)&strategy); + parcMemory_Deallocate((void **)&impl); + *strategyPtr = NULL; +} diff --git a/hicn-light/src/hicn/strategies/loadBalancerWithPD.h b/hicn-light/src/hicn/strategies/loadBalancerWithPD.h new file mode 100644 index 000000000..d8a215913 --- /dev/null +++ b/hicn-light/src/hicn/strategies/loadBalancerWithPD.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 less loaded path taking into account the propagation delay of + * the first hop + */ + +#ifndef loadBalancerWithPD_h +#define loadBalancerWithPD_h + +#include +#include + +StrategyImpl *strategyLoadBalancerWithPD_Create(); +void strategyLoadBalancerWithPD_SetConnectionTable(StrategyImpl *strategy, + ConnectionTable *connTable); +#endif // loadBalancerWithPD_h diff --git a/hicn-light/src/hicn/strategies/nexthopState.c b/hicn-light/src/hicn/strategies/nexthopState.c new file mode 100644 index 000000000..13c7dbe7a --- /dev/null +++ b/hicn-light/src/hicn/strategies/nexthopState.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include + +#include +#include + +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)); + if (x->avg_pi == 0.0) { + 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 new file mode 100644 index 000000000..35a9f497b --- /dev/null +++ b/hicn-light/src/hicn/strategies/nexthopState.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include + +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/nexthopStateWithPD.c b/hicn-light/src/hicn/strategies/nexthopStateWithPD.c new file mode 100644 index 000000000..ac23de289 --- /dev/null +++ b/hicn-light/src/hicn/strategies/nexthopStateWithPD.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +struct strategy_nexthop_state_with_pd { + unsigned int pi; + unsigned delay; + double weight; + double avg_pi; +}; + +static bool _strategyNexthopStateWithPD_Destructor( + StrategyNexthopStateWithPD **instancePtr) { + return true; +} + +parcObject_ImplementAcquire(strategyNexthopStateWithPD, + StrategyNexthopStateWithPD); + +parcObject_ImplementRelease(strategyNexthopStateWithPD, + StrategyNexthopStateWithPD); + +parcObject_Override( + StrategyNexthopStateWithPD, PARCObject, + .destructor = (PARCObjectDestructor *) + _strategyNexthopStateWithPD_Destructor, + .copy = (PARCObjectCopy *)strategyNexthopStateWithPD_Copy, + .display = (PARCObjectDisplay *)strategyNexthopStateWithPD_Display, + .toString = (PARCObjectToString *)strategyNexthopStateWithPD_ToString, + .equals = (PARCObjectEquals *)strategyNexthopStateWithPD_Equals, + .compare = (PARCObjectCompare *)strategyNexthopStateWithPD_Compare, + .hashCode = (PARCObjectHashCode *)strategyNexthopStateWithPD_HashCode, + .display = (PARCObjectDisplay *)strategyNexthopStateWithPD_Display); + +void strategyNexthopStateWithPD_AssertValid( + const StrategyNexthopStateWithPD *instance) { + parcAssertTrue(strategyNexthopStateWithPD_IsValid(instance), + "StrategyNexthopStateWithPD is not valid."); +} + +StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Create() { + StrategyNexthopStateWithPD *result = + parcObject_CreateInstance(StrategyNexthopStateWithPD); + if (result != NULL) { + result->pi = 0; + result->avg_pi = 1.0; + result->weight = 1; + result->delay = 0; + } + return result; +} + +void strategyNexthopStateWithPD_Reset(StrategyNexthopStateWithPD *x) { + x->pi = 0; + x->avg_pi = 1.0; + x->weight = 1; + x->delay = 0; +} + +int strategyNexthopStateWithPD_Compare( + const StrategyNexthopStateWithPD *val, + const StrategyNexthopStateWithPD *other) { + if (val == NULL) { + if (other != NULL) { + return -1; + } + } else if (other == NULL) { + return 1; + } else { + strategyNexthopStateWithPD_OptionalAssertValid(val); + strategyNexthopStateWithPD_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; + } + + if (val->delay < other->delay) { + return -1; + } else if (val->delay > other->delay) { + return 1; + } + } + + return 0; +} + +StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Copy( + const StrategyNexthopStateWithPD *original) { + StrategyNexthopStateWithPD *result = strategyNexthopStateWithPD_Create(); + result->pi = original->pi; + result->avg_pi = original->avg_pi; + result->weight = original->weight; + result->delay = original->delay; + + return result; +} + +void strategyNexthopStateWithPD_Display( + const StrategyNexthopStateWithPD *instance, int indentation) { + parcDisplayIndented_PrintLine(indentation, "StrategyNexthopStateWithPD@%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 + 1, "%f", instance->delay); + parcDisplayIndented_PrintLine(indentation, "}"); +} + +bool strategyNexthopStateWithPD_Equals(const StrategyNexthopStateWithPD *x, + const StrategyNexthopStateWithPD *y) { + bool result = false; + + if (x == y) { + result = true; + } else if (x == NULL || y == NULL) { + result = false; + } else { + strategyNexthopStateWithPD_OptionalAssertValid(x); + strategyNexthopStateWithPD_OptionalAssertValid(y); + + if (strategyNexthopStateWithPD_Compare(x, y) == 0) { + result = true; + } + } + + return result; +} + +PARCHashCode strategyNexthopStateWithPD_HashCode( + const StrategyNexthopStateWithPD *x) { + PARCHashCode result = 0; + char str[128]; + sprintf(str, "PI:%d: AVG_PI:%f: W:%f D:%d", x->pi, x->avg_pi, x->weight, + x->delay); + result = parcHashCode_Hash((uint8_t *)&str, strlen(str)); + return result; +} + +bool strategyNexthopStateWithPD_IsValid(const StrategyNexthopStateWithPD *x) { + bool result = false; + + if (x != NULL) { + result = true; + } + + return result; +} + +char *strategyNexthopStateWithPD_ToString(const StrategyNexthopStateWithPD *x) { + // this is not implemented + parcTrapNotImplemented( + "strategyNexthopStateWithPD_ToString is not implemented"); + return NULL; +} + +unsigned strategyNexthopStateWithPD_GetPI(const StrategyNexthopStateWithPD *x) { + strategyNexthopStateWithPD_OptionalAssertValid(x); + + return x->pi; +} + +double strategyNexthopStateWithPD_GetAvgPI( + const StrategyNexthopStateWithPD *x) { + strategyNexthopStateWithPD_OptionalAssertValid(x); + + return x->avg_pi; +} + +double strategyNexthopStateWithPD_GetWeight( + const StrategyNexthopStateWithPD *x) { + strategyNexthopStateWithPD_OptionalAssertValid(x); + + return x->weight; +} + +unsigned strategyNexthopStateWithPD_GetDelay( + const StrategyNexthopStateWithPD *x) { + strategyNexthopStateWithPD_OptionalAssertValid(x); + + return x->delay; +} + +void strategyNexthopStateWithPD_SetDelay(StrategyNexthopStateWithPD *x, + unsigned delay) { + strategyNexthopStateWithPD_OptionalAssertValid(x); + if (delay != 0) { + x->delay = delay; + } +} + +double strategyNexthopStateWithPD_UpdateState(StrategyNexthopStateWithPD *x, + bool inc, unsigned min_delay, + double alpha) { + strategyNexthopStateWithPD_OptionalAssertValid(x); + + if (inc) { + x->pi++; + } else { + if (x->pi > 0) { + x->pi--; + } + } + + x->avg_pi = (x->avg_pi * alpha) + (x->pi * (1 - alpha)); + if (x->avg_pi == 0.0) { + x->avg_pi = 0.1; + } + + double factor = 1.0; + if (min_delay != INT_MAX && x->delay != 0) { + factor = ((double)min_delay / (double)x->delay); + } + + x->weight = 1 / (x->avg_pi * factor); + + return x->weight; +} diff --git a/hicn-light/src/hicn/strategies/nexthopStateWithPD.h b/hicn-light/src/hicn/strategies/nexthopStateWithPD.h new file mode 100644 index 000000000..4d8bd6d15 --- /dev/null +++ b/hicn-light/src/hicn/strategies/nexthopStateWithPD.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 nexthopstatewithpd_h +#define nexthopstatewithpd_h + +#include +#include + +struct strategy_nexthop_state_with_pd; +typedef struct strategy_nexthop_state_with_pd StrategyNexthopStateWithPD; +extern parcObjectDescriptor_Declaration(StrategyNexthopStateWithPD); + +/** + */ +StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Acquire( + const StrategyNexthopStateWithPD *instance); + +#ifdef PARCLibrary_DISABLE_VALIDATION +#define strategyNexthopStateWithPD_OptionalAssertValid(_instance_) +#else +#define strategyNexthopStateWithPD_OptionalAssertValid(_instance_) \ + strategyNexthopStateWithPD_AssertValid(_instance_) +#endif + +/** + */ +void strategyNexthopStateWithPD_AssertValid( + const StrategyNexthopStateWithPD *instance); + +/** + */ +StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Create(); + +void strategyNexthopStateWithPD_Reset(StrategyNexthopStateWithPD *x); +/** + */ +int strategyNexthopStateWithPD_Compare( + const StrategyNexthopStateWithPD *instance, + const StrategyNexthopStateWithPD *other); + +/** + */ +StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Copy( + const StrategyNexthopStateWithPD *original); + +/** + */ +void strategyNexthopStateWithPD_Display( + const StrategyNexthopStateWithPD *instance, int indentation); + +/** + */ +bool strategyNexthopStateWithPD_Equals(const StrategyNexthopStateWithPD *x, + const StrategyNexthopStateWithPD *y); + +/** + */ +PARCHashCode strategyNexthopStateWithPD_HashCode( + const StrategyNexthopStateWithPD *instance); + +/** + */ +bool strategyNexthopStateWithPD_IsValid( + const StrategyNexthopStateWithPD *instance); + +/** + */ +void strategyNexthopStateWithPD_Release( + StrategyNexthopStateWithPD **instancePtr); + +/** + */ +char *strategyNexthopStateWithPD_ToString( + const StrategyNexthopStateWithPD *instance); + +/** + */ +unsigned strategyNexthopStateWithPD_GetPI(const StrategyNexthopStateWithPD *x); + +double strategyNexthopStateWithPD_GetAvgPI(const StrategyNexthopStateWithPD *x); + +double strategyNexthopStateWithPD_GetWeight( + const StrategyNexthopStateWithPD *x); + +unsigned strategyNexthopStateWithPD_GetDelay( + const StrategyNexthopStateWithPD *x); +void strategyNexthopStateWithPD_SetDelay(StrategyNexthopStateWithPD *x, + unsigned delay); + +double strategyNexthopStateWithPD_UpdateState(StrategyNexthopStateWithPD *x, + bool inc, unsigned min_delay, + double alpha); +#endif diff --git a/hicn-light/src/hicn/strategies/rnd.c b/hicn-light/src/hicn/strategies/rnd.c new file mode 100644 index 000000000..e797bb4d9 --- /dev/null +++ b/hicn-light/src/hicn/strategies/rnd.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +static void _strategyRnd_ReceiveObject(StrategyImpl *strategy, + const NumberSet *egressId, + const Message *objectMessage, Ticks rtt); +static void _strategyRnd_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId); +static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy, + const Message *interestMessage); +static NumberSet *_strategyRnd_ReturnNexthops(StrategyImpl *strategy); +static unsigned _strategyRnd_CountNexthops(StrategyImpl *strategy); +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, + .returnNexthops = &_strategyRnd_ReturnNexthops, + .countNexthops = &_strategyRnd_CountNexthops, + .addNexthop = &_strategyRnd_AddNexthop, + .removeNexthop = &_strategyRnd_RemoveNexthop, + .destroy = &_strategyRnd_ImplDestroy, + .getStrategy = &_strategyRnd_GetStrategy, +}; + +struct strategy_rnd; +typedef struct strategy_rnd StrategyRnd; + +struct strategy_rnd { + NumberSet *nexthops; +}; + +StrategyImpl *strategyRnd_Create() { + StrategyRnd *strategy = parcMemory_AllocateAndClear(sizeof(StrategyRnd)); + parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(StrategyRnd)); + + strategy->nexthops = numberSet_Create(); + 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 _strategyRnd_GetStrategy(StrategyImpl *strategy) { + return SET_STRATEGY_RANDOM; +} + +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); +} + +static void _strategyRnd_ReceiveObject(StrategyImpl *strategy, + const NumberSet *egressId, + const Message *objectMessage, + Ticks rtt) {} + +static void _strategyRnd_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId) {} + +static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy, + const Message *interestMessage) { + StrategyRnd *srnd = (StrategyRnd *)strategy->context; + + unsigned in_connection = message_GetIngressConnectionId(interestMessage); + unsigned nexthopSize = (unsigned)numberSet_Length(srnd->nexthops); + + NumberSet *out = numberSet_Create(); + 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; + } + + unsigned out_connection; + do { + out_connection = _select_Nexthop(srnd); + } while (out_connection == in_connection); + + if (out_connection == -1) { + return out; + } + + numberSet_Add(out, out_connection); + return out; +} + +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); +} + +static void _strategyRnd_AddNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyRnd *srnd = (StrategyRnd *)strategy->context; + if (!numberSet_Contains(srnd->nexthops, connectionId)) { + numberSet_Add(srnd->nexthops, connectionId); + } +} + +static void _strategyRnd_RemoveNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyRnd *srnd = (StrategyRnd *)strategy->context; + + if (numberSet_Contains(srnd->nexthops, connectionId)) { + numberSet_Remove(srnd->nexthops, connectionId); + } +} + +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; + StrategyRnd *strategy = (StrategyRnd *)impl->context; + + numberSet_Release(&(strategy->nexthops)); + + parcMemory_Deallocate((void **)&strategy); + parcMemory_Deallocate((void **)&impl); + *strategyPtr = NULL; +} diff --git a/hicn-light/src/hicn/strategies/rnd.h b/hicn-light/src/hicn/strategies/rnd.h new file mode 100644 index 000000000..b57b41ccf --- /dev/null +++ b/hicn-light/src/hicn/strategies/rnd.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 randomly + */ + +#ifndef rnd_h +#define rnd_h + +#include + +StrategyImpl* strategyRnd_Create(); +#endif // rnd_h diff --git a/hicn-light/src/hicn/strategies/rndSegment.c b/hicn-light/src/hicn/strategies/rndSegment.c new file mode 100644 index 000000000..ca1cffefc --- /dev/null +++ b/hicn-light/src/hicn/strategies/rndSegment.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +static void _strategyRndSegment_ReceiveObject(StrategyImpl *strategy, + const NumberSet *egressId, + const Message *objectMessage, + Ticks rtt); +static void _strategyRndSegment_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId); +static NumberSet *_strategyRndSegment_LookupNexthop( + StrategyImpl *strategy, const Message *interestMessage); +static NumberSet *_strategyRndSegment_ReturnNexthops(StrategyImpl *strategy); +static unsigned _strategyRndSegment_CountNexthops(StrategyImpl *strategy); +static void _strategyRndSegment_AddNexthop(StrategyImpl *strategy, + unsigned connectionId); +static void _strategyRndSegment_RemoveNexthop(StrategyImpl *strategy, + unsigned connectionId); +static void _strategyRndSegment_ImplDestroy(StrategyImpl **strategyPtr); +static strategy_type _strategyRndSegment_GetStrategy(StrategyImpl *strategy); + +static StrategyImpl _template = { + .context = NULL, + .receiveObject = &_strategyRndSegment_ReceiveObject, + .onTimeout = &_strategyRndSegment_OnTimeout, + .lookupNexthop = &_strategyRndSegment_LookupNexthop, + .returnNexthops = &_strategyRndSegment_ReturnNexthops, + .countNexthops = &_strategyRndSegment_CountNexthops, + .addNexthop = &_strategyRndSegment_AddNexthop, + .removeNexthop = &_strategyRndSegment_RemoveNexthop, + .destroy = &_strategyRndSegment_ImplDestroy, + .getStrategy = &_strategyRndSegment_GetStrategy, +}; + +struct strategy_rnd_segment; +typedef struct strategy_rnd_segment StrategyRndSegment; + +struct strategy_rnd_segment { + NumberSet *nexthops; + NameBitvector *segmentName; + int last_used_face; +}; + +StrategyImpl *strategyRndSegment_Create() { + StrategyRndSegment *strategy = + parcMemory_AllocateAndClear(sizeof(StrategyRndSegment)); + parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(StrategyRndSegment)); + + strategy->nexthops = numberSet_Create(); + strategy->segmentName = NULL; + strategy->last_used_face = 0; + 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 _strategyRndSegment_GetStrategy(StrategyImpl *strategy) { + return SET_STRATEGY_RANDOM_PER_DASH_SEGMENT; +} + +static int _select_Nexthop(StrategyRndSegment *strategy) { + unsigned len = (unsigned)numberSet_Length(strategy->nexthops); + if (len == 0) { + return -1; + } + + int rnd = (rand() % len); + return numberSet_GetItem(strategy->nexthops, rnd); +} + +static void _strategyRndSegment_ReceiveObject(StrategyImpl *strategy, + const NumberSet *egressId, + const Message *objectMessage, + Ticks rtt) {} + +static void _strategyRndSegment_OnTimeout(StrategyImpl *strategy, + const NumberSet *egressId) {} + +static NumberSet *_strategyRndSegment_LookupNexthop( + StrategyImpl *strategy, const Message *interestMessage) { + StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; + + unsigned in_connection = message_GetIngressConnectionId(interestMessage); + unsigned nexthopSize = (unsigned)numberSet_Length(srnd->nexthops); + + NumberSet *out = numberSet_Create(); + 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; + } + + NameBitvector *interestName = + name_GetContentName(message_GetName(interestMessage)); + + if (srnd->segmentName == NULL) { + srnd->segmentName = nameBitvector_Copy(interestName); + } else if (!nameBitvector_Equals(srnd->segmentName, interestName)) { + nameBitvector_Destroy(&srnd->segmentName); + srnd->segmentName = nameBitvector_Copy(interestName); + } else { + // here we need to check if the output face still exists or if someone erase + // it + if (numberSet_Contains(srnd->nexthops, srnd->last_used_face)) { + // face exists, so keep using it! + numberSet_Add(out, srnd->last_used_face); + return out; + } else { + // the face does not exists anymore, try to find a new face but keep the + // name of the dash segment + } + } + + int out_connection; + do { + out_connection = _select_Nexthop(srnd); + } while (out_connection == in_connection); + + if (out_connection == -1) { + return out; + } + + srnd->last_used_face = out_connection; + numberSet_Add(out, out_connection); + return out; +} + +static NumberSet *_strategyRndSegment_ReturnNexthops(StrategyImpl *strategy) { + StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; + return srnd->nexthops; +} + +unsigned _strategyRndSegment_CountNexthops(StrategyImpl *strategy) { + StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; + return (unsigned)numberSet_Length(srnd->nexthops); +} + +static void _strategyRndSegment_AddNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; + if (!numberSet_Contains(srnd->nexthops, connectionId)) { + numberSet_Add(srnd->nexthops, connectionId); + } +} + +static void _strategyRndSegment_RemoveNexthop(StrategyImpl *strategy, + unsigned connectionId) { + StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; + + if (numberSet_Contains(srnd->nexthops, connectionId)) { + numberSet_Remove(srnd->nexthops, connectionId); + } +} + +static void _strategyRndSegment_ImplDestroy(StrategyImpl **strategyPtr) { + parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*strategyPtr, + "Parameter must dereference to non-null pointer"); + + StrategyImpl *impl = *strategyPtr; + StrategyRndSegment *strategy = (StrategyRndSegment *)impl->context; + + numberSet_Release(&(strategy->nexthops)); + if (strategy->segmentName != NULL) { + nameBitvector_Destroy(&strategy->segmentName); + } + + parcMemory_Deallocate((void **)&strategy); + parcMemory_Deallocate((void **)&impl); + *strategyPtr = NULL; +} diff --git a/hicn-light/src/hicn/strategies/rndSegment.h b/hicn-light/src/hicn/strategies/rndSegment.h new file mode 100644 index 000000000..897ccca47 --- /dev/null +++ b/hicn-light/src/hicn/strategies/rndSegment.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 randomly, selects a path every time the client ask for a new dash + * segment + */ + +#ifndef rnd_Segment_h +#define rnd_Segment_h + +#include + +StrategyImpl* strategyRndSegment_Create(); +#endif // rnd_Segment_h diff --git a/hicn-light/src/hicn/strategies/strategyImpl.h b/hicn-light/src/hicn/strategies/strategyImpl.h new file mode 100644 index 000000000..2634665eb --- /dev/null +++ b/hicn-light/src/hicn/strategies/strategyImpl.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include + +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 rtt); + void (*onTimeout)(StrategyImpl *strategy, const NumberSet *egressId); + NumberSet *(*lookupNexthop)(StrategyImpl *strategy, + const Message *interestMessage); + NumberSet *(*returnNexthops)(StrategyImpl *strategy); + unsigned (*countNexthops)(StrategyImpl *strategy); + 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/utils/CMakeLists.txt b/hicn-light/src/hicn/utils/CMakeLists.txt new file mode 100644 index 000000000..120061211 --- /dev/null +++ b/hicn-light/src/hicn/utils/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +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}/punting.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}/punting.c + ${CMAKE_CURRENT_SOURCE_DIR}/utils.c +) + +set(TO_INSTALL_HEADER_FILES + ${TO_INSTALL_HEADER_FILES} + ${CMAKE_CURRENT_SOURCE_DIR}/commands.h + PARENT_SCOPE +) + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/hicn/utils/address.c b/hicn-light/src/hicn/utils/address.c new file mode 100644 index 000000000..fe222a43c --- /dev/null +++ b/hicn-light/src/hicn/utils/address.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#endif +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +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 new file mode 100644 index 000000000..6ca98347a --- /dev/null +++ b/hicn-light/src/hicn/utils/address.h @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#endif +#include + +#include +#include +#include + +/** + * 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(©); + * } + * @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(©); + * } + * @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 new file mode 100644 index 000000000..434ceb7ca --- /dev/null +++ b/hicn-light/src/hicn/utils/addressList.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include + +#include +#include +#include + +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 new file mode 100644 index 000000000..823b0c8cb --- /dev/null +++ b/hicn-light/src/hicn/utils/addressList.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +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 new file mode 100644 index 000000000..9527e5064 --- /dev/null +++ b/hicn-light/src/hicn/utils/commands.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 +#include +#endif + +#include +#include + +typedef struct in6_addr ipv6_addr_t; +typedef uint32_t ipv4_addr_t; + +union commandAddr { + ipv4_addr_t ipv4; + ipv6_addr_t ipv6; +}; + +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_ROUTE, + CACHE_STORE, + CACHE_SERVE, + CACHE_CLEAR, + SET_STRATEGY, + SET_WLDR, + ADD_PUNTING, + LIST_LISTENERS, + MAPME_ENABLE, + MAPME_DISCOVERY, + MAPME_TIMESCALE, + MAPME_RETX, + 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[16]; + // char interfaceName[16]; + union commandAddr address; + uint16_t port; + // uint16_t etherType; + uint8_t addressType; + uint8_t listenerMode; + uint8_t connectionType; +} add_listener_command; + +// SIZE=40 + +//========== [01] ADD CONNECTION ========== + +typedef struct { + char symbolic[16]; + union commandAddr remoteIp; + union commandAddr localIp; + uint16_t remotePort; + uint16_t localPort; + uint8_t ipType; + uint8_t connectionType; +} 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; +} list_connections_command; + +// SIZE=64 + +//========== [03] ADD ROUTE ========== + +typedef struct { + char symbolicOrConnid[16]; + union commandAddr address; + uint16_t cost; + uint8_t addressType; + uint8_t len; +} add_route_command; + +// SIZE=36 + +//========== [04] LIST ROUTE ========== + +typedef struct { + union commandAddr 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[16]; +} remove_connection_command; + +// SIZE=16 + +//========== [06] REMOVE ROUTE ========== + +typedef struct { + char symbolicOrConnid[16]; + union commandAddr address; + uint8_t addressType; + uint8_t len; +} remove_route_command; + +// SIZE=36 + +//========== [07] CACHE STORE ========== + +typedef struct { + uint8_t activate; +} cache_store_command; + +// SIZE=1 + +//========== [08] CACHE SERVE ========== + +typedef struct { + uint8_t activate; +} cache_serve_command; + +// SIZE=1 + +//========== [09] SET STRATEGY ========== + +typedef enum { + SET_STRATEGY_LOADBALANCER, + SET_STRATEGY_RANDOM, + SET_STRATEGY_RANDOM_PER_DASH_SEGMENT, + SET_STRATEGY_LOADBALANCER_WITH_DELAY, + SET_STRATEGY_LOADBALANCER_BY_RATE, + SET_STRATEGY_LOADBALANCER_BEST_ROUTE, + LAST_STRATEGY_VALUE +} strategy_type; + +typedef struct { + union commandAddr address; + uint8_t strategyType; + uint8_t addressType; + uint8_t len; +} set_strategy_command; + +// SIZE=20 + +//========== [11] SET WLDR ========== + +typedef struct { + char symbolicOrConnid[16]; + uint8_t activate; +} set_wldr_command; + +// SIZE=17 + +//========== [12] ADD PUNTING ========== + +typedef struct { + char symbolicOrConnid[16]; + union commandAddr address; + uint8_t addressType; + uint8_t len; +} add_punting_command; + +// SIZE=36 + +//========== [13] LIST LISTENER ========== + +typedef struct { + union commandAddr address; + uint32_t connid; + uint16_t port; + uint8_t addressType; + uint8_t encapType; +} list_listeners_command; + +// SIZE=24 + +//========== [14] MAPME ========== + +// (enable/discovery/timescale/retx) + +typedef struct { + uint8_t activate; +} mapme_activator_command; + +// SIZE=1 + +typedef struct { + uint32_t timePeriod; +} mapme_timing_command; + +// SIZE=1 + +//===== 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_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 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 new file mode 100644 index 000000000..dce9ed8f3 --- /dev/null +++ b/hicn-light/src/hicn/utils/interface.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct interface { + char *name; + unsigned interfaceIndex; + bool loopback; + bool supportMulticast; + unsigned mtu; + + AddressList *addressList; +}; + +char *interfaceToString(const Interface *interface) { + PARCBufferComposer *composer = parcBufferComposer_Create(); + + parcBufferComposer_Format( + composer, "%3u %10s %1s%1s %8u ", interface->interfaceIndex, + interface->name, interface->loopback ? "l" : " ", + interface->supportMulticast ? "m" : " ", interface->mtu); + + for (size_t i = 0; i < addressListLength(interface->addressList); i++) { + addressBuildString(addressListGetItem(interface->addressList, i), composer); + if (i < (addressListLength(interface->addressList) - 1)) { + parcBufferComposer_PutStrings(composer, "\n", NULL); + } + } + + PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); + char *result = parcBuffer_ToString(tempBuffer); + parcBuffer_Release(&tempBuffer); + parcBufferComposer_Release(&composer); + return result; +} + +Interface *interfaceCreate(const char *name, unsigned interfaceIndex, + bool loopback, bool supportMulticast, unsigned mtu) { + Interface *iface = parcMemory_AllocateAndClear(sizeof(Interface)); + + parcAssertNotNull(iface, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(Interface)); + iface->name = parcMemory_StringDuplicate(name, 64); + iface->interfaceIndex = interfaceIndex; + iface->loopback = loopback; + iface->supportMulticast = supportMulticast; + iface->mtu = mtu; + iface->addressList = addressListCreate(); + + return iface; +} + +void interfaceDestroy(Interface **interfacePtr) { + parcAssertNotNull(interfacePtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*interfacePtr, + "Parameter must dereference to non-null pointer"); + + Interface *iface = *interfacePtr; + parcMemory_Deallocate((void **)&iface->name); + addressListDestroy(&iface->addressList); + parcMemory_Deallocate((void **)&iface); + interfacePtr = NULL; +} + +void interfaceAddAddress(Interface *iface, Address *address) { + parcAssertNotNull(iface, "Parameter iface must be non-null"); + + size_t length = addressListLength(iface->addressList); + for (size_t i = 0; i < length; i++) { + const Address *a = addressListGetItem(iface->addressList, i); + if (addressEquals(a, address)) { + return; + } + } + + addressListAppend(iface->addressList, address); +} + +const AddressList *interfaceGetAddresses(const Interface *iface) { + parcAssertNotNull(iface, "Parameter iface must be non-null"); + return iface->addressList; +} + +unsigned interfaceGetInterfaceIndex(const Interface *iface) { + parcAssertNotNull(iface, "Parameter iface must be non-null"); + return iface->interfaceIndex; +} + +bool interfaceNameEquals(const Interface *iface, const char *name) { + parcAssertNotNull(iface, "Parameter iface must be non-null"); + + if (strcasecmp(iface->name, name) == 0) { + return true; + } + return false; +} + +bool interfaceEquals(const Interface *a, const Interface *b) { + if (a == NULL && b == NULL) { + return true; + } + + if (a == NULL || b == NULL) { + return false; + } + + if (a->interfaceIndex == b->interfaceIndex) { + if (a->loopback == b->loopback) { + if (a->supportMulticast == b->supportMulticast) { + if (a->mtu == b->mtu) { + if (strcasecmp(a->name, b->name) == 0) { + if (addressListEquals(a->addressList, b->addressList)) { + return true; + } + } + } + } + } + } + return false; +} + +// static const char light_Iface[] = "Interface"; +// static const char light_IfName[] = "Name"; +// static const char light_IFIDX[] = "Index"; +// static const char light_IsLoopback[] = "Loopback"; +// static const char light_Multicast[] = "Multicast"; +// static const char light_MTU[] = "MTU"; + +// static const char light_True[] = "true"; +// static const char light_False[] = "false"; +// static const char light_Addrs[] = "Addrs"; + +const char *interfaceGetName(const Interface *iface) { + parcAssertNotNull(iface, "Parameter iface must be non-null"); + return iface->name; +} + +unsigned interfaceGetMTU(const Interface *iface) { + parcAssertNotNull(iface, "Parameter iface must be non-null"); + return iface->mtu; +} diff --git a/hicn-light/src/hicn/utils/interface.h b/hicn-light/src/hicn/utils/interface.h new file mode 100644 index 000000000..fd91edb1d --- /dev/null +++ b/hicn-light/src/hicn/utils/interface.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 <#Brief Description#> + * + * <#Detailed Description#> + * + */ +#ifndef interface_h +#define interface_h + +#include +#include + +struct interface; +typedef struct interface Interface; + +/** + * Creates a representation of an interface + * + * The name is copied. Creates a representation of a system interface. + * + * @param <#param1#> + * @return An allocated object, you must call interfaceDestroy() + * + * Example: + * @code + * <#example#> + * @endcode + */ +Interface *interfaceCreate(const char *name, unsigned interfaceIndex, + bool loopback, bool supportMulticast, unsigned mtu); + +void interfaceDestroy(Interface **interfacePtr); + +/** + * Adds an address to an interface + * + * Does not allow duplicates, if already exists is not added again + * + * @param <#param1#> + * @return <#return#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +void interfaceAddAddress(Interface *iface, Address *address); + +/** + * Retrieves a list of interface addresses + * + * <#Discussion#> + * + * @param <#param1#> + * @return Will not be NULL, but may be empty + * + * Example: + * @code + * <#example#> + * @endcode + */ +const AddressList *interfaceGetAddresses(const Interface *iface); + +/** + * The interface index + * + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +unsigned interfaceGetInterfaceIndex(const Interface *iface); + +/** + * Returns the interface name, e.g. "eth0" + * + * <#Paragraphs Of Explanation#> + * + * @param [in] iface An allocated Interface + * + * @return non-null The interface Name as a C-string + * @return null An error + * + * Example: + * @code + * <#example#> + * @endcode + */ +const char *interfaceGetName(const Interface *iface); + +/** + * Returns the Maximum Transmission Unit (MTU) of the interface + * + * <#Paragraphs Of Explanation#> + * + * @param [in] iface An allocated Interface + * + * @return number The MTU as reported by the kernel + * + * Example: + * @code + * { + * <#example#> + * } + * @endcode + */ +unsigned interfaceGetMTU(const Interface *iface); + +/** + * Determine if two InterfaceName instances are equal. + * + * + * The following equivalence relations on non-null `InterfaceName` instances are + * maintained: + * + * * It is reflexive: for any non-null reference value x, + * `InterfaceName_Equals(x, x)` must return true. + * + * * It is symmetric: for any non-null reference values x and y, + * `InterfaceName_Equals(x, y)` must return true if and only if + * `InterfaceName_Equals(y, x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `InterfaceName_Equals(x, y)` returns true and + * `InterfaceName_Equals(y, z)` returns true, + * then `InterfaceName_Equals(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple + * invocations of `InterfaceName_Equals(x, y)` consistently return true or + * consistently return false. + * + * * For any non-null reference value x, `InterfaceName_Equals(x, NULL)` must + * return false. + * + * @param a A pointer to a `InterfaceName` instance. + * @param b A pointer to a `InterfaceName` instance. + * @return true if the two `InterfaceName` instances are equal. + * + * Example: + * @code + * { + * InterfaceName *a = InterfaceName_Create(); + * InterfaceName *b = InterfaceName_Create(); + * + * if (InterfaceName_Equals(a, b)) { + * // true + * } else { + * // false + * } + * } + * @endcode + */ +bool interfaceNameEquals(const Interface *iface, const char *name); + +/** + * Two Interfaces are idential + * + * All properties must be the same. The order of addresses matters, and + * they must have been added to the address list in the same order. + * + * The interface name match is case in-sensitive. + * + * @param <#param1#> + * @return <#return#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool interfaceEquals(const Interface *a, const Interface *b); + +/** + * <#OneLineDescription#> + * + * <#Discussion#> + * + * @param interface A Interface structure pointer. + * @return An allocate string representation of the Interface that must be freed + * via parcMemory_Deallocate(). + * + * Example: + * @code + * <#example#> + * @endcode + */ +char *interfaceToString(const Interface *interface); +#endif // interface_h diff --git a/hicn-light/src/hicn/utils/interfaceSet.c b/hicn-light/src/hicn/utils/interfaceSet.c new file mode 100644 index 000000000..35c97812b --- /dev/null +++ b/hicn-light/src/hicn/utils/interfaceSet.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include +#include + +#include + +struct interfaceSet { + PARCArrayList *listOfInterfaces; +}; + +static void _destroyInterface(void **ifaceVoidPtr) { + interfaceDestroy((Interface **)ifaceVoidPtr); +} + +InterfaceSet *interfaceSetCreate(void) { + InterfaceSet *set = parcMemory_AllocateAndClear(sizeof(InterfaceSet)); + parcAssertNotNull(set, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(InterfaceSet)); + set->listOfInterfaces = parcArrayList_Create(_destroyInterface); + return set; +} + +void interfaceSetDestroy(InterfaceSet **setPtr) { + parcAssertNotNull(setPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*setPtr, "Parameter must dereference to non-null pointer"); + + InterfaceSet *set = *setPtr; + parcArrayList_Destroy(&set->listOfInterfaces); + parcMemory_Deallocate((void **)&set); + *setPtr = NULL; +} + +bool interfaceSetAdd(InterfaceSet *set, Interface *iface) { + parcAssertNotNull(set, "Parameter set must be non-null"); + parcAssertNotNull(iface, "Parameter iface must be non-null"); + + unsigned ifaceIndex = interfaceGetInterfaceIndex(iface); + size_t length = parcArrayList_Size(set->listOfInterfaces); + for (size_t i = 0; i < length; i++) { + Interface *listEntry = + (Interface *)parcArrayList_Get(set->listOfInterfaces, i); + unsigned entryInterfaceIndex = interfaceGetInterfaceIndex(listEntry); + if (entryInterfaceIndex == ifaceIndex) { + return false; + } + } + + parcArrayList_Add(set->listOfInterfaces, (PARCObject *)iface); + return true; +} + +size_t interfaceSetLength(const InterfaceSet *set) { + parcAssertNotNull(set, "Parameter set must be non-null"); + return parcArrayList_Size(set->listOfInterfaces); +} + +Interface *interfaceSetGetByOrdinalIndex(InterfaceSet *set, + size_t ordinalIndex) { + parcAssertNotNull(set, "Parameter set must be non-null"); + return (Interface *)parcArrayList_Get(set->listOfInterfaces, ordinalIndex); +} + +Interface *interfaceSetGetByInterfaceIndex(const InterfaceSet *set, + unsigned interfaceIndex) { + size_t length = parcArrayList_Size(set->listOfInterfaces); + for (size_t i = 0; i < length; i++) { + Interface *listEntry = + (Interface *)parcArrayList_Get(set->listOfInterfaces, i); + unsigned entryInterfaceIndex = interfaceGetInterfaceIndex(listEntry); + if (entryInterfaceIndex == interfaceIndex) { + return listEntry; + } + } + return NULL; +} + +/** + * Uses the system name (e.g. "en0") + * + * <#Discussion#> + * + * @param <#param1#> + * @return NULL if not found + * + * Example: + * @code + * <#example#> + * @endcode + */ +Interface *interfaceSetGetByName(InterfaceSet *set, const char *name) { + size_t length = parcArrayList_Size(set->listOfInterfaces); + for (size_t i = 0; i < length; i++) { + Interface *listEntry = + (Interface *)parcArrayList_Get(set->listOfInterfaces, i); + if (interfaceNameEquals(listEntry, name)) { + return listEntry; + } + } + return NULL; +} + +bool interfaceSetEquals(const InterfaceSet *a, const InterfaceSet *b) { + if (a == NULL && b == NULL) { + return true; + } + + if (a == NULL || b == NULL) { + return false; + } + + size_t length_a = parcArrayList_Size(a->listOfInterfaces); + size_t length_b = parcArrayList_Size(b->listOfInterfaces); + + if (length_a == length_b) { + for (size_t i = 0; i < length_a; i++) { + Interface *iface_a = + (Interface *)parcArrayList_Get(a->listOfInterfaces, i); + + // the set is unique by interface id, so if it exists in set b, it + // exists there by interface id + Interface *iface_b = interfaceSetGetByInterfaceIndex( + b, interfaceGetInterfaceIndex(iface_a)); + if (!interfaceEquals(iface_b, iface_b)) { + return false; + } + } + return true; + } + return false; +} diff --git a/hicn-light/src/hicn/utils/interfaceSet.h b/hicn-light/src/hicn/utils/interfaceSet.h new file mode 100644 index 000000000..e43f985fe --- /dev/null +++ b/hicn-light/src/hicn/utils/interfaceSet.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 <#Brief Description#> + * + * <#Detailed Description#> + * + */ +#ifndef InterfaceSet_h +#define InterfaceSet_h + +#include + +struct interfaceSet; +/** + * + * @see interfaceSetCreate + */ +typedef struct interfaceSet InterfaceSet; + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +InterfaceSet *interfaceSetCreate(void); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +void interfaceSetDestroy(InterfaceSet **setPtr); + +/** + * Adds interface to set, does not allow duplicates + * + * Takes ownership of the iface memory if added + * + * Duplicates are two entries with the same interface index + * + * @param <#param1#> + * @return true if added, false if not (likely a duplicate) + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool interfaceSetAdd(InterfaceSet *set, Interface *iface); + +/** + * The number of interfaces in the set + * + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +size_t interfaceSetLength(const InterfaceSet *set); + +/** + * Uses the ordinal index of the interface in the Set + * + * Ranges from 0 .. interfaceSetLength()-1. + * + * @param <#param1#> + * @return NULL if not found + * + * Example: + * @code + * <#example#> + * @endcode + */ +Interface *interfaceSetGetByOrdinalIndex(InterfaceSet *set, + size_t ordinalIndex); + +/** + * Retreives by the assigned interface index + * + * <#Discussion#> + * + * @param <#param1#> + * @return NULL if not found + * + * Example: + * @code + * <#example#> + * @endcode + */ +Interface *interfaceSetGetByInterfaceIndex(const InterfaceSet *set, + unsigned interfaceIndex); + +/** + * Uses the system name (e.g. "en0") + * + * <#Discussion#> + * + * @param <#param1#> + * @return NULL if not found + * + * Example: + * @code + * <#example#> + * @endcode + */ +Interface *interfaceSetGetByName(InterfaceSet *set, const char *name); + +/** + * Determine if two InterfaceSet instances are equal. + * + * Two InterfaceSet instances are equal if, and only if, the sets contain the + * same elements + * - order independent. + * Each element is compared via interfaceEquals() + * + * The following equivalence relations on non-null `InterfaceSet` instances are + * maintained: + * + * * It is reflexive: for any non-null reference value x, + * `InterfaceSet_Equals(x, x)` must return true. + * + * * It is symmetric: for any non-null reference values x and y, + * `InterfaceSet_Equals(x, y)` must return true if and only if + * `interfaceSetEquals(y, x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `interfaceSetEquals(x, y)` returns true and + * `interfaceSetEquals(y, z)` returns true, + * then `interfaceSetEquals(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple + * invocations of `interfaceSetEquals(x, y)` consistently return true or + * consistently return false. + * + * * For any non-null reference value x, `interfaceSetEquals(x, NULL)` must + * return false. + * + * @param a A pointer to a `InterfaceSet` instance. + * @param b A pointer to a `InterfaceSet` instance. + * @return true if the two `InterfaceSet` instances are equal. + * + * Example: + * @code + * { + * InterfaceSet *a = interfaceSetCreate(); + * InterfaceSet *b = interfaceSetCreate(); + * + * if (interfaceSetEquals(a, b)) { + * // true + * } else { + * // false + * } + * } + * @endcode + */ +bool interfaceSetEquals(const InterfaceSet *a, const InterfaceSet *b); +#endif // InterfaceSet_h diff --git a/hicn-light/src/hicn/utils/punting.c b/hicn-light/src/hicn/utils/punting.c new file mode 100644 index 000000000..06466172c --- /dev/null +++ b/hicn-light/src/hicn/utils/punting.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include +#include + +struct punting { + char *symbolic; + Address *prefix; + uint32_t len; +}; + +Punting *puntingCreate(const char *listenerName, Address *prefix, + uint32_t len) { + parcAssertNotNull(listenerName, "Parameter listenerName must be non-null"); + parcAssertNotNull(prefix, "Parameter prefix must be non-null"); + + Punting *punting = parcMemory_AllocateAndClear(sizeof(Punting)); + if (punting) { + punting->symbolic = + parcMemory_StringDuplicate(listenerName, strlen(listenerName)); + punting->prefix = addressCopy(prefix); + punting->len = len; + } + + return punting; +} + +void puntingRelease(Punting **puntingPtr) { + parcAssertNotNull(puntingPtr, + "Parameter puntingPtr must be non-null double pointer"); + parcAssertNotNull(*puntingPtr, + "Parameter puntingPtr dereference to non-null pointer"); + + Punting *punting = *puntingPtr; + + if (punting->symbolic) { + parcMemory_Deallocate((void **)&punting->symbolic); + } + + if (punting->prefix) { + addressDestroy(&punting->prefix); + } + + parcMemory_Deallocate((void **)&punting); + *puntingPtr = NULL; +} + +bool puntingEquals(const Punting *a, const Punting *b) { + if ((a == NULL && b == NULL) || a == b) { + // both null or identically equal + return true; + } + + if (a == NULL || b == NULL) { + // only one is null + return false; + } + + if ((strcmp(a->symbolic, b->symbolic) == 0) && + (addressEquals(a->prefix, b->prefix)) && (a->len == b->len)) { + return true; + } + + return false; +} + +const char *puntingGetSymbolicName(const Punting *punting) { + parcAssertNotNull(punting, "Parameter listener must be non-null"); + return punting->symbolic; +} + +Address *puntingGetAddress(const Punting *punting) { + parcAssertNotNull(punting, "Parameter listener must be non-null"); + return punting->prefix; +} + +uint32_t puntingPrefixLen(const Punting *punting) { + parcAssertNotNull(punting, "Parameter listener must be non-null"); + return punting->len; +} diff --git a/hicn-light/src/hicn/utils/punting.h b/hicn-light/src/hicn/utils/punting.h new file mode 100644 index 000000000..9be1baed4 --- /dev/null +++ b/hicn-light/src/hicn/utils/punting.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 punting_h +#define punting_h + +struct punting; +typedef struct punting Punting; + +#include + +/** + * Creates a Punting object + * + * The symbolic name represents this listener and may be used by other commands. + * It must be unique, otherwise the command will fail when sent to the + * forwarder. + * + * @param [in] symbolic name of the listener + * @param [in] prefix address to add to the punting rule + * @param [in] len prefix length + * + * @return non-null An Allocated object + * @return null An error + * + */ +Punting *puntingCreate(const char *symbolic, Address *prefix, uint32_t len); + +/** + * Releases a reference count to the object + * + * <#Paragraphs Of Explanation#> + * + * @param [in,out] etherConnPtr A pointer to an etherConn object, will be + * null'd. + * + */ +void puntingRelease(Punting **puntingPtr); + +/** + * Determine if two light Punting are equal. + * + */ + +bool puntingEquals(const Punting *a, const Punting *b); + +/** + * Returns the symbolic name + * + */ +const char *puntingGetSymbolicName(const Punting *punting); + +/** + * Returns the address (INET or INET6 ip address) + * + */ +Address *puntingGetAddress(const Punting *punting); + +uint32_t puntingPrefixLen(const Punting *punting); +#endif // punting_h diff --git a/hicn-light/src/hicn/utils/utils.c b/hicn-light/src/hicn/utils/utils.c new file mode 100644 index 000000000..61ff9a904 --- /dev/null +++ b/hicn-light/src/hicn/utils/utils.c @@ -0,0 +1,236 @@ +// Utility function for commands + +#ifndef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// 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, + union commandAddr *address, + in_port_t *port) { + char *result; + + switch (addressType) { + case ADDR_INET: { + result = utils_BuildStringFromInet(&address->ipv4, port); + break; + } + + case ADDR_INET6: { + result = utils_BuildStringFromInet6(&address->ipv6, 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, + union commandAddr *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 new file mode 100644 index 000000000..ce8cb4e17 --- /dev/null +++ b/hicn-light/src/hicn/utils/utils.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +/** + * 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, + union commandAddr *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, + union commandAddr *address, + uint8_t *prefixLen); + +#endif \ No newline at end of file diff --git a/hicn-light/src/io/CMakeLists.txt b/hicn-light/src/io/CMakeLists.txt deleted file mode 100644 index f65f0b580..000000000 --- a/hicn-light/src/io/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -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(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/io/addressPair.c b/hicn-light/src/io/addressPair.c deleted file mode 100644 index 5d2017a3d..000000000 --- a/hicn-light/src/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 -#include - -#include -#include -#include -#include -#include - -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/io/addressPair.h b/hicn-light/src/io/addressPair.h deleted file mode 100644 index 5152267b6..000000000 --- a/hicn-light/src/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 - -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/io/hicnConnection.c b/hicn-light/src/io/hicnConnection.c deleted file mode 100644 index 991c0064e..000000000 --- a/hicn-light/src/io/hicnConnection.c +++ /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. - */ - -/** - * Embodies the reader/writer for a Hicn connection - * - * NB The Send() function may overflow the output buffer - * - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include - -typedef struct hicn_state { - Forwarder *forwarder; - 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; - - // this address contains one of the content names reachable - // throught the connection peer. We need this address beacuse it is - // the only way we have to conntact the next hop, since the main tun - // does not have address. Notice that a connection that sends probes - // is a connection that sends interest. In a "data" connection this - // value will remain NULL. We refresh the content address every time - // we send a probe, in this way we don't need to waste to much time in - // copy the address, but we can also react to the routing changes - struct sockaddr *probeDestAddress; - socklen_t probeDestAddressLength; - bool refreshProbeDestAddress; - - bool isLocal; - bool isUp; - unsigned id; - - unsigned delay; -} _HicnState; - -// Prototypes -static bool _send(IoOperations *ops, const Address *nexthop, Message *message); -static bool _sendCommandResponse(IoOperations *ops, struct iovec *message); -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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message); - -/* - * 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, - .sendCommandResponse = &_sendCommandResponse, - .getRemoteAddress = &_getRemoteAddress, - .getAddressPair = &_getAddressPair, - .getConnectionId = &_getConnectionId, - .isUp = &_isUp, - .isLocal = &_isLocal, - .destroy = &_destroy, - .class = &_streamConnection_Class, - .getConnectionType = &_getConnectionType, - .sendProbe = &_sendProbe}; - -// ================================================================= - -static void _setConnectionState(_HicnState *Hicn, bool isUp); -static bool _saveSockaddr(_HicnState *hicnConnState, const AddressPair *pair); -static void _refreshProbeDestAddress(_HicnState *hicnConnState, - const uint8_t *message); - -IoOperations *hicnConnection_Create(Forwarder *forwarder, 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->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); - - 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); - 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)); - if (hicnConnState->probeDestAddress != NULL) - parcMemory_Deallocate((void **)&(hicnConnState->probeDestAddress)); - - 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); - } - - // XXX - // do not close hicListenerSocket, the listener will close - // that when its done - // should I say something to libhicn? - - logger_Release(&hicnConnState->logger); - 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 - // XXX - 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)); - } - - // only in this case we may need to set the probeDestAddress - if (hicnConnState->refreshProbeDestAddress) { - _refreshProbeDestAddress(hicnConnState, message_FixedHeader(message)); - } - - } 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 _sendCommandResponse(IoOperations *ops, struct iovec *message) { - //XXX this should be nerver called since we do not handle control messages - //with hicn connections, so nothing to do here! - return false; -} - -static list_connections_type _getConnectionType(const IoOperations *ops) { - return CONN_HICN; -} - -static Ticks _sendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message) { - parcAssertNotNull(ops, "Parameter ops must be non-null"); - _HicnState *hicnConnState = (_HicnState *)ioOperations_GetClosure(ops); - - if ((hicnConnState->peerAddressLength == sizeof(struct sockaddr_in)) || - (hicnConnState->localAddressLength == sizeof(struct sockaddr_in))) - return false; - - if (hicnConnState->probeDestAddress == NULL && - probeType == PACKET_TYPE_PROBE_REPLY) { - uint8_t *pkt = parcMemory_AllocateAndClear( - messageHandler_GetICMPPacketSize(IPv6_TYPE)); - messageHandler_SetProbePacket( - pkt, probeType, - (struct in6_addr *)messageHandler_GetDestination(message), - (struct in6_addr *)messageHandler_GetSource(message)); - - ssize_t writeLength = write(hicnConnState->hicnListenerSocket, pkt, - messageHandler_GetICMPPacketSize(IPv6_TYPE)); - - parcMemory_Deallocate((void **)&pkt); - - if (writeLength < 0) { - return 0; - } - - } else if (hicnConnState->probeDestAddress != NULL && - probeType == PACKET_TYPE_PROBE_REQUEST) { - hicnConnState->refreshProbeDestAddress = true; - - uint8_t *pkt = parcMemory_AllocateAndClear( - messageHandler_GetICMPPacketSize(IPv6_TYPE)); - messageHandler_SetProbePacket( - pkt, probeType, - &((struct sockaddr_in6 *)hicnConnState->localAddress)->sin6_addr, - &((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_addr); - - ssize_t writeLength = write(hicnConnState->hicnListenerSocket, pkt, - messageHandler_GetICMPPacketSize(IPv6_TYPE)); - - parcMemory_Deallocate((void **)&pkt); - - if (writeLength < 0) { - return 0; - } - - } else { - if (hicnConnState->probeDestAddress == NULL && - probeType == PACKET_TYPE_PROBE_REQUEST) { - // this happen for the first probe - hicnConnState->refreshProbeDestAddress = true; - } - // do nothing - return 0; - } - - return forwarder_GetTicks(hicnConnState->forwarder); -} - -// ================================================================= -// 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; - - hicnConnState->probeDestAddress = NULL; - hicnConnState->probeDestAddressLength = (socklen_t)bytes; - hicnConnState->refreshProbeDestAddress = false; - - 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; - - hicnConnState->probeDestAddress = NULL; - hicnConnState->probeDestAddressLength = (socklen_t)bytes; - hicnConnState->refreshProbeDestAddress = false; - - 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 _refreshProbeDestAddress(_HicnState *hicnConnState, - const uint8_t *message) { - if ((hicnConnState->peerAddressLength == sizeof(struct sockaddr_in)) || - (hicnConnState->localAddressLength == sizeof(struct sockaddr_in))) - return; - - if (hicnConnState->probeDestAddress == NULL) { - hicnConnState->probeDestAddress = - parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6)); - parcAssertNotNull(hicnConnState->probeDestAddress, - "parcMemory_Allocate(%zu) returned NULL", - sizeof(struct sockaddr_in6)); - } - - ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_family = - AF_INET6; - ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_port = - htons(1234); - ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_scope_id = 0; - ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_flowinfo = 0; - ((struct sockaddr_in6 *)hicnConnState->probeDestAddress)->sin6_addr = - *((struct in6_addr *)messageHandler_GetDestination(message)); - hicnConnState->refreshProbeDestAddress = false; -} - -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; - } -} diff --git a/hicn-light/src/io/hicnConnection.h b/hicn-light/src/io/hicnConnection.h deleted file mode 100644 index 930e2d470..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -/** - * 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, int fd, - const AddressPair *pair, bool isLocal); -#endif // hicnConnection_h diff --git a/hicn-light/src/io/hicnListener.c b/hicn-light/src/io/hicnListener.c deleted file mode 100644 index bcf4de6a3..000000000 --- a/hicn-light/src/io/hicnListener.c +++ /dev/null @@ -1,727 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#ifdef WITH_MAPME -#include -#include -#include -#include -#endif /* WITH_MAPME */ -#include -#include -#include -#include -#include -#include -#include - -#define IPv6 6 -#define IPv4 4 -#define MTU_SIZE 1500 // bytes -#define MAX_HICN_RETRY 5 - -struct hicn_listener { - 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 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 ListenerOps _hicnTemplate = {.context = NULL, - .destroy = &_destroy, - .getInterfaceIndex = &_getInterfaceIndex, - .getListenAddress = &_getListenAddress, - .getEncapType = &_getEncapType, - .getSocket = &_getSocket}; - -static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid); - -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 bool _isEmptyAddressIPv4(Address *address) { - bool res = false; - - if (strcmp("inet4://0.0.0.0:1234", addressToString(address)) == 0) res = true; - 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->logger = logger_Acquire(forwarder_GetLogger(forwarder)); - - hicn->conn_id = forwarder_GetNextConnectionId(forwarder); - hicn->localAddress = addressCopy(address); - - 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); - 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); - - hicn->hicn_event = dispatcher_CreateNetworkEvent( - forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb, - (void *)hicn, hicn->hicn_fd); - dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), - hicn->hicn_event); - - ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); - parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(ListenerOps)); - - memcpy(ops, &_hicnTemplate, sizeof(ListenerOps)); - ops->context = hicn; - - 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->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); - 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); - - hicn->hicn_event = dispatcher_CreateNetworkEvent( - forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb, - (void *)hicn, hicn->hicn_fd); - dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), - hicn->hicn_event); - - ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); - parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(ListenerOps)); - - memcpy(ops, &_hicnTemplate, sizeof(ListenerOps)); - ops->context = hicn; - - 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_bild 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_bild 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; - - // close(hicn->hicn_fd); //XXX close the fd in the hicnlib (detroy listener?) - 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 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) { - printf("Error trying to discard frame from fd %d: (%d) %s", fd, errno, - strerror(errno)); - 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(HicnListener *hicn, int fd, - const AddressPair *pair) { - bool isLocal = false; - - // udpConnection_Create takes ownership of the pair - IoOperations *ops = hicnConnection_Create(hicn->forwarder, fd, pair, isLocal); - Connection *conn = connection_Create(ops); - - connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), conn); - unsigned connid = ioOperations_GetConnectionId(ops); - - return connid; -} - -const Connection *_findConnectionFromPacket(HicnListener *hicn, - Address *packetSourceAddress) { - 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 _handleProbeMessage(HicnListener *hicn, uint8_t *msgBuffer) { - Address *packetAddr = _createAddressFromPacket(msgBuffer); - - if (packetAddr != NULL) { - const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); - if (conn != NULL) { - // we drop all the probes for a connection that does not exists - connection_HandleProbe((Connection *)conn, msgBuffer, - forwarder_GetTicks(hicn->forwarder)); - } - } - - addressDestroy(&packetAddr); - parcMemory_Deallocate((void **)&msgBuffer); -} - -static void _handleWldrNotification(HicnListener *hicn, uint8_t *msgBuffer) { - Address *packetAddr = _createAddressFromPacket(msgBuffer); - - if (packetAddr == NULL) { - parcMemory_Deallocate((void **)&msgBuffer); - return; - } - - const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); - if (conn == NULL) { - addressDestroy(&packetAddr); - return; - } - - addressDestroy(&packetAddr); - - 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); -} - -#ifdef WITH_MAPME -static void _handleMapMe(HicnListener *hicn, int fd, uint8_t *msgBuffer) { - Address *packetAddr = _createAddressFromPacket(msgBuffer); - - if (packetAddr == NULL) { - parcMemory_Deallocate((void **)&msgBuffer); - return; - } - - const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); - unsigned conn_id; - if (conn == NULL) { - /* Unlike the interest path, we don't create virtual connections bound - * on the listener, whose only interest is to send data, but full - * tunnels to be able to route interests - * - * packetAddr is the remote address, we need to ask the lib for our - * local address - * hicn->localAddress is None as the interest is received by the main - * listener. - */ - printf("MapMe, connection did not exist, creating\n"); - - /* Populate remote_address through packetAddr */ - struct sockaddr_in6 sockaddr; // XXX IPv6 only - addressGetInet6(packetAddr, &sockaddr); - ip_address_t remote_address = {.family = AF_INET6, - .prefix_len = IPV6_ADDR_LEN_BITS}; - memcpy(&remote_address.buffer, &sockaddr.sin6_addr, - ip_address_len(&remote_address)); - - /* Get local address through libhicn */ - ip_address_t local_address; - int rc = hicn_get_local_address(&remote_address, &local_address); - if (rc < 0) { - printf("Error getting local address. Discarded mapme packet.\n"); - return; - } - - 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 *)&(local_address.buffer), 16); - - Address *localAddr = addressCreateFromInet6(&addr_in6); - IoOperations *ops = - hicnTunnel_Create(hicn->forwarder, localAddr, packetAddr); - - if (!ops) { - printf("Error creating tunnel. Discarded mapme packet.\n"); - return; - } - - conn = connection_Create(ops); - - connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), - (Connection *)conn); - } - conn_id = connection_GetConnectionId(conn); - - addressDestroy(&packetAddr); - - forwarder_ProcessMapMe(hicn->forwarder, msgBuffer, conn_id); -} -#endif /* WITH_MAPME */ - -static Message *_readMessage(HicnListener *hicn, int fd, uint8_t *msgBuffer) { - 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); - const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); - - if (conn == NULL) { - AddressPair *pair = addressPair_Create(hicn->localAddress, packetAddr); - connid = _createNewConnection(hicn, 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(hicn, msgBuffer); - } else if (messageHandler_IsLoadBalancerProbe(msgBuffer)) { - _handleProbeMessage(hicn, msgBuffer); - } -#ifdef WITH_MAPME - else if (mapMe_isMapMe(msgBuffer)) { - /* This function triggers the handling of the MAP-Me message, and we - * will return NULL so as to terminate the processing of this - * msgBuffer. */ - _handleMapMe(hicn, fd, msgBuffer); - } -#endif /* WITH_MAPME */ - - return message; -} - -static void _receivePacket(HicnListener *hicn, int fd) { - Message *msg = NULL; - uint8_t *msgBuffer = parcMemory_AllocateAndClear(MTU_SIZE); - msg = _readMessage(hicn, fd, msgBuffer); - - if (msg) { - forwarder_Receive(hicn->forwarder, msg); - } -} - -static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid) { - HicnListener *hicn = (HicnListener *)hicnVoid; - - if (hicn->inetFamily == IPv4 || hicn->inetFamily == IPv6) { - if (what & PARCEventType_Read) { - _receivePacket(hicn, fd); - } - } else { - _readFrameToDiscard(hicn, fd); - } -} diff --git a/hicn-light/src/io/hicnListener.h b/hicn-light/src/io/hicnListener.h deleted file mode 100644 index 5897d33ad..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -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/io/hicnTunnel.c b/hicn-light/src/io/hicnTunnel.c deleted file mode 100644 index e55393137..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -#include -#include -#include -#include - -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, 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/io/hicnTunnel.h b/hicn-light/src/io/hicnTunnel.h deleted file mode 100644 index 70295797c..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -/** - * 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/io/ioOperations.c b/hicn-light/src/io/ioOperations.c deleted file mode 100644 index b40b51d76..000000000 --- a/hicn-light/src/io/ioOperations.c +++ /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. - */ - -#include -#include -#include -#include - -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_SendCommandResponse(IoOperations *ops, - struct iovec *message) { - return ops->sendCommandResponse(ops, message); -} - - -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); -} - -Ticks ioOperations_SendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message) { - return ops->sendProbe(ops, probeType, message); -} diff --git a/hicn-light/src/io/ioOperations.h b/hicn-light/src/io/ioOperations.h deleted file mode 100644 index 48319c259..000000000 --- a/hicn-light/src/io/ioOperations.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#include -#include - -// 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. - * @discussion <#Discussion#> - */ -struct io_ops { - void *closure; - bool (*send)(IoOperations *ops, const Address *nexthop, Message *message); - bool (*sendCommandResponse)(IoOperations *ops, struct iovec *message); - 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); - Ticks (*sendProbe)(IoOperations *ops, unsigned probeType, uint8_t *message); -}; - -/** - * 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_SendCommandResponse(IoOperations *ops, - struct iovec *message); - -/** - * 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); - -Ticks ioOperations_SendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message); -#endif // io_h diff --git a/hicn-light/src/io/listener.h b/hicn-light/src/io/listener.h deleted file mode 100644 index ffbb513fa..000000000 --- a/hicn-light/src/io/listener.h +++ /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. - */ - -/** - * @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 - -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 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 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); -}; -#endif // listener_h diff --git a/hicn-light/src/io/listenerSet.c b/hicn-light/src/io/listenerSet.c deleted file mode 100644 index a890cd5b8..000000000 --- a/hicn-light/src/io/listenerSet.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 -#include - -#include -#include -#include -#include - -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; -} diff --git a/hicn-light/src/io/listenerSet.h b/hicn-light/src/io/listenerSet.h deleted file mode 100644 index 671e68479..000000000 --- a/hicn-light/src/io/listenerSet.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 - -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); -#endif diff --git a/hicn-light/src/io/streamConnection.c b/hicn-light/src/io/streamConnection.c deleted file mode 100644 index 78c19fb18..000000000 --- a/hicn-light/src/io/streamConnection.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -// 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; - Logger *logger; - - int fd; - - AddressPair *addressPair; - PARCEventQueue *bufferEventVector; - - bool isLocal; - bool isUp; - bool isClosed; - unsigned id; - - size_t nextMessageLength; -} _StreamState; - -// Prototypes -static bool _streamConnection_Send(IoOperations *ops, const Address *nexthop, - Message *message); -static bool _streamConnection_SendCommandResponse(IoOperations *ops, - struct iovec *msg); -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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message); - -/* - * 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, - .sendCommandResponse = &_streamConnection_SendCommandResponse, - .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, -}; - -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->logger = logger_Acquire(forwarder_GetLogger(forwarder)); - stream->fd = fd; - 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); - - 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->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_SendCommandResponse(IoOperations *ops, - struct iovec *response) { - parcAssertNotNull(ops, "Parameter ops must be non-null"); - parcAssertNotNull(response, "Parameter message must be non-null"); - _StreamState *conn = (_StreamState *)ioOperations_GetClosure(ops); - - bool success = false; - if (conn->isUp) { - 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_Debug)) { - logger_Log( - conn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, - "connid %u Writing %zu bytes to buffer with backlog %zu bytes", - conn->id, - (response[0].iov_len + - response[1].iov_len), // NEW: take total lenght - buffer_backlog); - } - - // NEW: write directly ino the parcEventQueue without passing through - // message - int failure = - parcEventQueue_Write(conn->bufferEventVector, response[0].iov_base, - response[0].iov_len) + - parcEventQueue_Write(conn->bufferEventVector, response[1].iov_base, - response[1].iov_len); - - if (failure == 0) { - success = true; - } - } else { - 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); - } - } - } else { - 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 success; -} - -/** - * @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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message) { - // we don't need to implemet this here, it is a local connection - return 0; -} - -// ================================================================= -// 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); - 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) malformend 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 */ -} diff --git a/hicn-light/src/io/streamConnection.h b/hicn-light/src/io/streamConnection.h deleted file mode 100644 index 8eb63a094..000000000 --- a/hicn-light/src/io/streamConnection.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#include -#include -#include - -/** - * @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_SendCommandResponse(IoOperations *ops, struct iovec *response); - -#endif // streamConnection_h diff --git a/hicn-light/src/io/tcpListener.c b/hicn-light/src/io/tcpListener.c deleted file mode 100644 index 6f0477f5b..000000000 --- a/hicn-light/src/io/tcpListener.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -typedef struct tcp_listener { - Forwarder *forwarder; - Logger *logger; - - PARCEventSocket *listener; - - Address *localAddress; - - unsigned id; - - // 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 unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops); -static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops); -static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops); - -static ListenerOps _tcpTemplate = { - .context = NULL, - .destroy = &_tcpListener_OpsDestroy, - .getInterfaceIndex = &_tcpListener_OpsGetInterfaceIndex, - .getListenAddress = &_tcpListener_OpsGetListenAddress, - .getEncapType = &_tcpListener_OpsGetEncapType, - .getSocket = NULL}; - -// STREAM daemon listener callback -static void _tcpListener_Listen(int, struct sockaddr *, int socklen, - void *tcpVoid); - -ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, - struct sockaddr_in6 sin6) { - _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); - parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(_TcpListener)); - - tcp->forwarder = forwarder; - tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); - - 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, - struct sockaddr_in sin) { - _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); - parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(_TcpListener)); - - tcp->forwarder = forwarder; - tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); - 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); - } - - logger_Release(&tcp->logger); - dispatcher_DestroyListener(forwarder_GetDispatcher(tcp->forwarder), - &tcp->listener); - addressDestroy(&tcp->localAddress); - parcMemory_Deallocate((void **)&tcp); - *listenerPtr = NULL; -} - -// ================================================== - -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/io/tcpListener.h b/hicn-light/src/io/tcpListener.h deleted file mode 100644 index 9664b32b0..000000000 --- a/hicn-light/src/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 -#endif - -#include -#include -#include - -ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, - struct sockaddr_in6 sin6); -ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, - struct sockaddr_in sin); -#endif // tcpListener_h diff --git a/hicn-light/src/io/tcpTunnel.c b/hicn-light/src/io/tcpTunnel.c deleted file mode 100644 index a2bf2bd30..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -#include -#include -#include -#include - -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/io/tcpTunnel.h b/hicn-light/src/io/tcpTunnel.h deleted file mode 100644 index 4daa7d032..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -/** - */ -// 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/io/udpConnection.c b/hicn-light/src/io/udpConnection.c deleted file mode 100644 index 5fbdf4998..000000000 --- a/hicn-light/src/io/udpConnection.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#endif -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -typedef struct udp_state { - Forwarder *forwarder; - 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; -} _UdpState; - -// Prototypes -static bool _send(IoOperations *ops, const Address *nexthop, Message *message); -static bool _sendCommandResponse(IoOperations *ops, struct iovec *message); -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 Ticks _sendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message); -/* - * 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, - .sendCommandResponse = &_sendCommandResponse, - .getRemoteAddress = &_getRemoteAddress, - .getAddressPair = &_getAddressPair, - .getConnectionId = &_getConnectionId, - .isUp = &_isUp, - .isLocal = &_isLocal, - .destroy = &_destroy, - .class = &_streamConnection_Class, - .getConnectionType = &_getConnectionType, - .sendProbe = &_sendProbe}; - -// ================================================================= - -static void _setConnectionState(_UdpState *Udp, bool isUp); -static bool _saveSockaddr(_UdpState *udpConnState, const AddressPair *pair); - -IoOperations *udpConnection_Create(Forwarder *forwarder, 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->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); - - 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); - 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); - 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 _sendCommandResponse(IoOperations *ops, struct iovec *message){ - 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, 2); - - 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[2]; - DWORD BytesSent = 0; - - for (int i = 0; i < 2; i++) { - dataBuf[i].buf = message[i].iov_base; - dataBuf[i].len = (ULONG)message[i].iov_len; - } - - int rc = WSASendTo(udpConnState->udpListenerSocket, dataBuf, 2, - &BytesSent, 0, (SOCKADDR *)udpConnState->peerAddress, - udpConnState->peerAddressLength, NULL, NULL); - - if (rc == SOCKET_ERROR) { - return false; - } -#endif - return true; -} - -static list_connections_type _getConnectionType(const IoOperations *ops) { - return CONN_UDP; -} - -static Ticks _sendProbe(IoOperations *ops, unsigned probeType, - uint8_t *message) { - //TODO - return 0; -} - -// ================================================================= -// 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; - } -} diff --git a/hicn-light/src/io/udpConnection.h b/hicn-light/src/io/udpConnection.h deleted file mode 100644 index 122f332d5..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -/** - * 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, int fd, - const AddressPair *pair, bool isLocal); -#endif // udpConnection_h diff --git a/hicn-light/src/io/udpListener.c b/hicn-light/src/io/udpListener.c deleted file mode 100644 index fefe116f9..000000000 --- a/hicn-light/src/io/udpListener.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include -#endif -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef WITH_MAPME -#include -#endif /* WITH_MAPME */ - -#define IPv4 4 -#define IPv6 6 - -struct udp_listener { - Forwarder *forwarder; - Logger *logger; - - PARCEvent *udp_event; - SocketType udp_socket; - uint16_t port; - - unsigned id; - Address *localAddress; -}; - -static void _destroy(ListenerOps **listenerOpsPtr); -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 ListenerOps udpTemplate = {.context = NULL, - .destroy = &_destroy, - .getInterfaceIndex = &_getInterfaceIndex, - .getListenAddress = &_getListenAddress, - .getEncapType = &_getEncapType, - .getSocket = &_getSocket}; - -static void _readcb(int fd, PARCEventType what, void *udpVoid); - -ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, - struct sockaddr_in6 sin6) { - ListenerOps *ops = NULL; - - UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener)); - parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(UdpListener)); - udp->forwarder = forwarder; - 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) { - udp->udp_event = - dispatcher_CreateNetworkEvent(forwarder_GetDispatcher(forwarder), true, - _readcb, (void *)udp, udp->udp_socket); - dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), - udp->udp_event); - - ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); - parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(ListenerOps)); - memcpy(ops, &udpTemplate, sizeof(ListenerOps)); - ops->context = udp; - - 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); - } -#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, - struct sockaddr_in sin) { - ListenerOps *ops = NULL; - - UdpListener *udp = parcMemory_AllocateAndClear(sizeof(UdpListener)); - parcAssertNotNull(udp, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(UdpListener)); - udp->forwarder = forwarder; - 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) { - udp->udp_event = - dispatcher_CreateNetworkEvent(forwarder_GetDispatcher(forwarder), true, - _readcb, (void *)udp, udp->udp_socket); - dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), - udp->udp_event); - - ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); - parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(ListenerOps)); - memcpy(ops, &udpTemplate, sizeof(ListenerOps)); - ops->context = udp; - - 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); - } - - close(udp->udp_socket); - 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); - } - -#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 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; -} - -/** - * @function _lookupConnectionId - * @abstract Lookup a connection in the connection table - * @discussion - * Looks up the connection in the connection table and returns the connection - * id if it exists. - * - * @param outputConnectionIdPtr is the output parameter - * @return true if connection found and outputConnectionIdPtr set - */ -static bool _lookupConnectionId(UdpListener *udp, AddressPair *pair, - unsigned *outputConnectionIdPtr) { - ConnectionTable *connTable = forwarder_GetConnectionTable(udp->forwarder); - - const Connection *conn = connectionTable_FindByAddressPair(connTable, pair); - if (conn) { - *outputConnectionIdPtr = connection_GetConnectionId(conn); - return true; - } else { - *outputConnectionIdPtr = 0; - return false; - } -} - -/** - * @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(UdpListener *udp, int fd, - const AddressPair *pair) { - //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, 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 _handleProbeMessage(UdpListener *udp, uint8_t *msgBuffer) { - // TODO - parcMemory_Deallocate((void **)&msgBuffer); -} - -static void _handleWldrNotification(UdpListener *udp, unsigned connId, - uint8_t *msgBuffer) { - const Connection *conn = connectionTable_FindById( - forwarder_GetConnectionTable(udp->forwarder), connId); - if (conn == NULL) { - 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(UdpListener *udp, int fd, - AddressPair *pair, uint8_t * packet, bool * processed) { - - Message *message = NULL; - - unsigned connid = 0; - bool foundConnection = _lookupConnectionId(udp, pair, &connid); - - 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(udp, 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 if (messageHandler_IsLoadBalancerProbe(packet)) { - *processed = true; - _handleProbeMessage(udp, packet); - } -#ifdef WITH_MAPME - else if (mapMe_isMapMe(packet)) { - *processed = true; - forwarder_ProcessMapMe(udp->forwarder, packet, connid); - } -#endif /* WITH_MAPME */ - - return message; -} - -static void _readCommand(UdpListener *udp, int fd, - AddressPair *pair, - uint8_t * command) { - - if (*command != REQUEST_LIGHT){ - printf("the message received is not a command, drop\n"); - return; - } - - command_id id = *(command + 1); - - if (id >= LAST_COMMAND_VALUE){ - printf("the message received is not a valid command, drop\n"); - return; - } - - unsigned connid = 0; - bool foundConnection = _lookupConnectionId(udp, pair, &connid); - if(!foundConnection){ - connid = _createNewConnection(udp, 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(UdpListener *udp, int fd, - AddressPair *pair, - uint8_t * packet) { - bool processed = false; - Message *message = _readMessage(udp, fd, pair, - packet, &processed); - if (message) { - forwarder_Receive(udp->forwarder, message); - } - return processed; -} - -static void _readcb(int fd, PARCEventType what, void *udpVoid) { - UdpListener *udp = (UdpListener *)udpVoid; - - 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" : "", udpVoid); - } - - 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"); - return; - } - - AddressPair *pair = _constructAddressPair( - udp, (struct sockaddr *)&peerIpAddress, peerIpAddressLength); - - bool done = _receivePacket(udp, fd, pair, packet); - if(!done){ - _readCommand(udp, fd, pair, packet); - } - - addressPair_Release(&pair); - } -} diff --git a/hicn-light/src/io/udpListener.h b/hicn-light/src/io/udpListener.h deleted file mode 100644 index 14c03fd52..000000000 --- a/hicn-light/src/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 -#endif - -#include -#include -#include - -struct udp_listener; -typedef struct udp_listener UdpListener; - -ListenerOps *udpListener_CreateInet6(Forwarder *forwarder, - struct sockaddr_in6 sin6); -ListenerOps *udpListener_CreateInet(Forwarder *forwarder, - struct sockaddr_in sin); -// void udpListener_SetPacketType(ListenerOps *ops, MessagePacketType type); -#endif // udpListener_h diff --git a/hicn-light/src/io/udpTunnel.c b/hicn-light/src/io/udpTunnel.c deleted file mode 100644 index d49f43f05..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -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, 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/io/udpTunnel.h b/hicn-light/src/io/udpTunnel.h deleted file mode 100644 index a79ca4a4e..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -/** - */ -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/messenger/CMakeLists.txt b/hicn-light/src/messenger/CMakeLists.txt deleted file mode 100644 index 92bc13b5b..000000000 --- a/hicn-light/src/messenger/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -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 -) - -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 -) - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/messenger/messenger.c b/hicn-light/src/messenger/messenger.c deleted file mode 100644 index 26c7a85e2..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include -#include -#include - -#include -#include - -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/messenger/messenger.h b/hicn-light/src/messenger/messenger.h deleted file mode 100644 index f945e7e72..000000000 --- a/hicn-light/src/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 -#include -#include - -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/messenger/messengerRecipient.c b/hicn-light/src/messenger/messengerRecipient.c deleted file mode 100644 index 14251f8eb..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -#include -#include - -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/messenger/messengerRecipient.h b/hicn-light/src/messenger/messengerRecipient.h deleted file mode 100644 index 66d8f40f5..000000000 --- a/hicn-light/src/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 - -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/messenger/missive.c b/hicn-light/src/messenger/missive.c deleted file mode 100644 index a8bcb0282..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -#include - -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/messenger/missive.h b/hicn-light/src/messenger/missive.h deleted file mode 100644 index 33f3ef8b8..000000000 --- a/hicn-light/src/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 - -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/messenger/missiveDeque.c b/hicn-light/src/messenger/missiveDeque.c deleted file mode 100644 index 418027d7a..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -#include -#include - -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/messenger/missiveDeque.h b/hicn-light/src/messenger/missiveDeque.h deleted file mode 100644 index c6f955ce0..000000000 --- a/hicn-light/src/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/messenger/missiveType.h b/hicn-light/src/messenger/missiveType.h deleted file mode 100644 index b0d9c7704..000000000 --- a/hicn-light/src/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/platforms/CMakeLists.txt b/hicn-light/src/platforms/CMakeLists.txt deleted file mode 100644 index 191a72213..000000000 --- a/hicn-light/src/platforms/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") - list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/android/system.c - ) -elseif(APPLE) - list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/darwin/system.c - ) -elseif( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) - list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/linux/system.c - ) -elseif( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" ) - list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/windows/system.c - ${CMAKE_CURRENT_SOURCE_DIR}/windows/win_portability.c - ) - list(APPEND HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/windows/win_portability.h - ) - -endif() - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/platforms/README.txt b/hicn-light/src/platforms/README.txt deleted file mode 100644 index a1293944c..000000000 --- a/hicn-light/src/platforms/README.txt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Operating system dependent modules. - diff --git a/hicn-light/src/platforms/android/system.c b/hicn-light/src/platforms/android/system.c deleted file mode 100644 index 68f99424b..000000000 --- a/hicn-light/src/platforms/android/system.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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -//#define __USE_MISC -#include - -// to get the list of arp types -#include - -// for the mac address -#include - -#include -#include - -#include - -#include "ifaddrs.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) { - struct ifreq ifr; - int fd; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - - strcpy(ifr.ifr_name, ifname); - ioctl(fd, SIOCGIFMTU, &ifr); - - close(fd); - return ifr.ifr_mtu; -} - -InterfaceSet *system_Interfaces(Forwarder *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); - parcAssertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); - - struct ifaddrs *next; - for (next = ifaddr; next != NULL; next = next->ifa_next) { - if ((next->ifa_addr == NULL) || ((next->ifa_flags & IFF_UP) == 0)) { - continue; - } - - Interface *iface = interfaceSetGetByName(set, next->ifa_name); - if (iface == NULL) { - unsigned mtu = (unsigned)getMtu(next->ifa_name); - - iface = interfaceCreate( - next->ifa_name, forwarder_GetNextConnectionId(forwarder), - next->ifa_flags & IFF_LOOPBACK, next->ifa_flags & IFF_MULTICAST, mtu); - - 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; - } - } - } - - freeifaddrs(ifaddr); - return set; -} - -Address *system_GetMacAddressByName(Forwarder *forwarder, - const char *interfaceName) { - Address *linkAddress = NULL; - - InterfaceSet *interfaceSet = system_Interfaces(forwarder); - Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); - - if (interface) { - const AddressList *addressList = interfaceGetAddresses(interface); - - size_t length = addressListLength(addressList); - for (size_t i = 0; i < length && !linkAddress; i++) { - const Address *a = addressListGetItem(addressList, i); - if (addressGetType(a) == ADDR_LINK) { - linkAddress = addressCopy(a); - } - } - } - - interfaceSetDestroy(&interfaceSet); - - return linkAddress; -} - -unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) { - unsigned mtu = 0; - - InterfaceSet *interfaceSet = system_Interfaces(forwarder); - Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); - - if (interface) { - mtu = interfaceGetMTU(interface); - } - - interfaceSetDestroy(&interfaceSet); - - return mtu; -} diff --git a/hicn-light/src/platforms/darwin/system.c b/hicn-light/src/platforms/darwin/system.c deleted file mode 100644 index b8ef80c63..000000000 --- a/hicn-light/src/platforms/darwin/system.c +++ /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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -InterfaceSet *system_Interfaces(Forwarder *forwarder) { - InterfaceSet *set = interfaceSetCreate(); - - // this is the dynamically allocated head of the list - struct ifaddrs *ifaddr; - int failure = getifaddrs(&ifaddr); - parcAssertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); - - struct ifaddrs *next; - for (next = ifaddr; next != NULL; next = next->ifa_next) { - if ((next->ifa_addr == NULL) || ((next->ifa_flags & IFF_UP) == 0)) { - continue; - } - - // This assumes the LINK address comes first so we can get the MTU - // when the interface is created. - - Interface *iface = interfaceSetGetByName(set, next->ifa_name); - if (iface == NULL) { - unsigned mtu = 0; - - if (next->ifa_data != NULL) { - struct if_data *ifdata = (struct if_data *)next->ifa_data; - mtu = ifdata->ifi_mtu; - } - - iface = interfaceCreate( - next->ifa_name, forwarder_GetNextConnectionId(forwarder), - next->ifa_flags & IFF_LOOPBACK, next->ifa_flags & IFF_MULTICAST, mtu); - - 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_LINK: { - struct sockaddr_dl *addr_dl = (struct sockaddr_dl *)next->ifa_addr; - - // skip links with 0-length address - if (addr_dl->sdl_alen > 0) { - // addr_dl->sdl_data[12] contains the interface name followed by the - // MAC address, so need to offset in to the array past the interface - // name. - Address *address = addressCreateFromLink( - (uint8_t *)&addr_dl->sdl_data[addr_dl->sdl_nlen], - addr_dl->sdl_alen); - interfaceAddAddress(iface, address); - } - break; - } - } - } - - freeifaddrs(ifaddr); - - return set; -} - -Address *system_GetMacAddressByName(Forwarder *forwarder, - const char *interfaceName) { - Address *linkAddress = NULL; - - InterfaceSet *interfaceSet = system_Interfaces(forwarder); - Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); - - if (interface) { - const AddressList *addressList = interfaceGetAddresses(interface); - - size_t length = addressListLength(addressList); - for (size_t i = 0; i < length && !linkAddress; i++) { - const Address *a = addressListGetItem(addressList, i); - if (addressGetType(a) == ADDR_LINK) { - linkAddress = addressCopy(a); - } - } - } - - interfaceSetDestroy(&interfaceSet); - - return linkAddress; -} - -unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) { - unsigned mtu = 0; - - if (interfaceName) { - InterfaceSet *interfaceSet = system_Interfaces(forwarder); - Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); - - if (interface) { - mtu = interfaceGetMTU(interface); - } - - interfaceSetDestroy(&interfaceSet); - } - return mtu; -} diff --git a/hicn-light/src/platforms/linux/system.c b/hicn-light/src/platforms/linux/system.c deleted file mode 100644 index fcf13becc..000000000 --- a/hicn-light/src/platforms/linux/system.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#define __USE_MISC -#include - -// to get the list of arp types -#include - -// for the mac address -#include - -#include -#include - -#include - -#include - -/** - * 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) { - struct ifreq ifr; - int fd; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - - strcpy(ifr.ifr_name, ifname); - ioctl(fd, SIOCGIFMTU, &ifr); - - close(fd); - return ifr.ifr_mtu; -} - -InterfaceSet *system_Interfaces(Forwarder *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); - parcAssertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); - - struct ifaddrs *next; - for (next = ifaddr; next != NULL; next = next->ifa_next) { - if ((next->ifa_addr == NULL) || ((next->ifa_flags & IFF_UP) == 0)) { - continue; - } - - Interface *iface = interfaceSetGetByName(set, next->ifa_name); - if (iface == NULL) { - unsigned mtu = (unsigned)getMtu(next->ifa_name); - - iface = interfaceCreate( - next->ifa_name, forwarder_GetNextConnectionId(forwarder), - next->ifa_flags & IFF_LOOPBACK, next->ifa_flags & IFF_MULTICAST, mtu); - - 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; - } - } - } - - freeifaddrs(ifaddr); - return set; -} - -Address *system_GetMacAddressByName(Forwarder *forwarder, - const char *interfaceName) { - Address *linkAddress = NULL; - - InterfaceSet *interfaceSet = system_Interfaces(forwarder); - Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); - - if (interface) { - const AddressList *addressList = interfaceGetAddresses(interface); - - size_t length = addressListLength(addressList); - for (size_t i = 0; i < length && !linkAddress; i++) { - const Address *a = addressListGetItem(addressList, i); - if (addressGetType(a) == ADDR_LINK) { - linkAddress = addressCopy(a); - } - } - } - - interfaceSetDestroy(&interfaceSet); - - return linkAddress; -} - -unsigned system_InterfaceMtu(Forwarder *forwarder, const char *interfaceName) { - unsigned mtu = 0; - - InterfaceSet *interfaceSet = system_Interfaces(forwarder); - Interface *interface = interfaceSetGetByName(interfaceSet, interfaceName); - - if (interface) { - mtu = interfaceGetMTU(interface); - } - - interfaceSetDestroy(&interfaceSet); - - return mtu; -} diff --git a/hicn-light/src/platforms/windows/system.c b/hicn-light/src/platforms/windows/system.c deleted file mode 100644 index a23b7d95e..000000000 --- a/hicn-light/src/platforms/windows/system.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include - -#include - -#include -#include - -#define WORKING_BUFFER_SIZE 15000 -#define MAX_TRIES 3 - -#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) -#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) - -#include -#include - -#include - -/** - * 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/platforms/windows/win_portability.c b/hicn-light/src/platforms/windows/win_portability.c deleted file mode 100644 index cc592cd4b..000000000 --- a/hicn-light/src/platforms/windows/win_portability.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -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); -} \ No newline at end of file diff --git a/hicn-light/src/platforms/windows/win_portability.h b/hicn-light/src/platforms/windows/win_portability.h deleted file mode 100644 index 5c25f4bb2..000000000 --- a/hicn-light/src/platforms/windows/win_portability.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once -#include -#include -#include -#include -#include -#include -#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/processor/CMakeLists.txt b/hicn-light/src/processor/CMakeLists.txt deleted file mode 100644 index b7eeabe3b..000000000 --- a/hicn-light/src/processor/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -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/processor/fib.c b/hicn-light/src/processor/fib.c deleted file mode 100644 index c7b1e2de2..000000000 --- a/hicn-light/src/processor/fib.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include - -#include -#include - -#include - -#define NULL_POS 128 -#define MSB_POS 127 - -struct node; -typedef struct node FibNode; - -struct node { - FibNode *left; - FibNode *right; - FibEntry *entry; - unsigned pos; -}; - -struct fib { - FibNode *root; - unsigned size; -}; - -// ===================================================== -// Public API - -FibNode *_createNode(FibNode *left, FibNode *right, FibEntry *entry, - unsigned pos) { - 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->pos = pos; - - return n; -} - -FIB *fib_Create() { - FIB *hicnFib = parcMemory_AllocateAndClear(sizeof(FIB)); - parcAssertNotNull(hicnFib, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(FIB)); - - hicnFib->root = - _createNode(NULL, NULL, NULL, - NULL_POS); // the pos will decrease going down in the trie - hicnFib->root->left = hicnFib->root; - hicnFib->root->right = hicnFib->root; - - hicnFib->size = 0; - - return hicnFib; -} - -void _destroyNode(FibNode *n) { - fibEntry_Release(&n->entry); - parcMemory_Deallocate((void **)&n); - n = NULL; -} - -void _destroyFib(FIB *fib) { - // XXX - // to be done - return; -} - -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); - 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 *name = name_GetContentName(fibEntry_GetPrefix(entry)); - - // search the name - FibNode *prev = fib->root; - FibNode *curr; - - if (nameBitvector_testBit(name, MSB_POS)) { - curr = fib->root->right; - } else { - curr = fib->root->left; - } - - while (prev->pos > curr->pos) { - prev = curr; - if (nameBitvector_testBit(name, curr->pos)) { - curr = curr->right; - } else { - curr = curr->left; - } - } - - if (curr->entry != NULL && - nameBitvector_Equals( - name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) { - // there is already an entry with this name - // do nothing. Before call ADD we should check - // if the node exists, and, in that case update it - return; - } - - // if the name is not in the FIB search for the first different bit between - // the new name to add and the node found in the trie - uint8_t pos = MSB_POS; - if (curr->entry != NULL) - pos = nameBitvector_firstDiff( - name, name_GetContentName(fibEntry_GetPrefix(curr->entry))); - - // reset pointer and search the insertion point - prev = fib->root; - if (nameBitvector_testBit(name, MSB_POS)) - curr = fib->root->right; - else - curr = fib->root->left; - - while (prev->pos > curr->pos && curr->pos > pos) { - prev = curr; - if (nameBitvector_testBit(name, curr->pos)) { - curr = curr->right; - } else { - curr = curr->left; - } - } - - // insert the node - fib->size++; - FibNode *n = _createNode(NULL, NULL, entry, pos); - - if (nameBitvector_testBit(name, pos)) { - n->left = curr; - n->right = n; - } else { - n->left = n; - n->right = curr; - } - - uint8_t new_pos = prev->pos; - if (new_pos == NULL_POS) new_pos = MSB_POS; - - if (nameBitvector_testBit(name, new_pos)) { - prev->right = n; - } else { - prev->left = n; - } -} - -FibEntry *fib_Contains(const FIB *fib, const Name *prefix) { - parcAssertNotNull(fib, "Parameter must be non-null"); - parcAssertNotNull(prefix, "Parameter must be non-null"); - - NameBitvector *name = name_GetContentName(prefix); - - // this is the same as the first part of the add function - // we cannnot call this function inside the add because - // we need the pointer prev and curr for the insertion - - FibNode *prev = fib->root; - FibNode *curr; - - if (nameBitvector_testBit(name, MSB_POS)) - curr = fib->root->right; - else - curr = fib->root->left; - - while (prev->pos > curr->pos) { - prev = curr; - - if (nameBitvector_testBit(name, curr->pos)) { - curr = curr->right; - } else { - curr = curr->left; - } - } - - if (curr->entry != NULL && - nameBitvector_Equals( - name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) { - return curr->entry; - } else { - return NULL; - } -} - -void _removeNode(FIB *fib, const Name *prefix) { - parcAssertNotNull(fib, "Parameter must be non-null"); - parcAssertNotNull(prefix, "Parameter must be non-null"); - - FibNode *grand = NULL; // grandparent - FibNode *prev = - fib->root; // parent: it will points to curr of the next hop in the trie - FibNode *curr; // current node: the node to remove - - NameBitvector *name = name_GetContentName(prefix); - - if (nameBitvector_testBit(name, MSB_POS)) { - curr = fib->root->right; - } else { - curr = fib->root->left; - } - - // in the first loop we always search the node to remove - while (prev->pos > curr->pos) { - grand = prev; - prev = curr; - - if (nameBitvector_testBit(name, curr->pos)) { - curr = curr->right; - } else { - curr = curr->left; - } - } - - if (!nameBitvector_Equals( - name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) { - // the node does not exists - return; - } - - // search for the real parent of curr (*tmpPrev) - // prev points to curr or next node in the trie - // this is because of the loopback links - - FibNode *tmpPrev = fib->root; - FibNode *tmpCurr; - - if (nameBitvector_testBit(name, MSB_POS)) { - tmpCurr = fib->root->right; - } else { - tmpCurr = fib->root->left; - } - - // here we compare pointer so we are sure to stop at the right potion - while (tmpCurr != curr) { - tmpPrev = tmpCurr; - - if (nameBitvector_testBit(name, tmpCurr->pos)) { - tmpCurr = tmpCurr->right; - } else { - tmpCurr = tmpCurr->left; - } - } - - // now curr is the node to remove and tmpPrev is the real parent of curr - - if (curr == prev) { - // this is the case where curr is a leaf node - FibNode *next; // child of curr (the loopback) - - if (nameBitvector_testBit(name, curr->pos)) { - next = curr->left; - } else { - next = curr->right; - } - - if (nameBitvector_testBit(name, tmpPrev->pos)) { - tmpPrev->right = next; - } else { - tmpPrev->left = next; - } - - } else { - // curr is an internal node - FibNode *next; // child of prev (loopback) - - if (nameBitvector_testBit(name, prev->pos)) { - next = prev->left; - } else { - next = prev->right; - } - - if (nameBitvector_testBit(name, grand->pos)) { - grand->right = next; - } else { - grand->left = next; - } - - if (nameBitvector_testBit(name, tmpPrev->pos)) { - tmpPrev->right = prev; - } else { - tmpPrev->left = prev; - } - - prev->left = curr->left; - prev->right = curr->right; - prev->pos = curr->pos; - } - - fib->size--; - _destroyNode(curr); -} - -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); - if (fibEntry_NexthopCount(entry) == 0) { - _removeNode(fib, name); - } -} - -void _removeConnectionId(FibNode *n, unsigned pos, unsigned connectionId, - FibEntryList *list) { - if (n->pos < pos) { - fibEntry_RemoveNexthopByConnectionId(n->entry, connectionId); - if (fibEntry_NexthopCount(n->entry) == 0) { - fibEntryList_Append(list, n->entry); - } - _removeConnectionId(n->left, n->pos, connectionId, list); - _removeConnectionId(n->right, n->pos, connectionId, list); - } -} - -void fib_RemoveConnectionId(FIB *fib, unsigned connectionId) { - parcAssertNotNull(fib, "Parameter must be non-null"); - - // 1 - we vist the tree to remove the connection id - // 2 - during the visit we collect the fib entry with 0 nexthop - // 3 - after the visit we remove this entries - - FibEntryList *list = fibEntryList_Create(); - - _removeConnectionId(fib->root->left, fib->root->pos, connectionId, list); - _removeConnectionId(fib->root->right, fib->root->pos, 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_Match(const FIB *fib, const Message *interestMessage) { - parcAssertNotNull(fib, "Parameter must be non-null"); - parcAssertNotNull(interestMessage, "Parameter must be non-null"); - - NameBitvector *name = name_GetContentName(message_GetName(interestMessage)); - - FibNode *prev = fib->root; - FibNode *curr; - - FibNode *match = NULL; - unsigned len = 0; - - if (nameBitvector_testBit(name, MSB_POS)) - curr = fib->root->right; - else - curr = fib->root->left; - - while (prev->pos > curr->pos) { - prev = curr; - - if (curr->entry != NULL) { - if (nameBitvector_StartsWith( - name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) && - nameBitvector_GetLength( - name_GetContentName(fibEntry_GetPrefix(curr->entry))) > len) { - match = curr; - len = nameBitvector_GetLength( - name_GetContentName(fibEntry_GetPrefix(curr->entry))); - } - } - - if (nameBitvector_testBit(name, curr->pos)) - curr = curr->right; - else - curr = curr->left; - } - - if (curr->entry != NULL) { - if (nameBitvector_StartsWith( - name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) && - nameBitvector_GetLength( - name_GetContentName(fibEntry_GetPrefix(curr->entry))) > len) { - match = curr; - len = nameBitvector_GetLength( - name_GetContentName(fibEntry_GetPrefix(curr->entry))); - } - } - - if (match != NULL && match->entry != NULL) { - return match->entry; - } else { - return NULL; - } -} - -void _collectFibEntries(FibNode *n, int pos, FibEntryList *list) { - if (n->pos < (unsigned)pos) { - fibEntryList_Append(list, n->entry); - _collectFibEntries(n->left, n->pos, list); - _collectFibEntries(n->right, n->pos, list); - } -} - -FibEntryList *fib_GetEntries(const FIB *fib) { - parcAssertNotNull(fib, "Parameter must be non-null"); - - FibEntryList *list = fibEntryList_Create(); - - _collectFibEntries(fib->root->left, fib->root->pos, list); - _collectFibEntries(fib->root->right, fib->root->pos, list); - - return list; -} diff --git a/hicn-light/src/processor/fib.h b/hicn-light/src/processor/fib.h deleted file mode 100644 index 4409419db..000000000 --- a/hicn-light/src/processor/fib.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. - */ -#ifndef fib_h -#define fib_h - -#include -#include -#include -#include - -struct fib; -typedef struct fib FIB; - -FIB *fib_Create(); - -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_Match(const FIB *fib, const Message *interestMessage); - -size_t fib_Length(const FIB *fib); - -FibEntryList *fib_GetEntries(const FIB *fib); -#endif // fib_h diff --git a/hicn-light/src/processor/fibEntry.c b/hicn-light/src/processor/fibEntry.c deleted file mode 100644 index 6d741e312..000000000 --- a/hicn-light/src/processor/fibEntry.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#ifdef WITH_MAPME -#include -#include -#endif /* WITH_MAPME */ - -#include -#include - -#include - -struct fib_entry { - Name *name; - unsigned refcount; - StrategyImpl *fwdStrategy; -#ifdef WITH_MAPME - void *userData; - void (*userDataRelease)(void **userData); -#endif /* WITH_MAPME */ -}; - -FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy) { - FibEntry *fibEntry = parcMemory_AllocateAndClear(sizeof(FibEntry)); - parcAssertNotNull(fibEntry, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(FibEntry)); - fibEntry->name = name_Acquire(name); - - if (fwdStrategy) { - switch (fwdStrategy) { - case SET_STRATEGY_LOADBALANCER: - fibEntry->fwdStrategy = strategyLoadBalancer_Create(); - break; - - case SET_STRATEGY_RANDOM_PER_DASH_SEGMENT: - fibEntry->fwdStrategy = strategyRndSegment_Create(); - break; - - case SET_STRATEGY_LOADBALANCER_WITH_DELAY: - fibEntry->fwdStrategy = strategyLoadBalancerWithPD_Create(); - break; - - default: - // LB is the defualt strategy - fibEntry->fwdStrategy = strategyLoadBalancer_Create(); - // the LB strategy is the default one - // other strategies can be set using the appropiate function - break; - } - - } else { - fibEntry->fwdStrategy = strategyLoadBalancer_Create(); - } - - fibEntry->refcount = 1; - -#ifdef WITH_MAPME - fibEntry->userData = NULL; - fibEntry->userDataRelease = NULL; -#endif /* WITH_MAPME */ - - 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->userData); - } -#endif /* WITH_MAPME */ - parcMemory_Deallocate((void **)&fibEntry); - } - *fibEntryPtr = NULL; -} - -void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy) { - StrategyImpl *fwdStrategyImpl; - - switch (strategy) { - case SET_STRATEGY_LOADBALANCER: - fwdStrategyImpl = strategyLoadBalancer_Create(); - break; - - case SET_STRATEGY_RANDOM_PER_DASH_SEGMENT: - fwdStrategyImpl = strategyRndSegment_Create(); - break; - - case SET_STRATEGY_LOADBALANCER_WITH_DELAY: - fwdStrategyImpl = strategyLoadBalancerWithPD_Create(); - break; - - default: - // LB is the defualt strategy - fwdStrategyImpl = strategyLoadBalancer_Create(); - // the LB strategy is the default one - // other strategies can be set using the appropiate function - break; - } - - 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; -} -void fibEntry_AddNexthop(FibEntry *fibEntry, unsigned connectionId) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId); -} - -void fibEntry_RemoveNexthopByConnectionId(FibEntry *fibEntry, - unsigned connectionId) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - fibEntry->fwdStrategy->removeNexthop(fibEntry->fwdStrategy, connectionId); -} - -size_t fibEntry_NexthopCount(const FibEntry *fibEntry) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - return fibEntry->fwdStrategy->countNexthops(fibEntry->fwdStrategy); -} - -const NumberSet *fibEntry_GetNexthops(const FibEntry *fibEntry) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - return fibEntry->fwdStrategy->returnNexthops(fibEntry->fwdStrategy); -} - -const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy( - const FibEntry *fibEntry, const Message *interestMessage) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - return fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy, - interestMessage); -} - -void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry, - const NumberSet *egressId, - const Message *objectMessage, Ticks rtt) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - fibEntry->fwdStrategy->receiveObject(fibEntry->fwdStrategy, egressId, - objectMessage, rtt); -} - -void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - fibEntry->fwdStrategy->onTimeout(fibEntry->fwdStrategy, egressId); -} - -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_AddNexthopByConnectionId(FibEntry *fibEntry, - unsigned connectionId) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId); -} - -void *fibEntry_getUserData(const FibEntry *fibEntry) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - return fibEntry->userData; -} - -void fibEntry_setUserData(FibEntry *fibEntry, const void *userData, - void (*userDataRelease)(void **)) { - parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null"); - fibEntry->userData = (void *)userData; - fibEntry->userDataRelease = userDataRelease; -} - -#endif /* WITH_MAPME */ diff --git a/hicn-light/src/processor/fibEntry.h b/hicn-light/src/processor/fibEntry.h deleted file mode 100644 index 3bcac3884..000000000 --- a/hicn-light/src/processor/fibEntry.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 -#include - -#ifdef WITH_MAPME -#include -#include -#endif /* WITH_MAPME */ - -struct fib_entry; -typedef struct fib_entry FibEntry; - -FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy); - -/** - * 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); - -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); - -const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy( - const FibEntry *fibEntry, const Message *interestMessage); - -void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry, - const NumberSet *egressId, - const Message *objectMessage, Ticks rtt); - -void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId); - -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_AddNexthopByConnectionId - * @abstract Adds a next hop directly from the connection id. - * @param [in] fibEntry - Pointer to the FIB entry. - * @return The sequence number stored in the FIB entry. - */ -void fibEntry_AddNexthopByConnectionId(FibEntry *fibEntry, - unsigned connectionId); - -/** - * @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 *userData, - void (*userDataRelease)(void **)); - -#endif /* WITH_MAPME */ - -#endif // fibEntry_h diff --git a/hicn-light/src/processor/fibEntryList.c b/hicn-light/src/processor/fibEntryList.c deleted file mode 100644 index 2221fa614..000000000 --- a/hicn-light/src/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 -#include -#include - -#include -#include -#include -#include - -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/processor/fibEntryList.h b/hicn-light/src/processor/fibEntryList.h deleted file mode 100644 index 0f6066435..000000000 --- a/hicn-light/src/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 - -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 fibEntry. - * - * @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/processor/hashTableFunction.c b/hicn-light/src/processor/hashTableFunction.c deleted file mode 100644 index 6e70ef91a..000000000 --- a/hicn-light/src/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 -#include - -#include -#include - -#include -#include - -#include - -// ====================================================================== -// 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/processor/hashTableFunction.h b/hicn-light/src/processor/hashTableFunction.h deleted file mode 100644 index eb9989086..000000000 --- a/hicn-light/src/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 - -// ========================================================== -// 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/processor/matchingRulesTable.c b/hicn-light/src/processor/matchingRulesTable.c deleted file mode 100644 index 56e59c29e..000000000 --- a/hicn-light/src/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 -#include - -#include -#include - -#include -#include -#include - -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/processor/matchingRulesTable.h b/hicn-light/src/processor/matchingRulesTable.h deleted file mode 100644 index 96d099430..000000000 --- a/hicn-light/src/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 - * matchingRulesTable_AddToBestTable() to add an interest to the - * "best" (i.e. most restrictive match) table, then calls - * matchingRulesTable_GetUnion() on a content object to match - * against all of them. - * - * When used in a ContentStore, one calls - * matchingRulesTable_AddToAllTables() to index a Content Object in - * all the tables. one then calls matchingRulesTable_Get() 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 -#include -#include - -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/processor/messageProcessor.c b/hicn-light/src/processor/messageProcessor.c deleted file mode 100644 index 8c03ee739..000000000 --- a/hicn-light/src/processor/messageProcessor.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include - -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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; -}; - -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 - -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(); - - 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; - - 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); - - 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); - - const char *prefixStr = utils_PrefixLenToString( - control->addressType, &control->address, &control->len); - strategy_type fwdStrategy = - configuration_GetForwardingStrategy(config, prefixStr); - if (fwdStrategy == LAST_STRATEGY_VALUE) { - fwdStrategy = SET_STRATEGY_LOADBALANCER; - } - - Name *prefix = name_CreateFromAddress(control->addressType, control->address, - control->len); - FibEntry *entry = fib_Contains(processor->fib, prefix); - bool newEntry = false; - if (entry != NULL) { - fibEntry_AddNexthop(entry, ifidx); - } else { - newEntry = true; - entry = fibEntry_Create(prefix, fwdStrategy); - fibEntry_AddNexthop(entry, ifidx); - fib_Add(processor->fib, entry); - } - - name_Release(&prefix); - if (newEntry && (fwdStrategy == SET_STRATEGY_LOADBALANCER_WITH_DELAY)) { - strategyLoadBalancerWithPD_SetConnectionTable( - fibEntry_GetFwdStrategy(entry), - forwarder_GetConnectionTable(processor->forwarder)); - } - - 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; -} - -void messageProcessor_RemoveConnectionIdFromRoutes(MessageProcessor *processor, - unsigned connectionId) { - fib_RemoveConnectionId(processor->fib, connectionId); -} - -void processor_SetStrategy(MessageProcessor *processor, Name *prefix, - strategy_type strategy) { - FibEntry *entry = fib_Contains(processor->fib, prefix); - if (entry != NULL) { - fibEntry_SetStrategy(entry, strategy); - if (strategy == SET_STRATEGY_LOADBALANCER_WITH_DELAY) { - strategyLoadBalancerWithPD_SetConnectionTable( - fibEntry_GetFwdStrategy(entry), - forwarder_GetConnectionTable(processor->forwarder)); - } - } -} - -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 - * messageProcessor_Receive(), 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. - */ -static bool messageProcessor_AggregateInterestInPit(MessageProcessor *processor, - Message *interestMessage) { - 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 messageProcessor_ForwardToNexthops(), 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 - * interestMessage 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 - */ -static bool messageProcessor_ForwardViaFib(MessageProcessor *processor, - Message *interestMessage) { - FibEntry *fibEntry = fib_Match(processor->fib, interestMessage); - if (fibEntry == NULL) { - return false; - } - - PitEntry *pitEntry = pit_GetPitEntry(processor->pit, interestMessage); - if (pitEntry == NULL) { - return false; - } - - pitEntry_AddFibEntry(pitEntry, fibEntry); - - NumberSet *nexthops = (NumberSet *)fibEntry_GetNexthopsFromForwardingStrategy( - fibEntry, interestMessage); - // 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); - } - } - - 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 - if (messageProcessor_AggregateInterestInPit(processor, interestMessage)) { - // done - return; - } - - // 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 - if (messageProcessor_ForwardViaFib(processor, interestMessage)) { - // 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); - } - - // 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/processor/messageProcessor.h b/hicn-light/src/processor/messageProcessor.h deleted file mode 100644 index ce3049938..000000000 --- a/hicn-light/src/processor/messageProcessor.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 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 -#include -#include - -#include - -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); - -/** - * 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); - -#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/processor/pit.c b/hicn-light/src/processor/pit.c deleted file mode 100644 index 9cae4062e..000000000 --- a/hicn-light/src/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 -#include -#include - -#include - -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/processor/pit.h b/hicn-light/src/processor/pit.h deleted file mode 100644 index 1f909be3e..000000000 --- a/hicn-light/src/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 -#include -#include -#include -#include - -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 - * pitEntry_Destory() 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/processor/pitEntry.c b/hicn-light/src/processor/pitEntry.c deleted file mode 100644 index 38103cb8e..000000000 --- a/hicn-light/src/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 -#include - -#include -#include -#include - -#include - -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/processor/pitEntry.h b/hicn-light/src/processor/pitEntry.h deleted file mode 100644 index b7d45e6a4..000000000 --- a/hicn-light/src/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 -#include -#include -#include - -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 message_Release() - * 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 pitEntry_Release() 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 Message_Release() on it. - * - * @return A reference counted copy, call Message_Release() 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/processor/pitStandard.c b/hicn-light/src/processor/pitStandard.c deleted file mode 100644 index 8d507626a..000000000 --- a/hicn-light/src/processor/pitStandard.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 -#include - -#define __STDC_FORMAT_MACROS -#include - -#include -#include - -#include - -#include -#include -#include - -#include - -#include - -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)); - } - - return PITVerdict_Forward; - } - - // 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) { - // this is a rough estimation of the residual RTT - Ticks rtt = forwarder_GetTicks(pit->forwarder) - - pitEntry_GetCreationTime(pitEntry); - fibEntry_ReceiveObjectMessage(fibEntry, pitEntry_GetEgressSet(pitEntry), - objectMessage, - rtt); // need to implement RTT - } - 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/processor/pitStandard.h b/hicn-light/src/processor/pitStandard.h deleted file mode 100644 index b9ba026c8..000000000 --- a/hicn-light/src/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 - -/** - * 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/processor/pitVerdict.h b/hicn-light/src/processor/pitVerdict.h deleted file mode 100644 index 16631fa51..000000000 --- a/hicn-light/src/processor/pitVerdict.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 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 - */ -typedef enum { PITVerdict_Forward, PITVerdict_Aggregate } PITVerdict; -#endif // pitVerdict_h diff --git a/hicn-light/src/socket/CMakeLists.txt b/hicn-light/src/socket/CMakeLists.txt deleted file mode 100644 index 6ea94dcfa..000000000 --- a/hicn-light/src/socket/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -if (UNIX AND NOT APPLE AND NOT ANDROID_API) - list(APPEND HEADER_FILES - socket/api.h - socket/error.h - socket/ops.h - ) - - list(APPEND SOURCE_FILES - socket/api.c - socket/error.c - socket/ops_linux.c - ) -endif() - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/socket/api.c b/hicn-light/src/socket/api.c deleted file mode 100644 index aede01efe..000000000 --- a/hicn-light/src/socket/api.c +++ /dev/null @@ -1,604 +0,0 @@ -#include // inet_ntop -#include // '' -#include // tfind(), tdestroy(), twalk(), preorder... -#include -#include // perror -#include // calloc -#include // memcpy -#include // '' -#include // getaddrinfo -#include // close - -#include "api.h" -#include "error.h" -#include "ops.h" - -#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN - -#define IF_NAMESIZE 16 -#define MAX_TABLES 256 - -#define DEFAULT_INTERVAL 1000 -#define DEFAULT_IDENTIFIER "hicn" -#define DEFAULT_SOCKET_IDENTIFIER "main" -#define LOCAL_IPV6_PREFIX "fe80" - -#define LOCAL_PRIORITY 32000 - -extern hicn_socket_ops_t ops; - -/* Configuration stored as a global variable to allow access from signal - * handlers for instance */ - -static hicn_conf_t hicn_default_conf = { - .identifier = DEFAULT_IDENTIFIER, - //.format = HF_INET6_TCP -}; - -/* Global state */ -// FIXME move into helper state ? - -struct ip_rule_state_ { - char tun_name[IF_NAMESIZE]; - ip_address_t ip_address; - uint32_t table_id; - uint8_t priority; - uint8_t address_family; -}; - -struct ip_route_state_ { - char remote_ip_address[128]; // this is to big, but it is fine for now - uint8_t address_family; - uint32_t table_id; -}; - -typedef struct ip_rule_state_ ip_rule_state; -typedef struct ip_route_state_ ip_route_state; - -int punting_table_id; -uint16_t rules_counter; -uint16_t routes_counter; -static ip_rule_state rules_to_remove[MAX_TABLES]; -static ip_route_state routes_to_remove[MAX_TABLES]; - -// END FIXME - -hicn_socket_helper_t *hicn_create() { - int rc; - - punting_table_id = -1; - rules_counter = 0; - - hicn_socket_helper_t *hicn = malloc(sizeof(hicn_socket_helper_t)); - if (!hicn) { - goto ERR_MALLOC; - } - - hicn->conf = malloc(sizeof(hicn_conf_t)); - if (hicn->conf < 0) goto ERR_CONF; - memcpy(hicn->conf, &hicn_default_conf, sizeof(hicn_conf_t)); - - /* Initialize socket tree to empty */ - hicn->socket_root = NULL; - - // enable forwarding globally. Per-interface forwarding will be enabled when - // interfaces are created (TODO) - rc = ops.enable_v6_forwarding(NULL); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.enable_v4_forwarding(); - if (rc < 0) { - goto ERR_FW; - } - - // modify priority of table local - /* ip -6 rule del from all prio 0 table local */ - /* ip -6 rule add from all prio 32000 table local */ - - rc = ops.del_lo_prio_rule(NULL, AF_INET6, 0); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.del_lo_prio_rule(NULL, AF_INET, 0); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR_FW; - } - - return hicn; - -ERR_FW: - free(hicn->conf); -ERR_CONF: - free(hicn); -ERR_MALLOC: - return NULL; -} - -void hicn_destroy() { - int rc; - uint16_t i; - - /* Restore default rules */ - printf("Restoring default configuration.\n"); - rc = ops.del_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR; - } - - rc = ops.del_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET6, 0); - if (rc < 0) { - goto ERR; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET, 0); - if (rc < 0) { - goto ERR; - } - - for (i = 0; i < rules_counter; i++) { - if (strcmp(rules_to_remove[i].tun_name, "NONE") != 0) { - rc = ops.del_rule(rules_to_remove[i].tun_name, - rules_to_remove[i].address_family, - rules_to_remove[i].table_id); - if (rc < 0) { - goto ERR; - } - } else { - rc = ops.del_prio_rule( - &rules_to_remove[i].ip_address, rules_to_remove[i].address_family, - rules_to_remove[i].priority, rules_to_remove[i].table_id); - if (rc < 0) { - goto ERR; - } - } - } - - 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) { - goto ERR; - } - } - -ERR: - if (rc < 0) printf("Unexpected exit. Some state may not be deleted.\n"); - return; -} - -void hicn_free(hicn_socket_helper_t *hicn) { - // close tun ? - free(hicn); -} - -hicn_socket_t *hicn_socket_create() { - hicn_socket_t *socket = calloc(1, sizeof(hicn_socket_t)); - if (!socket) { - goto ERR_SOCKET; - } - socket->type = HS_UNSPEC; - - return socket; - -ERR_SOCKET: - return NULL; -} - -int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) { - return b->fd - a->fd; -} - -ip_address_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { - if (socket->type != HS_CONNECTION) { - return NULL; - } - return &socket->connection.tun_ip_address; -} - -typedef int (*cmp_t)(const void *, const void *); - -int hicn_socket_add(hicn_socket_helper_t *hicn, hicn_socket_t *socket) { - if (!(tsearch(socket, &hicn->socket_root, (cmp_t)hicn_socket_cmp))) { - // ERROR("Could not insert field id into index"); - return -1; - } - return 0; -} - -hicn_socket_t *hicn_socket_find(hicn_socket_helper_t *hicn, int fd) { - hicn_socket_t search = { - .fd = fd, - }; - hicn_socket_t **socket = - tfind(&search, &hicn->socket_root, (cmp_t)hicn_socket_cmp); - return socket ? *socket : NULL; -} - -/******************************************************************************* - * New API - *******************************************************************************/ - -int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address, - bool allow_null) { - int rc = HICN_SOCKET_ERROR_NONE; - - if (!local_ip_address) { - if (!allow_null) { - rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_NULL_ADDRESS; - } - goto end; - } - - /* local_ip_address should be a prefix with global scope in which to pick - * the locator address to use as the source. - * If we expect to pick another IP for the tun, then it needs to be of size - * less than 128. - */ - - /* Copy the local IP address inside the connection */ - rc = hicn_ip_pton(local_ip_address, &socket->connection.tun_ip_address); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR; - goto end; - } - -end: - return rc; -} - -// XXX This could be used by hicn_set_remote_endpoint -// XXX This has been introduced for mapme -int hicn_get_local_address(const ip_address_t *remote_address, - ip_address_t *local_address) { - int rc = 0; - uint32_t interface_id; - char remote_address_str[INET_MAX_ADDRSTRLEN]; - - rc = hicn_ip_ntop(remote_address, remote_address_str, - sizeof(remote_address_str)); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; - goto ERR; - } - - rc = ops.get_output_ifid(remote_address_str, remote_address->family, - &interface_id); - if (rc < 0 || interface_id == 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_INTERFACE; - goto ERR; - } - - /* Local ip */ - rc = ops.get_ip_addr(interface_id, remote_address->family, local_address); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_NETMASK; - goto ERR; - } - -ERR: - return rc; -} - -/** - * - * sets socket->interface_id - */ -int hicn_set_remote_endpoint(hicn_socket_t *socket, - const char *remote_ip_address) { - int af, rc = HICN_SOCKET_ERROR_NONE; - ip_address_t addr; - - af = get_addr_family(remote_ip_address); - if ((af != AF_INET6) && (af != AF_INET)) { - return HICN_SOCKET_ERROR_INVALID_IP_ADDRESS; - } - - /* Bind local endpoint if not done yet */ - if (ip_address_empty(&socket->connection.tun_ip_address)) { - char local_ip_address[INET_MAX_ADDRSTRLEN]; - - /* Local interface id */ - // INFO("Getting interface_id from gateway IP address %s", - // remote_ip_address); - ///// - int addr_family = get_addr_family(remote_ip_address); - if (addr_family < 0) { - rc = addr_family; - goto ERR; - } - - rc = ops.get_output_ifid(remote_ip_address, (uint8_t)addr_family, - &socket->connection.interface_id); - if (rc < 0 || socket->connection.interface_id == 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_INTERFACE; - goto ERR; - } - - /* Local ip */ - rc = ops.get_ip_addr(socket->connection.interface_id, (uint8_t)addr_family, - &addr); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_NETMASK; - goto ERR; - } - ///// - - /* Convert to representation format */ - rc = hicn_ip_ntop(&addr, local_ip_address, sizeof(local_ip_address)); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; - goto ERR; - } - - rc = hicn_set_local_endpoint(socket, local_ip_address, true); - if (rc < 0) { - switch (rc) { - case HICN_SOCKET_ERROR_SOCKET_LOCAL_NULL_ADDRESS: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_NULL_ADDR; - break; - case HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_REPR; - break; - case HICN_SOCKET_ERROR_SOCKET_LOCAL_HEURISTIC: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_HEURISTIC; - break; - case HICN_SOCKET_ERROR_SOCKET_LOCAL_SET_TUN_IP: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_SET_TUN_IP; - break; - } - goto ERR; - } - } - return HICN_SOCKET_ERROR_NONE; - -ERR: - return rc; -} - -/** - * - * We need at least an identifier. - */ -int hicn_socket(hicn_socket_helper_t *hicn, const char *identifier, - const char *local_ip_address) { - int rc; - - hicn_socket_t *socket = hicn_socket_create(); - if (!socket) { - rc = -5; - goto ERR_SOCKET; - } - - ops.get_tun_name(hicn->conf->identifier, identifier, socket->tun_name); - - // register the hicn face on which to bind prefixes, create the in/out TUN - // device - socket->fd = ops.tun_create(socket->tun_name); - if (socket->fd <= 0) { - rc = -2; - goto ERR_TUN; - } - - // INFO("Successfully created listener on TUN device %s", socket->tun_name); - - /* Retrieve interface id */ - socket->tun_id = ops.get_ifid(socket->tun_name); - if (socket->tun_id < 0) { - rc = -3; - goto ERR_TUNIFID; - } - // INFO("Interface id=%d", socket->tun_id); - - // WARN("Need to set offload"); - - // INFO("Setting interface up"); - rc = ops.up_if(socket->tun_id); - if (rc < 0) { - rc = -4; - goto ERR_UP; - } - - /* Update state */ - rc = hicn_socket_add(hicn, socket); - if (rc < 0) { - rc = -5; - goto ERR_ADD; - } - - rc = hicn_set_local_endpoint(socket, local_ip_address, true); - if (rc < 0) { - rc = -6; - goto ERR_ADJACENCY; - } - - return socket->fd; - -ERR_ADJACENCY: -ERR_ADD: -ERR_UP: -ERR_TUNIFID: -ERR_TUN: - free(socket); -ERR_SOCKET: - // ERR_PARAMS: - return rc; -} - -int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { - int rc; - hicn_socket_t *socket = hicn_socket_find(hicn, fd); - if (!socket) { - return -1; - } - - /* Check socket is not a connection */ - if (socket->type == HS_CONNECTION) { - return -1; - } - - rc = ops.add_in_route_s(prefix, socket->tun_id); - if (rc < 0) { - return rc; - } - - ip_address_t ip_address; - rc = hicn_ip_pton(prefix, &ip_address); - if (rc < 0) { - return rc; - } - - // ip -6 rule add from b001::/16 prio 0 table 100 - socket->connection.table_id = - socket->tun_id % MAX_TABLES; // this table should be unused - - if (punting_table_id == -1) punting_table_id = socket->connection.table_id; - - rc = ops.add_prio_rule(&ip_address, ip_address.family, 0, - socket->connection.table_id); - if (rc < 0) { - return rc; - } - - strcpy(rules_to_remove[rules_counter].tun_name, "NONE"); - - rules_to_remove[rules_counter].ip_address = ip_address; - rules_to_remove[rules_counter].address_family = ip_address.family; - rules_to_remove[rules_counter].table_id = socket->connection.table_id; - rules_to_remove[rules_counter].priority = 0; - ++rules_counter; - - /* Update socket upon success */ - socket->type = HS_LISTENER; - - return 0; -} - -/** - * - * We can pass all adjacency parameters but identifier - */ -int hicn_bind(hicn_socket_helper_t *hicn, int fd, - const char *remote_ip_address) { - // uint32_t interface_id; - int rc = HICN_SOCKET_ERROR_NONE; - - hicn_socket_t *socket = hicn_socket_find(hicn, fd); - if (!socket) { - rc = HICN_SOCKET_ERROR_BIND_SOCKET_NOT_FOUND; - goto ERR; - } - - /* We allow reuse */ - if (socket->type == HS_CONNECTION) return rc; - - /* Check socket is not a connection */ - if (socket->type != HS_UNSPEC) { - rc = HICN_SOCKET_ERROR_BIND_SOCKET_ALREADY_BOUND; - goto ERR; - } - socket->type = HS_CONNECTION; - - // each connection is associated a table id, let's take it equal to the - // tun ID by default (% MAX_TABLES, assuming TUN IDs do not overlap modulo - // 256...). - // XXX we need to make sure the corresponding table is flushed. - socket->connection.table_id = - socket->tun_id % MAX_TABLES; // interface_id; // ops.get_free_table_id(); - - // XXX use IP address - rc = hicn_set_remote_endpoint(socket, remote_ip_address); - if (rc < 0) { - goto ERR; - } - - // rule - // ip -6 rule from all iif eth0 lookup 200 - // INFO("Adding output rule for %s in table %d", socket->tun_name, - // socket->connection.table_id); - int addr_family = get_addr_family(remote_ip_address); - if (addr_family < 0) { - rc = addr_family; - goto ERR; - } - - rc = ops.add_rule(socket->tun_name, (uint8_t)addr_family, - socket->connection.table_id); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_RULE; - goto ERR; - } - - strcpy(rules_to_remove[rules_counter].tun_name, socket->tun_name); - rules_to_remove[rules_counter].address_family = addr_family; - rules_to_remove[rules_counter].table_id = socket->connection.table_id; - ++rules_counter; - - // route - // ip -6 route add default via 2002::2 table 28 - // INFO("Adding output route in table %d via gateway %s", - // socket->connection.table_id, - // remote_ip_address); - - // if the address is an IPv6 and start with fe80 we need to specify the device - // in the route - u32 default_interface = ~0; - if (addr_family == AF_INET6 && strncmp(LOCAL_IPV6_PREFIX, remote_ip_address, - strlen(LOCAL_IPV6_PREFIX)) == 0) { - rc = ops.get_output_ifid(remote_ip_address, (uint8_t)addr_family, - &default_interface); - if (rc < 0) { - goto ERR; - } - } - - rc = ops.add_out_route(remote_ip_address, (uint8_t)addr_family, - socket->connection.table_id, default_interface); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_ROUTE; - goto ERR; - } - - strcpy(routes_to_remove[routes_counter].remote_ip_address, remote_ip_address); - routes_to_remove[routes_counter].table_id = socket->connection.table_id; - routes_to_remove[routes_counter].address_family = (uint8_t)addr_family; - ++routes_counter; - - // add route for data - // ip -6 route add 0:1::/64 dev hicn-if0 table 100 - // this routes are deleted by removing the tun interfaces - - if (punting_table_id == -1) { - // the punting_table_id was not initialized beacause no main-tun was created - // we use as an id (socket->tun_id - 1) % MAX_TABLES, so that we will hava a - // collision only after 255 new interfaces - punting_table_id = (socket->tun_id - 1) % MAX_TABLES; - } - rc = ops.add_in_route_table(&socket->connection.tun_ip_address, - socket->tun_id, punting_table_id); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_ROUTE; - goto ERR; - } - -ERR: - return rc; -} diff --git a/hicn-light/src/socket/api.h b/hicn-light/src/socket/api.h deleted file mode 100644 index 3a1ae92b4..000000000 --- a/hicn-light/src/socket/api.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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_face.h - * @brief hICN socket library - * - * This module provides an interface to managing so-called hICN sockets, - * realizing punting of interest and data packets using a TUN device. - */ - -#ifndef HICN_SOCKET_API_H -#define HICN_SOCKET_API_H - -#include // uint*_t -#include - -#include -#include "error.h" - -#define BUFSIZE 4096 -#define MAX_CONNECTIONS \ - 255 // We currently limit the number of connections we can establish -#ifndef IF_NAMESIZE -#define IF_NAMESIZE 16 -#endif -/* hICN socket helper */ - -/** hICN configuration options */ -typedef struct { - // uint32_t interval; - - /* Identifier used to name hICN TUN interfaces (should be unique) */ - char *identifier; - // hicn_format_t format; - -} hicn_conf_t; - -/** - * hICN adjacency - */ -typedef struct { - char *local_ip_address; - char *gateway_ip_address; -} hicn_adjacency_t; - -#define EMPTY_HICN_ADJACENCY \ - (hicn_adjacency_t) { 0, 0 } - -/* hICN socket operations */ - -typedef struct { - uint8_t pkbuf[BUFSIZE]; - uint32_t rb_pkbuf_r; - uint32_t rb_pkbuf_w; -} hicn_buffer_t; - -typedef enum { HS_UNSPEC, HS_LISTENER, HS_CONNECTION } hicn_socket_type_t; - -typedef struct hicn_socket_s { - hicn_socket_type_t type; - int fd; - - /* Implementation specific state follows */ - char tun_name[IF_NAMESIZE]; - uint32_t tun_id; - - hicn_buffer_t buffer; - void (*cb)(struct hicn_socket_s *, void *, uint8_t *, size_t); - void *cb_data; - - union { - struct { - ip_address_t tun_ip_address; - uint32_t interface_id; - - /* ID of the corresponding table : avoid default values of 0, 32766 and - * 32767 */ - uint8_t table_id; - } connection; - }; -} hicn_socket_t; - -/** - * hICN global state - */ -typedef struct { - /* Configuration data */ - hicn_conf_t *conf; - - // We need state associate to each FD, to know what type of socket it is and - // its state. - void *socket_root; /**< A tree of socket indexed by their fd */ - -} hicn_socket_helper_t; - -/** - * Create an hICN instance. - * - * This is used to configure the state of an hICN router consistently between - * a listener and the different connections. It also regroups all the state - * related to hICN functionalities. - * - * @return A pointer to an hICN instance. - */ -hicn_socket_helper_t *hicn_create(); - -void hicn_destroy(); - -/** - * Retrieve hICN configuration. - * - * Gets the current configuration of an hICN instance for information purposes, - * or later update it. - * - * TODO - * - We might want to prevent configuration updates while the hICN instance is - * running. Define running... - * - * @param [in] hicn Pointer to hICN instance. - * @return Pointer to an hICN configuration data structure. - * - * @see hicn_set_conf - */ -hicn_conf_t *hicn_get_conf(hicn_socket_helper_t *hicn); - -/** - * Update hICN configuration. - * - * @param [in] hicn Pointer to an hICN instance. - * @param [in] hicn_conf Pointer to an hICN configuration data structure. - * @return 0 in case of success, -1 otherwise. - * - * @see hicn_get_conf - */ -int hicn_set_conf(hicn_socket_helper_t *hicn, hicn_conf_t *hicn_conf); - -/** - * Release hICN state. - * - * @param [in] hicn Pointer to an hICN instance. - */ -void hicn_free(hicn_socket_helper_t *hicn); - -// FIXME doc -int hicn_get_local_address(const ip_address_t *remote_address, - ip_address_t *local_address); - -/* hICN socket */ - -/** - * Create an hICN socket. - * - * An hICN socket abstracts the underlying implementation and allows hICN - * packets to be sent and received independently of the underlying - * implementation. - * - * It is possible to further specialize the socket in a listener socket, and a - * connection socket. - * - * @param [in] hicn Pointer to an hICN instance. - * @param [in] identifier Unique identifier for this socket, used to named the - * TUN device - * @param [in] local_ip_address IP address used locally by the socket (or NULL - * for letting the library decide automatically). - * @return File descriptor (>0) in case of success, -1 otherwise. - * - * @see hicn_listen - * @see hicn_bind - */ -int hicn_socket(hicn_socket_helper_t *hicn, const char *identifier, - const char *local_ip_address); - -/** - * Packet punting. - * - * Note that we cannot listen on a socket that is already bound. - * - * @param [in] hicn Pointer to an hICN instance. - * @param [in] fd File descriptor identifying the hICN socket. - * @param [in] prefix Prefix (IPv4 or IPv6) to be bound to hICN in - * RFC-compliant presentation format. - * @return 0 in case of success, -1 otherwise. - * - * @see hicn_socket - */ -int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix); - -/** - * Packet forwarding - * @param [in] hicn Pointer to an hICN instance. - * @param [in] fd File descriptor identifying the hICN socket. - * @param [in] prefix Prefix (IPv4 or IPv6) to be bound to hICN in - * RFC-compliant presentation format. - * @return 0 in case of success, -1 otherwise. - * - * XXX adjacency does not perform any copy heresofar - * - * @see hicn_socket - */ -int hicn_bind(hicn_socket_helper_t *hicn, int fd, - const char *remote_ip_address); - -#endif /* HICN_SOCKET_API_H */ diff --git a/hicn-light/src/socket/error.c b/hicn-light/src/socket/error.c deleted file mode 100644 index 3dafec8cf..000000000 --- a/hicn-light/src/socket/error.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "error.h" - -const char* HICN_SOCKET_ERROR_STRING[] = { -#define _(a, b, c) [b] = c, - foreach_hicn_socket_error -#undef _ -}; diff --git a/hicn-light/src/socket/error.h b/hicn-light/src/socket/error.h deleted file mode 100644 index 8195efd84..000000000 --- a/hicn-light/src/socket/error.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef HICN_SOCKET_ERROR_H -#define HICN_SOCKET_ERROR_H - -// FIXME remove unused errors -#define foreach_hicn_socket_error \ - _(NONE, 0, "OK") \ - _(UNSPEC, 1, "unspecified error") \ - _(NOT_HICN, 2, "not a hICN paclet") \ - _(UNKNOWN_ADDRESS, 10, "unknown address") \ - _(INVALID_PARAMETER, 20, "invalid parameter") \ - _(INVALID_IP_ADDRESS, 21, "invalid IP address") \ - _(CORRUPTED_PACKET, 22, "corrupted packet") \ - _(UNEXPECTED, 98, "unexpected error") \ - _(NOT_IMPLEMENTED, 99, "not implemented") \ - _(SOCKET_LOCAL_NULL_ADDRESS, 101, "empty local address") \ - _(SOCKET_LOCAL_REPR, 102, "cannot represent local address") \ - _(SOCKET_LOCAL_HEURISTIC, 103, "error finding local address") \ - _(SOCKET_LOCAL_SET_TUN_IP, 104, "cannot set local IP to TUN") \ - _(BIND_SOCKET_NOT_FOUND, 301, "bind: socket not found") \ - _(BIND_SOCKET_ALREADY_BOUND, 302, "bind: socket already bound") \ - _(BIND_REMOTE_INTERFACE, 303, "bind: no interface towards gateway") \ - _(BIND_REMOTE_NETMASK, 304, "bind: no local IP with netmask < 128") \ - _(BIND_REMOTE_REPR, 305, "bind: error representing local IP") \ - _(BIND_REMOTE_LOCAL_NULL_ADDR, 306, "bind: could not set local endpoint") \ - _(BIND_REMOTE_LOCAL_REPR, 307, "bind: error representing remote IP") \ - _(BIND_REMOTE_LOCAL_HEURISTIC, 308, "bind: could not apply heuristic") \ - _(BIND_REMOTE_LOCAL_SET_TUN_IP, 309, "bind: error setting local IP to TUN") \ - _(BIND_NDP, 310, "bind: could not enable NDP proxy") \ - _(BIND_NEIGH_PROXY, 311, "bind: could not neighbour") \ - _(BIND_REPR, 312, "bind: error represeting IP") \ - _(BIND_LO, 313, "bind: could not remove local route") \ - _(BIND_RULE, 314, "bind: could not add rule") \ - _(BIND_ROUTE, 315, "bind: could not add output route") - -typedef enum { -#define _(a, b, c) HICN_SOCKET_ERROR_##a = (-b), - foreach_hicn_socket_error -#undef _ - HICN_SOCKET_N_ERROR, -} hicn_socket_error_t; - -extern const char *HICN_SOCKET_ERROR_STRING[]; - -#define hicn_socket_strerror(errno) (char *)(HICN_SOCKET_ERROR_STRING[-errno]) - -#endif /* HICN_SOCKET_ERROR_H */ diff --git a/hicn-light/src/socket/ops.h b/hicn-light/src/socket/ops.h deleted file mode 100644 index 249caf87a..000000000 --- a/hicn-light/src/socket/ops.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef HICN_SOCKET_OPS_H -#define HICN_SOCKET_OPS_H - -#include -#include - -typedef struct { - char *arch; - int (*tun_create)(char *name); - int (*get_tun_name)(const char *prefix, const char *identifier, - char *tun_name); - int (*enable_v6_forwarding)(char *interface_name); - int (*enable_v4_forwarding)(); - int (*enable_ndp_proxy)(); - - uint32_t (*get_ifid)(const char *ifname); - 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_address_t *ip_address); - int (*set_ip_addr)(uint32_t interface_id, ip_address_t *ip_address); - int (*up_if)(uint32_t interface_id); - int (*add_in_route_table)(const ip_address_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, - const uint8_t table_id); - int (*add_in_route_s)(const char *prefix, const uint32_t interface_id); - int (*add_out_route)(const char *gateway, const uint8_t address_family, - 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_address_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_address_t *ip_address, - const uint32_t interface_id); - int (*add_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority, - const uint8_t table_id); - int (*add_lo_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, - const uint32_t priority); - int (*del_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority, - const uint8_t table_id); - int (*del_lo_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, - const uint32_t priority); -} hicn_socket_ops_t; - -#endif /* HICN_SOCKET_OPS_H */ diff --git a/hicn-light/src/socket/ops_linux.c b/hicn-light/src/socket/ops_linux.c deleted file mode 100644 index d085f0d3d..000000000 --- a/hicn-light/src/socket/ops_linux.c +++ /dev/null @@ -1,1723 +0,0 @@ -#include // ioctl -#include // needed by linux/if.h -//#include -#include -#include // '' -#include -#include // PATH_MAX -#include // fprintf -#include // memset -#include // open -#include // writev -#include // close - -#include "error.h" -#include "ops.h" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) - -/****************************************************************************** - * netlink.h - ******************************************************************************/ - -#ifndef HICN_NETLINK_H -#define HICN_NETLINK_H - -#include -#include - -// DEPRECATED|/* Socket */ -// DEPRECATED|int _nl_get_socket(); -// DEPRECATED|int _nl_send(int s, uint8_t * buffer, size_t len); -// DEPRECATED|size_t _nl_receive(uint8_t * buffer, size_t len); -// DEPRECATED| -// DEPRECATED|/* Netlink packet format */ -// DEPRECATED|int _nl_header(int request, uint8_t * buffer, size_t len, uint32_t -// flags); DEPRECATED|int _nl_payload_rule(uint8_t table_id, uint8_t * buffer, -// size_t len); DEPRECATED|int _nl_payload_link(uint32_t ifindex, uint8_t * -// buffer, size_t len); DEPRECATED|int _nl_payload_route(uint8_t table_id, -// uint8_t dst_len, uint8_t * buffer, size_t len); DEPRECATED| DEPRECATED|int -// _nl_parse(uint8_t * buffer, size_t len); DEPRECATED|int _nl_parse_ret(uint8_t -// * buffer, size_t len); DEPRECATED|int _nl_parse_link_ifid(uint8_t * buffer, -// size_t len, uint32_t * interface_id); DEPRECATED|int -// _nl_parse_link_ip_addr(uint8_t * buffer, size_t len, struct in6_addr * addr); - -/* Public interface */ - -/** - * Get the interface ID of an interface by its name - * - * @return 32-bit interface identifier in case of success, or 0. - * - * @see if_nametoindex - * - */ -uint32_t _nl_get_ifid(const char *ifname); - -/** - * Retrieve the output interface corresponding to the specified IP address. - * - * @param [in] addr IP(v6) address in presentation form. - * @param [out] Identifier of the corresponding output interface. - * @return int 0 in case of success, -1 otherwise - */ -int _nl_get_output_ifid(const char *ip_address, uint8_t address_family, - uint32_t *interface_id); - -/** - * Retrieve the first IP address of an interface (identified by its id) which - * has a netmask < 128. - * - * @param [in] s File descriptor of the netlink socket (deprecated). - * @param [in] interface_id Identifier of the interface for which to retrieve - * the IP address. - * @param [out] addr IP(v6) address in binary form. - * @return int 0 in case of success, -1 otherwise - * - * @see getifaddrs - */ -int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_address_t *ip_address); - -int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address); - -int _nl_up_if(uint32_t interface_id); - -int _nl_add_in_route_table(const ip_address_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); -int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id); - -int _nl_add_out_route(const char *gateway, const uint8_t address_family, - const uint8_t table_idi, int default_route); -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_address_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_address_t *ip_address, - const uint32_t interface_id); - -int _nl_add_prio_rule(const ip_address_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_address_t *ip_address, - const uint8_t address_family, const uint32_t priority); -int _nl_del_prio_rule(const ip_address_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_address_t *ip_address, - const uint8_t address_family, const uint32_t priority); - -#endif /* HICN_NETLINK_H */ - -/****************************************************************************** - * netlink.c - ******************************************************************************/ - -/* - * This module offers an interface to the Netlink API appropriate for - * implementing punting as required by hICN (1). - * - * More specifically, it consists of the following functionalities: - * - LINK - . map interface name to ID - . set and interface up - * - ADDR - . get and set ip addresses on a given interface ID - * - ROUTE - . get output interface id towards IP (ip route get IP > interface_id) - . add input route (ip route add PREFIX dev INTERFACE) for punting - interests . add output route (ip route add default GATEWAY table TABLE) for - routing interests (2, 3) . delete local route towards IP (ip route del IP table - local) for ??? - /!\ could this be avoided by removing the local attribute in the - netlink call ? - * - RULE - * . add output rule (ip rule add iif interface table TABLE) for routing - interests (2, 3) - * - ND PROXY - * . enable NDP proxy functionality for IP on interface ID (ip -6 neigh add - proxy IP dev INTERFACE) - * for allowing the TUN to be reachable on the reverse data path - * - * Implementation notes: - * (1) We have not been using the libnl library because it requires - * manipulating too many function and data structures for a simple purpose. - * Currently, many parts of the code are somehow repetitive, but this might - * be improved by a proper API in a future release. - * (2) allows load balancing over different interfaces = multihoming. Please - * note that it is not possible to have load balancing over two faces using - * the same output interface as we are using the underlying IP network ! - * This might be mitigated with the use of SR however. - * (3) The implementation of punting heavily uses the policy routing - * functionalities, as we need to hook through a TUN into user space a - * whole prefix used as a destination (for interests) or source (for data - * packets). We thus combine the use of rules to assign routing table IDs, - * and routes inside those tables. As there is no easy way to allocate - * which routing tables we use, we made the choice to index them by the ID - * of the interface, assuming there is no external conflict. This might be - * improved in the future. - * - * This hICN implementation uses TUNs in two different ways: - * - a main TUN interface, which receives all punted interests, - * demultiplex them before assigning them an input face (eventually - * dynamically creating it); - * - a set of output TUN interfaces, aka faces, used for routing of - * interests, and for receiving the corresponding data packets on the way - * back. Punting of data packets if based of their destination IP, which - * is the IP of the physical output interface used for the interest, which - * is unique (cf (2)). - * - * The corresponding routing tables IDs are : - * MAIN_TUN_ID -> used for punting of data packets - * OUTPUT_TUN_ID_i -> used for routing of interests towards next hop - * (bypassing local IP routing table) - * - * Note that punting of interests is done just through a route, and routing - * of data packets is done just through the regular IP routing table on the - * note after the address translation done in the forwarder. - * - * - Forging netlink packets - * - * A previous implementation used function calls with pointers to populate - * the various header parts in a buffer in order to build a netlink packet. - * A newer implementation uses nested structs and iovecs to build the whole - * packet in a single write call. This should allow a simpler evolution - * towards a cleaner API. - */ - -#include // inet_pton -#include // errno -#include // fib_rule_hdr, FRA_* -#include -#include -#include // IFF_UP -#include // in6addr -#include // perror -#include -#include // '' -#include // socket -#include // read - -#include // '' -#include // send, recv - -//#include "../../hicn.h" -//#include "../../hicn_util.h" // ARRAY_SIZE, hicn_packet_dump_iov - -#define BUFSIZE 4096 -#define FLAGS_CREATE NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK -// ?? -#define FLAGS_CREATE_MATCH \ - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_MATCH - -// XXX putting ACK poses a prolem for the value received by get_if_id. -#define FLAGS_GET NLM_F_REQUEST -#define FLAGS_GET_ROOT (NLM_F_REQUEST | NLM_F_ROOT) - -#define FLAGS_LIST NLM_F_REQUEST | NLM_F_DUMP - -#define IF_NAMESIZE 16 -#define FR_ACT_TO_TBL 1 -#define NLMSG_BOTTOM(nlmsg) \ - ((struct rtattr *)(((void *)(nlmsg)) + NLMSG_ALIGN((nlmsg)->nlmsg_len))) - -int seq = 1; - -static inline size_t iov_length(const struct iovec *iov, - unsigned long nr_segs) { - unsigned long seg; - size_t ret = 0; - - for (seg = 0; seg < nr_segs; seg++) ret += iov[seg].iov_len; - return ret; -} - -typedef struct { - struct nlmsghdr hdr; - struct nlmsgerr payload; -} nl_err_hdr_t; - -/* Low level : nl header */ - -int _nl_get_socket() { return socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); } - -int _nl_header(int request, uint8_t *buffer, size_t len, uint32_t flags) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - - nl->nlmsg_len = 0; // NLMSG_LENGTH(sizeof(struct ifinfomsg)); - nl->nlmsg_type = request; - nl->nlmsg_flags = flags; - nl->nlmsg_seq = seq++; // - nl->nlmsg_pid = 0; // getpid(); - - return 0; -} - -/* Low level : nl protocols */ - -/* Low level : attributes */ - -int addAttr(struct nlmsghdr *nl, int maxlen, int type, void *data, - int attr_len) { - struct rtattr *rta; - int len = RTA_LENGTH(attr_len); - - if (NLMSG_ALIGN(nl->nlmsg_len) + len > maxlen) { - exit(EXIT_FAILURE); - } - - rta = (struct rtattr *)((char *)nl + NLMSG_ALIGN(nl->nlmsg_len)); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), data, attr_len); - nl->nlmsg_len = NLMSG_ALIGN(nl->nlmsg_len) + len; - return 0; -} - -int _nl_payload_rule(uint8_t table_id, uint8_t address_family, uint8_t *buffer, - size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct fib_rule_hdr *frh = (struct fib_rule_hdr *)(NLMSG_DATA(buffer)); - - memset(frh, 0, sizeof(struct fib_rule_hdr)); - frh->family = address_family; - frh->table = table_id; - frh->action = FR_ACT_TO_TBL, - frh->flags = NLM_F_REPLACE; // 0 - frh->tos = 0; - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct fib_rule_hdr)); - - return 0; -} - -int _nl_payload_link(uint32_t ifindex, uint8_t *buffer, size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct ifinfomsg *ifi = (struct ifinfomsg *)(NLMSG_DATA(buffer)); - - memset(ifi, 0, sizeof(struct ifinfomsg)); - ifi->ifi_family = AF_UNSPEC; - // ifi->ifi_type = 0; - ifi->ifi_index = - ifindex; // new interface, could be specified since linux 3.7 - ifi->ifi_flags = 0; - // ifi->ifi_change = 0xffffffff; - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct ifinfomsg)); - - return 0; -} - -int _nl_payload_addr(uint32_t ifindex, uint8_t *buffer, size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct ifaddrmsg *addr = (struct ifaddrmsg *)(NLMSG_DATA(buffer)); - - memset(addr, 0, sizeof(struct ifaddrmsg)); - addr->ifa_family = AF_UNSPEC; // INET6; - /* - addr->ifa_prefixlen = 128; - addr->ifa_flags = 0; - addr->ifa_scope = RT_SCOPE_LINK; //IFA_ADDRESS; - addr->ifa_index = ifindex; - */ - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct ifaddrmsg)) - 4; - - return 0; -} - -int _nl_payload_route(uint8_t table_id, uint8_t addr_family, uint8_t dst_len, - uint8_t *buffer, size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct rtmsg *raddr = (struct rtmsg *)(NLMSG_DATA(buffer)); - - raddr->rtm_family = addr_family; - raddr->rtm_dst_len = dst_len; - raddr->rtm_src_len = 0; - raddr->rtm_tos = 0; - - raddr->rtm_table = table_id; - raddr->rtm_protocol = RTPROT_BOOT; - raddr->rtm_scope = RT_SCOPE_UNIVERSE; - raddr->rtm_type = RTN_UNICAST; - - raddr->rtm_flags = 0; - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct rtmsg)); - - return 0; -} - -uint32_t _nl_get_ifid(const char *interface_name) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - size_t len = interface_name ? strlen(interface_name) + 1 : 0; - uint8_t padding[RTA_ALIGNTO] = {0, 0, 0, 0}; - - if (len == 0) { - goto ERR_IF; - } - - struct { - struct nlmsghdr hdr; - struct ifinfomsg payload; - } msg = {//.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), - .hdr.nlmsg_type = RTM_GETLINK, - .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 iovec iov[] = {{&msg, sizeof(msg)}, - {&a_ifname, sizeof(a_ifname)}, - {(char *)interface_name, len}, - {padding, RTA_SPACE(len) - RTA_LENGTH(len)}}; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; /* Unexpected */ - } - - for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { - struct ifinfomsg *payload = (struct ifinfomsg *)NLMSG_DATA(hdr); - return payload->ifi_index; - } - return 0; - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: -ERR_IF: - return 0; -} - -int _nl_get_output_ifid(const char *ip_address, uint8_t family_address, - uint32_t *interface_id) { - int rc; - - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - if (family_address == AF_INET6) { - struct in6_addr addr; // V6SPECIFIC - - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_GETROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = AF_INET6, - .payload.rtm_dst_len = IPV6_ADDR_LEN_BITS, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = RT_TABLE_UNSPEC, - .payload.rtm_protocol = RTPROT_UNSPEC, - .payload.rtm_scope = RT_SCOPE_UNIVERSE, - .payload.rtm_type = RTN_UNSPEC, - .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' - }; - - /* Convert the IP address to binary form */ - rc = inet_pton(AF_INET6, ip_address, &addr); - if (rc <= 0) { - goto ERR; - } - - /* Set attribute = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(16), RTA_DST}; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - {&a_dst, sizeof(a_dst)}, // attribute - {&addr, sizeof(addr)} // value - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } else if (family_address == AF_INET) { - struct in_addr addr; - - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_GETROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = AF_INET, - .payload.rtm_dst_len = IPV4_ADDR_LEN_BITS, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = RT_TABLE_UNSPEC, - .payload.rtm_protocol = RTPROT_UNSPEC, - .payload.rtm_scope = RT_SCOPE_UNIVERSE, - .payload.rtm_type = RTN_UNSPEC, - .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' - }; - - /* Convert the IP address to binary form */ - rc = inet_pton(AF_INET, ip_address, &addr); - if (rc <= 0) { - goto ERR; - } - - /* Set attribute = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(4), RTA_DST}; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - {&a_dst, sizeof(a_dst)}, // attribute - {&addr, sizeof(addr)} // value - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } else { - goto ERR; - } - - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - return HICN_SOCKET_ERROR_UNEXPECTED; /* Unexpected */ - } - - for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { - struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(hdr); - int attrlen = RTM_PAYLOAD(hdr); - struct rtattr *rta; - for (rta = RTM_RTA(rtm); RTA_OK(rta, attrlen); - rta = RTA_NEXT(rta, attrlen)) { - if (rta->rta_type == RTA_OIF) { - *interface_id = *(uint32_t *)RTA_DATA(rta); - return HICN_SOCKET_ERROR_NONE; - } - } - } - - return HICN_SOCKET_ERROR_NONE; - -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_address_t *ip_address) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - struct { - struct nlmsghdr hdr; - struct ifaddrmsg payload; - } msg = {.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), - .hdr.nlmsg_type = RTM_GETADDR, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT, // | NLM_F_MATCH, - .payload.ifa_family = address_family, - .payload.ifa_index = 0}; - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, &msg, sizeof(msg), 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return -99; /* Unexpected */ - } - - for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { - struct ifaddrmsg *payload = (struct ifaddrmsg *)NLMSG_DATA(hdr); - - if (address_family == AF_INET6) { - if ((payload->ifa_index == interface_id) && - (payload->ifa_prefixlen < IPV6_ADDR_LEN * 8)) { - printf("got ip address\n"); - memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV6_ADDR_LEN); - ip_address->family = AF_INET6; - ip_address->prefix_len = IPV6_ADDR_LEN_BITS; - printf("returning %d\n", HICN_SOCKET_ERROR_NONE); - return HICN_SOCKET_ERROR_NONE; - } - } else if (address_family == AF_INET) { - if ((payload->ifa_index == interface_id) && - (payload->ifa_prefixlen < IPV4_ADDR_LEN * 8)) { - printf("got ip address\n"); - memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV4_ADDR_LEN); - ip_address->family = AF_INET; - ip_address->prefix_len = IPV4_ADDR_LEN_BITS; - printf("returning %d\n", HICN_SOCKET_ERROR_NONE); - return HICN_SOCKET_ERROR_NONE; - } - } else { - return -99; - } - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - printf("error getting ip address\n"); - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - struct { - struct nlmsghdr hdr; - struct ifaddrmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWADDR, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC, - .hdr.nlmsg_seq = seq++, - .payload.ifa_family = ip_address->family, - .payload.ifa_prefixlen = ip_address->prefix_len, - .payload.ifa_flags = 0, - .payload.ifa_scope = RT_SCOPE_UNIVERSE, - .payload.ifa_index = interface_id}; - - /* Set attributes = length/type/value */ - struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(ip_address)), - IFA_ADDRESS}; - // XXX maybe the reason why we have a local route ? - // struct rtattr ifa_local = { RTA_LENGTH(ip_address_len(ip_address)), - // IFA_LOCAL }; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - {&ifa_address, sizeof(ifa_address)}, - {(void *)&ip_address->buffer, sizeof(ip_address->buffer)}, - // { &ifa_local, sizeof(ifa_local) }, - // { (void*)&ip_address->buffer, sizeof(ip_address->buffer) }, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - // hicn_packet_dump_iov(iov, ARRAY_SIZE(iov)); - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - } - - return 0; - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -int _nl_up_if(uint32_t interface_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - struct { - struct nlmsghdr hdr; - struct ifinfomsg payload; - } msg = { - .hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), - .hdr.nlmsg_type = RTM_NEWLINK, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, - .payload.ifi_family = AF_UNSPEC, - .payload.ifi_index = interface_id, - .payload.ifi_flags = IFF_UP, - .payload.ifi_change = IFF_UP // 0xffffffff - }; - - n = send(fd, &msg, sizeof(msg), 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -struct route_info { - char *dst_addr; - char *src_addr; - char *gateway; - char ifName[IF_NAMESIZE]; -}; - -/* - * ip -6 route add PREFIX dev INTERFACE_NAME - */ -#if 0 -int _nl_add_in_route(const char * prefix, const uint32_t interface_id) -{ - char buffer[BUFSIZE]; - struct nlmsghdr * hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - int pton_fd; - unsigned char dst[sizeof(struct in6_addr)]; - char * p; - char * eptr; - char addr[strlen(prefix)]; - uint32_t dst_len; - - strncpy(addr, prefix, strlen(prefix)); - - p = strchr(addr, '/'); - if (!p) { - dst_len = IPV6_ADDR_LEN; - } else { - dst_len = strtoul(p + 1, &eptr, 10); - if (dst_len > IPV6_ADDR_LEN * 8) { - printf("E: Netmask > IPV6_ADDR_LEN"); - return -1; - } - *p = 0; - } - - pton_fd = inet_pton(AF_INET6, addr, dst); - if (pton_fd <= 0) { - if (pton_fd == 0) - ;//ERROR("Not in presentation format"); - else - perror("inet_pton"); - return -2; - } - - _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE_MATCH); - _nl_payload_route(RT_TABLE_MAIN, dst_len, (uint8_t *)buffer, BUFSIZE); - - addAttr(hdr, BUFSIZE, RTA_DST, dst, IPV6_ADDR_LEN); - addAttr(hdr, BUFSIZE, RTA_OIF, (void*)&interface_id, sizeof(uint32_t)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr * err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; - -} -#endif - -/* - * ip -6 route add local default via GATEWAY_IP table TABLE_ID - */ -int _nl_add_out_route(const char *gateway, uint8_t address_family, - const uint8_t table_id, int default_route) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - int pton_fd; - - if (address_family == AF_INET) { - struct in_addr gw; - - pton_fd = inet_pton(AF_INET, gateway, (struct in_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - - } else if (address_family == AF_INET6) { - struct in6_addr gw; - - pton_fd = inet_pton(AF_INET6, gateway, (struct in6_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - if (default_route != -1) { - addAttr(hdr, BUFSIZE, RTA_OIF, &default_route, sizeof(default_route)); - } - - } else { - return -1; - } - - // For more than 255 tables - // addAttr(msg, BUFSIZE, RTA_TABLE, &table_id, sizeof(uint32_t)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip -6 route del local default via GATEWAY_IP table TABLE_ID - */ -int _nl_del_out_route(const char *gateway, const uint8_t address_family, - const uint8_t table_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - int pton_fd; - - if (address_family == AF_INET) { - struct in_addr gw; - - pton_fd = inet_pton(AF_INET, gateway, (struct in_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_DELROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - - } else if (address_family == AF_INET6) { - struct in6_addr gw; - - pton_fd = inet_pton(AF_INET6, gateway, (struct in6_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_DELROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - - } else { - return -1; - } - - // For more than 255 tables - // addAttr(msg, BUFSIZE, RTA_TABLE, &table_id, sizeof(uint32_t)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip route del 1:2::2 dev lo table local - * - */ -int _nl_del_lo_route(const ip_address_t *ip_address) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_DELROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = ip_address->family, - .payload.rtm_dst_len = ip_address->prefix_len, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = RT_TABLE_LOCAL, - .payload.rtm_protocol = RTPROT_UNSPEC, - .payload.rtm_scope = RT_SCOPE_UNIVERSE, - .payload.rtm_type = RTN_UNSPEC, - .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' - }; - - /* Set attribute = length/type/value */ - uint32_t one = 1; - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), RTA_DST}; - struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)&ip_address->buffer, ip_address_len(ip_address)}, - /* Interface id */ - {&a_ifid_lo, sizeof(a_ifid_lo)}, - {&one, sizeof(one)}}; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - return 0; - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -/* - * ip -6 rule add iif INTERFACE_NAME lookup TABLE_ID - */ -int _nl_add_rule(const char *interface_name, uint8_t address_family, - const uint8_t table_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - _nl_header(RTM_NEWRULE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE); - _nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE); - - /* XXX iif */ - addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name, - strlen(interface_name)); - // attr1 = addNestedAttr(hdr, IFLA_LINKINFO); - // endNestedAttr(hdr, attr1); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip -6 rule del iif INTERFACE_NAME //lookup TABLE_ID - */ -int _nl_del_rule(const char *interface_name, uint8_t address_family, - const uint8_t table_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - _nl_header(RTM_DELRULE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE); - _nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE); - - /* XXX iif */ - addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name, - strlen(interface_name)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei - * - */ -int _nl_add_neigh_proxy(const ip_address_t *ip_address, - const uint32_t interface_id) { - /* Buffer for holding the response, with appropriate casting on the header */ - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct ndmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWNEIGH, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.ndm_family = ip_address->family, - .payload.ndm_ifindex = interface_id, - .payload.ndm_state = NUD_PERMANENT, - .payload.ndm_flags = NTF_PROXY, - }; - - /* Message attributes = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), NDA_DST}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)&ip_address->buffer, sizeof(ip_address->buffer)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -/* 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_address_t *prefix, - const uint32_t interface_id, - const uint8_t table_id) { - /* Buffer for holding the response, with appropriate casting on the header */ - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = prefix->family, - .payload.rtm_dst_len = prefix->prefix_len, // XXX ? XXX dst_len, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = table_id, /* RT_TABLE_MAIN, etc. */ - .payload.rtm_protocol = RTPROT_BOOT, - .payload.rtm_scope = - prefix->family == AF_INET6 ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, - .payload.rtm_type = RTN_UNICAST, - .payload.rtm_flags = 0, - }; - - /* Message attributes = length/type/value */ - // XXX This could be put directly inside the iovec maybe ? XXX - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix)), RTA_DST}; - struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Destination prefix / ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)&prefix->buffer, ip_address_len(prefix)}, - /* Output interface */ - {&a_oif, sizeof(a_oif)}, - {(void *)&interface_id, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -/* Additional helper functions */ - -int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, - const uint8_t table_id) { - int rc; - ip_address_t ip_address; - - rc = hicn_ip_pton(prefix, &ip_address); - if (rc < 0) { - return rc; - } - - return _nl_add_in_route_table(&ip_address, interface_id, table_id); -} - -int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) { - return _nl_add_in_route_table_s(prefix, interface_id, RT_TABLE_MAIN); -} - -////////* ip -6 rule add from all prio 10 table local */ -/* ip -6 rule add from b001::/16 prio 0 table 100 */ -int _nl_add_prio_rule(const ip_address_t *ip_address, 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]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct fib_rule_hdr payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWRULE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.family = address_family, - //.payload.dst_len = , - .payload.src_len = ip_address ? ip_address->prefix_len : 0, - .payload.tos = 0, - .payload.table = table_id, - .payload.action = FR_ACT_TO_TBL, - .payload.flags = NLM_F_REPLACE, // 0 - }; - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - if (ip_address) { - /* Message attributes = length/type/value */ - struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC}; - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Source prefix / ip_address */ - {&a_src, sizeof(a_src)}, - {(void *)&ip_address->buffer, ip_address_len(ip_address)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } else { - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_add_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family, - const uint32_t priority) { - return _nl_add_prio_rule(ip_address, address_family, priority, - RT_TABLE_LOCAL); -} - -/* ip -6 rule del from all prio 0 table local */ -int _nl_del_prio_rule(const ip_address_t *ip_address, 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]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct fib_rule_hdr payload; - } msg = { - .hdr.nlmsg_type = RTM_DELRULE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.family = address_family, - //.payload.dst_len = , - .payload.src_len = ip_address ? ip_address->prefix_len : 0, - .payload.tos = 0, - .payload.table = table_id, - .payload.action = FR_ACT_TO_TBL, - .payload.flags = NLM_F_REPLACE, // 0 - }; - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - /* Message attributes = length/type/value */ - if (ip_address) { - struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC}; - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Source prefix / ip_address */ - {&a_src, sizeof(a_src)}, - {(void *)&ip_address->buffer, ip_address_len(ip_address)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - - } else { - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0 && - err->error != -2) { //-2 is not such file or directory - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_del_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family, - const uint32_t priority) { - return _nl_del_prio_rule(ip_address, address_family, priority, - RT_TABLE_LOCAL); -} - -/******************************************************************************/ - -// #include -// duplicate declarations, in the meantime -#define IF_NAMESIZE 16 - -//#define WITH_TUN_PI 1 - -#ifdef WITH_TUN_PI -#define TUN_FLAGS IFF_TUN -#else -#define TUN_FLAGS IFF_TUN | IFF_NO_PI -#endif - -/* - * Taken from Kernel Documentation/networking/tuntap.txt - */ - -int tun_alloc(char *dev, int flags) { - struct ifreq ifr; - int fd, err; - char *clonedev = "/dev/net/tun"; - - /* Arguments taken by the function: - * - * char *dev: the name of an interface (or '\0'). MUST have enough - * space to hold the interface name if '\0' is passed - * int flags: interface flags (eg, IFF_TUN etc.) - */ - - /* open the clone device */ - if ((fd = open(clonedev, O_RDWR)) < 0) { - return fd; - } - - /* preparation of the struct ifr, of type "struct ifreq" */ - memset(&ifr, 0, sizeof(ifr)); - - ifr.ifr_flags = flags; - - if (*dev) { - /* 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); - } - - /* try to create the device */ - if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { - close(fd); - return err; - } - - /* if the operation was successful, write back the name of the - * 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); - - /* this is the special file descriptor that the caller will use to talk - * with the virtual interface */ - return fd; -} - -int linux_get_tun_name(const char *prefix, const char *identifier, - char *tun_name) { - snprintf(tun_name, IF_NAMESIZE, "%s-%s", prefix, - identifier ? identifier : "main"); - return 0; -} - -int linux_tun_enable_offload(int fd) { - unsigned int offload = 0, tso4 = 1, tso6 = 1, ecn = 1, ufo = 1, csum = 1; - - /* Check if our kernel supports TUNSETOFFLOAD */ - if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) { - goto ERR_TUN; - } - - if (csum) { - offload |= TUN_F_CSUM; - if (tso4) offload |= TUN_F_TSO4; - if (tso6) offload |= TUN_F_TSO6; - if ((tso4 || tso6) && ecn) offload |= TUN_F_TSO_ECN; - if (ufo) offload |= TUN_F_UFO; - } - - if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { - offload &= ~TUN_F_UFO; - if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { - fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", strerror(errno)); - } - } - - return 0; - -ERR_TUN: - return -1; -} - -int linux_tun_create(char *name) { - int fd, rc; - - fd = tun_alloc(name, TUN_FLAGS); - if (fd < 0) { - // ERROR("Error connecting to tun/tap interface %s!", name); - errno = -2; - goto ERR_TUN; - } - - rc = linux_tun_enable_offload(fd); - if (rc < 0) { - // WARN("Could not enable hardware offload on TUN device"); - } else { - // INFO("Enabled hardware offload on TUN device"); - } - - return fd; - -ERR_TUN: - return -1; -} - -/* - * - * interface name can be NULL for all interfaces - */ -int linux_enable_proc(char *path) { - int ret = 0; - int fd; - - fd = open(path, O_WRONLY); - if (fd < 0) { - return -1; - } - - if (write(fd, "1", 1) != 1) { - ret = -2; - } - - close(fd); - return ret; -} - -int linux_enable_v4_forwarding() { - return linux_enable_proc("/proc/sys/net/ipv4/ip_forward"); -} - -int linux_enable_v6_forwarding(char *interface_name) { - char path[PATH_MAX]; - snprintf(path, PATH_MAX, "/proc/sys/net/ipv6/conf/%s/forwarding", - (interface_name) ? interface_name : "all"); - - return linux_enable_proc(path); -} - -int linux_enable_ndp_proxy() { - return linux_enable_proc("/proc/sys/net/ipv6/conf/all/proxy_ndp"); -} - -const hicn_socket_ops_t ops = { - .arch = "linux", - .get_tun_name = linux_get_tun_name, - .tun_create = linux_tun_create, - .enable_v4_forwarding = linux_enable_v4_forwarding, - .enable_v6_forwarding = linux_enable_v6_forwarding, - .enable_ndp_proxy = linux_enable_ndp_proxy, - .get_ifid = _nl_get_ifid, - .get_output_ifid = _nl_get_output_ifid, - .get_ip_addr = _nl_get_ip_addr, - .set_ip_addr = _nl_set_ip_addr, - .up_if = _nl_up_if, - .add_in_route_table = _nl_add_in_route_table, - .add_in_route_table_s = _nl_add_in_route_table_s, - .add_in_route_s = _nl_add_in_route_s, - .add_out_route = _nl_add_out_route, - .del_out_route = _nl_del_out_route, - .del_lo_route = _nl_del_lo_route, - .add_rule = _nl_add_rule, - .del_rule = _nl_del_rule, - .add_neigh_proxy = _nl_add_neigh_proxy, - .add_prio_rule = _nl_add_prio_rule, - .add_lo_prio_rule = _nl_add_lo_prio_rule, - .del_prio_rule = _nl_del_prio_rule, - .del_lo_prio_rule = _nl_del_lo_prio_rule, -}; diff --git a/hicn-light/src/strategies/CMakeLists.txt b/hicn-light/src/strategies/CMakeLists.txt deleted file mode 100644 index 7f0730b2f..000000000 --- a/hicn-light/src/strategies/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -list(APPEND HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/strategyImpl.h - ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.h - ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancerWithPD.h - ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.h - ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateWithPD.h - ${CMAKE_CURRENT_SOURCE_DIR}/rnd.h - ${CMAKE_CURRENT_SOURCE_DIR}/rndSegment.h -) - -list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.c - ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancerWithPD.c - ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.c - ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateWithPD.c - ${CMAKE_CURRENT_SOURCE_DIR}/rnd.c - ${CMAKE_CURRENT_SOURCE_DIR}/rndSegment.c -) - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) diff --git a/hicn-light/src/strategies/loadBalancer.c b/hicn-light/src/strategies/loadBalancer.c deleted file mode 100644 index 8dda98603..000000000 --- a/hicn-light/src/strategies/loadBalancer.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy, - const NumberSet *egressId, - const Message *objectMessage, - Ticks rtt); -static void _strategyLoadBalancer_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId); -static NumberSet *_strategyLoadBalancer_LookupNexthop( - StrategyImpl *strategy, const Message *interestMessage); -static NumberSet *_strategyLoadBalancer_ReturnNexthops(StrategyImpl *strategy); -static unsigned _strategyLoadBalancer_CountNexthops(StrategyImpl *strategy); -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, - .returnNexthops = &_strategyLoadBalancer_ReturnNexthops, - .countNexthops = &_strategyLoadBalancer_CountNexthops, - .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 { - double weights_sum; - // hash map from connectionId to StrategyNexthopState - PARCHashMap *strategy_state; - NumberSet *nexthops; -}; - -StrategyImpl *strategyLoadBalancer_Create() { - StrategyLoadBalancer *strategy = - parcMemory_AllocateAndClear(sizeof(StrategyLoadBalancer)); - parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(StrategyLoadBalancer)); - - strategy->weights_sum = 0.0; - strategy->strategy_state = parcHashMap_Create(); - strategy->nexthops = numberSet_Create(); - 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; - double w = strategyNexthopState_GetWeight(state); - strategy->weights_sum -= w; - w = strategyNexthopState_UpdateState(state, inc, ALPHA); - strategy->weights_sum += w; -} - -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; -} - -static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy, - const NumberSet *egressId, - const Message *objectMessage, - Ticks rtt) { - _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, const Message *interestMessage) { - StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; - - unsigned in_connection = message_GetIngressConnectionId(interestMessage); - PARCUnsigned *in = parcUnsigned_Create(in_connection); - - unsigned mapSize = (unsigned)parcHashMap_Size(lb->strategy_state); - NumberSet *outList = numberSet_Create(); - - 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); - return outList; -} - -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); -} - -static void _strategyLoadBalancer_resetState(StrategyImpl *strategy) { - StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; - lb->weights_sum = 0.0; - 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); - lb->weights_sum += strategyNexthopState_GetWeight(elem); - } - - parcIterator_Release(&it); -} - -static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyNexthopState *state = strategyNexthopState_Create(); - - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context; - - if (!parcHashMap_Contains(lb->strategy_state, cid)) { - parcHashMap_Put(lb->strategy_state, cid, state); - numberSet_Add(lb->nexthops, connectionId); - _strategyLoadBalancer_resetState(strategy); - } -} - -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)) { - parcHashMap_Remove(lb->strategy_state, cid); - numberSet_Remove(lb->nexthops, connectionId); - _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; - - parcHashMap_Release(&(strategy->strategy_state)); - numberSet_Release(&(strategy->nexthops)); - - parcMemory_Deallocate((void **)&strategy); - parcMemory_Deallocate((void **)&impl); - *strategyPtr = NULL; -} diff --git a/hicn-light/src/strategies/loadBalancer.h b/hicn-light/src/strategies/loadBalancer.h deleted file mode 100644 index 1178c30fe..000000000 --- a/hicn-light/src/strategies/loadBalancer.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 less loaded path - */ - -#ifndef loadBalancer_h -#define loadBalancer_h - -#include - -StrategyImpl *strategyLoadBalancer_Create(); -#endif // loadBalancer_h diff --git a/hicn-light/src/strategies/loadBalancerWithPD.c b/hicn-light/src/strategies/loadBalancerWithPD.c deleted file mode 100644 index c9c1479a2..000000000 --- a/hicn-light/src/strategies/loadBalancerWithPD.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -const unsigned PROBE_FREQUENCY = 1024; - -static void _strategyLoadBalancerWithPD_ReceiveObject( - StrategyImpl *strategy, const NumberSet *egressId, - const Message *objectMessage, Ticks rtt); -static void _strategyLoadBalancerWithPD_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId); -static NumberSet *_strategyLoadBalancerWithPD_LookupNexthop( - StrategyImpl *strategy, const Message *interestMessage); -static NumberSet *_strategyLoadBalancerWithPD_ReturnNexthops( - StrategyImpl *strategy); -static unsigned _strategyLoadBalancerWithPD_CountNexthops( - StrategyImpl *strategy); -static void _strategyLoadBalancerWithPD_AddNexthop(StrategyImpl *strategy, - unsigned connectionId); -static void _strategyLoadBalancerWithPD_RemoveNexthop(StrategyImpl *strategy, - unsigned connectionId); -static void _strategyLoadBalancerWithPD_ImplDestroy(StrategyImpl **strategyPtr); -static strategy_type _strategyLoadBalancerWithPD_GetStrategy( - StrategyImpl *strategy); - -static StrategyImpl _template = { - .context = NULL, - .receiveObject = &_strategyLoadBalancerWithPD_ReceiveObject, - .onTimeout = &_strategyLoadBalancerWithPD_OnTimeout, - .lookupNexthop = &_strategyLoadBalancerWithPD_LookupNexthop, - .returnNexthops = &_strategyLoadBalancerWithPD_ReturnNexthops, - .countNexthops = &_strategyLoadBalancerWithPD_CountNexthops, - .addNexthop = &_strategyLoadBalancerWithPD_AddNexthop, - .removeNexthop = &_strategyLoadBalancerWithPD_RemoveNexthop, - .destroy = &_strategyLoadBalancerWithPD_ImplDestroy, - .getStrategy = &_strategyLoadBalancerWithPD_GetStrategy, -}; - -struct strategy_load_balancer_with_pd; -typedef struct strategy_load_balancer_with_pd StrategyLoadBalancerWithPD; - -struct strategy_load_balancer_with_pd { - double weights_sum; - unsigned min_delay; - // hash map from connectionId to StrategyNexthopState - PARCHashMap *strategy_state; - NumberSet *nexthops; - ConnectionTable *connTable; - bool toInit; - unsigned int fwdPackets; -}; - -StrategyImpl *strategyLoadBalancerWithPD_Create() { - StrategyLoadBalancerWithPD *strategy = - parcMemory_AllocateAndClear(sizeof(StrategyLoadBalancerWithPD)); - parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(StrategyLoadBalancerWithPD)); - - strategy->weights_sum = 0.0; - strategy->min_delay = INT_MAX; - strategy->strategy_state = parcHashMap_Create(); - strategy->nexthops = numberSet_Create(); - 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; - strategy->connTable = NULL; - strategy->fwdPackets = 0; - strategy->toInit = true; - - return impl; -} - -void strategyLoadBalancerWithPD_SetConnectionTable(StrategyImpl *strategy, - ConnectionTable *connTable) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - lb->connTable = connTable; -} - -// ======================================================= -// Dispatch API - -strategy_type _strategyLoadBalancerWithPD_GetStrategy(StrategyImpl *strategy) { - return SET_STRATEGY_LOADBALANCER_WITH_DELAY; -} - -static void _update_Stats(StrategyLoadBalancerWithPD *strategy, - StrategyNexthopStateWithPD *state, bool inc, - Ticks rtt) { - const double ALPHA = 0.9; - double w = strategyNexthopStateWithPD_GetWeight(state); - strategy->weights_sum -= w; - w = strategyNexthopStateWithPD_UpdateState(state, inc, strategy->min_delay, - ALPHA); - strategy->weights_sum += w; -} - -static void _sendProbes(StrategyLoadBalancerWithPD *strategy) { - unsigned size = (unsigned)numberSet_Length(strategy->nexthops); - for (unsigned i = 0; i < size; i++) { - unsigned nhop = numberSet_GetItem(strategy->nexthops, i); - Connection *conn = - (Connection *)connectionTable_FindById(strategy->connTable, nhop); - if (conn != NULL) { - connection_Probe(conn); - unsigned delay = (unsigned)connection_GetDelay(conn); - PARCUnsigned *cid = parcUnsigned_Create(nhop); - StrategyNexthopStateWithPD *elem = - (StrategyNexthopStateWithPD *)parcHashMap_Get( - strategy->strategy_state, cid); - strategyNexthopStateWithPD_SetDelay(elem, delay); - if (delay < strategy->min_delay && delay != 0) { - strategy->min_delay = delay; - } - - parcUnsigned_Release(&cid); - } - } -} - -static unsigned _select_Nexthop(StrategyLoadBalancerWithPD *strategy) { - strategy->fwdPackets++; - if (strategy->toInit || strategy->fwdPackets == PROBE_FREQUENCY) { - strategy->toInit = false; - strategy->fwdPackets = 0; - _sendProbes(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 StrategyNexthopStateWithPD *elem = - parcHashMap_Get(strategy->strategy_state, cid); - - double w = strategyNexthopStateWithPD_GetWeight(elem); - - // printf("next = %u .. pi %u avgpi %f w %f avgrtt - // %f\n",parcUnsigned_GetUnsigned(cid), - // strategyNexthopStateWithPD_GetPI(elem), - // strategyNexthopStateWithPD_GetWeight(elem), - // strategyNexthopStateWithPD_GetWeight(elem), - // strategyNexthopStateWithPD_GetAvgRTT(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; -} - -static void _strategyLoadBalancerWithPD_ReceiveObject( - StrategyImpl *strategy, const NumberSet *egressId, - const Message *objectMessage, Ticks rtt) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - - for (unsigned i = 0; i < numberSet_Length(egressId); i++) { - unsigned outId = numberSet_GetItem(egressId, i); - PARCUnsigned *cid = parcUnsigned_Create(outId); - - const StrategyNexthopStateWithPD *state = - parcHashMap_Get(lb->strategy_state, cid); - if (state != NULL) { - _update_Stats(lb, (StrategyNexthopStateWithPD *)state, false, 0); - } else { - // this may happen if we remove a face/route while downloading a file - // we should ignore this timeout - } - parcUnsigned_Release(&cid); - } -} - -static void _strategyLoadBalancerWithPD_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - - for (unsigned i = 0; i < numberSet_Length(egressId); i++) { - unsigned outId = numberSet_GetItem(egressId, i); - PARCUnsigned *cid = parcUnsigned_Create(outId); - - const StrategyNexthopStateWithPD *state = - parcHashMap_Get(lb->strategy_state, cid); - if (state != NULL) { - _update_Stats(lb, (StrategyNexthopStateWithPD *)state, false, 0); - } else { - // this may happen if we remove a face/route while downloading a file - // we should ignore this timeout - } - parcUnsigned_Release(&cid); - } -} - -// ATTENTION!! This interface force us to create a NumberSet which need to be -// delited somewhere The specification in the interface requires that this -// function never returns NULL. in case we have no output face we need to return -// an empty NumberSet -static NumberSet *_strategyLoadBalancerWithPD_LookupNexthop( - StrategyImpl *strategy, const Message *interestMessage) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - - unsigned in_connection = message_GetIngressConnectionId(interestMessage); - PARCUnsigned *in = parcUnsigned_Create(in_connection); - - unsigned mapSize = (unsigned)parcHashMap_Size(lb->strategy_state); - NumberSet *outList = numberSet_Create(); - - 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 StrategyNexthopStateWithPD *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, (StrategyNexthopStateWithPD *)state, true, 0); - - parcUnsigned_Release(&in); - parcUnsigned_Release(&out); - - numberSet_Add(outList, out_connection); - return outList; -} - -static NumberSet *_strategyLoadBalancerWithPD_ReturnNexthops( - StrategyImpl *strategy) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - return lb->nexthops; -} - -unsigned _strategyLoadBalancerWithPD_CountNexthops(StrategyImpl *strategy) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - return (unsigned)numberSet_Length(lb->nexthops); -} - -static void _strategyLoadBalancerWithPD_resetState(StrategyImpl *strategy) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - lb->weights_sum = 0.0; - lb->min_delay = INT_MAX; - lb->toInit = true; - PARCIterator *it = parcHashMap_CreateKeyIterator(lb->strategy_state); - - while (parcIterator_HasNext(it)) { - PARCUnsigned *cid = parcIterator_Next(it); - StrategyNexthopStateWithPD *elem = - (StrategyNexthopStateWithPD *)parcHashMap_Get(lb->strategy_state, cid); - - strategyNexthopStateWithPD_Reset(elem); - lb->weights_sum += strategyNexthopStateWithPD_GetWeight(elem); - } - - parcIterator_Release(&it); -} - -static void _strategyLoadBalancerWithPD_AddNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyNexthopStateWithPD *state = strategyNexthopStateWithPD_Create(); - - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - - if (!parcHashMap_Contains(lb->strategy_state, cid)) { - parcHashMap_Put(lb->strategy_state, cid, state); - numberSet_Add(lb->nexthops, connectionId); - _strategyLoadBalancerWithPD_resetState(strategy); - } -} - -static void _strategyLoadBalancerWithPD_RemoveNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyLoadBalancerWithPD *lb = - (StrategyLoadBalancerWithPD *)strategy->context; - - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - if (parcHashMap_Contains(lb->strategy_state, cid)) { - parcHashMap_Remove(lb->strategy_state, cid); - numberSet_Remove(lb->nexthops, connectionId); - _strategyLoadBalancerWithPD_resetState(strategy); - } - - parcUnsigned_Release(&cid); -} - -static void _strategyLoadBalancerWithPD_ImplDestroy( - StrategyImpl **strategyPtr) { - parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer"); - parcAssertNotNull(*strategyPtr, - "Parameter must dereference to non-null pointer"); - - StrategyImpl *impl = *strategyPtr; - StrategyLoadBalancerWithPD *strategy = - (StrategyLoadBalancerWithPD *)impl->context; - - parcHashMap_Release(&(strategy->strategy_state)); - numberSet_Release(&(strategy->nexthops)); - - parcMemory_Deallocate((void **)&strategy); - parcMemory_Deallocate((void **)&impl); - *strategyPtr = NULL; -} diff --git a/hicn-light/src/strategies/loadBalancerWithPD.h b/hicn-light/src/strategies/loadBalancerWithPD.h deleted file mode 100644 index 6ea7f0785..000000000 --- a/hicn-light/src/strategies/loadBalancerWithPD.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. - */ - -/** - * Forward on the less loaded path taking into account the propagation delay of - * the first hop - */ - -#ifndef loadBalancerWithPD_h -#define loadBalancerWithPD_h - -#include -#include - -StrategyImpl *strategyLoadBalancerWithPD_Create(); -void strategyLoadBalancerWithPD_SetConnectionTable(StrategyImpl *strategy, - ConnectionTable *connTable); -#endif // loadBalancerWithPD_h diff --git a/hicn-light/src/strategies/nexthopState.c b/hicn-light/src/strategies/nexthopState.c deleted file mode 100644 index ef0ffe982..000000000 --- a/hicn-light/src/strategies/nexthopState.c +++ /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. - */ - -#include -#include - -#include -#include -#include - -#include -#include - -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)); - if (x->avg_pi == 0.0) { - x->avg_pi = 0.1; - } - x->weight = 1 / x->avg_pi; - - return x->weight; -} diff --git a/hicn-light/src/strategies/nexthopState.h b/hicn-light/src/strategies/nexthopState.h deleted file mode 100644 index 35a9f497b..000000000 --- a/hicn-light/src/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 -#include - -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/strategies/nexthopStateWithPD.c b/hicn-light/src/strategies/nexthopStateWithPD.c deleted file mode 100644 index 2eecb0c64..000000000 --- a/hicn-light/src/strategies/nexthopStateWithPD.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -struct strategy_nexthop_state_with_pd { - unsigned int pi; - unsigned delay; - double weight; - double avg_pi; -}; - -static bool _strategyNexthopStateWithPD_Destructor( - StrategyNexthopStateWithPD **instancePtr) { - return true; -} - -parcObject_ImplementAcquire(strategyNexthopStateWithPD, - StrategyNexthopStateWithPD); - -parcObject_ImplementRelease(strategyNexthopStateWithPD, - StrategyNexthopStateWithPD); - -parcObject_Override( - StrategyNexthopStateWithPD, PARCObject, - .destructor = (PARCObjectDestructor *) - _strategyNexthopStateWithPD_Destructor, - .copy = (PARCObjectCopy *)strategyNexthopStateWithPD_Copy, - .display = (PARCObjectDisplay *)strategyNexthopStateWithPD_Display, - .toString = (PARCObjectToString *)strategyNexthopStateWithPD_ToString, - .equals = (PARCObjectEquals *)strategyNexthopStateWithPD_Equals, - .compare = (PARCObjectCompare *)strategyNexthopStateWithPD_Compare, - .hashCode = (PARCObjectHashCode *)strategyNexthopStateWithPD_HashCode, - .display = (PARCObjectDisplay *)strategyNexthopStateWithPD_Display); - -void strategyNexthopStateWithPD_AssertValid( - const StrategyNexthopStateWithPD *instance) { - parcAssertTrue(strategyNexthopStateWithPD_IsValid(instance), - "StrategyNexthopStateWithPD is not valid."); -} - -StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Create() { - StrategyNexthopStateWithPD *result = - parcObject_CreateInstance(StrategyNexthopStateWithPD); - if (result != NULL) { - result->pi = 0; - result->avg_pi = 1.0; - result->weight = 1; - result->delay = 0; - } - return result; -} - -void strategyNexthopStateWithPD_Reset(StrategyNexthopStateWithPD *x) { - x->pi = 0; - x->avg_pi = 1.0; - x->weight = 1; - x->delay = 0; -} - -int strategyNexthopStateWithPD_Compare( - const StrategyNexthopStateWithPD *val, - const StrategyNexthopStateWithPD *other) { - if (val == NULL) { - if (other != NULL) { - return -1; - } - } else if (other == NULL) { - return 1; - } else { - strategyNexthopStateWithPD_OptionalAssertValid(val); - strategyNexthopStateWithPD_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; - } - - if (val->delay < other->delay) { - return -1; - } else if (val->delay > other->delay) { - return 1; - } - } - - return 0; -} - -StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Copy( - const StrategyNexthopStateWithPD *original) { - StrategyNexthopStateWithPD *result = strategyNexthopStateWithPD_Create(); - result->pi = original->pi; - result->avg_pi = original->avg_pi; - result->weight = original->weight; - result->delay = original->delay; - - return result; -} - -void strategyNexthopStateWithPD_Display( - const StrategyNexthopStateWithPD *instance, int indentation) { - parcDisplayIndented_PrintLine(indentation, "StrategyNexthopStateWithPD@%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 + 1, "%f", instance->delay); - parcDisplayIndented_PrintLine(indentation, "}"); -} - -bool strategyNexthopStateWithPD_Equals(const StrategyNexthopStateWithPD *x, - const StrategyNexthopStateWithPD *y) { - bool result = false; - - if (x == y) { - result = true; - } else if (x == NULL || y == NULL) { - result = false; - } else { - strategyNexthopStateWithPD_OptionalAssertValid(x); - strategyNexthopStateWithPD_OptionalAssertValid(y); - - if (strategyNexthopStateWithPD_Compare(x, y) == 0) { - result = true; - } - } - - return result; -} - -PARCHashCode strategyNexthopStateWithPD_HashCode( - const StrategyNexthopStateWithPD *x) { - PARCHashCode result = 0; - char str[128]; - sprintf(str, "PI:%d: AVG_PI:%f: W:%f D:%d", x->pi, x->avg_pi, x->weight, - x->delay); - result = parcHashCode_Hash((uint8_t *)&str, strlen(str)); - return result; -} - -bool strategyNexthopStateWithPD_IsValid(const StrategyNexthopStateWithPD *x) { - bool result = false; - - if (x != NULL) { - result = true; - } - - return result; -} - -char *strategyNexthopStateWithPD_ToString(const StrategyNexthopStateWithPD *x) { - // this is not implemented - parcTrapNotImplemented( - "strategyNexthopStateWithPD_ToString is not implemented"); - return NULL; -} - -unsigned strategyNexthopStateWithPD_GetPI(const StrategyNexthopStateWithPD *x) { - strategyNexthopStateWithPD_OptionalAssertValid(x); - - return x->pi; -} - -double strategyNexthopStateWithPD_GetAvgPI( - const StrategyNexthopStateWithPD *x) { - strategyNexthopStateWithPD_OptionalAssertValid(x); - - return x->avg_pi; -} - -double strategyNexthopStateWithPD_GetWeight( - const StrategyNexthopStateWithPD *x) { - strategyNexthopStateWithPD_OptionalAssertValid(x); - - return x->weight; -} - -unsigned strategyNexthopStateWithPD_GetDelay( - const StrategyNexthopStateWithPD *x) { - strategyNexthopStateWithPD_OptionalAssertValid(x); - - return x->delay; -} - -void strategyNexthopStateWithPD_SetDelay(StrategyNexthopStateWithPD *x, - unsigned delay) { - strategyNexthopStateWithPD_OptionalAssertValid(x); - if (delay != 0) { - x->delay = delay; - } -} - -double strategyNexthopStateWithPD_UpdateState(StrategyNexthopStateWithPD *x, - bool inc, unsigned min_delay, - double alpha) { - strategyNexthopStateWithPD_OptionalAssertValid(x); - - if (inc) { - x->pi++; - } else { - if (x->pi > 0) { - x->pi--; - } - } - - x->avg_pi = (x->avg_pi * alpha) + (x->pi * (1 - alpha)); - if (x->avg_pi == 0.0) { - x->avg_pi = 0.1; - } - - double factor = 1.0; - if (min_delay != INT_MAX && x->delay != 0) { - factor = ((double)min_delay / (double)x->delay); - } - - x->weight = 1 / (x->avg_pi * factor); - - return x->weight; -} diff --git a/hicn-light/src/strategies/nexthopStateWithPD.h b/hicn-light/src/strategies/nexthopStateWithPD.h deleted file mode 100644 index 4d8bd6d15..000000000 --- a/hicn-light/src/strategies/nexthopStateWithPD.h +++ /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. - */ - -#ifndef nexthopstatewithpd_h -#define nexthopstatewithpd_h - -#include -#include - -struct strategy_nexthop_state_with_pd; -typedef struct strategy_nexthop_state_with_pd StrategyNexthopStateWithPD; -extern parcObjectDescriptor_Declaration(StrategyNexthopStateWithPD); - -/** - */ -StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Acquire( - const StrategyNexthopStateWithPD *instance); - -#ifdef PARCLibrary_DISABLE_VALIDATION -#define strategyNexthopStateWithPD_OptionalAssertValid(_instance_) -#else -#define strategyNexthopStateWithPD_OptionalAssertValid(_instance_) \ - strategyNexthopStateWithPD_AssertValid(_instance_) -#endif - -/** - */ -void strategyNexthopStateWithPD_AssertValid( - const StrategyNexthopStateWithPD *instance); - -/** - */ -StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Create(); - -void strategyNexthopStateWithPD_Reset(StrategyNexthopStateWithPD *x); -/** - */ -int strategyNexthopStateWithPD_Compare( - const StrategyNexthopStateWithPD *instance, - const StrategyNexthopStateWithPD *other); - -/** - */ -StrategyNexthopStateWithPD *strategyNexthopStateWithPD_Copy( - const StrategyNexthopStateWithPD *original); - -/** - */ -void strategyNexthopStateWithPD_Display( - const StrategyNexthopStateWithPD *instance, int indentation); - -/** - */ -bool strategyNexthopStateWithPD_Equals(const StrategyNexthopStateWithPD *x, - const StrategyNexthopStateWithPD *y); - -/** - */ -PARCHashCode strategyNexthopStateWithPD_HashCode( - const StrategyNexthopStateWithPD *instance); - -/** - */ -bool strategyNexthopStateWithPD_IsValid( - const StrategyNexthopStateWithPD *instance); - -/** - */ -void strategyNexthopStateWithPD_Release( - StrategyNexthopStateWithPD **instancePtr); - -/** - */ -char *strategyNexthopStateWithPD_ToString( - const StrategyNexthopStateWithPD *instance); - -/** - */ -unsigned strategyNexthopStateWithPD_GetPI(const StrategyNexthopStateWithPD *x); - -double strategyNexthopStateWithPD_GetAvgPI(const StrategyNexthopStateWithPD *x); - -double strategyNexthopStateWithPD_GetWeight( - const StrategyNexthopStateWithPD *x); - -unsigned strategyNexthopStateWithPD_GetDelay( - const StrategyNexthopStateWithPD *x); -void strategyNexthopStateWithPD_SetDelay(StrategyNexthopStateWithPD *x, - unsigned delay); - -double strategyNexthopStateWithPD_UpdateState(StrategyNexthopStateWithPD *x, - bool inc, unsigned min_delay, - double alpha); -#endif diff --git a/hicn-light/src/strategies/rnd.c b/hicn-light/src/strategies/rnd.c deleted file mode 100644 index 35b9e87c6..000000000 --- a/hicn-light/src/strategies/rnd.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include - -static void _strategyRnd_ReceiveObject(StrategyImpl *strategy, - const NumberSet *egressId, - const Message *objectMessage, Ticks rtt); -static void _strategyRnd_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId); -static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy, - const Message *interestMessage); -static NumberSet *_strategyRnd_ReturnNexthops(StrategyImpl *strategy); -static unsigned _strategyRnd_CountNexthops(StrategyImpl *strategy); -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, - .returnNexthops = &_strategyRnd_ReturnNexthops, - .countNexthops = &_strategyRnd_CountNexthops, - .addNexthop = &_strategyRnd_AddNexthop, - .removeNexthop = &_strategyRnd_RemoveNexthop, - .destroy = &_strategyRnd_ImplDestroy, - .getStrategy = &_strategyRnd_GetStrategy, -}; - -struct strategy_rnd; -typedef struct strategy_rnd StrategyRnd; - -struct strategy_rnd { - NumberSet *nexthops; -}; - -StrategyImpl *strategyRnd_Create() { - StrategyRnd *strategy = parcMemory_AllocateAndClear(sizeof(StrategyRnd)); - parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(StrategyRnd)); - - strategy->nexthops = numberSet_Create(); - 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 _strategyRnd_GetStrategy(StrategyImpl *strategy) { - return SET_STRATEGY_RANDOM; -} - -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); -} - -static void _strategyRnd_ReceiveObject(StrategyImpl *strategy, - const NumberSet *egressId, - const Message *objectMessage, - Ticks rtt) {} - -static void _strategyRnd_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId) {} - -static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy, - const Message *interestMessage) { - StrategyRnd *srnd = (StrategyRnd *)strategy->context; - - unsigned in_connection = message_GetIngressConnectionId(interestMessage); - unsigned nexthopSize = (unsigned)numberSet_Length(srnd->nexthops); - - NumberSet *out = numberSet_Create(); - 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; - } - - unsigned out_connection; - do { - out_connection = _select_Nexthop(srnd); - } while (out_connection == in_connection); - - if (out_connection == -1) { - return out; - } - - numberSet_Add(out, out_connection); - return out; -} - -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); -} - -static void _strategyRnd_AddNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyRnd *srnd = (StrategyRnd *)strategy->context; - if (!numberSet_Contains(srnd->nexthops, connectionId)) { - numberSet_Add(srnd->nexthops, connectionId); - } -} - -static void _strategyRnd_RemoveNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyRnd *srnd = (StrategyRnd *)strategy->context; - - if (numberSet_Contains(srnd->nexthops, connectionId)) { - numberSet_Remove(srnd->nexthops, connectionId); - } -} - -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; - StrategyRnd *strategy = (StrategyRnd *)impl->context; - - numberSet_Release(&(strategy->nexthops)); - - parcMemory_Deallocate((void **)&strategy); - parcMemory_Deallocate((void **)&impl); - *strategyPtr = NULL; -} diff --git a/hicn-light/src/strategies/rnd.h b/hicn-light/src/strategies/rnd.h deleted file mode 100644 index 69bedc1a5..000000000 --- a/hicn-light/src/strategies/rnd.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 randomly - */ - -#ifndef rnd_h -#define rnd_h - -#include - -StrategyImpl* strategyRnd_Create(); -#endif // rnd_h diff --git a/hicn-light/src/strategies/rndSegment.c b/hicn-light/src/strategies/rndSegment.c deleted file mode 100644 index 5ed9bf1a9..000000000 --- a/hicn-light/src/strategies/rndSegment.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -static void _strategyRndSegment_ReceiveObject(StrategyImpl *strategy, - const NumberSet *egressId, - const Message *objectMessage, - Ticks rtt); -static void _strategyRndSegment_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId); -static NumberSet *_strategyRndSegment_LookupNexthop( - StrategyImpl *strategy, const Message *interestMessage); -static NumberSet *_strategyRndSegment_ReturnNexthops(StrategyImpl *strategy); -static unsigned _strategyRndSegment_CountNexthops(StrategyImpl *strategy); -static void _strategyRndSegment_AddNexthop(StrategyImpl *strategy, - unsigned connectionId); -static void _strategyRndSegment_RemoveNexthop(StrategyImpl *strategy, - unsigned connectionId); -static void _strategyRndSegment_ImplDestroy(StrategyImpl **strategyPtr); -static strategy_type _strategyRndSegment_GetStrategy(StrategyImpl *strategy); - -static StrategyImpl _template = { - .context = NULL, - .receiveObject = &_strategyRndSegment_ReceiveObject, - .onTimeout = &_strategyRndSegment_OnTimeout, - .lookupNexthop = &_strategyRndSegment_LookupNexthop, - .returnNexthops = &_strategyRndSegment_ReturnNexthops, - .countNexthops = &_strategyRndSegment_CountNexthops, - .addNexthop = &_strategyRndSegment_AddNexthop, - .removeNexthop = &_strategyRndSegment_RemoveNexthop, - .destroy = &_strategyRndSegment_ImplDestroy, - .getStrategy = &_strategyRndSegment_GetStrategy, -}; - -struct strategy_rnd_segment; -typedef struct strategy_rnd_segment StrategyRndSegment; - -struct strategy_rnd_segment { - NumberSet *nexthops; - NameBitvector *segmentName; - int last_used_face; -}; - -StrategyImpl *strategyRndSegment_Create() { - StrategyRndSegment *strategy = - parcMemory_AllocateAndClear(sizeof(StrategyRndSegment)); - parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(StrategyRndSegment)); - - strategy->nexthops = numberSet_Create(); - strategy->segmentName = NULL; - strategy->last_used_face = 0; - 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 _strategyRndSegment_GetStrategy(StrategyImpl *strategy) { - return SET_STRATEGY_RANDOM_PER_DASH_SEGMENT; -} - -static int _select_Nexthop(StrategyRndSegment *strategy) { - unsigned len = (unsigned)numberSet_Length(strategy->nexthops); - if (len == 0) { - return -1; - } - - int rnd = (rand() % len); - return numberSet_GetItem(strategy->nexthops, rnd); -} - -static void _strategyRndSegment_ReceiveObject(StrategyImpl *strategy, - const NumberSet *egressId, - const Message *objectMessage, - Ticks rtt) {} - -static void _strategyRndSegment_OnTimeout(StrategyImpl *strategy, - const NumberSet *egressId) {} - -static NumberSet *_strategyRndSegment_LookupNexthop( - StrategyImpl *strategy, const Message *interestMessage) { - StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; - - unsigned in_connection = message_GetIngressConnectionId(interestMessage); - unsigned nexthopSize = (unsigned)numberSet_Length(srnd->nexthops); - - NumberSet *out = numberSet_Create(); - 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; - } - - NameBitvector *interestName = - name_GetContentName(message_GetName(interestMessage)); - - if (srnd->segmentName == NULL) { - srnd->segmentName = nameBitvector_Copy(interestName); - } else if (!nameBitvector_Equals(srnd->segmentName, interestName)) { - nameBitvector_Destroy(&srnd->segmentName); - srnd->segmentName = nameBitvector_Copy(interestName); - } else { - // here we need to check if the output face still exists or if someone erase - // it - if (numberSet_Contains(srnd->nexthops, srnd->last_used_face)) { - // face exists, so keep using it! - numberSet_Add(out, srnd->last_used_face); - return out; - } else { - // the face does not exists anymore, try to find a new face but keep the - // name of the dash segment - } - } - - int out_connection; - do { - out_connection = _select_Nexthop(srnd); - } while (out_connection == in_connection); - - if (out_connection == -1) { - return out; - } - - srnd->last_used_face = out_connection; - numberSet_Add(out, out_connection); - return out; -} - -static NumberSet *_strategyRndSegment_ReturnNexthops(StrategyImpl *strategy) { - StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; - return srnd->nexthops; -} - -unsigned _strategyRndSegment_CountNexthops(StrategyImpl *strategy) { - StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; - return (unsigned)numberSet_Length(srnd->nexthops); -} - -static void _strategyRndSegment_AddNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; - if (!numberSet_Contains(srnd->nexthops, connectionId)) { - numberSet_Add(srnd->nexthops, connectionId); - } -} - -static void _strategyRndSegment_RemoveNexthop(StrategyImpl *strategy, - unsigned connectionId) { - StrategyRndSegment *srnd = (StrategyRndSegment *)strategy->context; - - if (numberSet_Contains(srnd->nexthops, connectionId)) { - numberSet_Remove(srnd->nexthops, connectionId); - } -} - -static void _strategyRndSegment_ImplDestroy(StrategyImpl **strategyPtr) { - parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer"); - parcAssertNotNull(*strategyPtr, - "Parameter must dereference to non-null pointer"); - - StrategyImpl *impl = *strategyPtr; - StrategyRndSegment *strategy = (StrategyRndSegment *)impl->context; - - numberSet_Release(&(strategy->nexthops)); - if (strategy->segmentName != NULL) { - nameBitvector_Destroy(&strategy->segmentName); - } - - parcMemory_Deallocate((void **)&strategy); - parcMemory_Deallocate((void **)&impl); - *strategyPtr = NULL; -} diff --git a/hicn-light/src/strategies/rndSegment.h b/hicn-light/src/strategies/rndSegment.h deleted file mode 100644 index 0749692f7..000000000 --- a/hicn-light/src/strategies/rndSegment.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. - */ - -/** - * Forward randomly, selects a path every time the client ask for a new dash - * segment - */ - -#ifndef rnd_Segment_h -#define rnd_Segment_h - -#include - -StrategyImpl* strategyRndSegment_Create(); -#endif // rnd_Segment_h diff --git a/hicn-light/src/strategies/strategyImpl.h b/hicn-light/src/strategies/strategyImpl.h deleted file mode 100644 index c089e0b2b..000000000 --- a/hicn-light/src/strategies/strategyImpl.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 -#include - -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 rtt); - void (*onTimeout)(StrategyImpl *strategy, const NumberSet *egressId); - NumberSet *(*lookupNexthop)(StrategyImpl *strategy, - const Message *interestMessage); - NumberSet *(*returnNexthops)(StrategyImpl *strategy); - unsigned (*countNexthops)(StrategyImpl *strategy); - 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/utils/CMakeLists.txt b/hicn-light/src/utils/CMakeLists.txt deleted file mode 100644 index 120061211..000000000 --- a/hicn-light/src/utils/CMakeLists.txt +++ /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. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -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}/punting.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}/punting.c - ${CMAKE_CURRENT_SOURCE_DIR}/utils.c -) - -set(TO_INSTALL_HEADER_FILES - ${TO_INSTALL_HEADER_FILES} - ${CMAKE_CURRENT_SOURCE_DIR}/commands.h - PARENT_SCOPE -) - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/hicn-light/src/utils/address.c b/hicn-light/src/utils/address.c deleted file mode 100644 index a59c6a59d..000000000 --- a/hicn-light/src/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 -#include -#endif -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -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/utils/address.h b/hicn-light/src/utils/address.h deleted file mode 100644 index ca3141ede..000000000 --- a/hicn-light/src/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 -#include -#endif -#include - -#include -#include -#include - -/** - * 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(©); - * } - * @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(©); - * } - * @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/utils/addressList.c b/hicn-light/src/utils/addressList.c deleted file mode 100644 index 4f51a11bf..000000000 --- a/hicn-light/src/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 -#include - -#include - -#include - -#include -#include -#include - -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/utils/addressList.h b/hicn-light/src/utils/addressList.h deleted file mode 100644 index bcb312c14..000000000 --- a/hicn-light/src/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 - -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/utils/commands.h b/hicn-light/src/utils/commands.h deleted file mode 100644 index 9527e5064..000000000 --- a/hicn-light/src/utils/commands.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES 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 -#include -#endif - -#include -#include - -typedef struct in6_addr ipv6_addr_t; -typedef uint32_t ipv4_addr_t; - -union commandAddr { - ipv4_addr_t ipv4; - ipv6_addr_t ipv6; -}; - -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_ROUTE, - CACHE_STORE, - CACHE_SERVE, - CACHE_CLEAR, - SET_STRATEGY, - SET_WLDR, - ADD_PUNTING, - LIST_LISTENERS, - MAPME_ENABLE, - MAPME_DISCOVERY, - MAPME_TIMESCALE, - MAPME_RETX, - 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[16]; - // char interfaceName[16]; - union commandAddr address; - uint16_t port; - // uint16_t etherType; - uint8_t addressType; - uint8_t listenerMode; - uint8_t connectionType; -} add_listener_command; - -// SIZE=40 - -//========== [01] ADD CONNECTION ========== - -typedef struct { - char symbolic[16]; - union commandAddr remoteIp; - union commandAddr localIp; - uint16_t remotePort; - uint16_t localPort; - uint8_t ipType; - uint8_t connectionType; -} 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; -} list_connections_command; - -// SIZE=64 - -//========== [03] ADD ROUTE ========== - -typedef struct { - char symbolicOrConnid[16]; - union commandAddr address; - uint16_t cost; - uint8_t addressType; - uint8_t len; -} add_route_command; - -// SIZE=36 - -//========== [04] LIST ROUTE ========== - -typedef struct { - union commandAddr 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[16]; -} remove_connection_command; - -// SIZE=16 - -//========== [06] REMOVE ROUTE ========== - -typedef struct { - char symbolicOrConnid[16]; - union commandAddr address; - uint8_t addressType; - uint8_t len; -} remove_route_command; - -// SIZE=36 - -//========== [07] CACHE STORE ========== - -typedef struct { - uint8_t activate; -} cache_store_command; - -// SIZE=1 - -//========== [08] CACHE SERVE ========== - -typedef struct { - uint8_t activate; -} cache_serve_command; - -// SIZE=1 - -//========== [09] SET STRATEGY ========== - -typedef enum { - SET_STRATEGY_LOADBALANCER, - SET_STRATEGY_RANDOM, - SET_STRATEGY_RANDOM_PER_DASH_SEGMENT, - SET_STRATEGY_LOADBALANCER_WITH_DELAY, - SET_STRATEGY_LOADBALANCER_BY_RATE, - SET_STRATEGY_LOADBALANCER_BEST_ROUTE, - LAST_STRATEGY_VALUE -} strategy_type; - -typedef struct { - union commandAddr address; - uint8_t strategyType; - uint8_t addressType; - uint8_t len; -} set_strategy_command; - -// SIZE=20 - -//========== [11] SET WLDR ========== - -typedef struct { - char symbolicOrConnid[16]; - uint8_t activate; -} set_wldr_command; - -// SIZE=17 - -//========== [12] ADD PUNTING ========== - -typedef struct { - char symbolicOrConnid[16]; - union commandAddr address; - uint8_t addressType; - uint8_t len; -} add_punting_command; - -// SIZE=36 - -//========== [13] LIST LISTENER ========== - -typedef struct { - union commandAddr address; - uint32_t connid; - uint16_t port; - uint8_t addressType; - uint8_t encapType; -} list_listeners_command; - -// SIZE=24 - -//========== [14] MAPME ========== - -// (enable/discovery/timescale/retx) - -typedef struct { - uint8_t activate; -} mapme_activator_command; - -// SIZE=1 - -typedef struct { - uint32_t timePeriod; -} mapme_timing_command; - -// SIZE=1 - -//===== 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_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 LAST_COMMAND_VALUE: - return 0; - default: - return 0; - } -} -#endif diff --git a/hicn-light/src/utils/interface.c b/hicn-light/src/utils/interface.c deleted file mode 100644 index ab7a88f0f..000000000 --- a/hicn-light/src/utils/interface.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -struct interface { - char *name; - unsigned interfaceIndex; - bool loopback; - bool supportMulticast; - unsigned mtu; - - AddressList *addressList; -}; - -char *interfaceToString(const Interface *interface) { - PARCBufferComposer *composer = parcBufferComposer_Create(); - - parcBufferComposer_Format( - composer, "%3u %10s %1s%1s %8u ", interface->interfaceIndex, - interface->name, interface->loopback ? "l" : " ", - interface->supportMulticast ? "m" : " ", interface->mtu); - - for (size_t i = 0; i < addressListLength(interface->addressList); i++) { - addressBuildString(addressListGetItem(interface->addressList, i), composer); - if (i < (addressListLength(interface->addressList) - 1)) { - parcBufferComposer_PutStrings(composer, "\n", NULL); - } - } - - PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); - char *result = parcBuffer_ToString(tempBuffer); - parcBuffer_Release(&tempBuffer); - parcBufferComposer_Release(&composer); - return result; -} - -Interface *interfaceCreate(const char *name, unsigned interfaceIndex, - bool loopback, bool supportMulticast, unsigned mtu) { - Interface *iface = parcMemory_AllocateAndClear(sizeof(Interface)); - - parcAssertNotNull(iface, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(Interface)); - iface->name = parcMemory_StringDuplicate(name, 64); - iface->interfaceIndex = interfaceIndex; - iface->loopback = loopback; - iface->supportMulticast = supportMulticast; - iface->mtu = mtu; - iface->addressList = addressListCreate(); - - return iface; -} - -void interfaceDestroy(Interface **interfacePtr) { - parcAssertNotNull(interfacePtr, "Parameter must be non-null double pointer"); - parcAssertNotNull(*interfacePtr, - "Parameter must dereference to non-null pointer"); - - Interface *iface = *interfacePtr; - parcMemory_Deallocate((void **)&iface->name); - addressListDestroy(&iface->addressList); - parcMemory_Deallocate((void **)&iface); - interfacePtr = NULL; -} - -void interfaceAddAddress(Interface *iface, Address *address) { - parcAssertNotNull(iface, "Parameter iface must be non-null"); - - size_t length = addressListLength(iface->addressList); - for (size_t i = 0; i < length; i++) { - const Address *a = addressListGetItem(iface->addressList, i); - if (addressEquals(a, address)) { - return; - } - } - - addressListAppend(iface->addressList, address); -} - -const AddressList *interfaceGetAddresses(const Interface *iface) { - parcAssertNotNull(iface, "Parameter iface must be non-null"); - return iface->addressList; -} - -unsigned interfaceGetInterfaceIndex(const Interface *iface) { - parcAssertNotNull(iface, "Parameter iface must be non-null"); - return iface->interfaceIndex; -} - -bool interfaceNameEquals(const Interface *iface, const char *name) { - parcAssertNotNull(iface, "Parameter iface must be non-null"); - - if (strcasecmp(iface->name, name) == 0) { - return true; - } - return false; -} - -bool interfaceEquals(const Interface *a, const Interface *b) { - if (a == NULL && b == NULL) { - return true; - } - - if (a == NULL || b == NULL) { - return false; - } - - if (a->interfaceIndex == b->interfaceIndex) { - if (a->loopback == b->loopback) { - if (a->supportMulticast == b->supportMulticast) { - if (a->mtu == b->mtu) { - if (strcasecmp(a->name, b->name) == 0) { - if (addressListEquals(a->addressList, b->addressList)) { - return true; - } - } - } - } - } - } - return false; -} - -// static const char light_Iface[] = "Interface"; -// static const char light_IfName[] = "Name"; -// static const char light_IFIDX[] = "Index"; -// static const char light_IsLoopback[] = "Loopback"; -// static const char light_Multicast[] = "Multicast"; -// static const char light_MTU[] = "MTU"; - -// static const char light_True[] = "true"; -// static const char light_False[] = "false"; -// static const char light_Addrs[] = "Addrs"; - -const char *interfaceGetName(const Interface *iface) { - parcAssertNotNull(iface, "Parameter iface must be non-null"); - return iface->name; -} - -unsigned interfaceGetMTU(const Interface *iface) { - parcAssertNotNull(iface, "Parameter iface must be non-null"); - return iface->mtu; -} diff --git a/hicn-light/src/utils/interface.h b/hicn-light/src/utils/interface.h deleted file mode 100644 index 0810ec053..000000000 --- a/hicn-light/src/utils/interface.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 <#Brief Description#> - * - * <#Detailed Description#> - * - */ -#ifndef interface_h -#define interface_h - -#include -#include - -struct interface; -typedef struct interface Interface; - -/** - * Creates a representation of an interface - * - * The name is copied. Creates a representation of a system interface. - * - * @param <#param1#> - * @return An allocated object, you must call interfaceDestroy() - * - * Example: - * @code - * <#example#> - * @endcode - */ -Interface *interfaceCreate(const char *name, unsigned interfaceIndex, - bool loopback, bool supportMulticast, unsigned mtu); - -void interfaceDestroy(Interface **interfacePtr); - -/** - * Adds an address to an interface - * - * Does not allow duplicates, if already exists is not added again - * - * @param <#param1#> - * @return <#return#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -void interfaceAddAddress(Interface *iface, Address *address); - -/** - * Retrieves a list of interface addresses - * - * <#Discussion#> - * - * @param <#param1#> - * @return Will not be NULL, but may be empty - * - * Example: - * @code - * <#example#> - * @endcode - */ -const AddressList *interfaceGetAddresses(const Interface *iface); - -/** - * The interface index - * - * <#Discussion#> - * - * @param <#param1#> - * @return <#return#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -unsigned interfaceGetInterfaceIndex(const Interface *iface); - -/** - * Returns the interface name, e.g. "eth0" - * - * <#Paragraphs Of Explanation#> - * - * @param [in] iface An allocated Interface - * - * @return non-null The interface Name as a C-string - * @return null An error - * - * Example: - * @code - * <#example#> - * @endcode - */ -const char *interfaceGetName(const Interface *iface); - -/** - * Returns the Maximum Transmission Unit (MTU) of the interface - * - * <#Paragraphs Of Explanation#> - * - * @param [in] iface An allocated Interface - * - * @return number The MTU as reported by the kernel - * - * Example: - * @code - * { - * <#example#> - * } - * @endcode - */ -unsigned interfaceGetMTU(const Interface *iface); - -/** - * Determine if two InterfaceName instances are equal. - * - * - * The following equivalence relations on non-null `InterfaceName` instances are - * maintained: - * - * * It is reflexive: for any non-null reference value x, - * `InterfaceName_Equals(x, x)` must return true. - * - * * It is symmetric: for any non-null reference values x and y, - * `InterfaceName_Equals(x, y)` must return true if and only if - * `InterfaceName_Equals(y, x)` returns true. - * - * * It is transitive: for any non-null reference values x, y, and z, if - * `InterfaceName_Equals(x, y)` returns true and - * `InterfaceName_Equals(y, z)` returns true, - * then `InterfaceName_Equals(x, z)` must return true. - * - * * It is consistent: for any non-null reference values x and y, multiple - * invocations of `InterfaceName_Equals(x, y)` consistently return true or - * consistently return false. - * - * * For any non-null reference value x, `InterfaceName_Equals(x, NULL)` must - * return false. - * - * @param a A pointer to a `InterfaceName` instance. - * @param b A pointer to a `InterfaceName` instance. - * @return true if the two `InterfaceName` instances are equal. - * - * Example: - * @code - * { - * InterfaceName *a = InterfaceName_Create(); - * InterfaceName *b = InterfaceName_Create(); - * - * if (InterfaceName_Equals(a, b)) { - * // true - * } else { - * // false - * } - * } - * @endcode - */ -bool interfaceNameEquals(const Interface *iface, const char *name); - -/** - * Two Interfaces are idential - * - * All properties must be the same. The order of addresses matters, and - * they must have been added to the address list in the same order. - * - * The interface name match is case in-sensitive. - * - * @param <#param1#> - * @return <#return#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -bool interfaceEquals(const Interface *a, const Interface *b); - -/** - * <#OneLineDescription#> - * - * <#Discussion#> - * - * @param interface A Interface structure pointer. - * @return An allocate string representation of the Interface that must be freed - * via parcMemory_Deallocate(). - * - * Example: - * @code - * <#example#> - * @endcode - */ -char *interfaceToString(const Interface *interface); -#endif // interface_h diff --git a/hicn-light/src/utils/interfaceSet.c b/hicn-light/src/utils/interfaceSet.c deleted file mode 100644 index 3f56ec167..000000000 --- a/hicn-light/src/utils/interfaceSet.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include - -#include -#include - -#include - -struct interfaceSet { - PARCArrayList *listOfInterfaces; -}; - -static void _destroyInterface(void **ifaceVoidPtr) { - interfaceDestroy((Interface **)ifaceVoidPtr); -} - -InterfaceSet *interfaceSetCreate(void) { - InterfaceSet *set = parcMemory_AllocateAndClear(sizeof(InterfaceSet)); - parcAssertNotNull(set, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(InterfaceSet)); - set->listOfInterfaces = parcArrayList_Create(_destroyInterface); - return set; -} - -void interfaceSetDestroy(InterfaceSet **setPtr) { - parcAssertNotNull(setPtr, "Parameter must be non-null double pointer"); - parcAssertNotNull(*setPtr, "Parameter must dereference to non-null pointer"); - - InterfaceSet *set = *setPtr; - parcArrayList_Destroy(&set->listOfInterfaces); - parcMemory_Deallocate((void **)&set); - *setPtr = NULL; -} - -bool interfaceSetAdd(InterfaceSet *set, Interface *iface) { - parcAssertNotNull(set, "Parameter set must be non-null"); - parcAssertNotNull(iface, "Parameter iface must be non-null"); - - unsigned ifaceIndex = interfaceGetInterfaceIndex(iface); - size_t length = parcArrayList_Size(set->listOfInterfaces); - for (size_t i = 0; i < length; i++) { - Interface *listEntry = - (Interface *)parcArrayList_Get(set->listOfInterfaces, i); - unsigned entryInterfaceIndex = interfaceGetInterfaceIndex(listEntry); - if (entryInterfaceIndex == ifaceIndex) { - return false; - } - } - - parcArrayList_Add(set->listOfInterfaces, (PARCObject *)iface); - return true; -} - -size_t interfaceSetLength(const InterfaceSet *set) { - parcAssertNotNull(set, "Parameter set must be non-null"); - return parcArrayList_Size(set->listOfInterfaces); -} - -Interface *interfaceSetGetByOrdinalIndex(InterfaceSet *set, - size_t ordinalIndex) { - parcAssertNotNull(set, "Parameter set must be non-null"); - return (Interface *)parcArrayList_Get(set->listOfInterfaces, ordinalIndex); -} - -Interface *interfaceSetGetByInterfaceIndex(const InterfaceSet *set, - unsigned interfaceIndex) { - size_t length = parcArrayList_Size(set->listOfInterfaces); - for (size_t i = 0; i < length; i++) { - Interface *listEntry = - (Interface *)parcArrayList_Get(set->listOfInterfaces, i); - unsigned entryInterfaceIndex = interfaceGetInterfaceIndex(listEntry); - if (entryInterfaceIndex == interfaceIndex) { - return listEntry; - } - } - return NULL; -} - -/** - * Uses the system name (e.g. "en0") - * - * <#Discussion#> - * - * @param <#param1#> - * @return NULL if not found - * - * Example: - * @code - * <#example#> - * @endcode - */ -Interface *interfaceSetGetByName(InterfaceSet *set, const char *name) { - size_t length = parcArrayList_Size(set->listOfInterfaces); - for (size_t i = 0; i < length; i++) { - Interface *listEntry = - (Interface *)parcArrayList_Get(set->listOfInterfaces, i); - if (interfaceNameEquals(listEntry, name)) { - return listEntry; - } - } - return NULL; -} - -bool interfaceSetEquals(const InterfaceSet *a, const InterfaceSet *b) { - if (a == NULL && b == NULL) { - return true; - } - - if (a == NULL || b == NULL) { - return false; - } - - size_t length_a = parcArrayList_Size(a->listOfInterfaces); - size_t length_b = parcArrayList_Size(b->listOfInterfaces); - - if (length_a == length_b) { - for (size_t i = 0; i < length_a; i++) { - Interface *iface_a = - (Interface *)parcArrayList_Get(a->listOfInterfaces, i); - - // the set is unique by interface id, so if it exists in set b, it - // exists there by interface id - Interface *iface_b = interfaceSetGetByInterfaceIndex( - b, interfaceGetInterfaceIndex(iface_a)); - if (!interfaceEquals(iface_b, iface_b)) { - return false; - } - } - return true; - } - return false; -} diff --git a/hicn-light/src/utils/interfaceSet.h b/hicn-light/src/utils/interfaceSet.h deleted file mode 100644 index 8eb8397fb..000000000 --- a/hicn-light/src/utils/interfaceSet.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 <#Brief Description#> - * - * <#Detailed Description#> - * - */ -#ifndef InterfaceSet_h -#define InterfaceSet_h - -#include - -struct interfaceSet; -/** - * - * @see interfaceSetCreate - */ -typedef struct interfaceSet InterfaceSet; - -/** - * <#One Line Description#> - * - * <#Paragraphs Of Explanation#> - * - * @param [<#in out in,out#>] <#name#> <#description#> - * - * @return <#value#> <#explanation#> - * - * Example: - * @code - * <#example#> - * @endcode - * - * @see <#references#> - */ -InterfaceSet *interfaceSetCreate(void); - -/** - * <#One Line Description#> - * - * <#Paragraphs Of Explanation#> - * - * @param [<#in out in,out#>] <#name#> <#description#> - * - * @return <#value#> <#explanation#> - * - * Example: - * @code - * <#example#> - * @endcode - * - * @see <#references#> - */ -void interfaceSetDestroy(InterfaceSet **setPtr); - -/** - * Adds interface to set, does not allow duplicates - * - * Takes ownership of the iface memory if added - * - * Duplicates are two entries with the same interface index - * - * @param <#param1#> - * @return true if added, false if not (likely a duplicate) - * - * Example: - * @code - * <#example#> - * @endcode - */ -bool interfaceSetAdd(InterfaceSet *set, Interface *iface); - -/** - * The number of interfaces in the set - * - * <#Discussion#> - * - * @param <#param1#> - * @return <#return#> - * - * Example: - * @code - * <#example#> - * @endcode - */ -size_t interfaceSetLength(const InterfaceSet *set); - -/** - * Uses the ordinal index of the interface in the Set - * - * Ranges from 0 .. interfaceSetLength()-1. - * - * @param <#param1#> - * @return NULL if not found - * - * Example: - * @code - * <#example#> - * @endcode - */ -Interface *interfaceSetGetByOrdinalIndex(InterfaceSet *set, - size_t ordinalIndex); - -/** - * Retreives by the assigned interface index - * - * <#Discussion#> - * - * @param <#param1#> - * @return NULL if not found - * - * Example: - * @code - * <#example#> - * @endcode - */ -Interface *interfaceSetGetByInterfaceIndex(const InterfaceSet *set, - unsigned interfaceIndex); - -/** - * Uses the system name (e.g. "en0") - * - * <#Discussion#> - * - * @param <#param1#> - * @return NULL if not found - * - * Example: - * @code - * <#example#> - * @endcode - */ -Interface *interfaceSetGetByName(InterfaceSet *set, const char *name); - -/** - * Determine if two InterfaceSet instances are equal. - * - * Two InterfaceSet instances are equal if, and only if, the sets contain the - * same elements - * - order independent. - * Each element is compared via interfaceEquals() - * - * The following equivalence relations on non-null `InterfaceSet` instances are - * maintained: - * - * * It is reflexive: for any non-null reference value x, - * `InterfaceSet_Equals(x, x)` must return true. - * - * * It is symmetric: for any non-null reference values x and y, - * `InterfaceSet_Equals(x, y)` must return true if and only if - * `interfaceSetEquals(y, x)` returns true. - * - * * It is transitive: for any non-null reference values x, y, and z, if - * `interfaceSetEquals(x, y)` returns true and - * `interfaceSetEquals(y, z)` returns true, - * then `interfaceSetEquals(x, z)` must return true. - * - * * It is consistent: for any non-null reference values x and y, multiple - * invocations of `interfaceSetEquals(x, y)` consistently return true or - * consistently return false. - * - * * For any non-null reference value x, `interfaceSetEquals(x, NULL)` must - * return false. - * - * @param a A pointer to a `InterfaceSet` instance. - * @param b A pointer to a `InterfaceSet` instance. - * @return true if the two `InterfaceSet` instances are equal. - * - * Example: - * @code - * { - * InterfaceSet *a = interfaceSetCreate(); - * InterfaceSet *b = interfaceSetCreate(); - * - * if (interfaceSetEquals(a, b)) { - * // true - * } else { - * // false - * } - * } - * @endcode - */ -bool interfaceSetEquals(const InterfaceSet *a, const InterfaceSet *b); -#endif // InterfaceSet_h diff --git a/hicn-light/src/utils/punting.c b/hicn-light/src/utils/punting.c deleted file mode 100644 index 9352732fe..000000000 --- a/hicn-light/src/utils/punting.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 -#include - -#include - -#include -#include - -struct punting { - char *symbolic; - Address *prefix; - uint32_t len; -}; - -Punting *puntingCreate(const char *listenerName, Address *prefix, - uint32_t len) { - parcAssertNotNull(listenerName, "Parameter listenerName must be non-null"); - parcAssertNotNull(prefix, "Parameter prefix must be non-null"); - - Punting *punting = parcMemory_AllocateAndClear(sizeof(Punting)); - if (punting) { - punting->symbolic = - parcMemory_StringDuplicate(listenerName, strlen(listenerName)); - punting->prefix = addressCopy(prefix); - punting->len = len; - } - - return punting; -} - -void puntingRelease(Punting **puntingPtr) { - parcAssertNotNull(puntingPtr, - "Parameter puntingPtr must be non-null double pointer"); - parcAssertNotNull(*puntingPtr, - "Parameter puntingPtr dereference to non-null pointer"); - - Punting *punting = *puntingPtr; - - if (punting->symbolic) { - parcMemory_Deallocate((void **)&punting->symbolic); - } - - if (punting->prefix) { - addressDestroy(&punting->prefix); - } - - parcMemory_Deallocate((void **)&punting); - *puntingPtr = NULL; -} - -bool puntingEquals(const Punting *a, const Punting *b) { - if ((a == NULL && b == NULL) || a == b) { - // both null or identically equal - return true; - } - - if (a == NULL || b == NULL) { - // only one is null - return false; - } - - if ((strcmp(a->symbolic, b->symbolic) == 0) && - (addressEquals(a->prefix, b->prefix)) && (a->len == b->len)) { - return true; - } - - return false; -} - -const char *puntingGetSymbolicName(const Punting *punting) { - parcAssertNotNull(punting, "Parameter listener must be non-null"); - return punting->symbolic; -} - -Address *puntingGetAddress(const Punting *punting) { - parcAssertNotNull(punting, "Parameter listener must be non-null"); - return punting->prefix; -} - -uint32_t puntingPrefixLen(const Punting *punting) { - parcAssertNotNull(punting, "Parameter listener must be non-null"); - return punting->len; -} diff --git a/hicn-light/src/utils/punting.h b/hicn-light/src/utils/punting.h deleted file mode 100644 index 03841c5ad..000000000 --- a/hicn-light/src/utils/punting.h +++ /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. - */ - -#ifndef punting_h -#define punting_h - -struct punting; -typedef struct punting Punting; - -#include - -/** - * Creates a Punting object - * - * The symbolic name represents this listener and may be used by other commands. - * It must be unique, otherwise the command will fail when sent to the - * forwarder. - * - * @param [in] symbolic name of the listener - * @param [in] prefix address to add to the punting rule - * @param [in] len prefix length - * - * @return non-null An Allocated object - * @return null An error - * - */ -Punting *puntingCreate(const char *symbolic, Address *prefix, uint32_t len); - -/** - * Releases a reference count to the object - * - * <#Paragraphs Of Explanation#> - * - * @param [in,out] etherConnPtr A pointer to an etherConn object, will be - * null'd. - * - */ -void puntingRelease(Punting **puntingPtr); - -/** - * Determine if two light Punting are equal. - * - */ - -bool puntingEquals(const Punting *a, const Punting *b); - -/** - * Returns the symbolic name - * - */ -const char *puntingGetSymbolicName(const Punting *punting); - -/** - * Returns the address (INET or INET6 ip address) - * - */ -Address *puntingGetAddress(const Punting *punting); - -uint32_t puntingPrefixLen(const Punting *punting); -#endif // punting_h diff --git a/hicn-light/src/utils/utils.c b/hicn-light/src/utils/utils.c deleted file mode 100644 index e40b219fb..000000000 --- a/hicn-light/src/utils/utils.c +++ /dev/null @@ -1,236 +0,0 @@ -// Utility function for commands - -#ifndef _WIN32 -#include -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -// 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, - union commandAddr *address, - in_port_t *port) { - char *result; - - switch (addressType) { - case ADDR_INET: { - result = utils_BuildStringFromInet(&address->ipv4, port); - break; - } - - case ADDR_INET6: { - result = utils_BuildStringFromInet6(&address->ipv6, 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, - union commandAddr *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/utils/utils.h b/hicn-light/src/utils/utils.h deleted file mode 100644 index 2c4efa965..000000000 --- a/hicn-light/src/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 -#include -#include - -/** - * 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, - union commandAddr *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, - union commandAddr *address, - uint8_t *prefixLen); - -#endif \ No newline at end of file -- cgit 1.2.3-korg