aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAngelo Mantellini <angelo.mantellini@cisco.com>2020-03-31 17:50:43 +0200
committerJordan Augé <jordan.auge+fdio@cisco.com>2020-04-27 11:26:51 +0200
commit15ad172a847fa667c57a4594ef4158405db9a984 (patch)
tree80c0bd083d7f206774f2b8fb3d0dacec06fde24f
parent23c3bb7400839b664096ad5e16a2346386109bda (diff)
[HICN-554] hicn-light refactoring
Change-Id: I36f2d393741d4502ce14d3791158e43e3e9cd4cf Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
-rw-r--r--.gitreview1
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/cfg.h2
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/facelet.h2
-rw-r--r--ctrl/facemgr/src/api.c6
-rw-r--r--ctrl/facemgr/src/cfg.c2
-rw-r--r--ctrl/facemgr/src/facelet.c14
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c2
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.h2
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.c2
-rw-r--r--ctrl/libhicnctrl/includes/CMakeLists.txt1
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/route.h2
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt3
-rw-r--r--ctrl/libhicnctrl/src/api.c14
-rw-r--r--hicn-light/CMakeLists.txt14
-rw-r--r--hicn-light/src/hicn/CMakeLists.txt22
-rw-r--r--hicn-light/src/hicn/base/CMakeLists.txt (renamed from hicn-light/src/hicn/messenger/CMakeLists.txt)26
-rw-r--r--hicn-light/src/hicn/base/bitmap.h55
-rw-r--r--hicn-light/src/hicn/base/common.h62
-rw-r--r--hicn-light/src/hicn/base/hash.h250
-rw-r--r--hicn-light/src/hicn/base/khash.h627
-rw-r--r--hicn-light/src/hicn/base/loop.c355
-rw-r--r--hicn-light/src/hicn/base/loop.h104
-rw-r--r--hicn-light/src/hicn/base/pool.c88
-rw-r--r--hicn-light/src/hicn/base/pool.h104
-rw-r--r--hicn-light/src/hicn/base/vector.c54
-rw-r--r--hicn-light/src/hicn/base/vector.h70
-rw-r--r--hicn-light/src/hicn/command_line/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/command_line/controller/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c1
-rw-r--r--hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c585
-rw-r--r--hicn-light/src/hicn/config.h.in3
-rw-r--r--hicn-light/src/hicn/config/CMakeLists.txt168
-rw-r--r--hicn-light/src/hicn/config/configuration.c2407
-rw-r--r--hicn-light/src/hicn/config/configuration.h51
-rw-r--r--hicn-light/src/hicn/config/configurationFile.c313
-rw-r--r--hicn-light/src/hicn/config/configurationListeners.c627
-rw-r--r--hicn-light/src/hicn/config/configurationListeners.h74
-rw-r--r--hicn-light/src/hicn/config/configuration_file.c292
-rw-r--r--hicn-light/src/hicn/config/configuration_file.h (renamed from hicn-light/src/hicn/config/configurationFile.h)32
-rw-r--r--hicn-light/src/hicn/config/controlAddConnection.c41
-rw-r--r--hicn-light/src/hicn/config/controlAddListener.c4
-rw-r--r--hicn-light/src/hicn/config/controlAddPolicy.c4
-rw-r--r--hicn-light/src/hicn/config/controlAddPunting.c4
-rw-r--r--hicn-light/src/hicn/config/controlAddRoute.c28
-rw-r--r--hicn-light/src/hicn/config/controlListConnections.c8
-rw-r--r--hicn-light/src/hicn/config/controlListListeners.c2
-rw-r--r--hicn-light/src/hicn/config/controlListPolicies.c30
-rw-r--r--hicn-light/src/hicn/config/controlListRoutes.c2
-rw-r--r--hicn-light/src/hicn/config/controlRemoveConnection.c1
-rw-r--r--hicn-light/src/hicn/config/controlRemoveListener.c1
-rw-r--r--hicn-light/src/hicn/config/controlRemovePolicy.c6
-rw-r--r--hicn-light/src/hicn/config/controlRemovePunting.c1
-rw-r--r--hicn-light/src/hicn/config/controlRemoveRoute.c6
-rw-r--r--hicn-light/src/hicn/config/controlSetStrategy.c29
-rw-r--r--hicn-light/src/hicn/config/controlState.c14
-rw-r--r--hicn-light/src/hicn/config/controlState.h2
-rw-r--r--hicn-light/src/hicn/config/symbolicNameTable.c191
-rw-r--r--hicn-light/src/hicn/content_store/CMakeLists.txt14
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreEntry.c136
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreEntry.h146
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreInterface.c57
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreInterface.h211
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreLRU.c462
-rw-r--r--hicn-light/src/hicn/content_store/contentStoreLRU.h39
-rw-r--r--hicn-light/src/hicn/content_store/listLRU.c135
-rw-r--r--hicn-light/src/hicn/content_store/listLRU.h94
-rw-r--r--hicn-light/src/hicn/content_store/listTimeOrdered.c94
-rw-r--r--hicn-light/src/hicn/content_store/listTimeOrdered.h103
-rw-r--r--hicn-light/src/hicn/content_store/lru.c190
-rw-r--r--hicn-light/src/hicn/content_store/lru.h (renamed from hicn-light/src/hicn/processor/pitStandard.h)39
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt54
-rw-r--r--hicn-light/src/hicn/core/address.c43
-rw-r--r--hicn-light/src/hicn/core/address.h88
-rw-r--r--hicn-light/src/hicn/core/address_pair.c33
-rw-r--r--hicn-light/src/hicn/core/address_pair.h48
-rw-r--r--hicn-light/src/hicn/core/connection.c720
-rw-r--r--hicn-light/src/hicn/core/connection.h279
-rw-r--r--hicn-light/src/hicn/core/connectionList.c68
-rw-r--r--hicn-light/src/hicn/core/connectionList.h70
-rw-r--r--hicn-light/src/hicn/core/connectionManager.c196
-rw-r--r--hicn-light/src/hicn/core/connectionManager.h37
-rw-r--r--hicn-light/src/hicn/core/connectionTable.c226
-rw-r--r--hicn-light/src/hicn/core/connectionTable.h99
-rw-r--r--hicn-light/src/hicn/core/connection_table.c89
-rw-r--r--hicn-light/src/hicn/core/connection_table.h126
-rw-r--r--hicn-light/src/hicn/core/connection_vft.c31
-rw-r--r--hicn-light/src/hicn/core/connection_vft.h51
-rw-r--r--hicn-light/src/hicn/core/content_store.c198
-rw-r--r--hicn-light/src/hicn/core/content_store.h125
-rw-r--r--hicn-light/src/hicn/core/dispatcher.c474
-rw-r--r--hicn-light/src/hicn/core/dispatcher.h288
-rw-r--r--hicn-light/src/hicn/core/fib.c531
-rw-r--r--hicn-light/src/hicn/core/fib.h60
-rw-r--r--hicn-light/src/hicn/core/fib_entry.c503
-rw-r--r--hicn-light/src/hicn/core/fib_entry.h166
-rw-r--r--hicn-light/src/hicn/core/forwarder.c1370
-rw-r--r--hicn-light/src/hicn/core/forwarder.h225
-rw-r--r--hicn-light/src/hicn/core/listener.c326
-rw-r--r--hicn-light/src/hicn/core/listener.h97
-rw-r--r--hicn-light/src/hicn/core/listener_table.c107
-rw-r--r--hicn-light/src/hicn/core/listener_table.h106
-rw-r--r--hicn-light/src/hicn/core/listener_vft.c31
-rw-r--r--hicn-light/src/hicn/core/listener_vft.h55
-rw-r--r--hicn-light/src/hicn/core/logger.c177
-rw-r--r--hicn-light/src/hicn/core/logger.h170
-rw-r--r--hicn-light/src/hicn/core/mapme.c1573
-rw-r--r--hicn-light/src/hicn/core/mapme.h46
-rw-r--r--hicn-light/src/hicn/core/message.c298
-rw-r--r--hicn-light/src/hicn/core/message.h180
-rw-r--r--hicn-light/src/hicn/core/messageHandler.h219
-rw-r--r--hicn-light/src/hicn/core/messagePacketType.h11
-rw-r--r--hicn-light/src/hicn/core/msgbuf.c (renamed from hicn-light/src/hicn/strategies/rnd.h)14
-rw-r--r--hicn-light/src/hicn/core/msgbuf.h80
-rw-r--r--hicn-light/src/hicn/core/name.c380
-rw-r--r--hicn-light/src/hicn/core/name.h7
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.c534
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.h4
-rw-r--r--hicn-light/src/hicn/core/nexthops.h154
-rw-r--r--hicn-light/src/hicn/core/numberSet.c203
-rw-r--r--hicn-light/src/hicn/core/numberSet.h157
-rw-r--r--hicn-light/src/hicn/core/packet_cache.c20
-rw-r--r--hicn-light/src/hicn/core/packet_cache.h20
-rw-r--r--hicn-light/src/hicn/core/pit.c227
-rw-r--r--hicn-light/src/hicn/core/pit.h92
-rw-r--r--hicn-light/src/hicn/core/prefix_stats.c202
-rw-r--r--hicn-light/src/hicn/core/prefix_stats.h91
-rw-r--r--hicn-light/src/hicn/core/strategy.c39
-rw-r--r--hicn-light/src/hicn/core/strategy.h70
-rw-r--r--hicn-light/src/hicn/core/strategy_vft.h76
-rw-r--r--hicn-light/src/hicn/core/system.h1
-rw-r--r--hicn-light/src/hicn/core/ticks.h33
-rw-r--r--hicn-light/src/hicn/core/wldr.c106
-rw-r--r--hicn-light/src/hicn/core/wldr.h19
-rw-r--r--hicn-light/src/hicn/io/CMakeLists.txt41
-rw-r--r--hicn-light/src/hicn/io/addressPair.c129
-rw-r--r--hicn-light/src/hicn/io/addressPair.h128
-rw-r--r--hicn-light/src/hicn/io/hicn.c522
-rw-r--r--hicn-light/src/hicn/io/hicnConnection.c541
-rw-r--r--hicn-light/src/hicn/io/hicnConnection.h53
-rw-r--r--hicn-light/src/hicn/io/hicnListener.c669
-rw-r--r--hicn-light/src/hicn/io/hicnListener.h42
-rw-r--r--hicn-light/src/hicn/io/hicnTunnel.c106
-rw-r--r--hicn-light/src/hicn/io/hicnTunnel.h65
-rw-r--r--hicn-light/src/hicn/io/ioOperations.c100
-rw-r--r--hicn-light/src/hicn/io/ioOperations.h449
-rw-r--r--hicn-light/src/hicn/io/listener.h128
-rw-r--r--hicn-light/src/hicn/io/listenerSet.c182
-rw-r--r--hicn-light/src/hicn/io/listenerSet.h188
-rw-r--r--hicn-light/src/hicn/io/streamConnection.c773
-rw-r--r--hicn-light/src/hicn/io/streamConnection.h76
-rw-r--r--hicn-light/src/hicn/io/tcp.c563
-rw-r--r--hicn-light/src/hicn/io/tcpListener.c262
-rw-r--r--hicn-light/src/hicn/io/tcpListener.h40
-rw-r--r--hicn-light/src/hicn/io/tcpTunnel.c43
-rw-r--r--hicn-light/src/hicn/io/tcpTunnel.h42
-rw-r--r--hicn-light/src/hicn/io/udp.c483
-rw-r--r--hicn-light/src/hicn/io/udpConnection.c495
-rw-r--r--hicn-light/src/hicn/io/udpConnection.h53
-rw-r--r--hicn-light/src/hicn/io/udpListener.c649
-rw-r--r--hicn-light/src/hicn/io/udpListener.h35
-rw-r--r--hicn-light/src/hicn/io/udpTunnel.c105
-rw-r--r--hicn-light/src/hicn/io/udpTunnel.h42
-rw-r--r--hicn-light/src/hicn/messenger/messenger.c171
-rw-r--r--hicn-light/src/hicn/messenger/messenger.h69
-rw-r--r--hicn-light/src/hicn/messenger/messengerRecipient.c62
-rw-r--r--hicn-light/src/hicn/messenger/messengerRecipient.h104
-rw-r--r--hicn-light/src/hicn/messenger/missive.c54
-rw-r--r--hicn-light/src/hicn/messenger/missive.h89
-rw-r--r--hicn-light/src/hicn/messenger/missiveDeque.c77
-rw-r--r--hicn-light/src/hicn/messenger/missiveDeque.h55
-rw-r--r--hicn-light/src/hicn/messenger/missiveType.h55
-rw-r--r--hicn-light/src/hicn/platforms/linux/system.c65
-rw-r--r--hicn-light/src/hicn/processor/CMakeLists.txt40
-rw-r--r--hicn-light/src/hicn/processor/fib.c548
-rw-r--r--hicn-light/src/hicn/processor/fib.h45
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.c891
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.h173
-rw-r--r--hicn-light/src/hicn/processor/fibEntryList.c72
-rw-r--r--hicn-light/src/hicn/processor/fibEntryList.h96
-rw-r--r--hicn-light/src/hicn/processor/hashTableFunction.c47
-rw-r--r--hicn-light/src/hicn/processor/hashTableFunction.h73
-rw-r--r--hicn-light/src/hicn/processor/matchingRulesTable.c132
-rw-r--r--hicn-light/src/hicn/processor/matchingRulesTable.h113
-rw-r--r--hicn-light/src/hicn/processor/messageProcessor.c908
-rw-r--r--hicn-light/src/hicn/processor/messageProcessor.h206
-rw-r--r--hicn-light/src/hicn/processor/pit.c45
-rw-r--r--hicn-light/src/hicn/processor/pit.h114
-rw-r--r--hicn-light/src/hicn/processor/pitEntry.c142
-rw-r--r--hicn-light/src/hicn/processor/pitEntry.h164
-rw-r--r--hicn-light/src/hicn/processor/pitStandard.c305
-rw-r--r--hicn-light/src/hicn/processor/pitVerdict.h40
-rw-r--r--hicn-light/src/hicn/strategies/CMakeLists.txt17
-rw-r--r--hicn-light/src/hicn/strategies/loadBalancer.c368
-rw-r--r--hicn-light/src/hicn/strategies/load_balancer.c174
-rw-r--r--hicn-light/src/hicn/strategies/load_balancer.h (renamed from hicn-light/src/hicn/core/connectionState.h)28
-rw-r--r--hicn-light/src/hicn/strategies/lowLatency.c851
-rw-r--r--hicn-light/src/hicn/strategies/lowLatency.h33
-rw-r--r--hicn-light/src/hicn/strategies/low_latency.c783
-rw-r--r--hicn-light/src/hicn/strategies/low_latency.h98
-rw-r--r--hicn-light/src/hicn/strategies/nexthopState.c212
-rw-r--r--hicn-light/src/hicn/strategies/nexthopState.h94
-rw-r--r--hicn-light/src/hicn/strategies/nexthopStateLowLatency.c285
-rw-r--r--hicn-light/src/hicn/strategies/random.c87
-rw-r--r--hicn-light/src/hicn/strategies/random.h (renamed from hicn-light/src/hicn/strategies/loadBalancer.h)14
-rw-r--r--hicn-light/src/hicn/strategies/rnd.c211
-rw-r--r--hicn-light/src/hicn/strategies/strategyImpl.h73
-rw-r--r--hicn-light/src/hicn/utils/CMakeLists.txt12
-rw-r--r--hicn-light/src/hicn/utils/address.c450
-rw-r--r--hicn-light/src/hicn/utils/address.h524
-rw-r--r--hicn-light/src/hicn/utils/addressList.c133
-rw-r--r--hicn-light/src/hicn/utils/addressList.h196
-rw-r--r--hicn-light/src/hicn/utils/commands.h561
-rw-r--r--hicn-light/src/hicn/utils/interface.c6
-rw-r--r--hicn-light/src/hicn/utils/interface.h7
-rw-r--r--hicn-light/src/hicn/utils/punting.c8
-rw-r--r--hicn-light/src/hicn/utils/punting.h19
-rw-r--r--hicn-light/src/hicn/utils/utils.c358
-rw-r--r--hicn-light/src/hicn/utils/utils.h36
-rw-r--r--hicn-plugin/src/mapme_ctrl_node.c12
-rw-r--r--hicn-plugin/src/mapme_eventmgr.c3
-rw-r--r--hicn-plugin/src/mapme_eventmgr.h2
-rw-r--r--lib/includes/CMakeLists.txt1
-rw-r--r--lib/includes/hicn/base.h9
-rw-r--r--lib/includes/hicn/face.h (renamed from ctrl/libhicnctrl/includes/hicn/ctrl/face.h)19
-rw-r--r--lib/includes/hicn/policy.h64
-rw-r--r--lib/includes/hicn/protocol/tcp.h6
-rw-r--r--lib/includes/hicn/util/ip_address.h2
-rw-r--r--lib/src/CMakeLists.txt6
-rw-r--r--lib/src/face.c (renamed from ctrl/libhicnctrl/src/face.c)26
-rw-r--r--lib/src/util/ip_address.c11
-rw-r--r--utils/src/hiperf.cc4
232 files changed, 14292 insertions, 24130 deletions
diff --git a/.gitreview b/.gitreview
index 2579a4a..ff42a10 100644
--- a/.gitreview
+++ b/.gitreview
@@ -2,3 +2,4 @@
host=gerrit.fd.io
port=29418
project=hicn
+defaultbranch=hicn-light-ng
diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
index 84d63fe..bb43633 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
@@ -20,7 +20,7 @@
#ifndef FACEMGR_CFG_H
#define FACEMGR_CFG_H
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/facemgr/facelet.h>
#include <hicn/util/log.h>
diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
index cfdc554..9ac61ac 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
@@ -28,7 +28,7 @@
#include <stdbool.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/ctrl/route.h>
#define MAXSZ_FACELET 1024
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index f934883..5d48e99 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -63,7 +63,7 @@
#include "interfaces/android_utility/android_utility.h"
#endif /* WITH_ANDROID_UTILITY */
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/facemgr/facelet.h>
#include "common.h"
#include "facelet_array.h"
@@ -655,7 +655,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
/* Default ignore list */
if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) {
DEBUG("Ignored interface '%s/%s'...", netdevice.name,
- netdevice_type_str[netdevice_type]);
+ netdevice_type_str(netdevice_type));
return -3;
}
@@ -666,7 +666,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
return -1;
if (ignore) {
DEBUG("Ignored interface '%s/%s'...", netdevice.name,
- netdevice_type_str[netdevice_type]);
+ netdevice_type_str(netdevice_type));
return -3;
}
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
index df73acd..872769d 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -182,7 +182,7 @@ void facemgr_cfg_rule_dump(facemgr_cfg_rule_t * rule)
DEBUG(" <rule>");
DEBUG(" <match interface_name=%s interface_type=%s>",
rule->match.interface_name,
- netdevice_type_str[rule->match.interface_type]);
+ netdevice_type_str(rule->match.interface_type));
DEBUG(" <override>");
if (rule->override.is_face_type) {
DEBUG(" <face_type>%d</face_type>", rule->override.face_type);
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 0cf44d4..1958749 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -20,7 +20,7 @@
#include <assert.h>
#include <stdbool.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include <hicn/ctrl/route.h>
#include <hicn/facemgr/cfg.h>
#include <hicn/facemgr/facelet.h>
@@ -1072,7 +1072,7 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
/* Netdevice type */
if (facelet_has_netdevice_type(facelet)) {
rc = snprintf(cur, s + size - cur, " type=%s",
- netdevice_type_str[facelet->netdevice_type]);
+ netdevice_type_str(facelet->netdevice_type));
if (rc < 0)
return rc;
cur += rc;
@@ -1141,7 +1141,7 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
/* Admin state */
if (facelet_has_admin_state(facelet)) {
rc = snprintf(cur, s + size - cur, " admin_state=%s",
- face_state_str[facelet->admin_state]);
+ face_state_str(facelet->admin_state));
if (rc < 0)
return rc;
cur += rc;
@@ -1152,7 +1152,7 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
/* State */
if (facelet_has_state(facelet)) {
rc = snprintf(cur, s + size - cur, " state=%s",
- face_state_str[facelet->state]);
+ face_state_str(facelet->state));
if (rc < 0)
return rc;
cur += rc;
@@ -1295,7 +1295,7 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int
if (facelet_has_netdevice_type(facelet)) {
rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
"\"netdevice_type\"",
- netdevice_type_str[facelet->netdevice_type]);
+ netdevice_type_str(facelet->netdevice_type));
if (rc < 0)
return rc;
cur += rc;
@@ -1383,7 +1383,7 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int
if (facelet_has_admin_state(facelet)) {
rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
"\"admin_state\"",
- face_state_str[facelet->admin_state]);
+ face_state_str(facelet->admin_state));
if (rc < 0)
return rc;
cur += rc;
@@ -1395,7 +1395,7 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int
if (facelet_has_state(facelet)) {
rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
"\"state\"",
- face_state_str[facelet->state]);
+ face_state_str(facelet->state));
if (rc < 0)
return rc;
cur += rc;
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
index d1fe324..55468ba 100644
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
+++ b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
@@ -20,8 +20,8 @@
#include <assert.h>
+#include <hicn/face.h>
#include <hicn/facemgr.h>
-#include <hicn/ctrl/face.h>
#include <hicn/util/log.h>
#include "../../common.h"
#include "../../interface.h"
diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
index fe05307..ece6dce 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h
@@ -25,7 +25,7 @@
* queries...
*/
-#include <hicn/ctrl/face.h> /* netdevice_t */
+#include <hicn/face.h> /* netdevice_t */
typedef struct {
netdevice_t netdevice;
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
index 2c4bff5..c8963d8 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
@@ -32,7 +32,7 @@
#include <hicn/util/map.h>
#include "../../common.h"
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
#include "../../interface.h"
#include "network_framework.h"
diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt
index 50cfa4a..36a55ca 100644
--- a/ctrl/libhicnctrl/includes/CMakeLists.txt
+++ b/ctrl/libhicnctrl/includes/CMakeLists.txt
@@ -21,7 +21,6 @@ set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ctrl.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/commands.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/face.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h
PARENT_SCOPE
)
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index c1eccbd..c3fb625 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -70,7 +70,7 @@
#include <hicn/util/ip_address.h>
#include <hicn/ctrl/commands.h>
-#include "face.h"
+#include <hicn/face.h>
#define HICN_DEFAULT_PORT 9695
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
index d7ef6a2..b2ca04f 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h
@@ -21,7 +21,7 @@
#define HICN_ROUTE_H
#include <hicn/util/ip_address.h>
-#include <hicn/ctrl/face.h>
+#include <hicn/face.h>
typedef u16 route_cost_t;
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index 00661a2..c3d8431 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -18,15 +18,12 @@ list(APPEND COMPILER_DEFINITIONS
set(HEADER_FILES
api.h
commands.h
- face.h
)
set(UTIL_HEADER_FILES
- face.h
)
set(SOURCE_FILES
- face.c
route.c
)
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 8dcb978..84f34d3 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -1640,7 +1640,7 @@ _hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
{
int rc;
DEBUG("[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s async=%s",
- conn_id_or_name, face_state_str[state], BOOLSTR(async));
+ conn_id_or_name, face_state_str(state), BOOLSTR(async));
struct {
header_control_message hdr;
connection_set_admin_state_command payload;
@@ -2602,11 +2602,11 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
face->id,
face->name,
face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
+ face_type_str(face->face.type),
local,
remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state],
+ face_state_str(face->face.state),
+ face_state_str(face->face.admin_state),
face->face.priority,
tags);
#else
@@ -2614,11 +2614,11 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
face->id,
face->name,
face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
+ face_type_str(face->face.type),
local,
remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state]);
+ face_state_str(face->face.state),
+ face_state_str(face->face.admin_state));
#endif /* WITH_POLICY */
}
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index db56fef..4a61505 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -50,27 +50,29 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DLIBRTA_DISABLE_VALIDATION
include(IosMacros)
include(WindowsMacros)
-find_package_wrapper(Libparc REQUIRED)
-
set(HICN_LIGHT hicn-light CACHE INTERNAL "" FORCE)
set(HICN_LIGHT_CONTROL ${HICN_LIGHT}-control CACHE INTERNAL "" FORCE)
set(HICN_LIGHT_DAEMON ${HICN_LIGHT}-daemon CACHE INTERNAL "" FORCE)
+find_package_wrapper(LibEvent REQUIRED)
+
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
find_package_wrapper(Libhicn REQUIRED)
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
- set(HICN_LIBRARIES ${LIBHICN_STATIC})
+ set(HICN_LIBRARIES ${LIBEVENT_STATIC} ${LIBHICN_STATIC})
else ()
- set(HICN_LIBRARIES ${LIBHICN_STATIC} log)
+ set(HICN_LIBRARIES ${LIBEVENT_STATIC} ${LIBHICN_STATIC} log)
endif ()
list(APPEND DEPENDENCIES
+ ${LIBEVENT_STATIC}
${LIBHICN_STATIC}
)
else ()
set(HICN_LIBRARIES ${LIBHICN_SHARED})
list(APPEND DEPENDENCIES
+ ${LIBEVENT_SHARED}
${LIBHICN_SHARED}
)
endif ()
@@ -86,7 +88,7 @@ set(LIBHICN_LIGHT_STATIC ${LIBHICN_LIGHT}.static)
set(HICN_LIGHT_LINK_LIBRARIES
${LIBHICN_LIGHT_STATIC}
${HICN_LIBRARIES}
- ${LIBPARC_LIBRARIES}
+ ${LIBEVENT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${WINDOWS_LIBRARIES}
)
@@ -95,7 +97,7 @@ set(HICN_LIGHT_LINK_LIBRARIES
# Include dirs -- Order does matter!
list(APPEND HICN_LIGHT_INCLUDE_DIRS
${HICN_INCLUDE_DIRS}
- ${LIBPARC_INCLUDE_DIRS}
+ ${LIBEVENT_INCLUDE_DIRS}
${WINDOWS_INCLUDE_DIRS}
)
diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt
index 82de74a..29b76da 100644
--- a/hicn-light/src/hicn/CMakeLists.txt
+++ b/hicn-light/src/hicn/CMakeLists.txt
@@ -3,6 +3,10 @@
include(BuildMacros)
configure_file(config.h.in hicn-light/config.h @ONLY)
+if(UNIX AND NOT APPLE)
+ set(LINUX TRUE)
+endif()
+
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND ENABLE_PUNTING)
list(APPEND COMPILER_DEFINITIONS
"-DPUNTING"
@@ -10,21 +14,33 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND ENABLE_PUNTING)
endif()
list(APPEND COMPILER_DEFINITIONS
+# "-DWITH_GRO"
+# "-DWITH_GSO"
+# "-DWITH_ZEROCOPY"
"-DWITH_MAPME"
- "-DWITH_POLICY"
+ "-DWITH_POLICY" # XXX Requires WITH_MAPME... enforce
+ "-DWITH_PREFIX_STATS"
+ "-DWITH_CLI"
+# "-DNDEBUG=1" # disable assertions
)
+if (LINUX)
+list(APPEND COMPILER_DEFINITIONS
+ "-D_GNU_SOURCE" # batching support through struct mmsghdr
+)
+endif()
+
+
if (NOT DISABLE_EXECUTABLES)
add_subdirectory(command_line)
endif()
+add_subdirectory(base)
add_subdirectory(config)
add_subdirectory(content_store)
add_subdirectory(core)
add_subdirectory(io)
-add_subdirectory(messenger)
add_subdirectory(platforms)
-add_subdirectory(processor)
add_subdirectory(socket)
add_subdirectory(strategies)
add_subdirectory(utils)
diff --git a/hicn-light/src/hicn/messenger/CMakeLists.txt b/hicn-light/src/hicn/base/CMakeLists.txt
index 92bc13b..5b2677e 100644
--- a/hicn-light/src/hicn/messenger/CMakeLists.txt
+++ b/hicn-light/src/hicn/base/CMakeLists.txt
@@ -14,19 +14,25 @@
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
+ ${CMAKE_CURRENT_SOURCE_DIR}/bitmap.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/common.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/khash.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/loop.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/pool.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/vector.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/messenger.c
- ${CMAKE_CURRENT_SOURCE_DIR}/messengerRecipient.c
- ${CMAKE_CURRENT_SOURCE_DIR}/missive.c
- ${CMAKE_CURRENT_SOURCE_DIR}/missiveDeque.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/loop.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pool.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/vector.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+
+set(TO_INSTALL_HEADER_FILES
+ ${TO_INSTALL_HEADER_FILES}
+ ${HEADER_FILES}
+ PARENT_SCOPE
+)
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
new file mode 100644
index 0000000..df94b80
--- /dev/null
+++ b/hicn-light/src/hicn/base/bitmap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file bitmap.h
+ * \brief Bitmap
+ *
+ * A bitmap is implemented as a wrapper over a vector made of bit elements
+ */
+
+#ifndef UTIL_BITMAP_H
+#define UTIL_BITMAP_H
+
+#include <string.h>
+#include "common.h"
+
+#define BITMAP_WIDTH(bitmap) (sizeof((bitmap)[0]) * 8)
+
+#define bitmap_init(bitmap, size) \
+ vector_init(bitmap, next_pow2(size / BITMAP_WIDTH(bitmap)))
+
+#define bitmap_ensure_pos(bitmap, pos) vector_ensure_pos(bitmap, pos / BITMAP_WIDTH(bitmap))
+
+#define bitmap_get(bitmap, i) ((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap))))
+
+#define bitmap_is_set(bitmap, i) (bitmap_get((bitmap), (i)) == 1)
+
+#define bitmap_is_unset(bitmap, i) (bitmap_get((bitmap), (i)) == 0)
+
+#define bitmap_set(bitmap, i) bitmap[(i) / BITMAP_WIDTH(bitmap)] |= 1 << ((i) % BITMAP_WIDTH(bitmap))
+
+#define bitmap_unset(bitmap, i) bitmap[(i) / BITMAP_WIDTH(bitmap)] &= ~ (1 << ((i) % BITMAP_WIDTH(bitmap)))
+
+#define bitmap_set_to(bitmap, pos) \
+do { \
+ size_t offset = (pos / BITMAP_WIDTH(bitmap) + 1); \
+ memset(bitmap, 0xFF, pos * sizeof(bitmap[0])); \
+ size_t set_bits = offset * BITMAP_WIDTH(bitmap); \
+ for (unsigned i = pos; i < set_bits; i++) \
+ bitmap_unset(bitmap, i); \
+} while(0);
+
+#endif /* UTIL_BITMAP_H */
diff --git a/hicn-light/src/hicn/base/common.h b/hicn-light/src/hicn/base/common.h
new file mode 100644
index 0000000..9960503
--- /dev/null
+++ b/hicn-light/src/hicn/base/common.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file array.h
+ * \brief Fixed-size pool allocator
+ */
+
+#ifndef UTIL_COMMON_H
+#define UTIL_COMMON_H
+
+#define round_pow2(x, pow2) ((x + pow2 - 1) & ~(pow2 - 1))
+
+#define _SIZEOF_ALIGNED(x, size) round_pow2(sizeof(x), size)
+#define SIZEOF_ALIGNED(x) _SIZEOF_ALIGNED(x, sizeof(void*))
+
+/* Definitions for builtins unavailable on MSVC */
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <intrin.h>
+
+uint32_t __inline __builtin_ctz(uint32_t value) {
+ uint32_t trailing_zero = 0;
+ if (_BitScanForward(&trailing_zero, value))
+ return trailing_zero;
+ else
+ return 32;
+}
+
+uint32_t __inline __builtin_clz(uint32_t value) {
+ uint32_t leading_zero = 0;
+ if (_BitScanReverse(&leading_zero, value))
+ return 31 - leading_zero;
+ else
+ return 32;
+}
+
+uint32_t __inline __builtin_clzll(uint64_t value) {
+ uint32_t leading_zero = 0;
+ if (_BitScanReverse64(&leading_zero, value))
+ return 63 - leading_zero;
+ else
+ return 64;
+}
+
+#define __builtin_clzl __builtin_clzll
+#endif
+
+#define next_pow2(x) (x == 1 ? 1 : 1<<(64-__builtin_clzl(x-1)))
+
+#endif /* UTIL_COMMON_H */
diff --git a/hicn-light/src/hicn/base/hash.h b/hicn-light/src/hicn/base/hash.h
new file mode 100644
index 0000000..0b6a659
--- /dev/null
+++ b/hicn-light/src/hicn/base/hash.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * \file hash.h
+ * \brief Simple non-cryptographic hash implementation.
+ *
+ * Two helpers are provided :
+ * hash(buf, len) : hash a buffer <buf> of length <len>
+ * hash_struct(buf) : hash a buffer corresponding to an allocated struct
+ *
+ * This file consists in excerpts from Jenkins hash (public domain).
+ * http://www.burtleburtle.net/bob/c/lookup3.c
+ */
+#ifndef UTIL_HASH_H
+#define UTIL_HASH_H
+
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+# define HASH_LITTLE_ENDIAN 1
+# define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 1
+#else
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+#define mix(a,b,c) \
+{ \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+}
+
+#define final(a,b,c) \
+{ \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c,4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+}
+
+static inline
+uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a,b,c; /* internal state */
+ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : return c;
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t)k[1])<<16);
+ b += k[2] + (((uint32_t)k[3])<<16);
+ c += k[4] + (((uint32_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t)k[5])<<16);
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : return c; /* zero length requires no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t)k[1])<<8;
+ a += ((uint32_t)k[2])<<16;
+ a += ((uint32_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t)k[5])<<8;
+ b += ((uint32_t)k[6])<<16;
+ b += ((uint32_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t)k[9])<<8;
+ c += ((uint32_t)k[10])<<16;
+ c += ((uint32_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t)k[11])<<24;
+ case 11: c+=((uint32_t)k[10])<<16;
+ case 10: c+=((uint32_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t)k[7])<<24;
+ case 7 : b+=((uint32_t)k[6])<<16;
+ case 6 : b+=((uint32_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t)k[3])<<24;
+ case 3 : a+=((uint32_t)k[2])<<16;
+ case 2 : a+=((uint32_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
+
+/* Helpers */
+
+#define HASH_INITVAL 1
+//#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL)
+#define hash(buf, len) hashlittle(buf, len, HASH_INITVAL)
+#define hash_struct(buf) hash(buf, sizeof(buf))
+
+#define str_hash(str) (hash(str, strlen(str)))
+#define str_hash_eq(a, b) (str_hash(b) - str_hash(a))
+
+#endif /* UTIL_JENKINS_HASH_H */
diff --git a/hicn-light/src/hicn/base/khash.h b/hicn-light/src/hicn/base/khash.h
new file mode 100644
index 0000000..f75f347
--- /dev/null
+++ b/hicn-light/src/hicn/base/khash.h
@@ -0,0 +1,627 @@
+/* The MIT License
+
+ Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+/*
+ An example:
+
+#include "khash.h"
+KHASH_MAP_INIT_INT(32, char)
+int main() {
+ int ret, is_missing;
+ khiter_t k;
+ khash_t(32) *h = kh_init(32);
+ k = kh_put(32, h, 5, &ret);
+ kh_value(h, k) = 10;
+ k = kh_get(32, h, 10);
+ is_missing = (k == kh_end(h));
+ k = kh_get(32, h, 5);
+ kh_del(32, h, k);
+ for (k = kh_begin(h); k != kh_end(h); ++k)
+ if (kh_exist(h, k)) kh_value(h, k) = 1;
+ kh_destroy(32, h);
+ return 0;
+}
+*/
+
+/*
+ 2013-05-02 (0.2.8):
+
+ * Use quadratic probing. When the capacity is power of 2, stepping function
+ i*(i+1)/2 guarantees to traverse each bucket. It is better than double
+ hashing on cache performance and is more robust than linear probing.
+
+ In theory, double hashing should be more robust than quadratic probing.
+ However, my implementation is probably not for large hash tables, because
+ the second hash function is closely tied to the first hash function,
+ which reduce the effectiveness of double hashing.
+
+ Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
+
+ 2011-12-29 (0.2.7):
+
+ * Minor code clean up; no actual effect.
+
+ 2011-09-16 (0.2.6):
+
+ * The capacity is a power of 2. This seems to dramatically improve the
+ speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
+
+ - http://code.google.com/p/ulib/
+ - http://nothings.org/computer/judy/
+
+ * Allow to optionally use linear probing which usually has better
+ performance for random input. Double hashing is still the default as it
+ is more robust to certain non-random input.
+
+ * Added Wang's integer hash function (not used by default). This hash
+ function is more robust to certain non-random input.
+
+ 2011-02-14 (0.2.5):
+
+ * Allow to declare global functions.
+
+ 2009-09-26 (0.2.4):
+
+ * Improve portability
+
+ 2008-09-19 (0.2.3):
+
+ * Corrected the example
+ * Improved interfaces
+
+ 2008-09-11 (0.2.2):
+
+ * Improved speed a little in kh_put()
+
+ 2008-09-10 (0.2.1):
+
+ * Added kh_clear()
+ * Fixed a compiling error
+
+ 2008-09-02 (0.2.0):
+
+ * Changed to token concatenation which increases flexibility.
+
+ 2008-08-31 (0.1.2):
+
+ * Fixed a bug in kh_get(), which has not been tested previously.
+
+ 2008-08-31 (0.1.1):
+
+ * Added destructor
+*/
+
+
+#ifndef __AC_KHASH_H
+#define __AC_KHASH_H
+
+/*!
+ @header
+
+ Generic hash table library.
+ */
+
+#define AC_VERSION_KHASH_H "0.2.8"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+/* compiler specific configuration */
+
+#if UINT_MAX == 0xffffffffu
+typedef unsigned int khint32_t;
+#elif ULONG_MAX == 0xffffffffu
+typedef unsigned long khint32_t;
+#endif
+
+#if ULONG_MAX == ULLONG_MAX
+typedef unsigned long khint64_t;
+#else
+typedef unsigned long long khint64_t;
+#endif
+
+#ifndef kh_inline
+#ifdef _MSC_VER
+#define kh_inline __inline
+#else
+#define kh_inline inline
+#endif
+#endif /* kh_inline */
+
+#ifndef klib_unused
+#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
+#define klib_unused __attribute__ ((__unused__))
+#else
+#define klib_unused
+#endif
+#endif /* klib_unused */
+
+typedef khint32_t khint_t;
+typedef khint_t khiter_t;
+
+#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
+#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
+#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
+#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
+#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
+#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
+#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
+
+#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
+
+#ifndef kroundup32
+#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
+#endif
+
+#ifndef kcalloc
+#define kcalloc(N,Z) calloc(N,Z)
+#endif
+#ifndef kmalloc
+#define kmalloc(Z) malloc(Z)
+#endif
+#ifndef krealloc
+#define krealloc(P,Z) realloc(P,Z)
+#endif
+#ifndef kfree
+#define kfree(P) free(P)
+#endif
+
+static const double __ac_HASH_UPPER = 0.77;
+
+#define __KHASH_TYPE(name, khkey_t, khval_t) \
+ typedef struct kh_##name##_s { \
+ khint_t n_buckets, size, n_occupied, upper_bound; \
+ khint32_t *flags; \
+ khkey_t *keys; \
+ khval_t *vals; \
+ } kh_##name##_t;
+
+#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
+ extern kh_##name##_t *kh_init_##name(void); \
+ extern void kh_destroy_##name(kh_##name##_t *h); \
+ extern void kh_clear_##name(kh_##name##_t *h); \
+ extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
+ extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
+ extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
+ extern void kh_del_##name(kh_##name##_t *h, khint_t x);
+
+#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+ SCOPE kh_##name##_t *kh_init_##name(void) { \
+ return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \
+ } \
+ SCOPE void kh_destroy_##name(kh_##name##_t *h) \
+ { \
+ if (h) { \
+ kfree((void *)h->keys); kfree(h->flags); \
+ kfree((void *)h->vals); \
+ kfree(h); \
+ } \
+ } \
+ SCOPE void kh_clear_##name(kh_##name##_t *h) \
+ { \
+ if (h && h->flags) { \
+ memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
+ h->size = h->n_occupied = 0; \
+ } \
+ } \
+ SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
+ { \
+ if (h->n_buckets) { \
+ khint_t k, i, last, mask, step = 0; \
+ mask = h->n_buckets - 1; \
+ k = __hash_func(key); i = k & mask; \
+ last = i; \
+ while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
+ i = (i + (++step)) & mask; \
+ if (i == last) return h->n_buckets; \
+ } \
+ return __ac_iseither(h->flags, i)? h->n_buckets : i; \
+ } else return 0; \
+ } \
+ SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
+ { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
+ khint32_t *new_flags = 0; \
+ khint_t j = 1; \
+ { \
+ kroundup32(new_n_buckets); \
+ if (new_n_buckets < 4) new_n_buckets = 4; \
+ if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
+ else { /* hash table size to be changed (shrink or expand); rehash */ \
+ new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
+ if (!new_flags) return -1; \
+ memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
+ if (h->n_buckets < new_n_buckets) { /* expand */ \
+ khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
+ if (!new_keys) { kfree(new_flags); return -1; } \
+ h->keys = new_keys; \
+ if (kh_is_map) { \
+ khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
+ if (!new_vals) { kfree(new_flags); return -1; } \
+ h->vals = new_vals; \
+ } \
+ } /* otherwise shrink */ \
+ } \
+ } \
+ if (j) { /* rehashing is needed */ \
+ for (j = 0; j != h->n_buckets; ++j) { \
+ if (__ac_iseither(h->flags, j) == 0) { \
+ khkey_t key = h->keys[j]; \
+ khval_t val; \
+ khint_t new_mask; \
+ new_mask = new_n_buckets - 1; \
+ if (kh_is_map) val = h->vals[j]; \
+ __ac_set_isdel_true(h->flags, j); \
+ while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
+ khint_t k, i, step = 0; \
+ k = __hash_func(key); \
+ i = k & new_mask; \
+ while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
+ __ac_set_isempty_false(new_flags, i); \
+ if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
+ { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
+ if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
+ __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
+ } else { /* write the element and jump out of the loop */ \
+ h->keys[i] = key; \
+ if (kh_is_map) h->vals[i] = val; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
+ h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
+ if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
+ } \
+ kfree(h->flags); /* free the working space */ \
+ h->flags = new_flags; \
+ h->n_buckets = new_n_buckets; \
+ h->n_occupied = h->size; \
+ h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
+ } \
+ return 0; \
+ } \
+ SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
+ { \
+ khint_t x; \
+ if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
+ if (h->n_buckets > (h->size<<1)) { \
+ if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
+ *ret = -1; return h->n_buckets; \
+ } \
+ } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
+ *ret = -1; return h->n_buckets; \
+ } \
+ } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
+ { \
+ khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
+ x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
+ if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
+ else { \
+ last = i; \
+ while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
+ if (__ac_isdel(h->flags, i)) site = i; \
+ i = (i + (++step)) & mask; \
+ if (i == last) { x = site; break; } \
+ } \
+ if (x == h->n_buckets) { \
+ if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
+ else x = i; \
+ } \
+ } \
+ } \
+ if (__ac_isempty(h->flags, x)) { /* not present at all */ \
+ h->keys[x] = key; \
+ __ac_set_isboth_false(h->flags, x); \
+ ++h->size; ++h->n_occupied; \
+ *ret = 1; \
+ } else if (__ac_isdel(h->flags, x)) { /* deleted */ \
+ h->keys[x] = key; \
+ __ac_set_isboth_false(h->flags, x); \
+ ++h->size; \
+ *ret = 2; \
+ } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
+ return x; \
+ } \
+ SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
+ { \
+ if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
+ __ac_set_isdel_true(h->flags, x); \
+ --h->size; \
+ } \
+ }
+
+#define KHASH_DECLARE(name, khkey_t, khval_t) \
+ __KHASH_TYPE(name, khkey_t, khval_t) \
+ __KHASH_PROTOTYPES(name, khkey_t, khval_t)
+
+#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+ __KHASH_TYPE(name, khkey_t, khval_t) \
+ __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
+
+#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+ KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
+
+/* --- BEGIN OF HASH FUNCTIONS --- */
+
+/*! @function
+ @abstract Integer hash function
+ @param key The integer [khint32_t]
+ @return The hash value [khint_t]
+ */
+#define kh_int_hash_func(key) (khint32_t)(key)
+/*! @function
+ @abstract Integer comparison function
+ */
+#define kh_int_hash_equal(a, b) ((a) == (b))
+/*! @function
+ @abstract 64-bit integer hash function
+ @param key The integer [khint64_t]
+ @return The hash value [khint_t]
+ */
+#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
+/*! @function
+ @abstract 64-bit integer comparison function
+ */
+#define kh_int64_hash_equal(a, b) ((a) == (b))
+/*! @function
+ @abstract const char* hash function
+ @param s Pointer to a null terminated string
+ @return The hash value
+ */
+static kh_inline khint_t __ac_X31_hash_string(const char *s)
+{
+ khint_t h = (khint_t)*s;
+ if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
+ return h;
+}
+/*! @function
+ @abstract Another interface to const char* hash function
+ @param key Pointer to a null terminated string [const char*]
+ @return The hash value [khint_t]
+ */
+#define kh_str_hash_func(key) __ac_X31_hash_string(key)
+/*! @function
+ @abstract Const char* comparison function
+ */
+#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
+
+static kh_inline khint_t __ac_Wang_hash(khint_t key)
+{
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+}
+#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key)
+
+/* --- END OF HASH FUNCTIONS --- */
+
+/* Other convenient macros... */
+
+/*!
+ @abstract Type of the hash table.
+ @param name Name of the hash table [symbol]
+ */
+#define khash_t(name) kh_##name##_t
+
+/*! @function
+ @abstract Initiate a hash table.
+ @param name Name of the hash table [symbol]
+ @return Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_init(name) kh_init_##name()
+
+/*! @function
+ @abstract Destroy a hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_destroy(name, h) kh_destroy_##name(h)
+
+/*! @function
+ @abstract Reset a hash table without deallocating memory.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_clear(name, h) kh_clear_##name(h)
+
+/*! @function
+ @abstract Resize a hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param s New size [khint_t]
+ */
+#define kh_resize(name, h, s) kh_resize_##name(h, s)
+
+/*! @function
+ @abstract Insert a key to the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Key [type of keys]
+ @param r Extra return code: -1 if the operation failed;
+ 0 if the key is present in the hash table;
+ 1 if the bucket is empty (never used); 2 if the element in
+ the bucket has been deleted [int*]
+ @return Iterator to the inserted element [khint_t]
+ */
+#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
+
+/*! @function
+ @abstract Retrieve a key from the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Key [type of keys]
+ @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t]
+ */
+#define kh_get(name, h, k) kh_get_##name(h, k)
+
+/*! @function
+ @abstract Remove a key from the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Iterator to the element to be deleted [khint_t]
+ */
+#define kh_del(name, h, k) kh_del_##name(h, k)
+
+/*! @function
+ @abstract Test whether a bucket contains data.
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return 1 if containing data; 0 otherwise [int]
+ */
+#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
+
+/*! @function
+ @abstract Get key given an iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return Key [type of keys]
+ */
+#define kh_key(h, x) ((h)->keys[x])
+
+/*! @function
+ @abstract Get value given an iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return Value [type of values]
+ @discussion For hash sets, calling this results in segfault.
+ */
+#define kh_val(h, x) ((h)->vals[x])
+
+/*! @function
+ @abstract Alias of kh_val()
+ */
+#define kh_value(h, x) ((h)->vals[x])
+
+/*! @function
+ @abstract Get the start iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return The start iterator [khint_t]
+ */
+#define kh_begin(h) (khint_t)(0)
+
+/*! @function
+ @abstract Get the end iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return The end iterator [khint_t]
+ */
+#define kh_end(h) ((h)->n_buckets)
+
+/*! @function
+ @abstract Get the number of elements in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return Number of elements in the hash table [khint_t]
+ */
+#define kh_size(h) ((h)->size)
+
+/*! @function
+ @abstract Get the number of buckets in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return Number of buckets in the hash table [khint_t]
+ */
+#define kh_n_buckets(h) ((h)->n_buckets)
+
+/*! @function
+ @abstract Iterate over the entries in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param kvar Variable to which key will be assigned
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
+ for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
+ if (!kh_exist(h,__i)) continue; \
+ (kvar) = kh_key(h,__i); \
+ (vvar) = kh_val(h,__i); \
+ code; \
+ } }
+
+/*! @function
+ @abstract Iterate over the values in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach_value(h, vvar, code) { khint_t __i; \
+ for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
+ if (!kh_exist(h,__i)) continue; \
+ (vvar) = kh_val(h,__i); \
+ code; \
+ } }
+
+/* More convenient interfaces */
+
+/*! @function
+ @abstract Instantiate a hash set containing integer keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_INT(name) \
+ KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing integer keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_INT(name, khval_t) \
+ KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash set containing 64-bit integer keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_INT64(name) \
+ KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing 64-bit integer keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_INT64(name, khval_t) \
+ KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
+
+typedef const char *kh_cstr_t;
+/*! @function
+ @abstract Instantiate a hash map containing const char* keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_STR(name) \
+ KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing const char* keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_STR(name, khval_t) \
+ KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
+
+#endif /* __AC_KHASH_H */
diff --git a/hicn-light/src/hicn/base/loop.c b/hicn-light/src/hicn/base/loop.c
new file mode 100644
index 0000000..fecab9c
--- /dev/null
+++ b/hicn-light/src/hicn/base/loop.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file loop.c
+ * @brief Implementation of event loop based on libevent
+ */
+
+#include <assert.h>
+#include <event2/event.h>
+#include <event2/thread.h>
+#include <fcntl.h> // fcntl
+#ifdef WITH_THREAD
+#include <pthread.h>
+#endif /* WITH_THREAD */
+#include <stdlib.h>
+#include <sys/timerfd.h>
+#include <unistd.h> // fcntl
+
+#include <hicn/util/log.h>
+#include <hicn/util/map.h>
+
+#include "loop.h"
+
+loop_t * MAIN_LOOP = NULL;
+
+/**
+ * \brief Holds all callback parameters
+ */
+typedef struct {
+ void * owner;
+ fd_callback_t callback;
+ void * data;
+} cb_wrapper_args_t;
+
+TYPEDEF_MAP_H(event_map, int, struct event *);
+TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf, generic_snprintf);
+
+/* Map that associates timer fds with their associated cb_wrapper_args_t */
+TYPEDEF_MAP_H(timer_fd_map, int, cb_wrapper_args_t *);
+TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf, generic_snprintf);
+
+struct loop_s {
+ struct event_base * event_base;
+ event_map_t * event_map;
+ timer_fd_map_t * timer_fd_map;
+#ifdef WITH_THREAD
+ pthread_t thread;
+#endif /* WITH_THREAD */
+};
+
+loop_t *
+loop_create()
+{
+ loop_t * loop = malloc(sizeof(loop_t));
+ if (!loop) {
+ ERROR("[loop_create] Failed to allocate memory");
+ goto ERR_MALLOC;
+ }
+
+#ifdef WITH_THREAD
+ evthread_use_pthreads();
+#endif /* WITH_THREAD */
+
+ loop->event_base = event_base_new();
+ if (!loop)
+ goto ERR_EVENT;
+
+ loop->event_map = event_map_create();
+ if (!loop->event_map) {
+ ERROR("[loop_create] Failed to create event_map");
+ goto ERR_EVENT_MAP;
+ }
+
+ loop->timer_fd_map = timer_fd_map_create();
+ if (!loop->timer_fd_map) {
+ ERROR("[loop_create] Failed to create timer_fd_map");
+ goto ERR_TIMER_FD_MAP;
+ }
+
+ event_set_log_callback(NULL);
+
+ return loop;
+
+ timer_fd_map_free(loop->timer_fd_map);
+ERR_TIMER_FD_MAP:
+ event_map_free(loop->event_map);
+ERR_EVENT_MAP:
+ event_base_free(loop->event_base);
+ERR_EVENT:
+ free(loop);
+ERR_MALLOC:
+ return NULL;
+}
+
+void
+loop_free(loop_t * loop)
+{
+ /*
+ * Release all timer cb_wrapper_args_t
+ *
+ * We need to stop all timers, this should release associated fd events at
+ * the same time... for that reason, this code has to be called before
+ * releasing events
+ */
+
+ int * timer_fd_map_array;
+ int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array);
+ if (n < 0) {
+ ERROR("[loop_free] Could not get event map array");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ int fd = timer_fd_map_array[i];
+ if (loop_unregister_timer(loop, fd) < 0) {
+ ERROR("[loop_free] Could not unregister timer");
+ }
+ }
+ free(timer_fd_map_array);
+ }
+ timer_fd_map_free(loop->timer_fd_map);
+
+ /* Release all events */
+
+ int * event_map_array;
+ n = event_map_get_key_array(loop->event_map, &event_map_array);
+ if (n < 0) {
+ ERROR("[loop_free] Could not get event map array");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ int fd = event_map_array[i];
+ if (loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[loop_free] Could not unregister fd");
+ }
+ }
+ free(event_map_array);
+ }
+ event_map_free(loop->event_map);
+
+ event_base_free(loop->event_base);
+
+ free(loop);
+}
+
+int
+loop_dispatch(loop_t * loop)
+{
+#ifdef WITH_THREAD
+ if (pthread_create(&loop->thread, NULL, (void * (*)(void *))event_base_dispatch, loop->event_base)) {
+ fprintf(stderr, "Error creating thread\n");
+ return -1;
+ }
+#else
+ event_base_dispatch(loop->event_base);
+#endif /* WITH_THREAD */
+ return 0;
+}
+
+int
+loop_undispatch(loop_t * loop)
+{
+#ifdef WITH_THREAD
+ DEBUG("Waiting for loop to terminate...");
+ if(pthread_join(loop->thread, NULL)) {
+ fprintf(stderr, "Error joining thread\n");
+ return -1;
+ }
+ DEBUG("Loop terminated !");
+#endif /* WITH_THREAD */
+ return 0;
+}
+
+void
+loop_break(loop_t * loop)
+{
+ event_base_loopbreak(loop->event_base);
+}
+
+void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
+ cb_wrapper_args_t * cb_wrapper_args = arg;
+ cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data);
+}
+
+int
+loop_register_fd(loop_t * loop, int fd, void * callback_owner,
+ fd_callback_t callback, void * callback_data)
+{
+ /* This will be freed with the event */
+ cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t) {
+ .owner = callback_owner,
+ .callback = callback,
+ .data = callback_data,
+ };
+
+ evutil_make_socket_nonblocking(fd);
+ struct event * event = event_new(loop->event_base, fd, EV_READ | EV_PERSIST, cb_wrapper, cb_wrapper_args);
+ if (!event) {
+ ERROR("[loop_register_fd] event_new");
+ goto ERR_EVENT_NEW;
+ }
+
+ if (event_add(event, NULL) < 0) {
+ ERROR("[loop_register_fd] event_add");
+ goto ERR_EVENT_ADD;
+ }
+
+ if (event_map_add(loop->event_map, fd, event) < 0) {
+ ERROR("[loop_register_fd] event_map_add");
+ goto ERR_EVENT_MAP;
+ }
+
+ return 0;
+
+ERR_EVENT_MAP:
+ERR_EVENT_ADD:
+ event_free(event);
+ERR_EVENT_NEW:
+ return -1;
+}
+
+int
+loop_unregister_fd(loop_t * loop, int fd)
+{
+ struct event * event = NULL;
+
+ if (event_map_remove(loop->event_map, fd, &event) < 0) {
+ ERROR("[loop_unregister_fd] Error removing event associated to fd");
+ return -1;
+ }
+
+ assert(event);
+
+ cb_wrapper_args_t * cb_wrapper_args = event_get_callback_arg(event);
+ free(cb_wrapper_args);
+
+ event_del(event);
+ event_free(event);
+
+ return 0;
+}
+
+int
+loop_timer_callback(loop_t * loop, int fd, void * data)
+{
+ char buf[1024]; /* size is not important */
+ cb_wrapper_args_t * cb_wrapper_args = data;
+ while (read(fd, &buf, sizeof(buf)) > 0)
+ ;
+
+ int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd,
+ cb_wrapper_args->data);
+
+ return rc;
+}
+
+int
+_loop_register_timer(loop_t * loop, unsigned delay_ms, void * owner,
+ fd_callback_t callback, void * data)
+{
+ int fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd == -1) {
+ perror("timerfd_create");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ return -1;
+ }
+
+ struct itimerspec ts = {
+ .it_interval = {
+ .tv_sec = delay_ms / 1000,
+ .tv_nsec = (delay_ms % 1000) * 1000000,
+ },
+ .it_value = {
+ .tv_sec = delay_ms / 1000,
+ .tv_nsec = (delay_ms % 1000) * 1000000,
+ }
+ };
+
+ if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
+ perror("timerfd_settime");
+ return -1;
+ }
+
+ /* This should be freed together with the timer release */
+ cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t) {
+ .owner = owner,
+ .callback = callback,
+ .data = data,
+ };
+
+ if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) {
+ ERROR("[loop_register_timer] Could not add cb_wrapper to timer map");
+ return -1;
+ }
+
+ if (loop_register_fd(loop, fd, loop,
+ (fd_callback_t) loop_timer_callback, cb_wrapper_args) < 0) {
+ ERROR("[loop_register_timer] Error registering fd to event loop");
+ return -1;
+ }
+
+ return fd;
+}
+
+int
+loop_unregister_timer(loop_t * loop, int fd)
+{
+ struct itimerspec ts = {
+ .it_interval = {
+ .tv_sec = 0,
+ .tv_nsec = 0,
+ },
+ .it_value = { /* This value disables the timer */
+ .tv_sec = 0,
+ .tv_nsec = 0,
+ }
+ };
+ ts.it_value.tv_sec = 0;
+
+ if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
+ perror("timerfd_settime");
+ return -1;
+ }
+
+ cb_wrapper_args_t * cb_wrapper_args;
+ if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) {
+ ERROR("[loop_unregister_timer] Could not remove cb_wrapper from timer map");
+ return -1;
+ }
+ assert(cb_wrapper_args);
+ free(cb_wrapper_args);
+
+ if (loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[loop_unregister_timer] Error unregistering fd from event loop");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/hicn-light/src/hicn/base/loop.h b/hicn-light/src/hicn/base/loop.h
new file mode 100644
index 0000000..b73d917
--- /dev/null
+++ b/hicn-light/src/hicn/base/loop.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 loop.h
+ * \brief Face manager main loop
+ */
+
+#ifndef FACEMGR_LOOP_H
+#define FACEMGR_LOOP_H
+
+/* fd & timer callbacks */
+
+typedef int (*fd_callback_t)(void * owner, int fd, void * data);
+
+typedef struct {
+ int fd;
+ void *owner;
+ fd_callback_t callback;
+ //int (*callback)(void * owner, int fd, void * data);
+ void *data;
+} fd_callback_data_t;
+
+/* loop */
+
+typedef struct loop_s loop_t;
+
+/* Global loop to be used in single threaded applications */
+extern loop_t * MAIN_LOOP;
+
+/**
+ * \brief Creates a main loop
+ * \return Pointer to the newly created loop, or NULL in case of error
+ */
+loop_t * loop_create();
+
+/**
+ * \brief Releases a loop instance and frees all associated memory
+ * \param [in] loop - Pointer to the loop instance to free
+ */
+void loop_free(loop_t * loop);
+
+/**
+ * \brief Runs the loop instance to process events
+ * \param [in] loop - Pointer to the loop instance
+ * \return 0 if successful, -1 otherwise
+ */
+int loop_dispatch(loop_t * loop);
+
+/**
+ * \brief Terminates the dispatching of events
+ * \param [in] loop - Pointer to the loop instance
+ */
+int loop_undispatch(loop_t * loop);
+
+/**
+ * \brief Breaks out of the loop
+ * \param [in] loop - Pointer to the loop instance
+ */
+void loop_break(loop_t * loop);
+
+/**
+ * \brief Registers a new file descriptor to the event loop
+ * \param [in] fd - File descriptor to register
+ * \param [in] callback_owner - Pointer to the owner of the callack (first
+ * parameter of callback function)
+ * \param [in] callback - Callback function
+ * \param [in] callback_data - User data to pass alongside callback invocation
+ * \return 0 in case of success, -1 otherwise
+ */
+int
+loop_register_fd(loop_t * loop, int fd, void * callback_owner,
+ fd_callback_t callback, void * callback_data);
+
+/**
+ * \brief Unregisters a file descriptor from the event loop
+ * \param [in] fd - File descriptor to unregister
+ * \return 0 in case of success, -1 otherwise
+ */
+int
+loop_unregister_fd(loop_t * loop, int fd);
+
+int _loop_register_timer(loop_t * loop, unsigned delay_ms, void * owner,
+ fd_callback_t callback, void * data);
+
+#define loop_register_timer(loop, delay_ms, owner, callback, data) \
+ _loop_register_timer(loop, delay_ms, owner, (fd_callback_t) callback, data)
+
+int
+loop_unregister_timer(loop_t * loop, int fd);
+
+#endif /* FACEMGR_LOOP_H */
diff --git a/hicn-light/src/hicn/base/pool.c b/hicn-light/src/hicn/base/pool.c
new file mode 100644
index 0000000..abca864
--- /dev/null
+++ b/hicn-light/src/hicn/base/pool.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file pool.c
+ * \brief Implementation of fixed-size pool allocator
+ */
+
+#include <stdlib.h> // calloc
+
+#include "common.h"
+#include "pool.h"
+
+
+/**
+ * \brief Initialize the pool data structure
+ * \param [in,out] pool - Pointer to the pool structure storage
+ * \param [in] elt_size - Size of elements in vector
+ * \param [in] max_elts - Maximum size
+ *
+ * Note that an empty pool might be equal to NULL
+ */
+void
+_pool_init(void ** pool_ptr, size_t elt_size, size_t max_elts)
+{
+ pool_hdr_t * ph = calloc(POOL_HDRLEN + elt_size * max_elts, 1);
+ if (!ph)
+ abort();
+
+ /* Free indices */
+ off_t * free_indices;
+ vector_init(free_indices, max_elts);
+
+ uint_fast32_t * fb = ph->free_bitmap;
+ bitmap_init(fb, max_elts);
+ bitmap_set_to(fb, max_elts);
+
+ for(unsigned i = 0; i < max_elts; i++)
+ free_indices[i] = (max_elts - 1) - i;
+ ph->free_indices = free_indices;
+
+ *pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
+}
+
+void
+_pool_free(void ** pool_ptr)
+{
+ free(pool_hdr(*pool_ptr));
+ *pool_ptr = NULL;
+}
+
+void
+_pool_resize(void ** pool_ptr, size_t elt_size)
+{
+ pool_hdr_t * ph = pool_hdr(*pool_ptr);
+ size_t old_elts = ph->max_elts;
+ size_t new_elts = old_elts * 2;
+
+ /* Double pool storage */
+ ph = realloc(ph, POOL_HDRLEN + new_elts * elt_size);
+ if (!ph)
+ abort();
+ ph->max_elts = new_elts;
+
+ /*
+ * After resize, the pool will have old_elts free indices, ranging from
+ * old_elts to (new_elts - 1)
+ */
+ off_t * free_indices = ph->free_indices;
+ vector_ensure_pos(free_indices, old_elts);
+ for (unsigned i = 0; i < old_elts; i++)
+ free_indices[i] = new_elts - 1 - i;
+
+ /* Reassign pool pointer */
+ *pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
+}
diff --git a/hicn-light/src/hicn/base/pool.h b/hicn-light/src/hicn/base/pool.h
new file mode 100644
index 0000000..360dedc
--- /dev/null
+++ b/hicn-light/src/hicn/base/pool.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file array.h
+ * \brief Fixed-size pool allocator
+ */
+
+#ifndef UTIL_POOL_H
+#define UTIL_POOL_H
+
+#include <stdint.h>
+
+#include "bitmap.h"
+#include "vector.h"
+
+/** Local variable naming macro. */
+#define _pool_var(v) _pool_##v
+
+
+typedef struct {
+ size_t elt_size;
+ size_t max_elts;
+ uint_fast32_t * free_bitmap;
+ off_t * free_indices; /* vector of free indices */
+} pool_hdr_t;
+
+void _pool_init(void ** pool_ptr, size_t elt_size, size_t max_elts);
+void _pool_free(void ** pool_ptr);
+void _pool_resize(void ** pool_ptr, size_t elt_size);
+
+#define POOL_HDRLEN SIZEOF_ALIGNED(pool_hdr_t)
+
+/* This header actually prepends the actual content of the pool */
+#define pool_hdr(pool) ((pool_hdr_t *)((uint8_t*)(pool) - POOL_HDRLEN))
+
+// XXX TODO need common naming for cur_len, len, max_len
+#define pool_elts(pool) \
+ (pool_hdr(pool)->max_elts - vector_len((pool_hdr(pool)->free_indices)))
+
+#define pool_init(pool, max_elts) \
+ _pool_init((void**)&pool, sizeof(pool[0]), max_elts);
+
+#define pool_free(pool) \
+ _pool_free((void**)&pool);
+
+#define pool_get(pool, elt) \
+do { \
+ pool_hdr_t * _pool_var(ph) = pool_hdr(pool); \
+ u64 _pool_var(l) = vector_len(_pool_var(ph)->free_indices); \
+ if (_pool_var(l) == 0) \
+ _pool_resize((void**)&(pool), sizeof((pool)[0])); \
+ off_t _pool_var(free_id) = \
+ _pool_var(ph)->free_indices[_pool_var(l) - 1]; \
+ elt = (pool) + _pool_var(free_id); \
+ memset(&elt, 0, sizeof(elt)); \
+} while(0)
+
+#define pool_put(pool, elt) \
+do { \
+ pool_hdr_t * _pool_var(ph) = pool_hdr(pool); \
+ u64 _pool_var(l) = vector_len(_pool_var(ph)->free_indices); \
+ vector_ensure_pos(_pool_var(ph)->free_indices, _pool_var(l)); \
+ _pool_var(ph)->free_indices[_pool_var(l)] = (elt) - (pool); \
+ vector_len(_pool_var(ph)->free_indices)++; \
+ bitmap_set(_pool_var(ph)->free_bitmap, _pool_var(l)); \
+} while(0)
+
+#define pool_validate_id(pool, id) \
+ bitmap_is_unset((pool_hdr(pool))->free_bitmap, (id))
+
+#define pool_enumerate(pool, i, eltp, BODY) \
+do { \
+ pool_hdr_t * _pool_var(ph) = pool_hdr(pool); \
+ uint_fast32_t * _pool_var(fb) = _pool_var(ph)->free_bitmap; \
+ for((i) = 0; (i) < _pool_var(ph)->max_elts; (i)++) { \
+ if (bitmap_is_unset(_pool_var(fb), (i))) \
+ continue; \
+ eltp = (pool) + (i); \
+ do { BODY; } while (0); \
+ } \
+} while(0)
+
+#define pool_foreach(pool, eltp, BODY) \
+do { \
+ unsigned _pool_var(i); \
+ pool_enumerate((pool), _pool_var(i), (eltp), BODY); \
+} while(0)
+
+
+
+#endif /* UTIL_POOL_H */
diff --git a/hicn-light/src/hicn/base/vector.c b/hicn-light/src/hicn/base/vector.c
new file mode 100644
index 0000000..00ed7c3
--- /dev/null
+++ b/hicn-light/src/hicn/base/vector.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file vector.c
+ * \brief Implementation of resizeable static array
+ */
+
+#include <stddef.h> // size_t
+#include <stdlib.h> // calloc
+
+#include "vector.h"
+
+void
+_vector_init(void ** vector_ptr, size_t elt_size, size_t max_elts)
+{
+ vector_hdr_t * vh = calloc(VECTOR_HDRLEN + elt_size * max_elts, 1);
+ *vector_ptr = (uint8_t*)vh - VECTOR_HDRLEN;
+}
+
+void
+_vector_free(void ** vector_ptr)
+{
+ free(vector_hdr(*vector_ptr));
+ *vector_ptr = NULL;
+}
+
+void
+_vector_resize(void ** vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t * vh = vector_hdr(*vector_ptr);
+ size_t new_elts = (pos > 0) ? next_pow2(pos) : vh->max_elts * 2;
+
+ /* Double the allocated vector size */
+ vh = realloc(vh, VECTOR_HDRLEN + new_elts * elt_size);
+ if (!vh)
+ abort();
+ vh->max_elts = new_elts;
+
+ /* Reassign vector pointer */
+ *vector_ptr = (uint8_t*) + VECTOR_HDRLEN;
+}
diff --git a/hicn-light/src/hicn/base/vector.h b/hicn-light/src/hicn/base/vector.h
new file mode 100644
index 0000000..9b99ba8
--- /dev/null
+++ b/hicn-light/src/hicn/base/vector.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file vector.h
+ * \brief Resizeable static array
+ */
+
+#ifndef UTIL_VECTOR_H
+#define UTIL_VECTOR_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "common.h"
+
+/** Local variable naming macro. */
+#define _vector_var(v) _vector_##v
+
+typedef struct {
+ size_t num_elts;
+ size_t max_elts;
+} vector_hdr_t;
+
+void _vector_init(void ** vector_ptr, size_t elt_size, size_t max_elts);
+void _vector_free(void ** vector_ptr);
+void _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
+
+/* Make sure elements following the header are aligned */
+#define VECTOR_HDRLEN SIZEOF_ALIGNED(vector_hdr_t)
+
+/* This header actually prepends the actual content of the vector */
+#define vector_hdr(vector) ((vector_hdr_t *)((uint8_t*)vector - VECTOR_HDRLEN))
+
+#define vector_init(vector, max_elts) \
+ _vector_init((void**)&vector, sizeof(vector[0]), max_elts)
+
+#define vector_free(vector) \
+ _vector_free(&vector)
+
+#define vector_len(vector) (vector_hdr(vector)->num_elts)
+
+#define vector_resize(vector) _vector_resize((void**)&(vector), sizeof((vector)[0]), 0)
+
+#define vector_ensure_pos(vector, pos) \
+do { \
+ if ((pos) >= vector_len(vector)) \
+ _vector_resize((void**)&(vector), sizeof((vector)[0]), pos); \
+} while(0)
+
+#define vector_push(vector, elt) \
+do { \
+ vector_ensure_pos(vector_len(vector)); \
+ vector[vector_len(vector)++] = elt; \
+} while(0)
+
+#endif /* UTIL_VECTOR_H */
diff --git a/hicn-light/src/hicn/command_line/CMakeLists.txt b/hicn-light/src/hicn/command_line/CMakeLists.txt
index 16c23dc..217e00f 100644
--- a/hicn-light/src/hicn/command_line/CMakeLists.txt
+++ b/hicn-light/src/hicn/command_line/CMakeLists.txt
@@ -1,2 +1,2 @@
-add_subdirectory(controller)
+#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
index 949cace..26d4c0b 100644
--- a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
+++ b/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
@@ -12,7 +12,7 @@
# limitations under the License.
list(APPEND CONTROLLER_SRC
- hicnLightControl_main.c
+hicnLightControl_main.c
)
if (NOT DISABLE_EXECUTABLES)
build_executable(${HICN_LIGHT_CONTROL}
diff --git a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
index 8f56dc6..cc91e5a 100644
--- a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
+++ b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c
@@ -41,7 +41,6 @@
#include <parc/algol/parc_Memory.h>
#include <parc/algol/parc_SafeMemory.h>
-#include <hicn/core/dispatcher.h>
#include <hicn/core/forwarder.h>
#include <errno.h>
diff --git a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
index 89a80d0..f3fbf84 100644
--- a/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
+++ b/hicn-light/src/hicn/command_line/daemon/hicnLightDaemon_main.c
@@ -26,136 +26,131 @@
#include <sys/stat.h>
#include <hicn/hicn-light/config.h>
-#include <parc/algol/parc_FileOutputStream.h>
-#include <parc/logging/parc_LogLevel.h>
-#include <parc/logging/parc_LogReporterFile.h>
-#include <parc/logging/parc_LogReporterTextStdout.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/core/dispatcher.h>
#include <hicn/core/forwarder.h>
+#include <hicn/util/log.h>
+#include <hicn/base/loop.h>
static void _printRed(const char *output) {
#ifndef _WIN32
- printf("\033[0;31m%s", output);
+ 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);
+ 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);
+ 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);
+ 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");
+ _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");
+ 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");
+ 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");
+ 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");
+ 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);
+ 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);
}
+#if 0
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);
- }
+ 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);
+ }
}
/**
@@ -163,251 +158,261 @@ static void _setLogLevelToLevel(int logLevelArray[LoggerFacility_END],
* 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;
+ 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);
+ }
}
- }
-
- if (facility < LoggerFacility_END) {
- _setLogLevelToLevel(logLevelArray, facility, levelString);
- } else {
- printf("Invalid facility string %s\n", facilityString);
- _usage(EXIT_FAILURE);
- }
}
- }
- parcMemory_Deallocate((void **)&tofree);
+ parcMemory_Deallocate((void **)&tofree);
}
+#endif
#ifndef _WIN32
static void _daemonize(void) {
- if (getppid() == 1) {
- // already a daemon
- return;
- }
+ if (getppid() == 1) {
+ // already a daemon
+ return;
+ }
- int forkReturn = fork();
- parcTrapUnexpectedStateIf(forkReturn < 0, "Fork error")
+ int forkReturn = fork();
+ assert(forkReturn >= 0);
- if (forkReturn > 0) {
- // parent exits
- exit(EXIT_SUCCESS);
- }
+ if (forkReturn > 0) {
+ // parent exits
+ exit(EXIT_SUCCESS);
+ }
- // Child daemon detaches
- printf("child continuing, pid = %u\n", getpid());
+ // Child daemon detaches
+ printf("child continuing, pid = %u\n", getpid());
- // get a new process group independent from old parent
- setsid();
+ // get a new process group independent from old parent
+ setsid();
- /* close all descriptors */
+ /* close all descriptors */
#ifdef __ANDROID__
- for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i) {
- close(i);
- }
+ for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i) {
+ close(i);
+ }
#else
- for (int i = getdtablesize(); i >= 0; --i) {
- close(i);
- }
+ for (int i = getdtablesize(); i >= 0; --i) {
+ close(i);
+ }
#endif
- // reset errno because it might be seg to EBADF from the close calls above
- errno = 0;
-
- // Redirect stdin and stdout and stderr to /dev/null
- const char *devnull = "/dev/null";
- int nullfile = open(devnull, O_RDWR);
- parcAssertTrue(nullfile >= 0, "Error opening file '%s': (%d) %s", devnull,
- errno, strerror(errno));
-
- int ret;
- ret = dup(nullfile);
- parcAssertTrue(ret == 1, "Error duping fd 1 got %d file: (%d) %s", ret, errno,
- strerror(errno));
- ret = dup(nullfile);
- parcAssertTrue(ret == 2, "Error duping fd 2, got %d file: (%d) %s", ret,
- errno, strerror(errno));
-
- // forwarder will capture signals
+ // 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);
+ assert(nullfile >= 0);
+
+ int ret;
+ ret = dup(nullfile);
+ assert(ret == 1);
+ ret = dup(nullfile);
+ assert(ret == 2);
+ (void)ret; /* UNUSED */
+
+ // forwarder will capture signals
}
#endif
+#if 0
static Logger *_createLogfile(const char *logfile) {
#ifndef _WIN32
- int logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
+ 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);
+ 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);
- }
+ 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);
+ chmod(logfile, S_IRWXU);
#endif
- PARCFileOutputStream *fos = parcFileOutputStream_Create(logfd);
- PARCOutputStream *pos = parcFileOutputStream_AsOutputStream(fos);
- PARCLogReporter *reporter = parcLogReporterFile_Create(pos);
+ PARCFileOutputStream *fos = parcFileOutputStream_Create(logfd);
+ PARCOutputStream *pos = parcFileOutputStream_AsOutputStream(fos);
+ PARCLogReporter *reporter = parcLogReporterFile_Create(pos);
- Logger *logger = logger_Create(reporter, parcClock_Wallclock());
+ Logger *logger = logger_Create(reporter, parcClock_Wallclock());
- parcOutputStream_Release(&pos);
- parcLogReporter_Release(&reporter);
+ parcOutputStream_Release(&pos);
+ parcLogReporter_Release(&reporter);
- return logger;
+ return logger;
}
+#endif
int main(int argc, const char *argv[]) {
- _displayForwarderLogo();
+ _displayForwarderLogo();
#ifndef _WIN32
- bool daemon = false;
+ bool daemon = false;
#else
- WSADATA wsaData = {0};
- WSAStartup(MAKEWORD(2, 2), &wsaData);
+ 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++;
+ 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);
+ }
+
+#if 0
+ int logLevelArray[LoggerFacility_END];
+ for (int i = 0; i < LoggerFacility_END; i++) {
+ logLevelArray[i] = -1;
+ }
+#endif
+
+ 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;
+ } 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);
+ } else if (strcmp(argv[i], "--capacity") == 0 ||
+ strcmp(argv[i], "-c") == 0) {
+ capacity = atoi(argv[i + 1]);
+ i++;
+#if 0
+ } 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++;
+#endif
+ } else {
+ _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);
+ // 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();
- }
+ 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]);
+#if 0
+ 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);
}
- }
- // this will update the clock to the tick clock
- Forwarder *forwarder = forwarder_Create(logger);
+ for (int i = 0; i < LoggerFacility_END; i++) {
+ if (logLevelArray[i] > -1) {
+ logger_SetLogLevel(logger, i, logLevelArray[i]);
+ }
+ }
+#endif
- if (forwarder == NULL) {
- logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Error, "daemon",
- "Forwarder initialization failed. Are you running it with sudo "
- "privileges?");
- return -1;
- }
+ forwarder_t * forwarder = forwarder_create();
+ if (!forwarder) {
+ ERROR("Forwarder initialization failed. Are you running it with sudo privileges?");
+ return -1;
+ }
- Configuration *configuration = forwarder_GetConfiguration(forwarder);
+ configuration_t * configuration = forwarder_get_configuration(forwarder);
+ if (capacity > -1) {
+ configuration_content_store_set_size(configuration, capacity);
+ }
- if (capacity > -1) {
- configuration_SetObjectStoreSize(configuration, capacity);
- }
+ forwarder_setup_local_listeners(forwarder, port);
+ if (configFileName) {
+ forwarder_read_config(forwarder, configFileName);
+ }
- forwarder_SetupLocalListeners(forwarder, port);
- if (configFileName) {
- forwarder_SetupFromConfigFile(forwarder, configFileName);
- }
+ INFO("hicn-light running port %d configuration-port %d", port,
+ configurationPort);
- Dispatcher *dispatcher = forwarder_GetDispatcher(forwarder);
+ /* Main loop */
+ MAIN_LOOP = loop_create();
+ if (loop_dispatch(MAIN_LOOP) < 0) {
+ ERROR("Failed to run main loop");
+ return EXIT_FAILURE;
+ }
- logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Alert, "daemon",
- "hicn-light running port %d configuration-port %d", port,
- configurationPort);
+ INFO("hicn-light exiting port %d", port);
- dispatcher_Run(dispatcher);
+ if (loop_undispatch(MAIN_LOOP) < 0) {
+ ERROR("Failed to terminate main loop");
+ return EXIT_FAILURE;
+ }
- logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Alert, "daemon",
- "hicn-light exiting port %d", port);
+ forwarder_free(forwarder);
- forwarder_Destroy(&forwarder);
+ loop_free(MAIN_LOOP);
+ MAIN_LOOP = NULL;
#ifndef _WIN32
- sleep(2);
+ sleep(2);
#else
- Sleep(2000);
- WSACleanup();
+ Sleep(2000);
+ WSACleanup();
#endif
- logger_Release(&logger);
- return 0;
+ return 0;
}
diff --git a/hicn-light/src/hicn/config.h.in b/hicn-light/src/hicn/config.h.in
index 90ab8e8..6c2915b 100644
--- a/hicn-light/src/hicn/config.h.in
+++ b/hicn-light/src/hicn/config.h.in
@@ -2,7 +2,8 @@
#define LEVEL1_DCACHE_LINESIZE @LEVEL1_DCACHE_LINESIZE@
#ifndef _WIN32
-#define _GNU_SOURCE
+// This is now in CMakeLists.txt
+//#define _GNU_SOURCE
#else
#include <hicn/platforms/windows/win_portability.h>
#endif
diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt
index 45f36e8..9db4138 100644
--- a/hicn-light/src/hicn/config/CMakeLists.txt
+++ b/hicn-light/src/hicn/config/CMakeLists.txt
@@ -14,95 +14,93 @@
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}/controlAddPolicy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.h
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/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}/configuration_file.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlList.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/commandOps.c
- ${CMAKE_CURRENT_SOURCE_DIR}/commandParser.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/commandOps.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/commandParser.c
${CMAKE_CURRENT_SOURCE_DIR}/configuration.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configurationFile.c
- ${CMAKE_CURRENT_SOURCE_DIR}/configurationListeners.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlState.c
- ${CMAKE_CURRENT_SOURCE_DIR}/symbolicNameTable.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAdd.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddConnection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlList.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRoot.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeRetx.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.c
- ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlState.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/symbolicNameTable.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAdd.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddConnection.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddRoute.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPolicy.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddListener.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlList.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListConnections.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListListeners.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListRoutes.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlListPolicies.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlQuit.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemove.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveListener.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveConnection.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemoveRoute.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePolicy.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRoot.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSet.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetDebug.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnset.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUnsetDebug.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMe.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeEnable.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeDiscovery.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeTimescale.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlMapMeRetx.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheServe.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheStore.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCacheClear.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlCache.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetStrategy.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlSetWldr.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlAddPunting.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlRemovePunting.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdate.c
+# ${CMAKE_CURRENT_SOURCE_DIR}/controlUpdateConnection.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c
index 39d3271..a6f78f9 100644
--- a/hicn-light/src/hicn/config/configuration.c
+++ b/hicn-light/src/hicn/config/configuration.c
@@ -26,531 +26,424 @@
#include <unistd.h>
#endif
#include <ctype.h>
-#include <parc/assert/parc_Assert.h>
#include <hicn/hicn-light/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_String.h>
-
-#include <hicn/config/configurationListeners.h>
-#include <hicn/config/symbolicNameTable.h>
-
#include <hicn/core/connection.h>
-#include <hicn/core/connectionTable.h>
+#include <hicn/core/connection_table.h>
#include <hicn/core/forwarder.h>
-#include <hicn/core/system.h>
+//#include <hicn/core/system.h>
#ifdef WITH_MAPME
#include <hicn/core/mapme.h>
#endif /* WITH_MAPME */
-#include <hicn/io/streamConnection.h>
-
-#include <hicn/io/hicnTunnel.h>
-#include <hicn/io/tcpTunnel.h>
-#include <hicn/io/udpTunnel.h>
-
-#include <parc/algol/parc_Unsigned.h>
-#include <hicn/io/listener.h> //the listener list
-#include <hicn/io/listenerSet.h> // needed to print
+#include <hicn/core/listener.h> //the listener list
+#include <hicn/core/listener_table.h>
#include <hicn/utils/commands.h>
#include <hicn/utils/utils.h>
-
-#include <hicn/utils/address.h>
+#include <hicn/utils/punting.h>
+#include <hicn/util/log.h>
+#include <hicn/face.h>
#define ETHERTYPE 0x0801
+#define DEFAULT_COST 1
+#define DEFAULT_PORT 1234
+
+#define make_ack(msg) msg->header.messageType = ACK_LIGHT
+#define make_nack(msg) msg->header.messageType = NACK_LIGHT
+
+#define msg_malloc_list(msg, N) \
+do { \
+ msg = malloc(sizeof((msg)->header) + N * sizeof((msg)->payload)); \
+ (msg)->header.messageType = RESPONSE_LIGHT; \
+ (msg)->header.length = (uint16_t)(N); \
+} while(0);
+
+/*
+ * XXX TODO
+ *
+ * Currently the strategy map only stores the strategy type, but it should be
+ * extended with strategy options.
+ *
+ * Or maybe we simply remove this map like in VPP.
+ *
+ * prefix_str -> strategy_type
+ */
+KHASH_INIT(strategy_map, const char *, unsigned, 0, str_hash, str_hash_eq);
-struct configuration {
- Forwarder *forwarder;
- Logger *logger;
+struct configuration_s {
+ forwarder_t * forwarder;
- size_t maximumContentObjectStoreSize;
+ size_t maximumContentObjectStoreSize;
- // map from prefix (parcString) to strategy (parcString)
- PARCHashMap *strategy_map;
+ // map from prefix (parcString) to strategy (parcString)
+ kh_strategy_map_t * strategy_map;
- // translates between a symblic name and a connection id
- SymbolicNameTable *symbolicNameTable;
+#if 0
+ // translates between a symblic name and a connection id
+ // XXX This might be moved as two indices in the listener and connection
+ // tables to be widely reachable... this has nothing to do with
+ // configuration.
+ SymbolicNameTable *symbolic_nameTable;
+#endif
};
// ========================================================================================
-Connection *
-getConnectionBySymbolicOrId(Configuration * config, const char * symbolicOrConnid)
+// conn_id = UINT_MAX when symbolic_name is not found
+static inline
+unsigned
+_symbolic_to_conn_id(configuration_t * config, const char * symbolicOrConnid,
+ bool allow_self, unsigned ingress_id)
{
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
- unsigned connid;
- Connection *conn = NULL;
-
- /* Try to resolve an eventual symbolic name as input */
- if (utils_IsNumber(symbolicOrConnid)) {
- connid = (unsigned int)strtold(symbolicOrConnid, NULL);
-
- } else {
- connid = symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid);
- if (connid == UINT32_MAX) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Symbolic name '%s' could not be resolved",
- symbolicOrConnid);
- }
- }
- }
-
- /* Get connection by ID */
- conn = (Connection *)connectionTable_FindById( table, connid);
- if (!conn) {
- if (logger_IsLoggable(config->logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "ConnID not found, check list connections");
+ unsigned conn_id;
+ const connection_table_t * table = forwarder_get_connection_table(config->forwarder);
+
+ if (allow_self && strcmp(symbolicOrConnid, "SELF") == 0) {
+ conn_id = ingress_id;
+ } else if (utils_IsNumber(symbolicOrConnid)) {
+ // case for conn_id as input
+ // XXX type issue ! XXX No check, see man
+ int id = atoi(symbolicOrConnid);
+ if (id < 0)
+ return CONNECTION_ID_UNDEFINED;
+ conn_id = id;
+
+ if (!connection_table_validate_id(table, conn_id)) {
+ ERROR("ConnID not found, check list connections");
+ conn_id = CONNECTION_ID_UNDEFINED;
+ }
+ } else {
+ // case for symbolic as input: check if symbolic name can be resolved
+ conn_id = connection_table_get_id_by_name(table, symbolicOrConnid);
+ if (connection_id_is_valid(conn_id)) {
+ DEBUG("Resolved symbolic name '%s' to conn_id %u", symbolicOrConnid, conn_id);
+ } else {
+ WARN("Symbolic name '%s' could not be resolved", symbolicOrConnid);
+ }
}
- }
- return conn;
+ return conn_id;
}
-// ========================================================================================
+#define symbolic_to_conn_id(config, symbolic) _symbolic_to_conn_id(config, symbolic, false, 0)
+
+#define symbolic_to_conn_id_self(config, symbolic, ingress_id) \
+ _symbolic_to_conn_id(config, symbolic, true, ingress_id)
-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;
+connection_t *
+getConnectionBySymbolicOrId(configuration_t * config, const char * symbolicOrConnid)
+{
+ connection_table_t * table = forwarder_get_connection_table(config->forwarder);
+ unsigned conn_id = symbolic_to_conn_id(config, symbolicOrConnid);
+ if (!connection_id_is_valid(conn_id))
+ return NULL;
+
+ /* conn_id is assumed validated here */
+ return connection_table_at(table, conn_id);
}
-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;
+// ========================================================================================
+
+configuration_t *
+configuration_create(forwarder_t * forwarder)
+{
+ assert(forwarder);
+
+ configuration_t * config = malloc(sizeof(configuration_t));
+ if (!config)
+ return NULL;
+
+ config->forwarder = forwarder;
+ config->maximumContentObjectStoreSize = 100000;
+ config->strategy_map = kh_init_strategy_map();
+#if 0
+ config->symbolic_nameTable = symbolic_nameTable_Create();
+#endif
+
+ return config;
}
-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;
+void
+configuration_free(configuration_t * config)
+{
+ assert(config);
- bool success = false;
+ kh_destroy_strategy_map(config->strategy_map);
+#if 0
+ symbolic_nameTable_Destroy(&config->symbolic_nameTable);
+#endif
+ free(config);
+}
- const char *symbolicOrConnid = control->symbolicOrConnid;
+/* Listener */
- 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);
+uint8_t *
+configuration_on_listener_add(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- // 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
- }
+ msg_listener_add_t * msg = (msg_listener_add_t *)packet;
+ cmd_listener_add_t * control = &msg->payload;
- } 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);
+ forwarder_t * forwarder = configuration_get_forwarder(config);
+ assert(forwarder);
- } 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
- }
- }
+ listener_table_t * table = forwarder_get_listener_table(forwarder);
+ assert(table);
- // generate ACK/NACK
- struct iovec *response;
+ /* Verify that the listener DOES NOT exist */
+ listener_t * listener = listener_table_get_by_name(table, control->symbolic);
+ if (listener)
+ goto NACK;
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(add_route_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(add_route_command));
- }
+ address_t address;
+ if (address_from_ip_port(&address, control->family, &control->address,
+ control->port) < 0) {
+ WARN("Unsupported address type for HICN (ingress id %u): "
+ "must be either IPV4 or IPV6", ingress_id);
+ return false;
+ }
- return response;
-}
+ // NOTE: interface_name is expected NULL for hICN listener
+ face_type_t face_type;
+ if (!face_type_is_defined(control->listener_type))
+ goto NACK;
+ face_type = (face_type_t)control->listener_type;
-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;
+ listener = listener_create(face_type, &address, control->interface_name, control->symbolic, forwarder);
+ if (!listener)
+ goto NACK;
- const char *symbolicOrConnid = control->symbolicOrConnid;
+ make_ack(msg);
+ return (uint8_t*)msg;
- if (utils_IsNumber(symbolicOrConnid)) {
- // case for connid as input
- unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL);
- ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder);
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
+}
- // check if interface index present in the fwd table
- if (connectionTable_FindById(table, connid)) {
- success = forwarder_RemoveRoute(config->forwarder, control, connid);
+uint8_t *
+configuration_on_listener_remove(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_listener_remove_t * msg = (msg_listener_remove_t*)packet;
+ cmd_listener_remove_t * control = &msg->payload;
+
+ const char *symbolicOrListenerid = control->symbolicOrListenerid;
+ off_t listener_id;
+ listener_t * listener;
+
+ listener_table_t * listener_table = forwarder_get_listener_table(config->forwarder);
+
+ // Factor like for connections
+ if (utils_IsNumber(symbolicOrListenerid)) {
+ // XXX no check
+ int id = atoi(symbolicOrListenerid);
+ if (id < 0)
+ goto NACK;
+ listener_id = id;
+
+ listener = listener_table_get_by_id(listener_table, listener_id);
+ if (!listener) {
+ ERROR("Listener Id not found, check list listeners");
+ goto NACK;
+ }
} else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "ConnID not found, check list connections");
- // failure
+ listener = listener_table_get_by_name(listener_table, symbolicOrListenerid);
+ listener_id = listener_table_get_listener_id(listener_table, listener);
}
- } 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
- }
- }
+ connection_table_t * table = forwarder_get_connection_table(config->forwarder);
+ connection_t * connection;
+ connection_table_foreach(table, connection, {
+ const address_pair_t * pair = connection_get_pair(connection);
+ if (!address_equals(listener_get_address(listener),
+ address_pair_get_local(pair)))
+ continue;
+
+ unsigned conn_id = connection_table_get_connection_id(table, connection);
+ /* Remove connection from the FIB */
+ forwarder_remove_connection_id_from_routes(config->forwarder, conn_id);
+
+ /* Remove connection */
+ connection_table_remove_by_id(table, conn_id);
+
+#if 0
+ const char *symbolicConnection =
+ symbolic_nameTable_GetNameByIndex(config->symbolic_nameTable, conn_id);
+ symbolic_nameTable_Remove(config->symbolic_nameTable, symbolicConnection);
+#endif
+ });
- // generate ACK/NACK
- struct iovec *response;
+ /* Remove listener */
+ listener_table_remove_by_id(listener_table, listener_id);
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(remove_route_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(remove_route_command));
- }
+ make_ack(msg);
+ return (uint8_t*)msg;
- return response;
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_ProcessRegistrationList(Configuration *config,
- struct iovec *request) {
- FibEntryList *fibList = forwarder_GetFibEntries(config->forwarder);
-
- size_t payloadSize = fibEntryList_Length(fibList);
- size_t effective_payloadSize = 0;
- size_t pointerLocation = 0;
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* = bytes granularity
- uint8_t *payloadResponse =
- parcMemory_AllocateAndClear(sizeof(list_routes_command) * payloadSize);
-
- for (size_t i = 0; i < fibEntryList_Length(fibList); i++) {
- FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i);
- NameBitvector *prefix = name_GetContentName(fibEntry_GetPrefix(entry));
- const NumberSet *nexthops = fibEntry_GetNexthops(entry);
-
- if (numberSet_Length(nexthops) == 0)
- continue;
-
- if (numberSet_Length(nexthops) > 1) {
- // payload extended, need reallocate, further entries via nexthops
- payloadSize = payloadSize + numberSet_Length(nexthops) - 1;
- payloadResponse = (uint8_t *) parcMemory_Reallocate(
- payloadResponse, sizeof(list_routes_command) * payloadSize);
+static inline
+void
+fill_listener_command(configuration_t * config, listener_t * listener,
+ cmd_listener_list_item_t * cmd)
+{
+ assert(config);
+ assert(listener);
+ assert(cmd);
+
+ struct sockaddr_in * sin;
+ struct sockaddr_in6 * sin6;
+
+ const address_t * addr = listener_get_address(listener);
+
+ cmd->id = (uint32_t)listener_get_id(listener);
+ cmd->type = (uint8_t)listener_get_type(listener);
+
+ switch(addr->ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *) addr;
+ cmd->family = AF_INET;
+ cmd->address.v4.as_inaddr = sin->sin_addr;
+ cmd->port = sin->sin_port;
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) addr;
+ cmd->family = AF_INET6;
+ cmd->address.v6.as_in6addr = sin6->sin6_addr;
+ cmd->port = sin6->sin6_port;
+ break;
+ default:
+ break;
}
- for (size_t j = 0; j < numberSet_Length(nexthops); j++) {
- list_routes_command *listRouteCommand =
- (list_routes_command *)(payloadResponse +
- (pointerLocation *
- sizeof(list_routes_command)));
-
- Address *addressEntry = nameBitvector_ToAddress(prefix);
- if (addressGetType(addressEntry) == ADDR_INET) {
- addressGetInet(addressEntry, &tmpAddr);
- listRouteCommand->addressType = ADDR_INET;
- listRouteCommand->address.v4.as_inaddr = tmpAddr.sin_addr;
- } else if (addressGetType(addressEntry) == ADDR_INET6) {
- addressGetInet6(addressEntry, &tmpAddr6);
- listRouteCommand->addressType = ADDR_INET6;
- listRouteCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr;
- }
- listRouteCommand->connid = numberSet_GetItem(nexthops, j);
- listRouteCommand->len = nameBitvector_GetLength(prefix);
- listRouteCommand->cost = 1; // cost
-
- pointerLocation++;
- effective_payloadSize++;
- addressDestroy(&addressEntry);
- }
- }
+ const char * name = listener_get_name(listener);
+ snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", name);
+ const char * interface_name = listener_get_interface_name(listener);
+ snprintf(cmd->interface_name, SYMBOLIC_NAME_LEN, "%s", interface_name);
+}
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (unsigned)effective_payloadSize;
+uint8_t *
+configuration_on_listener_list(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ listener_table_t * table = forwarder_get_listener_table(config->forwarder);
+ size_t n = listener_table_len(table);
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
+ msg_listener_list_reply_t * msg;
+ msg_malloc_list(msg, n)
+ if (!msg)
+ return NULL;
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len = sizeof(list_routes_command) * effective_payloadSize;
+ cmd_listener_list_item_t * payload = &msg->payload;
+ listener_t * listener;
+ listener_table_foreach(table, listener, {
+ fill_listener_command(config, listener, payload);
+ payload++;
+ });
- fibEntryList_Destroy(&fibList);
- return response;
+ return (uint8_t*)msg;
}
-static void configuration_SendResponse(Configuration *config, struct iovec *msg,
- unsigned egressId) {
- ConnectionTable *connectionTable =
- forwarder_GetConnectionTable(config->forwarder);
- const Connection *conn = connectionTable_FindById(connectionTable, egressId);
+/* Connection */
- if (conn == NULL) {
- return;
- }
- connection_SendIOVBuffer(conn, msg, 2);
-}
+uint8_t *
+configuration_on_connection_add(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
-struct iovec *configuration_ProcessCreateTunnel(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- add_connection_command *control = request[1].iov_base;
-
- bool success = false;
-
- Connection *conn;
- const char *symbolicName = control->symbolic;
-
- Address *source = NULL;
- Address *destination = NULL;
-
- if (symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) {
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Connection symbolic name already exists");
- goto ERR;
- }
-
- if (control->ipType == ADDR_INET) {
- source =
- addressFromInaddr4Port(&control->localIp.v4.as_u32, &control->localPort);
- destination =
- addressFromInaddr4Port(&control->remoteIp.v4.as_u32, &control->remotePort);
- } else if (control->ipType == ADDR_INET6) {
- source =
- addressFromInaddr6Port(&control->localIp.v6.as_in6addr, &control->localPort);
- destination =
- addressFromInaddr6Port(&control->remoteIp.v6.as_in6addr, &control->remotePort);
- } else {
- printf("Invalid IP type.\n"); // will generate a Nack
- }
-
- AddressPair *pair = addressPair_Create(source, destination);
- conn = (Connection *)connectionTable_FindByAddressPair(
- forwarder_GetConnectionTable(config->forwarder), pair);
-
- addressPair_Release(&pair);
-
- if (!conn) {
- IoOperations *ops = NULL;
- switch (control->connectionType) {
- case TCP_CONN:
- // logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- // __func__,
- // "Unsupported tunnel protocol: TCP");
- ops = tcpTunnel_Create(config->forwarder, source, destination);
- break;
- case UDP_CONN:
- ops = udpTunnel_Create(config->forwarder, source, destination);
- break;
- case GRE_CONN:
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Unsupported tunnel protocol: GRE");
- break;
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- case HICN_CONN:
- ops = hicnTunnel_Create(config->forwarder, source, destination);
- break;
-#endif /* __APPLE__ _WIN32*/
- default:
- logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error,
- __func__, "Unsupported tunnel protocol: %d",
- control->connectionType);
- break;
- }
+ msg_connection_add_t * msg = (msg_connection_add_t*)packet;
+ cmd_connection_add_t * control = &msg->payload;
- if (ops != NULL) {
- Connection *conn = connection_Create(ops);
-#ifdef WITH_POLICY
- connection_SetTags(conn, control->tags);
- connection_SetPriority(conn, control->priority);
-#endif /* WITH_POLICY */
+ const char *symbolic_name = control->symbolic;
- connection_SetAdminState(conn, control->admin_state);
+ face_type_t face_type;
+ if (!face_type_is_defined(control->type))
+ goto NACK;
+ face_type = (face_type_t)control->type;
- connectionTable_Add(forwarder_GetConnectionTable(config->forwarder),
- conn);
- symbolicNameTable_Add(config->symbolicNameTable, symbolicName,
- connection_GetConnectionId(conn));
+ connection_table_t * table = forwarder_get_connection_table(config->forwarder);
+ if (connection_table_get_by_name(table, symbolic_name)) {
+ ERROR("Connection symbolic name already exists");
+ goto NACK;
+ }
+
+ address_pair_t pair;
+ if (address_pair_from_ip_port(&pair, control->family,
+ &control->local_ip, control->local_port,
+ &control->remote_ip, control->remote_port) < 0)
+ goto NACK;
+ connection_t * connection = connection_table_get_by_pair(table, &pair);
#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_CREATE);
+ connection_event_t event;
#endif /* WITH_MAPME */
- success = true;
+ if (!connection) {
+ connection = connection_create(face_type, symbolic_name, &pair, config->forwarder);
+ if (!connection) {
+ ERROR("Failed to create %s connection",
+ face_type_str(connection->type));
+ goto NACK;
+ }
- } else {
- printf("failed, could not create IoOperations");
- }
+#ifdef WITH_MAPME
+ event = CONNECTION_EVENT_CREATE;
+#endif /* WITH_MAPME */
- } else {
+ } else {
#ifdef WITH_POLICY
- connection_SetTags(conn, control->tags);
- connection_SetPriority(conn, control->priority);
- connection_SetAdminState(conn, control->admin_state);
-
#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_UPDATE);
+ event = CONNECTION_EVENT_UPDATE;
#endif /* WITH_MAPME */
- if (source)
- addressDestroy(&source);
- if (destination)
- addressDestroy(&destination);
-
- success = true;
#else
- printf("failed, symbolic name or connection already exist\n");
+ ERROR("failed, symbolic name or connection already exist\n");
+ goto NACK;
#endif /* WITH_POLICY */
- }
-
- if (source)
- addressDestroy(&source);
- if (destination)
- addressDestroy(&destination);
-
- if (!success)
- goto ERR;
-
- // ACK
- return utils_CreateAck(header, control, sizeof(add_connection_command));
+ }
-ERR:
- return utils_CreateNack(header, control, sizeof(add_connection_command));
-}
+#ifdef WITH_POLICY
+ connection_set_tags(connection, control->tags);
+ connection_set_priority(connection, control->priority);
+#endif /* WITH_POLICY */
-struct iovec *configuration_ProcessRemoveListener(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- remove_listener_command *control = request[1].iov_base;
-
- bool success = false;
-
- const char *symbolicOrListenerid = control->symbolicOrListenerid;
- int listenerId = -1;
- ListenerSet *listenerSet = forwarder_GetListenerSet(config->forwarder);
- if (utils_IsNumber(symbolicOrListenerid)) {
- // case for connid as input
- listenerId = (unsigned)strtold(symbolicOrListenerid, NULL);
- } else {
- listenerId = listenerSet_FindIdByListenerName(listenerSet, symbolicOrListenerid);
- }
-
- if (listenerId >= 0) {
-
- ConnectionTable *connTable = forwarder_GetConnectionTable(config->forwarder);
- ListenerOps *listenerOps = listenerSet_FindById(listenerSet, listenerId);
- if (listenerOps) {
- ConnectionList *connectionList = connectionTable_GetEntries(connTable);
- for (size_t i = 0; i < connectionList_Length(connectionList); i++) {
- Connection *connection = connectionList_Get(connectionList, i);
- const AddressPair *addressPair = connection_GetAddressPair(connection);
- const Address *address = addressPair_GetLocal(addressPair);
- if (addressEquals(listenerOps->getListenAddress(listenerOps),address)) {
- // case for connid as input
- unsigned connid = connection_GetConnectionId(connection);
- // remove connection from the FIB
- forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid);
- // remove connection
- connectionTable_RemoveById(connTable, connid);
- const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid);
- symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection);
- }
- }
- connectionList_Destroy(&connectionList);
- // remove listener
- listenerSet_RemoveById(listenerSet, listenerId);
- success = true;
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "Listener Id not found, check list listeners");
- }
- }
+ connection_set_admin_state(connection, control->admin_state);
- // generate ACK/NACK
- struct iovec *response;
+#ifdef WITH_MAPME
+ /* Hook: new connection created through the control protocol */
+ forwarder_on_connection_event(config->forwarder, connection, event);
+#endif /* WITH_MAPME */
- if (success) { // ACK
- response =
- utils_CreateAck(header, control, sizeof(remove_listener_command));
- } else { // NACK
- response =
- utils_CreateNack(header, control, sizeof(remove_connection_command));
- }
+ make_ack(msg);
+ return (uint8_t*)msg;
- return response;
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
/**
* Add an IP-based tunnel.
*
- * The call cal fail if the symbolic name is a duplicate. It could also fail if
+ * The call can fail if the symbolic name is a duplicate. It could also fail if
* there's an problem creating the local side of the tunnel (i.e. the local
* socket address is not usable).
*
@@ -558,952 +451,966 @@ struct iovec *configuration_ProcessRemoveListener(Configuration *config,
* @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;
+uint8_t *
+configuration_on_connection_remove(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- bool success = false;
+ msg_connection_remove_t * msg = (msg_connection_remove_t*)packet;
+ cmd_connection_remove_t * control = &msg->payload;
- 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);
+ unsigned conn_id = symbolic_to_conn_id_self(config, control->symbolicOrConnid,
+ ingress_id);
+ if (!connection_id_is_valid(conn_id))
+ goto NACK;
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
-#endif /* WITH_MAPME */
+ /* Remove connection from the FIB */
+ forwarder_remove_connection_id_from_routes(config->forwarder, conn_id);
- success = true;
- } else if (utils_IsNumber(symbolicOrConnid)) {
- // case for connid as input
- unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL);
-
- // check if interface index present in the fwd table
- //(it was missing and therefore caused a program crash)
- if (connectionTable_FindById(table, connid)) {
- // remove connection from the FIB
- forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid);
- // remove connection
- connectionTable_RemoveById(table, connid);
- // remove connection from symbolicNameTable
- const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid);
- symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection);
+ /* Remove connection */
+ connection_table_t *table = forwarder_get_connection_table(config->forwarder);
+ connection_table_remove_by_id(table, conn_id);
+
+#if 0
+ /* Remove connection from symbolic_nameTable */
+ const char *symbolicConnection = symbolic_nameTable_GetNameByIndex(config->symbolic_nameTable, conn_id);
+ symbolic_nameTable_Remove(config->symbolic_nameTable, symbolicConnection);
+#endif
#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
+ /* Hook: new connection created through the control protocol */
+ forwarder_on_connection_event(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
#endif /* WITH_MAPME */
- success = true;
- } else {
- logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO,
- PARCLogLevel_Error, __func__,
- "ConnID not found, check list connections");
- // failure
- }
+ make_ack(msg);
+ return (uint8_t*)msg;
- } 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);
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
+}
-#ifdef WITH_MAPME
- /* Hook: new connection created through the control protocol */
- forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE);
-#endif /* WITH_MAPME */
+static inline
+void
+tolower_str(char * str) {
+ char * p = str;
+ for (; *p; p++)
+ *p = tolower(*p);
+}
- 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
- }
- }
+static inline
+void
+fill_connections_command(configuration_t * config, connection_t * connection,
+ cmd_connection_list_item_t * cmd)
+{
+ assert(config);
+ assert(connection);
+ assert(cmd);
+ struct sockaddr_in * sin;
+ struct sockaddr_in6 * sin6;
+ const address_pair_t * pair = connection_get_pair(connection);
+#if 0
+ const char *name = symbolic_nameTable_GetNameByIndex(config->symbolic_nameTable,
+ connection_get_id(connection));
+#endif
+
+ *cmd = (cmd_connection_list_item_t) {
+ .id = connection_get_id(connection),
+ .state = connection_get_state(connection),
+ .admin_state = connection_get_admin_state(connection),
+ .type = connection_get_type(connection),
+#ifdef WITH_POLICY
+ .priority = connection_get_priority(connection),
+ .tags = connection_get_tags(connection),
+#endif /* WITH_POLICY */
+ };
+
+ snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", connection_get_name(connection));
+ tolower_str(cmd->name);
+
+ snprintf(cmd->interface_name, SYMBOLIC_NAME_LEN, "%s",
+ connection_get_interface_name(connection));
+
+ switch(pair->local.ss_family) {
+ case AF_INET:
+ cmd->family = AF_INET;
+
+ sin = (struct sockaddr_in *)(&pair->local);
+ cmd->local_port = sin->sin_port;
+ cmd->local_ip.v4.as_inaddr = sin->sin_addr;
- // generate ACK/NACK
- struct iovec *response;
+ sin = (struct sockaddr_in *)(&pair->remote);
+ cmd->remote_port = sin->sin_port;
+ cmd->remote_ip.v4.as_inaddr = sin->sin_addr;
+ break;
- if (success) { // ACK
- response =
- utils_CreateAck(header, control, sizeof(remove_connection_command));
- } else { // NACK
- response =
- utils_CreateNack(header, control, sizeof(remove_connection_command));
- }
+ case AF_INET6:
+ cmd->family = AF_INET6;
- return response;
+ sin6 = (struct sockaddr_in6 *)(&pair->local);
+ cmd->local_port = sin6->sin6_port;
+ cmd->local_ip.v6.as_in6addr = sin6->sin6_addr;
+
+ sin6 = (struct sockaddr_in6 *)(&pair->remote);
+ cmd->remote_port = sin6->sin6_port;
+ cmd->remote_ip.v6.as_in6addr = sin6->sin6_addr;
+ break;
+
+ default:
+ break;
+ }
}
-void _parc_strlwr(char *string) {
- char *p = string;
- while ((*p = tolower(*p))) {
- p++;
- }
+uint8_t *
+configuration_on_connection_list(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ connection_table_t *table = forwarder_get_connection_table(config->forwarder);
+ size_t n = connection_table_len(table);
+
+ msg_connection_list_reply_t * msg;
+ msg_malloc_list(msg, n)
+ if (!msg)
+ return NULL;
+
+ cmd_connection_list_item_t * payload = &msg->payload;
+ connection_t * connection;
+ connection_table_foreach(table, connection, {
+ fill_connections_command(config, connection, payload);
+ payload++;
+ });
+
+ return (uint8_t*)msg;
}
-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;
+uint8_t *
+configuration_on_connection_set_admin_state(configuration_t * config,
+ uint8_t * packet, unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- // allocate payload, cast from void* to uint8_t* fot bytes granularity
- uint8_t *payloadResponse = parcMemory_AllocateAndClear(
- sizeof(list_connections_command) * connectionList_Length(connList));
+ msg_connection_set_admin_state_t * msg = (msg_connection_set_admin_state_t *)packet;
+ cmd_connection_set_admin_state_t *control = &msg->payload;
- for (size_t i = 0; i < connectionList_Length(connList); i++) {
- // Don't release original, it is not stored
- Connection *original = connectionList_Get(connList, i);
+ if ((control->admin_state != FACE_STATE_UP) &&
+ (control->admin_state != FACE_STATE_DOWN))
+ goto NACK;
- const AddressPair *addressPair = connection_GetAddressPair(original);
- Address *localAddress = addressCopy(addressPair_GetLocal(addressPair));
- Address *remoteAddress = addressCopy(addressPair_GetRemote(addressPair));
+ connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
+ if (!conn)
+ goto NACK;
- // 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
+ connection_set_admin_state(conn, control->admin_state);
- listConnectionsCommand->connid = connection_GetConnectionId(original);
+#ifdef WITH_MAPME
+ /* Hook: connection event */
+ forwarder_on_connection_event(config->forwarder, conn,
+ control->admin_state == FACE_STATE_UP
+ ? CONNECTION_EVENT_SET_UP
+ : CONNECTION_EVENT_SET_DOWN);
+#endif /* WITH_MAPME */
- const char *connectionName = symbolicNameTable_GetNameByIndex(config->symbolicNameTable, connection_GetConnectionId(original));
- snprintf(listConnectionsCommand->connectionName, SYMBOLIC_NAME_LEN, "%s", connectionName);
- _parc_strlwr(listConnectionsCommand->connectionName);
+ make_ack(msg);
+ return (uint8_t*)msg;
- snprintf(listConnectionsCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", ioOperations_GetInterfaceName(connection_GetIoOperations(original)));
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
+}
- listConnectionsCommand->state =
- connection_IsUp(original) ? IFACE_UP : IFACE_DOWN;
- listConnectionsCommand->connectionData.admin_state =
- (connection_GetAdminState(original) == CONNECTION_STATE_UP) ? IFACE_UP : IFACE_DOWN;
- listConnectionsCommand->connectionData.connectionType =
- ioOperations_GetConnectionType(connection_GetIoOperations(original));
- listConnectionsCommand->connectionData.admin_state = connection_GetAdminState(original);
+uint8_t *
+configuration_on_connection_update(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
#ifdef WITH_POLICY
- listConnectionsCommand->connectionData.priority = connection_GetPriority(original);
- listConnectionsCommand->connectionData.tags = connection_GetTags(original);
-#endif /* WITH_POLICY */
+ msg_connection_update_t * msg = (msg_connection_update_t *)packet;
+ cmd_connection_update_t * control = &msg->payload;
+
+ connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
+ if (!conn)
+ goto NACK;
+
+ connection_set_tags(conn, control->tags);
+ connection_set_admin_state(conn, control->admin_state);
+ if (control->priority > 0)
+ connection_set_priority(conn, control->priority);
- if (addressGetType(localAddress) == ADDR_INET &&
- addressGetType(remoteAddress) == ADDR_INET) {
- listConnectionsCommand->connectionData.ipType = ADDR_INET;
-
- // get local port/address
- addressGetInet(localAddress, &tmpAddr);
- listConnectionsCommand->connectionData.localPort = tmpAddr.sin_port;
- listConnectionsCommand->connectionData.localIp.v4.as_inaddr =
- tmpAddr.sin_addr;
- memset(&tmpAddr, 0, sizeof(tmpAddr));
- // get remote port/address
- addressGetInet(remoteAddress, &tmpAddr);
- listConnectionsCommand->connectionData.remotePort = tmpAddr.sin_port;
- listConnectionsCommand->connectionData.remoteIp.v4.as_inaddr =
- tmpAddr.sin_addr;
-
- } else if (addressGetType(localAddress) == ADDR_INET6 &&
- addressGetType(remoteAddress) == ADDR_INET6) {
- listConnectionsCommand->connectionData.ipType = ADDR_INET6;
-
- // get local port/address
- addressGetInet6(localAddress, &tmpAddr6);
- listConnectionsCommand->connectionData.localPort = tmpAddr6.sin6_port;
- listConnectionsCommand->connectionData.localIp.v6.as_in6addr = tmpAddr6.sin6_addr;
- memset(&tmpAddr6, 0, sizeof(tmpAddr6));
- // get remote port/address
- addressGetInet6(remoteAddress, &tmpAddr6);
- listConnectionsCommand->connectionData.remotePort = tmpAddr6.sin6_port;
- listConnectionsCommand->connectionData.remoteIp.v6.as_in6addr = tmpAddr6.sin6_addr;
-
- } // no need further else, control on the addressed already done at the
- // time of insertion in the connection table
- addressDestroy(&localAddress);
- addressDestroy(&remoteAddress);
- }
-
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (uint16_t)connectionList_Length(connList);
-
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
-
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len =
- sizeof(list_connections_command) * connectionList_Length(connList);
-
- connectionList_Destroy(&connList);
- return response;
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_ProcessListenersList(Configuration *config,
- struct iovec *request) {
- ListenerSet *listenerList = forwarder_GetListenerSet(config->forwarder);
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* fot bytes granularity
- uint8_t *payloadResponse = parcMemory_AllocateAndClear(
- sizeof(list_listeners_command) * listenerSet_Length(listenerList));
-
- for (size_t i = 0; i < listenerSet_Length(listenerList); i++) {
- ListenerOps *listenerEntry = listenerSet_Get(listenerList, i);
-
- // Fill payload by shifting and casting at each 'i' step.
- list_listeners_command *listListenersCommand =
- (list_listeners_command *)(payloadResponse +
- (i * sizeof(list_listeners_command)));
-
- listListenersCommand->connid =
- (uint32_t)listenerEntry->getInterfaceIndex(listenerEntry);
- listListenersCommand->encapType =
- (uint8_t)listenerEntry->getEncapType(listenerEntry);
- if (addressGetType((const Address *)listenerEntry->getListenAddress(
- listenerEntry)) == ADDR_INET) {
- addressGetInet(
- (const Address *)listenerEntry->getListenAddress(listenerEntry),
- &tmpAddr);
- listListenersCommand->addressType = ADDR_INET;
- listListenersCommand->address.v4.as_inaddr = tmpAddr.sin_addr;
- listListenersCommand->port = tmpAddr.sin_port;
- } else if (addressGetType((const Address *)listenerEntry->getListenAddress(
- listenerEntry)) == ADDR_INET6) {
- addressGetInet6(
- (const Address *)listenerEntry->getListenAddress(listenerEntry),
- &tmpAddr6);
- listListenersCommand->addressType = ADDR_INET6;
- listListenersCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr;
- listListenersCommand->port = tmpAddr6.sin6_port;
- }
+uint8_t *
+configuration_on_connection_set_priority(configuration_t * config,
+ uint8_t * packet, unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- const char * listenerName = listenerEntry->getListenerName(listenerEntry);
- snprintf(listListenersCommand->listenerName, SYMBOLIC_NAME_LEN, "%s", listenerName);
- if (listenerEntry->getEncapType(listenerEntry) == ENCAP_TCP ||
- listenerEntry->getEncapType(listenerEntry) == ENCAP_UDP) {
- const char * interfaceName = listenerEntry->getInterfaceName(listenerEntry);
- snprintf(listListenersCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", interfaceName);
- }
- }
+#ifdef WITH_POLICY
+ msg_connection_set_priority_t * msg = (msg_connection_set_priority_t *)packet;
+ cmd_connection_set_priority_t * control = &msg->payload;
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (uint16_t)listenerSet_Length(listenerList);
+ connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
+ if (!conn)
+ goto NACK;
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
+ connection_set_priority(conn, control->priority);
- 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);
+#ifdef WITH_MAPME
+ /* Hook: connection event */
+ forwarder_on_connection_event(config->forwarder, conn,
+ CONNECTION_EVENT_PRIORITY_CHANGED);
+#endif /* WITH_MAPME */
- return response;
-}
+ make_ack(msg);
+ return (uint8_t*)msg;
-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;
+NACK:
+#endif /* WITH_POLICY */
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-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;
-}
+uint8_t *
+configuration_on_connection_set_tags(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+#ifdef WITH_POLICY
+ msg_connection_set_tags_t * msg = (msg_connection_set_tags_t *)packet;
+ cmd_connection_set_tags_t * control = &msg->payload;
-struct iovec *configuration_ProcessCacheClear(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
+ connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
+ if (!conn)
+ goto NACK;
- forwarder_ClearCache(config->forwarder);
+ connection_set_tags(conn, control->tags);
- struct iovec *response = utils_CreateAck(header, NULL, 0);
- return response;
-}
+#ifdef WITH_MAPME
+ /* Hook: connection event */
+ forwarder_on_connection_event(config->forwarder, conn,
+ CONNECTION_EVENT_TAGS_CHANGED);
+#endif /* WITH_MAPME */
-size_t configuration_GetObjectStoreSize(Configuration *config) {
- return config->maximumContentObjectStoreSize;
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+#endif /* WITH_POLICY */
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-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);
+
+/* Route */
+
+uint8_t *
+configuration_on_route_add(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_route_add_t * msg = (msg_route_add_t *)packet;
+ cmd_route_add_t * control = &msg->payload;
+
+ unsigned conn_id = symbolic_to_conn_id_self(config,
+ control->symbolicOrConnid, ingress_id);
+ if (!connection_id_is_valid(conn_id))
+ goto NACK;
+
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len
+ };
+
+ if (!forwarder_add_or_update_route(config->forwarder, &prefix, conn_id))
+ goto NACK;
+
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-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));
- }
+uint8_t *
+configuration_on_route_remove(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_route_remove_t * msg = (msg_route_remove_t *)packet;
+ cmd_route_remove_t * control = &msg->payload;
+
+ unsigned conn_id = symbolic_to_conn_id(config, control->symbolicOrConnid);
+ if (!connection_id_is_valid(conn_id))
+ goto NACK;
+
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len
+ };
+
+ if (!forwarder_remove_route(config->forwarder, &prefix, conn_id))
+ goto NACK;
- return response;
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-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;
- }
+uint8_t *
+configuration_on_route_list(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ const fib_t * fib = forwarder_get_fib(config->forwarder);
+ fib_entry_t * entry;
+
+ /*
+ * Two step approach to precompute the number of entries to allocate
+ *
+ * NOTE: we might have routes with no or multiple next hops.
+ */
+ size_t n = 0;
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t * nexthops = fib_entry_get_nexthops(entry);
+ assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops));
+ n += nexthops_get_len(nexthops);
+ });
+
+ msg_route_list_reply_t * msg;
+ msg_malloc_list(msg, n);
+ if (!msg)
+ return NULL;
+
+ cmd_route_list_item_t * payload = &msg->payload;
+ fib_foreach_entry(fib, entry, {
+ const nexthops_t * nexthops = fib_entry_get_nexthops(entry);
+ assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops));
+ size_t num_nexthops = nexthops_get_len(nexthops);
+
+ if (num_nexthops == 0)
+ continue;
+
+ NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry));
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+
+ address_t address;
+ nameBitvector_ToAddress(prefix, &address);
+ switch(address_family(&address)) {
+ case AF_INET:
+ payload->family = AF_INET;
+ payload->address.v4.as_inaddr = address4_ip(&address);
+ break;
+ case AF_INET6:
+ payload->family = AF_INET6;
+ payload->address.v6.as_in6addr = address6_ip(&address);
+ break;
+ default:
+ break;
+ }
+ payload->connection_id = nexthop;
+ payload->len = nameBitvector_GetLength(prefix);
+ payload->cost = DEFAULT_COST;
+
+ payload++;
+ });
+ });
+
+ return (uint8_t*)msg;
}
-struct iovec *configuration_SetForwardingStrategy(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- set_strategy_command *control = request[1].iov_base;
-
- const char *prefix = utils_PrefixLenToString(
- control->addressType, &control->address, &control->len);
- strategy_type strategy = control->strategyType;
- strategy_type existingFwdStrategy =
- configuration_GetForwardingStrategy(config, prefix);
-
- if (existingFwdStrategy == LAST_STRATEGY_VALUE ||
- strategy != existingFwdStrategy) {
- // means such a new strategy is not present in the hash table or has to be
- // updated
- _configuration_StoreFwdStrategy(config, prefix, strategy);
- Name *hicnPrefix = name_CreateFromAddress(control->addressType,
- control->address, control->len);
- Name *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- if(control->related_prefixes != 0){
- for(int i = 0; i < control->related_prefixes; i++){
- related_prefixes[i] = name_CreateFromAddress(
- control->addresses_type[i],
- control->addresses[i], control->lens[i]);
- }
- }
- forwarder_SetStrategy(config->forwarder, hicnPrefix, strategy,
- control->related_prefixes, related_prefixes);
- name_Release(&hicnPrefix);
- if(control->related_prefixes != 0){
- for(int i = 0; i < control->related_prefixes; i++){
- name_Release(&related_prefixes[i]);
- }
- }
- }
- free((char *) prefix);
- struct iovec *response =
- utils_CreateAck(header, control, sizeof(set_strategy_command));
+/* Cache */
- return response;
-}
+uint8_t *
+configuration_on_cache_set_store(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_cache_set_store_t * msg = (msg_cache_set_store_t *)packet;
+ cmd_cache_set_store_t * control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1))
+ goto NACK;
+ bool value = (bool)control->activate;
-void configuration_SetObjectStoreSize(Configuration *config,
- size_t maximumObjectCount) {
- config->maximumContentObjectStoreSize = maximumObjectCount;
+ forwarder_content_store_set_store(config->forwarder, value);
+ /* XXX Why do we need to check ? */
+ if (forwarder_content_store_get_store(config->forwarder) != value)
+ goto NACK;
- forwarder_SetContentObjectStoreSize(config->forwarder,
- config->maximumContentObjectStoreSize);
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-Forwarder *configuration_GetForwarder(const Configuration *config) {
- return config->forwarder;
+uint8_t *
+configuration_on_cache_set_serve(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_cache_set_serve_t * msg = (msg_cache_set_serve_t *)packet;
+ cmd_cache_set_serve_t * control = &msg->payload;
+
+ if ((control->activate != 0) && (control->activate != 1))
+ goto NACK;
+ bool value = (bool)control->activate;
+
+ forwarder_content_store_set_serve(config->forwarder, value);
+ /* XXX Why do we need to check ? */
+ if (forwarder_content_store_get_serve(config->forwarder) != value)
+ goto NACK;
+
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-Logger *configuration_GetLogger(const Configuration *config) {
- return config->logger;
+uint8_t *
+configuration_on_cache_clear(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_cache_clear_t * msg = (msg_cache_clear_t *)packet;
+
+ forwarder_content_store_clear(config->forwarder);
+
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_MapMeEnable(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- mapme_activator_command *control = request[1].iov_base;
- const char *stateString[2] = {"on", "off"};
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer,
- "The mapme enable setting received is: %s",
- stateString[control->activate]);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+/* Strategy */
+
+strategy_type_t
+configuration_get_strategy(configuration_t * config, const char *prefix)
+{
+ khiter_t k = kh_get_strategy_map(config->strategy_map, prefix);
+ if (k == kh_end(config->strategy_map))
+ return STRATEGY_TYPE_UNDEFINED;
+ return kh_val(config->strategy_map, k);
}
-struct iovec *configuration_MapMeDiscovery(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- mapme_activator_command *control = request[1].iov_base;
- const char *stateString[2] = {"on", "off"};
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer,
- "The mapme discovery setting received is: %s",
- stateString[control->activate]);
-
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
-
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+uint8_t *
+configuration_on_strategy_set(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_strategy_set_t * msg = (msg_strategy_set_t *)packet;
+ cmd_strategy_set_t * control = &msg->payload;
+
+ char prefix_s[MAXSZ_IP_PREFIX];
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len,
+ };
+ int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0)
+ goto NACK;
+
+ strategy_type_t strategy = control->strategy_type;
+ strategy_type_t existingFwdStrategy =
+ configuration_get_strategy(config, prefix_s);
+
+ strategy_options_t options;
+
+ if (existingFwdStrategy == STRATEGY_TYPE_UNDEFINED ||
+ strategy != existingFwdStrategy) {
+ // means such a new strategy is not present in the hash table or has to be
+ // updated
+ int res;
+ khiter_t k = kh_put_strategy_map(config->strategy_map, prefix_s, &res);
+ kh_value(config->strategy_map, k) = strategy;
+
+ Name *name_prefix = name_CreateFromAddress(control->family,
+ control->address, control->len);
+ // XXX TODO error handling
+
+ switch(control->strategy_type) {
+ case STRATEGY_TYPE_LOW_LATENCY:
+ options.low_latency.related_prefixes_len = control->related_prefixes;
+ Name **related_prefixes = options.low_latency.related_prefixes;
+
+ if(control->related_prefixes != 0){
+ for(int i = 0; i < control->related_prefixes; i++){
+ related_prefixes[i] = name_CreateFromAddress(
+ control->low_latency.families[i],
+ control->low_latency.addresses[i],
+ control->low_latency.lens[i]);
+ }
+ // XXX TODO error handling
+ }
+ forwarder_set_strategy(config->forwarder, name_prefix, strategy, &options);
+
+ if (control->related_prefixes != 0) {
+ for(int i = 0; i < control->related_prefixes; i++)
+ name_Release(&related_prefixes[i]);
+ }
+ break;
+ default:
+ break;
+ }
+ name_Release(&name_prefix);
+ }
+
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+ make_nack(msg);
+ return (uint8_t*)msg;
}
-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;
+/* WLDR */
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(composer,
- "The mapme timescale value received is: %u",
- control->timePeriod);
+uint8_t *
+configuration_on_wldr_set(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
+ msg_wldr_set_t * msg = (msg_wldr_set_t *)packet;
+ cmd_wldr_set_t * control = &msg->payload;
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
-}
+ if ((control->activate != 0) && (control->activate != 1))
+ goto NACK;
+ bool value = (bool)control->activate;
-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;
+ unsigned conn_id = symbolic_to_conn_id(config, control->symbolicOrConnid);
+ if (!connection_id_is_valid(conn_id))
+ goto NACK;
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_Format(
- composer, "The mapme retransmission time value received is: %u",
- control->timePeriod);
+ connection_table_t * table = forwarder_get_connection_table(config->forwarder);
+ connection_t * conn = connection_table_at(table, conn_id);
- PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
- char *result = parcBuffer_ToString(tempBuffer);
- parcBuffer_Release(&tempBuffer);
- puts(result);
- parcMemory_Deallocate((void **)&result);
- parcBufferComposer_Release(&composer);
+ if (value)
+ connection_wldr_enable(conn, value);
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec * configuration_MapMeSendUpdate(Configuration *config,
- struct iovec *request, unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- mapme_send_update_command *control = request[1].iov_base;
-
- FIB * fib = forwarder_getFib(config->forwarder);
- if (!fib)
- goto ERR;
- Name *prefix = name_CreateFromAddress(control->addressType, control->address,
- control->len);
- if (!prefix)
- goto ERR;
- FibEntry *entry = fib_Contains(fib, prefix);
- name_Release(&prefix);
- if (!entry)
- goto ERR;
-
- const NumberSet * nexthops = fibEntry_GetNexthops(entry);
- unsigned size = (unsigned) numberSet_Length(nexthops);
-
- /* The command is accepted iif triggered by (one of) the producer of this prefix */
- for (unsigned i = 0; i < size; i++) {
- unsigned nhop = numberSet_GetItem(nexthops, i);
- if (nhop == ingressId) {
- MapMe * mapme = forwarder_getMapmeInstance(config->forwarder);
- mapme_send_updates(mapme, entry, nexthops);
- return utils_CreateAck(header, control, sizeof(mapme_timing_command));
+/* Punting */
+
+uint8_t *
+configuration_on_punting_add(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
+ msg_punting_add_t * msg = (msg_punting_add_t *)packet;
+ cmd_punting_add_t * control = &msg->payload;
+
+ if (ip_address_empty(&control->address))
+ goto NACK;
+
+ /* This is for hICN listeners only */
+ // XXX add check !
+ // comments:
+ // EncapType: I use the Hicn encap since the punting is available only for
+ // Hicn listeners LocalAddress: The only listern for which we need punting
+ // rules is the main one, which has no address
+ // so I create a fake empty address. This need to be consistent
+ // with the address set at creation time
+ address_t fakeaddr;
+ memset(&fakeaddr, 0, sizeof(address_t));
+ fakeaddr = ADDRESS_ANY(control->family, DEFAULT_PORT);
+
+ forwarder_t * forwarder = configuration_get_forwarder(config);
+ listener_table_t * table = forwarder_get_listener_table(forwarder);
+ listener_t * listener = listener_table_get_by_address(table, FACE_TYPE_HICN, &fakeaddr);
+ if (!listener) {
+ ERROR("the main listener does not exist");
+ goto NACK;
+ }
+
+
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len
+ };
+ char prefix_s[MAXSZ_IP_PREFIX];
+ int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix);
+ assert(rc < MAXSZ_IP_PREFIX);
+ if (rc < 0)
+ goto NACK;
+
+ if (listener_punt(listener, prefix_s) < 0) {
+ ERROR("error while adding the punting rule\n");
+ goto NACK;
}
- }
-ERR:
- return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command));
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
+#endif
+ make_ack(msg);
+ return (uint8_t*)msg;
}
+/* MAP-Me */
-struct iovec *configuration_ConnectionSetAdminState(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- connection_set_admin_state_command *control = request[1].iov_base;
+uint8_t *
+configuration_on_mapme_enable(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- if ((control->admin_state != CONNECTION_STATE_UP) && (control->admin_state != CONNECTION_STATE_DOWN))
- return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command));
+ msg_mapme_enable_t * msg = (msg_mapme_enable_t *)packet;
+ cmd_mapme_enable_t * control = &msg->payload;
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command));
+ if ((control->activate != 0) && (control->activate != 1))
+ goto NACK;
+ bool value = (bool)control->activate;
- connection_SetAdminState(conn, control->admin_state);
+ INFO("MAP-Me SET enable: %s", value ? "on" : "off");
-#ifdef WITH_MAPME
- /* Hook: connection event */
- forwarder_onConnectionEvent(config->forwarder, conn,
- control->admin_state == CONNECTION_STATE_UP
- ? CONNECTION_EVENT_SET_UP
- : CONNECTION_EVENT_SET_DOWN);
-#endif /* WITH_MAPME */
+ make_ack(msg);
+ return (uint8_t*)msg;
- return utils_CreateAck(header, control, sizeof(connection_set_admin_state_command));
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-#ifdef WITH_POLICY
+uint8_t *
+configuration_on_mapme_set_discovery(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
-struct iovec *configuration_ConnectionSetPriority(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- connection_set_priority_command *control = request[1].iov_base;
+ msg_mapme_set_discovery_t * msg = (msg_mapme_set_discovery_t *)packet;
+ cmd_mapme_set_discovery_t * control = &msg->payload;
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(connection_set_priority_command));
+ if ((control->activate != 0) && (control->activate != 1))
+ goto NACK;
+ bool value = (bool)control->activate;
- connection_SetPriority(conn, control->priority);
+ INFO("MAP-Me SET discovery: %s", value ? "on" : "off");
-#ifdef WITH_MAPME
- /* Hook: connection event */
- forwarder_onConnectionEvent(config->forwarder, conn,
- CONNECTION_EVENT_PRIORITY_CHANGED);
-#endif /* WITH_MAPME */
+ make_ack(msg);
+ return (uint8_t*)msg;
- return utils_CreateAck(header, control, sizeof(connection_set_priority_command));
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_ConnectionSetTags(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- connection_set_tags_command *control = request[1].iov_base;
+uint8_t *
+configuration_on_mapme_set_timescale(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(connection_set_tags_command));
+ msg_mapme_set_timescale_t * msg = (msg_mapme_set_timescale_t *)packet;
+ cmd_mapme_set_timescale_t * control = &msg->payload;
- connection_SetTags(conn, control->tags);
+ INFO("MAP-Me SET timescale: %u", control->timePeriod);
-#ifdef WITH_MAPME
- /* Hook: connection event */
- forwarder_onConnectionEvent(config->forwarder, conn,
- CONNECTION_EVENT_TAGS_CHANGED);
-#endif /* WITH_MAPME */
+ make_ack(msg);
+ return (uint8_t*)msg;
+}
+
+uint8_t *
+configuration_on_mapme_set_retx(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_mapme_set_retx_t * msg = (msg_mapme_set_retx_t *)packet;
+ cmd_mapme_set_retx_t * control = &msg->payload;
- return utils_CreateAck(header, control, sizeof(connection_set_tags_command));
+ INFO("MAP-Me SET retx: %u", control->timePeriod);
+
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_ProcessPolicyAdd(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- add_policy_command *control = request[1].iov_base;
- if (forwarder_AddOrUpdatePolicy(config->forwarder, control)) {
- return utils_CreateAck(header, control, sizeof(add_policy_command));
- } else {
- return utils_CreateNack(header, control, sizeof(add_policy_command));
- }
+uint8_t *
+configuration_on_mapme_send_update(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
+
+ msg_mapme_send_update_t * msg = (msg_mapme_send_update_t *)packet;
+ cmd_mapme_send_update_t * control = &msg->payload;
+
+ fib_t * fib = forwarder_get_fib(config->forwarder);
+ if (!fib)
+ goto NACK;
+ Name *prefix = name_CreateFromAddress(control->family, control->address,
+ control->len);
+ if (!prefix)
+ goto NACK;
+ fib_entry_t *entry = fib_contains(fib, prefix);
+ name_Release(&prefix);
+ if (!entry)
+ goto NACK;
+
+ /* The command is accepted iif triggered by (one of) the producer of this prefix */
+ const nexthops_t * nexthops = fib_entry_get_nexthops(entry);
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ if (nexthop != ingress_id)
+ continue;
+ mapme_t * mapme = forwarder_get_mapme(config->forwarder);
+ mapme_send_to_all_nexthops(mapme, entry);
+ make_ack(msg);
+ return (uint8_t*)msg;
+ });
+
+NACK:
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_ProcessPolicyList(Configuration *config,
- struct iovec *request) {
- FibEntryList *fibList = forwarder_GetFibEntries(config->forwarder);
-
- size_t payloadSize = fibEntryList_Length(fibList);
- struct sockaddr_in tmpAddr;
- struct sockaddr_in6 tmpAddr6;
-
- // allocate payload, cast from void* to uint8_t* = bytes granularity
- uint8_t *payloadResponse =
- parcMemory_AllocateAndClear(sizeof(list_policies_command) * payloadSize);
-
- for (size_t i = 0; i < fibEntryList_Length(fibList); i++) {
- FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i);
- NameBitvector *prefix = name_GetContentName(fibEntry_GetPrefix(entry));
-
- list_policies_command *listPoliciesCommand =
- (list_policies_command *)(payloadResponse +
- (i * sizeof(list_policies_command)));
-
- Address *addressEntry = nameBitvector_ToAddress(prefix);
- if (addressGetType(addressEntry) == ADDR_INET) {
- addressGetInet(addressEntry, &tmpAddr);
- listPoliciesCommand->addressType = ADDR_INET;
- listPoliciesCommand->address.v4.as_inaddr = tmpAddr.sin_addr;
- } else if (addressGetType(addressEntry) == ADDR_INET6) {
- addressGetInet6(addressEntry, &tmpAddr6);
- listPoliciesCommand->addressType = ADDR_INET6;
- listPoliciesCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr;
- }
- listPoliciesCommand->len = nameBitvector_GetLength(prefix);
- listPoliciesCommand->policy = fibEntry_GetPolicy(entry);
+/* Policy */
- addressDestroy(&addressEntry);
- }
+uint8_t *
+configuration_on_policy_add(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
- // send response
- header_control_message *header = request[0].iov_base;
- header->messageType = RESPONSE_LIGHT;
- header->length = (unsigned)payloadSize;
+#ifdef WITH_POLICY
+ msg_policy_add_t * msg = (msg_policy_add_t *)packet;
+ cmd_policy_add_t * control = &msg->payload;
+
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len
+ };
- struct iovec *response =
- parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
+ if (!forwarder_add_or_update_policy(config->forwarder, &prefix, &control->policy))
+ goto NACK;
- response[0].iov_base = header;
- response[0].iov_len = sizeof(header_control_message);
- response[1].iov_base = payloadResponse;
- response[1].iov_len = sizeof(list_policies_command) * payloadSize;
+ make_ack(msg);
+ return (uint8_t*)msg;
- fibEntryList_Destroy(&fibList);
- return response;
+NACK:
+#endif /* WITH_POLICY */
+ make_ack(msg);
+ return (uint8_t*)msg;
}
-struct iovec *configuration_ProcessPolicyRemove(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- remove_policy_command *control = request[1].iov_base;
- if (forwarder_RemovePolicy(config->forwarder, control))
- return utils_CreateAck(header, control, sizeof(remove_policy_command));
- else
- return utils_CreateNack(header, control, sizeof(remove_policy_command));
-}
+uint8_t *
+configuration_on_policy_remove(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
-struct iovec *configuration_UpdateConnection(Configuration *config,
- struct iovec *request) {
- header_control_message *header = request[0].iov_base;
- update_connection_command *control = request[1].iov_base;
+#ifdef WITH_POLICY
+ msg_policy_remove_t * msg = (msg_policy_remove_t *)packet;
+ cmd_policy_remove_t * control = &msg->payload;
- Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid);
- if (!conn)
- return utils_CreateNack(header, control, sizeof(update_connection_command));
+ ip_prefix_t prefix = {
+ .family = control->family,
+ .address = control->address,
+ .len = control->len
+ };
- connection_SetTags(conn, control->tags);
- connection_SetAdminState(conn, control->admin_state);
- if (control->priority > 0)
- connection_SetPriority(conn, control->priority);
+ if (!forwarder_remove_policy(config->forwarder, &prefix))
+ goto NACK;
- return utils_CreateAck(header, control, sizeof(update_connection_command));
-}
+ make_ack(msg);
+ return (uint8_t*)msg;
+
+NACK:
#endif /* WITH_POLICY */
+ make_ack(msg);
+ return (uint8_t*)msg;
+}
-// ===========================
-// Main functions that deal with receiving commands, executing them, and sending
-// ACK/NACK
+uint8_t *
+configuration_on_policy_list(configuration_t * config, uint8_t * packet,
+ unsigned ingress_id)
+{
+ assert(config);
+ assert(packet);
-struct iovec *configuration_DispatchCommand(Configuration *config,
- command_id command,
- struct iovec *control,
- unsigned ingressId) {
- struct iovec *response = NULL;
- switch (command) {
- case ADD_LISTENER:
- response = configurationListeners_Add(config, control, ingressId);
- break;
-
- case ADD_CONNECTION:
- response = configuration_ProcessCreateTunnel(config, control);
- break;
-
- case LIST_CONNECTIONS:
- response = configuration_ProcessConnectionList(config, control);
- break;
-
- case ADD_ROUTE:
- response =
- configuration_ProcessRegisterHicnPrefix(config, control, ingressId);
- break;
-
- case LIST_ROUTES:
- response = configuration_ProcessRegistrationList(config, control);
- break;
-
- case REMOVE_CONNECTION:
- response = configuration_ProcessRemoveTunnel(config, control, ingressId);
- break;
-
- case REMOVE_LISTENER:
- response = configuration_ProcessRemoveListener(config, control, ingressId);
- break;
-
- case REMOVE_ROUTE:
- response = configuration_ProcessUnregisterHicnPrefix(config, control);
- break;
-
- case CACHE_STORE:
- response = configuration_ProcessCacheStore(config, control);
- break;
-
- case CACHE_SERVE:
- response = configuration_ProcessCacheServe(config, control);
- break;
-
- case CACHE_CLEAR:
- response = configuration_ProcessCacheClear(config, control);
- break;
-
- case SET_STRATEGY:
- response = configuration_SetForwardingStrategy(config, control);
- break;
-
- case SET_WLDR:
- response = configuration_SetWldr(config, control);
- break;
-
- case ADD_PUNTING:
- response = configurationListeners_AddPunting(config, control, ingressId);
- break;
-
- case LIST_LISTENERS:
- response = configuration_ProcessListenersList(config, control);
- break;
-
- case MAPME_ENABLE:
- response = configuration_MapMeEnable(config, control);
- break;
-
- case MAPME_DISCOVERY:
- response = configuration_MapMeDiscovery(config, control);
- break;
-
- case MAPME_TIMESCALE:
- response = configuration_MapMeTimescale(config, control);
- break;
-
- case MAPME_RETX:
- response = configuration_MapMeRetx(config, control);
- break;
-
- case MAPME_SEND_UPDATE:
- response = configuration_MapMeSendUpdate(config, control, ingressId);
- break;
-
- case CONNECTION_SET_ADMIN_STATE:
- response = configuration_ConnectionSetAdminState(config, control);
- break;
+ const fib_t * fib = forwarder_get_fib(config->forwarder);
+ assert(fib);
+ size_t n = fib_get_size(fib);
#ifdef WITH_POLICY
- case ADD_POLICY:
- response = configuration_ProcessPolicyAdd(config, control);
- break;
+ msg_policy_list_reply_t * msg;
+ msg_malloc_list(msg, n);
+ if (!msg)
+ return NULL;
+
+ cmd_policy_list_item_t * payload = &msg->payload;
+
+ fib_entry_t * entry;
- case LIST_POLICIES:
- response = configuration_ProcessPolicyList(config, control);
- break;
+ fib_foreach_entry(fib, entry, {
+ NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry));
+ address_t address;
+ nameBitvector_ToAddress(prefix, &address);
- case REMOVE_POLICY:
- response = configuration_ProcessPolicyRemove(config, control);
- break;
+ switch(address_family(&address)) {
+ case AF_INET:
+ payload->family = AF_INET;
+ payload->address.v4.as_inaddr = address4_ip(&address);
+ break;
- case UPDATE_CONNECTION:
- response = configuration_UpdateConnection(config, control);
- break;
+ case AF_INET6:
+ payload->family = AF_INET6;
+ payload->address.v6.as_in6addr = address6_ip(&address);
+ break;
- case CONNECTION_SET_PRIORITY:
- response = configuration_ConnectionSetPriority(config, control);
- break;
+ default:
+ break;
+ }
+ payload->len = nameBitvector_GetLength(prefix);
+ payload->policy = fib_entry_get_policy(entry);
+
+ payload++;
+ });
- case CONNECTION_SET_TAGS:
- response = configuration_ConnectionSetTags(config, control);
- break;
+ return (uint8_t*)msg;
+#else
+ return NULL;
#endif /* WITH_POLICY */
+}
- default:
- break;
- }
+size_t
+configuration_content_store_get_size(configuration_t * config)
+{
+ return config->maximumContentObjectStoreSize;
+}
+
+void
+configuration_content_store_set_size(configuration_t * config, size_t size)
+{
+ config->maximumContentObjectStoreSize = size;
- return response;
+ forwarder_content_store_set_size(config->forwarder,
+ config->maximumContentObjectStoreSize);
}
-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...:
- case LIST_LISTENERS:
- 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
+forwarder_t *
+configuration_get_forwarder(const configuration_t * config) {
+ return config->forwarder;
+}
+
+
+// ===========================
+// Main functions that deal with receiving commands, executing them, and sending
+// ACK/NACK
+
+uint8_t *
+configuration_dispatch_command(configuration_t * config, command_type_t command_type,
+ uint8_t * packet, unsigned ingress_id)
+{
+ switch (command_type) {
+#define _(l, u) \
+ case COMMAND_TYPE_ ## u: \
+ return configuration_on_ ## l(config, packet, ingress_id);
+ foreach_command_type
+#undef _
+ case COMMAND_TYPE_UNDEFINED:
+ case COMMAND_TYPE_N:
+ ERROR("Unexpected command type");
+ break;
+ }
+ return NULL;
+}
+
+void configuration_receive_command(configuration_t * config,
+ command_type_t command_type, uint8_t * packet, unsigned ingress_id)
+{
+ assert(config);
+ assert(command_type_is_valid(command_type));
+ assert(packet);
+
+ bool nack = false;
+
+ uint8_t * reply = configuration_dispatch_command(config, command_type, packet, ingress_id);
+ if (!reply) {
+ reply = packet;
+ msg_header_t * hdr = (msg_header_t *)reply;
+ make_nack(hdr);
+ nack = true;
+ }
+
+ connection_table_t * table = forwarder_get_connection_table(config->forwarder);
+ const connection_t *connection = connection_table_at(table, ingress_id);
+ connection_send_packet(connection, reply, false);
+
+ switch (command_type) {
+ case COMMAND_TYPE_LISTENER_LIST:
+ case COMMAND_TYPE_CONNECTION_LIST:
+ case COMMAND_TYPE_ROUTE_LIST:
+ case COMMAND_TYPE_POLICY_LIST:
+ if (!nack)
+ free(reply);
+ break;
+ default:
+ break;
+ }
}
diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h
index 5090f14..86efa52 100644
--- a/hicn-light/src/hicn/config/configuration.h
+++ b/hicn-light/src/hicn/config/configuration.h
@@ -26,14 +26,11 @@
#ifndef configuration_h
#define configuration_h
-#include <hicn/core/logger.h>
#include <hicn/utils/commands.h>
-struct configuration;
-typedef struct configuration Configuration;
+typedef struct configuration_s configuration_t;
-struct forwarder;
-typedef struct forwarder Forwarder;
+struct forwarder_s;
/**
* <#One Line Description#>
@@ -49,7 +46,7 @@ typedef struct forwarder Forwarder;
* <#example#>
* @endcode
*/
-Configuration *configuration_Create(Forwarder *forwarder);
+configuration_t * configuration_create(struct forwarder_s * forwarder);
/**
* <#One Line Description#>
@@ -65,13 +62,13 @@ Configuration *configuration_Create(Forwarder *forwarder);
* <#example#>
* @endcode
*/
-void configuration_Destroy(Configuration **configPtr);
+void configuration_free(configuration_t * config);
-void configuration_SetupAllListeners(Configuration *config, uint16_t port,
+void configuration_setup_all_listeners(configuration_t *config, uint16_t port,
const char *localPath);
-void configuration_ReceiveCommand(Configuration *config, command_id command,
- struct iovec *request, unsigned ingressId);
+void configuration_receive_command(configuration_t *config, command_type_t command,
+ uint8_t * packet, unsigned ingress_id);
/**
* Returns the configured size of the content store
@@ -87,7 +84,7 @@ void configuration_ReceiveCommand(Configuration *config, command_id command,
* <#example#>
* @endcode
*/
-size_t configuration_GetObjectStoreSize(Configuration *config);
+size_t configuration_content_store_get_size(configuration_t *config);
/**
* Sets the size of the content store (in objects, not bytes)
@@ -101,11 +98,9 @@ size_t configuration_GetObjectStoreSize(Configuration *config);
* <#example#>
* @endcode
*/
-void configuration_SetObjectStoreSize(Configuration *config,
- size_t maximumContentObjectCount);
+void configuration_content_store_set_size(configuration_t *config, size_t size);
-strategy_type configuration_GetForwardingStrategy(Configuration *config,
- const char *prefix);
+strategy_type_t configuration_get_strategy(configuration_t *config, const char *prefix);
/**
* Returns the Forwarder that owns the Configuration
@@ -125,28 +120,10 @@ strategy_type configuration_GetForwardingStrategy(Configuration *config,
* }
* @endcode
*/
-Forwarder *configuration_GetForwarder(const Configuration *config);
+struct forwarder_s * configuration_get_forwarder(const configuration_t *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);
+uint8_t *
+configuration_dispatch_command(configuration_t * config, command_type_t command_type,
+ uint8_t * packet, unsigned ingress_id);
#endif // configuration_h
diff --git a/hicn-light/src/hicn/config/configurationFile.c b/hicn-light/src/hicn/config/configurationFile.c
deleted file mode 100644
index 5f9c9ce..0000000
--- a/hicn-light/src/hicn/config/configurationFile.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_List.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/config/configuration.h>
-#include <hicn/config/configurationFile.h>
-#include <hicn/config/controlRoot.h>
-#include <hicn/config/controlState.h>
-
-struct configuration_file {
- Forwarder *forwarder;
- const char *filename;
- FILE *fh;
-
- size_t linesRead;
-
- // our custom state machine.
- ControlState *controlState;
-};
-
-/*
- * Called by a command to dispatch the correct command
- */
-struct iovec *_writeRead(ControlState *state, struct iovec *msg) {
- ConfigurationFile *configFile =
- (ConfigurationFile *)controlState_GetUserdata(state);
-
- parcAssertNotNull(msg, "Parameter msg must be non-null");
- struct iovec *response = configuration_DispatchCommand(
- forwarder_GetConfiguration(configFile->forwarder),
- ((header_control_message *)msg[0].iov_base)->commandID, msg, 0);
-
- return response;
-}
-
-/**
- * Removes leading whitespace (space + tab).
- *
- * If the string is all whitespace, the return value will point to the
- * terminating '\0'.
- *
- * @param [in] str A null-terminated c-string
- *
- * @retval non-null A pointer in to string of the first non-whitespace
- *
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-static char *_stripLeadingWhitespace(char *str) {
- while (isspace(*str)) {
- str++;
- }
- return str;
-}
-
-/**
- * Removes trailing whitespace
- *
- * Inserts a NULL after the last non-whitespace character, modiyfing the input
- * string.
- *
- * @param [in] str A null-terminated c-string
- *
- * @return non-null A pointer to the input string
- *
- * Example:
- * @code
- * {
- * <#example#>
- * }
- * @endcode
- */
-static char *_stripTrailingWhitespace(char *str) {
- char *p = str + strlen(str) - 1;
- while (p > str && isspace(*p)) {
- p--;
- }
-
- // cap it. If no whitespace, p+1 == str + strlen(str), so will overwrite the
- // current null. If all whitespace p+1 == str+1. For an empty string, p+1 =
- // str.
- *(p + 1) = 0;
-
- // this does not catch the case where the entire string is whitespace
- if (p == str && isspace(*p)) {
- *p = 0;
- }
-
- return str;
-}
-
-/**
- * Removed leading and trailing whitespace
- *
- * Modifies the input string (may add a NULL at the end). Will return
- * a pointer to the first non-whitespace character or the terminating NULL.
- *
- * @param [in] str A null-terminated c-string
- *
- * @return non-null A pointer in to the input string
- *
- * Example:
- * @code
- * {
- * <#example#>
- * }
- * @endcode
- */
-static char *_trim(char *str) {
- return _stripTrailingWhitespace(_stripLeadingWhitespace(str));
-}
-
-/**
- * Parse a string in to a PARCList with one word per element
- *
- * The string passed will be modified by inserting NULLs after each token.
- *
- * @param [in] str A c-string (will be modified)
- *
- * @retval non-null A PARCList where each item is a single word
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-static PARCList *_parseArgs(char *str) {
- PARCList *list =
- parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
-
- const char delimiters[] = " \t";
-
- char *token;
- token = strtok(str, delimiters);
- while (token != NULL) {
- if (strlen(token) > 0) {
- parcList_Add(list, strdup(token));
- }
- token = strtok(NULL, delimiters);
- }
- // while ((token = strsep(&str, delimiters)) != NULL) {
- // parcList_Add(list, token);
- // }
-
- return list;
-}
-
-// =============================================================
-
-static void _destroy(ConfigurationFile **configFilePtr) {
- ConfigurationFile *configFile = *configFilePtr;
- parcMemory_Deallocate((void **)&configFile->filename);
-
- if (configFile->fh != NULL) {
- fclose(configFile->fh);
- }
-
- controlState_Destroy(&configFile->controlState);
-}
-
-parcObject_ExtendPARCObject(ConfigurationFile, _destroy, NULL, NULL, NULL, NULL,
- NULL, NULL);
-
-parcObject_ImplementRelease(configurationFile, ConfigurationFile);
-
-ConfigurationFile *configurationFile_Create(Forwarder *forwarder,
- const char *filename) {
- parcAssertNotNull(forwarder, "Parameter hicn-fwd must be non-null");
- parcAssertNotNull(filename, "Parameter filename must be non-null");
-
- ConfigurationFile *configFile = parcObject_CreateInstance(ConfigurationFile);
-
- if (configFile) {
- configFile->linesRead = 0;
- configFile->forwarder = forwarder;
- configFile->filename =
- parcMemory_StringDuplicate(filename, strlen(filename));
- parcAssertNotNull(configFile->filename, "Could not copy string '%s'",
- filename);
-
- // setup the control state for the command parser: last parameter NULL
- // because
- // writeRead still not implemented from configuration file.
- configFile->controlState =
- controlState_Create(configFile, _writeRead, false,
- SRV_CTRL_IP, SRV_CTRL_PORT);
-
- // we do not register Help commands
- controlState_RegisterCommand(configFile->controlState,
- controlRoot_Create(configFile->controlState));
-
- // open the file and make sure we can read it
- configFile->fh = fopen(configFile->filename, "r");
-
- if (configFile->fh) {
- if (logger_IsLoggable(forwarder_GetLogger(forwarder),
- LoggerFacility_Config, PARCLogLevel_Debug)) {
- logger_Log(forwarder_GetLogger(forwarder), LoggerFacility_Config,
- PARCLogLevel_Debug, __func__, "Open config file %s",
- configFile->filename);
- }
- } else {
- if (logger_IsLoggable(forwarder_GetLogger(forwarder),
- LoggerFacility_Config, PARCLogLevel_Error)) {
- logger_Log(forwarder_GetLogger(forwarder), LoggerFacility_Config,
- PARCLogLevel_Error, __func__,
- "Could not open config file %s: (%d) %s",
- configFile->filename, errno, strerror(errno));
- }
-
- // failure cleanup the object -- this nulls it so final return null be
- // NULL
- configurationFile_Release(&configFile);
- }
- }
- return configFile;
-}
-
-bool configurationFile_Process(ConfigurationFile *configFile) {
- parcAssertNotNull(configFile, "Parameter configFile must be non-null");
-
- // default to a "true" return value and only set to false if we encounter an
- // error.
- bool success = true;
-
-#define BUFFERLEN 2048
- char buffer[BUFFERLEN];
-
- configFile->linesRead = 0;
-
- // always clear errors and fseek to start of file in case we get called
- // multiple times.
- clearerr(configFile->fh);
- rewind(configFile->fh);
-
- while (success && fgets(buffer, BUFFERLEN, configFile->fh) != NULL) {
- configFile->linesRead++;
-
- char *stripedBuffer = _trim(buffer);
- if (strlen(stripedBuffer) > 0) {
- if (stripedBuffer[0] != '#') {
- // not empty and not a comment
-
- // _parseArgs will modify the string
- char *copy =
- parcMemory_StringDuplicate(stripedBuffer, strlen(stripedBuffer));
- PARCList *args = _parseArgs(copy);
- 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;
- }
- for(int i = 0; i < parcList_Size(args); i++){
- free(parcList_GetAtIndex(args, i));
- }
- parcList_Release(&args);
- parcMemory_Deallocate((void **)&copy);
- }
- }
- }
-
- if (ferror(configFile->fh)) {
- if (logger_IsLoggable(forwarder_GetLogger(configFile->forwarder),
- LoggerFacility_Config, PARCLogLevel_Error)) {
- logger_Log(forwarder_GetLogger(configFile->forwarder),
- LoggerFacility_Config, PARCLogLevel_Error, __func__,
- "Error on input file %s line %d: (%d) %s",
- configFile->filename, configFile->linesRead, errno,
- strerror(errno));
- }
- success = false;
- }
-
- return success;
-}
diff --git a/hicn-light/src/hicn/config/configurationListeners.c b/hicn-light/src/hicn/config/configurationListeners.c
deleted file mode 100644
index 21bfe76..0000000
--- a/hicn-light/src/hicn/config/configurationListeners.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <unistd.h>
-#endif
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Network.h>
-
-#include <hicn/core/system.h>
-#include <hicn/utils/interfaceSet.h>
-#include <hicn/utils/punting.h>
-
-#include <hicn/config/configurationListeners.h>
-#include <hicn/io/hicnListener.h>
-#include <hicn/io/tcpListener.h>
-#include <hicn/io/udpListener.h>
-
-#include <hicn/utils/address.h>
-#include <hicn/utils/addressList.h>
-#include <hicn/utils/commands.h>
-#include <hicn/utils/utils.h>
-
-static bool _setupHicnListenerOnInet4(Forwarder *forwarder,
- const char *symbolic, Address *address) {
- bool success = false;
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- ListenerOps *ops =
- hicnListener_CreateInet(forwarder, (char *)symbolic, address);
- if (ops != NULL) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
- parcAssertTrue(success, "Failed to add Hicn listener %s to ListenerSet",
- symbolic);
- }
-#endif /* __APPLE__ _WIN32*/
- return success;
-}
-
-static bool _setupHicnListenerOnInet6(Forwarder *forwarder,
- const char *symbolic, Address *address) {
- bool success = false;
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- ListenerOps *ops =
- hicnListener_CreateInet6(forwarder, (char *)symbolic, address);
- if (ops != NULL) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
- parcAssertTrue(success, "Failed to add Hicn listener %s to ListenerSet",
- symbolic);
- }
-#endif /* __APPLE__ _WIN32 */
- return success;
-}
-
-bool configurationListeners_Remove(const Configuration *config) {
- Logger *logger = configuration_GetLogger(config);
- if (logger_IsLoggable(logger, LoggerFacility_Config, PARCLogLevel_Warning)) {
- logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__,
- "Removing a listener not supported: ingress %u control %s");
- }
-
- return false;
-}
-
-bool _AddPuntingInet(const Configuration *config, Punting *punting,
- unsigned ingressId) {
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- struct sockaddr *addr = parcNetwork_SockAddress("0.0.0.0", 1234);
- if (addr == NULL) {
- printf("Error creating address\n");
- return false;
- }
-
- Address *fakeAddr = addressCreateFromInet((struct sockaddr_in *)addr);
-
- ListenerOps *listenerOps = listenerSet_Find(
- forwarder_GetListenerSet(configuration_GetForwarder(config)), ENCAP_HICN,
- fakeAddr);
- addressDestroy(&fakeAddr);
-
- if (listenerOps == NULL) {
- printf("the main listener (IPV4) does not exists\n");
- return false;
- }
-
- struct sockaddr_in puntingAddr;
-
- Address *address = puntingGetAddress(punting);
- if (address == NULL) return false;
-
- bool res = addressGetInet(address, &puntingAddr);
- if (!res) {
- printf("unable to read the punting address\n");
- return false;
- }
-
- char prefix[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &(puntingAddr.sin_addr), prefix, INET_ADDRSTRLEN);
-
- char len[5];
- sprintf(len, "%d", puntingPrefixLen(punting));
-
- char *prefixStr =
- malloc(strlen(prefix) + strlen(len) + 2); //+1 for the zero-terminator
- if (prefixStr == NULL) {
- printf("error while create the prefix string\n");
- return false;
- }
- strcpy(prefixStr, prefix);
- strcat(prefixStr, "/");
- strcat(prefixStr, len);
-
- res = hicnListener_Punting(listenerOps, prefixStr);
- if (!res) {
- printf("error while adding the punting rule\n");
- return false;
- }
-
- return true;
-#else
- return false;
-#endif
-}
-
-bool _AddPuntingInet6(const Configuration *config, Punting *punting,
- unsigned ingressId) {
-#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING)
- struct sockaddr *addr = parcNetwork_SockAddress("0::0", 1234);
- if (addr == NULL) {
- printf("Error creating address\n");
- return false;
- }
-
- Address *fakeAddr = addressCreateFromInet6((struct sockaddr_in6 *)addr);
-
- // comments:
- // EncapType: I use the Hicn encap since the punting is available only for
- // Hicn listeners LocalAddress: The only listern for which we need punting
- // rules is the main one, which has no address
- // so I create a fake empty address. This need to be consistent
- // with the address set at creation time
-
- ListenerOps *listenerOps = listenerSet_Find(
- forwarder_GetListenerSet(configuration_GetForwarder(config)), ENCAP_HICN,
- fakeAddr);
- addressDestroy(&fakeAddr);
-
- if (listenerOps == NULL) {
- printf("the main listener does not exists\n");
- return false;
- }
-
- struct sockaddr_in6 puntingAddr;
- bool res = addressGetInet6(puntingGetAddress(punting), &puntingAddr);
- if (!res) {
- printf("unable to read the punting address\n");
- return false;
- }
-
- char prefix[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &(puntingAddr.sin6_addr), prefix, INET6_ADDRSTRLEN);
-
- char len[5];
- sprintf(len, "%d", puntingPrefixLen(punting));
-
- char *prefixStr =
- malloc(strlen(prefix) + strlen(len) + 2); //+1 for the zero-terminator
- if (prefixStr == NULL) {
- printf("error while create the prefix string\n");
- return false;
- }
- strcpy(prefixStr, prefix);
- strcat(prefixStr, "/");
- strcat(prefixStr, len);
-
- res = hicnListener_Punting(listenerOps, prefixStr);
- if (!res) {
- printf("error while adding the punting rule\n");
- return false;
- }
-
- return true;
-#else
- return false;
-#endif
-}
-
-//============= LIGHT COMMAN ===============
-
-static bool _addEther(Configuration *config, add_listener_command *control,
- unsigned ingressId) {
- // Not implemented
- return false;
-}
-
-/*
- * Create a new IPV4/TCP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] listenerName The name of the listener
- * @param [in] addr4 The ipv4 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupTcpListenerOnInet(Forwarder *forwarder, char *listenerName, ipv4_addr_t *addr4,
- uint16_t *port, char *interfaceName) {
- parcAssertNotNull(listenerName, "Parameter listenerName must be non-null");
-
- bool success = false;
-
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = *port;
- addr.sin_addr.s_addr = *addr4;
-
- ListenerOps *ops = tcpListener_CreateInet(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add TCP listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-
-/*
- * Create a new IPV4/UDP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] listenerName The name of the listener
- * @param [in] addr4 The ipv4 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupUdpListenerOnInet(Forwarder *forwarder, char *listenerName, ipv4_addr_t *addr4,
- uint16_t *port, char *interfaceName) {
- bool success = false;
-
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = *port;
- addr.sin_addr.s_addr = *addr4;
-
- ListenerOps *ops = udpListener_CreateInet(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add UDP listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-
-/*
- * Create a new IPV6/TCP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] addr6 The ipv6 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, char *listenerName,
- ipv6_addr_t *addr6, uint16_t *port, char *interfaceName,
- uint32_t scopeId) {
- bool success = false;
-
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
- addr.sin6_port = *port;
- addr.sin6_addr = *addr6;
- addr.sin6_scope_id = scopeId;
-
- ListenerOps *ops = tcpListener_CreateInet6(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add TCP6 listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-
-/*
- * Create a new IPV6/UDP listener.
- *
- * @param [in,out] forwarder The hicn-light forwarder instance
- * @param [in] listenerName The name of the listener
- * @param [in] addr6 The ipv6 address in network byte order
- * @param [in] port The port number in network byte order
- * @param [in] interfaceName The name of the interface to bind the socket
- *
- * return true if success, false otherwise
- */
-static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder, char *listenerName,
- ipv6_addr_t *addr6, uint16_t *port, char *interfaceName) {
- bool success = false;
-
- struct sockaddr_in6 addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
- addr.sin6_port = *port;
- addr.sin6_addr = *addr6;
- addr.sin6_scope_id = 0;
-
- ListenerOps *ops = udpListener_CreateInet6(forwarder, listenerName, addr, interfaceName);
- if (ops) {
- success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops);
-#if 0
- parcAssertTrue(success, "Failed to add UDP6 listener on %s to ListenerSet",
- addressToString(ops->getListenAddress(ops)));
-#endif
- }
- return success;
-}
-
-/*
- * Create a new HICN listener.
- *
- * @param [in] config The configuration
- * @param [in] control The control command
- * @param [in] port The connection id of the command
- *
- * return true if success, false otherwise
- */
-bool _addHicn(Configuration *config, add_listener_command *control,
- unsigned ingressId) {
- bool success = false;
- const char *symbolic = control->symbolic;
- Address *localAddress = NULL;
-
- switch (control->addressType) {
- case ADDR_INET: {
- localAddress =
- addressFromInaddr4Port(&control->address.v4.as_u32, &control->port);
- success = _setupHicnListenerOnInet4(configuration_GetForwarder(config),
- symbolic, localAddress);
- break;
- }
-
- case ADDR_INET6: {
- localAddress =
- addressFromInaddr6Port(&control->address.v6.as_in6addr, &control->port);
- success = _setupHicnListenerOnInet6(configuration_GetForwarder(config),
- symbolic, localAddress);
- break;
- }
-
- default:
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Warning)) {
- logger_Log(configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Warning, __func__,
- "Unsupported address type for HICN (ingress id %u): "
- "must be either IPV4 or IPV6",
- ingressId);
- }
- break;
- }
-
- if (success == true && localAddress != NULL) {
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Info)) {
- 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;
- char *symbolic = control->symbolic;
-
- switch (control->addressType) {
- case ADDR_INET: {
-
- if (control->connectionType == UDP_CONN) {
- success =
- _setupUdpListenerOnInet(configuration_GetForwarder(config), symbolic,
- &control->address.v4.as_u32, &control->port, control->interfaceName);
- } else if (control->connectionType == TCP_CONN) {
- success =
- _setupTcpListenerOnInet(configuration_GetForwarder(config), symbolic,
- &control->address.v4.as_u32, &control->port, control->interfaceName);
- }
- break;
- }
-
- case ADDR_INET6: {
- if (control->connectionType == UDP_CONN) {
- success = _setupUdpListenerOnInet6Light(
- configuration_GetForwarder(config), symbolic, &control->address.v6.as_in6addr,
- &control->port, control->interfaceName);
- } else if (control->connectionType == TCP_CONN) {
- success = _setupTcpListenerOnInet6Light(
- configuration_GetForwarder(config), symbolic, &control->address.v6.as_in6addr,
- &control->port, control->interfaceName, 0);
- }
- break;
- }
-
- default:
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Warning)) {
- char *addrStr = utils_CommandAddressToString(
- control->addressType, &control->address, &control->port);
- logger_Log(
- configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Warning, __func__,
- "Unsupported address type for IP encapsulation ingress id %u: %s",
- ingressId, addrStr);
- parcMemory_Deallocate((void **)&addrStr);
- }
- break;
- }
-
- if (success) {
- if (logger_IsLoggable(configuration_GetLogger(config),
- LoggerFacility_Config, PARCLogLevel_Info)) {
- char *addrStr = utils_CommandAddressToString(
- control->addressType, &control->address, &control->port);
- logger_Log(configuration_GetLogger(config), LoggerFacility_Config,
- PARCLogLevel_Info, __func__, "Setup listener on address %s",
- addrStr);
- parcMemory_Deallocate((void **)&addrStr);
- }
- }
-
- return success;
-}
-
-struct iovec *configurationListeners_Add(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- add_listener_command *control = request[1].iov_base;
-
- bool success = false;
-
- ListenerSet *listenerSet = forwarder_GetListenerSet(configuration_GetForwarder(config));
- int listenerId = listenerSet_FindIdByListenerName(listenerSet, control->symbolic);
-
- if (listenerId < 0) {
- if (control->listenerMode == ETHER_MODE) {
- parcTrapNotImplemented("Add Ethernet Listener is not supported");
- success = _addEther(config, control, ingressId);
- // it is a failure
- } else if (control->listenerMode == IP_MODE) {
- success = _addIP(config, control, ingressId);
- } else if (control->listenerMode == HICN_MODE) {
- success = _addHicn(config, control, ingressId);
- } else {
- Logger *logger = configuration_GetLogger(config);
- if (logger_IsLoggable(logger, LoggerFacility_Config,
- PARCLogLevel_Warning)) {
- logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__,
- "Unsupported encapsulation mode (ingress id %u)", ingressId);
- }
- }
- }
-
- // generate ACK/NACK
- struct iovec *response;
-
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(add_listener_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(add_listener_command));
- }
-
- return response;
-}
-
-struct iovec *configurationListeners_AddPunting(Configuration *config,
- struct iovec *request,
- unsigned ingressId) {
- header_control_message *header = request[0].iov_base;
- add_punting_command *control = request[1].iov_base;
-
- const char *symbolicOrConnid = control->symbolicOrConnid;
- uint32_t len = control->len;
- in_port_t port = htons(1234);
- bool success = false;
-
- if (control->addressType == ADDR_INET) {
- Address *address = addressFromInaddr4Port(&control->address.v4.as_u32, &port);
- Punting *punting = puntingCreate(symbolicOrConnid, address, len);
- success = _AddPuntingInet(config, punting, ingressId);
- addressDestroy(&address);
- } else if (control->addressType == ADDR_INET6) {
- Address *address = addressFromInaddr6Port(&control->address.v6.as_in6addr, &port);
- Punting *punting = puntingCreate(symbolicOrConnid, address, len);
- success = _AddPuntingInet6(config, punting, ingressId);
- addressDestroy(&address);
- } else {
- printf("Invalid IP type.\n"); // will generate a Nack
- return utils_CreateNack(header, control, sizeof(add_punting_command));
- }
-
- // generate ACK/NACK
- struct iovec *response;
- if (success) { // ACK
- response = utils_CreateAck(header, control, sizeof(add_punting_command));
- } else { // NACK
- response = utils_CreateNack(header, control, sizeof(add_punting_command));
- }
-
- return response;
-}
-
-//=========================== INITIAL LISTENERS ====================
-
-static void _setupListenersOnAddress(Forwarder *forwarder, char *listenerName,
- const Address *address, uint16_t port,
- char *interfaceName) {
- address_type type = addressGetType(address);
- switch (type) {
- case ADDR_INET: {
- struct sockaddr_in tmp;
- addressGetInet(address, &tmp);
- _setupTcpListenerOnInet(forwarder, listenerName, &tmp.sin_addr.s_addr, &port, interfaceName);
- break;
- }
-
- case ADDR_INET6: {
- struct sockaddr_in6 tmp;
- addressGetInet6(address, &tmp);
- _setupTcpListenerOnInet6Light(forwarder, listenerName, &tmp.sin6_addr, &port, interfaceName,
- tmp.sin6_scope_id);
- break;
- }
-
- case ADDR_LINK:
- // not used
- break;
-
- default:
- // dont' know how to handle this, so no listeners
- break;
- }
-}
-
-void configurationListeners_SetupAll(const Configuration *config, uint16_t port,
- const char *localPath) {
- Forwarder *forwarder = configuration_GetForwarder(config);
- InterfaceSet *set = system_Interfaces(forwarder);
-
- size_t interfaceSetLen = interfaceSetLength(set);
- for (size_t i = 0; i < interfaceSetLen; i++) {
- Interface *iface = interfaceSetGetByOrdinalIndex(set, i);
-
- const AddressList *addresses = interfaceGetAddresses(iface);
- size_t addressListLen = addressListLength(addresses);
-
- for (size_t j = 0; j < addressListLen; j++) {
- const Address *address = addressListGetItem(addresses, j);
-
- // Do not start on link address
- char listenerName[SYMBOLIC_NAME_LEN];
-#ifdef __ANDROID__
- snprintf(listenerName, SYMBOLIC_NAME_LEN, "local_%zu", i);
-#else
- snprintf(listenerName, SYMBOLIC_NAME_LEN, "local_%ld", i);
-#endif
- if (addressGetType(address) != ADDR_LINK) {
- _setupListenersOnAddress(forwarder, listenerName, address, port,
- (char *)interfaceGetName(iface));
- }
- }
- }
-
- interfaceSetDestroy(&set);
-}
-
-void configurationListeners_SetutpLocalIPv4(const Configuration *config,
- uint16_t port) {
- Forwarder *forwarder = configuration_GetForwarder(config);
- in_addr_t addr = inet_addr("127.0.0.1");
- uint16_t network_byte_order_port = htons(port);
-
- char listenerNameUdp[SYMBOLIC_NAME_LEN] = "lo_udp";
- char listenerNameTcp[SYMBOLIC_NAME_LEN] = "lo_tcp";
- char *loopback_interface = "lo";
- _setupUdpListenerOnInet(forwarder, listenerNameUdp,(ipv4_addr_t *)&(addr),
- &network_byte_order_port, loopback_interface);
- _setupTcpListenerOnInet(forwarder, listenerNameTcp, (ipv4_addr_t *)&(addr),
- &network_byte_order_port, loopback_interface);
-}
diff --git a/hicn-light/src/hicn/config/configurationListeners.h b/hicn-light/src/hicn/config/configurationListeners.h
deleted file mode 100644
index b09ad51..0000000
--- a/hicn-light/src/hicn/config/configurationListeners.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file configurationListeners.h
- * @brief Configuration routines related to Listeners
- *
- * Adding and removing listeners.
- *
- */
-
-#ifndef configurationListeners_h
-#define configurationListeners_h
-
-#include <hicn/config/configuration.h>
-#include <hicn/core/forwarder.h>
-
-#include <hicn/utils/address.h>
-
-/**
- * Setup udp, tcp, and local listeners
- *
- * Will bind to all available IP protocols on the given port.
- * Does not add Ethernet listeners.
- *
- * @param port is the UPD and TCP port to use
- * @param localPath is the AF_UNIX path to use, if NULL no AF_UNIX listener is
- * setup
- *
- * Example:
- * @code
- * <#example#>
- * @endcode
- */
-void configurationListeners_SetupAll(const Configuration *config, uint16_t port,
- const char *localPath);
-
-void configurationListeners_SetutpLocalIPv4(const Configuration *config,
- uint16_t port);
-
-bool configurationListeners_Remove(const Configuration *config);
-
-// light functions
-
-/**
- * Add new listener.
- *
- * @param request The request coming from hicnLightControl or the
- * configuration file. The bytes in the request are
- * ordered following the network byte order convention.
- *
- * @param ingressId The connection id of the incoming request.
- */
-struct iovec *configurationListeners_Add(Configuration *config,
- struct iovec *request,
- unsigned ingressId);
-
-struct iovec *configurationListeners_AddPunting(Configuration *config,
- struct iovec *request,
- unsigned ingressId);
-
-#endif /* defined(configurationListeners_h) */
diff --git a/hicn-light/src/hicn/config/configuration_file.c b/hicn-light/src/hicn/config/configuration_file.c
new file mode 100644
index 0000000..b53bb02
--- /dev/null
+++ b/hicn-light/src/hicn/config/configuration_file.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <hicn/config/configuration.h>
+#include <hicn/config/configuration_file.h>
+//#include <hicn/config/controlRoot.h>
+//#include <hicn/config/controlState.h>
+#include <hicn/util/log.h>
+
+struct configuration_file {
+ forwarder_t *forwarder;
+ char *filename;
+ FILE *fh;
+
+ size_t linesRead;
+
+ // our custom state machine.
+ // XXX ControlState *control_state;
+};
+
+#if 0
+/*
+ * Called by a command to dispatch the correct command
+ */
+uint8_t *
+_write_read(ControlState *state, uint8_t * packet)
+{
+ assert(state);
+ assert(packet);
+
+ configuration_file_t *configFile =
+ (configuration_file_t *)controlState_GetUserdata(state);
+
+ configuration_t * config = forwarder_get_configuration(configFile->forwarder);
+ command_type_t command_type =
+ command_type_from_uchar(((cmd_header_t*)packet)->commandID);
+
+ return configuration_dispatch_command(config, command_type, packet, 0);
+}
+
+/**
+ * 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);
+ }
+ return list;
+}
+#endif
+
+// =============================================================
+
+configuration_file_t *
+configuration_file_create(forwarder_t * forwarder, const char * filename)
+{
+ assert(forwarder);
+ assert(filename);
+
+ configuration_file_t *cfg = malloc(sizeof(configuration_file_t));
+ if (!cfg)
+ return NULL;
+
+ cfg->linesRead = 0;
+ cfg->forwarder = forwarder;
+ cfg->filename = strdup(filename);
+ assert(cfg->filename);
+
+#if 0
+ // setup the control state for the command parser: last parameter NULL
+ // because
+ // write_read still not implemented from configuration file.
+ cfg->control_state = controlState_Create(cfg, _write_read, false,
+ SRV_CTRL_IP, SRV_CTRL_PORT);
+#endif
+
+ // we do not register Help commands
+ //controlState_RegisterCommand(cfg->control_state, controlRoot_Create(cfg->control_state));
+
+ // open the file and make sure we can read it
+ cfg->fh = fopen(cfg->filename, "r");
+
+ if (cfg->fh) {
+ DEBUG("Open config file %s", cfg->filename);
+ } else {
+ ERROR("Could not open config file %s: (%d) %s", cfg->filename, errno, strerror(errno));
+
+ // failure cleanup the object -- this nulls it so final return null be
+ // NULL
+ configuration_file_free(cfg);
+ }
+ return cfg;
+}
+
+bool
+configuration_file_process(configuration_file_t *configFile)
+{
+ assert(configFile);
+
+ // default to a "true" return value and only set to false if we encounter an
+ // error.
+ bool success = true;
+
+#if 0
+#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->control_state, args);
+
+ // we ignore EXIT from the configuration file
+ if (result == CommandReturn_Failure) {
+ ERROR("Error on input file %s line %d: %s",
+ configFile->filename, configFile->linesRead,
+ stripedBuffer);
+ success = false;
+ }
+ for(int i = 0; i < parcList_Size(args); i++){
+ free(parcList_GetAtIndex(args, i));
+ }
+ parcList_Release(&args);
+ parcMemory_Deallocate((void **)&copy);
+ }
+ }
+ }
+
+ if (ferror(configFile->fh)) {
+ ERROR("Error on input file %s line %d: (%d) %s",
+ configFile->filename, configFile->linesRead, errno,
+ strerror(errno));
+ success = false;
+ }
+
+#endif
+ return success;
+}
+
+void
+configuration_file_free(configuration_file_t * cfg)
+{
+ free(cfg->filename);
+ if (cfg->fh)
+ fclose(cfg->fh);
+ //controlState_Destroy(&cfg->control_state);
+ free(cfg);
+}
diff --git a/hicn-light/src/hicn/config/configurationFile.h b/hicn-light/src/hicn/config/configuration_file.h
index b748dfc..eedcbc6 100644
--- a/hicn-light/src/hicn/config/configurationFile.h
+++ b/hicn-light/src/hicn/config/configuration_file.h
@@ -14,7 +14,7 @@
*/
/**
- * @file configurationFile.h
+ * @file configuration_file.h
* @brief Accepts a filename and provides a means to read it into Configuration
*
* Reads a configuration file and converts the lines in to configuration
@@ -24,24 +24,24 @@
*
*/
-#ifndef configurationFile_h
-#define configurationFile_h
+#ifndef configuration_file_h
+#define configuration_file_h
#include <hicn/core/forwarder.h>
struct configuration_file;
-typedef struct configuration_file ConfigurationFile;
+typedef struct configuration_file configuration_file_t;
/**
- * Creates a ConfigurationFile to prepare to process the file
+ * Creates a configuration_file_t 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] hicn-light An allocated forwarder_t * to configure with the file
* @param [in] filename The file to use
*
- * @retval non-null An allocated ConfigurationFile that is readable
+ * @retval non-null An allocated configuration_file_t that is readable
* @retval null An error
*
* Example:
@@ -49,8 +49,8 @@ typedef struct configuration_file ConfigurationFile;
* <#example#>
* @endcode
*/
-ConfigurationFile *configurationFile_Create(Forwarder *forwarder,
- const char *filename);
+configuration_file_t * configuration_file_create(forwarder_t * forwarder, const
+ char * filename);
/**
* Reads the configuration file line-by-line and issues commands to
@@ -60,7 +60,7 @@ ConfigurationFile *configurationFile_Create(Forwarder *forwarder,
*
* Will stop on the first error. Lines already processed will not be un-done.
*
- * @param [in] configFile An allocated ConfigurationFile
+ * @param [in] configFile An allocated configuration_file_t
*
* @retval true The entire files was processed without error.
* @retval false There was an error in the file.
@@ -70,17 +70,17 @@ ConfigurationFile *configurationFile_Create(Forwarder *forwarder,
* <#example#>
* @endcode
*/
-bool configurationFile_Process(ConfigurationFile *configFile);
+bool configuration_file_process(configuration_file_t *configFile);
-// void configurationFile_ProcessForwardingStrategies(Configuration * config,
-// ConfigurationFile * configFile);
+// void configuration_file_ProcessForwardingStrategies(Configuration * config,
+// configuration_file_t * configFile);
/**
* Closes the underlying file and releases memory
*
* <#Paragraphs Of Explanation#>
*
- * @param [in,out] configFilePtr An allocated ConfigurationFile that will be
+ * @param [in,out] configFilePtr An allocated configuration_file_t that will be
* NULL'd as output
*
* Example:
@@ -88,6 +88,6 @@ bool configurationFile_Process(ConfigurationFile *configFile);
* <#example#>
* @endcode
*/
-void configurationFile_Release(ConfigurationFile **configFilePtr);
+void configuration_file_free(configuration_file_t * configFile);
-#endif /* defined(configurationFile_h) */
+#endif /* defined(configuration_file_h) */
diff --git a/hicn-light/src/hicn/config/controlAddConnection.c b/hicn-light/src/hicn/config/controlAddConnection.c
index e5af5a2..6160ff1 100644
--- a/hicn-light/src/hicn/config/controlAddConnection.c
+++ b/hicn-light/src/hicn/config/controlAddConnection.c
@@ -29,6 +29,7 @@
#include <hicn/utils/commands.h>
#include <hicn/utils/utils.h>
+#include <hicn/face.h>
// ===================================================
@@ -189,7 +190,7 @@ static CommandReturn _controlAddConnection_Execute(CommandParser *parser,
* @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] type The tunneling protocol
* @param [in] symbolic The symbolic name for the connection (must be unique)
*
* @return <#value#> <#explanation#>
@@ -218,44 +219,44 @@ static CommandReturn _controlAddConnection_Execute(CommandParser *parser,
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) {
+ face_type_t type, 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));
+ cmd_connection_add_t *cmd =
+ parcMemory_AllocateAndClear(sizeof(cmd_connection_add_t));
// check and set IP addresses
- if (inet_pton(AF_INET, remote_ip, &addConnectionCommand->remoteIp.v4.as_u32) ==
+ if (inet_pton(AF_INET, remote_ip, &cmd->remote_ip.v4.as_u32) ==
1 &&
- inet_pton(AF_INET, local_ip, &addConnectionCommand->localIp.v4.as_u32) == 1) {
- addConnectionCommand->ipType = ADDR_INET;
+ inet_pton(AF_INET, local_ip, &cmd->local_ip.v4.as_u32) == 1) {
+ cmd->family = AF_INET;
} else if (inet_pton(AF_INET6, remote_ip,
- &addConnectionCommand->remoteIp.v6.as_in6addr) == 1 &&
+ &cmd->remote_ip.v6.as_in6addr) == 1 &&
inet_pton(AF_INET6, local_ip,
- &addConnectionCommand->localIp.v6.as_in6addr) == 1) {
- addConnectionCommand->ipType = ADDR_INET6;
+ &cmd->local_ip.v6.as_in6addr) == 1) {
+ cmd->family = AF_INET6;
} else {
printf("Error: local address %s not same type as remote address %s\n",
local_ip, remote_ip);
- parcMemory_Deallocate(&addConnectionCommand);
+ parcMemory_Deallocate(&cmd);
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));
+ cmd->type = type;
+ strcpy(cmd->symbolic, symbolic);
+ cmd->remote_port = htons((uint16_t)atoi(remote_port));
+ cmd->local_port = htons((uint16_t)atoi(local_port));
// send message and receive response
struct iovec *response =
- utils_SendRequest(state, ADD_CONNECTION, addConnectionCommand,
- sizeof(add_connection_command));
+ utils_SendRequest(state, COMMAND_TYPE_CONNECTION_ADD, cmd,
+ sizeof(cmd_connection_add_t));
if (!response) { // get NULL pointer
return CommandReturn_Failure;
@@ -318,7 +319,7 @@ static CommandReturn _controlAddConnection_HicnExecute(CommandParser *parser,
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);
+ parser, ops, local_ip, port, remote_ip, port, FACE_TYPE_HICN, symbolic);
}
#endif
@@ -360,7 +361,7 @@ static CommandReturn _controlAddConnection_UdpExecute(CommandParser *parser,
char *local_port = parcList_GetAtIndex(args, _indexLocPort);
return _controlAddConnection_CreateTunnel(parser, ops, local_ip, local_port,
- remote_ip, remote_port, UDP_CONN,
+ remote_ip, remote_port, FACE_TYPE_UDP,
symbolic);
}
@@ -402,6 +403,6 @@ static CommandReturn _controlAddConnection_TcpExecute(CommandParser *parser,
char *local_port = parcList_GetAtIndex(args, _indexLocPort);
return _controlAddConnection_CreateTunnel(parser, ops, local_ip, local_port,
- remote_ip, remote_port, TCP_CONN,
+ remote_ip, remote_port, FACE_TYPE_TCP,
symbolic);
}
diff --git a/hicn-light/src/hicn/config/controlAddListener.c b/hicn-light/src/hicn/config/controlAddListener.c
index 2f0fd3f..18766fd 100644
--- a/hicn-light/src/hicn/config/controlAddListener.c
+++ b/hicn-light/src/hicn/config/controlAddListener.c
@@ -107,10 +107,10 @@ static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops,
// check and set IP address
if (inet_pton(AF_INET, addr, &addListenerCommand->address.v4.as_u32) == 1) {
- addListenerCommand->addressType = ADDR_INET;
+ addListenerCommand->family = AF_INET;
} else if (inet_pton(AF_INET6, addr, &addListenerCommand->address.v6.as_in6addr) == 1) {
- addListenerCommand->addressType = ADDR_INET6;
+ addListenerCommand->family = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
diff --git a/hicn-light/src/hicn/config/controlAddPolicy.c b/hicn-light/src/hicn/config/controlAddPolicy.c
index 2912044..24b9d5e 100644
--- a/hicn-light/src/hicn/config/controlAddPolicy.c
+++ b/hicn-light/src/hicn/config/controlAddPolicy.c
@@ -111,7 +111,7 @@ static CommandReturn _controlAddPolicy_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- addPolicyCommand->addressType = ADDR_INET;
+ addPolicyCommand->family = AF_INET;
} else if (inet_pton(AF_INET6, addr, &addPolicyCommand->address.v6.as_in6addr) == 1) {
if (len > 128) {
printf("ERROR: exceeded INET6 mask length, max=128\n");
@@ -119,7 +119,7 @@ static CommandReturn _controlAddPolicy_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- addPolicyCommand->addressType = ADDR_INET6;
+ addPolicyCommand->family = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
parcMemory_Deallocate(&addPolicyCommand);
diff --git a/hicn-light/src/hicn/config/controlAddPunting.c b/hicn-light/src/hicn/config/controlAddPunting.c
index e3fb57c..a833508 100644
--- a/hicn-light/src/hicn/config/controlAddPunting.c
+++ b/hicn-light/src/hicn/config/controlAddPunting.c
@@ -116,7 +116,7 @@ static CommandReturn _controlAddPunting_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- addPuntingCommand->addressType = ADDR_INET;
+ addPuntingCommand->family = AF_INET;
} else if (inet_pton(AF_INET6, addr, &addPuntingCommand->address.v6.as_in6addr) == 1) {
if (len > 128) {
printf("ERROR: exceeded INET6 mask length, max=128\n");
@@ -124,7 +124,7 @@ static CommandReturn _controlAddPunting_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- addPuntingCommand->addressType = ADDR_INET6;
+ addPuntingCommand->family = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
parcMemory_Deallocate(&addPuntingCommand);
diff --git a/hicn-light/src/hicn/config/controlAddRoute.c b/hicn-light/src/hicn/config/controlAddRoute.c
index 8a1adf6..f7b83e3 100644
--- a/hicn-light/src/hicn/config/controlAddRoute.c
+++ b/hicn-light/src/hicn/config/controlAddRoute.c
@@ -109,29 +109,29 @@ static CommandReturn _controlAddRoute_Execute(CommandParser *parser,
}
// allocate command payload
- add_route_command *addRouteCommand =
- parcMemory_AllocateAndClear(sizeof(add_route_command));
+ cmd_route_add_t *cmd =
+ parcMemory_AllocateAndClear(sizeof(cmd_route_add_t));
// check and set IP address
- if (inet_pton(AF_INET, addr, &addRouteCommand->address.v4.as_u32) == 1) {
+ if (inet_pton(AF_INET, addr, &cmd->address.v4.as_u32) == 1) {
if (len > 32) {
printf("ERROR: exceeded INET mask length, max=32\n");
- parcMemory_Deallocate(&addRouteCommand);
+ parcMemory_Deallocate(&cmd);
free(addr);
return CommandReturn_Failure;
}
- addRouteCommand->addressType = ADDR_INET;
- } else if (inet_pton(AF_INET6, addr, &addRouteCommand->address.v6.as_in6addr) == 1) {
+ cmd->family = AF_INET;
+ } else if (inet_pton(AF_INET6, addr, &cmd->address.v6.as_in6addr) == 1) {
if (len > 128) {
printf("ERROR: exceeded INET6 mask length, max=128\n");
- parcMemory_Deallocate(&addRouteCommand);
+ parcMemory_Deallocate(&cmd);
free(addr);
return CommandReturn_Failure;
}
- addRouteCommand->addressType = ADDR_INET6;
+ cmd->family = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
- parcMemory_Deallocate(&addRouteCommand);
+ parcMemory_Deallocate(&cmd);
free(addr);
return CommandReturn_Failure;
}
@@ -139,13 +139,13 @@ static CommandReturn _controlAddRoute_Execute(CommandParser *parser,
free(addr);
// Fill remaining payload fields
- addRouteCommand->len = len;
- addRouteCommand->cost = (uint16_t)cost;
- strcpy(addRouteCommand->symbolicOrConnid, symbolicOrConnid);
+ cmd->len = len;
+ cmd->cost = (uint16_t)cost;
+ strcpy(cmd->symbolicOrConnid, symbolicOrConnid);
// send message and receive response
- struct iovec *response = utils_SendRequest(state, ADD_ROUTE, addRouteCommand,
- sizeof(add_route_command));
+ struct iovec *response = utils_SendRequest(state, COMMAND_TYPE_ROUTE_ADD, cmd,
+ sizeof(cmd_route_add_t));
if (!response) { // get NULL pointer
return CommandReturn_Failure;
diff --git a/hicn-light/src/hicn/config/controlListConnections.c b/hicn-light/src/hicn/config/controlListConnections.c
index cbed8a7..c474317 100644
--- a/hicn-light/src/hicn/config/controlListConnections.c
+++ b/hicn-light/src/hicn/config/controlListConnections.c
@@ -38,8 +38,10 @@ static CommandReturn _controlListConnections_HelpExecute(CommandParser *parser,
static const char *_commandListConnections = "list connections";
static const char *_commandListConnectionsHelp = "help list connections";
+
+// XXX TODO in connection{_state}.h
const char *connTypeString[6] = {"GRE", "TCP", "UDP", "MCAST", "L2", "HICN"};
-const char *stateString[3] = {"UP", "DOWN", "UNKNOWN"};
+const char *stateString[3] = {"UNKNOWN", "DOWN", "UP"};
CommandOps *controlListConnections_Create(ControlState *state) {
return commandOps_Create(state, _commandListConnections, NULL,
@@ -127,12 +129,12 @@ static CommandReturn _controlListConnections_Execute(CommandParser *parser,
(i * sizeof(list_connections_command)));
sourceString = utils_CommandAddressToString(
- listConnectionsCommand->connectionData.ipType,
+ listConnectionsCommand->connectionData.family,
&listConnectionsCommand->connectionData.localIp,
&listConnectionsCommand->connectionData.localPort);
destinationString = utils_CommandAddressToString(
- listConnectionsCommand->connectionData.ipType,
+ listConnectionsCommand->connectionData.family,
&listConnectionsCommand->connectionData.remoteIp,
&listConnectionsCommand->connectionData.remotePort);
diff --git a/hicn-light/src/hicn/config/controlListListeners.c b/hicn-light/src/hicn/config/controlListListeners.c
index 1489470..f0ab820 100644
--- a/hicn-light/src/hicn/config/controlListListeners.c
+++ b/hicn-light/src/hicn/config/controlListListeners.c
@@ -106,7 +106,7 @@ static CommandReturn _controlListListeners_Execute(CommandParser *parser,
(list_listeners_command *)(receivedPayload +
(i * sizeof(list_listeners_command)));
- addrString = utils_CommandAddressToString(listListenersCommand->addressType,
+ addrString = utils_CommandAddressToString(listListenersCommand->family,
&listListenersCommand->address,
&listListenersCommand->port);
diff --git a/hicn-light/src/hicn/config/controlListPolicies.c b/hicn-light/src/hicn/config/controlListPolicies.c
index 81be6dd..9ea3bae 100644
--- a/hicn-light/src/hicn/config/controlListPolicies.c
+++ b/hicn-light/src/hicn/config/controlListPolicies.c
@@ -148,7 +148,7 @@ static CommandReturn _controlListPolicies_Execute(CommandParser *parser,
#undef _
addrString = utils_CommandAddressToString(
- listPoliciesCommand->addressType, &listPoliciesCommand->address, &port);
+ listPoliciesCommand->family, &listPoliciesCommand->address, &port);
#if 0
PARCBufferComposer *composer = parcBufferComposer_Create();
@@ -191,6 +191,7 @@ static CommandReturn _controlListPolicies_Execute(CommandParser *parser,
#endif
}
+#if 0
printf("\nSTATISTICS\n\n");
// STATISTICS
printf("%*s %*s %*s | %*s | %*s | %*s\n",
@@ -207,22 +208,23 @@ static CommandReturn _controlListPolicies_Execute(CommandParser *parser,
(list_policies_command *)(receivedPayload +
(i * sizeof(list_policies_command)));
addrString = utils_CommandAddressToString(
- listPoliciesCommand->addressType, &listPoliciesCommand->address, &port);
+ listPoliciesCommand->family, &listPoliciesCommand->address, &port);
printf("%*s %*s %*.2f %*.2f %*.2f | %*.2f %*.2f %*.2f | %*.2f %*.2f %*.2f | %*.2f %*.2f %*.2f\n",
MAXSZ_PREFIX, addrString, MAXSZ_APP_NAME, listPoliciesCommand->policy.app_name,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wired.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wired.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wired.loss_rate,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wifi.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wifi.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.wifi.loss_rate,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.cellular.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.cellular.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.cellular.loss_rate,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.all.throughput,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.all.latency,
- MAXSZ_STR_STAT, listPoliciesCommand->policy.stats.all.loss_rate);
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.wired.throughput,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.wired.latency,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.wired.loss_rate,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.wifi.throughput,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.wifi.latency,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.wifi.loss_rate,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.cellular.throughput,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.cellular.latency,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.cellular.loss_rate,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.all.throughput,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.all.latency,
+ MAXSZ_STR_STAT, listPoliciesCommand->prefix_stats.all.loss_rate);
}
+#endif
controlState_SetCommandOutput(state, commandOutputMain);
diff --git a/hicn-light/src/hicn/config/controlListRoutes.c b/hicn-light/src/hicn/config/controlListRoutes.c
index 3dc8fa3..33a1ac6 100644
--- a/hicn-light/src/hicn/config/controlListRoutes.c
+++ b/hicn-light/src/hicn/config/controlListRoutes.c
@@ -120,7 +120,7 @@ static CommandReturn _controlListRoutes_Execute(CommandParser *parser,
(i * sizeof(list_routes_command)));
addrString = utils_CommandAddressToString(
- listRoutesCommand->addressType, &listRoutesCommand->address, &port);
+ listRoutesCommand->family, &listRoutesCommand->address, &port);
PARCBufferComposer *composer = parcBufferComposer_Create();
diff --git a/hicn-light/src/hicn/config/controlRemoveConnection.c b/hicn-light/src/hicn/config/controlRemoveConnection.c
index 7c79f9c..cbc1fb8 100644
--- a/hicn-light/src/hicn/config/controlRemoveConnection.c
+++ b/hicn-light/src/hicn/config/controlRemoveConnection.c
@@ -25,7 +25,6 @@
#include <parc/algol/parc_Memory.h>
#include <parc/algol/parc_Network.h>
-#include <hicn/utils/address.h>
#include <hicn/config/controlRemoveConnection.h>
diff --git a/hicn-light/src/hicn/config/controlRemoveListener.c b/hicn-light/src/hicn/config/controlRemoveListener.c
index 545e189..2e38a8a 100644
--- a/hicn-light/src/hicn/config/controlRemoveListener.c
+++ b/hicn-light/src/hicn/config/controlRemoveListener.c
@@ -25,7 +25,6 @@
#include <parc/algol/parc_Memory.h>
#include <parc/algol/parc_Network.h>
-#include <hicn/utils/address.h>
#include <hicn/config/controlRemoveListener.h>
diff --git a/hicn-light/src/hicn/config/controlRemovePolicy.c b/hicn-light/src/hicn/config/controlRemovePolicy.c
index bd2e6e6..ff49cb7 100644
--- a/hicn-light/src/hicn/config/controlRemovePolicy.c
+++ b/hicn-light/src/hicn/config/controlRemovePolicy.c
@@ -27,8 +27,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <hicn/utils/address.h>
-
#include <hicn/config/controlRemovePolicy.h>
#include <hicn/utils/commands.h>
@@ -103,7 +101,7 @@ static CommandReturn _controlRemovePolicy_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- removePolicyCommand->addressType = ADDR_INET;
+ removePolicyCommand->family = AF_INET;
} else if (inet_pton(AF_INET6, addr, &removePolicyCommand->address.v6.as_in6addr) ==
1) {
if (len > 128) {
@@ -112,7 +110,7 @@ static CommandReturn _controlRemovePolicy_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- removePolicyCommand->addressType = ADDR_INET6;
+ removePolicyCommand->family = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
parcMemory_Deallocate(&removePolicyCommand);
diff --git a/hicn-light/src/hicn/config/controlRemovePunting.c b/hicn-light/src/hicn/config/controlRemovePunting.c
index bf00389..b5b7348 100644
--- a/hicn-light/src/hicn/config/controlRemovePunting.c
+++ b/hicn-light/src/hicn/config/controlRemovePunting.c
@@ -25,7 +25,6 @@
#include <parc/algol/parc_Memory.h>
#include <parc/algol/parc_Network.h>
-#include <hicn/utils/address.h>
#include <hicn/config/controlRemovePunting.h>
diff --git a/hicn-light/src/hicn/config/controlRemoveRoute.c b/hicn-light/src/hicn/config/controlRemoveRoute.c
index 0f46211..067fea2 100644
--- a/hicn-light/src/hicn/config/controlRemoveRoute.c
+++ b/hicn-light/src/hicn/config/controlRemoveRoute.c
@@ -25,8 +25,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <hicn/utils/address.h>
-
#include <hicn/config/controlRemoveRoute.h>
#include <hicn/utils/commands.h>
@@ -111,7 +109,7 @@ static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- removeRouteCommand->addressType = ADDR_INET;
+ removeRouteCommand->family = AF_INET;
} else if (inet_pton(AF_INET6, addr, &removeRouteCommand->address.v6.as_in6addr) ==
1) {
if (len > 128) {
@@ -120,7 +118,7 @@ static CommandReturn _controlRemoveRoute_Execute(CommandParser *parser,
free(addr);
return CommandReturn_Failure;
}
- removeRouteCommand->addressType = ADDR_INET6;
+ removeRouteCommand->family = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
parcMemory_Deallocate(&removeRouteCommand);
diff --git a/hicn-light/src/hicn/config/controlSetStrategy.c b/hicn-light/src/hicn/config/controlSetStrategy.c
index 10fec96..3cb5d9d 100644
--- a/hicn-light/src/hicn/config/controlSetStrategy.c
+++ b/hicn-light/src/hicn/config/controlSetStrategy.c
@@ -42,7 +42,8 @@ static CommandReturn _controlSetStrategy_HelpExecute(CommandParser *parser,
static const char *_commandSetStrategy = "set strategy";
static const char *_commandSetStrategyHelp = "help set strategy";
-static const char *_commandSetStrategyOptions[LAST_STRATEGY_VALUE] = {
+static const char *_commandSetStrategyOptions[STRATEGY_TYPE_N] = {
+ "(undefined)",
"loadbalancer",
"random",
"low_latency",
@@ -62,10 +63,10 @@ CommandOps *controlSetStrategy_HelpCreate(ControlState *state) {
// ====================================================
-strategy_type _validStrategy(const char *strategy) {
- strategy_type validStrategy = LAST_STRATEGY_VALUE;
+strategy_type_t _validStrategy(const char *strategy) {
+ strategy_type_t validStrategy = STRATEGY_TYPE_UNDEFINED;
- for (int i = 0; i < LAST_STRATEGY_VALUE; i++) {
+ for (int i = 0; i < STRATEGY_TYPE_N; i++) {
if (strcmp(_commandSetStrategyOptions[i], strategy) == 0) {
validStrategy = i;
break;
@@ -92,7 +93,7 @@ static bool _checkAndSetIp(set_strategy_command * setStrategyCommand,
res = inet_pton(AF_INET, addr, &setStrategyCommand->address.v4.as_u32);
else
res = inet_pton(AF_INET, addr,
- &setStrategyCommand->addresses[index].v4.as_u32);
+ &setStrategyCommand->low_latency.addresses[index].v4.as_u32);
if(res == 1) {
if (len == UINT32_MAX) {
@@ -103,9 +104,9 @@ static bool _checkAndSetIp(set_strategy_command * setStrategyCommand,
return false;
}
if(index == -1)
- setStrategyCommand->addressType = ADDR_INET;
+ setStrategyCommand->family = AF_INET;
else
- setStrategyCommand->addresses_type[index] = ADDR_INET;
+ setStrategyCommand->low_latency.families[index] = AF_INET;
} else {
@@ -114,7 +115,7 @@ static bool _checkAndSetIp(set_strategy_command * setStrategyCommand,
&setStrategyCommand->address.v6.as_in6addr);
else
res = inet_pton(AF_INET6, addr,
- &setStrategyCommand->addresses[index].v6.as_in6addr);
+ &setStrategyCommand->low_latency.addresses[index].v6.as_in6addr);
if(res == 1) {
if (len == UINT32_MAX) {
@@ -126,9 +127,9 @@ static bool _checkAndSetIp(set_strategy_command * setStrategyCommand,
}
if(index == -1)
- setStrategyCommand->addressType = ADDR_INET6;
+ setStrategyCommand->family = AF_INET6;
else
- setStrategyCommand->addresses_type[index] = ADDR_INET6;
+ setStrategyCommand->low_latency.families[index] = AF_INET6;
} else {
printf("Error: %s is not a valid network address \n", addr);
@@ -191,8 +192,8 @@ static CommandReturn _controlSetStrategy_Execute(CommandParser *parser,
const char *strategyStr = parcList_GetAtIndex(args, 3);
// check valid strategy
- strategy_type strategy;
- if ((strategy = _validStrategy(strategyStr)) == LAST_STRATEGY_VALUE) {
+ strategy_type_t strategy;
+ if ((strategy = _validStrategy(strategyStr)) == STRATEGY_TYPE_UNDEFINED) {
printf("Error: invalid strategy \n");
parcMemory_Deallocate(&setStrategyCommand);
_controlSetStrategy_HelpExecute(parser, ops, args);
@@ -204,7 +205,7 @@ static CommandReturn _controlSetStrategy_Execute(CommandParser *parser,
// Fill remaining payload fields
setStrategyCommand->len = len;
- setStrategyCommand->strategyType = strategy;
+ setStrategyCommand->strategy_type = strategy;
//check additional prefixes
if(parcList_Size(args) > 4){
@@ -223,7 +224,7 @@ static CommandReturn _controlSetStrategy_Execute(CommandParser *parser,
free(rel_addr);
return CommandReturn_Failure;
}
- setStrategyCommand->lens[addr_index] = rel_len;
+ setStrategyCommand->low_latency.lens[addr_index] = rel_len;
free(rel_addr);
index++;
addr_index++;
diff --git a/hicn-light/src/hicn/config/controlState.c b/hicn-light/src/hicn/config/controlState.c
index 2df8805..34a0b13 100644
--- a/hicn-light/src/hicn/config/controlState.c
+++ b/hicn-light/src/hicn/config/controlState.c
@@ -42,7 +42,7 @@ struct controller_state {
bool debugFlag;
void *userdata;
- struct iovec *(*writeRead)(ControlState *state, struct iovec *msg);
+ uint8_t *(*writeRead)(ControlState *state, uint8_t *msg);
int sockfd;
char **commandOutput;
bool isInteractive;
@@ -75,7 +75,7 @@ int controlState_connectToFwdDeamon(char *server_ip, uint16_t port) {
ControlState *controlState_Create(
void *userdata,
- struct iovec *(*writeRead)(ControlState *state, struct iovec *msg),
+ uint8_t *(*writeRead)(ControlState *state, uint8_t * msg),
bool openControllerConnetion,
char *server_ip, uint16_t port) {
ControlState *state = parcMemory_AllocateAndClear(sizeof(ControlState));
@@ -128,11 +128,13 @@ void controlState_RegisterCommand(ControlState *state, CommandOps *ops) {
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");
+uint8_t *
+controlState_write_read(ControlState *state, uint8_t *packet)
+{
+ assert(state);
+ assert(packet);
- return state->writeRead(state, msg);
+ return state->writeRead(state, packet);
}
static PARCList *_controlState_ParseStringIntoTokens(
diff --git a/hicn-light/src/hicn/config/controlState.h b/hicn-light/src/hicn/config/controlState.h
index cc38cbe..5c565f9 100644
--- a/hicn-light/src/hicn/config/controlState.h
+++ b/hicn-light/src/hicn/config/controlState.h
@@ -61,7 +61,7 @@ typedef struct controller_state ControlState;
ControlState *controlState_Create(
void *userdata,
- struct iovec *(*writeRead)(ControlState *state, struct iovec *msg),
+ uint8_t *(*writeRead)(ControlState *state, uint8_t * msg),
bool openControllerConnetion,
char * server_ip, uint16_t port);
diff --git a/hicn-light/src/hicn/config/symbolicNameTable.c b/hicn-light/src/hicn/config/symbolicNameTable.c
deleted file mode 100644
index e5ae81d..0000000
--- a/hicn-light/src/hicn/config/symbolicNameTable.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ctype.h>
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/config/symbolicNameTable.h>
-
-struct symblic_name_table {
- PARCHashCodeTable *symbolicNameTable;
- PARCHashCodeTable *indexToNameTable;
-};
-
-// ========================================================================================
-// symbolic name table functions
-
-static bool _symbolicNameEquals(const void *keyA, const void *keyB) {
- return (strcasecmp((const char *)keyA, (const char *)keyB) == 0);
-}
-
-static HashCodeType _symbolicNameHash(const void *keyA) {
- const char *str = (const char *)keyA;
- size_t length = strlen(str);
- return parcHash32_Data(str, length);
-}
-
-static bool _connectionIdEquals(const void *keyA, const void *keyB) {
- unsigned idA = *((unsigned *)keyA);
- unsigned idB = *((unsigned *)keyB);
- return (idA == idB);
-}
-
-static HashCodeType _connectionIdHash(const void *keyA) {
- unsigned idA = *((unsigned *)keyA);
- return parcHash32_Int32(idA);
-}
-
-// ========================================================================================
-
-SymbolicNameTable *symbolicNameTable_Create(void) {
- SymbolicNameTable *table = parcMemory_Allocate(sizeof(SymbolicNameTable));
-
- if (table) {
- // key = char *
- // value = uint32_t *
- table->symbolicNameTable = parcHashCodeTable_Create(
- _symbolicNameEquals, _symbolicNameHash, parcMemory_DeallocateImpl,
- parcMemory_DeallocateImpl);
- table->indexToNameTable = parcHashCodeTable_Create(
- _connectionIdEquals, _connectionIdHash, parcMemory_DeallocateImpl,
- parcMemory_DeallocateImpl);
- }
-
- return table;
-}
-
-void symbolicNameTable_Destroy(SymbolicNameTable **tablePtr) {
- SymbolicNameTable *table = *tablePtr;
- parcHashCodeTable_Destroy(&table->symbolicNameTable);
- parcHashCodeTable_Destroy(&table->indexToNameTable);
- parcMemory_Deallocate((void **)&table);
- *tablePtr = NULL;
-}
-
-static char *_createKey(const char *symbolicName) {
- char *key = parcMemory_StringDuplicate(symbolicName, strlen(symbolicName));
-
- // convert key to upper case
- char *p = key;
-
- // keeps looping until the first null
- while ((*p = toupper(*p))) {
- p++;
- }
- return key;
-}
-
-bool symbolicNameTable_Exists(SymbolicNameTable *table,
- const char *symbolicName) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
-
- char *key = _createKey(symbolicName);
- bool found = (parcHashCodeTable_Get(table->symbolicNameTable, key) != NULL);
- parcMemory_Deallocate((void **)&key);
- return found;
-}
-
-void symbolicNameTable_Remove(SymbolicNameTable *table,
- const char *symbolicName) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
-
- char *key = _createKey(symbolicName);
-
- unsigned id = symbolicNameTable_Get(table, symbolicName);
- uint32_t *value = parcMemory_Allocate(sizeof(uint32_t));
- *value = id;
-
- parcHashCodeTable_Del(table->symbolicNameTable, key);
- parcHashCodeTable_Del(table->indexToNameTable, value);
- parcMemory_Deallocate((void **)&key);
- parcMemory_Deallocate((void **)&value);
-}
-
-bool symbolicNameTable_Add(SymbolicNameTable *table, const char *symbolicName,
- unsigned connid) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
- parcAssertTrue(connid < UINT32_MAX, "Parameter connid must be less than %u",
- UINT32_MAX);
-
- char *key1 = _createKey(symbolicName);
-
- uint32_t *value1 = parcMemory_Allocate(sizeof(uint32_t));
- *value1 = connid;
-
- bool success = parcHashCodeTable_Add(table->symbolicNameTable, key1, value1);
- if (!success)
- goto ERR_NAME;
-
- char *key2 = _createKey(symbolicName);
-
- uint32_t *value2 = parcMemory_Allocate(sizeof(uint32_t));
- *value2 = connid;
-
- success = parcHashCodeTable_Add(table->indexToNameTable, value2, key2);
- if (!success)
- goto ERR_INDEX;
-
- goto END;
-
-ERR_INDEX:
- parcMemory_Deallocate((void **)&key2);
- parcMemory_Deallocate((void **)&value2);
- parcHashCodeTable_Del(table->symbolicNameTable, key1);
-ERR_NAME:
- parcMemory_Deallocate((void **)&key1);
- parcMemory_Deallocate((void **)&value1);
-END:
- return success;
-
-}
-
-unsigned symbolicNameTable_Get(SymbolicNameTable *table,
- const char *symbolicName) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(symbolicName, "Parameter symbolicName must be non-null");
-
- unsigned connid = UINT32_MAX;
-
- char *key = _createKey(symbolicName);
-
- uint32_t *value = parcHashCodeTable_Get(table->symbolicNameTable, key);
- if (value)
- connid = *value;
-
- parcMemory_Deallocate((void **)&key);
- return connid;
-}
-
-const char *symbolicNameTable_GetNameByIndex(SymbolicNameTable *table,
- unsigned id) {
- parcAssertNotNull(table, "Parameter table must be non-null");
-
- uint32_t *value = parcMemory_Allocate(sizeof(uint32_t));
- *value = id;
-
- const char *name = parcHashCodeTable_Get(table->indexToNameTable, value);
- if (name == NULL) name = "";
-
- parcMemory_Deallocate((void **)&value);
- return name;
-}
diff --git a/hicn-light/src/hicn/content_store/CMakeLists.txt b/hicn-light/src/hicn/content_store/CMakeLists.txt
index 85643cf..45cfe22 100644
--- a/hicn-light/src/hicn/content_store/CMakeLists.txt
+++ b/hicn-light/src/hicn/content_store/CMakeLists.txt
@@ -14,20 +14,12 @@
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
+ ${CMAKE_CURRENT_SOURCE_DIR}/lru.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreInterface.c
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreLRU.c
- ${CMAKE_CURRENT_SOURCE_DIR}/listLRU.c
- ${CMAKE_CURRENT_SOURCE_DIR}/listTimeOrdered.c
- ${CMAKE_CURRENT_SOURCE_DIR}/contentStoreEntry.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lru.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/content_store/contentStoreEntry.c b/hicn-light/src/hicn/content_store/contentStoreEntry.c
deleted file mode 100644
index 45f9888..0000000
--- a/hicn-light/src/hicn/content_store/contentStoreEntry.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <hicn/content_store/contentStoreEntry.h>
-
-#include <parc/assert/parc_Assert.h>
-
-const uint64_t contentStoreEntry_MaxExpiryTime = UINT64_MAX;
-
-struct contentstore_entry {
- Message *message;
- ListLruEntry *lruEntry;
- unsigned refcount;
- bool hasExpiryTimeTicks;
- uint64_t expiryTimeTicks;
-};
-
-ContentStoreEntry *contentStoreEntry_Create(Message *contentMessage,
- ListLru *listLRU) {
- parcAssertNotNull(contentMessage, "Parameter objectMessage must be non-null");
-
- ContentStoreEntry *entry =
- parcMemory_AllocateAndClear(sizeof(ContentStoreEntry));
- parcAssertNotNull(entry, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ContentStoreEntry));
- entry->message = message_Acquire(contentMessage);
- entry->refcount = 1;
-
- if (listLRU != NULL) {
- entry->lruEntry = listLRU_NewHeadEntry(listLRU, entry);
- }
-
- entry->hasExpiryTimeTicks = message_HasContentExpiryTime(contentMessage);
-
- if (entry->hasExpiryTimeTicks) {
- entry->expiryTimeTicks = message_GetContentExpiryTimeTicks(contentMessage);
- }
-
- return entry;
-}
-
-ContentStoreEntry *contentStoreEntry_Acquire(
- const ContentStoreEntry *original) {
- parcAssertNotNull(original, "Parameter must be non-null");
- ((ContentStoreEntry *)original)->refcount++;
- return (ContentStoreEntry *)original;
-}
-
-void contentStoreEntry_Release(ContentStoreEntry **entryPtr) {
- parcAssertNotNull(entryPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*entryPtr,
- "Parameter must dereference to non-null pointer");
-
- ContentStoreEntry *entry = *entryPtr;
- parcAssertTrue(entry->refcount > 0, "Illegal state: has refcount of 0");
-
- entry->refcount--;
- if (entry->refcount == 0) {
- if (entry->lruEntry) {
- listLRU_EntryDestroy(&entry->lruEntry);
- }
- message_Release(&entry->message);
- parcMemory_Deallocate((void **)&entry);
- }
- *entryPtr = NULL;
-}
-
-Message *contentStoreEntry_GetMessage(const ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- return storeEntry->message;
-}
-
-bool contentStoreEntry_HasExpiryTimeTicks(const ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- return storeEntry->hasExpiryTimeTicks;
-}
-
-uint64_t contentStoreEntry_GetExpiryTimeTicks(
- const ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- parcAssertTrue(storeEntry->hasExpiryTimeTicks,
- "storeEntry has no ExpiryTimeTicks. Did you call "
- "contentStoreEntry_HasExpiryTimeTicks() first?");
- return storeEntry->expiryTimeTicks;
-}
-
-int contentStoreEntry_CompareExpiryTime(const ContentStoreEntry *value1,
- const ContentStoreEntry *value2) {
- // A signum comparison. negative if key 1 is smaller, 0 if key1 == key2,
- // greater than 0 if key1 is bigger.
-
- ContentStoreEntry *v1 = (ContentStoreEntry *)value1;
- ContentStoreEntry *v2 = (ContentStoreEntry *)value2;
-
- if (v1->expiryTimeTicks < v2->expiryTimeTicks) {
- return -1;
- } else if (v1->expiryTimeTicks > v2->expiryTimeTicks) {
- return +1;
- } else {
- // At this point, the times are the same. Use the address of the message as
- // the decider. This allows us to store multiple messages with the same
- // expiry/cache time.
- if (v1->message < v2->message) {
- return -1;
- } else if (v1->message > v2->message) {
- return +1;
- }
- }
-
- return 0; // The same message has been encountered.
-}
-
-void contentStoreEntry_MoveToHead(ContentStoreEntry *storeEntry) {
- parcAssertNotNull(storeEntry, "Parameter must be non-null");
- parcAssertNotNull(storeEntry->lruEntry,
- "ContentStoreEntry is not attached to an ListLru");
- if (storeEntry->lruEntry) {
- listLRU_EntryMoveToHead(storeEntry->lruEntry);
- }
-}
diff --git a/hicn-light/src/hicn/content_store/contentStoreEntry.h b/hicn-light/src/hicn/content_store/contentStoreEntry.h
deleted file mode 100644
index 4f0fd19..0000000
--- a/hicn-light/src/hicn/content_store/contentStoreEntry.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef contentStoreEntry_h
-#define contentStoreEntry_h
-
-#include <hicn/content_store/listLRU.h>
-#include <hicn/core/message.h>
-
-struct contentstore_entry;
-typedef struct contentstore_entry ContentStoreEntry;
-
-/**
- * The max time allowed for an ExpiryTime. Will never be exceeded.
- */
-extern const uint64_t contentStoreEntry_MaxExpiryTime;
-
-/**
- * Creates a new `ContentStoreEntry` instance, acquiring a reference to the
- * supplied `Message`.
- *
- * @param message the message to store
- * @param listLRU the LRU list that this entry will be stored in.
- * @return A newly created `ContentStoreEntry` instance that must eventually be
- * released by calling
- * {@link contentStoreEntry_Release}.
- *
- * @see contentStoreEntry_Release
- */
-ContentStoreEntry *contentStoreEntry_Create(Message *objectMessage,
- ListLru *listLRU);
-
-/**
- * Returns a reference counted copy of the supplied `ContentStoreEntry`.
- *
- * @param original the ContentStoreEntry to return a reference to.
- * @return Reference counted copy, must call
- * <code>contentStoreEntry_Destroy()</code> on it.
- */
-ContentStoreEntry *contentStoreEntry_Acquire(const ContentStoreEntry *original);
-
-/**
- * Releases one reference count and destroys object when reaches zero
- *
- * @param [in,out] entryPtr A pointer to an allocated ContentStoreEntry
- *
- */
-void contentStoreEntry_Release(ContentStoreEntry **entryPtr);
-
-/**
- * Returns a pointer to the contained {@link Message}.
- * The caller must called {@link message_Acquire()} if they want to keep a
- * reference to the returned message.
- *
- * @param storeEntry the ContentStoreEntry from which to retrieve the `Message`
- * pointer.
- * @return the address of the `Message` contained in the storeEntry.
- * @see message_Acquire
- */
-Message *contentStoreEntry_GetMessage(const ContentStoreEntry *storeEntry);
-
-/**
- * Return true if the message stored in this `ContentStoreEntry` has an
- * ExpiryTime.
- *
- * @param storeEntry the ContentStoreEntry containing the message.
- * @return true if the referenced message has an ExpiryTime. False, otherwise.
- */
-bool contentStoreEntry_HasExpiryTimeTicks(const ContentStoreEntry *storeEntry);
-
-/**
- * Return the ExpiryTime stored in this `ContentStoreEntry`.
- *
- * @param storeEntry the ContentStoreEntry from which to retrieve the `Message`
- * pointer.
- * @return the address of the `Message` contained in the storeEntry.
- */
-uint64_t contentStoreEntry_GetExpiryTimeTicks(
- const ContentStoreEntry *storeEntry);
-
-/**
- * A signum function comparing two `ContentStoreEntry` instances, using their
- * ExpiryTime and, if necessary, the addresses of the referenced Message. In
- * other words, if two ContentStoreEntries have the same ExpiryTime, the
- * comparison will then be made on the memory addresses of the Messages
- * referenced by the ContentStoreEntrys. So, the only way two ContentStoreEntrys
- * will compare equally (0) is if they both have the same ExpiryTime and
- * reference the same Message.
- *
- * Used to determine the ordering relationship of two `ContentStoreEntry`
- * instances. This is used by the {@link ListTimeOrdered} to keep a list of
- * ContentStoreEntrys, sorted by ExpiryTime.
- *
- * @param [in] storeEntry1 A pointer to a `ContentStoreEntry` instance.
- * @param [in] storeEntry2 A pointer to a `ContentStoreEntry` instance to be
- * compared to `storeEntry1`.
- *
- * @return 0 if `storeEntry1` and `storeEntry2` are equivalent
- * @return < 0 if `storeEntry1` < `storeEntry2`
- * @return > 0 if `storeEntry1` > `storeEntry2`
- *
- * Example:
- * @code
- * {
- * ContentStoreEntry *entry1 = contentStoreEntry_Create(...);
- * ContentStoreEntry *entry2 = contentStoreEntry_Create(...);
- *
- * int val = contentStoreEntry_CompareExpiryTime(entry1, entry2);
- * if (val < 0) {
- * // entry1 has a lower ExpiryTime, or the same ExpiryTime as entry2
- * and a different message. } else if (val > 0) {
- * // entry2 has a lower ExpiryTime, or the same ExpiryTime as entry1
- * and a different message. } else {
- * // entry1 and entry2 have the same ExpiryTime AND the same message.
- * }
- *
- * contentStoreEntry_Release(&entry1);
- * contentStoreEntry_Release(&entry2);
- *
- * }
- * @endcode
- */
-int contentStoreEntry_CompareExpiryTime(const ContentStoreEntry *storeEntry1,
- const ContentStoreEntry *storeEntry2);
-
-/**
- * Move this entry to the head of the LRU list
- *
- * Moves the entry to the head of the LRU list it was created with
- *
- * @param [in] storeEntry An allocated ContenstoreEntry
- */
-void contentStoreEntry_MoveToHead(ContentStoreEntry *storeEntry);
-#endif // contentStoreEntry_h
diff --git a/hicn-light/src/hicn/content_store/contentStoreInterface.c b/hicn-light/src/hicn/content_store/contentStoreInterface.c
deleted file mode 100644
index 2f5ddb8..0000000
--- a/hicn-light/src/hicn/content_store/contentStoreInterface.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <hicn/content_store/contentStoreInterface.h>
-
-void contentStoreInterface_Release(ContentStoreInterface **storeImplPtr) {
- (*storeImplPtr)->release(storeImplPtr);
-}
-
-bool contentStoreInterface_PutContent(ContentStoreInterface *storeImpl,
- Message *content,
- uint64_t currentTimeTicks) {
- return storeImpl->putContent(storeImpl, content, currentTimeTicks);
-}
-
-bool contentStoreInterface_RemoveContent(ContentStoreInterface *storeImpl,
- Message *content) {
- return storeImpl->removeContent(storeImpl, content);
-}
-
-Message *contentStoreInterface_MatchInterest(ContentStoreInterface *storeImpl,
- Message *interest,
- uint64_t currentTimeTicks) {
- return storeImpl->matchInterest(storeImpl, interest, currentTimeTicks);
-}
-
-size_t contentStoreInterface_GetObjectCapacity(
- ContentStoreInterface *storeImpl) {
- return storeImpl->getObjectCapacity(storeImpl);
-}
-
-size_t contentStoreInterface_GetObjectCount(ContentStoreInterface *storeImpl) {
- return storeImpl->getObjectCount(storeImpl);
-}
-
-void contentStoreInterface_Log(ContentStoreInterface *storeImpl) {
- storeImpl->log(storeImpl);
-}
-
-void *contentStoreInterface_GetPrivateData(ContentStoreInterface *storeImpl) {
- return storeImpl->_privateData;
-}
diff --git a/hicn-light/src/hicn/content_store/contentStoreInterface.h b/hicn-light/src/hicn/content_store/contentStoreInterface.h
deleted file mode 100644
index b2bc3f9..0000000
--- a/hicn-light/src/hicn/content_store/contentStoreInterface.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef contentStoreInterface_h
-#define contentStoreInterface_h
-
-#include <stdio.h>
-
-#include <hicn/core/message.h>
-
-typedef struct contentstore_config {
- size_t objectCapacity;
-} ContentStoreConfig;
-
-typedef struct contentstore_interface ContentStoreInterface;
-
-struct contentstore_interface {
- /**
- * Place a Message representing a ContentObject into the ContentStore. If
- * necessary to make room, remove expired content or content that has exceeded
- * the Recommended Cache Time.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to place in the store.
- * @param currentTimeTicks - the current time, in hicn-light ticks, since the
- * UTC epoch.
- */
- bool (*putContent)(ContentStoreInterface *storeImpl, Message *content,
- uint64_t currentTimeTicks);
-
- /**
- * The function to call to remove content from the ContentStore.
- * It will Release any references that were created when the content was
- * placed into the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to remove from the store.
- */
- bool (*removeContent)(ContentStoreInterface *storeImpl, Message *content);
-
- /**
- * Given a Message that represents and Interest, try to find a matching
- * ContentObject.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param interest - a pointer to a `Message` representing the Interest to
- * match.
- *
- * @return a pointer to a Message containing the matching ContentObject
- * @return NULL if no matching ContentObject was found
- */
- Message *(*matchInterest)(ContentStoreInterface *storeImpl, Message *interest,
- uint64_t currentTimeTicks);
-
- /**
- * Return the maximum number of ContentObjects that can be stored in this
- * ContentStore. This is a raw count, not based on memory size.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the maximum number of ContentObjects that can be stored
- */
- size_t (*getObjectCapacity)(ContentStoreInterface *storeImpl);
-
- /**
- * Return the number of ContentObjects currently stored in the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the current number of ContentObjects in the ContentStore
- */
- size_t (*getObjectCount)(ContentStoreInterface *storeImpl);
-
- /**
- * Log a ContentStore implementation specific version of store-related
- * information.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
- void (*log)(ContentStoreInterface *storeImpl);
-
- /**
- * Acquire a new reference to the specified ContentStore instance. This
- * reference will eventually need to be released by calling {@link
- * contentStoreInterface_Release}.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
- ContentStoreInterface *(*acquire)(const ContentStoreInterface *storeImpl);
-
- /**
- * Release the ContentStore, which will also Release any references held by
- * it.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
- void (*release)(ContentStoreInterface **storeImpl);
-
- /**
- * A pointer to opaque private data used by the ContentStore instance
- * represented by this instance of ContentStoreInterface.
- */
- void *_privateData;
-};
-
-/**
- * Place a Message representing a ContentObject into the ContentStore. If
- * necessary to make room, remove expired content or content that has exceeded
- * the Recommended Cache Time.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to place in the store.
- *
- * @param currentTimeTicks - the current time, in hicn-light ticks, since the
- * UTC epoch.
- */
-bool contentStoreInterface_PutContent(ContentStoreInterface *storeImpl,
- Message *content,
- uint64_t currentTimeTicks);
-
-/**
- * The function to call to remove content from the ContentStore.
- * It will Release any references that were created when the content was placed
- * into the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param content - a pointer to a `Message` to remove from the store.
- */
-bool contentStoreInterface_RemoveContent(ContentStoreInterface *storeImpl,
- Message *content);
-
-/**
- * Given a Message that represents and Interest, try to find a matching
- * ContentObject.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- * @param interest - a pointer to a `Message` representing the Interest to
- * match.
- *
- * @return a pointer to a Message containing the matching ContentObject
- * @return NULL if no matching ContentObject was found
- */
-Message *contentStoreInterface_MatchInterest(ContentStoreInterface *storeImpl,
- Message *interest,
- uint64_t currentTimeTicks);
-
-/**
- * Return the maximum number of ContentObjects that can be stored in this
- * ContentStore. This is a raw count, not based on memory size.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the maximum number of ContentObjects that can be stored
- */
-size_t contentStoreInterface_GetObjectCapacity(
- ContentStoreInterface *storeImpl);
-
-/**
- * Return the number of ContentObjects currently stored in the ContentStore.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- *
- * @return the current number of ContentObjects in the ContentStore
- */
-size_t contentStoreInterface_GetObjectCount(ContentStoreInterface *storeImpl);
-
-/**
- * Loga ContentStore implementation specific version of store-related
- * information.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-void contentStoreInterface_Log(ContentStoreInterface *storeImpl);
-
-/**
- * Acquire a new reference to the specified ContentStore instance. This
- * reference will eventually need to be released by calling {@link
- * contentStoreInterface_Release}.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-ContentStoreInterface *contentStoreInterface_Aquire(
- const ContentStoreInterface *storeImpl);
-
-/**
- * Release the ContentStore, which will also Release any references held by it.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-void contentStoreInterface_Release(ContentStoreInterface **storeImplPtr);
-
-/**
- * Return a pointer to the data private to this implementation of the
- * ContentStore interface.
- *
- * @param storeImpl - a pointer to this ContentStoreInterface instance.
- */
-void *contentStoreInterface_GetPrivateData(ContentStoreInterface *storeImpl);
-#endif // contentStoreInterface_h
diff --git a/hicn-light/src/hicn/content_store/contentStoreLRU.c b/hicn-light/src/hicn/content_store/contentStoreLRU.c
deleted file mode 100644
index 76a2c86..0000000
--- a/hicn-light/src/hicn/content_store/contentStoreLRU.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <sys/queue.h>
-#endif
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_DisplayIndented.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Object.h>
-
-#include <hicn/core/logger.h>
-
-#include <hicn/content_store/contentStoreLRU.h>
-
-#include <hicn/content_store/contentStoreEntry.h>
-#include <hicn/content_store/contentStoreInterface.h>
-#include <hicn/content_store/listLRU.h>
-#include <hicn/content_store/listTimeOrdered.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/processor/hashTableFunction.h>
-
-typedef struct contentstore_stats {
- uint64_t countExpiryEvictions;
- uint64_t countRCTEvictions;
- uint64_t countLruEvictions;
- uint64_t countAdds;
- uint64_t countHits;
- uint64_t countMisses;
-} _ContentStoreLRUStats;
-
-typedef struct contentstore_lru_data {
- size_t objectCapacity;
- size_t objectCount;
-
- Logger *logger;
-
- // This LRU is just for keeping track of insertion and access order.
- ListLru *lru;
-
- ListTimeOrdered *indexByExpirationTime;
-
- PARCHashCodeTable *storageByName;
-
- _ContentStoreLRUStats stats;
-} _ContentStoreLRU;
-
-static void _destroyIndexes(_ContentStoreLRU *store) {
- if (store->indexByExpirationTime != NULL) {
- listTimeOrdered_Release(&(store->indexByExpirationTime));
- }
-
- if (store->storageByName != NULL) {
- parcHashCodeTable_Destroy(&(store->storageByName));
- }
-
- if (store->lru != NULL) {
- listLRU_Destroy(&(store->lru));
- }
-}
-
-static void _contentStoreInterface_Destroy(
- ContentStoreInterface **storeImplPtr) {
- _ContentStoreLRU *store = contentStoreInterface_GetPrivateData(*storeImplPtr);
-
- parcObject_Release((PARCObject **)&store);
-}
-
-static bool _contentStoreLRU_Destructor(_ContentStoreLRU **storePtr) {
- _ContentStoreLRU *store = *storePtr;
-
- _destroyIndexes(store);
- logger_Release(&store->logger);
-
- return true;
-}
-
-parcObject_Override(_ContentStoreLRU, PARCObject,
- .destructor = (PARCObjectDestructor *)
- _contentStoreLRU_Destructor);
-
-parcObject_ExtendPARCObject(ContentStoreInterface,
- _contentStoreInterface_Destroy, NULL, NULL, NULL,
- NULL, NULL, NULL);
-
-static parcObject_ImplementAcquire(_contentStoreLRU, ContentStoreInterface);
-static parcObject_ImplementRelease(_contentStoreLRU, ContentStoreInterface);
-
-static void _hashTableFunction_ContentStoreEntryDestroyer(void **dataPtr) {
- contentStoreEntry_Release((ContentStoreEntry **)dataPtr);
-}
-
-static bool _contentStoreLRU_Init(_ContentStoreLRU *store,
- ContentStoreConfig *config, Logger *logger) {
- bool result = false;
-
- store->logger = logger_Acquire(logger);
-
- size_t initialSize = config->objectCapacity * 2;
- memset(&store->stats, 0, sizeof(_ContentStoreLRUStats));
-
- store->objectCapacity = config->objectCapacity;
- store->objectCount = 0;
-
- // initial size must be at least 1 or else the data structures break.
- initialSize = (initialSize == 0) ? 1 : initialSize;
-
- store->indexByExpirationTime = listTimeOrdered_Create(
- (TimeOrderList_KeyCompare *)contentStoreEntry_CompareExpiryTime);
-
- store->storageByName = parcHashCodeTable_Create_Size(
- hashTableFunction_MessageNameEquals,
- hashTableFunction_MessageNameHashCode, NULL,
- _hashTableFunction_ContentStoreEntryDestroyer, initialSize);
-
- store->lru = listLRU_Create();
-
- // If any of the index tables couldn't be allocated, we can't continue.
- if ((store->indexByExpirationTime == NULL) ||
- (store->storageByName == NULL) || (store->lru == NULL)) {
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Error)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Error,
- __func__,
- "ContentStoreLRU could not be created. Could not allocate all "
- "index tables.",
- (void *)store, store->objectCapacity);
- }
-
- _destroyIndexes(store);
- result = false;
- } else {
- result = true;
- }
- return result;
-}
-
-/**
- * Remove a ContentStoreEntry from all tables and indices.
- */
-static void _contentStoreLRU_PurgeStoreEntry(_ContentStoreLRU *store,
- ContentStoreEntry *entryToPurge) {
- if (contentStoreEntry_HasExpiryTimeTicks(entryToPurge)) {
- listTimeOrdered_Remove(store->indexByExpirationTime, entryToPurge);
- }
-
- Message *content = contentStoreEntry_GetMessage(entryToPurge);
-
- // This _Del call will call the Release/Destroy on the ContentStoreEntry,
- // which will remove it from the LRU as well.
- parcHashCodeTable_Del(store->storageByName, content);
-
- store->objectCount--;
-}
-
-static bool _contentStoreLRU_RemoveLeastUsed(_ContentStoreLRU *store) {
- bool result = false;
-
- if (store->objectCount > 0) {
- ListLruEntry *lruEntry = listLRU_PopTail(store->lru);
- ContentStoreEntry *storeEntry =
- (ContentStoreEntry *)listLRU_EntryGetData(lruEntry);
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(
- store->logger, LoggerFacility_Processor, PARCLogLevel_Debug, __func__,
- "ContentStore %p evict message %p by LRU (LRU evictions %" PRIu64 ")",
- (void *)store, (void *)contentStoreEntry_GetMessage(storeEntry),
- store->stats.countLruEvictions);
- }
-
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
-
- result = true;
- }
- return result;
-}
-
-static void _evictByStorePolicy(_ContentStoreLRU *store,
- uint64_t currentTimeInTicks) {
- // We need to make room. Here's the plan:
- // 1) Check to see if anything has expired. If so, remove it and we're done.
- // If not, 2) Remove the least recently used item.
-
- ContentStoreEntry *entry =
- listTimeOrdered_GetOldest(store->indexByExpirationTime);
- if (entry && contentStoreEntry_HasExpiryTimeTicks(entry) &&
- (currentTimeInTicks > contentStoreEntry_GetExpiryTimeTicks(entry))) {
- // Found an expired entry. Remove it, and we're done.
-
- store->stats.countExpiryEvictions++;
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStore %p evict message %p by ExpiryTime (ExpiryTime "
- "evictions %" PRIu64 ")",
- (void *)store, (void *)contentStoreEntry_GetMessage(entry),
- store->stats.countExpiryEvictions);
- }
-
- _contentStoreLRU_PurgeStoreEntry(store, entry);
- } else {
- store->stats.countLruEvictions++;
- _contentStoreLRU_RemoveLeastUsed(store);
- }
-}
-
-static bool _contentStoreLRU_PutContent(ContentStoreInterface *storeImpl,
- Message *content,
- uint64_t currentTimeTicks)
-
-{
- bool result = false;
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- parcAssertNotNull(store, "Parameter store must be non-null");
- parcAssertNotNull(content, "Parameter objectMessage must be non-null");
-
- parcAssertTrue(message_GetType(content) == MessagePacketType_ContentObject,
- "Parameter objectMessage must be a Content Object");
-
- if (store->objectCapacity == 0) {
- return false;
- }
-
- ContentStoreEntry *storeEntry = parcHashCodeTable_Get(store->storageByName, content);
- if(storeEntry){
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
- }
-
- uint64_t expiryTimeTicks = contentStoreEntry_MaxExpiryTime;
-
- if (message_HasContentExpiryTime(content)) {
- expiryTimeTicks = message_GetContentExpiryTimeTicks(content);
- }
- // Don't add anything that's already expired or has exceeded RCT.
- if (currentTimeTicks >= expiryTimeTicks) {
- return false;
- }
-
- if (store->objectCount >= store->objectCapacity) {
- // Store is full. Need to make room.
- _evictByStorePolicy(store, currentTimeTicks);
- }
-
- // And now add a new entry to the head of the LRU.
-
- ContentStoreEntry *entry = contentStoreEntry_Create(content, store->lru);
-
- if (entry != NULL) {
- if (parcHashCodeTable_Add(store->storageByName, content, entry)) {
- if (contentStoreEntry_HasExpiryTimeTicks(entry)) {
- listTimeOrdered_Add(store->indexByExpirationTime, entry);
- }
-
- store->objectCount++;
- store->stats.countAdds++;
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStoreLRU %p saved message %p (object count %" PRIu64
- ")",
- (void *)store, (void *)content, store->objectCount);
- }
-
- result = true;
- } else {
- // Free what we just created, but did not add. 'entry' has ownership of
- // 'copy', and so will call _Release() on it
- contentStoreEntry_Release(&entry);
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Warning)) {
- logger_Log(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Warning, __func__,
- "ContentStoreLRU %p failed to add message %p to hash table",
- (void *)store, (void *)content);
- }
- }
- }
-
- return result;
-}
-
-static Message *_contentStoreLRU_MatchInterest(ContentStoreInterface *storeImpl,
- Message *interest,
- uint64_t currentTimeTicks) {
- Message *result = NULL;
-
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
-
- parcAssertNotNull(store, "Parameter store must be non-null");
- parcAssertNotNull(interest, "Parameter interestMessage must be non-null");
- parcAssertTrue(message_GetType(interest) == MessagePacketType_Interest,
- "Parameter interestMessage must be an Interest");
-
- PARCHashCodeTable *table;
- table = store->storageByName;
-
- ContentStoreEntry *storeEntry = parcHashCodeTable_Get(table, interest);
-
- bool foundEntry = false;
-
- if (storeEntry) {
- if (contentStoreEntry_HasExpiryTimeTicks(storeEntry) &&
- contentStoreEntry_GetExpiryTimeTicks(storeEntry) < currentTimeTicks) {
- // the entry is expired, we can remove it
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
- } else {
- foundEntry = true;
- }
- }
-
- if (foundEntry) {
- contentStoreEntry_MoveToHead(storeEntry);
- result = contentStoreEntry_GetMessage(storeEntry);
-
- store->stats.countHits++;
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStoreLRU %p matched interest %p (hits %" PRIu64
- ", misses %" PRIu64 ")",
- (void *)store, (void *)interest, store->stats.countHits,
- store->stats.countMisses);
- }
- } else {
- store->stats.countMisses++;
-
- if (logger_IsLoggable(store->logger, LoggerFacility_Processor,
- PARCLogLevel_Debug)) {
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_Debug,
- __func__,
- "ContentStoreLRU %p missed interest %p (hits %" PRIu64
- ", misses %" PRIu64 ")",
- (void *)store, (void *)interest, store->stats.countHits,
- store->stats.countMisses);
- }
- }
-
- return result;
-}
-
-static bool _contentStoreLRU_RemoveContent(ContentStoreInterface *storeImpl,
- Message *content) {
- bool result = false;
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
-
- ContentStoreEntry *storeEntry =
- parcHashCodeTable_Get(store->storageByName, content);
-
- if (storeEntry != NULL) {
- _contentStoreLRU_PurgeStoreEntry(store, storeEntry);
- result = true;
- }
-
- return result;
-}
-
-static void _contentStoreLRU_Log(ContentStoreInterface *storeImpl) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
-
- logger_Log(store->logger, LoggerFacility_Processor, PARCLogLevel_All,
- __func__,
- "ContentStoreLRU @%p {count = %zu, capacity = %zu {"
- "stats = @%p {adds = %" PRIu64 ", hits = %" PRIu64
- ", misses = %" PRIu64 ", LRUEvictons = %" PRIu64
- ", ExpiryEvictions = %" PRIu64 ", RCTEvictions = %" PRIu64 "} }",
- store, store->objectCount, store->objectCapacity, &store->stats,
- store->stats.countAdds, store->stats.countHits,
- store->stats.countMisses, store->stats.countLruEvictions,
- store->stats.countExpiryEvictions, store->stats.countRCTEvictions);
-}
-
-static size_t _contentStoreLRU_GetObjectCapacity(
- ContentStoreInterface *storeImpl) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- return store->objectCapacity;
-}
-
-static size_t _contentStoreLRU_GetObjectCount(
- ContentStoreInterface *storeImpl) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- return store->objectCount;
-}
-
-static size_t _contentStoreLRU_SetObjectCapacity(
- ContentStoreInterface *storeImpl, size_t newCapacity) {
- _ContentStoreLRU *store =
- (_ContentStoreLRU *)contentStoreInterface_GetPrivateData(storeImpl);
- return store->objectCapacity = newCapacity;
-}
-
-ContentStoreInterface *contentStoreLRU_Create(ContentStoreConfig *config,
- Logger *logger) {
- ContentStoreInterface *storeImpl = NULL;
-
- parcAssertNotNull(logger, "ContentStoreLRU requires a non-NULL logger");
-
- storeImpl = parcObject_CreateAndClearInstance(ContentStoreInterface);
-
- if (storeImpl != NULL) {
- storeImpl->_privateData =
- parcObject_CreateAndClearInstance(_ContentStoreLRU);
-
- if (_contentStoreLRU_Init(storeImpl->_privateData, config, logger)) {
- storeImpl->putContent = &_contentStoreLRU_PutContent;
- storeImpl->removeContent = &_contentStoreLRU_RemoveContent;
-
- storeImpl->matchInterest = &_contentStoreLRU_MatchInterest;
-
- storeImpl->getObjectCount = &_contentStoreLRU_GetObjectCount;
- storeImpl->getObjectCapacity = &_contentStoreLRU_GetObjectCapacity;
-
- storeImpl->log = &_contentStoreLRU_Log;
-
- storeImpl->acquire = &_contentStoreLRU_Acquire;
- storeImpl->release = &_contentStoreLRU_Release;
-
- // Initialize from the config passed to us.
- _contentStoreLRU_SetObjectCapacity(storeImpl, config->objectCapacity);
-
- if (logger_IsLoggable(logger, LoggerFacility_Processor,
- PARCLogLevel_Info)) {
- logger_Log(logger, LoggerFacility_Processor, PARCLogLevel_Info,
- __func__, "ContentStoreLRU %p created with capacity %zu",
- (void *)storeImpl,
- contentStoreInterface_GetObjectCapacity(storeImpl));
- }
- }
- } else {
- parcObject_Release((void **)&storeImpl);
- }
-
- return storeImpl;
-}
diff --git a/hicn-light/src/hicn/content_store/contentStoreLRU.h b/hicn-light/src/hicn/content_store/contentStoreLRU.h
deleted file mode 100644
index 94ec4d6..0000000
--- a/hicn-light/src/hicn/content_store/contentStoreLRU.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef contentStoreLRU_h
-#define contentStoreLRU_h
-
-#include <hicn/content_store/contentStoreInterface.h>
-#include <hicn/core/logger.h>
-#include <stdio.h>
-
-/**
- * Create and Initialize an instance of contentStoreLRU. A newly allocated
- * {@link ContentStoreInterface} object is initialized and returned. It must
- * eventually be released by calling {@link contentStoreInterface_Release}.
- *
- *
- * @param config An instance of `ContentStoreConfig`, specifying options to be
- * applied by the underlying contentStoreLRU instance.
- * @param logger An instance of a {@link Logger} to use for logging content
- * store events.
- *
- * @return a newly created contentStoreLRU instance.
- *
- */
-ContentStoreInterface *contentStoreLRU_Create(ContentStoreConfig *config,
- Logger *logger);
-#endif // contentStoreLRU_h
diff --git a/hicn-light/src/hicn/content_store/listLRU.c b/hicn-light/src/hicn/content_store/listLRU.c
deleted file mode 100644
index 242af40..0000000
--- a/hicn-light/src/hicn/content_store/listLRU.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _WIN32
-#include <sys/queue.h>
-#endif
-#include <hicn/hicn-light/config.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#include <hicn/content_store/listLRU.h>
-
-struct list_lru_entry {
- void *userData;
-
- // always set to the list
- ListLru *parentList;
-
- // indicates if the Entry is currently in the list
- bool inList;
-
- TAILQ_ENTRY(list_lru_entry) list;
-};
-
-// this defines the TAILQ structure so we can access the tail pointer
-TAILQ_HEAD(lru_s, list_lru_entry);
-
-struct list_lru {
- struct lru_s head;
- size_t itemsInList;
-};
-
-void listLRU_EntryDestroy(ListLruEntry **entryPtr) {
- parcAssertNotNull(entryPtr,
- "Parameter entryPtr must be non-null double pointer");
-
- ListLruEntry *entry = *entryPtr;
- if (entry->inList) {
- TAILQ_REMOVE(&entry->parentList->head, entry, list);
- parcAssertTrue(
- entry->parentList->itemsInList > 0,
- "Invalid state, removed entry from list, but itemsInList is 0");
- entry->parentList->itemsInList--;
- }
-
- parcMemory_Deallocate((void **)&entry);
- *entryPtr = NULL;
-}
-
-void listLRU_EntryMoveToHead(ListLruEntry *entry) {
- parcAssertNotNull(entry, "Parameter entry must be non-null");
-
- TAILQ_REMOVE(&entry->parentList->head, entry, list);
- TAILQ_INSERT_HEAD(&entry->parentList->head, entry, list);
-}
-
-void *listLRU_EntryGetData(ListLruEntry *entry) { return entry->userData; }
-
-ListLru *listLRU_Create() {
- ListLru *list = parcMemory_AllocateAndClear(sizeof(ListLru));
- parcAssertNotNull(list, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListLru));
- list->itemsInList = 0;
- TAILQ_INIT(&list->head);
- return list;
-}
-
-void listLRU_Destroy(ListLru **lruPtr) {
- parcAssertNotNull(lruPtr, "Parameter lruPtr must be non-null double pointer");
-
- ListLru *lru = *lruPtr;
-
- ListLruEntry *entry = TAILQ_FIRST(&lru->head);
- while (entry != NULL) {
- ListLruEntry *next = TAILQ_NEXT(entry, list);
- listLRU_EntryDestroy(&entry);
- entry = next;
- }
-
- parcMemory_Deallocate((void **)&lru);
- *lruPtr = NULL;
-}
-
-ListLruEntry *listLRU_NewHeadEntry(ListLru *lru, void *data) {
- parcAssertNotNull(lru, "Parameter lru must be non-null");
- parcAssertNotNull(data, "Parameter data must be non-null");
-
- ListLruEntry *entry = parcMemory_AllocateAndClear(sizeof(ListLruEntry));
- parcAssertNotNull(entry, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ListLruEntry));
- entry->userData = data;
- entry->parentList = lru;
- entry->inList = true;
-
- TAILQ_INSERT_HEAD(&lru->head, entry, list);
- lru->itemsInList++;
-
- return entry;
-}
-
-ListLruEntry *listLRU_PopTail(ListLru *lru) {
- parcAssertNotNull(lru, "Parameter lru must be non-null");
-
- ListLruEntry *entry = TAILQ_LAST(&lru->head, lru_s);
-
- if (entry) {
- parcAssertTrue(
- lru->itemsInList > 0,
- "Invalid state, removed entry from list, but itemsInList is 0");
- lru->itemsInList--;
- TAILQ_REMOVE(&lru->head, entry, list);
- entry->inList = false;
- }
-
- return entry;
-}
-
-size_t listLRU_Length(const ListLru *lru) {
- parcAssertNotNull(lru, "Parameter lru must be non-null");
- return lru->itemsInList;
-}
diff --git a/hicn-light/src/hicn/content_store/listLRU.h b/hicn-light/src/hicn/content_store/listLRU.h
deleted file mode 100644
index 75f698b..0000000
--- a/hicn-light/src/hicn/content_store/listLRU.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file listLRU.h
- * @brief Maintains an LRU for the content store
- *
- * An LRU list is make up of LRU entries. The entries are bound to the list.
- * The user of the list is reponsible for knowing when there's too many things
- * and wants to remove one. The LRU list will grow without bound otherwise.
- *
- * The LRU list is meant to be used as an auxiliary data structure, not the
- * primary storage of data elements.
- *
- */
-
-#ifndef listLRU_h
-#define listLRU_h
-
-struct list_lru_entry;
-typedef struct list_lru_entry ListLruEntry;
-
-struct list_lru;
-typedef struct list_lru ListLru;
-
-/**
- * @function lruEntry_Destroy
- * @abstract Destroys and element. This will also remove it from the list.
- */
-void listLRU_EntryDestroy(ListLruEntry **entryPtr);
-
-/**
- * @function listLRU_EntryMoveToHead
- * @abstract move an element to head
- */
-void listLRU_EntryMoveToHead(ListLruEntry *entry);
-
-/**
- * @function lruEntry_GetData
- * @abstract Returns the user-supplied opaque data when the entry was created
- */
-void *listLRU_EntryGetData(ListLruEntry *entry);
-
-/**
- * @function listLRU_Create
- * @abstract Creates a new Least-Recently-Used list
- */
-ListLru *listLRU_Create();
-
-/**
- * @function listLRU_Destroy
- * @abstract Destroys a list and frees all the elements in it
- */
-void listLRU_Destroy(ListLru **listPtr);
-
-/**
- * Returns the number of items in the list
- *
- * @param [in] lru An allocated ListLru
- * @retval number The number of items in the LRU list
- */
-size_t listLRU_Length(const ListLru *lru);
-
-/**
- * @function listLRU_NewHeadEntry
- * @abstract Creates a new entry for the list. It is inserted at the head of
- * the list.
- */
-ListLruEntry *listLRU_NewHeadEntry(ListLru *lru, void *data);
-
-/**
- * @function listLRU_PopTail
- * @abstract Removes the tail element from the list and returns it to the user
- * @discussion
- * Pops the tail element. The user should examine its data to destroy their
- * tail object, then call <code>LruEntry_Destroy()</code> to free the
- * LRU entry.
- *
- * @return The tail element, or NULL for an empty list
- */
-ListLruEntry *listLRU_PopTail(ListLru *list);
-#endif // listLRU_h
diff --git a/hicn-light/src/hicn/content_store/listTimeOrdered.c b/hicn-light/src/hicn/content_store/listTimeOrdered.c
deleted file mode 100644
index 690c6e4..0000000
--- a/hicn-light/src/hicn/content_store/listTimeOrdered.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/hicn-light/config.h>
-#include <hicn/content_store/listTimeOrdered.h>
-
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_TreeRedBlack.h>
-
-/**
- * A list of ContentStoreEntrys, kept in sorted order by time. The ordering is
- * calculated by a key compare function (e.g. {@link TimeOrderList_KeyCompare}),
- * passed in.
- *
- * This container does not hold references to the objects that it contains. In
- * other words, it does not Acquire() the Messages that are placed in it. That
- * reference count is managed by the owning ContentStore. This is purely an
- * index, and provides an easy to way index Messages based on a specified time
- * value. Typically, that would be the Expiration Time.
- *
- * It maintains a tree, sorted by the time values passed in to the Add()
- * function. It does not manage capacity, and can grow uncontrollably if the
- * owning ContentStore does not manage it. Items are indexed first by time, then
- * address of the Message (just as a distringuishing attribute). This allows us
- * to store multiple items with the same expiration time.
- */
-
-struct list_timeordered {
- PARCTreeRedBlack *timeOrderedTree;
-};
-
-static void _finalRelease(ListTimeOrdered **listP) {
- ListTimeOrdered *list = *listP;
- parcTreeRedBlack_Destroy(&list->timeOrderedTree);
-}
-
-parcObject_ExtendPARCObject(ListTimeOrdered, _finalRelease, NULL, NULL, NULL,
- NULL, NULL, NULL);
-
-parcObject_ImplementAcquire(listTimeOrdered, ListTimeOrdered);
-
-parcObject_ImplementRelease(listTimeOrdered, ListTimeOrdered);
-
-ListTimeOrdered *listTimeOrdered_Create(
- TimeOrderList_KeyCompare *keyCompareFunction) {
- ListTimeOrdered *result = parcObject_CreateInstance(ListTimeOrdered);
- if (NULL != result) {
- result->timeOrderedTree =
- parcTreeRedBlack_Create(keyCompareFunction, // keyCompare
- NULL, // keyFree
- NULL, // keyCopy
- NULL, // valueEquals
- NULL, // valueFree
- NULL); // valueCopy
- }
- return result;
-}
-
-void listTimeOrdered_Add(ListTimeOrdered *list, ContentStoreEntry *entry) {
- parcTreeRedBlack_Insert(list->timeOrderedTree, entry, entry);
-}
-
-ContentStoreEntry *listTimeOrdered_GetOldest(ListTimeOrdered *list) {
- return parcTreeRedBlack_FirstKey(list->timeOrderedTree);
-}
-
-bool listTimeOrdered_Remove(ListTimeOrdered *list,
- ContentStoreEntry *storeEntry) {
- bool result = false;
-
- ContentStoreEntry *entry = (ContentStoreEntry *)parcTreeRedBlack_Remove(
- list->timeOrderedTree, storeEntry);
- if (entry != NULL) {
- result = true;
- }
- return result;
-}
-
-size_t listTimeOrdered_Length(ListTimeOrdered *list) {
- return (size_t)parcTreeRedBlack_Size(list->timeOrderedTree);
-}
diff --git a/hicn-light/src/hicn/content_store/listTimeOrdered.h b/hicn-light/src/hicn/content_store/listTimeOrdered.h
deleted file mode 100644
index 325e7c0..0000000
--- a/hicn-light/src/hicn/content_store/listTimeOrdered.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef listTimeOrdered_h
-#define listTimeOrdered_h
-
-#include <parc/algol/parc_TreeRedBlack.h>
-#include <hicn/content_store/contentStoreEntry.h>
-#include <hicn/core/message.h>
-#include <stdio.h>
-
-struct list_timeordered;
-typedef struct list_timeordered ListTimeOrdered;
-
-/**
- * A signum function that takes two instances of ContentStoreEntrys and
- * returns a value based on their relative values.
- */
-typedef PARCTreeRedBlack_KeyCompare TimeOrderList_KeyCompare;
-
-/**
- * Create a new instance of `ListTimeOrdered` that will maintain the order of
- * its list items using the supplied `keyCompareFunction`.
- *
- * The newly created `ListTimeOrdered` must eventually be released by calling
- * {@link listTimeOrdered_Release}.
- *
- * @param keyCompareFunction the signum comparison function to use to sort
- * stored items.
- * @return a new instance of `TimeOrderList`.
- * @return NULL if the new instance couldn't be created.
- *
- */
-ListTimeOrdered *listTimeOrdered_Create(
- TimeOrderList_KeyCompare *keyCompareFunction);
-
-/**
- * Release a previously acquired reference to the specified instance,
- * decrementing the reference count for the instance.
- *
- * The pointer to the instance is set to NULL as a side-effect of this function.
- *
- * If the invocation causes the last reference to the instance to be released,
- * the instance is deallocated and the instance's implementation will perform
- * additional cleanup and release other privately held references.
- *
- */
-void listTimeOrdered_Release(ListTimeOrdered **listP);
-
-/**
- * Add a {@link ContentStoreEntry} instance to the specified list. Note that a
- * new refernece to the specified `storeEntry` is not acquired.
- *
- * @param list the list instance into which to add the specified storeEntry.
- * @param storeEntry the storeEntry instance to add.
- *
- */
-void listTimeOrdered_Add(ListTimeOrdered *list, ContentStoreEntry *storeEntry);
-
-/**
- * Remove a {@link ContentStoreEntry} instance from the specified list.
- *
- * @param list the list instance from which to remove the specified storeEntry.
- * @param storeEntry the storeEntry instance to remove.
- * @return true if the removal was succesful.
- * @return false if the removal was not succesful.
- *
- */
-bool listTimeOrdered_Remove(ListTimeOrdered *list,
- ContentStoreEntry *storeEntry);
-
-/**
- * Return the oldest {@link ContentStoreEntry} instance in this list. That is,
- * the one with the smallest time value.
- *
- * @param list the list instance from which to retrieve the oldest storeEntry.
- * @param the oldest `ContentStoreEntry` in the list
- * @param NULL if no `ContentStoreEntry` was available.
- *
- */
-ContentStoreEntry *listTimeOrdered_GetOldest(ListTimeOrdered *list);
-
-/**
- * Return the number of items currently stored in the list.
- *
- * @param list the `ListTimeOrdered` instance from which to retrieve the count.
- * @return the number of items in the list.
- *
- */
-size_t listTimeOrdered_Length(ListTimeOrdered *list);
-#endif /* defined(listTimeOrdered_h) */
diff --git a/hicn-light/src/hicn/content_store/lru.c b/hicn-light/src/hicn/content_store/lru.c
new file mode 100644
index 0000000..30f972c
--- /dev/null
+++ b/hicn-light/src/hicn/content_store/lru.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <sys/queue.h>
+#endif
+
+#include <hicn/util/log.h>
+
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+
+#include <hicn/core/content_store.h>
+#include "lru.h"
+
+// XXX TODO some part to be moved to parent
+
+// XXX TODO
+#if 0
+static void _content_store_lru_Log(ContentStoreInterface *storeImpl) {
+ content_store_lru_data_t *store =
+ (content_store_lru_data_t *)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
+bool
+_content_store_lru_remove_least_used(content_store_t * cs)
+{
+ if (content_store_size(cs) == 0)
+ return false;
+
+#if 0
+ ListLruEntry *lruEntry = listLRU_PopTail(store->lru);
+ content_store_entry_t *storeEntry =
+ (content_store_entry_t *)listLRU_EntryGetData(lruEntry);
+#else
+ content_store_entry_t * entry = NULL;
+#endif
+
+ DEBUG("CS %p LRU evict msgbuf %p (#evictions %" PRIu64 ")",
+ cs, content_store_entry_message(entry),
+ cs->stats.lru.countLruEvictions);
+
+ content_store_purge_entry(cs, entry);
+
+ return true;
+}
+
+static
+void
+_evictByStorePolicy(content_store_t * cs, 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.
+
+ content_store_entry_t *entry =
+ listTimeOrdered_GetOldest(store->indexByExpirationTime);
+ if (entry && content_store_entry_has_expiry_time(entry) &&
+ (currentTimeInTicks > content_store_entry_get_expiry_time(entry))) {
+ // Found an expired entry. Remove it, and we're done.
+
+ store->stats.countExpiryEvictions++;
+ DEBUG("ContentStore %p evict message %p by ExpiryTime (ExpiryTime evictions %" PRIu64 ")",
+ (void *)store, (void *)contentStoreEntry_GetMessage(entry),
+ store->stats.countExpiryEvictions);
+
+ _content_store_lru_purge_entry(store, entry);
+ } else {
+ store->stats.countLruEvictions++;
+ _content_store_lru_remove_least_used(store);
+ }
+}
+#endif
+
+void
+content_store_lru_initialize(content_store_t * cs)
+{
+ content_store_lru_data_t * data = cs->data;
+
+ data->lru = NULL;
+ if (!data->lru) {
+ ERROR("Could not create LRU index");
+ goto ERR_INDEX;
+ }
+
+ERR_INDEX:
+ return;
+}
+
+void
+content_store_lru_finalize(content_store_t * cs)
+{
+ content_store_lru_data_t * data = cs->data;
+
+ if (data->lru != NULL)
+ ; // XXX TODO listLRU_Destroy(&(store->lru));
+}
+
+bool
+content_store_lru_add_entry(content_store_t * cs, content_store_entry_t * entry)
+{
+ assert(cs);
+ assert(entry);
+
+ if (content_store_size(cs) == 0)
+ return false;
+#if 0
+ content_store_lru_data_t * data = cs->data;
+
+ content_store_entry_t *dataEntry = parcHashCodeTable_Get(data->storageByName, content);
+ if(dataEntry)
+ _content_store_lru_purge_entry(data, dataEntry);
+
+ 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 (now >= expiryTimeTicks)
+ return false;
+
+ if (data->objectCount >= data->objectCapacity)
+ // Store is full. Need to make room.
+ _evictByStorePolicy(data, now);
+
+ // And now add a new entry to the head of the LRU.
+ content_store_entry_t *entry = contentStoreEntry_Create(content, data->lru);
+ if (!entry)
+ return false;
+
+ if (!parcHashCodeTable_Add(data->storageByName, content, entry)) {
+ // Free what we just created, but did not add. 'entry' has ownership of
+ // 'copy', and so will call _Release() on it
+ contentStoreEntry_Release(&entry);
+ WARN("ContentStoreLRU %p failed to add message %p to hash table",
+ (void *)data, (void *)content);
+ return false;
+ }
+
+ if (content_store_entry_has_expiry_time(entry))
+ listTimeOrdered_Add(data->indexByExpirationTime, entry);
+
+ data->objectCount++;
+ data->stats.countAdds++;
+
+ DEBUG("ContentStoreLRU %p saved message %p (object count %" PRIu64 ")",
+ data, msgbuf, content_store_size(cs));
+#endif
+ return true;
+}
+
+/**
+ * Remove a content_store_entry_t from all tables and indices.
+ */
+static
+void
+content_store_lru_remove_entry(content_store_t * cs, content_store_entry_t * entry)
+{
+ assert(cs);
+ assert(entry);
+ //
+ // XXX REMOVE ENTRY FROM LRU
+}
+
+
+DECLARE_CONTENT_STORE(lru);
diff --git a/hicn-light/src/hicn/processor/pitStandard.h b/hicn-light/src/hicn/content_store/lru.h
index 9d7ce6a..6134192 100644
--- a/hicn-light/src/hicn/processor/pitStandard.h
+++ b/hicn-light/src/hicn/content_store/lru.h
@@ -13,29 +13,22 @@
* limitations under the License.
*/
-/**
- * @file pitStandard.h
- * @brief The Pending Interest Table
- *
- * Implements the standard Pending Interest Table.
- *
- */
+#ifndef HICNLIGHT_CONTENT_STORE_LRU_H
+#define HICNLIGHT_CONTENT_STORE_LRU_H
-#ifndef pitStandard_h
-#define pitStandard_h
+typedef struct {
+ // This LRU is just for keeping track of insertion and access order.
+ //ListLru *lru;
+ void * lru;
+} content_store_lru_data_t;
-#include <hicn/processor/pit.h>
+typedef struct {
+ uint64_t countExpiryEvictions;
+ uint64_t countRCTEvictions;
+ uint64_t countLruEvictions;
+ uint64_t countAdds;
+ uint64_t countHits;
+ uint64_t countMisses;
+} content_store_lru_stats_t;
-/**
- * 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
+#endif /* HICNLIGHT_CONTENT_STORE_LRU_H */
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index 5e2b696..b1f952a 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -14,20 +14,27 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionState.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionTable.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/address.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/address_pair.h
${CMAKE_CURRENT_SOURCE_DIR}/connection.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_vft.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_table.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/content_store.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib.h
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h
- ${CMAKE_CURRENT_SOURCE_DIR}/logger.h
- ${CMAKE_CURRENT_SOURCE_DIR}/dispatcher.h
- ${CMAKE_CURRENT_SOURCE_DIR}/message.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.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}/msgbuf.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/pit.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/prefix_stats.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy_vft.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/system.h
${CMAKE_CURRENT_SOURCE_DIR}/mapme.h
${CMAKE_CURRENT_SOURCE_DIR}/wldr.h
${CMAKE_CURRENT_SOURCE_DIR}/messageHandler.h
@@ -36,20 +43,27 @@ list(APPEND HEADER_FILES
)
list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/address.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/address_pair.c
${CMAKE_CURRENT_SOURCE_DIR}/connection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionList.c
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.c
- ${CMAKE_CURRENT_SOURCE_DIR}/connectionTable.c
- ${CMAKE_CURRENT_SOURCE_DIR}/dispatcher.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_table.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/connection_vft.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/content_store.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.c
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.c
- ${CMAKE_CURRENT_SOURCE_DIR}/logger.c
- ${CMAKE_CURRENT_SOURCE_DIR}/message.c
- ${CMAKE_CURRENT_SOURCE_DIR}/numberSet.c
- ${CMAKE_CURRENT_SOURCE_DIR}/streamBuffer.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.c
${CMAKE_CURRENT_SOURCE_DIR}/mapme.c
- ${CMAKE_CURRENT_SOURCE_DIR}/wldr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.c
${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.c
${CMAKE_CURRENT_SOURCE_DIR}/name.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pit.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/prefix_stats.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/strategy.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/wldr.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/core/address.c b/hicn-light/src/hicn/core/address.c
new file mode 100644
index 0000000..07aa4a8
--- /dev/null
+++ b/hicn-light/src/hicn/core/address.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file address.c
+ * \brief Implementation of Address
+ */
+
+#include <hicn/core/address.h>
+
+int
+address_from_ip_port(address_t * address, int family, ip_address_t * addr, uint16_t port)
+{
+ memset(address, 0, sizeof(address_t));
+ switch(family) {
+ case AF_INET:
+ *address = ADDRESS4(addr->v4.as_inaddr.s_addr, port);
+ break;
+ case AF_INET6:
+ *address = ADDRESS6(addr->v6.as_in6addr, port);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+const char * _address_family_str[] = {
+ [AF_INET] = "AF_INET",
+ [AF_INET6] = "AF_INET6",
+};
diff --git a/hicn-light/src/hicn/core/address.h b/hicn-light/src/hicn/core/address.h
new file mode 100644
index 0000000..d13fc99
--- /dev/null
+++ b/hicn-light/src/hicn/core/address.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file address.h
+ * \brief Address
+ */
+
+#ifndef HICN_ADDRESS_H
+#define HICN_ADDRESS_H
+
+#include <netinet/in.h>
+
+#include <string.h> // memcmp
+#include <hicn/util/ip_address.h>
+#include <netinet/in.h>
+
+typedef struct sockaddr_storage address_t;
+
+#define address_equals(a, b) (memcmp(a, b, sizeof(address_t)) == 0)
+
+#define address_family(address) ((address)->ss_family)
+
+#define address4(address) ((struct sockaddr_in *)(address))
+#define address6(address) ((struct sockaddr_in6 *)(address))
+#define address_sa(address) ((struct sockaddr *)(address))
+
+#define address4_ip(address) (address4(address)->sin_addr)
+#define address6_ip(address) (address6(address)->sin6_addr)
+#define address6_scope_id(address) (address4_ptr(address)->sin6_scope_id)
+
+#define address_socklen(address) (((address)->ss_family == AF_INET) \
+ ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
+
+#define address4_is_local(address) \
+ ((htonl((address4_ip(address)).s_addr) & 0xFF000000) == 0x7F000000)
+
+#define address6_is_local(address) (IN6_IS_ADDR_LOOPBACK(address6(address)))
+
+#define address_is_local(address) ((address)->ss_family == AF_INET) \
+ ? address4_is_local(address) : address6_is_local(address)
+
+int address_from_ip_port(address_t * address, int family, ip_address_t * addr, uint16_t port);
+
+#define ADDRESS4(ip, port) (*(address_t*) &((struct sockaddr_in) { \
+ .sin_family = AF_INET, \
+ .sin_port = htons(port), \
+ .sin_addr.s_addr = htonl(ip), \
+}))
+
+#define ADDRESS4_LOCALHOST(port) ADDRESS4(INADDR_LOOPBACK, (port))
+#define ADDRESS4_ANY(port) ADDRESS4(INADDR_ANY, (port))
+
+#define ADDRESS6(ip, port) (*(address_t*) &((struct sockaddr_in6) {\
+ .sin6_family = AF_INET6, \
+ .sin6_port = htons(port), \
+ .sin6_addr = IN6ADDR_ANY_INIT, \
+ .sin6_scope_id = 0, \
+}))
+
+#define ADDRESS6_ANY(port) ADDRESS6(IN6ADDR_ANY_INIT, port)
+
+#define ADDRESS_ANY(family, port) ((family == AF_INET) \
+ ? ADDRESS4_ANY(port) \
+ : ADDRESS6_ANY(port))
+
+extern const char * _address_family_str[];
+
+#define address_family_str(address) (_address_family_str[address_family(address)])
+
+#define address4_empty(address) (address4_ip(address).s_addr == 0)
+#define address6_empty(address) (memcmp(address6_ip(address).s6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0)
+#define address_empty(address) (address_family(address) == AF_INET ? address4_empty(address) : address6_empty(address))
+
+#endif /* HICN_ADDRESS_H */
+
diff --git a/hicn-light/src/hicn/core/address_pair.c b/hicn-light/src/hicn/core/address_pair.c
new file mode 100644
index 0000000..dee06c0
--- /dev/null
+++ b/hicn-light/src/hicn/core/address_pair.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file address_pair.c
+ * \brief Implementation of Address pair
+ */
+
+#include "address_pair.h"
+
+int
+address_pair_from_ip_port(address_pair_t * pair, int family,
+ ip_address_t * local_addr, uint16_t local_port,
+ ip_address_t * remote_addr, uint16_t remote_port)
+{
+ if (address_from_ip_port(&pair->local, family, local_addr, local_port) < 0)
+ return -1;
+ if (address_from_ip_port(&pair->remote, family, remote_addr, remote_port) < 0)
+ return -1;
+ return 0;
+}
diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h
new file mode 100644
index 0000000..fae4f25
--- /dev/null
+++ b/hicn-light/src/hicn/core/address_pair.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file address_pair.h
+ * \brief Address pair
+ */
+
+#ifndef HICN_ADDRESS_PAIR_H
+#define HICN_ADDRESS_PAIR_H
+
+#include <hicn/core/address.h>
+#include <hicn/util/ip_address.h>
+
+typedef struct {
+ address_t local;
+ address_t remote;
+} address_pair_t;
+
+int address_pair_from_ip_port(address_pair_t * pair, int family,
+ ip_address_t * local_addr, uint16_t local_port,
+ ip_address_t * remote_addr, uint16_t remote_port);
+
+#define address_pair_get_local(pair) (&(pair)->local)
+#define address_pair_get_remote(pair) (&(pair)->remote)
+
+#define address_pair_get_local_family(pair) \
+ (address_family(address_pair_local(pair)))
+#define address_pair_get_remote_family(pair) \
+ (address_family(address_pair_remote(pair)))
+#define address_pair_get_family(pair) address_pair_local_family(pair)
+
+#define address_pair_is_valid(pair) \
+ (address_pair_local_family(pair) == address_pair_remote_family(pair))
+
+#endif /* HICN_ADDRESS_PAIR_H */
diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c
index c2ac71a..582e2f5 100644
--- a/hicn-light/src/hicn/core/connection.c
+++ b/hicn-light/src/hicn/core/connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -13,347 +13,583 @@
* limitations under the License.
*/
-#include <limits.h>
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
+/**
+ * @file connection.c
+ * @brief Implementation of hICN connections
+ */
-#include <hicn/core/connection.h>
-#include <hicn/core/connectionState.h>
-#include <hicn/core/messageHandler.h>
-#include <hicn/core/ticks.h>
-#include <hicn/core/wldr.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
+#include <assert.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/assert/parc_Assert.h>
-#ifdef WITH_POLICY
-#include <hicn/policy.h>
-#endif /* WITH_POLICY */
+#include <hicn/core/forwarder.h>
+#include <hicn/util/log.h>
+#include <hicn/core/wldr.h>
-struct connection {
+#include "connection.h"
+#include "connection_vft.h"
- const AddressPair *addressPair;
- IoOperations *ops;
+#define _conn_var(x) _connection_ ## x
- unsigned refCount;
+#if 0
- unsigned counter;
+/* Accessors */
- 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;
+static inline
+unsigned
+connection_get_id(const connection_t * connection)
+{
+ return connection->id;
+}
-#ifdef WITH_POLICY
- policy_tags_t tags;
-#endif /* WITH_POLICY */
+static inline
+char *
+connection_get_name(const connection_t * connection)
+{
+ return connection->name;
+}
-};
+static inline
+face_type_t
+connection_get_type(const connection_t * connection)
+{
+ return connection->type;
+}
-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;
+static inline
+address_pair_t *
+connection_get_pair(const connection_t * connection)
+{
+ return connection->pair;
+}
- conn->wldrAutoStart = true;
- conn->counter = 0;
+static inline
+bool
+connection_is_up(const connection_t * connection)
+{
+ return connection->up;
+}
- /* By default, a connection will aim at the UP state */
- connection_SetAdminState(conn, CONNECTION_STATE_UP);
+static inline
+bool
+connection_is_local(const connection_t * connection)
+{
+ return connection->local;
+}
-#ifdef WITH_POLICY
- conn->tags = POLICY_TAGS_EMPTY;
-#endif /* WITH_POLICY */
+static inline
+face_state_t
+connection_get_state(const connection_t * connection)
+{
+ return connection->state;
+}
- return conn;
+static inline
+void
+connection_set_state(connection_t * connection, face_state_t state)
+{
+ connection->state = state;
}
-Connection *connection_Acquire(Connection *connection) {
- parcAssertNotNull(connection, "Parameter conn must be non-null");
- connection->refCount++;
- return connection;
+static inline
+face_state_t
+connection_get_admin_state(const connection_t * connection)
+{
+ return connection->admin_state;
}
-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;
+static inline
+void
+connection_set_admin_state(connection_t * connection, face_state_t state)
+{
+ connection->admin_state = state;
+}
- 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;
+static inline
+const char *
+connection_get_interface_name(const connection_t * connection)
+{
+ return connection->interface_name;
}
-bool connection_Send(const Connection *conn, Message *message) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
+#ifdef WITH_POLICY
- 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;
+static inline
+uint32_t
+connection_get_priority(const connection_t * connection)
+{
+ connection->priority = priority;
}
-bool connection_SendIOVBuffer(const Connection *conn, struct iovec *msg,
- size_t size) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(msg, "Parameter message must be non-null");
-
- return ioOperations_SendIOVBuffer(conn->ops, msg, size);
+static inline
+void
+connection_set_priority(connection_t * connection, uint32_t priority)
+{
+ connection->priority = priority;
}
-bool connection_SendBuffer(const Connection *conn, u8 * buffer, size_t length)
+static inline
+policy_tags_t
+connection_get_tags(const connection_t * connection)
{
- struct iovec iov[1];
- iov[0].iov_base = buffer;
- iov[0].iov_len = length;
- return connection_SendIOVBuffer(conn, iov, 1);
+ return connection->tags;
}
-void connection_Probe(Connection *conn, uint8_t * probe) {
- ioOperations_SendProbe(conn->ops, probe);
+static inline
+void
+connection_set_tags(connection_t * connection, policy_tags_t tags)
+{
+ connection->tags = tags;
}
-void connection_HandleProbe(Connection *conn, uint8_t *probe){
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- parcAssertNotNull(probe, "Parameter pkt must be non-null");
+#endif /* WITH_POLICY */
- if(messageHandler_IsInterest(probe)){
- messageHandler_CreateProbeReply(probe, HF_INET6_TCP);
- ioOperations_SendProbe(conn->ops, probe);
- }
-}
+/* API */
-IoOperations *connection_GetIoOperations(const Connection *conn) {
- return conn->ops;
-}
+#endif
-unsigned connection_GetConnectionId(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_GetConnectionId(conn->ops);
-}
+connection_t *
+connection_create_on_listener(const listener_t * listener, const char * name,
+ const address_pair_t * pair, forwarder_t * forwarder)
+{
+ const connection_table_t * table = forwarder_get_connection_table(forwarder);
-const AddressPair *connection_GetAddressPair(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_GetAddressPair(conn->ops);
-}
+ connection_t * connection;
+ connection_table_allocate(table, connection, pair, name);
-bool connection_IsUp(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops) return false;
- return ioOperations_IsUp(conn->ops);
+ unsigned connection_id = connection_table_get_connection_id(table, connection);
+
+ const char * interface_name = listener_get_interface_name(listener);
+ // XXX This should not be there !
+ int fd = listener_get_socket(listener, address_pair_get_local(pair),
+ address_pair_get_remote(pair), NULL);
+ bool local = address_is_local(&pair->local);
+
+ if (connection_initialize(connection, listener->type, name, interface_name, fd, pair, local,
+ connection_id, forwarder) < 0) {
+ connection_table_deallocate(table, connection);
+ return NULL;
+ }
+
+ return connection;
}
-bool connection_IsLocal(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_IsLocal(conn->ops);
+
+// This is called by configuration
+// XXX different wit create on listener : when listener receives a new
+// connection
+// !
+connection_t *
+connection_create(face_type_t type, const char * name,
+ const address_pair_t * pair, forwarder_t * forwarder)
+{
+ assert(face_type_is_valid(type));
+ assert(pair);
+ assert(forwarder);
+
+ listener_table_t * table = forwarder_get_listener_table(forwarder);
+ listener_t *listener = listener_table_get_by_address(table, type, &pair->local);
+ if (!listener) {
+ // XXX TODO
+ //char *str = addressToString(localAddress);
+ ERROR("Could not find listener to match address N/A");
+ //parcMemory_Deallocate((void **)&str);
+ return NULL;
+ }
+
+ return connection_create_on_listener(listener, name, pair, forwarder);
}
-const void *connection_Class(const Connection *conn) {
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- return ioOperations_Class(conn->ops);
+#if 0
+
+ const char * interface_name = listener->getInterfaceName(listener);
+ int fd = listener->getSocket(listener, pair);
+ bool is_local = address_is_local(&pair->local);
+
+
+ return udpConnection_Create(forwarder, interface_name, fd, pair, is_local, connid);
+
+ // alternatively
+ //
}
+#endif
-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;
+/**
+ * @brief Initializes a connection
+ *
+ * @param [out] connection - Allocated connection buffer (eg. from pool) to be
+ * initialized.
+ * @param [in] forwarder - forwarder_t to which the connection is associated. This
+ * parameter needs to be non-NULL for connections receiving packets, such
+ * as TCP connections which are very close to UDP listeners, and unlike
+ * bound UDP connections).
+ * @return 0 if no error, -1 otherwise
+ */
+int
+connection_initialize(connection_t * connection, face_type_t type, const char * name,
+ const char * interface_name, int fd, const address_pair_t * pair,
+ bool local, unsigned connection_id, forwarder_t * forwarder)
+{
+ int rc;
+
+ assert(connection);
+ /* Interface name can be NULL eg always for TCP connnections */
+ assert(pair);
+ assert(address_pair_valid(pair));
+
+ *connection = (connection_t) {
+ .id = connection_id,
+ .name = strdup(name),
+ .type = type,
+ .interface_name = strdup(interface_name),
+ .pair = *pair,
+ .fd = fd,
+// .up = true,
+ .local = local,
+ // XXX UDP should start UP, TCP DOWN until remove side answer ?
+ .state = FACE_STATE_UNDEFINED,
+ .admin_state = FACE_STATE_UP,
+#ifdef WITH_POLICY
+ .priority = 0,
+#endif /* WITH_POLICY */
- if (connection_IsUp(conn)) {
- // here the wldr header is alreay set: this message is a retransmission or a
- // notification
+ .forwarder = forwarder,
+ .closed = false,
- // 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
+ /* WLDR */
+ .wldr = NULL,
+ .wldr_autostart = true,
+ };
- 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);
+ connection->data = malloc(connection_vft[connection->type]->data_size);
+ if (!connection->data)
+ goto ERR_DATA;
- res = ioOperations_Send(conn->ops, NULL, message);
+ assert(connection_has_valid_type(connection));
- message_SetPathLabel(message, old_path_label);
- } else {
- res = ioOperations_Send(conn->ops, NULL, message);
+ rc = connection_vft[connection->type]->initialize(connection);
+ if (rc < 0) {
+ goto ERR_VFT;
}
- }
- if (notification) {
- // the notification is never destroyed
- message_Release(&message);
- }
+ // XXX uncertain as fd is created by the listener !!
+ // XXX check whether it is registered !
+#if 0
+ connection->fd = connection_vft[connection->type]->get_socket(connection, address, NULL, interface_name);
+ if (connection->fd < 0) {
+ ERROR("Error creating connection fd: (%d) %s", errno, strerror(errno));
+ goto ERR_FD;
+ }
+
+ // XXX data should be pre-allocated here
+
+ if (loop_register_fd(MAIN_LOOP, connection->fd, connection,
+ connection_vft[connection->type]->read_callback, NULL) < 0)
+ goto ERR_REGISTER_FD;
+#endif
+
+ // XXX TODO
+ //char *str = pair_ToString(udp->pair);
+ DEBUG("%s connection %p created for address %s (local=%s)",
+ face_type_str(connection->type), connection, "N/A",
+ connection_is_local(connection) ? "true" : "false");
+ //free(str);
+ //
+ return 0;
+
+#if 0
+ERR_REGISTER_FD:
+#ifndef _WIN32
+ close(connection->fd);
+#else
+ closesocket(connection->fd);
+#endif
+ERR_FD:
+#endif
+ERR_VFT:
+ free(connection->data);
+ERR_DATA:
+ free(connection->interface_name);
+ free(connection->name);
+ return -1;
+}
+
+int
+connection_finalize(connection_t * connection)
+{
+ assert(connection);
- return res;
+ if (connection->wldr)
+ wldr_free(connection->wldr);
+
+ connection_vft[connection->type]->finalize(connection);
+
+ free(connection->interface_name);
+ free(connection);
+
+ DEBUG("%s connection %p destroyed", face_type_str(connection->type),
+ connection);
+
+ return 0;
}
-void connection_AllowWldrAutoStart(Connection *conn, bool allow) {
- conn->wldrAutoStart = allow;
+#if 0
+// XXX put in common the validation and processing of commands with UDP and hICN
+// listeners !
+command_type_t
+_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);
+
+ message_type_t message_type = message_type_from_uchar(msg[0]);
+ //if (!message_type_is_valid(message_type))
+ if (message_type != REQUEST_LIGHT)
+ return COMMAND_TYPE_N;
+
+ return command_type_from_uchar(msg[1]);
}
-void connection_EnableWldr(Connection *conn) {
- if (!connection_IsLocal(conn)) {
- if (conn->wldr == NULL) {
- printf("----------------- enable wldr\n");
- conn->wldr = wldr_Init();
+// XXX new function to process all incoming bytes
+// result : consumed, discard/invalid, wait for more
+// PRE: buffer has at least 8 bytes (to get the length of all packets)
+// This function is only used to make decisions
+/**
+ * \return the number of consumed bytes, or a negative value in case of error
+ */
+// XXX mutualize with listener_process_buffer
+size_t
+connection_process_buffer(connection_t * connection, const uint8_t * buffer, size_t size)
+{
+ size_t expected;
+
+ /* Too small a packet is not useful to decide between a control message and
+ * an hICN packet, the size of a control message is enough to test for both
+ * pakcet types */
+ if (size < sizeof(header_control_message))
+ return 0;
+
+ /* We expect complete packets most of the time, so don't bother with state */
+ message_type_t message_type = message_type_from_uchar(msg[0]);
+ if (message_type == REQUEST_LIGHT) {
+ command_type_t command_type = command_type_from_uchar(msg[1]);
+ if (!command_type_is_valid(command_type))
+ break;
+ expected = sizeof(header_control_message) +
+ command_get_payload_len(command_type);
+ if (size < expected)
+ return 0;
+ forwarder_receive_command(connection->forwarder, command_type, packet,
+ connection->id);
+ return expected;
+ }
+
+ if (!messageHandler_IsValidHicnPacket(packet)) {
+ WARN("Connection #%u: Malformed packet received",
+ connection_get_id(connection));
+ return -1;
}
- }
-}
-void connection_DisableWldr(Connection *conn) {
- if (!connection_IsLocal(conn)) {
- if (conn->wldr != NULL) {
- printf("----------------- disable wldr\n");
- wldr_Destroy(&(conn->wldr));
- conn->wldr = NULL;
+ /* Check that we have a full packet */
+ expected = messageHandler_GetTotalPacketLength(packet),
+ if (size < expected)
+ return 0;
+
+ msgbuf_t msgbuf;
+ MessagePacketType packet_type;
+ if (messageHandler_IsInterest(message->messageHead)) {
+ packet_type = MESSAGE_TYPE_INTEREST;
+ } else if (messageHandler_IsData(message->messageHead)) {
+ packet_type = MESSAGE_TYPE_DATA;
+ } else {
+ ERROR("Dropped packet that is not interest nor data");
+ return -1;
}
- }
-}
-bool connection_HasWldr(const Connection *conn) {
- if (conn->wldr == NULL) {
- return false;
- } else {
- return true;
- }
-}
+ // this is an Hicn packet (here we should distinguish between IPv4 and
+ // IPv6 tryReadMessage may set nextMessageLength
+ msgbuf_from_packet(&msgbuf, packet, expected, packet_type,
+ connection_get_id(connection), ticks_now());
+ forwarder_receive(connection->forwarder, &msgbuf, 1);
-bool connection_WldrAutoStartAllowed(const Connection *conn) {
- return conn->wldrAutoStart;
+ return size;
}
-void connection_DetectLosses(Connection *conn, Message *message) {
- if (conn->wldr != NULL) wldr_DetectLosses(conn->wldr, conn, message);
-}
+int
+connection_read_message(connection_t * connection, msgbuf_t * msgbuf)
+{
+ assert(connection);
+ assert(face_type_is_valid(connection->type));
+ assert(msgbuf);
-void connection_HandleWldrNotification(Connection *conn, Message *message) {
- if (conn->wldr != NULL)
- wldr_HandleWldrNotification(conn->wldr, conn, message);
+ return connection_vft[connection->type]->read_message(connection, msgbuf);
}
-connection_state_t connection_GetState(const Connection *conn)
+uint8_t *
+connection_read_packet(connection_t * connection)
{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return CONNECTION_STATE_UNDEFINED;
- return ioOperations_GetState(conn->ops);
+ assert(connection);
+ assert(face_type_is_valid(connection->type));
+
+ return connection_vft[connection->type]->read_packet(connection);
}
+#endif
-void connection_SetState(Connection *conn, connection_state_t state)
+int
+connection_send_packet(const connection_t * connection, const uint8_t * packet,
+ size_t size)
{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return;
- ioOperations_SetState(conn->ops, state);
+ assert(connection);
+ assert(face_type_is_valid(connection->type));
+ assert(packet);
+
+ return connection_vft[connection->type]->send_packet(connection, packet, size);
}
-connection_state_t connection_GetAdminState(const Connection *conn)
+// ALL DEPRECATED CODE HERE TO BE UPDATED
+
+// XXX nexthops null ?? to be removed ???
+bool
+_connection_send(const connection_t * connection, msgbuf_t * msgbuf, bool queue)
{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return CONNECTION_STATE_UNDEFINED;
- return ioOperations_GetAdminState(conn->ops);
+ return connection_vft[connection->type]->send(connection, msgbuf, queue);
}
-void connection_SetAdminState(Connection *conn, connection_state_t admin_state)
+bool
+connection_send(const connection_t * connection, msgbuf_t * msgbuf, bool queue)
{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return;
- if ((admin_state != CONNECTION_STATE_UP) && (admin_state != CONNECTION_STATE_DOWN))
- return;
- ioOperations_SetAdminState(conn->ops, admin_state);
+ assert(connection);
+
+ /* NULL message means flush */
+ if (!msgbuf)
+ return _connection_send(connection, NULL, false);
+
+ if (!connection_is_up(connection))
+ return false;
+
+ if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA) {
+ uint8_t conn_id = (uint8_t)connection_get_id(connection);
+ msgbuf_update_pathlabel(msgbuf, conn_id);
+ }
+
+ if (connection->wldr)
+ wldr_set_label(connection->wldr, msgbuf);
+ else
+ msgbuf_reset_wldr_label(msgbuf);
+
+ return _connection_send(connection, msgbuf, queue);
}
-#ifdef WITH_POLICY
-uint32_t connection_GetPriority(const Connection *conn)
+/*
+ * here the wldr header is alreay set: this message is a retransmission or a
+ * notification
+ *
+ * we need to recompute the path label since we always store a pointer to
+ * the same message if this message will be sent again to someone else, the
+ * new path label must be computed starting from the orignal label. Note
+ * that we heve the same problem in case of PIT aggregation. That case is
+ * handled inside the MessageProcessor. This is specific to WLDR
+ * retransmittions. This is done only for data packets
+ */
+bool
+connection_resend(const connection_t * connection, msgbuf_t * msgbuf, bool
+ notification)
{
- parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return 0;
- return ioOperations_GetPriority(conn->ops);
+ assert(connection);
+ assert(msgbuf);
+
+ bool ret = false;
+
+ if (!connection_is_up(connection))
+ return ret;
+
+ if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA) {
+ uint8_t conn_id = (uint8_t)connection_get_id(connection);
+ uint32_t old_path_label = msgbuf_get_pathlabel(msgbuf);
+ msgbuf_update_pathlabel(msgbuf, conn_id);
+ ret = _connection_send(connection, msgbuf, false); /* no queueing */
+ msgbuf_set_pathlabel(msgbuf, old_path_label);
+ } else {
+ ret = _connection_send(connection, msgbuf, false); /* no queueing */
+ }
+
+ return ret;
}
-void connection_SetPriority(Connection *conn, uint32_t priority)
-{
+#if 0
+bool connection_sendv(const connection_t * conn, struct iovec *msg,
+ size_t size) {
parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return;
- ioOperations_SetPriority(conn->ops, priority);
+ parcAssertNotNull(msg, "Parameter message must be non-null");
+
+ return ioOperations_SendIOVBuffer(conn->ops, msg, size);
}
-#endif /* WITH_POLICY */
-const char * connection_GetInterfaceName(const Connection * conn)
-{
+void connection_probe(connection_t * conn, uint8_t * probe) {
+ ioOperations_SendProbe(conn->ops, probe);
+}
+
+void connection_hangle_probe(connection_t * conn, uint8_t *probe){
parcAssertNotNull(conn, "Parameter conn must be non-null");
- if (!conn->ops)
- return NULL;
- return ioOperations_GetInterfaceName(conn->ops);
+ parcAssertNotNull(probe, "Parameter pkt must be non-null");
+
+ if(messageHandler_IsInterest(probe)){
+ messageHandler_CreateProbeReply(probe, HF_INET6_TCP);
+ ioOperations_SendProbe(conn->ops, probe);
+ }
}
+#endif
-#ifdef WITH_POLICY
-void connection_AddTag(Connection *conn, policy_tag_t tag)
+/* WLDR */
+
+void
+connection_wldr_allow_autostart(connection_t * connection, bool value)
{
- policy_tags_add(&conn->tags, tag);
+ connection->wldr_autostart = value;
}
-void connection_RemoveTag(Connection *conn, policy_tag_t tag)
+bool
+connection_wldr_autostart_is_allowed(connection_t * connection)
{
- policy_tags_remove(&conn->tags, tag);
+ return connection->wldr_autostart;
}
-policy_tags_t connection_GetTags(const Connection *conn)
+void
+connection_wldr_enable(connection_t * connection, bool value)
{
- return conn->tags;
+ if (connection_is_local(connection))
+ return;
+ if (value) {
+ if (connection->wldr)
+ return;
+ connection->wldr = wldr_create();
+ } else {
+ if (!connection->wldr)
+ return;
+ wldr_free(connection->wldr);
+ }
}
-void connection_SetTags(Connection *conn, policy_tags_t tags)
+bool
+connection_has_wldr(const connection_t * connection)
{
- conn->tags = tags;
+ return !!connection->wldr;
}
-void connection_ClearTags(Connection *conn)
+void
+connection_wldr_detect_losses(const connection_t * connection, msgbuf_t * msgbuf)
{
- conn->tags = POLICY_TAGS_EMPTY;
+ if (!connection->wldr)
+ return;
+ wldr_detect_losses(connection->wldr, connection, msgbuf);
}
-int connection_HasTag(const Connection *conn, policy_tag_t tag)
+void
+connection_wldr_handle_notification(const connection_t * connection, msgbuf_t * msgbuf)
{
- return policy_tags_has(conn->tags, tag);
+ if (!connection->wldr)
+ return;
+ wldr_handle_notification(connection->wldr, connection, msgbuf);
}
-
-#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h
index b6513ea..45d341a 100644
--- a/hicn-light/src/hicn/core/connection.h
+++ b/hicn-light/src/hicn/core/connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -15,19 +15,22 @@
/**
* @file connection.h
- * @brief Wrapper for different types of connections
- *
- * A connection wraps a specific set of {@link IoOperations}. Those operations
- * allow for input and output. Connections get stored in the Connection Table.
- *
+ * @brief hICN connections
*/
-#ifndef connection_h
-#define connection_h
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/connectionState.h>
-#include <hicn/io/ioOperations.h>
-#include <hicn/utils/address.h>
+#ifndef HICNLIGHT_CONNECTION_H
+#define HICNLIGHT_CONNECTION_H
+
+#include <hicn/core/address_pair.h>
+#include <hicn/core/listener.h>
+#include <hicn/core/msgbuf.h>
+#include <hicn/face.h>
+
+#ifdef WITH_POLICY
+#include <hicn/policy.h>
+#endif /* WITH_POLICY */
+
+#define CONNECTION_ID_UNDEFINED ~0
#ifdef WITH_MAPME
typedef enum {
@@ -42,157 +45,169 @@ typedef enum {
#endif /* WITH_MAPME */
+struct forwarder_s;
+struct wldr_s;
+
+typedef struct {
+ unsigned id;
+ char * name;
+ char * interface_name;
+ face_type_t type;
+ address_pair_t pair;
+ int fd;
+// bool up;
+ bool local;
+ face_state_t state;
+ face_state_t admin_state;
#ifdef WITH_POLICY
-#include <hicn/policy.h>
+ policy_tags_t tags;
+ uint32_t priority;
#endif /* WITH_POLICY */
+ void * data;
+
+ struct forwarder_s * forwarder; // recv only
+ bool closed;
+
+ /* WLDR */
+
+ bool wldr_autostart;
+ /*
+ * if true, wldr can be set automatically by default this value is set to
+ * true. if wldr is activated using a command (config file/hicnLightControl)
+ * this value is set to false so that a base station can not disable wldr at
+ * the client.
+ */
+ struct wldr_s * wldr;
+
+} connection_t;
+
+#if 1
+#define connection_get_id(C) ((C)->id)
+#define connection_id_is_valid(ID) (ID != CONNECTION_ID_UNDEFINED)
+#define connection_get_name(C) ((C)->name)
+#define connection_get_type(C) ((C)->type)
+#define connection_has_valid_id(C) (connection_id_is_valid(connection_get_id(C))
+#define connection_get_pair(C) (&(C)->pair)
+#define connection_get_local(C) (address_pair_local(connection_get_pair(C)))
+#define connection_get_remote(C) (address_pair_remote(connection_get_pair(C)))
+#define connection_get_local(C) (address_pair_local(connection_get_pair(C)))
+#define connection_get_remote(C) (address_pair_remote(connection_get_pair(C)))
+#define connection_is_up(C) ((C)->state == FACE_STATE_UP)
+#define connection_is_closed(C) ((C)->closed == true)
+#define connection_is_local(C) ((C)->local)
+#define connection_get_state(C) ((C)->state)
+#define connection_set_state(C, STATE) (C)->state = STATE
+#define connection_get_admin_state(C) ((C)->admin_state)
+#define connection_set_admin_state(C, STATE) (C)->admin_state = STATE
+#define connection_get_interface_name(C) ((C)->interface_name)
-struct connection;
-typedef struct connection Connection;
+#ifdef WITH_POLICY
+#define connection_get_priority(C) ((C)->priority)
+#define connection_set_priority(C, PRIORITY) (C)->priority = PRIORITY
+#define connection_get_tags(C) ((C)->tags)
+#define connection_set_tags(C, TAGS) (C)->tags = TAGS
+#define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG)
+#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG)
+#define connection_remove_tag(C, TAG) \
+do { \
+ policy_tags_t _conn_var(tags); \
+ _conn_var(tags) = connection_get_tags(C); \
+ policy_tags_remove(_conn_var(tags), (TAG)); \
+ connection_set_tags((C), _conn_var(tags)); \
+} while(0)
+#define connection_clear_tags(C) connection_set_tags(C, POLICY_TAGS_EMPTY)
-/**
- * Creates a connection object.
- */
-Connection *connection_Create(IoOperations *ops);
+#endif /* WITH_POLICY */
-/**
- * @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);
+#else
-/**
- * @function connection_Send
- * @abstract Sends the message on the connection
- * @return true if message sent, false if connection not up
- */
-bool connection_Send(const Connection *conn, Message *message);
+/* Accessors */
+static inline unsigned connection_get_id(const connection_t * connection);
-/**
- * @function connection_SendIOVBuffer
- * @abstract Sends an IOV buffer
- */
-bool connection_SendIOVBuffer(const Connection *conn, struct iovec *msg,
- size_t size);
+#define connection_id_is_valid(id) (id != CONNECTION_ID_UNDEFINED)
+#define connection_has_valid_id(C) (connection_id_is_valid(connection_get_id(C))
-/**
- * @function connection_SendBuffer
- * @abstract Sends a buffer
- */
-bool connection_SendBuffer(const Connection *conn, u8 * buffer, size_t length);
+static inline char * connection_get_name(const connection_t * connection);
-/**
- * Return the `IoOperations` instance associated with the specified `Connection`
- * instance.
- * @param [in] connection The allocated connection
- * @return a pointer to the IoOperations instance associated by th specified
- * connection.
- */
-IoOperations *connection_GetIoOperations(const Connection *conn);
+static inline face_type_t connection_get_type(const connection_t * connection);
-/**
- * Returns the unique identifier of the connection
- * Calls the underlying IoOperations to fetch the connection id
- * @param [in] connection The allocated connection
- * @return unsigned The unique connection id
- */
-unsigned connection_GetConnectionId(const Connection *conn);
+static inline address_pair_t * connection_get_pair(const connection_t * connection);
-/**
- * Returns the (remote, local) address pair that describes the connection
- * @param [in] connection The allocated connection
- * @return non-null The connection's remote and local address
- * @return null Should never return NULL
- */
-const AddressPair *connection_GetAddressPair(const Connection *conn);
+#define connection_get_local(C) (address_pair_local(connection_get_pair(C)))
+#define connection_get_remote(C) (address_pair_remote(connection_get_pair(C)))
-/**
- * Checks if the connection is in the "up" state
- * @param [in] connection The allocated connection
- * @return true The connection is in the "up" state
- * @return false The connection is not in the "up" state
- */
-bool connection_IsUp(const Connection *conn);
+static inline bool connection_is_up(const connection_t * connection);
-/**
- * Checks if the connection is to a Local/Loopback address
- *
- * A local connection is PF_LOCAL (PF_UNIX) and a loopback connection is
- * 127.0.0.0/8 or ::1 for IPv6.
- *
- * @param [in] connection The allocated connection
- *
- * @retval true The connection is local or loopback
- * @retval false The connection is not local or loopback
- */
-bool connection_IsLocal(const Connection *conn);
+static inline bool connection_is_local(const connection_t * connection);
-/**
- * Returns an opaque pointer representing the class of the Io Operations
- *
- * Returns an opaque pointer that an implementation can use to detect if
- * the connection is based on that class.
- *
- * @param [in] conn The Connection to analyze
- *
- * @return non-null An opaque pointer for each concrete implementation
- */
-const void *connection_Class(const Connection *conn);
+static inline face_state_t connection_get_state(const connection_t * connection);
+
+static inline void connection_set_state(connection_t * connection, face_state_t state);
+
+static inline face_state_t connection_get_admin_state(const connection_t * connection);
-bool connection_ReSend(const Connection *conn, Message *message,
- bool notification);
+static inline void connection_set_admin_state(connection_t * connection, face_state_t state);
-void connection_Probe(Connection *conn, uint8_t *probe);
+static inline const char * connection_get_interface_name(const connection_t * connection);
-void connection_HandleProbe(Connection *conn, uint8_t *message);
+#ifdef WITH_POLICY
-void connection_AllowWldrAutoStart(Connection *conn, bool allow);
+static inline uint32_t connection_get_priority(const connection_t * connection);
-void connection_EnableWldr(Connection *conn);
+static inline void connection_set_priority(connection_t * connection, uint32_t priority);
-void connection_DisableWldr(Connection *conn);
+static inline policy_tags_t connection_get_tags(const connection_t * connection);
-bool connection_HasWldr(const Connection *conn);
+static inline void connection_set_tags(connection_t * connection, policy_tags_t tags);
-bool connection_WldrAutoStartAllowed(const Connection *conn);
+#define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG)
-void connection_DetectLosses(Connection *conn, Message *message);
+#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG)
-void connection_HandleWldrNotification(Connection *conn, Message *message);
+#define connection_remove_tag(C, TAG) \
+do { \
+ policy_tags_t _conn_var(tags); \
+ _conn_var(tags) = connection_get_tags(C); \
+ policy_tags_remove(_conn_var(tags), (TAG)); \
+ connection_set_tags((C), _conn_var(tags)); \
+} while(0)
-connection_state_t connection_GetState(const Connection *conn);
+#define connection_clear_tags(C) connection_set_tags(C, POLICY_TAGS_EMPTY)
-void connection_SetState(Connection *conn, connection_state_t state);
+#endif /* WITH_POLICY */
-connection_state_t connection_GetAdminState(const Connection *conn);
+#endif
-void connection_SetAdminState(Connection *conn, connection_state_t admin_state);
+connection_t * connection_create(face_type_t type, const char * name,
+ const address_pair_t * pair, struct forwarder_s * forwarder);
-#ifdef WITH_POLICY
-uint32_t connection_GetPriority(const Connection *conn);
+int connection_initialize(connection_t * connection, face_type_t type, const char * name,
+ const char * interface_name, int fd, const address_pair_t * pair,
+ bool local, unsigned connection_id, struct forwarder_s * forwarder);
-void connection_SetPriority(Connection *conn, uint32_t priority);
-#endif /* WITH_POLICY */
+int connection_finalize(connection_t * connection);
-const char * connection_GetInterfaceName(const Connection * conn);
+int connection_send_packet(const connection_t * connection,
+ const uint8_t * packet, size_t size);
-#ifdef WITH_POLICY
-void connection_AddTag(Connection *conn, policy_tag_t tag);
-void connection_RemoveTag(Connection *conn, policy_tag_t tag);
-policy_tags_t connection_GetTags(const Connection *conn);
-void connection_SetTags(Connection *conn, policy_tags_t tags);
-void connection_ClearTags(Connection *conn);
-int connection_HasTag(const Connection *conn, policy_tag_t tag);
-#endif /* WITH_POLICY */
+bool connection_send(const connection_t * connection, msgbuf_t * msgbuf,
+ bool queue);
+
+size_t connection_process_buffer(connection_t * connection, const uint8_t * buffer, size_t size);
+
+/* WLDR */
+
+void connection_wldr_allow_autostart(connection_t * connection, bool value);
+
+bool connection_wldr_autostart_is_allowed(connection_t * connection);
+
+void connection_wldr_enable(connection_t * connection, bool value);
+
+bool connection_has_wldr(const connection_t * connection);
+
+void connection_wldr_detect_losses(const connection_t * connection, msgbuf_t * msgbuf);
+
+void connection_wldr_handle_notification(const connection_t * connection, msgbuf_t * msgbuf);
-#endif // connection_h
+#endif /* HICNLIGHT_CONNECTION_H */
diff --git a/hicn-light/src/hicn/core/connectionList.c b/hicn-light/src/hicn/core/connectionList.c
deleted file mode 100644
index d51a9aa..0000000
--- a/hicn-light/src/hicn/core/connectionList.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/core/connectionList.h>
-
-struct connection_list {
- PARCArrayList *listOfConnections;
-};
-
-static void connectionList_ArrayDestroyer(void **voidPtr) {
- Connection **entryPtr = (Connection **)voidPtr;
- connection_Release(entryPtr);
-}
-
-ConnectionList *connectionList_Create() {
- ConnectionList *list = parcMemory_AllocateAndClear(sizeof(ConnectionList));
- parcAssertNotNull(list, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ConnectionList));
- list->listOfConnections = parcArrayList_Create(connectionList_ArrayDestroyer);
- return list;
-}
-
-void connectionList_Destroy(ConnectionList **listPtr) {
- parcAssertNotNull(listPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listPtr, "Parameter must dereference to non-null pointer");
- ConnectionList *list = *listPtr;
- parcArrayList_Destroy(&list->listOfConnections);
- parcMemory_Deallocate((void **)&list);
- *listPtr = NULL;
-}
-
-void connectionList_Append(ConnectionList *list, Connection *entry) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- parcAssertNotNull(entry, "Parameter entry must be non-null");
-
- parcArrayList_Add(list->listOfConnections, connection_Acquire(entry));
-}
-
-size_t connectionList_Length(const ConnectionList *list) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- return parcArrayList_Size(list->listOfConnections);
-}
-
-Connection *connectionList_Get(ConnectionList *list, size_t index) {
- parcAssertNotNull(list, "Parameter list must be non-null");
- Connection *original =
- (Connection *)parcArrayList_Get(list->listOfConnections, index);
- return original;
-}
diff --git a/hicn-light/src/hicn/core/connectionList.h b/hicn-light/src/hicn/core/connectionList.h
deleted file mode 100644
index fbba9f6..0000000
--- a/hicn-light/src/hicn/core/connectionList.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file connectionList.h
- * @brief A typesafe list of Connection objects
- *
- * <#Detailed Description#>
- *
- */
-
-#ifndef connectionList_h
-#define connectionList_h
-
-struct connection_list;
-typedef struct connection_list ConnectionList;
-
-#include <hicn/core/connection.h>
-
-/**
- * Creates a lis of Connection
- *
- * @return non-null An allocated list
- * @return null An error
- */
-ConnectionList *connectionList_Create(void);
-
-/**
- * Destroys the list and all objects inside it
- */
-void connectionList_Destroy(ConnectionList **listPtr);
-
-/**
- * @function connectionList_Append
- * @abstract Adds a connection entry to the list.
- * @discussion
- * Acquires a reference to the passed entry and stores it in the list.
- */
-void connectionList_Append(ConnectionList *list, Connection *entry);
-
-/**
- * Returns the number of items on the list
- * @param [in] list The allocated list to check
- * @return number The number of items on the list
- */
-size_t connectionList_Length(const ConnectionList *list);
-
-/**
- * @function connectionList_Get
- * @abstract Returns the connection entry.
- * @discussion
- * Caller must not destroy the returned value. If you will store the
- * entry in your own data structure, you should acquire your own reference.
- * Will assert if you go beyond the end of the list.
- *
- */
-Connection *connectionList_Get(ConnectionList *list, size_t index);
-#endif // connectionList_h
diff --git a/hicn-light/src/hicn/core/connectionManager.c b/hicn-light/src/hicn/core/connectionManager.c
deleted file mode 100644
index 709f090..0000000
--- a/hicn-light/src/hicn/core/connectionManager.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * The Connection Manager sets itself up as a listener to the Messenger so it
- * can take action based on system events.
- *
- * The Connection Manager queues and then processes in a later time slice the
- * messages.
- *
- */
-
-#include <hicn/hicn-light/config.h>
-#include <hicn/core/connectionManager.h>
-#include <hicn/core/forwarder.h>
-#include <hicn/messenger/messenger.h>
-#include <hicn/messenger/messengerRecipient.h>
-#include <hicn/messenger/missiveDeque.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_Memory.h>
-
-#include <parc/assert/parc_Assert.h>
-
-struct connection_manager {
- Forwarder *forwarder;
- Logger *logger;
-
- MessengerRecipient *messengerRecipient;
-
- // we queue missives as they come in to process in our own
- // event timeslice
- MissiveDeque *missiveQueue;
-
- // for deferred queue processing
- PARCEventTimer *timerEvent;
-};
-
-/**
- * Receives missives from the messenger, queues them, and schedules our
- * execution
- *
- * We defer processing of missives to a later time slice
- */
-static void connectionManager_MessengerCallback(MessengerRecipient *recipient,
- Missive *missive);
-
-/**
- * Event callback
- *
- * This is our main run loop to process our queue of messages. It is scheduled
- * in {@link connectionManager_MessengerCallback} when the queue becomes
- * non-empty.
- *
- * When we are called here, we have exclusive use of the system, so we will not
- * create any message loops
- *
- * @param [in] fd unused, required for compliance with function prototype
- * @param [in] which_event unused, required for compliance with function
- * prototype
- * @param [in] connManagerVoidPtr A void* to ConnectionManager
- *
- */
-static void connectionManager_ProcessQueue(int fd, PARCEventType which_event,
- void *connManagerVoidPtr);
-
-static void connectionManager_ProcessClosedMissive(
- ConnectionManager *connManager, const Missive *missive);
-
-// ========================================================
-// Public API
-
-ConnectionManager *connectionManager_Create(Forwarder *forwarder) {
- ConnectionManager *connManager =
- parcMemory_AllocateAndClear(sizeof(ConnectionManager));
- parcAssertNotNull(connManager,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ConnectionManager));
- connManager->forwarder = forwarder;
- connManager->missiveQueue = missiveDeque_Create();
- connManager->logger = logger_Acquire(forwarder_GetLogger(forwarder));
-
- Messenger *messenger = forwarder_GetMessenger(connManager->forwarder);
-
- // creates the timer, but does not start it
- PARCEventScheduler *base =
- dispatcher_GetEventScheduler(forwarder_GetDispatcher(forwarder));
- connManager->timerEvent = parcEventTimer_Create(
- base, 0, connectionManager_ProcessQueue, connManager);
-
- connManager->messengerRecipient = messengerRecipient_Create(
- connManager, connectionManager_MessengerCallback);
- messenger_Register(messenger, connManager->messengerRecipient);
- return connManager;
-}
-
-void connectionManager_Destroy(ConnectionManager **managerPtr) {
- parcAssertNotNull(managerPtr, "Double pointer must be non-null");
- parcAssertNotNull(*managerPtr, "Double pointer must dereference to non-null");
-
- ConnectionManager *connManager = *managerPtr;
-
- Messenger *messenger = forwarder_GetMessenger(connManager->forwarder);
- parcEventTimer_Destroy(&(connManager->timerEvent));
- messenger_Unregister(messenger, connManager->messengerRecipient);
- messengerRecipient_Destroy(&connManager->messengerRecipient);
- missiveDeque_Release(&connManager->missiveQueue);
- logger_Release(&connManager->logger);
-
- parcMemory_Deallocate((void **)&connManager);
- *managerPtr = NULL;
-}
-
-// ========================================================
-// Internal Functions
-
-static void connectionManager_MessengerCallback(MessengerRecipient *recipient,
- Missive *missive) {
- ConnectionManager *connManager =
- messengerRecipient_GetRecipientContext(recipient);
-
- // we do not release our reference count, we store it until later
- // We are called with our own reference, so we do not need to acquire the
- // missive here.
- missiveDeque_Append(connManager->missiveQueue, missive);
-
- if (missiveDeque_Size(connManager->missiveQueue) == 1) {
- // When it becomes non-empty, schedule {@link
- // connectionManager_ProcessQueue}
- struct timeval immediateTimeout = {0, 0};
- parcEventTimer_Start(connManager->timerEvent, &immediateTimeout);
- }
-}
-
-static void connectionManager_ProcessQueue(int fd, PARCEventType which_event,
- void *connManagerVoidPtr) {
- ConnectionManager *connManager = (ConnectionManager *)connManagerVoidPtr;
-
- Missive *missive;
- while ((missive = missiveDeque_RemoveFirst(connManager->missiveQueue)) !=
- NULL) {
- switch (missive_GetType(missive)) {
- case MissiveType_ConnectionCreate:
- // hook to signal that a new connection was created
- break;
- case MissiveType_ConnectionUp:
- // hook to signal that a new connection is up
- break;
- case MissiveType_ConnectionDown:
- // hook to signal that a connection is down
- break;
- case MissiveType_ConnectionClosed:
- connectionManager_ProcessClosedMissive(connManager, missive);
- break;
- case MissiveType_ConnectionDestroyed:
- // hook to signal that a connection was destroyed
- break;
- default:
- parcTrapUnexpectedState("Missive %p of unknown type: %d",
- (void *)missive, missive_GetType(missive));
- }
- missive_Release(&missive);
- }
-}
-
-static void connectionManager_ProcessClosedMissive(
- ConnectionManager *connManager, const Missive *missive) {
- logger_Log(connManager->logger, LoggerFacility_Core, PARCLogLevel_Debug,
- __func__, "Processing CLOSED message for connid %u",
- missive_GetConnectionId(missive));
-
- ConnectionTable *table = forwarder_GetConnectionTable(connManager->forwarder);
- const Connection *conn =
- connectionTable_FindById(table, missive_GetConnectionId(missive));
-
- if (conn) {
- // this will destroy the connection if its the last reference count
- connectionTable_Remove(table, conn);
-
- // remove from FIB
- forwarder_RemoveConnectionIdFromRoutes(connManager->forwarder,
- missive_GetConnectionId(missive));
- }
-}
diff --git a/hicn-light/src/hicn/core/connectionManager.h b/hicn-light/src/hicn/core/connectionManager.h
deleted file mode 100644
index 34fee87..0000000
--- a/hicn-light/src/hicn/core/connectionManager.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file connectionManager.h
- * @brief The connection manager handles connection events, such as going down
- *
- * The connection manager listens to the event notification system. Based on
- * those events, the connection manager will take specific actions. This is
- * expected to be a singleton instantiated by the forwarder.
- *
- */
-
-#ifndef connectionManager_h
-#define connectionManager_h
-
-#include <hicn/core/forwarder.h>
-
-struct connection_manager;
-typedef struct connection_manager ConnectionManager;
-
-ConnectionManager *connectionManager_Create(Forwarder *forwarder);
-
-void connectionManager_Destroy(ConnectionManager **managerPtr);
-#endif // connectionManager_h
diff --git a/hicn-light/src/hicn/core/connectionTable.c b/hicn-light/src/hicn/core/connectionTable.c
deleted file mode 100644
index f8589c1..0000000
--- a/hicn-light/src/hicn/core/connectionTable.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header ConnectionTable
- * @abstract Records all the current connections and references to them
- * @discussion
- *
- */
-
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Hash.h>
-#include <parc/algol/parc_HashCodeTable.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_TreeRedBlack.h>
-#include <hicn/core/connectionTable.h>
-#include <hicn/io/addressPair.h>
-
-struct connection_table {
- // The main storage table that has a Destroy method.
- // The key is an unsigned int pointer. We use an unsigned int pointer
- // because we want to be able to lookup by the id alone, and not have to
- // have the IoOperations everywhere.
- PARCHashCodeTable *storageTableById;
-
- // The key is a AddressPair
- // It does not have a destroy method for the data or key,
- // as they are derived from the storage table.
- PARCHashCodeTable *indexByAddressPair;
-
- // An iterable stucture organized by connection id. The keys and
- // values are the same pointers as in storageTableById, so there
- // are no destructors in the tree.
- // The only reason to keep this tree is so we have an iterable list
- // of connections, which the hash table does not give us.
- PARCTreeRedBlack *listById;
-};
-
-static bool connectionTable_ConnectionIdEquals(const void *keyA,
- const void *keyB) {
- unsigned idA = *((unsigned *)keyA);
- unsigned idB = *((unsigned *)keyB);
- return (idA == idB);
-}
-
-static int connectionTable_ConnectionIdCompare(const void *keyA,
- const void *keyB) {
- unsigned idA = *((unsigned *)keyA);
- unsigned idB = *((unsigned *)keyB);
- if (idA < idB) {
- return -1;
- }
- if (idA > idB) {
- return +1;
- }
- return 0;
-}
-
-static bool connectionTable_AddressPairEquals(const void *keyA,
- const void *keyB) {
- const AddressPair *pairA = (const AddressPair *)keyA;
- const AddressPair *pairB = (const AddressPair *)keyB;
-
- return addressPair_Equals(pairA, pairB);
-}
-
-static HashCodeType connectionTable_ConnectionIdHashCode(const void *keyA) {
- unsigned idA = *((unsigned *)keyA);
- return parcHash32_Int32(idA);
-}
-
-static HashCodeType connectionTable_AddressPairHashCode(const void *keyA) {
- const AddressPair *pairA = (const AddressPair *)keyA;
- return addressPair_HashCode(pairA);
-}
-
-static void connectionTable_ConnectionIdDestroyer(void **dataPtr) {
- unsigned *idA = (unsigned *)*dataPtr;
- parcMemory_Deallocate((void **)&idA);
- *dataPtr = NULL;
-}
-
-static void connectionTable_ConnectionDestroyer(void **dataPtr) {
- connection_Release((Connection **)dataPtr);
-}
-
-ConnectionTable *connectionTable_Create() {
- size_t initialSize = 16384;
-
- ConnectionTable *conntable =
- parcMemory_AllocateAndClear(sizeof(ConnectionTable));
- parcAssertNotNull(conntable, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(ConnectionTable));
-
- conntable->storageTableById = parcHashCodeTable_Create_Size(
- connectionTable_ConnectionIdEquals, connectionTable_ConnectionIdHashCode,
- connectionTable_ConnectionIdDestroyer,
- connectionTable_ConnectionDestroyer, initialSize);
-
- // no key or data destroyer, this is an index into storageByid.
- conntable->indexByAddressPair = parcHashCodeTable_Create_Size(
- connectionTable_AddressPairEquals, connectionTable_AddressPairHashCode,
- NULL, NULL, initialSize);
-
- conntable->listById =
- parcTreeRedBlack_Create(connectionTable_ConnectionIdCompare,
- NULL, // key free
- NULL, // key copy
- NULL, // value equals
- NULL, // value free
- NULL); // value copy
-
- return conntable;
-}
-
-void connectionTable_Destroy(ConnectionTable **conntablePtr) {
- parcAssertNotNull(conntablePtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*conntablePtr,
- "Parameter must dereference to non-null pointer");
-
- ConnectionTable *conntable = *conntablePtr;
-
- parcTreeRedBlack_Destroy(&conntable->listById);
- parcHashCodeTable_Destroy(&conntable->indexByAddressPair);
- parcHashCodeTable_Destroy(&conntable->storageTableById);
- parcMemory_Deallocate((void **)&conntable);
- *conntablePtr = NULL;
-}
-
-/**
- * @function connectionTable_Add
- * @abstract Add a connection, takes ownership of memory
- */
-void connectionTable_Add(ConnectionTable *table, Connection *connection) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(connection, "Parameter connection must be non-null");
-
- unsigned *connectionIdKey = parcMemory_Allocate(sizeof(unsigned));
- parcAssertNotNull(connectionIdKey, "parcMemory_Allocate(%zu) returned NULL",
- sizeof(unsigned));
- *connectionIdKey = connection_GetConnectionId(connection);
-
- if (parcHashCodeTable_Add(table->storageTableById, connectionIdKey,
- connection)) {
- parcHashCodeTable_Add(table->indexByAddressPair,
- (void *)connection_GetAddressPair(connection),
- connection);
- parcTreeRedBlack_Insert(table->listById, connectionIdKey, connection);
- } else {
- parcTrapUnexpectedState(
- "Could not add connection id %u -- is it a duplicate?",
- *connectionIdKey);
- }
-}
-
-/**
- * @function connectionTable_Remove
- * @abstract Removes the connection, calling Destroy on our copy
- */
-void connectionTable_Remove(ConnectionTable *table,
- const Connection *connection) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- parcAssertNotNull(connection, "Parameter connection must be non-null");
-
- unsigned connid = connection_GetConnectionId(connection);
-
- parcTreeRedBlack_Remove(table->listById, &connid);
- parcHashCodeTable_Del(table->indexByAddressPair,
- connection_GetAddressPair(connection));
- parcHashCodeTable_Del(table->storageTableById, &connid);
-}
-
-void connectionTable_RemoveById(ConnectionTable *table, unsigned id) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- const Connection *connection = connectionTable_FindById(table, id);
- if (connection) {
- connectionTable_Remove(table, connection);
- }
-}
-
-const Connection *connectionTable_FindByAddressPair(ConnectionTable *table,
- const AddressPair *pair) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- return (Connection *)parcHashCodeTable_Get(table->indexByAddressPair, pair);
-}
-
-const Connection *connectionTable_FindById(const ConnectionTable *table,
- unsigned id) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- return (Connection *)parcHashCodeTable_Get(table->storageTableById, &id);
-}
-
-ConnectionList *connectionTable_GetEntries(const ConnectionTable *table) {
- parcAssertNotNull(table, "Parameter table must be non-null");
- ConnectionList *list = connectionList_Create();
-
- PARCArrayList *values = parcTreeRedBlack_Values(table->listById);
- for (size_t i = 0; i < parcArrayList_Size(values); i++) {
- Connection *original = parcArrayList_Get(values, i);
- connectionList_Append(list, original);
- }
- parcArrayList_Destroy(&values);
- return list;
-}
diff --git a/hicn-light/src/hicn/core/connectionTable.h b/hicn-light/src/hicn/core/connectionTable.h
deleted file mode 100644
index 548ef8e..0000000
--- a/hicn-light/src/hicn/core/connectionTable.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- */
-
-#ifndef connectionTable_h
-#define connectionTable_h
-
-#include <hicn/core/connection.h>
-#include <hicn/core/connectionList.h>
-#include <hicn/io/addressPair.h>
-#include <hicn/io/ioOperations.h>
-
-struct connection_table;
-typedef struct connection_table ConnectionTable;
-
-/**
- * Creates an empty connection table
- */
-ConnectionTable *connectionTable_Create(void);
-
-/**
- * Destroys the connection table
- * This will release the reference to all connections stored in the connection
- * table.
- * @param [in,out] conntablePtr Pointer to the allocated connection table, will
- * be NULL'd
- */
-void connectionTable_Destroy(ConnectionTable **conntablePtr);
-
-/**
- * @function connectionTable_Add
- * @abstract Add a connection, takes ownership of memory
- */
-void connectionTable_Add(ConnectionTable *table, Connection *connection);
-
-/**
- * @function connectionTable_Remove
- * @abstract Removes the connection, calling Destroy on our copy
- */
-void connectionTable_Remove(ConnectionTable *table,
- const Connection *connection);
-
-/**
- * Removes a connection from the connection table
- *
- * Looks up a connection by its connection ID and removes it from the connection
- * table. Removing the connection will call connection_Release() on the
- * connection object.
- *
- * @param [in] table The allocated connection table
- * @param [in] id The connection ID
- */
-void connectionTable_RemoveById(ConnectionTable *table, unsigned id);
-
-/**
- * Lookup a connection by the (local, remote) addres pair
- *
- * @param [in] table The allocated connection table
- * @param [in] pair The address pair to match, based on the inner values of the
- * local and remote addresses
- *
- * @retval non-null The matched conneciton
- * @retval null No match found or error
- */
-const Connection *connectionTable_FindByAddressPair(ConnectionTable *table,
- const AddressPair *pair);
-
-/**
- * @function connectionTable_FindById
- * @abstract Find a connection by its numeric id.
- * @return NULL if not found
- */
-const Connection *connectionTable_FindById(const ConnectionTable *table, unsigned id);
-
-/**
- * @function connectionTable_GetEntries
- * @abstract Returns a list of connections. They are reference counted copies
- * from the table.
- * @discussion
- * An allocated list of connections in the table. Each list entry is a
- * reference counted copy of the connection in the table, thus they are "live"
- * objects.
- */
-ConnectionList *connectionTable_GetEntries(const ConnectionTable *table);
-#endif // connectionTable_h
diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c
new file mode 100644
index 0000000..fd8013b
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_table.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file connection_table.c
+ * \brief Implementation of hICN connection table
+ */
+
+#include <hicn/core/connection.h>
+#include <hicn/core/connection_table.h>
+
+/* This is only used for first allocation, as the table is resizeable */
+#define DEFAULT_CONNECTION_TABLE_SIZE 64
+
+connection_table_t *
+connection_table_create(size_t elt_size, size_t max_elts)
+{
+ connection_table_t * table = malloc(sizeof(connection_table_t));
+ if (!table)
+ return NULL;
+
+ table->id_by_pair = kh_init_ct_pair();
+ table->id_by_name = kh_init_ct_name();
+ pool_init(table->connections, DEFAULT_CONNECTION_TABLE_SIZE);
+
+ return table;
+}
+
+void
+connection_table_free(connection_table_t * table)
+{
+ kh_destroy_ct_pair(table->id_by_pair);
+ kh_destroy_ct_name(table->id_by_name);
+ pool_free(table->connections);
+ free(table);
+}
+
+connection_t *
+connection_table_get_by_pair(const connection_table_t * table,
+ const address_pair_t * pair)
+{
+ khiter_t k = kh_get_ct_pair(table->id_by_pair, pair);
+ if (k == kh_end(table->id_by_pair))
+ return NULL;
+ return table->connections + kh_val(table->id_by_pair, k);
+}
+
+unsigned
+connection_table_get_id_by_name(const connection_table_t * table,
+ const char * name)
+{
+ khiter_t k = kh_get_ct_name(table->id_by_name, name);
+ if (k == kh_end(table->id_by_name))
+ return CONNECTION_ID_UNDEFINED;
+ return kh_val(table->id_by_name, k);
+}
+
+connection_t *
+connection_table_get_by_name(const connection_table_t * table,
+ const char * name)
+{
+ unsigned conn_id = connection_table_get_id_by_name(table, name);
+ if (!connection_id_is_valid(conn_id))
+ return NULL;
+ return table->connections + conn_id;
+}
+
+void
+connection_table_remove_by_id(connection_table_t * table, off_t id)
+{
+ /*
+ * Get the connection addresspair & name so as to be able to remove them
+ * from the hash table index
+ */
+ connection_t * connection = connection_table_at(table, id);
+ connection_table_deallocate(table, connection);
+}
diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h
new file mode 100644
index 0000000..c0406ce
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_table.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file connection_table.h
+ * \brief hICN connection_table
+ */
+
+/* Iterate on connection table : to remove all connections associated to a
+ * listener based on listen address */
+
+#ifndef HICN_CONNECTION_TABLE_H
+#define HICN_CONNECTION_TABLE_H
+
+//#include <hicn/base/common.h>
+#include <hicn/core/address_pair.h>
+#include <hicn/core/connection.h>
+#include <hicn/base/hash.h>
+#include <hicn/base/khash.h>
+#include <hicn/base/pool.h>
+
+#include <hicn/common.h>
+
+#define address_pair_hash(pair) (hash32(pair, sizeof(address_pair_t)))
+#define address_pair_hash_eq(a, b) (address_pair_hash(b) - address_pair_hash(a))
+
+KHASH_INIT(ct_pair, const address_pair_t *, unsigned, 0, address_pair_hash, address_pair_hash_eq);
+
+KHASH_INIT(ct_name, const char *, unsigned, 0, str_hash, str_hash_eq);
+
+/*
+ * The connection table is composed of :
+ * - a connection pool allowing connection access by id in constant time
+ * - a hash table allowing to perform lookups based on address pairs, to get a connection id.
+ *
+ * For fast lookup by ID, the connection table will point to the beginning of
+ * the pool / vector, holding all connections.
+ * The header will be prepended
+ */
+
+typedef struct {
+ kh_ct_pair_t * id_by_pair;
+ kh_ct_name_t * id_by_name;
+
+ connection_t * connections; // pool
+} connection_table_t;
+
+#define connection_table_allocate(table, conn, pair, name) \
+do { \
+ pool_get(table->connections, conn); \
+ off_t connection_id = conn - table->connections; \
+ int res; \
+ khiter_t k = kh_put_ct_pair(table->id_by_pair, pair, &res); \
+ kh_value(table->id_by_pair, k) = connection_id; \
+ if (name) { \
+ k = kh_put_ct_name(table->id_by_name, name, &res); \
+ kh_value(table->id_by_name, k) = connection_id; \
+ } \
+} while(0)
+
+#define connection_table_deallocate(table, conn) \
+do { \
+ const address_pair_t * pair = connection_get_pair(connection); \
+ khiter_t k = kh_get_ct_pair(table->id_by_pair, pair); \
+ if (k != kh_end(table->id_by_pair)) \
+ kh_del_ct_pair(table->id_by_pair, k); \
+ \
+ const char * name = connection_get_name(connection); \
+ if (name) { \
+ k = kh_get_ct_name(table->id_by_name, name); \
+ if (k != kh_end(table->id_by_name)) \
+ kh_del_ct_name(table->id_by_name, k); \
+ } \
+ \
+ pool_put(table->connections, conn); \
+} while(0) \
+
+#define connection_table_len(table) (pool_elts(table->connections))
+
+#define connection_table_validate_id(table, id) \
+ pool_validate_id((table)->connections, (id))
+
+#define connection_table_at(table, id) ((table)->connections + id)
+
+#define connection_table_get_connection_id(table, conn) \
+ (conn - table->connections)
+
+#define connection_table_foreach(table, conn, BODY) \
+ pool_foreach(table->connections, (conn), BODY)
+
+#define connection_table_enumerate(table, i, conn, BODY) \
+ pool_foreach(table->connections, (i), (conn), BODY)
+
+connection_table_t * connection_table_create();
+void connection_table_free(connection_table_t * table);
+
+#define connection_table_get_by_id(table, id) \
+ connection_table_validate_id((table), (id)) \
+ ? connection_table_at((table), (id)) : NULL;
+
+connection_t * connection_table_get_by_pair(const connection_table_t * table,
+ const address_pair_t * pair);
+
+unsigned connection_table_get_id_by_name(const connection_table_t * table,
+ const char * name);
+
+connection_t * connection_table_get_by_name(const connection_table_t * table,
+ const char * name);
+
+void connection_table_remove_by_id(connection_table_t * table, off_t id);
+
+//unsigned connection_table_add(connection_table_t * table, Connection * connection);
+
+#endif /* HICN_CONNECTION_TABLE_H */
diff --git a/hicn-light/src/hicn/core/connection_vft.c b/hicn-light/src/hicn/core/connection_vft.c
new file mode 100644
index 0000000..9efdd01
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_vft.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file connection_vft.c
+ * @brief Implementation of connection VFT
+ */
+
+#include "connection_vft.h"
+
+extern connection_ops_t connection_hicn;
+extern connection_ops_t connection_tcp;
+extern connection_ops_t connection_udp;
+
+const connection_ops_t * connection_vft[] = {
+ [FACE_TYPE_HICN] = &connection_hicn,
+ [FACE_TYPE_TCP] = &connection_tcp,
+ [FACE_TYPE_UDP] = &connection_udp,
+};
diff --git a/hicn-light/src/hicn/core/connection_vft.h b/hicn-light/src/hicn/core/connection_vft.h
new file mode 100644
index 0000000..589f395
--- /dev/null
+++ b/hicn-light/src/hicn/core/connection_vft.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file connection_vft.h
+ * @brief Connection VFT
+ */
+
+#ifndef HICNLIGHT_CONNECTION_VFT_H
+#define HICNLIGHT_CONNECTION_VFT_H
+
+#include "connection.h"
+
+typedef struct {
+ int (*initialize)(connection_t * connection);
+ void (*finalize)(connection_t * connection);
+ int (*get_socket)(const listener_t * listener, const address_t * local,
+ const address_t * remote, const char * interface_name);
+ int (*send)(const connection_t * connection, msgbuf_t * msgbuf, bool queue);
+ int (*send_packet)(const connection_t * connection,
+ const uint8_t * packet, size_t size);
+ void (*read_callback)(connection_t * connection, int fd, void * data);
+ size_t data_size;
+} connection_ops_t;
+
+#define DECLARE_CONNECTION(NAME) \
+const connection_ops_t connection_ ## NAME = { \
+ .initialize = connection_ ## NAME ## _initialize, \
+ .finalize = connection_ ## NAME ## _finalize, \
+ .get_socket = listener_ ## NAME ## _get_socket, \
+ .send = connection_ ## NAME ## _send, \
+ .send_packet = connection_ ## NAME ## _send_packet, \
+ .read_callback = connection_ ## NAME ## _read_callback, \
+ .data_size = sizeof(connection_ ## NAME ## _data_t), \
+};
+
+extern const connection_ops_t * connection_vft[];
+
+#endif /* HICNLIGHT_CONNECTION_VFT_H */
diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c
new file mode 100644
index 0000000..7ed2bd8
--- /dev/null
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file content_store.c
+ * \brief Implementation of hICN content_store
+ */
+
+#include <inttypes.h>
+#include <hicn/base/pool.h>
+#include <hicn/util/log.h>
+
+//#include <hicn/content_store/lru.h>
+
+#include "content_store.h"
+
+extern const content_store_ops_t content_store_lru;
+
+const content_store_ops_t * const content_store_vft[] = {
+ [CONTENT_STORE_TYPE_LRU] = &content_store_lru,
+};
+
+// XXX TODO replace by a single packet cache
+// XXX TODO per cs type entry data too !
+// XXX TODO getting rid of logger and the need to acquire
+// XXX TODO separate cs from vft, same with strategy
+
+#define content_store_entry_from_msgbuf(entry, msgbuf) \
+do { \
+ (entry)->hasExpiryTimeTicks = msgbuf_HasContentExpiryTime(msgbuf); \
+ if ((entry)->hasExpiryTimeTicks) \
+ (entry)->expiryTimeTicks = msgbuf_GetContentExpiryTimeTicks(msgbuf); \
+} while(0)
+
+
+content_store_t *
+content_store_create(content_store_type_t type, size_t max_elts)
+{
+ content_store_t * cs = malloc(sizeof(content_store_t));
+ if (!cs)
+ goto ERR_MALLOC;
+ if (!CONTENT_STORE_TYPE_VALID(type))
+ goto ERR_TYPE;
+ cs->type = type;
+
+ // XXX TODO an entry = data + metadata specific to each policy
+ pool_init(cs->entries, max_elts);
+
+ // data
+ // options
+ // stats
+
+
+ // index by name
+ cs->index_by_name = kh_init(cs_name);
+
+ cs->index_by_expiry_time = NULL;
+ if (!cs->index_by_expiry_time) {
+ ERROR("Could not create index (expiry time)");
+ goto ERR_INDEX_EXPIRY;
+ }
+
+
+ // XXX indices specific to each policy => vft
+ // index by expiration time
+ // lru ?
+
+ content_store_vft[type]->initialize(cs);
+
+ERR_INDEX_EXPIRY:
+ // XXX TODO
+ERR_TYPE:
+ERR_MALLOC:
+ return NULL;
+}
+
+void
+content_store_free(content_store_t * cs)
+{
+ content_store_vft[cs->type]->finalize(cs);
+
+ if (cs->index_by_expiry_time)
+ ; //listTimeOrdered_Release(&(store->indexByExpirationTime));
+}
+
+void content_store_clear(content_store_t * cs)
+{
+ // XXX TODO
+}
+
+msgbuf_t *
+content_store_match(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now)
+{
+ assert(cs);
+ assert(msgbuf);
+ assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+
+ /* Lookup entry by name */
+ khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
+ if (k == kh_end(cs->index_by_name))
+ return NULL;
+ content_store_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
+ assert(entry);
+
+ /* Remove any expired entry */
+ if (content_store_entry_has_expiry_time(entry) &&
+ content_store_entry_expiry_time(entry) < now) {
+ // the entry is expired, we can remove it
+ content_store_remove_entry(cs, entry);
+ goto NOT_FOUND;
+ }
+
+ cs->stats.lru.countHits++;
+
+#if 0 // XXX
+ contentStoreEntry_MoveToHead(entry);
+#endif
+
+ DEBUG("CS %p LRU match %p (hits %" PRIu64 ", misses %" PRIu64 ")",
+ cs, msgbuf, cs->stats.lru.countHits, cs->stats.lru.countMisses);
+ return content_store_entry_message(entry);
+
+NOT_FOUND:
+ cs->stats.lru.countMisses++;
+
+ DEBUG("ContentStoreLRU %p missed msgbuf %p (hits %" PRIu64 ", misses %" PRIu64 ")",
+ cs, msgbuf, cs->stats.lru.countHits, cs->stats.lru.countMisses);
+ return NULL;
+}
+
+void
+content_store_add(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now)
+{
+ assert(cs);
+ assert(msgbuf);
+ assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA);
+
+ content_store_entry_t * entry = NULL;
+
+ /* borrow from content_store_lru_add_entry */
+
+ content_store_vft[cs->type]->add_entry(cs, entry);
+}
+
+void
+content_store_remove_entry(content_store_t * cs, content_store_entry_t * entry)
+{
+ assert(cs);
+ assert(entry);
+
+ if (content_store_entry_has_expiry_time(entry))
+ ; // XXX TODO listTimeOrdered_Remove(store->indexByExpirationTime, entryToPurge);
+
+ msgbuf_t * msgbuf = content_store_entry_message(entry);
+ khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
+ if (k != kh_end(cs->index_by_name))
+ kh_del(cs_name, cs->index_by_name, k);
+
+ // This will take care of LRU entry for instance
+ content_store_vft[cs->type]->remove_entry(cs, entry);
+
+ //store->objectCount--;
+ pool_put(cs->entries, entry);
+
+}
+//
+// XXX TODO what is the difference between purge and remove ?
+bool
+content_store_remove(content_store_t * cs, msgbuf_t * msgbuf)
+{
+ assert(cs);
+ assert(msgbuf);
+ assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA);
+
+ /* Lookup entry by name */
+ khiter_t k = kh_get_cs_name(cs->index_by_name, msgbuf_get_name(msgbuf));
+ if (k == kh_end(cs->index_by_name))
+ return false;
+
+ content_store_entry_t * entry = cs->entries + kh_val(cs->index_by_name, k);
+ assert(entry);
+
+ content_store_remove_entry(cs, entry);
+ return true;
+}
+
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
new file mode 100644
index 0000000..1a339f4
--- /dev/null
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -0,0 +1,125 @@
+#ifndef HICNLIGHT_CONTENT_STORE_H
+#define HICNLIGHT_CONTENT_STORE_H
+
+#include <hicn/base/khash.h>
+#include <hicn/base/pool.h>
+#include <hicn/core/msgbuf.h>
+#include <hicn/core/name.h>
+#include <hicn/content_store/lru.h>
+
+typedef struct {
+ msgbuf_t * message;
+ //ListLruEntry *lruEntry;
+ bool hasExpiryTimeTicks;
+ uint64_t expiryTimeTicks; // single value for both ? 0 allowed ?
+} content_store_entry_t;
+
+#define content_store_entry_message(entry) ((entry)->message)
+#define content_store_entry_has_expiry_time(entry) ((entry)->hasExpiryTimeTicks)
+#define content_store_entry_expiry_time(entry) ((entry)->expiryTimeTicks)
+
+typedef enum {
+ CONTENT_STORE_TYPE_UNDEFINED,
+ CONTENT_STORE_TYPE_LRU,
+ CONTENT_STORE_TYPE_N,
+} content_store_type_t;
+
+#define CONTENT_STORE_TYPE_VALID(type) \
+ (type != CONTENT_STORE_TYPE_UNDEFINED) && \
+ (type != CONTENT_STORE_TYPE_N)
+
+typedef struct {
+ /* The maximum allowed expiry time (will never be exceeded). */
+ uint64_t max_expiry_time; // XXX part of lru ?
+} content_store_options_t;
+
+typedef union {
+ content_store_lru_stats_t lru;
+} content_store_stats_t;
+
+// XXX TODO
+#define name_hash(name) (name_HashCode(name))
+#define name_hash_eq(a, b) (name_hash(b) - name_hash(a))
+
+KHASH_INIT(cs_name, const Name *, unsigned, 0, name_hash, name_hash_eq);
+
+typedef struct {
+ content_store_type_t type;
+
+ // XXX TODO api to dynamically set max size
+ content_store_entry_t * entries; // pool
+
+ kh_cs_name_t * index_by_name;
+
+ void * index_by_expiry_time;
+ //ListTimeOrdered *indexByExpirationTime;
+
+
+ void * data; // per cs type data
+ void * options;
+ content_store_stats_t stats;
+} content_store_t;
+
+content_store_t * content_store_create(content_store_type_t type, size_t max_elts);
+
+void content_store_free(content_store_t * cs);
+
+void content_store_clear(content_store_t * cs);
+
+msgbuf_t * content_store_match(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now);
+
+void content_store_add(content_store_t * cs, msgbuf_t * msgbuf, uint64_t now);
+
+void content_store_remove_entry(content_store_t * cs, content_store_entry_t * entry);
+
+bool content_store_remove(content_store_t * cs, msgbuf_t * msgbuf);
+
+#define content_store_size(content_store) (pool_elts(cs->entries))
+
+void content_store_purge_entry(content_store_t * cs, content_store_entry_t * entry);
+
+typedef struct {
+
+ const char * name;
+
+ void (*initialize)(content_store_t * cs);
+
+ void (*finalize)(content_store_t * cs);
+
+ /**
+ * 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.
+ */
+ // XXX Do we always get now before adding ?
+ bool (*add_entry)(content_store_t * cs, content_store_entry_t * entry);
+
+ /**
+ * 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.
+ */
+ void (*remove_entry)(content_store_t * cs, content_store_entry_t * entry);
+
+} content_store_ops_t;
+
+extern const content_store_ops_t * const content_store_vft[];
+
+#define DECLARE_CONTENT_STORE(NAME) \
+ const content_store_ops_t content_store_ ## NAME = { \
+ .name = #NAME, \
+ .initialize = content_store_ ## NAME ## _initialize, \
+ .finalize = content_store_ ## NAME ## _finalize, \
+ .add_entry = content_store_ ## NAME ## _add_entry, \
+ .remove_entry = content_store_ ## NAME ## _remove_entry, \
+ }
+
+#endif /* HICNLIGHT_CONTENT_STORE_H */
diff --git a/hicn-light/src/hicn/core/dispatcher.c b/hicn-light/src/hicn/core/dispatcher.c
deleted file mode 100644
index 59951e9..0000000
--- a/hicn-light/src/hicn/core/dispatcher.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header dispatcher.c
- * @abstract Event dispatcher for hicn-light. Uses parcEvent
- * @discussion
- * Wraps the functions we use in parcEvent, along with StreamBuffer and
- * Message. The dispatcher is the event loop, so it manages things like signals,
- * timers, and network events.
- */
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <hicn/hicn-light/config.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <parc/algol/parc_EventQueue.h>
-#include <parc/algol/parc_EventTimer.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <hicn/core/dispatcher.h>
-
-#include <pthread.h>
-
-#ifndef INPORT_ANY
-#define INPORT_ANY 0
-#endif
-
-struct dispatcher {
- PARCEventScheduler *Base;
- Logger *logger;
-};
-
-// ==========================================
-// Public API
-
-PARCEventScheduler *dispatcher_GetEventScheduler(Dispatcher *dispatcher) {
- return dispatcher->Base;
-}
-
-Dispatcher *dispatcher_Create(Logger *logger) {
- Dispatcher *dispatcher = parcMemory_AllocateAndClear(sizeof(Dispatcher));
- parcAssertNotNull(dispatcher,
- "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(Dispatcher));
-
- dispatcher->Base = parcEventScheduler_Create();
- dispatcher->logger = logger_Acquire(logger);
-
- parcAssertNotNull(dispatcher->Base,
- "Got NULL from parcEventScheduler_Create()");
-
- return dispatcher;
-}
-
-void dispatcher_Destroy(Dispatcher **dispatcherPtr) {
- parcAssertNotNull(dispatcherPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*dispatcherPtr,
- "Parameter must dereference to non-null pointer");
- Dispatcher *dispatcher = *dispatcherPtr;
-
- logger_Release(&dispatcher->logger);
- parcEventScheduler_Destroy(&(dispatcher->Base));
- parcMemory_Deallocate((void **)&dispatcher);
- *dispatcherPtr = NULL;
-}
-
-void dispatcher_Stop(Dispatcher *dispatcher) {
- struct timeval delay = {0, 1000};
-
- parcEventScheduler_Stop(dispatcher->Base, &delay);
-}
-
-void dispatcher_Run(Dispatcher *dispatcher) {
- parcAssertNotNull(dispatcher, "Parameter must be non-null");
-
- parcEventScheduler_Start(dispatcher->Base, 0);
-}
-
-void dispatcher_RunDuration(Dispatcher *dispatcher, struct timeval *duration) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(duration, "Parameter duration must be non-null");
-
- parcEventScheduler_Stop(dispatcher->Base, duration);
- parcEventScheduler_Start(dispatcher->Base, 0);
-}
-
-void dispatcher_RunCount(Dispatcher *dispatcher, unsigned count) {
- parcAssertNotNull(dispatcher, "Parameter must be non-null");
-
- for (unsigned i = 0; i < count; i++) {
- parcEventScheduler_Start(dispatcher->Base,
- PARCEventSchedulerDispatchType_LoopOnce);
- }
-}
-
-PARCEventSocket *dispatcher_CreateListener(Dispatcher *dispatcher,
- PARCEventSocket_Callback *callback,
- void *user_data, int backlog,
- const struct sockaddr *sa,
- int socklen) {
- PARCEventSocket *listener = parcEventSocket_Create(
- dispatcher->Base, callback, NULL, user_data, sa, socklen);
- if (listener == NULL) {
- perror("Problem creating listener");
- }
- return listener;
-}
-
-void dispatcher_DestroyListener(Dispatcher *dispatcher,
- PARCEventSocket **listenerPtr) {
- parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*listenerPtr,
- "Parameter must dereference to non-null pointer");
- parcEventSocket_Destroy(listenerPtr);
-}
-
-PARCEventQueue *dispatcher_CreateStreamBufferFromSocket(Dispatcher *dispatcher,
- SocketType fd) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- PARCEventQueue *buffer = parcEventQueue_Create(
- dispatcher->Base, fd,
- PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks);
- parcAssertNotNull(buffer,
- "Got null from parcEventBufver_Create for socket %d", fd);
- return buffer;
-}
-
-PARCEventTimer *dispatcher_CreateTimer(Dispatcher *dispatcher, bool isPeriodic,
- PARCEvent_Callback *callback,
- void *userData) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(callback, "Parameter callback must be non-null");
-
- PARCEventType flags = 0;
- if (isPeriodic) {
- flags |= PARCEventType_Persist;
- }
- PARCEventTimer *event =
- parcEventTimer_Create(dispatcher->Base, flags, callback, userData);
- return event;
-}
-
-void dispatcher_StartTimer(Dispatcher *dispatcher, PARCEventTimer *timerEvent,
- struct timeval *delay) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(timerEvent, "Parameter timerEvent must be non-null");
- int failure = parcEventTimer_Start(timerEvent, delay);
- parcAssertFalse(failure < 0, "Error starting timer event %p: (%d) %s",
- (void *)timerEvent, errno, strerror(errno));
-}
-
-void dispatcher_StopTimer(Dispatcher *dispatcher, PARCEventTimer *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEventTimer_Stop(event);
- parcAssertFalse(failure < 0, "Error stopping signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-void dispatcher_DestroyTimerEvent(Dispatcher *dispatcher,
- PARCEventTimer **eventPtr) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(eventPtr,
- "Parameter eventPtr must be non-null double pointer");
- parcAssertNotNull(*eventPtr,
- "Paramter eventPtr must dereference to non-null pointer");
-
- parcEventTimer_Destroy(eventPtr);
- eventPtr = NULL;
-}
-
-PARCEvent *dispatcher_CreateNetworkEvent(Dispatcher *dispatcher,
- bool isPersistent,
- PARCEvent_Callback *callback,
- void *userData, int fd) {
- short flags = PARCEventType_Timeout | PARCEventType_Read;
- if (isPersistent) {
- flags |= PARCEventType_Persist;
- }
-
- PARCEvent *event =
- parcEvent_Create(dispatcher->Base, fd, flags, callback, userData);
- parcAssertNotNull(event, "Got null from parcEvent_Create for socket %d", fd);
- return event;
-}
-
-void dispatcher_DestroyNetworkEvent(Dispatcher *dispatcher,
- PARCEvent **eventPtr) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(eventPtr,
- "Parameter eventPtr must be non-null double pointer");
- parcAssertNotNull(*eventPtr,
- "Paramter eventPtr must dereference to non-null pointer");
-
- parcEvent_Destroy(eventPtr);
- eventPtr = NULL;
-}
-
-void dispatcher_StartNetworkEvent(Dispatcher *dispatcher, PARCEvent *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEvent_Start(event);
- parcAssertFalse(failure < 0, "Error starting signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-void dispatcher_StopNetworkEvent(Dispatcher *dispatcher, PARCEvent *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEvent_Stop(event);
- parcAssertFalse(failure < 0, "Error stopping signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-PARCEventSignal *dispatcher_CreateSignalEvent(
- Dispatcher *dispatcher, PARCEventSignal_Callback *callback, void *userData,
- int signal) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(callback, "Parameter callback must be non-null");
-
- PARCEventSignal *event = parcEventSignal_Create(
- dispatcher->Base, signal, PARCEventType_Signal | PARCEventType_Persist,
- callback, userData);
- parcAssertNotNull(event,
- "Got null event when creating signal catcher for signal %d",
- signal);
-
- return event;
-}
-
-void dispatcher_DestroySignalEvent(Dispatcher *dispatcher,
- PARCEventSignal **eventPtr) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(eventPtr,
- "Parameter eventPtr must be non-null double pointer");
- parcAssertNotNull(*eventPtr,
- "Paramter eventPtr must dereference to non-null pointer");
-
- parcEventSignal_Destroy(eventPtr);
- eventPtr = NULL;
-}
-
-void dispatcher_StartSignalEvent(Dispatcher *dispatcher,
- PARCEventSignal *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEventSignal_Start(event);
- parcAssertFalse(failure < 0, "Error starting signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-void dispatcher_StopSignalEvent(Dispatcher *dispatcher,
- PARCEventSignal *event) {
- parcAssertNotNull(dispatcher, "Parameter dispatcher must be non-null");
- parcAssertNotNull(event, "Parameter event must be non-null");
-
- int failure = parcEventSignal_Stop(event);
- parcAssertFalse(failure < 0, "Error stopping signal event %p: (%d) %s",
- (void *)event, errno, strerror(errno));
-}
-
-/**
- * Bind to a local address/port then connect to peer.
- */
-static bool dispatcher_StreamBufferBindAndConnect(Dispatcher *dispatcher,
- PARCEventQueue *buffer,
- struct sockaddr *localSock,
- socklen_t localSockLength,
- struct sockaddr *remoteSock,
- socklen_t remoteSockLength) {
- // we need to bind, then connect. Special operation, so we make our
- // own fd then pass it off to the buffer event
-
-#ifndef _WIN32
- int fd = socket(localSock->sa_family, SOCK_STREAM, 0);
- if (fd < 0) {
- perror("socket");
- return -1;
- }
-
- // Set non-blocking flag
- int flags = fcntl(fd, F_GETFL, NULL);
- if (flags < 0) {
- perror("F_GETFL");
- close(fd);
- return -1;
- }
- int failure = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- if (failure) {
- perror("F_SETFL");
- close(fd);
- return -1;
- }
-
- failure = bind(fd, localSock, localSockLength);
- if (failure) {
- perror("bind");
- close(fd);
- return false;
- }
-
- parcEventQueue_SetFileDescriptor(buffer, fd);
-
- failure = parcEventQueue_ConnectSocket(buffer, remoteSock, remoteSockLength);
- if (failure && (errno != EINPROGRESS)) {
- perror("connect");
- close(fd);
- return false;
- }
-#else
- SOCKET fd = socket(localSock->sa_family, SOCK_STREAM, 0);
- if (fd == INVALID_SOCKET) {
- perror("socket");
- return -1;
- }
-
- // Set non-blocking flag
- u_long mode = 1;
- int result = ioctlsocket(fd, FIONBIO, &mode);
- if (result == NO_ERROR) {
- perror("ioctlsocket error");
- closesocket(fd);
- WSACleanup();
- return -1;
- }
-
- int failure = bind(fd, localSock, (int)localSockLength);
- if (failure) {
- perror("bind");
- closesocket(fd);
- WSACleanup();
- return false;
- }
-
- parcEventQueue_SetFileDescriptor(buffer, (int)fd);
-
- failure = parcEventQueue_ConnectSocket(buffer, remoteSock, remoteSockLength);
- if (failure && (errno != EINPROGRESS)) {
- perror("connect");
- closesocket(fd);
- WSACleanup();
- return false;
- }
-#endif
-
- return true;
-}
-
-/**
- * Connect to an INET peer
- * @return NULL on error, otherwise a streambuffer
- */
-static PARCEventQueue *dispatcher_StreamBufferConnect_INET(
- Dispatcher *dispatcher, const Address *localAddress,
- const Address *remoteAddress) {
- struct sockaddr_in localSock, remoteSock;
- addressGetInet(localAddress, &localSock);
- addressGetInet(remoteAddress, &remoteSock);
-
- PARCEventQueue *buffer = parcEventQueue_Create(
- dispatcher->Base, -1, PARCEventQueueOption_CloseOnFree);
- parcAssertNotNull(buffer, "got null buffer from parcEventQueue_Create()");
-
- bool success = dispatcher_StreamBufferBindAndConnect(
- dispatcher, buffer, (struct sockaddr *)&localSock, sizeof(localSock),
- (struct sockaddr *)&remoteSock, sizeof(remoteSock));
- if (!success) {
- parcEventQueue_Destroy(&buffer);
- buffer = NULL;
- }
-
- return buffer;
-}
-
-/**
- * Connect to an INET peer
- * @return NULL on error, otherwise a streambuffer
- */
-static PARCEventQueue *
-// static StreamBuffer *
-dispatcher_StreamBufferConnect_INET6(Dispatcher *dispatcher,
- const Address *localAddress,
- const Address *remoteAddress) {
- struct sockaddr_in6 localSock, remoteSock;
- addressGetInet6(localAddress, &localSock);
- addressGetInet6(remoteAddress, &remoteSock);
-
- PARCEventQueue *buffer = parcEventQueue_Create(
- dispatcher->Base, -1, PARCEventQueueOption_CloseOnFree);
- parcAssertNotNull(buffer, "got null buffer from parcEventQueue_Create()");
-
- bool success = dispatcher_StreamBufferBindAndConnect(
- dispatcher, buffer, (struct sockaddr *)&localSock, sizeof(localSock),
- (struct sockaddr *)&remoteSock, sizeof(remoteSock));
- if (!success) {
- parcEventQueue_Destroy(&buffer);
- buffer = NULL;
- }
-
- return buffer;
-}
-
-PARCEventQueue *dispatcher_StreamBufferConnect(Dispatcher *dispatcher,
- const AddressPair *pair) {
- const Address *localAddress = addressPair_GetLocal(pair);
- const Address *remoteAddress = addressPair_GetRemote(pair);
-
- // they must be of the same address family
- if (addressGetType(localAddress) != addressGetType(remoteAddress)) {
- char message[2048];
- char *localAddressString = addressToString(localAddress);
- char *remoteAddressString = addressToString(remoteAddress);
- snprintf(message, 2048,
- "Remote address not same type as local address, expected %d got "
- "%d\nlocal %s remote %s",
- addressGetType(localAddress), addressGetType(remoteAddress),
- localAddressString, remoteAddressString);
-
- parcMemory_Deallocate((void **)&localAddressString);
- parcMemory_Deallocate((void **)&remoteAddressString);
-
- parcAssertTrue(
- addressGetType(localAddress) == addressGetType(remoteAddress), "%s",
- message);
- }
-
- address_type type = addressGetType(localAddress);
-
- PARCEventQueue *result = NULL;
-
- switch (type) {
- case ADDR_INET:
- return dispatcher_StreamBufferConnect_INET(dispatcher, localAddress,
- remoteAddress);
- break;
- case ADDR_INET6:
- return dispatcher_StreamBufferConnect_INET6(dispatcher, localAddress,
- remoteAddress);
- break;
- default:
- parcTrapIllegalValue(type, "local address unsupported address type: %d",
- type);
- }
- return result;
-}
diff --git a/hicn-light/src/hicn/core/dispatcher.h b/hicn-light/src/hicn/core/dispatcher.h
deleted file mode 100644
index e5c2df3..0000000
--- a/hicn-light/src/hicn/core/dispatcher.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @header hicn-light Dispatcher
- * @abstract The dispatcher is the event loop run by Forwarder.
- * @discussion
- * These functions manage listeners, timers, and network events inside
- * the event loop.
- *
- * Curently, it is a thin wrapper around an event so we don't have to
- * expose that implementation detail to other modules.
- *
- */
-
-#ifndef dispatcher_h
-#define dispatcher_h
-
-#ifndef _WIN32
-#include <sys/socket.h>
-#endif
-#include <stdbool.h>
-
-struct dispatcher;
-typedef struct dispatcher Dispatcher;
-
-#include <parc/algol/parc_Event.h>
-#include <parc/algol/parc_EventQueue.h>
-#include <parc/algol/parc_EventScheduler.h>
-#include <parc/algol/parc_EventSignal.h>
-#include <parc/algol/parc_EventSocket.h>
-#include <parc/algol/parc_EventTimer.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/core/logger.h>
-
-PARCEventScheduler *dispatcher_GetEventScheduler(Dispatcher *dispatcher);
-/**
- * Creates an event dispatcher
- *
- * Event dispatcher based on PARCEvent
- *
- * @return non-null Allocated event dispatcher
- * @return null An error
- */
-Dispatcher *dispatcher_Create(Logger *logger);
-
-/**
- * Destroys event dispatcher
- *
- * Caller is responsible for destroying call events before destroying
- * the event dispatcher.
- */
-void dispatcher_Destroy(Dispatcher **dispatcherPtr);
-
-/**
- * @function dispatcher_Stop
- * @abstract Called from a different thread, tells the dispatcher to stop
- * @discussion
- * Called from a user thread or from an interrupt handler.
- * Does not block. Use <code>dispatcher_WaitForStopped()</code> to
- * block until stopped after calling this.
- */
-void dispatcher_Stop(Dispatcher *dispatcher);
-
-/**
- * @function dispatcher_WaitForStopped
- * @abstract Blocks until dispatcher in stopped state
- * @discussion
- * Used after <code>dispatcher_Stop()</code> to wait for stop.
- */
-void dispatcher_WaitForStopped(Dispatcher *dispatcher);
-
-/**
- * @function dispatcher_Run
- * @abstract Runs the forwarder, blocks.
- */
-void dispatcher_Run(Dispatcher *dispatcher);
-
-/**
- * @function dispatcher_RunDuration
- * @abstract Runs forwarder for at most duration, blocks.
- * @discussion
- * Blocks running the forwarder for a duration. May be called
- * iteratively to keep running. Duration is a minimum, actual
- * runtime may be slightly longer.
- */
-void dispatcher_RunDuration(Dispatcher *dispatcher, struct timeval *duration);
-
-/**
- * @header dispatcher_RunCount
- * @abstract Run the event loop for the given count cycles
- * @discussion
- * Runs the event loop for the given number of cycles, blocking
- * until done. May be called sequentially over and over.
- *
- */
-void dispatcher_RunCount(Dispatcher *dispatcher, unsigned count);
-
-typedef int SocketType;
-
-typedef struct evconnlistener Listener;
-
-/**
- * @typedef ListenerCallback
- * @abstract Callback function typedef for a stream listener
- *
- * @constant listener is the object created by <code>forwarder_NewBind()</code>
- * that received the client connection
- * @constant client_socket is the client socket
- * @constant user_data is the user_data passed to
- * <code>forwarder_NewBind()</code>
- * @constant client_addr is the client address
- * @constant socklen is the length of client_addr
- * @discussion <#Discussion#>
- */
-typedef void(ListenerCallback)(Listener *listener, SocketType client_socket,
- struct sockaddr *client_addr, int socklen,
- void *user_data);
-
-/**
- * @header forwarder_NewBind
- * @abstract Allocate a new stream listener
- * @discussion
- * The server socket will be freed when closed and will be reusable.
- *
- * @param forwarder that owns the event loop
- * @param cb is the callback for a new connection
- * @param user_data is opaque user data passed to the callback
- * @param backlog is the listen() depth, may use -1 for a default value
- * @param sa is the socket address to bind to (INET, INET6, LOCAL)
- * @param socklen is the sizeof the actual sockaddr (e.g. sizeof(sockaddr_un))
- */
-PARCEventSocket *dispatcher_CreateListener(Dispatcher *dispatcher,
- PARCEventSocket_Callback *callback,
- void *user_data, int backlog,
- const struct sockaddr *sa,
- int socklen);
-
-void dispatcher_DestroyListener(Dispatcher *dispatcher,
- PARCEventSocket **listenerPtr);
-
-typedef struct event TimerEvent;
-typedef struct event NetworkEvent;
-typedef struct event SignalEvent;
-
-/**
- * @typedef EventCallback
- * @abstract A network event or a timer callback
- * @constant fd The file descriptor associated with the event, may be -1 for
- * timers
- * @constant which_event is a bitmap of the EventType
- * @constant user_data is the user_data passed to
- * <code>Forwarder_CreateEvent()</code>
- */
-typedef void(EventCallback)(SocketType fd, short which_event, void *user_data);
-
-/**
- * @function dispatcher_CreateTimer
- * @abstract Creates a Event for use as a timer.
- * @discussion
- *
- * When created, the timer is idle and you need to call
- * <code>forwarder_StartTimer()</code>
- *
- * @param isPeriodic means the timer will fire repeatidly, otherwise it is a
- * one-shot and needs to be set again with <code>dispatcher_StartTimer()</code>
- */
-PARCEventTimer *dispatcher_CreateTimer(Dispatcher *dispatcher, bool isPeriodic,
- PARCEvent_Callback *callback,
- void *userData);
-
-/**
- * @function dispatcher_StartTimer
- * @abstract Starts the timer with the given delay.
- * @discussion
- * If the timer is periodic, it will keep firing with the given delay
- */
-void dispatcher_StartTimer(Dispatcher *dispatcher, PARCEventTimer *timerEvent,
- struct timeval *delay);
-
-void dispatcher_StopTimer(Dispatcher *dispatcher, PARCEventTimer *timerEvent);
-
-/**
- * @function dispatcher_DestroyTimerEvent
- * @abstract Cancels the timer and frees the event
- */
-void dispatcher_DestroyTimerEvent(Dispatcher *dispatcher,
- PARCEventTimer **eventPtr);
-
-/**
- * @function dispatcher_CreateNetworkEvent
- * @abstract Creates a network event callback on the socket
- * @discussion
- * May be used on any sort of file descriptor or socket. The event is edge
- * triggered and non-reentrent. This means you need to drain the events off the
- * socket, as the callback will not be called again until a new event arrives.
- *
- * When created, the event is idle and you need to call
- * <code>forwarder_StartNetworkEvent()</code>
- *
- * @param isPersistent means the callback will keep firing with new events,
- * otherwise its a one-shot
- * @param fd is the socket to monitor
- */
-PARCEvent *dispatcher_CreateNetworkEvent(Dispatcher *dispatcher,
- bool isPersistent,
- PARCEvent_Callback *callback,
- void *userData, int fd);
-
-void dispatcher_StartNetworkEvent(Dispatcher *dispatcher, PARCEvent *event);
-void dispatcher_StopNetworkEvent(Dispatcher *dispatcher, PARCEvent *event);
-
-void dispatcher_DestroyNetworkEvent(Dispatcher *dispatcher,
- PARCEvent **eventPtr);
-
-/**
- * @function dispatcher_CreateSignalEvent
- * @abstract Creates a signal trap
- * @discussion
- * May be used on catchable signals. The event is edge triggered and
- * non-reentrent. Signal events are persistent.
- *
- * When created, the signal trap is idle and you need to call
- * <code>forwarder_StartSignalEvent()</code>
- *
- * @param signal is the system signal to monitor (e.g. SIGINT).
- * @return <#return#>
- */
-PARCEventSignal *dispatcher_CreateSignalEvent(
- Dispatcher *dispatcher, PARCEventSignal_Callback *callback, void *userData,
- int signal);
-
-void dispatcher_DestroySignalEvent(Dispatcher *dispatcher,
- PARCEventSignal **eventPtr);
-
-void dispatcher_StartSignalEvent(Dispatcher *dispatcher,
- PARCEventSignal *event);
-void dispatcher_StopSignalEvent(Dispatcher *dispatcher, PARCEventSignal *event);
-
-// =============
-// stream buffers
-
-#include <hicn/core/streamBuffer.h>
-#include <hicn/io/addressPair.h>
-
-/**
- * @function dispatcher_CreateStreamBuffer
- * @abstract Creates a high-function buffer around a stream socket
- */
-PARCEventQueue *dispatcher_CreateStreamBufferFromSocket(Dispatcher *dispatcher,
- SocketType fd);
-
-/**
- * @function dispatcher_StreamBufferConnect
- * @abstract Create a TCP tunnel to a remote peer
- * @discussion
- * For TCP, both address pairs need to be the same address family: both INET
- * or both INET6. The remote address must have the complete socket information
- * (address, port). The local socket could be wildcarded or may specify down to
- * the (address, port) pair.
- *
- * If the local address is IPADDR_ANY and the port is 0, then it is a normal
- * call to "connect" that will use whatever local IP address and whatever local
- * port for the connection. If either the address or port is set, the local
- * socket will first be bound (via bind(2)), and then call connect().
- *
- * It is unlikely that the buffer will be connected by the time the function
- * returns. The eventCallback will fire once the remote system accepts the
- * conneciton.
- *
- * @return NULL on error, otherwise a streambuffer.
- */
-PARCEventQueue *dispatcher_StreamBufferConnect(Dispatcher *dispatcher,
- const AddressPair *pair);
-#endif // dispatcher_h
diff --git a/hicn-light/src/hicn/core/fib.c b/hicn-light/src/hicn/core/fib.c
new file mode 100644
index 0000000..ddd8dd5
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+
+#include <hicn/core/fib.h>
+
+typedef struct fib_node_s {
+ struct fib_node_s *left;
+ struct fib_node_s *right;
+ fib_entry_t *entry;
+ bool is_used;
+} fib_node_t;
+
+static
+fib_node_t *
+fib_node_create(fib_node_t * left, fib_node_t * right, fib_entry_t * entry,
+ bool is_used)
+{
+ fib_node_t * node = malloc(sizeof(fib_node_t));
+ if (!node)
+ return NULL;
+
+ *node = (fib_node_t) {
+ .left = left,
+ .right = right,
+ .entry = entry,
+ .is_used = is_used,
+ };
+
+ return node;
+}
+
+static
+void
+fib_node_free(fib_node_t * node)
+{
+ if (!node)
+ return;
+
+ fib_node_free(node->right);
+ fib_node_free(node->left);
+
+ free(node);
+}
+
+/******************************************************************************/
+
+struct fib_s {
+ void * forwarder;
+ fib_node_t * root;
+ unsigned size;
+};
+
+fib_t *
+fib_create(void * forwarder)
+{
+ fib_t * fib = malloc(sizeof(fib_t));
+ if (!fib)
+ return NULL;
+
+ fib->forwarder = forwarder;
+ fib->root = NULL;
+ fib->size = 0;
+
+ return fib;
+}
+
+
+void
+fib_free(fib_t * fib)
+{
+ assert(fib);
+
+ fib_node_free(fib->root);
+
+ free(fib);
+}
+
+size_t
+fib_get_size(const fib_t * fib)
+{
+ return fib->size;
+}
+
+
+#define FIB_SET(CURR, NEW_PREFIX, CURR_PREFIX_LEN) \
+do { \
+ bool bit; \
+ int res = nameBitvector_testBit(NEW_PREFIX, CURR_PREFIX_LEN, &bit); \
+ assert(res >= 0); \
+ (void)res; /* unused */ \
+ CURR = bit ? CURR->right : CURR->left; \
+} while(0)
+
+#define FIB_INSERT(DST, SRC, PREFIX, PREFIX_LEN) \
+do { \
+ bool bit; \
+ int res = nameBitvector_testBit(PREFIX, PREFIX_LEN, &bit); \
+ assert(res >= 0); \
+ (void)res; /* unused */ \
+ if (bit) \
+ DST->right = SRC; \
+ else \
+ DST->left = SRC; \
+} while(0)
+
+void
+fib_add(fib_t * fib, fib_entry_t * entry)
+{
+ assert(fib);
+ assert(entry);
+
+ NameBitvector *new_prefix = name_GetContentName(fib_entry_get_prefix(entry));
+ uint32_t new_prefix_len = nameBitvector_GetLength(new_prefix);
+ fib_node_t * curr = fib->root;
+ fib_node_t * last = NULL;
+
+ NameBitvector *curr_name;
+ uint32_t curr_prefix_len;
+ uint32_t match_len;
+
+ while (curr) {
+ curr_name = name_GetContentName(fib_entry_get_prefix(curr->entry));
+
+ match_len = nameBitvector_lpm(new_prefix, curr_name);
+ curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if(curr_prefix_len != match_len || //the new entry does not match the curr
+ curr_prefix_len >= new_prefix_len) //in this case we cannot procede anymore
+ break;
+
+ last = curr;
+ FIB_SET(curr, new_prefix, curr_prefix_len);
+ }
+
+ //this is the root (empty trie) or an empty child
+ if (!curr) {
+ fib_node_t * new_node = fib_node_create(NULL, NULL, entry, true);
+ if (!last) {
+ fib->root = new_node;
+ } else {
+ uint32_t last_prefix_len = nameBitvector_GetLength(
+ name_GetContentName(fib_entry_get_prefix(last->entry)));
+
+ FIB_INSERT(last, new_node, new_prefix, last_prefix_len);
+ }
+ fib->size++;
+ return;
+ }
+
+ //curr is not null
+
+ //the node already exist
+ //if is not in use we turn it on and we set the rigth fib entry
+ if (curr_prefix_len == match_len && new_prefix_len == match_len) {
+ if (!curr->is_used) {
+ curr->is_used = true;
+ curr->entry = entry;
+ fib->size++;
+ return;
+ } else {
+ //this case should never happen beacuse of the way we add
+ //entries in the fib
+ const nexthops_t * nexthops = fib_entry_get_nexthops(entry);
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ fib_entry_nexthops_add(curr->entry, nexthop);
+ });
+ }
+ }
+
+ //key is prefix of the curr node (so new_prefix_len < curr_prefix_len)
+ if (new_prefix_len == match_len){
+ fib_node_t * new_node = fib_node_create(NULL, NULL, entry, true);
+ if (!last) {
+ fib->root = new_node;
+ } else {
+ uint32_t last_prefix_len = nameBitvector_GetLength(
+ name_GetContentName(fib_entry_get_prefix(last->entry)));
+ FIB_INSERT(last, new_node, new_prefix, last_prefix_len);
+ }
+ FIB_INSERT(new_node, curr, curr_name, match_len);
+ fib->size++;
+ return;
+ }
+
+ //in the last case we need to add an inner node
+ Name * inner_prefix = name_Copy(fib_entry_get_prefix(entry));
+ nameBitvector_clear(name_GetContentName(inner_prefix), match_len);
+ name_setLen(inner_prefix, match_len);
+
+ //this is an inner node, we don't want an acctive strategy
+ //like low_latency that sends probes in this node
+ fib_entry_t * inner_entry = fib_entry_create(inner_prefix,
+ STRATEGY_TYPE_UNDEFINED, NULL, fib->forwarder);
+
+ fib_node_t * inner_node = fib_node_create(NULL, NULL, inner_entry, false);
+ fib_node_t * new_node = fib_node_create(NULL, NULL, entry, true);
+
+ if (!last) {
+ //we need to place the inner_node at the root
+ fib->root = inner_node;
+ } else {
+ uint32_t last_prefix_len = nameBitvector_GetLength(
+ name_GetContentName(fib_entry_get_prefix(last->entry)));
+ NameBitvector *inner_name = name_GetContentName(inner_prefix);
+ FIB_INSERT(last, inner_node, inner_name, last_prefix_len);
+ }
+
+ bool bit;
+ int res = nameBitvector_testBit(new_prefix, match_len, &bit);
+ assert(res >= 0);
+ (void)res; /* unused */
+ inner_node->left = bit ? curr : new_node;
+ inner_node->right = bit ? new_node : curr;
+ fib->size++;
+}
+
+fib_entry_t *
+fib_contains(const fib_t * fib, const Name * prefix)
+{
+ assert(fib);
+ assert(prefix);
+
+ NameBitvector * key_name = name_GetContentName(prefix);
+ uint32_t key_prefix_len = nameBitvector_GetLength(key_name);
+
+ fib_node_t * curr = fib->root;
+
+ while (curr) {
+ NameBitvector *curr_name =
+ name_GetContentName(fib_entry_get_prefix(curr->entry));
+ uint32_t match_len = nameBitvector_lpm(key_name, curr_name);
+ uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if (match_len < curr_prefix_len) {
+ //the current node does not match completelly the key, so
+ //the key is not in the trie
+ //this implies curr_prefix_len > key_prefix_len
+ return NULL;
+ }
+
+ if (curr_prefix_len == key_prefix_len) { //== match_len
+ //this is an exact match
+ if (!curr->is_used) {
+ //the key does not exists
+ return NULL;
+ }
+ //we found the key
+ return curr->entry;
+ }
+
+ FIB_SET(curr, key_name, curr_prefix_len);
+ }
+
+ return NULL;
+}
+
+static
+void
+fib_node_remove(fib_t *fib, const Name *prefix)
+{
+ assert(fib);
+ assert(prefix);
+
+ NameBitvector *key_name = name_GetContentName(prefix);
+ uint32_t key_prefix_len = nameBitvector_GetLength(key_name);
+
+ fib_node_t * curr = fib->root;
+ fib_node_t * parent = NULL;
+ fib_node_t * grandpa = NULL;
+
+ uint32_t match_len;
+ uint32_t curr_prefix_len;
+
+ while(curr) {
+ NameBitvector *curr_name =
+ name_GetContentName(fib_entry_get_prefix(curr->entry));
+ match_len = nameBitvector_lpm(key_name, curr_name);
+ curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if(match_len < curr_prefix_len ||
+ curr_prefix_len == key_prefix_len){
+ break;
+ }
+
+ grandpa = parent;
+ parent = curr;
+
+ FIB_SET(curr, key_name, curr_prefix_len);
+ }
+
+ if (!curr || !curr->is_used || (curr_prefix_len != key_prefix_len)) {
+ //the node does not exists
+ return;
+ }
+
+ //curr has 2 children, leave it there and mark it as inner
+ if (curr->right && curr->left) {
+ curr->is_used = false;
+ fib->size--;
+ return;
+ }
+
+ //curr has no children
+ if (!curr->right && !curr->left) {
+ if (!parent) {
+ //curr is the root and is the only node in the fib
+ fib->root = NULL;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+ if (!grandpa) {
+ //parent is the root
+ if(fib->root->left == curr)
+ fib->root->left = NULL;
+ else
+ fib->root->right = NULL;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+ if(!parent->is_used){
+ //parent is an inner node
+ //remove curr and inner_node (parent), connect the other child
+ //of the parent to the grandpa
+ fib_node_t * tmp = (parent->right == curr) ? parent->left : parent->right;
+
+ if(grandpa->right == parent)
+ grandpa->right = tmp;
+ else
+ grandpa->left = tmp;
+
+ fib->size--;
+ fib_node_free(curr);
+ fib_node_free(parent);
+ return;
+ }
+ //parent is node not an inner_node
+ //just remove curr the node
+ if(parent->right == curr)
+ parent->right = NULL;
+ else
+ parent->left = NULL;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+
+ //curr has one child
+ if (curr->right || curr->left) {
+ if (!parent) {
+ //curr is the root
+ fib->root = fib->root->right ? fib->root->right : fib->root->left;
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+ //attach the child of curr to parent
+ fib_node_t * tmp = curr->right ? curr->right : curr->left;
+
+ if (parent->right == curr)
+ parent->right = tmp;
+ else
+ parent->left = tmp;
+
+ fib->size--;
+ fib_node_free(curr);
+ return;
+ }
+}
+
+void
+fib_remove(fib_t * fib, const Name * name, unsigned conn_id)
+{
+ assert(fib);
+ assert(name);
+
+ fib_entry_t *entry = fib_contains(fib, name);
+ if (!entry)
+ return;
+
+ fib_entry_nexthops_remove(entry, conn_id);
+#ifndef WITH_MAPME
+ if (fib_entry_nexthops_len(entry) == 0)
+ fib_node_remove(fib, name);
+#endif /* WITH_MAPME */
+}
+
+static
+size_t
+fib_node_remove_connection_id(fib_node_t * node, unsigned conn_id,
+ fib_entry_t ** array, size_t pos)
+{
+ if (!node)
+ return pos;
+ if (node->is_used) {
+ fib_entry_nexthops_remove(node->entry, conn_id);
+#ifndef WITH_MAPME
+ if (fib_entry_nexthops_len(node->entry) == 0)
+ array[pos++] = node->entry;
+#endif /* WITH_MAPME */
+ }
+ pos = fib_node_remove_connection_id(node->right, conn_id, array, pos);
+ pos = fib_node_remove_connection_id(node->left, conn_id, array, pos);
+ return pos;
+}
+
+void
+fib_remove_connection_id(fib_t * fib, unsigned conn_id)
+{
+ assert(fib);
+
+ fib_entry_t ** array = malloc(sizeof(fib_entry_t*) * fib->size);
+
+ size_t pos = 0;
+ pos = fib_node_remove_connection_id(fib->root, conn_id, array, pos);
+
+ for (int i = 0; i < pos; i++)
+ fib_node_remove(fib, fib_entry_get_prefix(array[i]));
+ free(array);
+}
+
+size_t
+fib_length(const fib_t * fib)
+{
+ assert(fib);
+ return fib->size;
+}
+
+fib_entry_t *
+fib_match_message(const fib_t *fib, const msgbuf_t *interest_msgbuf)
+{
+ assert(fib);
+ assert(interest_msgbuf);
+
+ return fib_match_bitvector(fib, name_GetContentName(
+ msgbuf_get_name(interest_msgbuf)));
+}
+
+fib_entry_t *
+fib_match_name(const fib_t * fib, const Name * name)
+{
+ assert(fib);
+ assert(name);
+
+ return fib_match_bitvector(fib, name_GetContentName(name));
+}
+
+
+fib_entry_t *
+fib_match_bitvector(const fib_t * fib, const NameBitvector * name)
+{
+ assert(fib);
+ assert(name);
+
+ uint32_t key_prefix_len = nameBitvector_GetLength(name);
+
+ fib_node_t * curr = fib->root;
+ fib_node_t * candidate = NULL;
+
+ while (curr) {
+ NameBitvector *curr_name =
+ name_GetContentName(fib_entry_get_prefix(curr->entry));
+ uint32_t match_len = nameBitvector_lpm(name, curr_name);
+ uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name);
+
+ if(match_len < curr_prefix_len){
+ //the current node does not match completelly the key, so
+ //return the parent of this node (saved in candidate)
+ break;
+ }
+
+ if (curr->is_used)
+ candidate = curr;
+
+ //if we are here match_len == curr_prefix_len (can't be larger)
+ //so this node is actually a good candidate for a match
+ if (curr_prefix_len == key_prefix_len){
+ //this an exact match, do not continue
+ break;
+ }
+
+ FIB_SET(curr, name, curr_prefix_len);
+ }
+
+ return candidate ? candidate->entry : NULL;
+}
+
+static
+size_t
+fib_node_collect_entries(fib_node_t * node, fib_entry_t ** array, size_t pos)
+{
+ assert(array);
+
+ if (!node)
+ return pos;
+
+ if(node->is_used)
+ array[pos++] = node->entry;
+
+ pos = fib_node_collect_entries(node->right, array, pos);
+ pos = fib_node_collect_entries(node->left, array, pos);
+ return pos;
+}
+
+size_t
+fib_get_entry_array(const fib_t * fib, fib_entry_t *** array_p)
+{
+ size_t pos = 0;
+ *array_p = malloc(sizeof(fib_entry_t*) * fib->size);
+ if (!*array_p)
+ return pos;
+ pos = fib_node_collect_entries(fib->root, *array_p, pos);
+ return pos;
+}
diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h
new file mode 100644
index 0000000..f60a42c
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib.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.
+ */
+#ifndef fib_h
+#define fib_h
+
+#include <hicn/core/msgbuf.h>
+#include <hicn/core/name.h>
+#include <hicn/core/fib_entry.h>
+
+#define _fib_var(x) _fib_ ## x
+
+typedef struct fib_s fib_t;
+
+fib_t * fib_create(void * forwarder);
+
+void fib_free(fib_t * fib);
+
+size_t fib_get_size(const fib_t * fib);
+
+void fib_add(fib_t *fib, fib_entry_t * node);
+
+fib_entry_t * fib_contains(const fib_t * fib, const Name * prefix);
+
+void fib_remove(fib_t * fib, const Name * prefix, unsigned conn_id);
+
+void fib_remove_connection_id(fib_t *fib, unsigned conn_id);
+
+size_t fib_length(const fib_t *fib);
+
+fib_entry_t * fib_match_message(const fib_t * fib, const msgbuf_t * interest_msgbuf);
+fib_entry_t * fib_match_name(const fib_t * fib, const Name * name);
+fib_entry_t * fib_match_bitvector(const fib_t * fib, const NameBitvector * name);
+
+size_t fib_get_entry_array(const fib_t * fib, fib_entry_t *** array_p);
+
+#define fib_foreach_entry(FIB, ENTRY, BODY) \
+do { \
+ fib_entry_t ** _fib_var(array); \
+ size_t _fib_var(n) = fib_get_entry_array((FIB), &_fib_var(array)); \
+ size_t _fib_var(i); \
+ for (_fib_var(i) = 0; _fib_var(i) < _fib_var(n); _fib_var(i)++) { \
+ ENTRY = _fib_var(array)[_fib_var(i)]; \
+ do { BODY } while(0); \
+ } \
+ free(_fib_var(array)); \
+} while(0)
+
+#endif // fib_h
diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c
new file mode 100644
index 0000000..5c6e28d
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib_entry.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include <hicn/hicn-light/config.h>
+#include <hicn/core/fib_entry.h>
+//#include <hicn/core/connectionState.h>
+#include <hicn/core/strategy_vft.h>
+#include <hicn/core/nameBitvector.h>
+#include <hicn/utils/commands.h>
+
+#ifdef WITH_MAPME
+#include <hicn/core/ticks.h>
+#endif /* WITH_MAPME */
+
+#ifdef WITH_POLICY
+#include <hicn/core/forwarder.h>
+#include <hicn/policy.h>
+
+#ifdef WITH_MAPME
+#include <hicn/core/mapme.h>
+#endif /* WITH_MAPME */
+
+#endif /* WITH_POLICY */
+
+#ifdef WITH_PREFIX_STATS
+#include <hicn/core/prefix_stats.h>
+#endif /* WITH_PREFIX_STATS */
+
+
+fib_entry_t *
+fib_entry_create(Name *name, strategy_type_t strategy_type,
+ strategy_options_t * strategy_options, const forwarder_t * forwarder)
+{
+
+ assert(name);
+ assert(forwarder);
+
+ fib_entry_t * entry = malloc(sizeof(fib_entry_t));
+ if (!entry)
+ goto ERR_MALLOC;
+
+ entry->name = name_Acquire(name);
+
+ // XXX TODO strategy type might be undefined. We need a default strategy
+ // specified somewhere in the configuration.
+ fib_entry_set_strategy(entry, strategy_type, strategy_options);
+
+#ifdef WITH_MAPME
+ entry->user_data = NULL;
+ entry->user_data_release = NULL;
+#endif /* WITH_MAPME */
+
+ entry->forwarder = forwarder;
+
+#ifdef WITH_POLICY
+ entry->policy = POLICY_NONE;
+#endif /* WITH_POLICY */
+
+#ifdef WITH_PREFIX_STATS
+ entry->prefix_stats = PREFIX_STATS_EMPTY;
+ entry->prefix_counters = PREFIX_COUNTERS_EMPTY;
+#endif /* WITH_PREFIX_STATS */
+
+ return entry;
+
+ERR_MALLOC:
+ return NULL;
+}
+
+void
+fib_entry_free(fib_entry_t * entry)
+{
+ assert(entry);
+
+ name_Release(&entry->name);
+#ifdef WITH_MAPME
+ if (entry->user_data)
+ entry->user_data_release(&entry->user_data);
+#endif /* WITH_MAPME */
+ free(entry);
+}
+
+// XXX TODO DUPLICATE
+void
+fib_entry_set_strategy(fib_entry_t * entry, strategy_type_t strategy_type,
+ strategy_options_t * strategy_options)
+{
+ if (STRATEGY_TYPE_VALID(strategy_type)) {
+ entry->strategy.type = strategy_type;
+ if (strategy_options)
+ entry->strategy.options = *strategy_options;
+ strategy_vft[strategy_type]->initialize(&entry->strategy);
+ }
+}
+
+#ifdef WITH_POLICY
+
+nexthops_t *
+fib_entry_filter_nexthops(fib_entry_t * entry, nexthops_t * nexthops,
+ unsigned ingress_id, bool prefer_local)
+{
+ assert(entry);
+ assert(nexthops);
+
+ /* Filter out ingress, down & administrative down faces */
+ const connection_table_t * table = forwarder_get_connection_table(entry->forwarder);
+ connection_t * conn;
+ unsigned nexthop, i;
+ uint_fast32_t flags;
+
+ policy_t policy = fib_entry_get_policy(entry);
+
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i, nexthop == ingress_id);
+ nexthops_disable_if(nexthops, i,
+ (connection_get_admin_state(conn) == FACE_STATE_DOWN));
+ nexthops_disable_if(nexthops, i,
+ (connection_get_state(conn) == FACE_STATE_DOWN));
+ });
+
+ if (prefer_local) {
+ /* Backup flags */
+ flags = nexthops->flags;
+
+ /* Filter local */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i, (!connection_is_local(conn)));
+ });
+
+ /* Local faces have priority */
+ if (nexthops_get_curlen(nexthops) > 0)
+ return nexthops;
+
+ nexthops->flags = flags;
+ }
+
+ /* Filter out local */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i, (connection_is_local(conn)));
+
+ /* Policy filtering : next hops */
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_WIRED)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_WIRED)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_WIFI)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_WIFI)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_CELLULAR)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_CELLULAR)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) &&
+ (!connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ nexthops_disable_if(nexthops, i,
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PROHIBIT) &&
+ (connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ });
+
+ if (nexthops_get_curlen(nexthops) == 0)
+ return nexthops;
+
+ /* We have at least one matching next hop, implement heuristic */
+
+ /*
+ * As VPN connections might trigger duplicate uses of one interface, we start
+ * by filtering out interfaces based on trust status.
+ */
+ flags = nexthops->flags;
+
+ if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) ||
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PREFER)) {
+
+ /* Try to filter out NON TRUSTED faces */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ (!connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ });
+
+ if ((nexthops_get_curlen(nexthops) == 0) && (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE)) {
+ return nexthops;
+ }
+
+ } else {
+ /* Try to filter out TRUSTED faces */
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ (connection_has_tag(conn, POLICY_TAG_TRUSTED)));
+ });
+ }
+
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+
+ /* Other preferences */
+ if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_AVOID) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_has_tag(conn, POLICY_TAG_WIRED));
+ });
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_AVOID) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_has_tag(conn, POLICY_TAG_WIFI));
+ });
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_AVOID) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_has_tag(conn, POLICY_TAG_CELLULAR));
+ });
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+ }
+
+ if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PREFER) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ !connection_has_tag(conn, POLICY_TAG_WIRED));
+ });
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PREFER) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ !connection_has_tag(conn, POLICY_TAG_WIFI));
+ });
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+ }
+ if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PREFER) {
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ !connection_has_tag(conn, POLICY_TAG_CELLULAR));
+ });
+ if (nexthops_get_curlen(nexthops) == 0)
+ nexthops->flags = flags;
+ }
+
+ /* Priority */
+ uint32_t max_priority = 0;
+ nexthops_foreach(nexthops, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ uint32_t priority = connection_get_priority(conn);
+ if (priority > max_priority)
+ max_priority = priority;
+ });
+ nexthops_enumerate(nexthops, i, nexthop, {
+ conn = connection_table_at(table, nexthop);
+ nexthops_disable_if(nexthops, i,
+ connection_get_priority(conn) < max_priority);
+ });
+
+ return nexthops;
+}
+
+/*
+ * Update available next hops following policy update.
+ *
+ * The last nexthop parameter is only used if needed, otherwise the pointer to
+ * fib entry is returned to avoid an useless copy
+ */
+nexthops_t *
+fib_entry_get_available_nexthops(fib_entry_t * entry, unsigned ingress_id, nexthops_t * new_nexthops)
+{
+ connection_table_t * table = forwarder_get_connection_table(entry->forwarder);
+
+ /*
+ * Give absolute preference to local faces, with no policy, unless
+ * ingress_id == ~0, which means we are searching faces on which to
+ * advertise our prefix
+ */
+ if (ingress_id == ~0) {
+ assert(new_nexthops);
+ /* We create a nexthop structure based on connections */
+ // XXX This should be done close to where it is needed
+ connection_t * connection;
+ connection_table_foreach(table, connection, {
+ new_nexthops->elts[nexthops_get_len(new_nexthops)] = connection_table_get_connection_id(table, connection);
+ nexthops_inc(new_nexthops);
+ });
+
+ return fib_entry_filter_nexthops(entry, new_nexthops, ingress_id, false);
+ }
+
+ return fib_entry_filter_nexthops(entry, fib_entry_get_nexthops(entry), ingress_id, true);
+}
+
+policy_t
+fib_entry_get_policy(const fib_entry_t * entry)
+{
+ return entry->policy;
+}
+
+void
+fib_entry_set_policy(fib_entry_t * entry, policy_t policy)
+{
+ entry->policy = policy;
+
+#ifdef WITH_MAPME
+ /*
+ * Skip entries that do not correspond to a producer ( / have a locally
+ * served prefix / have no local connection as next hop)
+ */
+ if (!fib_entry_has_local_nexthop(entry))
+ return;
+ mapme_t * mapme = forwarder_get_mapme(entry->forwarder);
+ mapme_send_to_all_nexthops(mapme, entry);
+#endif /* WITH_MAPME */
+}
+
+#endif /* WITH_POLICY */
+
+void
+fib_entry_nexthops_add(fib_entry_t * entry, unsigned nexthop)
+{
+ nexthops_add(fib_entry_get_nexthops(entry), nexthop);
+ // XXX TODO
+ strategy_vft[entry->strategy.type]->add_nexthop(&entry->strategy, nexthop, NULL);
+}
+
+void
+fib_entry_nexthops_remove(fib_entry_t * entry, unsigned nexthop)
+{
+ nexthops_remove(fib_entry_get_nexthops(entry), nexthop);
+ // XXX TODO
+ strategy_vft[entry->strategy.type]->remove_nexthop(&entry->strategy, nexthop, NULL);
+}
+
+const nexthops_t *
+fib_entry_get_nexthops_from_strategy(fib_entry_t * entry,
+ const msgbuf_t * msgbuf, bool is_retransmission)
+{
+ assert(entry);
+ assert(msgbuf);
+
+ const prefix_stats_mgr_t * mgr = forwarder_get_prefix_stats_mgr(entry->forwarder);
+ assert(mgr);
+
+ /* Filtering */
+ nexthops_t * nexthops = fib_entry_get_available_nexthops(entry,
+ msgbuf_get_connection_id(msgbuf), NULL);
+ if (nexthops_get_curlen(nexthops) == 0)
+ return nexthops;
+
+#ifdef WITH_PREFIX_STATS
+ /*
+ * Update statistics about loss rates. We only detect losses upon
+ * retransmissions, and assume for the computation that the candidate set of
+ * output faces is the same as previously (i.e. does not take into account
+ * event such as face up/down, policy update, etc. Otherwise we would need to
+ * know what was the previous choice !
+ */
+ if (is_retransmission)
+ prefix_stats_on_retransmission(mgr, &entry->prefix_counters, nexthops);
+#endif /* WITH_PREFIX_STATS */
+
+ /*
+ * NOTE: We might want to call a forwarding strategy even with no nexthop to
+ * take a fallback decision.
+ */
+ if (nexthops_get_curlen(nexthops) == 0)
+ return nexthops;
+
+#ifdef WITH_POLICY
+ /*
+ * If multipath is disabled, we don't offer much choice to the forwarding
+ * strategy, but still go through it for accounting purposes.
+ */
+ policy_t policy = fib_entry_get_policy(entry);
+ if ((policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_PROHIBIT) ||
+ (policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_AVOID)) {
+ nexthops_select_one(nexthops);
+ }
+#endif /* WITH_POLICY */
+
+ return strategy_vft[entry->strategy.type]->lookup_nexthops(&entry->strategy,
+ nexthops, msgbuf);
+}
+
+void
+fib_entry_on_data(fib_entry_t * entry,
+ const nexthops_t * nexthops, const msgbuf_t * msgbuf,
+ Ticks pitEntryCreation, Ticks objReception)
+{
+ assert(entry);
+ assert(nexthops);
+ assert(msgbuf);
+
+#ifdef WITH_PREFIX_STATS
+ const prefix_stats_mgr_t * mgr = forwarder_get_prefix_stats_mgr(entry->forwarder);
+ Ticks rtt = objReception - pitEntryCreation;
+ prefix_stats_on_data(mgr, &entry->prefix_stats, &entry->prefix_counters,
+ nexthops, msgbuf, rtt);
+#endif /* WITH_PREFIX_STATS */
+
+ strategy_vft[entry->strategy.type]->on_data(&entry->strategy, nexthops, msgbuf, pitEntryCreation, objReception);
+}
+
+void
+fib_entry_on_timeout(fib_entry_t * entry, const nexthops_t * nexthops)
+{
+ assert(entry);
+ assert(nexthops);
+
+#ifdef WITH_PREFIX_STATS
+ const prefix_stats_mgr_t * mgr = forwarder_get_prefix_stats_mgr(entry->forwarder);
+ prefix_stats_on_timeout(mgr, &entry->prefix_counters, nexthops);
+#endif /* WITH_PREFIX_STATS */
+
+ strategy_vft[entry->strategy.type]->on_timeout(&entry->strategy, nexthops);
+}
+
+Name *
+fib_entry_get_prefix(const fib_entry_t * entry)
+{
+ assert(entry);
+
+ return entry->name;
+}
+
+
+/*
+ * Return true if we have at least one local connection as next hop
+ */
+bool
+fib_entry_has_local_nexthop(const fib_entry_t * entry)
+{
+ connection_table_t * table = forwarder_get_connection_table(entry->forwarder);
+
+ unsigned nexthop;
+ nexthops_foreach(fib_entry_get_nexthops(entry), nexthop, {
+ const connection_t * conn = connection_table_at(table, nexthop);
+ /* Ignore non-local connections */
+ if (!connection_is_local(conn))
+ continue;
+ return true;
+ });
+ return false;
+}
+
+#ifdef WITH_MAPME
+
+void *
+fib_entry_get_user_data(const fib_entry_t * entry)
+{
+ assert(entry);
+
+ return entry->user_data;
+}
+
+void
+fib_entry_set_user_data(fib_entry_t * entry, const void * user_data,
+ void (*user_data_release)(void **))
+{
+ assert(entry);
+ assert(user_data);
+ assert(user_data_release);
+
+ entry->user_data = (void *)user_data;
+ entry->user_data_release = user_data_release;
+}
+
+#endif /* WITH_MAPME */
diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h
new file mode 100644
index 0000000..94d283d
--- /dev/null
+++ b/hicn-light/src/hicn/core/fib_entry.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 fib_entry.h
+ * @brief A forwarding entry in the FIB table
+ *
+ * A Forwarding Information Base (FIB) entry (fib_entry_t) is a
+ * set of nexthops for a name. It also indicates the forwarding strategy.
+ *
+ * Each nexthop contains the ConnectionId assocaited with it. This could be
+ * something specific like a MAC address or point-to-point tunnel. Or, it
+ * could be something general like a MAC group address or ip multicast overlay.
+ *
+ * See strategy.h for a description of forwarding strategies.
+ * In short, a strategy is the algorithm used to select one or more nexthops
+ * from the set of available nexthops.
+ *
+ * Each nexthop also contains a void* to a forwarding strategy data container.
+ * This allows a strategy to keep proprietary information about each nexthop.
+ *
+ *
+ */
+
+#ifndef fib_entry_h
+#define fib_entry_h
+
+#include <hicn/core/name.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/msgbuf.h>
+#include <hicn/core/nexthops.h>
+#include <hicn/core/prefix_stats.h>
+#include <hicn/utils/commands.h> // strategy type
+
+#ifdef WITH_MAPME
+//#include <parc/algol/parc_EventTimer.h>
+//#include <parc/algol/parc_Iterator.h>
+#endif /* WITH_MAPME */
+
+typedef struct {
+ Name *name;
+ unsigned refcount;
+ nexthops_t nexthops;
+ strategy_entry_t strategy;
+
+ const void * forwarder;
+
+#ifdef WITH_POLICY
+ policy_t policy;
+#endif /* WITH_POLICY */
+
+ prefix_counters_t prefix_counters;
+ prefix_stats_t prefix_stats;
+
+#ifdef WITH_MAPME
+ /* In case of no multipath, this stores the previous decision taken by policy. As the list of nexthops is not expected to change, we can simply store the flags */
+ uint_fast32_t prev_nexthops_flags;
+ void *user_data;
+ void (*user_data_release)(void **user_data);
+#endif /* WITH_MAPME */
+} fib_entry_t;
+
+#define _fib_entry_var(x) _fib_entry_##x
+
+#define fib_entry_strategy_type(fib_entry) ((fib_entry)->strategy.type)
+
+#define fib_entry_get_nexthops(fib_entry) (&(fib_entry)->nexthops)
+#define fib_entry_nexthops_len(fib_entry) (nexthops_len(&(fib_entry)->nexthops))
+#define fib_entry_nexthops_curlen(fib_entry) (nexthops_curlen(&(fib_entry)->nexthops))
+#define fib_entry_get_nexthop(fib_entry, i) ((fib_entry)->nexthops.elts[i])
+#define fib_entry_foreach_nexthop(fib_entry, nexthop, BODY) \
+ nexthops_foreach(fib_entry->nexthops, BODY)
+
+#define fib_entry_nexthops_changed(fib_entry) \
+ ((fib_entry)->prev_nexthops_flags == fib_entry_get_nexthops(fib_entry)->flags)
+
+#define fib_entry_set_prev_nexthops(fib_entry) \
+ ((fib_entry)->prev_nexthops_flags = fib_entry_get_nexthops(fib_entry)->flags)
+
+struct forwarder_s;
+fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type,
+ strategy_options_t * strategy_options, const struct forwarder_s * table);
+
+void fib_entry_set_strategy(fib_entry_t *fib_entry,
+ strategy_type_t strategy_type, strategy_options_t * strategy_options);
+
+void fib_entry_nexthops_add(fib_entry_t * fib_entry, unsigned nexthop);
+
+void fib_entry_nexthops_remove(fib_entry_t * fib_entry, unsigned nexthop);
+
+size_t fib_entry_NexthopCount(const fib_entry_t *fib_entry);
+
+/**
+ * @function fib_entry_nexthops_get
+ * @abstract Returns the nexthop set of the FIB entry. You must Acquire if it
+ * will be saved.
+ * @discussion
+ * Returns the next hop set for the FIB entry.
+ */
+const nexthops_t * fib_entry_nexthops_get(const fib_entry_t *fib_entry);
+
+const nexthops_t * fib_entry_nexthops_getFromForwardingStrategy(
+ fib_entry_t *fib_entry, const msgbuf_t *interest_msgbuf, bool is_retransmission);
+
+void fib_entry_on_data(fib_entry_t * fib_entry, const nexthops_t * nexthops,
+ const msgbuf_t * object_msgbuf, Ticks pit_entry_creation,
+ Ticks data_reception);
+
+#ifdef WITH_POLICY
+policy_t fib_entry_get_policy(const fib_entry_t *fib_entry);
+void fib_entry_reconsider_policy(fib_entry_t *fib_entry);
+void fib_entry_set_policy(fib_entry_t *fib_entry, policy_t policy);
+void fib_entry_update_stats(fib_entry_t *fib_entry, uint64_t now);
+#endif /* WITH_POLICY */
+
+nexthops_t * fib_entry_get_available_nexthops(fib_entry_t *fib_entry,
+ unsigned in_connection, nexthops_t * new_nexthops);
+void fib_entry_on_timeout(fib_entry_t *fib_entry, const nexthops_t *egressId);
+const nexthops_t * fib_entry_get_nexthops_from_strategy(fib_entry_t *fib_entry,
+ const msgbuf_t *interest_msgbuf, bool is_retransmission);
+
+/**
+ * @function fib_entry_get_prefix
+ * @abstract Returns a copy of the prefix.
+ * @return A reference counted copy that you must destroy
+ */
+Name *fib_entry_get_prefix(const fib_entry_t *fib_entry);
+
+bool fib_entry_has_local_nexthop(const fib_entry_t * entry);
+
+#ifdef WITH_MAPME
+
+/**
+ * @function fib_entry_get_user_data
+ * @abstract Returns user data associated to the FIB entry.
+ * @param [in] fib_entry - Pointer to the FIB entry.
+ * @return User data as a void pointer
+ */
+void *fib_entry_get_user_data(const fib_entry_t *fib_entry);
+
+/**
+ * @function fib_entry_get_user_data
+ * @abstract Associates user data and release callback to a FIB entry.
+ * @param [in] fib_entry - Pointer to the FIB entry.
+ * @param [in] user_data - Generic pointer to user data
+ * @param [in@ user_data_release - Callback used to release user data upon change
+ * of FIB entry removal.
+ */
+void fib_entry_set_user_data(fib_entry_t *fib_entry, const void *user_data,
+ void (*user_data_release)(void **));
+
+#endif /* WITH_MAPME */
+
+#endif // fib_entry_h
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index f7b0af2..f8e9919 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -41,553 +41,1157 @@
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#include <parc/algol/parc_ArrayList.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/logging/parc_LogReporterTextStdout.h>
-
-#include <hicn/core/connectionManager.h>
-#include <hicn/core/connectionTable.h>
-#include <hicn/core/dispatcher.h>
+#include <hicn/core/connection_table.h>
+#include <hicn/core/listener_table.h>
+#include <hicn/core/pit.h>
+#include <hicn/core/fib.h>
+#include <hicn/core/content_store.h>
#include <hicn/core/forwarder.h>
#include <hicn/core/messagePacketType.h>
#ifdef WITH_MAPME
#include <hicn/core/mapme.h>
#endif /* WITH_MAPME */
#include <hicn/config/configuration.h>
-#include <hicn/config/configurationFile.h>
-#include <hicn/config/configurationListeners.h>
-#include <hicn/processor/messageProcessor.h>
+#include <hicn/config/configuration_file.h>
+
+#ifdef WITH_PREFIX_STATS
+#include <hicn/core/prefix_stats.h>
+#endif /* WITH_PREFIX_STATS */
#include <hicn/core/wldr.h>
+#include <hicn/util/log.h>
-#include <parc/assert/parc_Assert.h>
+#define DEFAULT_PIT_SIZE 65535
-// the router's clock frequency (we now use the monotonic clock)
-#define HZ 1000
+typedef struct {
+ uint32_t countReceived;
+ uint32_t countInterestsReceived;
+ uint32_t countObjectsReceived;
-// 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)
+ uint32_t countInterestsAggregated;
-struct forwarder {
- Dispatcher *dispatcher;
+ uint32_t countDropped;
+ uint32_t countInterestsDropped;
+ uint32_t countDroppedNoRoute;
+ uint32_t countDroppedNoReversePath;
- uint16_t server_port;
+ uint32_t countDroppedConnectionNotFound;
+ uint32_t countObjectsDropped;
+ uint32_t countOtherDropped;
- PARCEventSignal *signal_int;
- PARCEventSignal *signal_term;
-#ifndef _WIN32
- PARCEventSignal *signal_usr1;
-#endif
- PARCEventTimer *keepalive_event;
+ uint32_t countSendFailures;
+ uint32_t countInterestForwarded;
+ uint32_t countObjectsForwarded;
+ uint32_t countInterestsSatisfiedFromStore;
- // will skew the virtual clock forward. In normal operaiton, it is 0.
- Ticks clockOffset;
+ uint32_t countDroppedNoHopLimit;
+ uint32_t countDroppedZeroHopLimitFromRemote;
+ uint32_t countDroppedZeroHopLimitToRemote;
+} forwarder_stats_t;
- unsigned nextConnectionid;
- Messenger *messenger;
- ConnectionManager *connectionManager;
- ConnectionTable *connectionTable;
- ListenerSet *listenerSet;
- Configuration *config;
+struct forwarder_s {
+// uint16_t server_port;
- // we'll eventually want to setup a threadpool of these
- MessageProcessor *processor;
+// XXX TODO signal handling
+#if 0
+ PARCEventSignal *signal_int;
+ PARCEventSignal *signal_term;
+#ifndef _WIN32
+ PARCEventSignal *signal_usr1;
+#endif
+#endif
- Logger *logger;
+ // used by seed48 and nrand48
+ unsigned short seed[3];
- PARCClock *clock;
+ connection_table_t * connection_table;
+ listener_table_t * listener_table;
+ configuration_t *config;
-#if !defined(__APPLE__)
- hicn_socket_helper_t
- *hicnSocketHelper; // state required to manage hicn connections
-#endif
- // used by seed48 and nrand48
- unsigned short seed[3];
+
+ pit_t * pit;
+ content_store_t * content_store;
+ fib_t * fib;
#ifdef WITH_MAPME
- MapMe *mapme;
+ mapme_t * mapme;
#endif /* WITH_MAPME */
+
+ bool store_in_content_store;
+ bool serve_from_content_store;
+
+ forwarder_stats_t stats;
+#ifdef WITH_PREFIX_STATS
+ prefix_stats_mgr_t prefix_stats_mgr;
+#endif /* WITH_PREFIX_STATS */
+
+ /*
+ * The message forwarder has to decide whether to queue incoming packets for
+ * batching, or trigger the transmission on the connection
+ */
+ unsigned pending_conn[MAX_MSG];
+ size_t num_pending_conn;
+
+ msgbuf_t msgbuf; /* Storage for msgbuf, which are currently processed 1 by 1 */
+
};
+#if 0
// 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 *);
+#endif
/**
* Reseed our pseudo-random number generator.
*/
-static void forwarder_Seed(Forwarder *forwarder) {
+static
+void
+forwarder_seed(forwarder_t * forwarder) {
#ifndef _WIN32
- int fd;
- ssize_t res;
-
- 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)) {
+ 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);
- }
- /*
- * 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
+int
+init_batch_buffers(batch_buffer_t * bb)
+{
+ /* Setup recvmmsg data structures. */
+ for (unsigned i = 0; i < MAX_MSG; i++) {
+ char *buf = &bb->buffers[i][0];
+ struct iovec *iovec = &bb->iovecs[i];
+ struct mmsghdr *msg = &bb->msghdr[i];
-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);
+ msg->msg_hdr.msg_iov = iovec;
+ msg->msg_hdr.msg_iovlen = 1;
- forwarder->clock = parcClock_Monotonic();
- forwarder->clockOffset = 0;
+ msg->msg_hdr.msg_name = &bb->addrs[i];
+ msg->msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
- 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);
+ iovec->iov_base = &buf[0];
+ iovec->iov_len = MTU;
}
+ return 0;
+}
- 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);
+forwarder_t *
+forwarder_create()
+{
+ forwarder_t * forwarder = malloc(sizeof(forwarder_t));
+ if (!forwarder)
+ goto ERR_MALLOC;
+
+ forwarder_seed(forwarder);
+
+ forwarder->config = configuration_create(forwarder);
+ if (!forwarder->config)
+ goto ERR_CONFIG;
+
+ forwarder->listener_table = listener_table_create();
+ if (!forwarder->listener_table)
+ goto ERR_LISTENER_TABLE;
+
+ forwarder->connection_table = connection_table_create();
+ if (!forwarder->connection_table)
+ goto ERR_CONNECTION_TABLE;
+
+ forwarder->fib = fib_create(forwarder);
+ if (!forwarder->fib)
+ goto ERR_FIB;
+
+ forwarder->pit = pit_create(DEFAULT_PIT_SIZE);
+ if (!forwarder->pit)
+ goto ERR_PIT;
+
+ size_t objectStoreSize =
+ configuration_content_store_get_size(forwarder_get_configuration(forwarder));
+ forwarder->content_store = content_store_create(CONTENT_STORE_TYPE_LRU,
+ objectStoreSize);
+ if (!forwarder->content_store)
+ goto ERR_CONTENT_STORE;
+
+ // the two flags for the content_store are set to true by default. If the content_store
+ // is active it always work as expected unless the use modifies this
+ // values using controller
+ forwarder->store_in_content_store = true;
+ forwarder->serve_from_content_store = true;
+
+#if 0
+ 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);
+ forwarder->signal_usr1 = dispatcher_CreateSignalEvent(
+ forwarder->dispatcher, _signal_cb, forwarder, SIGPIPE);
+ dispatcher_StartSignalEvent(forwarder->dispatcher, forwarder->signal_usr1);
+#endif
#endif
-
-#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && \
- defined(PUNTING)
- forwarder->hicnSocketHelper = hicn_create();
- if (!forwarder->hicnSocketHelper)
- goto ERR_SOCKET;
-#endif /* __APPLE__ */
#ifdef WITH_MAPME
- if (!(mapme_create(&forwarder->mapme, forwarder)))
- goto ERR_MAPME;
+ forwarder->mapme = mapme_create(forwarder);
+ if (!forwarder->mapme)
+ goto ERR_MAPME;
#endif /* WITH_MAPME */
- /* ignore child */
+ /* ignore child */
#ifndef _WIN32
- signal(SIGCHLD, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
- /* ignore tty signals */
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, 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);
+#ifdef WITH_PREFIX_STATS
+ if (prefix_stats_mgr_initialize(&forwarder->prefix_stats_mgr, forwarder) < 0)
+ goto ERR_MGR;
+#endif /* WITH_PREFIX_STATS */
- wtnow_timeout.tv_sec = 0;
- wtnow_timeout.tv_usec = 50000; // 20 Hz keepalive
-
- 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;
+ return forwarder;
+ERR_MGR:
#ifdef WITH_MAPME
ERR_MAPME:
#endif /* WITH_MAPME */
-#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && \
- defined(PUNTING)
- hicn_free(forwarder->hicnSocketHelper);
-ERR_SOCKET:
-#endif
- listenerSet_Destroy(&(forwarder->listenerSet));
- connectionManager_Destroy(&(forwarder->connectionManager));
- connectionTable_Destroy(&(forwarder->connectionTable));
- messageProcessor_Destroy(&(forwarder->processor));
- configuration_Destroy(&(forwarder->config));
- messenger_Destroy(&(forwarder->messenger));
-
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_int));
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_term));
+
+#if 0
+ dispatcher_DestroySignalEvent(forwarder->dispatcher,
+ &(forwarder->signal_int));
+ dispatcher_DestroySignalEvent(forwarder->dispatcher,
+ &(forwarder->signal_term));
#ifndef _WIN32
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_usr1));
+ dispatcher_DestroySignalEvent(forwarder->dispatcher,
+ &(forwarder->signal_usr1));
#endif
- parcClock_Release(&forwarder->clock);
- logger_Release(&forwarder->logger);
-
- // do the dispatcher last
- dispatcher_Destroy(&(forwarder->dispatcher));
+ // do the dispatcher last
+ dispatcher_Destroy(&(forwarder->dispatcher));
+#endif
- parcMemory_Deallocate((void **)&forwarder);
- return NULL;
+ content_store_free(forwarder->content_store);
+ERR_CONTENT_STORE:
+ pit_free(forwarder->pit);
+ERR_PIT:
+ fib_free(forwarder->fib);
+ERR_FIB:
+ connection_table_free(forwarder->connection_table);
+ERR_CONNECTION_TABLE:
+ listener_table_free(forwarder->listener_table);
+ERR_LISTENER_TABLE:
+ configuration_free(forwarder->config);
+ERR_CONFIG:
+ free(forwarder);
+ERR_MALLOC:
+ return NULL;
}
-void forwarder_Destroy(Forwarder **ptr) {
- parcAssertNotNull(ptr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*ptr, "Parameter must dereference to non-null pointer");
- Forwarder *forwarder = *ptr;
-#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && \
- defined(PUNTING)
- hicn_free(forwarder->hicnSocketHelper);
-#endif
- parcEventTimer_Destroy(&(forwarder->keepalive_event));
-
- listenerSet_Destroy(&(forwarder->listenerSet));
- connectionManager_Destroy(&(forwarder->connectionManager));
- connectionTable_Destroy(&(forwarder->connectionTable));
- messageProcessor_Destroy(&(forwarder->processor));
- configuration_Destroy(&(forwarder->config));
+void
+forwarder_free(forwarder_t * forwarder)
+{
+ assert(forwarder);
- // the messenger is used by many of the other pieces, so destroy it last
- messenger_Destroy(&(forwarder->messenger));
+ prefix_stats_mgr_finalize(&forwarder->prefix_stats_mgr);
#ifdef WITH_MAPME
- mapme_free(forwarder->mapme);
+ mapme_free(forwarder->mapme);
#endif /* WITH_MAPME */
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_int));
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_term));
+#if 0
+ dispatcher_DestroySignalEvent(forwarder->dispatcher,
+ &(forwarder->signal_int));
+ dispatcher_DestroySignalEvent(forwarder->dispatcher,
+ &(forwarder->signal_term));
#ifndef _WIN32
- dispatcher_DestroySignalEvent(forwarder->dispatcher,
- &(forwarder->signal_usr1));
+ dispatcher_DestroySignalEvent(forwarder->dispatcher,
+ &(forwarder->signal_usr1));
#endif
- parcClock_Release(&forwarder->clock);
- logger_Release(&forwarder->logger);
-
- // do the dispatcher last
- dispatcher_Destroy(&(forwarder->dispatcher));
+ // do the dispatcher last
+ dispatcher_Destroy(&(forwarder->dispatcher));
+#endif
- parcMemory_Deallocate((void **)&forwarder);
- *ptr = NULL;
+ content_store_free(forwarder->content_store);
+ pit_free(forwarder->pit);
+ fib_free(forwarder->fib);
+ connection_table_free(forwarder->connection_table);
+ listener_table_free(forwarder->listener_table);
+ configuration_free(forwarder->config);
+ free(forwarder);
}
-void forwarder_SetupAllListeners(Forwarder *forwarder, uint16_t port,
- const char *localPath) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
+void
+forwarder_setup_all_listeners(forwarder_t * forwarder, uint16_t port,
+ const char * local_path)
+{
+ assert(forwarder);
+ assert(local_path);
- configurationListeners_SetupAll(forwarder->config, port, localPath);
+ listener_setup_all(forwarder, port, local_path);
}
-void forwarder_SetupLocalListeners(Forwarder *forwarder, uint16_t port) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- configurationListeners_SetutpLocalIPv4(forwarder->config, port);
+void
+forwarder_setup_local_listeners(forwarder_t * forwarder, uint16_t port)
+{
+ assert(forwarder);
+ listener_setup_local_ipv4(forwarder, port);
}
-void forwarder_SetupFromConfigFile(Forwarder *forwarder, const char *filename) {
- ConfigurationFile *configFile = configurationFile_Create(forwarder, filename);
- if (configFile) {
- configurationFile_Process(configFile);
- configurationFile_Release(&configFile);
- }
-}
+void
+forwarder_read_config(forwarder_t * forwarder, const char * filename)
+{
+ configuration_file_t *cfg = configuration_file_create(forwarder, filename);
+ if (!cfg)
+ return;
-Configuration *forwarder_GetConfiguration(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->config;
+ configuration_file_process(cfg);
+ configuration_file_free(cfg);
}
-// ============================================================================
+configuration_t *
+forwarder_get_configuration(forwarder_t * forwarder)
+{
+ assert(forwarder);
+ return forwarder->config;
+}
-unsigned forwarder_GetNextConnectionId(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->nextConnectionid++;
+connection_table_t *
+forwarder_get_connection_table(const forwarder_t * forwarder)
+{
+ assert(forwarder);
+ return forwarder->connection_table;
}
-Messenger *forwarder_GetMessenger(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->messenger;
+listener_table_t *
+forwarder_get_listener_table(forwarder_t * forwarder)
+{
+ assert(forwarder);
+ return forwarder->listener_table;
}
-Dispatcher *forwarder_GetDispatcher(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->dispatcher;
+void
+forwarder_content_store_set_store(forwarder_t * forwarder, bool val)
+{
+ assert(forwarder);
+ forwarder->store_in_content_store = val;
}
-#ifdef WITH_POLICY
-ConnectionTable *forwarder_GetConnectionTable(const Forwarder *forwarder) {
-#else
-ConnectionTable *forwarder_GetConnectionTable(Forwarder *forwarder) {
-#endif /* WITH_POLICY */
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->connectionTable;
+bool
+forwarder_content_store_get_store(forwarder_t * forwarder)
+{
+ assert(forwarder);
+ return forwarder->store_in_content_store;
}
-ListenerSet *forwarder_GetListenerSet(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return forwarder->listenerSet;
+void
+forwarder_content_store_set_serve(forwarder_t * forwarder, bool val)
+{
+ assert(forwarder);
+ forwarder->serve_from_content_store = val;
}
-void forwarder_SetChacheStoreFlag(Forwarder *forwarder, bool val) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- messageProcessor_SetCacheStoreFlag(forwarder->processor, val);
+bool
+forwarder_content_store_get_serve(forwarder_t * forwarder)
+{
+ assert(forwarder);
+ return forwarder->serve_from_content_store;
}
-bool forwarder_GetChacheStoreFlag(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return messageProcessor_GetCacheStoreFlag(forwarder->processor);
+void
+forwarder_content_store_set_size(forwarder_t * forwarder, size_t size)
+{
+ assert(forwarder);
+
+ content_store_free(forwarder->content_store);
+
+ // XXX TODO
+#if 0
+ ContentStoreConfig content_storeConfig = {.objectCapacity =
+ maximumContentStoreSize};
+
+ forwarder->content_store =
+ content_storeLRU_Create(&content_storeConfig, forwarder->logger);
+#endif
}
-void forwarder_SetChacheServeFlag(Forwarder *forwarder, bool val) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- messageProcessor_SetCacheServeFlag(forwarder->processor, val);
+void
+forwarder_content_store_clear(forwarder_t * forwarder)
+{
+ assert(forwarder);
+
+ content_store_clear(forwarder->content_store);
}
-bool forwarder_GetChacheServeFlag(Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return messageProcessor_GetCacheServeFlag(forwarder->processor);
+void
+forwarder_receive_command(forwarder_t * forwarder, command_type_t command_type,
+ uint8_t * packet, unsigned connection_id)
+{
+ configuration_receive_command(forwarder->config, command_type, packet, connection_id);
}
-void forwarder_ReceiveCommand(Forwarder *forwarder, command_id command,
- struct iovec *message, unsigned ingressId) {
- configuration_ReceiveCommand(forwarder->config, command, message, ingressId);
+/**
+ * @function forwarder_Drop
+ * @abstract Whenever we "drop" a message, increment countes
+ * @discussion
+ * This is a bookkeeping function. It increments the appropriate counters.
+ *
+ * The default action for a message is to destroy it in
+ * <code>forwarder_Receive()</code>, so this function does not need to do
+ * that.
+ *
+ */
+static
+void
+forwarder_drop(forwarder_t * forwarder, msgbuf_t *message)
+{
+ forwarder->stats.countDropped++;
+
+ switch (msgbuf_get_type(message)) {
+ case MESSAGE_TYPE_INTEREST:
+ forwarder->stats.countInterestsDropped++;
+ break;
+
+ case MESSAGE_TYPE_DATA:
+ forwarder->stats.countObjectsDropped++;
+ break;
+
+ default:
+ forwarder->stats.countOtherDropped++;
+ break;
+ }
+
+ // dont destroy message here, its done at end of receive
}
-void forwarder_Receive(Forwarder *forwarder, Message *message) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- parcAssertNotNull(message, "Parameter message must be non-null");
+/*
+ * 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
+forwarder_forward_via_connection(forwarder_t * forwarder, msgbuf_t * msgbuf,
+ unsigned conn_id)
+{
+ connection_table_t * table = forwarder_get_connection_table(forwarder);
+ const connection_t * conn = connection_table_get_by_id(table, conn_id);
+
+ if (!conn) {
+ forwarder->stats.countDroppedConnectionNotFound++;
+ DEBUG("forward msgbuf %p to interface %u not found (count %u)",
+ msgbuf, conn_id, forwarder->stats.countDroppedConnectionNotFound);
+ forwarder_drop(forwarder, msgbuf);
+ return;
+ }
- // this takes ownership of the message, so we're done here
+ /* Always queue the packet... */
+ bool success = connection_send(conn, msgbuf, true);
- // 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));
+ /* ... and mark the connection as pending if this is not yet the case */
+ unsigned i;
+ for (i = 0; i < forwarder->num_pending_conn; i++) {
+ if (forwarder->pending_conn[i] == conn_id)
+ break;
+ }
+ if (i == forwarder->num_pending_conn)
+ forwarder->pending_conn[forwarder->num_pending_conn++] = conn_id;
- if (!conn) {
- return;
- }
+ if (!success) {
+ forwarder->stats.countSendFailures++;
- 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);
+ DEBUG("forward msgbuf %p to interface %u send failure (count %u)", msgbuf,
+ conn_id, forwarder->stats.countSendFailures);
+ forwarder_drop(forwarder, msgbuf);
+ return;
}
- // 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);
+
+ switch (msgbuf_get_type(msgbuf)) {
+ case MESSAGE_TYPE_INTEREST:
+ forwarder->stats.countInterestForwarded++;
+ break;
+
+ case MESSAGE_TYPE_DATA:
+ forwarder->stats.countObjectsForwarded++;
+ break;
+
+ default:
+ break;
}
- }
- messageProcessor_Receive(forwarder->processor, message);
+ DEBUG("forward msgbuf %p to interface %u (int %u, obj %u)", msgbuf,
+ conn_id, forwarder->stats.countInterestForwarded,
+ forwarder->stats.countObjectsForwarded);
+
}
-Ticks forwarder_GetTicks(const Forwarder *forwarder) {
- parcAssertNotNull(forwarder, "Parameter must be non-null");
- return parcClock_GetTime(forwarder->clock) + forwarder->clockOffset;
+/**
+ * @function forwarder_forward_to_nexthops
+ * @abstract Try to forward to each nexthop listed in the NumberSet
+ * @discussion
+ * Will not forward to the ingress connection.
+ *
+ * @return The number of nexthops tried
+ */
+static
+unsigned
+forwarder_forward_to_nexthops(forwarder_t * forwarder,
+ msgbuf_t *msgbuf, const nexthops_t * nexthops)
+{
+ unsigned forwardedCopies = 0;
+
+ unsigned ingressId = msgbuf_get_connection_id(msgbuf);
+ uint32_t old_path_label = 0;
+
+ if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA)
+ old_path_label = msgbuf_get_pathlabel(msgbuf);
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ if (nexthop == ingressId)
+ continue;
+
+ forwardedCopies++;
+ forwarder_forward_via_connection(forwarder, msgbuf, nexthop);
+
+ // 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.
+ if (msgbuf_get_type(msgbuf) == MESSAGE_TYPE_DATA)
+ msgbuf_set_pathlabel(msgbuf, old_path_label);
+ });
+
+ return forwardedCopies;
}
-Ticks forwarder_NanosToTicks(uint64_t nanos) { return NSEC_TO_TICKS(nanos); }
-uint64_t forwarder_TicksToNanos(Ticks ticks) {
- return (1000000000ULL) * ticks / HZ;
-}
+static
+bool
+forwarder_forward_via_fib(forwarder_t * forwarder, msgbuf_t *msgbuf,
+ pit_verdict_t verdict)
+{
+ assert(forwarder);
+ assert(msgbuf);
+ assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+
+ fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf);
+ if (!fib_entry)
+ return false;
+
+ // XXX TODO PROBE HOOK MIGHT BE HANDLED ELSEWHERE
+ if (msgbuf_is_probe(msgbuf)) {
+ connection_table_t * table = forwarder_get_connection_table(forwarder);
+ const nexthops_t * nexthops = fib_entry_get_nexthops(fib_entry);
+
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ connection_t * conn = connection_table_at(table, nexthop);
+ if (!conn)
+ continue;
+ if (!connection_is_local(conn))
+ continue;
+ uint8_t * packet = msgbuf_get_packet(msgbuf);
+ unsigned size = msgbuf_get_len(msgbuf);
+ connection_t * reply_connection = connection_table_get_by_id(table,
+ msgbuf_get_connection_id(msgbuf));
+ if (messageHandler_IsInterest(packet)) {
+ messageHandler_CreateProbeReply(packet, HF_INET6_TCP);
+ connection_send_packet(reply_connection, packet, size);
+ }
+ return false;
+ });
+ }
+
+ pit_entry_t * entry = pit_lookup(forwarder->pit, msgbuf);
+ if (!entry)
+ return false;
+
+ pit_entry_set_fib_entry(entry, fib_entry);
-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");
+ const nexthops_t * nexthops = fib_entry_get_nexthops_from_strategy(fib_entry,
+ msgbuf, verdict);
- // we only have one message processor
- bool res =
- messageProcessor_AddOrUpdateRoute(forwarder->processor, control, ifidx);
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ pit_entry_egress_add(entry, nexthop);
+ });
+
+ // 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)
+
+#if 0
+ // The function GetPitEntry encreases the ref counter in the pit entry
+ // we need to decrease it
+ entry_Release(&entry);
+#endif
+
+ if (forwarder_forward_to_nexthops(forwarder, msgbuf, nexthops) <= 0) {
+ DEBUG("Message %p returned an emtpy next hop set", msgbuf);
+ return false;
+ }
+ return true;
- 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");
+static
+bool
+_satisfy_from_content_store(forwarder_t * forwarder, msgbuf_t *interest_msgbuf)
+{
+ assert(forwarder);
+ assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+
+ if (msgbuf_get_interest_lifetime(interest_msgbuf) == 0)
+ return false;
+
+ if (!forwarder->serve_from_content_store)
+ return false;
+
+ // See if there's a match in the store.
+ msgbuf_t * data_msgbuf = content_store_match(forwarder->content_store,
+ interest_msgbuf, ticks_now());
+
+ if (!data_msgbuf)
+ return false;
+
+ // Remove it from the PIT. nexthops is allocated, so need to destroy
+ nexthops_t * nexthops = pit_on_data(forwarder->pit, data_msgbuf);
+ assert(nexthops); // Illegal state: got a null nexthops for an interest we just inserted
+
+ // send message in reply, then done
+ forwarder->stats.countInterestsSatisfiedFromStore++;
+
+ DEBUG("Message %p satisfied from content store (satisfied count %u)",
+ interest_msgbuf, forwarder->stats.countInterestsSatisfiedFromStore);
- // we only have one message processor
- return messageProcessor_RemoveRoute(forwarder->processor, control, ifidx);
+ msgbuf_reset_pathlabel(data_msgbuf);
+
+ forwarder_forward_to_nexthops(forwarder, data_msgbuf, nexthops);
+
+ return true;
}
-#ifdef WITH_POLICY
+/**
+ * @function forwarder_receive_interest
+ * @abstract Receive an interest from the network
+ * @discussion
+ * (1) if interest in the PIT, aggregate in PIT
+ * (2) if interest in the ContentStore, reply
+ * (3) if in the FIB, forward
+ * (4) drop
+ *
+ */
+static
+void
+forwarder_receive_interest(forwarder_t * forwarder, msgbuf_t * msgbuf)
+{
+ assert(forwarder);
+ assert(msgbuf);
+ assert(msgbuf_get_type(msgbuf) == MESSAGE_TYPE_INTEREST);
+ forwarder->stats.countInterestsReceived++;
+
+ // (1) Try to aggregate in PIT
+ pit_verdict_t verdict = pit_on_interest(forwarder->pit, msgbuf);
+ switch(verdict) {
+ case PIT_VERDICT_AGGREGATE:
+ forwarder->stats.countInterestsAggregated++;
+ DEBUG("Message %p aggregated in PIT (aggregated count %u)",
+ msgbuf, forwarder->stats.countInterestsAggregated);
+ return;
+
+ case PIT_VERDICT_FORWARD:
+ case PIT_VERDICT_RETRANSMIT:
+ DEBUG("Message %p not aggregated in PIT (aggregated count %u)",
+ msgbuf, forwarder->stats.countInterestsAggregated);
+ break;
+ }
+
+ // At this point, we just created a PIT entry. If we don't forward the
+ // interest, we need to remove the PIT entry.
-bool forwarder_AddOrUpdatePolicy(Forwarder *forwarder,
- add_policy_command *control) {
- parcAssertNotNull(forwarder, "Parameter forwarder must be non-null");
- parcAssertNotNull(control, "Parameter control must be non-null");
+ // (2) Try to satisfy from content store
+ if (_satisfy_from_content_store(forwarder, msgbuf)) {
+ // done
+ // If we found a content object in the CS,
+ // messageProcess_Satisfy_from_content_store already cleared the PIT state
+ return;
+ }
+
+ // (3) Try to forward it
+ if (forwarder_forward_via_fib(forwarder, msgbuf, verdict)) {
+ // done
+ return;
+ }
- return messageProcessor_AddOrUpdatePolicy(forwarder->processor, control);
+ // Remove the PIT entry?
+ forwarder->stats.countDroppedNoRoute++;
+
+ DEBUG("Message %p did not match FIB, no route (count %u)",
+ msgbuf, forwarder->stats.countDroppedNoRoute);
+
+ forwarder_drop(forwarder, msgbuf);
}
-bool forwarder_RemovePolicy(Forwarder *forwarder, remove_policy_command *control) {
- parcAssertNotNull(forwarder, "Parameter forwarder must be non-null");
- parcAssertNotNull(control, "Parameter control must be non-null");
+/**
+ * @function forwarder_receive_data
+ * @abstract Process an in-bound content object
+ * @discussion
+ * (1) If it does not match anything in the PIT, drop it
+ * (2) Add to Content Store
+ * (3) Reverse path forward via PIT entries
+ *
+ * @param <#param1#>
+ */
+static
+void
+forwarder_receive_data(forwarder_t * forwarder,
+ msgbuf_t *msgbuf)
+{
+ forwarder->stats.countObjectsReceived++;
+
+ nexthops_t * ingressSetUnion = pit_on_data(forwarder->pit, msgbuf);
+ if (!ingressSetUnion) {
+ // (1) If it does not match anything in the PIT, drop it
+ forwarder->stats.countDroppedNoReversePath++;
+
+ DEBUG("Message %p did not match PIT, no reverse path (count %u)",
+ msgbuf, forwarder->stats.countDroppedNoReversePath);
+
+ // MOVE PROBE HOOK ELSEWHERE
+ // XXX relationship with forwarding strategy... insert hooks
+ // if the packet is a probe we need to analyze it
+ // NOTE : probes are not stored in PIT
+ if (msgbuf_is_probe(msgbuf)) {
+ fib_entry_t *entry = fib_match_message(forwarder->fib, msgbuf);
+ if (entry && fib_entry_strategy_type(entry) == STRATEGY_TYPE_LOW_LATENCY) {
+ nexthops_t probe_nexthops;
+ nexthops_add(&probe_nexthops, msgbuf_get_connection_id(msgbuf));
+ fib_entry_on_data(entry, &probe_nexthops, msgbuf, 0, ticks_now());
+
+ // XXX TODO CONFIRM WE DON'T EXIT HERE ?
+ }
+ }
+
+ // 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
+ const connection_table_t * table = forwarder_get_connection_table(forwarder);
+ const connection_t * conn = connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
+
+ if (forwarder->store_in_content_store && connection_is_local(conn)) {
+ content_store_add(forwarder->content_store, msgbuf, ticks_now());
+ DEBUG("Message %p store in CS anyway", msgbuf);
+ }
+
+ forwarder_drop(forwarder, msgbuf);
+ } else {
+ // (2) Add to Content Store. Store may remove expired content, if necessary,
+ // depending on store policy.
+ if (forwarder->store_in_content_store) {
+ content_store_add(forwarder->content_store, msgbuf, ticks_now());
+ }
+ // (3) Reverse path forward via PIT entries
+ forwarder_forward_to_nexthops(forwarder, msgbuf, ingressSetUnion);
- return messageProcessor_RemovePolicy(forwarder->processor, control);
+ }
}
-#endif /* WITH_POLICY */
-void forwarder_RemoveConnectionIdFromRoutes(Forwarder *forwarder,
- unsigned connectionId) {
- parcAssertNotNull(forwarder, "Parameter hicn-light must be non-null");
- messageProcessor_RemoveConnectionIdFromRoutes(forwarder->processor,
- connectionId);
+/**
+ * A NULL msgbuf is used to indicate the end of a batch
+ */
+void
+forwarder_receive(forwarder_t * forwarder, msgbuf_t * msgbuf)
+{
+ assert(forwarder);
+
+ /* Send batch ? */
+ if (!msgbuf) {
+ const connection_table_t * table = forwarder_get_connection_table(forwarder);
+ for (unsigned i = 0; i < forwarder->num_pending_conn; i++) {
+