aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/strategies
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/hicn/strategies')
-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/strategies/loadBalancer.h)16
-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/rnd.h)12
-rw-r--r--hicn-light/src/hicn/strategies/rnd.c211
-rw-r--r--hicn-light/src/hicn/strategies/strategyImpl.h73
15 files changed, 1166 insertions, 2148 deletions
diff --git a/hicn-light/src/hicn/strategies/CMakeLists.txt b/hicn-light/src/hicn/strategies/CMakeLists.txt
index 400efcde9..d7a5e7333 100644
--- a/hicn-light/src/hicn/strategies/CMakeLists.txt
+++ b/hicn-light/src/hicn/strategies/CMakeLists.txt
@@ -14,20 +14,15 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/strategyImpl.h
- ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/lowLatency.h
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.h
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateLowLatency.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rnd.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/random.h
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.c
- ${CMAKE_CURRENT_SOURCE_DIR}/lowLatency.c
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopState.c
- ${CMAKE_CURRENT_SOURCE_DIR}/nexthopStateLowLatency.c
- ${CMAKE_CURRENT_SOURCE_DIR}/rnd.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/random.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/strategies/loadBalancer.c b/hicn-light/src/hicn/strategies/loadBalancer.c
deleted file mode 100644
index 878a58515..000000000
--- a/hicn-light/src/hicn/strategies/loadBalancer.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_Unsigned.h>
-
-#include <hicn/strategies/loadBalancer.h>
-#include <hicn/strategies/nexthopState.h>
-
-static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-static void _strategyLoadBalancer_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId);
-static NumberSet *_strategyLoadBalancer_LookupNexthop(
- StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
-static NumberSet *_strategyLoadBalancer_ReturnNexthops(StrategyImpl *strategy);
-static unsigned _strategyLoadBalancer_CountNexthops(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
-static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLoadBalancer_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLoadBalancer_ImplDestroy(StrategyImpl **strategyPtr);
-static strategy_type _strategyLoadBalancer_GetStrategy(StrategyImpl *strategy);
-
-static StrategyImpl _template = {
- .context = NULL,
- .receiveObject = &_strategyLoadBalancer_ReceiveObject,
- .onTimeout = &_strategyLoadBalancer_OnTimeout,
- .lookupNexthop = &_strategyLoadBalancer_LookupNexthop,
-#ifndef WITH_POLICY
- .returnNexthops = &_strategyLoadBalancer_ReturnNexthops,
- .countNexthops = &_strategyLoadBalancer_CountNexthops,
-#endif /* ! WITH_POLICY */
- .addNexthop = &_strategyLoadBalancer_AddNexthop,
- .removeNexthop = &_strategyLoadBalancer_RemoveNexthop,
- .destroy = &_strategyLoadBalancer_ImplDestroy,
- .getStrategy = &_strategyLoadBalancer_GetStrategy,
-};
-
-struct strategy_load_balancer;
-typedef struct strategy_load_balancer StrategyLoadBalancer;
-
-struct strategy_load_balancer {
-#ifndef WITH_POLICY
- double weights_sum;
-#endif /* ! WITH_POLICY */
- // hash map from connectionId to StrategyNexthopState
- PARCHashMap *strategy_state;
-#ifndef WITH_POLICY
- NumberSet *nexthops;
-#endif /* ! WITH_POLICY */
-};
-
-StrategyImpl *strategyLoadBalancer_Create() {
- StrategyLoadBalancer *strategy =
- parcMemory_AllocateAndClear(sizeof(StrategyLoadBalancer));
- parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyLoadBalancer));
-
-#ifndef WITH_POLICY
- strategy->weights_sum = 0.0;
-#endif /* ! WITH_POLICY */
- strategy->strategy_state = parcHashMap_Create();
-#ifndef WITH_POLICY
- strategy->nexthops = numberSet_Create();
-#endif /* ! WITH_POLICY */
- srand((unsigned int)time(NULL));
-
- StrategyImpl *impl = parcMemory_AllocateAndClear(sizeof(StrategyImpl));
- parcAssertNotNull(impl, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyImpl));
- memcpy(impl, &_template, sizeof(StrategyImpl));
- impl->context = strategy;
-
- return impl;
-}
-
-// =======================================================
-// Dispatch API
-
-strategy_type _strategyLoadBalancer_GetStrategy(StrategyImpl *strategy) {
- return SET_STRATEGY_LOADBALANCER;
-}
-
-static void _update_Stats(StrategyLoadBalancer *strategy,
- StrategyNexthopState *state, bool inc) {
- const double ALPHA = 0.9;
-#ifdef WITH_POLICY
- strategyNexthopState_UpdateState(state, inc, ALPHA);
-#else
- double w = strategyNexthopState_GetWeight(state);
- strategy->weights_sum -= w;
- w = strategyNexthopState_UpdateState(state, inc, ALPHA);
- strategy->weights_sum += w;
-#endif /* WITH_POLICY */
-}
-
-#ifndef WITH_POLICY
-static unsigned _select_Nexthop(StrategyLoadBalancer *strategy) {
- double rnd = (double)rand() / (double)RAND_MAX;
- double start_range = 0.0;
-
- PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
-
- unsigned nexthop = 100000;
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- const StrategyNexthopState *elem =
- parcHashMap_Get(strategy->strategy_state, cid);
-
- double w = strategyNexthopState_GetWeight(elem);
-
- double prob = w / strategy->weights_sum;
- if ((rnd >= start_range) && (rnd <= (start_range + prob))) {
- nexthop = parcUnsigned_GetUnsigned(cid);
- break;
- } else {
- start_range += prob;
- }
- }
-
- parcIterator_Release(&it);
-
- // if no face is selected by the algorithm (for example because of a wrong
- // round in the weights) we may always select the last face here. Double check
- // this!
- return nexthop;
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyLoadBalancer_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {
- _strategyLoadBalancer_OnTimeout(strategy, egressId);
-}
-
-static void _strategyLoadBalancer_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-
- for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
- unsigned outId = numberSet_GetItem(egressId, i);
- PARCUnsigned *cid = parcUnsigned_Create(outId);
-
- const StrategyNexthopState *state =
- parcHashMap_Get(lb->strategy_state, cid);
- if (state != NULL) {
- _update_Stats(lb, (StrategyNexthopState *)state, false);
- } else {
- // this may happen if we remove a face/route while downloading a file
- // we should ignore this timeout
- }
- parcUnsigned_Release(&cid);
- }
-}
-
-static NumberSet *_strategyLoadBalancer_LookupNexthop(
- StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
- NumberSet *outList = numberSet_Create();
-
-#ifdef WITH_POLICY
- /* Compute the sum of weights of potential next hops */
- double sum = 0;
- for (unsigned i = 0; i < numberSet_Length(nexthops); i++) {
- PARCUnsigned *cid = parcUnsigned_Create(numberSet_GetItem(nexthops, i));
- const StrategyNexthopState *elem =
- parcHashMap_Get(lb->strategy_state, cid);
- parcUnsigned_Release(&cid);
- if (!elem)
- continue;
- sum += strategyNexthopState_GetWeight(elem);
- }
-
- /* Perform weighted random selection */
- double distance = (double)rand() * sum / ((double)RAND_MAX + 1);
-
- for (unsigned i = 0; i < numberSet_Length(nexthops); i++) {
- PARCUnsigned *cid = parcUnsigned_Create(numberSet_GetItem(nexthops, i));
- const StrategyNexthopState *state =
- parcHashMap_Get(lb->strategy_state, cid);
- if (!state){
- parcUnsigned_Release(&cid);
- continue;
- }
- distance -= strategyNexthopState_GetWeight(state);
- if (distance < 0) {
- numberSet_Add(outList, parcUnsigned_GetUnsigned(cid));
- _update_Stats(lb, (StrategyNexthopState *)state, true);
- parcUnsigned_Release(&cid);
- break;
- }
- }
-#else
- unsigned in_connection = message_GetIngressConnectionId(interestMessage);
- PARCUnsigned *in = parcUnsigned_Create(in_connection);
-
- unsigned mapSize = (unsigned)parcHashMap_Size(lb->strategy_state);
-
- if ((mapSize == 0) ||
- ((mapSize == 1) && parcHashMap_Contains(lb->strategy_state, in))) {
- // there are no output faces or the input face is also the only output face.
- // return null to avoid loops
- parcUnsigned_Release(&in);
- return outList;
- }
-
- unsigned out_connection;
- do {
- out_connection = _select_Nexthop(lb);
- } while (out_connection == in_connection);
-
- PARCUnsigned *out = parcUnsigned_Create(out_connection);
-
- const StrategyNexthopState *state = parcHashMap_Get(lb->strategy_state, out);
- if (state == NULL) {
- // this is an error and should not happen!
- parcTrapNotImplemented(
- "Try to send an interest on a face that does not exists");
- }
-
- _update_Stats(lb, (StrategyNexthopState *)state, true);
-
- parcUnsigned_Release(&in);
- parcUnsigned_Release(&out);
-
- numberSet_Add(outList, out_connection);
-#endif /* WITH_POLICY */
-
- return outList;
-}
-
-#ifndef WITH_POLICY
-static NumberSet *_strategyLoadBalancer_ReturnNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
- return lb->nexthops;
-}
-
-unsigned _strategyLoadBalancer_CountNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
- return (unsigned)numberSet_Length(lb->nexthops);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyLoadBalancer_resetState(StrategyImpl *strategy) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-#ifndef WITH_POLICY
- lb->weights_sum = 0.0;
-#endif/* ! WITH_POLICY */
- PARCIterator *it = parcHashMap_CreateKeyIterator(lb->strategy_state);
-
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- StrategyNexthopState *elem =
- (StrategyNexthopState *)parcHashMap_Get(lb->strategy_state, cid);
-
- strategyNexthopState_Reset(elem);
-#ifndef WITH_POLICY
- lb->weights_sum += strategyNexthopState_GetWeight(elem);
-#endif /* ! WITH_POLICY */
- }
-
- parcIterator_Release(&it);
-}
-
-static void _strategyLoadBalancer_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
-
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-
- if (!parcHashMap_Contains(lb->strategy_state, cid)) {
- StrategyNexthopState *state = strategyNexthopState_Create();
- parcHashMap_Put(lb->strategy_state, cid, state);
-#ifndef WITH_POLICY
- numberSet_Add(lb->nexthops, connectionId);
-#endif /* WITH_POLICY */
- _strategyLoadBalancer_resetState(strategy);
- }
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLoadBalancer_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
- StrategyLoadBalancer *lb = (StrategyLoadBalancer *)strategy->context;
-
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- if (parcHashMap_Contains(lb->strategy_state, cid)) {
- StrategyNexthopState *state =
- (StrategyNexthopState *)parcHashMap_Get(lb->strategy_state, cid);
- parcObject_Release((void**)&state);
-
- parcHashMap_Remove(lb->strategy_state, cid);
-#ifndef WITH_POLICY
- numberSet_Remove(lb->nexthops, connectionId);
-#endif /* WITH_POLICY */
- _strategyLoadBalancer_resetState(strategy);
- }
-
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLoadBalancer_ImplDestroy(StrategyImpl **strategyPtr) {
- parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*strategyPtr,
- "Parameter must dereference to non-null pointer");
-
- StrategyImpl *impl = *strategyPtr;
- StrategyLoadBalancer *strategy = (StrategyLoadBalancer *)impl->context;
- if (parcHashMap_Size(strategy->strategy_state) > 0) {
- PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- StrategyNexthopState *state =
- (StrategyNexthopState *) parcHashMap_Get(strategy->strategy_state, cid);
- parcObject_Release((void **) &state);
- }
- parcIterator_Release(&it);
-
- parcHashMap_Release(&(strategy->strategy_state));
-#ifndef WITH_POLICY
- numberSet_Release(&(strategy->nexthops));
-#endif /* ! WITH_POLICY */
-
- parcMemory_Deallocate((void **) &strategy);
- parcMemory_Deallocate((void **) &impl);
- *strategyPtr = NULL;
- }
-}
diff --git a/hicn-light/src/hicn/strategies/load_balancer.c b/hicn-light/src/hicn/strategies/load_balancer.c
new file mode 100644
index 000000000..9f4ba825d
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/load_balancer.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <hicn/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+#include <hicn/core/nexthops.h>
+#include <hicn/core/fib_entry.h>
+
+#include "load_balancer.h"
+
+#define AVG_PI_THRESHOLD 1e-3
+#define AVG_PI_MIN 0.1
+
+#define ALPHA 0.9
+
+#define NEXTHOP_STATE_INIT { \
+ .pi = 0, \
+ .avg_pi = 0.0, \
+ .weight = 1, \
+}
+
+/* Shorthand */
+#define nexthop_state_t strategy_load_balancer_nexthop_state_t
+
+#define update_state(state) \
+do { \
+ state->avg_pi = (state->avg_pi * ALPHA) + \
+ (state->pi * 1 - ALPHA); \
+ if (state->avg_pi < AVG_PI_THRESHOLD) \
+ state->avg_pi = AVG_PI_MIN; \
+ state->weight = 1 / state->avg_pi; \
+} while(0)
+
+#define update_state_inc(state) \
+do { \
+ state->pi++; \
+ update_state(state); \
+} while(0)
+
+#define update_state_dec(state) \
+do { \
+ if (state->pi > 0) \
+ state->pi--; \
+ update_state(state); \
+} while(0)
+
+#if 0
+#define reset_all(nexthops, nexthops_state) \
+do { \
+ unsigned _lb_var(nexthop); \
+ nexthops_foreach((state), _lb_var(nexthop), { \
+ (nexthop) = NEXTHOP_STATE_INIT; \
+ }); \
+} while(0)
+#else
+#define reset_all(state)
+#endif
+
+static
+void
+strategy_load_balancer_initialize(strategy_entry_t * entry)
+{
+ // XXXreset_all(entry->state);
+ // XXX TODO initialize nexthops
+ // XXX maybe merge with nexthop data structure
+}
+
+static
+void
+strategy_load_balancer_finalize(strategy_entry_t * entry)
+{
+ /* Nothing to do */
+}
+
+static
+void
+strategy_load_balancer_add_nexthop(strategy_entry_t * entry, unsigned nexthop,
+ strategy_nexthop_state_t * state)
+{
+ // Create and reset associated state
+ // if this is really a new nexthop
+ // XXX assume nexthop is inserted before
+ reset_all(state);
+}
+
+static
+void
+strategy_load_balancer_remove_nexthop(strategy_entry_t * entry, unsigned
+ nexthop, strategy_nexthop_state_t * state)
+{
+ reset_all(state);
+}
+
+static
+nexthops_t *
+strategy_load_balancer_lookup_nexthops(strategy_entry_t * entry,
+ nexthops_t * nexthops, const msgbuf_t * msgbuf)
+{
+// TEMP
+ nexthop_state_t * state = NULL;
+
+ /* Compute the sum of weights of potential next hops */
+ double sum = 0;
+ unsigned i, nexthop;
+ nexthops_enumerate(nexthops, i, nexthop, {
+ (void)nexthop;
+ sum += nexthops_state(nexthops, i).load_balancer.weight;
+ });
+
+ /* Perform weighted random selection */
+ double distance = (double)rand() * sum / ((double)RAND_MAX + 1);
+
+ nexthops_enumerate(nexthops, i, nexthop, {
+ // XXX distance -= nexthop_state(nexthops, i).weight;
+ if (distance < 0) {
+ nexthops_select(nexthops, i);
+ update_state_inc(state); // XXX
+ break;
+ }
+ });
+ return nexthops;
+}
+
+static
+void
+strategy_load_balancer_on_timeout(strategy_entry_t * entry,
+ const nexthops_t * nexthops)
+{
+ /*
+ * As we have few nexthops in FIB entry, and even fewer selected ones in
+ * nexthops, we can allow for linear search that will be very efficient
+ * CPU-wise.
+ */
+// XXX TODO
+#if 0
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ // XXX TODO leverage coexistence between nexthop and state
+ if (correct_nexthop_id(nexthop))
+ update_state_dec(&entry.state.nexthop_state);
+ });
+#endif
+}
+
+static
+void
+strategy_load_balancer_on_data(strategy_entry_t * entry,
+ const nexthops_t * nexthops, const msgbuf_t * msgbuf,
+ Ticks pitEntryCreation, Ticks objReception)
+{
+ strategy_load_balancer_on_timeout(entry, nexthops);
+}
+
+DECLARE_STRATEGY(load_balancer);
+
+#undef nexthop_state_t
diff --git a/hicn-light/src/hicn/strategies/loadBalancer.h b/hicn-light/src/hicn/strategies/load_balancer.h
index 74920768d..f2acc205e 100644
--- a/hicn-light/src/hicn/strategies/loadBalancer.h
+++ b/hicn-light/src/hicn/strategies/load_balancer.h
@@ -17,11 +17,17 @@
* Forward on the less loaded path
*/
-#ifndef loadBalancer_h
-#define loadBalancer_h
+#ifndef HICNLIGHT_STRATEGY_LOAD_BALANCER_H
+#define HICNLIGHT_STRATEGY_LOAD_BALANCER_H
-#include <hicn/strategies/strategyImpl.h>
+typedef struct {
+ unsigned int pi;
+ double avg_pi;
+ double weight;
+} strategy_load_balancer_nexthop_state_t;
-StrategyImpl *strategyLoadBalancer_Create();
+typedef struct {} strategy_load_balancer_state_t;
-#endif // loadBalancer_h
+typedef struct {} strategy_load_balancer_options_t;
+
+#endif /* HICNLIGHT_STRATEGY_LOAD_BALANCER_H */
diff --git a/hicn-light/src/hicn/strategies/lowLatency.c b/hicn-light/src/hicn/strategies/lowLatency.c
deleted file mode 100644
index 61bffe243..000000000
--- a/hicn-light/src/hicn/strategies/lowLatency.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <math.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-#include <parc/algol/parc_Unsigned.h>
-
-#include <hicn/core/messageHandler.h>
-
-#include <hicn/strategies/lowLatency.h>
-#include <hicn/strategies/nexthopStateLowLatency.h>
-
-const unsigned STABILITY_FACTOR = 15;
-const unsigned MAX_SWITCH_TRY = 10;
-const unsigned MAX_LATENCY_DIFF = 10;
-const unsigned MAX_TOLLERATED_LATENCY_DIFF = 15;
-const unsigned MAX_ROUNDS_MP_WITHOUT_CHECK = 2;
-const unsigned MAX_ROUNDS_AVOIDING_MULTIPATH = 40; //about 20 sec
-const unsigned MAX_ROUNDS_WITH_ERROR = 4;
-const unsigned PROBE_LIFETIME = 500; //ms
-
-static void _strategyLowLatency_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-static void _strategyLowLatency_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId);
-static NumberSet *_strategyLowLatency_LookupNexthop(
- StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
-static NumberSet *_strategyLowLatency_ReturnNexthops(StrategyImpl *strategy);
-static unsigned _strategyLowLatency_CountNexthops(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
-static void _strategyLowLatency_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLowLatency_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyLowLatency_ImplDestroy(StrategyImpl **strategyPtr);
-static strategy_type _strategyLowLatency_GetStrategy(StrategyImpl *strategy);
-
-static StrategyImpl _template = {
- .context = NULL,
- .receiveObject = &_strategyLowLatency_ReceiveObject,
- .onTimeout = &_strategyLowLatency_OnTimeout,
- .lookupNexthop = &_strategyLowLatency_LookupNexthop,
-#ifndef WITH_POLICY
- .returnNexthops = &_strategyLowLatency_ReturnNexthops,
- .countNexthops = &_strategyLowLatency_CountNexthops,
-#endif /* ! WITH_POLICY */
- .addNexthop = &_strategyLowLatency_AddNexthop,
- .removeNexthop = &_strategyLowLatency_RemoveNexthop,
- .destroy = &_strategyLowLatency_ImplDestroy,
- .getStrategy = &_strategyLowLatency_GetStrategy,
-};
-
-struct strategy_low_latency;
-typedef struct strategy_low_latency StrategyLowLatency;
-
-struct strategy_low_latency {
- // hash map from connectionId to StrategyNexthopStateLL
- PARCHashMap *strategy_state;
- //hash map from sequence number to ticks (sent time)
- PARCHashMap *pending_probes_ticks;
- //hash map from sequence number to face id
- PARCHashMap *pending_probes_faces;
- const Forwarder * forwarder;
- PARCEventTimer *sendProbes;
- PARCEventTimer *computeBestFace;
- uint8_t * probe;
- hicn_name_t * name;
- StrategyNexthopStateLL * bestFaces[2];
- unsigned round;
- unsigned rounds_in_multipath;
- unsigned rounds_with_error;
- unsigned rounds_avoiding_multipath;
- bool use2paths;
- bool avoid_multipath;
- unsigned related_prefixes_len;
- Name **related_prefixes;
-#ifndef WITH_POLICY
- NumberSet *nexthops;
-#endif /* ! WITH_POLICY */
-};
-
-static void strategyLowLatency_SendProbesCB(int fd, PARCEventType which_event,
- void *data){
- parcAssertTrue(which_event & PARCEventType_Timeout,
- "Event incorrect, expecting %X set, got %X",
- PARCEventType_Timeout, which_event);
-
- StrategyLowLatency *ll = (StrategyLowLatency *) data;
-
- //delete old pending probes
- if(parcHashMap_Size(ll->pending_probes_ticks) != 0){
- Ticks now = forwarder_GetTicks(ll->forwarder);
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->pending_probes_ticks);
- NumberSet *to_remove = numberSet_Create();
- while(parcIterator_HasNext(iterator)) {
- PARCUnsigned *parc_seq = (PARCUnsigned *) parcIterator_Next(iterator);
- PARCUnsigned *parc_time = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_ticks, parc_seq);
- Ticks sent_time = parcUnsigned_GetUnsigned(parc_time);
- if((now - sent_time) > PROBE_LIFETIME){
- //probes to delete
- numberSet_Add(to_remove, parcUnsigned_GetUnsigned(parc_seq));
- }
- }
- parcIterator_Release(&iterator);
-
- for(int i = 0; i < numberSet_Length(to_remove); i++){
- PARCUnsigned *prob_seq = parcUnsigned_Create(numberSet_GetItem(to_remove,i));
- PARCUnsigned *cid = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_faces, prob_seq);
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
- strategyNexthopStateLL_LostProbe(state);
- parcHashMap_Remove(ll->pending_probes_ticks, prob_seq);
- parcHashMap_Remove(ll->pending_probes_faces, prob_seq);
- parcUnsigned_Release(&prob_seq);
- }
- numberSet_Release(&to_remove);
- }
-
- ConnectionTable * ct = forwarder_GetConnectionTable(ll->forwarder);
-
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while(parcIterator_HasNext(iterator)){
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- Connection *conn =
- (Connection *)connectionTable_FindById(ct,
- parcUnsigned_GetUnsigned(cid));
- if(!conn)
- continue;
-
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
-
- //probe only usable paths
- if(!strategyNexthopStateLL_IsAllowed(state))
- continue;
-
- uint32_t seq = rand();
- messageHandler_SetProbeName(ll->probe, HF_INET6_TCP,
- ll->name, seq);
- connection_Probe(conn, ll->probe);
-
- PARCUnsigned *parc_seq = parcUnsigned_Create(seq);
- Ticks now = forwarder_GetTicks(ll->forwarder);
- PARCUnsigned *parc_time = parcUnsigned_Create((unsigned int)now);
- parcHashMap_Put(ll->pending_probes_ticks, parc_seq, parc_time);
- parcHashMap_Put(ll->pending_probes_faces, parc_seq, cid);
- strategyNexthopStateLL_SentProbe(state);
- parcUnsigned_Release(&parc_seq);
- parcUnsigned_Release(&parc_time);
- }
- parcIterator_Release(&iterator);
-
- struct timeval timeout = {0,50000};
- parcEventTimer_Start(ll->sendProbes, &timeout);
-}
-
-static void strategyLowLatency_SendMapmeUpdate(StrategyLowLatency *ll,
- const NumberSet * nexthops){
- MapMe * mapme = forwarder_getMapmeInstance(ll->forwarder);
- FIB * fib = forwarder_getFib((Forwarder*) ll->forwarder);
- if(fib != NULL){
- for(unsigned i = 0; i < ll->related_prefixes_len; i++){
- FibEntry *fibEntry = fib_MatchName(fib, ll->related_prefixes[i]);
- if(fibEntry != NULL){
- mapme_maybe_send_updates(mapme, fibEntry, nexthops);
- }
- }
- }
-}
-
-static void strategyLowLatency_SelectBestFaces(StrategyLowLatency *ll,
- bool new_round){
-
- StrategyNexthopStateLL * old_faces[2];
- old_faces[0] = ll->bestFaces[0];
- old_faces[1] = ll->bestFaces[1];
-
- if(new_round){
- ll->round++;
- }
-
- if(parcHashMap_Size(ll->strategy_state) == 0){
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- if(ll->use2paths && ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL){
- //multipath case
-
- if(!strategyNexthopStateLL_IsLossy(ll->bestFaces[0])
- && !strategyNexthopStateLL_IsLossy(ll->bestFaces[1])
- && strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])
- && strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
-
- if(ll->rounds_in_multipath < MAX_ROUNDS_MP_WITHOUT_CHECK){
- //we are at the first rounds of the multipath let's wait a bit
- //(MAX_ROUNDS_MP_WITHOUT_CHECK) to make the queuing converge
- ll->rounds_in_multipath++;
- goto NEW_ROUND;
- }
-
- //we need to decide if we want ot keep using two paths or not
- ll->rounds_in_multipath++;
- double rtt0 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
- double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
- double diff = fabs(rtt0 - rtt1);
-
- if(diff < MAX_LATENCY_DIFF){
- //everything is working, keep using the two paths
- ll->rounds_with_error = 0;
- goto NEW_ROUND;
- }
-
- //check for how many rounds we had problems
- if(ll->rounds_with_error < MAX_ROUNDS_WITH_ERROR &&
- diff < MAX_TOLLERATED_LATENCY_DIFF){
- //we can tollerate few round with errors
- ll->rounds_with_error++;
- goto NEW_ROUND;
- }
-
- //prevent the usage of multiple paths
- ll->rounds_with_error = 0;
- ll->avoid_multipath = true;
- ll->rounds_avoiding_multipath = 0;
- } //else
- //at least one of the two path is lossy
- //or it is not allowed by the policies.
- //search for a better possibility
- }
-
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
-
- //check if there is at least one non lossy connection
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- bool check_losses = true;
- bool found_good_face = false;
- while(parcIterator_HasNext(iterator) && !found_good_face){
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- const StrategyNexthopStateLL *state = parcHashMap_Get(ll->strategy_state, cid);
- if(!strategyNexthopStateLL_IsLossy(state) &&
- strategyNexthopStateLL_IsAllowed(state)){
- found_good_face = true;
- }
- }
- parcIterator_Release(&iterator);
- if(!found_good_face){
- // all the available faces are lossy, so we take into account only
- // the latency computed with the probes
- check_losses = false;
- }
-
- if(ll->bestFaces[0] == NULL){
- //try to take a random face
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- bool face_found = false;
- while(parcIterator_HasNext(iterator) && !face_found) {
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid);
-
- if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
- !strategyNexthopStateLL_IsAllowed(state)){
- //skip the face
- continue;
- }
-
- ll->bestFaces[0] = state;
- face_found = true;
- }
- parcIterator_Release(&iterator);
- }
-
- if(ll->bestFaces[0] == NULL){
- //no usable face exists
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- double bestRtt = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
-
- if(ll->avoid_multipath)
- ll->rounds_avoiding_multipath++;
-
- if(ll->rounds_avoiding_multipath > MAX_ROUNDS_AVOIDING_MULTIPATH){
- ll->avoid_multipath = false;
- ll->rounds_avoiding_multipath = 0;
- }
-
- iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while (parcIterator_HasNext(iterator)) {
-
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid);
- double rtt = strategyNexthopStateLL_GetRTTLive(state);
-
- if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
- !strategyNexthopStateLL_IsAllowed(state)){
- //skip the face
- continue;
- }
-
- if(rtt + STABILITY_FACTOR < bestRtt){
- //maybe we found a better face
- double rttInUse = strategyNexthopStateLL_GetRTTInUse(state);
- unsigned try = strategyNexthopStateLL_GetTryToSwitch(state);
-
- //we check the rtt in use to check if the new face that we found
- //gets congested when we use it to send the traffic
- if(rttInUse < bestRtt || try > MAX_SWITCH_TRY){
- //we have a new best face!
- strategyNexthopStateLL_ResetTryToSwitch((StrategyNexthopStateLL*) state);
- bestRtt = rtt;
- if(ll->bestFaces[0] != NULL)
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[0]);
- ll->bestFaces[0] = (StrategyNexthopStateLL*) state;
- }else{
- //in this case we should switch but we wait MAX_SWITCH_TRY
- //before switch to avoid ossillations between different paths
- strategyNexthopStateLL_IncreaseTryToSwitch(
- (StrategyNexthopStateLL*) state, ll->round);
- }
- }
- }
-
- parcIterator_Release(&iterator);
-
- if(ll->bestFaces[0] == NULL){
- //we found no face so return
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- if(parcHashMap_Size(ll->strategy_state) == 1 || ll->avoid_multipath){
- //in this case (one face available or avoid multipath) we stop the
- //search here. Just reset face 1 if needed
- if(ll->bestFaces[1] != NULL){
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
- ll->bestFaces[1] = NULL;
- }
- ll->use2paths = false;
- goto NEW_ROUND;
- }
-
- //if we are here we have more than 1 interface, so we search for a second one
- //to use in case of multipath
- iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while (parcIterator_HasNext(iterator)) {
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- if(parcUnsigned_GetUnsigned(cid) !=
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])){
-
- StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid);
-
- if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
- !strategyNexthopStateLL_IsAllowed(state)){
- //skip the face
- continue;
- }
-
- if(ll->bestFaces[1] == NULL){
- //in case of 2 faces we should pass always here
- ll->bestFaces[1] = state;
- }else{
- //TODO this must be tested with more then 2 faces
- double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
- double rttNewFace = strategyNexthopStateLL_GetRTTLive(state);
- if(rttNewFace + STABILITY_FACTOR < rtt1){
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
- ll->bestFaces[1] = state;
- }
- }
- }
- }
- parcIterator_Release(&iterator);
-
- if(ll->bestFaces[1] != NULL){
- //we are not using the second face yet so we use the normal rtt for comparison
- double rtt0 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[0]);
- double rtt1 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[1]);
- double diff = fabs(rtt0 - rtt1);
- if(diff < MAX_LATENCY_DIFF) {
- //let's start to use 2 paths
- ll->rounds_with_error = 0;
- ll->use2paths = true;
- ll->rounds_in_multipath = 0;
- }else{
- //we use only one path
- strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
- ll->bestFaces[1] = NULL;
- ll->use2paths = false;
- }
- }else{
- ll->use2paths = false;
- }
-
- NEW_ROUND:
- {
- Logger * log = forwarder_GetLogger(ll->forwarder);
- if(log != NULL &&
- logger_IsLoggable(log, LoggerFacility_Strategy, PARCLogLevel_Info)){
- if(ll->use2paths){
- logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
- __func__, "use 2 paths. rtt face %d = %f queue = %f is_lossy = %d,"
- "rtt face %d = %f queue = %f is_lossy = %d\n",
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
- strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
- strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]),
- strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]),
- strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]),
- strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]),
- strategyNexthopStateLL_IsLossy(ll->bestFaces[1]));
- }else{
- if(ll->bestFaces[0] != NULL){
- logger_Log(log, LoggerFacility_Strategy,
- PARCLogLevel_Info, __func__,
- "use 1 path. rtt face %d = %f is_lossy = %d, "
- "(avoid multipath = %d)\n",
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
- strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
- strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
- ll->avoid_multipath);
- }else{
- logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
- __func__, "no face to use!\n");
- }
- }
- }
- }
-
- //update the round only at the end for all the faces
- if(new_round){
- PARCIterator * iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while (parcIterator_HasNext(iterator)) {
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- strategyNexthopStateLL_StartNewRound((StrategyNexthopStateLL *)
- parcHashMap_Get(ll->strategy_state, cid));
- }
- parcIterator_Release(&iterator);
- }
-
- //mapme updates
- //if ll->bestFaces[0] == NULL we don't have any output faces
- //so don't need to send any updates since we are disconnected
- if(ll->related_prefixes_len != 0){
- if(ll->bestFaces[0] != NULL){
- NumberSet *out = numberSet_Create();
- if(old_faces[0] == NULL ||
- (strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) !=
- strategyNexthopStateLL_GetFaceId(old_faces[0]))){
- //there is a new face 0 so we need a map me update
- //if ll->bestFaces[1] != NULL we need to send the update
- //even if it is the same as before
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- if(ll->bestFaces[1] != NULL){
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
- }
- strategyLowLatency_SendMapmeUpdate(ll,out);
- }else{
- if(ll->bestFaces[1] != NULL){
- if(old_faces[1] == NULL ||
- (strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) !=
- strategyNexthopStateLL_GetFaceId(old_faces[1]))){
- //send a mapme both with face 0 and face 1
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
- strategyLowLatency_SendMapmeUpdate(ll,out);
- }
- }else{
- if(old_faces[1] != NULL){
- //in the previuos round we were using two faces, now only one
- //send update with only face 0
- numberSet_Add(out,
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- strategyLowLatency_SendMapmeUpdate(ll,out);
- }
- }
- }
- numberSet_Release(&out);
- }
- }
-}
-
-static void strategyLowLatency_BestFaceCB(int fd, PARCEventType which_event,
- void *data){
- parcAssertTrue(which_event & PARCEventType_Timeout,
- "Event incorrect, expecting %X set, got %X",
- PARCEventType_Timeout, which_event);
-
- StrategyLowLatency * ll = (StrategyLowLatency *) data;
- strategyLowLatency_SelectBestFaces(ll, true);
-
- struct timeval timeout = {0, 500000};
- parcEventTimer_Start(ll->computeBestFace, &timeout);
-}
-
-StrategyImpl *strategyLowLatency_Create() {
- StrategyLowLatency *strategy =
- parcMemory_AllocateAndClear(sizeof(StrategyLowLatency));
- parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyLowLatency));
-
- strategy->strategy_state = parcHashMap_Create();
- strategy->pending_probes_ticks = parcHashMap_Create();
- strategy->pending_probes_faces = parcHashMap_Create();
-#ifndef WITH_POLICY
- strategy->nexthops = numberSet_Create();
-#endif /* ! WITH_POLICY */
- srand((unsigned int)time(NULL));
-
- StrategyImpl *impl = parcMemory_AllocateAndClear(sizeof(StrategyImpl));
- parcAssertNotNull(impl, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyImpl));
- memcpy(impl, &_template, sizeof(StrategyImpl));
- impl->context = strategy;
-
- return impl;
-}
-
-void strategyLowLatency_SetStrategy(StrategyImpl *strategy,
- const Forwarder * forwarder,
- const FibEntry * fibEntry,
- unsigned related_prefixes_len,
- Name **related_prefixes) {
- StrategyLowLatency *ll =
- (StrategyLowLatency *)strategy->context;
- ll->forwarder = forwarder;
-
- //create probe packet
- ll->probe = messageHandler_CreateProbePacket(HF_INET6_TCP, PROBE_LIFETIME);
- ip_prefix_t address;
- nameBitvector_ToIPAddress(name_GetContentName(
- fibEntry_GetPrefix(fibEntry)), &address);
- ll->name = messageHandler_CreateProbeName(&address);
-
-
- Dispatcher *dispatcher = forwarder_GetDispatcher((Forwarder *)ll->forwarder);
- ll->sendProbes = dispatcher_CreateTimer(dispatcher, false,
- strategyLowLatency_SendProbesCB, ll);
-
- ll->round = 0;
- ll->rounds_in_multipath = 0;
- ll->rounds_with_error = 0;
- ll->rounds_avoiding_multipath = 0;
- ll->use2paths = false;
- ll->avoid_multipath = false;
-
- ll->related_prefixes_len = related_prefixes_len;
- ll->related_prefixes = malloc(sizeof(Name *) * ll->related_prefixes_len);
- for(unsigned i = 0; i < ll->related_prefixes_len; i++){
- ll->related_prefixes[i] = name_Copy(related_prefixes[i]);
- }
-
- ll->computeBestFace = dispatcher_CreateTimer(dispatcher, false,
- strategyLowLatency_BestFaceCB, ll);
-}
-
-void _startTimers(StrategyImpl *strategy){
- StrategyLowLatency *ll =
- (StrategyLowLatency *)strategy->context;
-
- struct timeval timeoutProbes = {0,10000};
- parcEventTimer_Start(ll->sendProbes, &timeoutProbes);
- struct timeval timeoutBF = {1,0};
- parcEventTimer_Start(ll->computeBestFace, &timeoutBF);
-}
-
-void _stopTimers(StrategyImpl *strategy){
- StrategyLowLatency *ll =
- (StrategyLowLatency *)strategy->context;
-
- parcEventTimer_Stop(ll->sendProbes);
- parcEventTimer_Stop(ll->computeBestFace);
-}
-
-// =======================================================
-// Dispatch API
-
-strategy_type _strategyLowLatency_GetStrategy(StrategyImpl *strategy) {
- return SET_STRATEGY_LOW_LATENCY;
-}
-
-static void _strategyLowLatency_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- if(!messageHandler_IsAProbe(message_FixedHeader(objectMessage)))
- return;
-
- uint32_t seq = messageHandler_GetSegment(message_FixedHeader(objectMessage));
- PARCUnsigned *parc_seq = parcUnsigned_Create(seq);
- if (!parcHashMap_Contains(ll->pending_probes_ticks, parc_seq)){
- parcUnsigned_Release(&parc_seq);
- return;
- }
-
- //here numberSet_Length(egressId) should be 1
- for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
- unsigned outId = numberSet_GetItem(egressId, i);
- PARCUnsigned *cid = parcUnsigned_Create(outId);
-
- const StrategyNexthopStateLL *state =
- parcHashMap_Get(ll->strategy_state, cid);
- if (state != NULL) {
- Ticks time = parcUnsigned_GetUnsigned(
- parcHashMap_Get(ll->pending_probes_ticks, parc_seq));
- Ticks now = forwarder_GetTicks(ll->forwarder);
- Ticks RTT = now - time;
- if(RTT <= 0)
- RTT = 1;
- strategyNexthopStateLL_AddRttSample(
- (StrategyNexthopStateLL *) state, (unsigned int)RTT);
- parcHashMap_Remove(ll->pending_probes_ticks, parc_seq);
- } else {
- // this may happen if we remove a face/route while downloading a file
- // we should ignore this timeout
- }
- parcUnsigned_Release(&cid);
- }
- parcUnsigned_Release(&parc_seq);
-}
-
-static void _strategyLowLatency_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId) {}
-
-static NumberSet *_strategyLowLatency_LookupNexthop(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage) {
- //unsigned out_connection;
- NumberSet *out = numberSet_Create();
-
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- //update is_allowed flag of all the next hops
- PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
- while(parcIterator_HasNext(iterator)){
- PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
- if(numberSet_Contains(nexthops, parcUnsigned_GetUnsigned(cid))){
- strategyNexthopStateLL_SetIsAllowed(state,true);
- }else{
- strategyNexthopStateLL_SetIsAllowed(state,false);
- }
- }
- parcIterator_Release(&iterator);
-
- if(ll->bestFaces[0] != NULL &&
- !strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])){
- //if ll->bestFaces[0] is not allowed we need to find a new face
- strategyLowLatency_SelectBestFaces(ll, false);
- }
-
- //at this point ll->bestFaces[0] must be allowed
- //single path case
- if(ll->bestFaces[0] != NULL && (ll->bestFaces[1] == NULL || !ll->use2paths)){
- strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
-
- //multipath case
- }else if(ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL && ll->use2paths){
- //it may happen that ll->bestFaces[1] is not allowed, in that case we send on
- //ll->bestFaces[0] until the next best face selection
- if(!strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
- strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- }else{
- double queue0 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]);
- double queue1 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]);
- double prob0 = 0.5;
- if(queue0 > 1 || queue1 > 1){
- prob0 = 1.0 - (queue0 / (queue0 + queue1));
- }
- double coin = ((double) rand() / (RAND_MAX));
- if(coin < prob0){
- strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
- }else{
- strategyNexthopStateLL_SendPacket(ll->bestFaces[1]);
- numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
- }
- }
- }
- return out;
-}
-
-
-#ifndef WITH_POLICY
-static NumberSet *_strategyLowLatency_ReturnNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancerLL *ll = (StrategyLoadBalancerLL *)strategy->context;
- return ll->nexthops;
-}
-
-unsigned _strategyLowLatency_CountNexthops(StrategyImpl *strategy) {
- StrategyLoadBalancerLL *ll = (StrategyLoadBalancerLL *)strategy->context;
- return (unsigned)numberSet_Length(ll->nexthops);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyLowLatency_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- if (!parcHashMap_Contains(ll->strategy_state, cid)) {
- StrategyNexthopStateLL *state = strategyNexthopStateLL_Create(connectionId);
- parcHashMap_Put(ll->strategy_state, cid, state);
- if(ll->bestFaces[0] == NULL){
- ll->bestFaces[0] = state;
- }
-#ifndef WITH_POLICY
- numberSet_Add(ll->nexthops, connectionId);
-#endif /* WITH_POLICY */
- }
-
- if(parcHashMap_Size(ll->strategy_state) >= 2){
- _startTimers(strategy);
- }
-
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLowLatency_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
- StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
-
- bool reset_bestFaces = false;
-
- if((ll->bestFaces[0] != NULL &&
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) == connectionId) ||
- (ll->bestFaces[1] != NULL &&
- strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) == connectionId)){
- reset_bestFaces = true;
- }
-
- PARCUnsigned *cid = parcUnsigned_Create(connectionId);
-
- if (parcHashMap_Contains(ll->strategy_state, cid)) {
- parcHashMap_Remove(ll->strategy_state, cid);
-#ifndef WITH_POLICY
- numberSet_Remove(lb->nexthops, connectionId);
-#endif /* WITH_POLICY */
- }
-
- if(reset_bestFaces){
- ll->bestFaces[0] = NULL;
- ll->bestFaces[1] = NULL;
- strategyLowLatency_SelectBestFaces(ll, false);
- }
-
- if(parcHashMap_Size(ll->strategy_state) < 2){
- _stopTimers(strategy);
- }
-
- parcUnsigned_Release(&cid);
-}
-
-static void _strategyLowLatency_ImplDestroy(StrategyImpl **strategyPtr) {
- parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*strategyPtr,
- "Parameter must dereference to non-null pointer");
-
- StrategyImpl *impl = *strategyPtr;
- StrategyLowLatency *strategy = (StrategyLowLatency *)impl->context;
-
- _stopTimers(impl);
-
- parcEventTimer_Destroy(&(strategy->sendProbes));
- parcEventTimer_Destroy(&(strategy->computeBestFace));
-
- if (parcHashMap_Size(strategy->strategy_state) > 0) {
- PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
- while (parcIterator_HasNext(it)) {
- PARCUnsigned *cid = parcIterator_Next(it);
- StrategyNexthopStateLL *state =
- (StrategyNexthopStateLL *)parcHashMap_Get(strategy->strategy_state, cid);
- parcObject_Release((void**)&state);
- }
- parcIterator_Release(&it);
- }
-
- parcHashMap_Release(&(strategy->strategy_state));
- parcHashMap_Release(&(strategy->pending_probes_ticks));
- parcHashMap_Release(&(strategy->pending_probes_faces));
-
- parcMemory_Deallocate(&(strategy->probe));
- parcMemory_Deallocate(&(strategy->name));
-
- for(unsigned i = 0; i < strategy->related_prefixes_len; i++){
- name_Release(&(strategy->related_prefixes[i]));
- }
- free(strategy->related_prefixes);
-
-#ifndef WITH_POLICY
- numberSet_Release(&(strategy->nexthops));
-#endif /* ! WITH_POLICY */
-
- parcMemory_Deallocate((void **)&strategy);
- parcMemory_Deallocate((void **)&impl);
- *strategyPtr = NULL;
-}
diff --git a/hicn-light/src/hicn/strategies/lowLatency.h b/hicn-light/src/hicn/strategies/lowLatency.h
deleted file mode 100644
index 736c8783d..000000000
--- a/hicn-light/src/hicn/strategies/lowLatency.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Forward on the path with lowest latency
- */
-
-#ifndef lowLatency_h
-#define lowLatency_h
-
-#include <hicn/strategies/strategyImpl.h>
-#include <hicn/core/forwarder.h>
-
-StrategyImpl *strategyLowLatency_Create();
-
-void strategyLowLatency_SetStrategy(StrategyImpl *strategy,
- const Forwarder * forwarder,
- const FibEntry * fibEntry,
- unsigned related_prefixes_len,
- Name **related_prefixes);
-#endif // lowLatency_h
diff --git a/hicn-light/src/hicn/strategies/low_latency.c b/hicn-light/src/hicn/strategies/low_latency.c
new file mode 100644
index 000000000..9f7ecb89c
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/low_latency.c
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if 0
+
+#include <hicn/hicn-light/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+#include <hicn/base/khash.h>
+
+#include <parc/assert/parc_Assert.h>
+#include <parc/algol/parc_HashMap.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_Unsigned.h>
+
+#include <hicn/core/messageHandler.h>
+
+#include "low_latency.h"
+
+#define STABILITY_FACTOR 15
+#define MAX_SWITCH_TRY 10
+#define MAX_LATENCY_DIFF 10
+#define MAX_TOLLERATED_LATENCY_DIFF 15
+#define MAX_ROUNDS_MP_WITHOUT_CHECK 2
+#define MAX_ROUNDS_AVOIDING_MULTIPATH 40 /* about 20 sec */
+#define MAX_ROUNDS_WITH_ERROR 4
+#define PROBE_LIFETIME 500 /* ms */
+
+#define MAX_ROUNS_WITHOUT_PROBES 4
+
+/*
+ * If we do not receives probes for 4 rounds it means that we had no responce
+ * from any producer for 2 sec we can say that this interface is daed
+ */
+#define MIN_NON_LOSSY_ROUNDS 10
+
+/*
+ * Number of rounds in non lossy mode before switch to no lossy state
+ * Defaults to 10 %
+ */
+#define MAX_LOSS_RATE 0.10
+
+/* Shorthands */
+#define nexthop_state_t strategy_low_latency_nexthop_state_t
+#define state_t strategy_low_latency_state_t
+
+#define NEXTHOP_STATE_INIT { \
+ .in_use = false, \
+ .is_allowed = true, \
+ .sent_packets = 0, \
+ .last_try_to_switch_round = 0, \
+ .try_to_switch_counter = 0, \
+ .recevied_probes = 0, \
+ .rounds_without_probes = 0, \
+ .sent_probes = 0, \
+ .lost_probes = 0, \
+ .non_lossy_rounds = MIN_NON_LOSSY_ROUNDS, \
+ .avg_rtt = -1.0, \
+ .avg_rtt_in_use = -1.0, \
+ .avg_queue = 0.0001, \
+ .avg_loss_rate = 0.0, \
+}
+
+// XXX ????
+#define STATE_INIT { \
+}
+
+static
+ void
+strategy_low_latency_SendProbesCB(int fd, PARCEventType which_event, void *data)
+{
+ parcAssertTrue(which_event & PARCEventType_Timeout,
+ "Event incorrect, expecting %X set, got %X",
+ PARCEventType_Timeout, which_event);
+
+ StrategyLowLatency *ll = (StrategyLowLatency *) data;
+
+ //delete old pending probes
+ if(parcHashMap_Size(ll->pending_probes_ticks) != 0){
+ Ticks now = forwarder_GetTicks(ll->forwarder);
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->pending_probes_ticks);
+ NumberSet *to_remove = numberSet_Create();
+ while(parcIterator_HasNext(iterator)) {
+ PARCUnsigned *parc_seq = (PARCUnsigned *) parcIterator_Next(iterator);
+ PARCUnsigned *parc_time = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_ticks, parc_seq);
+ Ticks sent_time = parcUnsigned_GetUnsigned(parc_time);
+ if((now - sent_time) > PROBE_LIFETIME){
+ //probes to delete
+ numberSet_Add(to_remove, parcUnsigned_GetUnsigned(parc_seq));
+ }
+ }
+ parcIterator_Release(&iterator);
+
+ for(int i = 0; i < numberSet_Length(to_remove); i++){
+ PARCUnsigned *prob_seq = parcUnsigned_Create(numberSet_GetItem(to_remove,i));
+ PARCUnsigned *cid = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_faces, prob_seq);
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
+ strategyNexthopStateLL_LostProbe(state);
+ parcHashMap_Remove(ll->pending_probes_ticks, prob_seq);
+ parcHashMap_Remove(ll->pending_probes_faces, prob_seq);
+ parcUnsigned_Release(&prob_seq);
+ }
+ numberSet_Release(&to_remove);
+ }
+
+ ConnectionTable * ct = forwarder_GetConnectionTable(ll->forwarder);
+
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while(parcIterator_HasNext(iterator)){
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ Connection *conn =
+ (Connection *)connectionTable_FindById(ct,
+ parcUnsigned_GetUnsigned(cid));
+ if(!conn)
+ continue;
+
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
+
+ //probe only usable paths
+ if(!strategyNexthopStateLL_IsAllowed(state))
+ continue;
+
+ uint32_t seq = rand();
+ messageHandler_SetProbeName(ll->probe, HF_INET6_TCP,
+ ll->name, seq);
+ connection_Probe(conn, ll->probe);
+
+ PARCUnsigned *parc_seq = parcUnsigned_Create(seq);
+ Ticks now = forwarder_GetTicks(ll->forwarder);
+ PARCUnsigned *parc_time = parcUnsigned_Create((unsigned int)now);
+ parcHashMap_Put(ll->pending_probes_ticks, parc_seq, parc_time);
+ parcHashMap_Put(ll->pending_probes_faces, parc_seq, cid);
+ strategyNexthopStateLL_SentProbe(state);
+ parcUnsigned_Release(&parc_seq);
+ parcUnsigned_Release(&parc_time);
+ }
+ parcIterator_Release(&iterator);
+
+ struct timeval timeout = {0,50000};
+ parcEventTimer_Start(ll->sendProbes, &timeout);
+}
+
+static
+void
+strategy_low_latency_SendMapmeUpdate(StrategyLowLatency *ll,
+ const NumberSet * nexthops){
+ MapMe * mapme = forwarder_getMapmeInstance(ll->forwarder);
+ FIB * fib = forwarder_getFib((Forwarder*) ll->forwarder);
+ for(unsigned i = 0; i < ll->related_prefixes_len; i++){
+ FibEntry *fibEntry = fib_MatchName(fib, ll->related_prefixes[i]);
+ if (!fibEntry)
+ continue;
+ mapme_maybe_send_to_nexthops(mapme, fibEntry, nexthops);
+ }
+}
+
+static
+void
+strategy_low_latency_SelectBestFaces(StrategyLowLatency *ll, bool new_round)
+{
+
+ StrategyNexthopStateLL * old_faces[2];
+ old_faces[0] = ll->bestFaces[0];
+ old_faces[1] = ll->bestFaces[1];
+
+ if(new_round){
+ ll->round++;
+ }
+
+ if(parcHashMap_Size(ll->strategy_state) == 0){
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ if(ll->use2paths && ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL){
+ //multipath case
+
+ if(!strategyNexthopStateLL_IsLossy(ll->bestFaces[0])
+ && !strategyNexthopStateLL_IsLossy(ll->bestFaces[1])
+ && strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])
+ && strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
+
+ if(ll->rounds_in_multipath < MAX_ROUNDS_MP_WITHOUT_CHECK){
+ //we are at the first rounds of the multipath let's wait a bit
+ //(MAX_ROUNDS_MP_WITHOUT_CHECK) to make the queuing converge
+ ll->rounds_in_multipath++;
+ goto NEW_ROUND;
+ }
+
+ //we need to decide if we want ot keep using two paths or not
+ ll->rounds_in_multipath++;
+ double rtt0 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
+ double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
+ double diff = fabs(rtt0 - rtt1);
+
+ if(diff < MAX_LATENCY_DIFF){
+ //everything is working, keep using the two paths
+ ll->rounds_with_error = 0;
+ goto NEW_ROUND;
+ }
+
+ //check for how many rounds we had problems
+ if(ll->rounds_with_error < MAX_ROUNDS_WITH_ERROR &&
+ diff < MAX_TOLLERATED_LATENCY_DIFF){
+ //we can tollerate few round with errors
+ ll->rounds_with_error++;
+ goto NEW_ROUND;
+ }
+
+ //prevent the usage of multiple paths
+ ll->rounds_with_error = 0;
+ ll->avoid_multipath = true;
+ ll->rounds_avoiding_multipath = 0;
+ } //else
+ //at least one of the two path is lossy
+ //or it is not allowed by the policies.
+ //search for a better possibility
+ }
+
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+
+ //check if there is at least one non lossy connection
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ bool check_losses = true;
+ bool found_good_face = false;
+ while(parcIterator_HasNext(iterator) && !found_good_face){
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ const StrategyNexthopStateLL *state = parcHashMap_Get(ll->strategy_state, cid);
+ if(!strategyNexthopStateLL_IsLossy(state) &&
+ strategyNexthopStateLL_IsAllowed(state)){
+ found_good_face = true;
+ }
+ }
+ parcIterator_Release(&iterator);
+ if(!found_good_face){
+ // all the available faces are lossy, so we take into account only
+ // the latency computed with the probes
+ check_losses = false;
+ }
+
+ if(ll->bestFaces[0] == NULL){
+ //try to take a random face
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ bool face_found = false;
+ while(parcIterator_HasNext(iterator) && !face_found) {
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid);
+
+ if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
+ !strategyNexthopStateLL_IsAllowed(state)){
+ //skip the face
+ continue;
+ }
+
+ ll->bestFaces[0] = state;
+ face_found = true;
+ }
+ parcIterator_Release(&iterator);
+ }
+
+ if(ll->bestFaces[0] == NULL){
+ //no usable face exists
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ double bestRtt = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]);
+
+ if(ll->avoid_multipath)
+ ll->rounds_avoiding_multipath++;
+
+ if(ll->rounds_avoiding_multipath > MAX_ROUNDS_AVOIDING_MULTIPATH){
+ ll->avoid_multipath = false;
+ ll->rounds_avoiding_multipath = 0;
+ }
+
+ iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while (parcIterator_HasNext(iterator)) {
+
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid);
+ double rtt = strategyNexthopStateLL_GetRTTLive(state);
+
+ if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
+ !strategyNexthopStateLL_IsAllowed(state)){
+ //skip the face
+ continue;
+ }
+
+ if(rtt + STABILITY_FACTOR < bestRtt){
+ //maybe we found a better face
+ double rttInUse = strategyNexthopStateLL_GetRTTInUse(state);
+ unsigned try = strategyNexthopStateLL_GetTryToSwitch(state);
+
+ //we check the rtt in use to check if the new face that we found
+ //gets congested when we use it to send the traffic
+ if(rttInUse < bestRtt || try > MAX_SWITCH_TRY){
+ //we have a new best face!
+ strategyNexthopStateLL_ResetTryToSwitch((StrategyNexthopStateLL*) state);
+ bestRtt = rtt;
+ if(ll->bestFaces[0] != NULL)
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[0]);
+ ll->bestFaces[0] = (StrategyNexthopStateLL*) state;
+ }else{
+ //in this case we should switch but we wait MAX_SWITCH_TRY
+ //before switch to avoid ossillations between different paths
+ strategyNexthopStateLL_IncreaseTryToSwitch(
+ (StrategyNexthopStateLL*) state, ll->round);
+ }
+ }
+ }
+
+ parcIterator_Release(&iterator);
+
+ if(ll->bestFaces[0] == NULL){
+ //we found no face so return
+ ll->bestFaces[0] = NULL;
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ if(parcHashMap_Size(ll->strategy_state) == 1 || ll->avoid_multipath){
+ //in this case (one face available or avoid multipath) we stop the
+ //search here. Just reset face 1 if needed
+ if(ll->bestFaces[1] != NULL){
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
+ ll->bestFaces[1] = NULL;
+ }
+ ll->use2paths = false;
+ goto NEW_ROUND;
+ }
+
+ //if we are here we have more than 1 interface, so we search for a second one
+ //to use in case of multipath
+ iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while (parcIterator_HasNext(iterator)) {
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ if(parcUnsigned_GetUnsigned(cid) !=
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])){
+
+ StrategyNexthopStateLL *state = (StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid);
+
+ if((check_losses && strategyNexthopStateLL_IsLossy(state)) ||
+ !strategyNexthopStateLL_IsAllowed(state)){
+ //skip the face
+ continue;
+ }
+
+ if(ll->bestFaces[1] == NULL){
+ //in case of 2 faces we should pass always here
+ ll->bestFaces[1] = state;
+ }else{
+ //TODO this must be tested with more then 2 faces
+ double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]);
+ double rttNewFace = strategyNexthopStateLL_GetRTTLive(state);
+ if(rttNewFace + STABILITY_FACTOR < rtt1){
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
+ ll->bestFaces[1] = state;
+ }
+ }
+ }
+ }
+ parcIterator_Release(&iterator);
+
+ if(ll->bestFaces[1] != NULL){
+ //we are not using the second face yet so we use the normal rtt for comparison
+ double rtt0 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[0]);
+ double rtt1 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[1]);
+ double diff = fabs(rtt0 - rtt1);
+ if(diff < MAX_LATENCY_DIFF) {
+ //let's start to use 2 paths
+ ll->rounds_with_error = 0;
+ ll->use2paths = true;
+ ll->rounds_in_multipath = 0;
+ }else{
+ //we use only one path
+ strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]);
+ ll->bestFaces[1] = NULL;
+ ll->use2paths = false;
+ }
+ }else{
+ ll->use2paths = false;
+ }
+
+NEW_ROUND:
+ {
+ Logger * log = forwarder_GetLogger(ll->forwarder);
+ if(log != NULL &&
+ logger_IsLoggable(log, LoggerFacility_Strategy, PARCLogLevel_Info)){
+ if(ll->use2paths){
+ logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
+ __func__, "use 2 paths. rtt face %d = %f queue = %f is_lossy = %d,"
+ "rtt face %d = %f queue = %f is_lossy = %d\n",
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]),
+ strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]),
+ strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]),
+ strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]),
+ strategyNexthopStateLL_IsLossy(ll->bestFaces[1]));
+ }else{
+ if(ll->bestFaces[0] != NULL){
+ logger_Log(log, LoggerFacility_Strategy,
+ PARCLogLevel_Info, __func__,
+ "use 1 path. rtt face %d = %f is_lossy = %d, "
+ "(avoid multipath = %d)\n",
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]),
+ strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]),
+ strategyNexthopStateLL_IsLossy(ll->bestFaces[0]),
+ ll->avoid_multipath);
+ }else{
+ logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info,
+ __func__, "no face to use!\n");
+ }
+ }
+ }
+ }
+
+ //update the round only at the end for all the faces
+ if(new_round){
+ PARCIterator * iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while (parcIterator_HasNext(iterator)) {
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ strategyNexthopStateLL_StartNewRound((StrategyNexthopStateLL *)
+ parcHashMap_Get(ll->strategy_state, cid));
+ }
+ parcIterator_Release(&iterator);
+ }
+
+ //mapme updates
+ //if ll->bestFaces[0] == NULL we don't have any output faces
+ //so don't need to send any updates since we are disconnected
+ if(ll->related_prefixes_len != 0){
+ if(ll->bestFaces[0] != NULL){
+ NumberSet *out = numberSet_Create();
+ if(old_faces[0] == NULL ||
+ (strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) !=
+ strategyNexthopStateLL_GetFaceId(old_faces[0]))){
+ //there is a new face 0 so we need a map me update
+ //if ll->bestFaces[1] != NULL we need to send the update
+ //even if it is the same as before
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ if(ll->bestFaces[1] != NULL){
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
+ }
+ strategy_low_latency_SendMapmeUpdate(ll,out);
+ }else{
+ if(ll->bestFaces[1] != NULL){
+ if(old_faces[1] == NULL ||
+ (strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) !=
+ strategyNexthopStateLL_GetFaceId(old_faces[1]))){
+ //send a mapme both with face 0 and face 1
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
+ strategy_low_latency_SendMapmeUpdate(ll,out);
+ }
+ }else{
+ if(old_faces[1] != NULL){
+ //in the previuos round we were using two faces, now only one
+ //send update with only face 0
+ numberSet_Add(out,
+ strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ strategy_low_latency_SendMapmeUpdate(ll,out);
+ }
+ }
+ }
+ numberSet_Release(&out);
+ }
+ }
+}
+
+static
+void
+strategy_low_latency_BestFaceCB(int fd, PARCEventType which_event, void *data)
+{
+ parcAssertTrue(which_event & PARCEventType_Timeout,
+ "Event incorrect, expecting %X set, got %X",
+ PARCEventType_Timeout, which_event);
+
+ StrategyLowLatency * ll = (StrategyLowLatency *) data;
+ strategy_low_latency_SelectBestFaces(ll, true);
+
+ struct timeval timeout = {0, 500000};
+ parcEventTimer_Start(ll->computeBestFace, &timeout);
+}
+
+static
+void
+_startTimers(strategy_entry_t * entry)
+{
+ struct timeval timeoutProbes = {0, 10000};
+ struct timeval timeoutBF = {1, 0};
+
+ parcEventTimer_Start(entry->state.sendProbes, &timeoutProbes);
+ parcEventTimer_Start(entry->state.computeBestFace, &timeoutBF);
+}
+
+static
+void
+_stopTimers(strategy_entry_t * entry)
+{
+ parcEventTimer_Stop(entry->state.sendProbes);
+ parcEventTimer_Stop(entry->state.computeBestFace);
+}
+
+static
+void
+strategy_low_latency_initialize(strategy_entry_t * entry)
+{
+ srand((unsigned int)time(NULL));
+
+ /* XXX TODO Three hashmaps to initialize */
+ strategy->strategy_state = parcHashMap_Create();
+ strategy->pending_probes_ticks = parcHashMap_Create();
+ strategy->pending_probes_faces = parcHashMap_Create();
+
+ Dispatcher *dispatcher = forwarder_GetDispatcher((Forwarder *)ll->forwarder);
+ ip_prefix_t address;
+ nameBitvector_ToIPAddress(name_GetContentName(
+ fibEntry_GetPrefix(fibEntry)), &address);
+
+ entry->state = {
+ .probe = messageHandler_CreateProbePacket(HF_INET6_TCP, PROBE_LIFETIME),
+ .name = messageHandler_CreateProbeName(&address);
+ .sendProbes = dispatcher_CreateTimer(dispatcher, false,
+ strategy_low_latency_SendProbesCB, ll);
+ .round = 0;
+ .rounds_in_multipath = 0;
+ .rounds_with_error = 0;
+ .rounds_avoiding_multipath = 0;
+ .use2paths = false;
+ .avoid_multipath = false;
+ .computeBestFace = dispatcher_CreateTimer(dispatcher, false,
+ strategy_low_latency_BestFaceCB, ll);
+ .related_prefixes_len = related_prefixes_len;
+ // XXX TODO
+ .related_prefixes = malloc(sizeof(Name *) * related_prefixes_len);
+ };
+
+ for(unsigned i = 0; i < entry->state.related_prefixes_len; i++){
+ entry->state.related_prefixes[i] = name_Copy(related_prefixes[i]);
+ }
+}
+
+static
+void
+strategy_low_latency_finalize(strategy_entry_t * entry)
+{
+ _stopTimers(entry);
+
+ parcEventTimer_Destroy(&(strategy->sendProbes));
+ parcEventTimer_Destroy(&(strategy->computeBestFace));
+
+ if (parcHashMap_Size(strategy->strategy_state) > 0) {
+ PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state);
+ while (parcIterator_HasNext(it)) {
+ PARCUnsigned *cid = parcIterator_Next(it);
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *)parcHashMap_Get(strategy->strategy_state, cid);
+ parcObject_Release((void**)&state);
+ }
+ parcIterator_Release(&it);
+ }
+
+ parcHashMap_Release(&(strategy->strategy_state));
+ parcHashMap_Release(&(strategy->pending_probes_ticks));
+ parcHashMap_Release(&(strategy->pending_probes_faces));
+
+ parcMemory_Deallocate(&(strategy->probe));
+ parcMemory_Deallocate(&(strategy->name));
+
+ for(unsigned i = 0; i < strategy->related_prefixes_len; i++){
+ name_Release(&(strategy->related_prefixes[i]));
+ }
+ free(strategy->related_prefixes);
+
+ parcMemory_Deallocate((void **)&strategy);
+ parcMemory_Deallocate((void **)&impl);
+ *strategyPtr = NULL;
+}
+
+static
+void
+strategy_low_latency_add_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state)
+{
+ PARCUnsigned *cid = parcUnsigned_Create(connectionId);
+
+ StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
+
+ if (!parcHashMap_Contains(ll->strategy_state, cid)) {
+ StrategyNexthopStateLL *state = strategyNexthopStateLL_Create(connectionId);
+ parcHashMap_Put(ll->strategy_state, cid, state);
+ if(ll->bestFaces[0] == NULL){
+ ll->bestFaces[0] = state;
+ }
+ }
+
+ if(parcHashMap_Size(ll->strategy_state) >= 2){
+ _startTimers(strategy);
+ }
+
+ parcUnsigned_Release(&cid);
+}
+
+static
+void
+strategy_low_latency_remove_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state)
+{
+ bool reset_bestFaces = false;
+
+ if((entry->state.bestFaces[0] != NULL &&
+ strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[0]) == connectionId) ||
+ (entry->state.bestFaces[1] != NULL &&
+ strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[1]) == connectionId)){
+ reset_bestFaces = true;
+ }
+
+ PARCUnsigned *cid = parcUnsigned_Create(connectionId);
+
+ if (parcHashMap_Contains(entry->state.strategy_state, cid)) {
+ parcHashMap_Remove(entry->state.strategy_state, cid);
+ }
+
+ if(reset_bestFaces){
+ entry->state.bestFaces[0] = NULL;
+ entry->state.bestFaces[1] = NULL;
+ strategy_low_latency_SelectBestFaces(ll, false);
+ }
+
+ if(parcHashMap_Size(entry->state.strategy_state) < 2){
+ _stopTimers(strategy);
+ }
+
+ parcUnsigned_Release(&cid);
+}
+
+static
+nexthops_t *
+strategy_low_latency_lookup_nexthops(strategy_entry_t * entry,
+ const msgbuf_t * msgbuf)
+{
+ //unsigned out_connection;
+ NumberSet *out = numberSet_Create();
+
+ StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context;
+
+ //update is_allowed flag of all the next hops
+ PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state);
+ while(parcIterator_HasNext(iterator)){
+ PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator);
+ StrategyNexthopStateLL *state =
+ (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid);
+ if(numberSet_Contains(nexthops, parcUnsigned_GetUnsigned(cid))){
+ strategyNexthopStateLL_SetIsAllowed(state,true);
+ }else{
+ strategyNexthopStateLL_SetIsAllowed(state,false);
+ }
+ }
+ parcIterator_Release(&iterator);
+
+ if(ll->bestFaces[0] != NULL &&
+ !strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])){
+ //if ll->bestFaces[0] is not allowed we need to find a new face
+ strategy_low_latency_SelectBestFaces(ll, false);
+ }
+
+ //at this point ll->bestFaces[0] must be allowed
+ //single path case
+ if(ll->bestFaces[0] != NULL && (ll->bestFaces[1] == NULL || !ll->use2paths)){
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+
+ //multipath case
+ }else if(ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL && ll->use2paths){
+ //it may happen that ll->bestFaces[1] is not allowed, in that case we send on
+ //ll->bestFaces[0] until the next best face selection
+ if(!strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ }else{
+ double queue0 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]);
+ double queue1 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]);
+ double prob0 = 0.5;
+ if(queue0 > 1 || queue1 > 1){
+ prob0 = 1.0 - (queue0 / (queue0 + queue1));
+ }
+ double coin = ((double) rand() / (RAND_MAX));
+ if(coin < prob0){
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[0]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]));
+ }else{
+ strategyNexthopStateLL_SendPacket(ll->bestFaces[1]);
+ numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]));
+ }
+ }
+ }
+ return out;
+}
+
+
+
+static
+void
+strategy_low_latency_on_data(strategy_entry_t * entry,
+ const nexthops_t * nexthops, const msgbuf_t * msgbuf,
+ Ticks pitEntryCreation, Ticks objReception)
+{
+ if (!msgbuf_is_probe(msgbuf))
+ return;
+
+ uint32_t seq = messageHandler_GetSegment(message_FixedHeader(objectMessage));
+ if (!parcHashMap_Contains(ll->pending_probes_ticks, seq))
+ return; // unexpected
+
+ /* A single nexthop is expected */
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop, {
+ const StrategyNexthopStateLL *state =
+ parcHashMap_Get(ll->strategy_state, nexthop);
+ if (!state)
+ // this may happen if we remove a face/route while downloading a file
+ // we should ignore this timeout
+ continue;
+
+ Ticks time = parcUnsigned_GetUnsigned(
+ parcHashMap_Get(ll->pending_probes_ticks, seq));
+ Ticks now = forwarder_GetTicks(ll->forwarder);
+ Ticks RTT = now - time;
+ if(RTT <= 0)
+ RTT = 1;
+ strategyNexthopStateLL_AddRttSample(
+ (StrategyNexthopStateLL *) state, (unsigned int)RTT);
+ parcHashMap_Remove(ll->pending_probes_ticks, seq);
+ }
+ };
+}
+
+static
+void
+strategy_low_latency_on_timeout(strategy_entry_t * entry, const nexthops_t * nexthops)
+{
+ /* Nothing to do */
+}
+
+DECLARE_STRATEGY(low_latency);
+
+#undef nexthop_state_t
+#undef state_t
+
+#endif
diff --git a/hicn-light/src/hicn/strategies/low_latency.h b/hicn-light/src/hicn/strategies/low_latency.h
new file mode 100644
index 000000000..4745c4c47
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/low_latency.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Forward on the path with lowest latency
+ */
+
+#ifndef HICNLIGHT_STRATEGY_LOW_LATENCY_H
+#define HICNLIGHT_STRATEGY_LOW_LATENCY_H
+
+#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
+
+typedef struct {
+} strategy_low_latency_nexthop_state_t;
+
+typedef struct {
+} strategy_low_latency_state_t;
+
+typedef struct {
+ //Name ** related_prefixes;
+ Name *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES];
+ unsigned related_prefixes_len;
+} strategy_low_latency_options_t;
+
+#if 0
+
+/*
+ * We have global state in addition to state associated for each next hop :
+ */
+typedef struct {
+ bool in_use;
+ bool is_allowed; // XXX TODO the policy may not allow the use of this face
+// unsigned face_id;
+ unsigned sent_packets;
+ /* switch metrics */
+ unsigned last_try_to_switch_round;
+ unsigned try_to_switch_counter;
+ /* probes counters */
+ unsigned recevied_probes;
+ unsigned rounds_without_probes;
+ unsigned sent_probes;
+ unsigned lost_probes;
+ unsigned non_lossy_rounds;
+ /* Averages */
+ double avg_rtt;
+ double avg_rtt_in_use;
+ double avg_queue;
+ double avg_loss_rate;
+} strategy_low_latency_nexthop_state_t;
+
+typedef struct {
+ // hash map from connectionId to StrategyNexthopStateLL
+ //PARCHashMap *strategy_state;
+ // XXX This is now store in each nexthop state
+
+ /*
+ * Hhash map from sequence number to ticks (sent time)
+ *
+ * TODO improvement: the tick and face id could be stored in the probe and
+ * repeated in the reply to avoid state to be maintained.
+ *
+ * Also, in case we have few probes, linear scan might be more effective
+ */
+ PARCHashMap *pending_probes_ticks;
+
+ /* hash map from sequence number to face id */
+ PARCHashMap *pending_probes_faces;
+
+ const Forwarder * forwarder;
+ PARCEventTimer *sendProbes;
+ PARCEventTimer *computeBestFace;
+ uint8_t * probe;
+ hicn_name_t * name;
+ StrategyNexthopStateLL * bestFaces[2];
+ unsigned round;
+ unsigned rounds_in_multipath;
+ unsigned rounds_with_error;
+ unsigned rounds_avoiding_multipath;
+ bool use2paths;
+ bool avoid_multipath;
+} strategy_low_latency_state_t;
+
+#endif
+
+
+#endif /* HICNLIGHT_STRATEGY_LOW_LATENCY_H */
diff --git a/hicn-light/src/hicn/strategies/nexthopState.c b/hicn-light/src/hicn/strategies/nexthopState.c
deleted file mode 100644
index 40af14832..000000000
--- a/hicn-light/src/hicn/strategies/nexthopState.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-
-#include <parc/algol/parc_DisplayIndented.h>
-#include <parc/algol/parc_Memory.h>
-#include <parc/algol/parc_Object.h>
-
-#include <parc/assert/parc_Assert.h>
-#include <hicn/strategies/nexthopState.h>
-
-#define AVG_PI_THRESHOLD 1e-3
-
-struct strategy_nexthop_state {
- unsigned int pi;
- double avg_pi;
- double weight;
-};
-
-static bool _strategyNexthopState_Destructor(
- StrategyNexthopState **instancePtr) {
- return true;
-}
-
-parcObject_ImplementAcquire(strategyNexthopState, StrategyNexthopState);
-
-parcObject_ImplementRelease(strategyNexthopState, StrategyNexthopState);
-
-parcObject_Override(
- StrategyNexthopState, PARCObject,
- .destructor = (PARCObjectDestructor *)_strategyNexthopState_Destructor,
- .copy = (PARCObjectCopy *)strategyNexthopState_Copy,
- .display = (PARCObjectDisplay *)strategyNexthopState_Display,
- .toString = (PARCObjectToString *)strategyNexthopState_ToString,
- .equals = (PARCObjectEquals *)strategyNexthopState_Equals,
- .compare = (PARCObjectCompare *)strategyNexthopState_Compare,
- .hashCode = (PARCObjectHashCode *)strategyNexthopState_HashCode,
- .display = (PARCObjectDisplay *)strategyNexthopState_Display);
-
-void strategyNexthopState_AssertValid(const StrategyNexthopState *instance) {
- parcAssertTrue(strategyNexthopState_IsValid(instance),
- "StrategyNexthopState is not valid.");
-}
-
-StrategyNexthopState *strategyNexthopState_Create() {
- StrategyNexthopState *result =
- parcObject_CreateInstance(StrategyNexthopState);
- if (result != NULL) {
- result->pi = 0;
- result->avg_pi = 0.0;
- result->weight = 1;
- }
- return result;
-}
-
-void strategyNexthopState_Reset(StrategyNexthopState *x) {
- x->pi = 0;
- x->avg_pi = 0.0;
- x->weight = 1;
-}
-
-int strategyNexthopState_Compare(const StrategyNexthopState *val,
- const StrategyNexthopState *other) {
- if (val == NULL) {
- if (other != NULL) {
- return -1;
- }
- } else if (other == NULL) {
- return 1;
- } else {
- strategyNexthopState_OptionalAssertValid(val);
- strategyNexthopState_OptionalAssertValid(other);
-
- if (val->pi < other->pi) {
- return -1;
- } else if (val->pi > other->pi) {
- return 1;
- }
-
- if (val->avg_pi < other->avg_pi) {
- return -1;
- } else if (val->avg_pi > other->avg_pi) {
- return 1;
- }
-
- if (val->weight < other->weight) {
- return -1;
- } else if (val->weight > other->weight) {
- return 1;
- }
- }
-
- return 0;
-}
-
-StrategyNexthopState *strategyNexthopState_Copy(
- const StrategyNexthopState *original) {
- StrategyNexthopState *result = strategyNexthopState_Create();
- result->pi = original->pi;
- result->avg_pi = original->avg_pi;
- result->weight = original->weight;
-
- return result;
-}
-
-void strategyNexthopState_Display(const StrategyNexthopState *instance,
- int indentation) {
- parcDisplayIndented_PrintLine(indentation, "StrategyNexthopState@%p {",
- instance);
- parcDisplayIndented_PrintLine(indentation + 1, "%d", instance->pi);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_pi);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->weight);
- parcDisplayIndented_PrintLine(indentation, "}");
-}
-
-bool strategyNexthopState_Equals(const StrategyNexthopState *x,
- const StrategyNexthopState *y) {
- bool result = false;
-
- if (x == y) {
- result = true;
- } else if (x == NULL || y == NULL) {
- result = false;
- } else {
- strategyNexthopState_OptionalAssertValid(x);
- strategyNexthopState_OptionalAssertValid(y);
-
- if (strategyNexthopState_Compare(x, y) == 0) {
- result = true;
- }
- }
-
- return result;
-}
-
-PARCHashCode strategyNexthopState_HashCode(const StrategyNexthopState *x) {
- PARCHashCode result = 0;
- char str[128];
- sprintf(str, "PI:%d: AVG_PI:%f: W:%f", x->pi, x->avg_pi, x->weight);
- result = parcHashCode_Hash((uint8_t *)&str, strlen(str));
- return result;
-}
-
-bool strategyNexthopState_IsValid(const StrategyNexthopState *x) {
- bool result = false;
-
- if (x != NULL) {
- result = true;
- }
-
- return result;
-}
-
-char *strategyNexthopState_ToString(const StrategyNexthopState *x) {
- // this is not implemented
- parcTrapNotImplemented("strategyNexthopState_ToString is not implemented");
- return NULL;
-}
-
-unsigned strategyNexthopState_GetPI(const StrategyNexthopState *x) {
- strategyNexthopState_OptionalAssertValid(x);
-
- return x->pi;
-}
-
-double strategyNexthopState_GetAvgPI(const StrategyNexthopState *x) {
- strategyNexthopState_OptionalAssertValid(x);
-
- return x->avg_pi;
-}
-
-double strategyNexthopState_GetWeight(const StrategyNexthopState *x) {
- strategyNexthopState_OptionalAssertValid(x);
-
- return x->weight;
-}
-
-double strategyNexthopState_UpdateState(StrategyNexthopState *x, bool inc,
- double alpha) {
- if (inc) {
- x->pi++;
- } else {
- if (x->pi > 0) {
- x->pi--;
- }
- }
- x->avg_pi = (x->avg_pi * alpha) + (x->pi * (1 - alpha));
-#ifdef WITH_POLICY
- if (x->avg_pi < AVG_PI_THRESHOLD) {
-#else
- if (x->avg_pi == 0.0) {
-#endif /* WITH_POLICY */
- x->avg_pi = 0.1;
- }
- x->weight = 1 / x->avg_pi;
-
- return x->weight;
-}
diff --git a/hicn-light/src/hicn/strategies/nexthopState.h b/hicn-light/src/hicn/strategies/nexthopState.h
deleted file mode 100644
index 35a9f497b..000000000
--- a/hicn-light/src/hicn/strategies/nexthopState.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef nexthopstate_h
-#define nexthopstate_h
-
-#include <parc/algol/parc_HashCode.h>
-#include <parc/algol/parc_Object.h>
-
-struct strategy_nexthop_state;
-typedef struct strategy_nexthop_state StrategyNexthopState;
-extern parcObjectDescriptor_Declaration(StrategyNexthopState);
-
-/**
- */
-StrategyNexthopState *strategyNexthopState_Acquire(
- const StrategyNexthopState *instance);
-
-#ifdef PARCLibrary_DISABLE_VALIDATION
-#define strategyNexthopState_OptionalAssertValid(_instance_)
-#else
-#define strategyNexthopState_OptionalAssertValid(_instance_) \
- strategyNexthopState_AssertValid(_instance_)
-#endif
-
-/**
- */
-void strategyNexthopState_AssertValid(const StrategyNexthopState *instance);
-
-/**
- */
-StrategyNexthopState *strategyNexthopState_Create();
-
-void strategyNexthopState_Reset(StrategyNexthopState *x);
-/**
- */
-int strategyNexthopState_Compare(const StrategyNexthopState *instance,
- const StrategyNexthopState *other);
-
-/**
- */
-StrategyNexthopState *strategyNexthopState_Copy(
- const StrategyNexthopState *original);
-
-/**
- */
-void strategyNexthopState_Display(const StrategyNexthopState *instance,
- int indentation);
-
-/**
- */
-bool strategyNexthopState_Equals(const StrategyNexthopState *x,
- const StrategyNexthopState *y);
-
-/**
- */
-PARCHashCode strategyNexthopState_HashCode(
- const StrategyNexthopState *instance);
-
-/**
- */
-bool strategyNexthopState_IsValid(const StrategyNexthopState *instance);
-
-/**
- */
-void strategyNexthopState_Release(StrategyNexthopState **instancePtr);
-
-/**
- */
-char *strategyNexthopState_ToString(const StrategyNexthopState *instance);
-
-/**
- */
-unsigned strategyNexthopState_GetPI(const StrategyNexthopState *x);
-
-double strategyNexthopState_GetAvgPI(const StrategyNexthopState *x);
-
-double strategyNexthopState_GetWeight(const StrategyNexthopState *x);
-
-double strategyNexthopState_UpdateState(StrategyNexthopState *x, bool inc,
- double alpha);
-#endif
diff --git a/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c b/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c
index a3953987f..ceed60cf3 100644
--- a/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c
+++ b/hicn-light/src/hicn/strategies/nexthopStateLowLatency.c
@@ -24,291 +24,6 @@
#include <parc/assert/parc_Assert.h>
#include <hicn/strategies/nexthopStateLowLatency.h>
-const unsigned MAX_ROUNS_WITHOUT_PROBES = 4;
- //if we do not receives probes for 4 rounds it means
- //that we had no responce from any producer for 2 sec
- //we can say that this interface is daed
-const unsigned MIN_NON_LOSSY_ROUNDS = 10;
- //number of rounds in non lossy mode before switch to
- //no lossy state
-const double MAX_LOSS_RATE = 0.10; //10%
-
-struct strategy_nexthop_state_ll {
- bool in_use;
- bool is_allowed; // the policy may not allow the use of this face
- unsigned face_id;
- unsigned sent_packets;
- //switch metrics
- unsigned last_try_to_switch_round;
- unsigned try_to_switch_counter;
- //probes counters
- unsigned recevied_probes;
- unsigned rounds_without_probes;
- unsigned sent_probes;
- unsigned lost_probes;
- unsigned non_lossy_rounds;
- //avgs
- double avg_rtt;
- double avg_rtt_in_use;
- double avg_queue;
- double avg_loss_rate;
-
-};
-
-static bool _strategyNexthopStateLL_Destructor(
- StrategyNexthopStateLL **instancePtr) {
- return true;
-}
-
-parcObject_ImplementAcquire(strategyNexthopStateLL, StrategyNexthopStateLL);
-
-parcObject_ImplementRelease(strategyNexthopStateLL, StrategyNexthopStateLL);
-
-parcObject_Override(
- StrategyNexthopStateLL, PARCObject,
- .destructor = (PARCObjectDestructor *)_strategyNexthopStateLL_Destructor,
- .copy = (PARCObjectCopy *)strategyNexthopStateLL_Copy,
- .display = (PARCObjectDisplay *)strategyNexthopStateLL_Display,
- .toString = (PARCObjectToString *)strategyNexthopStateLL_ToString,
- .equals = (PARCObjectEquals *)strategyNexthopStateLL_Equals,
- .compare = (PARCObjectCompare *)strategyNexthopStateLL_Compare,
- .hashCode = (PARCObjectHashCode *)strategyNexthopStateLL_HashCode,
- .display = (PARCObjectDisplay *)strategyNexthopStateLL_Display);
-
-void strategyNexthopStateLL_AssertValid(const StrategyNexthopStateLL *instance) {
- parcAssertTrue(strategyNexthopStateLL_IsValid(instance),
- "StrategyNexthopState is not valid.");
-}
-
-StrategyNexthopStateLL *strategyNexthopStateLL_Create(unsigned face_id) {
- StrategyNexthopStateLL *result =
- parcObject_CreateInstance(StrategyNexthopStateLL);
- if (result != NULL) {
- result->in_use = false;
- result->is_allowed = true;
- result->face_id = face_id;
- result->sent_packets = 0;
- result->last_try_to_switch_round = 0;
- result->try_to_switch_counter = 0;
- result->recevied_probes = 0;
- result->rounds_without_probes = 0;
- result->sent_probes = 0;
- result->lost_probes = 0;
- result->non_lossy_rounds = MIN_NON_LOSSY_ROUNDS;
- result->avg_rtt = -1.0;
- result->avg_rtt_in_use = -1.0;
- result->avg_queue = 0.0001;
- result->avg_loss_rate = 0.0;
- }
- return result;
-}
-
-void strategyNexthopStateLL_Reset(StrategyNexthopStateLL *x) {
- x->in_use = false;
- x->is_allowed = true;
- x->sent_packets = 0;
- x->last_try_to_switch_round = 0;
- x->try_to_switch_counter = 0;
- x->recevied_probes = 0;
- x->rounds_without_probes = 0;
- x->sent_probes = 0;
- x->lost_probes = 0;
- x->non_lossy_rounds = MIN_NON_LOSSY_ROUNDS;
- x->avg_rtt = -1.0;
- x->avg_rtt_in_use = -1.0;
- x->avg_queue = 0.0001;
- x->avg_loss_rate = 0.0;
-}
-
-
-int strategyNexthopStateLL_Compare(const StrategyNexthopStateLL *val,
- const StrategyNexthopStateLL *other) {
- if (val == NULL) {
- if (other != NULL) {
- return -1;
- }
- } else if (other == NULL) {
- return 1;
- } else {
- strategyNexthopStateLL_OptionalAssertValid(val);
- strategyNexthopStateLL_OptionalAssertValid(other);
-
- if (val->in_use < other->in_use){
- return -1;
- }else if (val->in_use > other->in_use){
- return 1;
- }
-
- if (val->is_allowed < other->is_allowed){
- return -1;
- }else if (val->is_allowed> other->is_allowed){
- return 1;
- }
-
- if (val->face_id < other->face_id) {
- return -1;
- } else if (val->face_id > other->face_id) {
- return 1;
- }
-
- if (val->sent_packets < other->sent_packets){
- return -1;
- } else if (val->sent_packets > other->sent_packets){
- return 1;
- }
-
- if (val->last_try_to_switch_round <
- other->last_try_to_switch_round) {
- return -1;
- } else if (val->last_try_to_switch_round >
- other->last_try_to_switch_round) {
- return 1;
- }
-
- if (val->try_to_switch_counter <
- other->try_to_switch_counter) {
- return -1;
- } else if (val->try_to_switch_counter >
- other->try_to_switch_counter) {
- return 1;
- }
-
- if (val->recevied_probes < other->recevied_probes) {
- return -1;
- } else if (val->recevied_probes > other->recevied_probes) {
- return 1;
- }
-
- if (val->rounds_without_probes < other->rounds_without_probes) {
- return -1;
- } else if (val->rounds_without_probes > other->rounds_without_probes) {
- return 1;
- }
-
- if (val->sent_probes < other->sent_probes) {
- return -1;
- } else if (val->sent_probes > other->sent_probes) {
- return 1;
- }
-
- if (val->lost_probes < other->lost_probes) {
- return -1;
- } else if (val->lost_probes > other->lost_probes) {
- return 1;
- }
-
- if (val->non_lossy_rounds < other->non_lossy_rounds) {
- return -1;
- } else if (val->non_lossy_rounds > other->non_lossy_rounds) {
- return 1;
- }
-
- if (val->avg_rtt < other->avg_rtt) {
- return -1;
- } else if (val->avg_rtt > other->avg_rtt) {
- return 1;
- }
-
- if (val->avg_rtt_in_use < other->avg_rtt_in_use) {
- return -1;
- } else if (val->avg_rtt_in_use > other->avg_rtt_in_use) {
- return 1;
- }
-
- if (val->avg_queue < other->avg_queue) {
- return -1;
- } else if (val->avg_queue > other->avg_queue) {
- return 1;
- }
-
- if (val->avg_loss_rate < other->avg_loss_rate) {
- return -1;
- } else if (val->avg_loss_rate > other->avg_loss_rate) {
- return 1;
- }
- }
-
- return 0;
-}
-
-StrategyNexthopStateLL *strategyNexthopStateLL_Copy(
- const StrategyNexthopStateLL *original) {
- StrategyNexthopStateLL *result = strategyNexthopStateLL_Create(original->face_id);
- result->in_use = original->in_use;
- result->is_allowed = original->is_allowed;
- result->sent_packets = original->sent_packets;
- result->last_try_to_switch_round = original->last_try_to_switch_round;
- result->try_to_switch_counter = original->try_to_switch_counter;
- result->recevied_probes = original->recevied_probes;
- result->rounds_without_probes = original->rounds_without_probes;
- result->sent_probes = original->sent_probes;
- result->lost_probes = original->lost_probes;
- result->non_lossy_rounds = original->non_lossy_rounds;
- result->avg_rtt = original->avg_rtt;
- result->avg_rtt_in_use = original->avg_rtt_in_use;
- result->avg_queue = original->avg_queue;
- result->avg_loss_rate = original->avg_loss_rate;
- return result;
-}
-
-void strategyNexthopStateLL_Display(const StrategyNexthopStateLL *instance,
- int indentation) {
- parcDisplayIndented_PrintLine(indentation, "StrategyNexthopStateLL@%p {",
- instance);
- parcDisplayIndented_PrintLine(indentation + 1, "%d", instance->face_id);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_rtt);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_rtt_in_use);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_queue);
- parcDisplayIndented_PrintLine(indentation + 1, "%f", instance->avg_loss_rate);
- parcDisplayIndented_PrintLine(indentation, "}");
-}
-
-
-bool strategyNexthopStateLL_Equals(const StrategyNexthopStateLL *x,
- const StrategyNexthopStateLL *y) {
- bool result = false;
-
- if (x == y) {
- result = true;
- } else if (x == NULL || y == NULL) {
- result = false;
- } else {
- strategyNexthopStateLL_OptionalAssertValid(x);
- strategyNexthopStateLL_OptionalAssertValid(y);
-
- if (strategyNexthopStateLL_Compare(x, y) == 0) {
- result = true;
- }
- }
-
- return result;
-}
-
-PARCHashCode strategyNexthopStateLL_HashCode(const StrategyNexthopStateLL *x) {
- PARCHashCode result = 0;
- char str[128];
- sprintf(str, "ID:%d: RTT:%f: RTTUSE:%f: Q:%f L:%f", x->face_id, x->avg_rtt,
- x->avg_rtt_in_use, x->avg_queue, x->avg_loss_rate);
- result = parcHashCode_Hash((uint8_t *)&str, strlen(str));
- return result;
-}
-
-bool strategyNexthopStateLL_IsValid(const StrategyNexthopStateLL *x) {
- bool result = false;
-
- if (x != NULL) {
- result = true;
- }
-
- return result;
-}
-
-char *strategyNexthopStateLL_ToString(const StrategyNexthopStateLL *x) {
- // this is not implemented
- parcTrapNotImplemented("strategyNexthopStateLL_ToString is not implemented");
- return NULL;
-}
-
double strategyNexthopStateLL_GetRTTProbe(StrategyNexthopStateLL *x) {
strategyNexthopStateLL_OptionalAssertValid(x);
diff --git a/hicn-light/src/hicn/strategies/random.c b/hicn-light/src/hicn/strategies/random.c
new file mode 100644
index 000000000..329bb1153
--- /dev/null
+++ b/hicn-light/src/hicn/strategies/random.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <hicn/hicn-light/config.h>
+
+#include <hicn/core/nexthops.h>
+#include <hicn/core/strategy.h>
+#include <hicn/core/strategy_vft.h>
+
+#include "random.h"
+
+static
+void
+strategy_random_initialize(strategy_entry_t * entry)
+{
+ srand((unsigned int)time(NULL));
+}
+
+static
+void
+strategy_random_finalize(strategy_entry_t * entry)
+{
+ /* Nothing to do */
+}
+
+static
+void
+strategy_random_add_nexthop(strategy_entry_t * entry, unsigned nexthop,
+ strategy_nexthop_state_t * state)
+{
+ /* Nothing to do */
+}
+
+static
+void
+strategy_random_remove_nexthop(strategy_entry_t * entry, unsigned nexthop,
+ strategy_nexthop_state_t * state)
+{
+ /* Nothing to do */
+}
+
+static
+nexthops_t *
+strategy_random_lookup_nexthops(strategy_entry_t * entry,
+ nexthops_t * nexthops,
+ const msgbuf_t * msgbuf)
+{
+ nexthops_select(nexthops, rand() % nexthops_get_len(nexthops));
+ return nexthops;
+}
+
+static
+void
+strategy_random_on_data(strategy_entry_t * entry,
+ const nexthops_t * nexthops, const msgbuf_t * msgbuf,
+ Ticks pitEntryCreation, Ticks objReception)
+{
+ /* Nothing to do */
+}
+
+static
+void
+strategy_random_on_timeout(strategy_entry_t * entry,
+ const nexthops_t * nexthops)
+{
+ /* Nothing to do */
+}
+
+
+DECLARE_STRATEGY(random);
diff --git a/hicn-light/src/hicn/strategies/rnd.h b/hicn-light/src/hicn/strategies/random.h
index 78fb34758..edcc893e7 100644
--- a/hicn-light/src/hicn/strategies/rnd.h
+++ b/hicn-light/src/hicn/strategies/random.h
@@ -17,11 +17,13 @@
* Forward randomly
*/
-#ifndef rnd_h
-#define rnd_h
+#ifndef HICNLIGHT_STRATEGY_RANDOM_H
+#define HICNLIGHT_STRATEGY_RANDOM_H
-#include <hicn/strategies/strategyImpl.h>
+typedef struct {} strategy_random_nexthop_state_t;
-StrategyImpl* strategyRnd_Create();
+typedef struct {} strategy_random_state_t;
-#endif // rnd_h
+typedef struct {} strategy_random_options_t;
+
+#endif /* HICNLIGHT_STRATEGY_RANDOM_H */
diff --git a/hicn-light/src/hicn/strategies/rnd.c b/hicn-light/src/hicn/strategies/rnd.c
deleted file mode 100644
index 064f3965b..000000000
--- a/hicn-light/src/hicn/strategies/rnd.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/hicn-light/config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <parc/assert/parc_Assert.h>
-
-#include <parc/algol/parc_HashMap.h>
-#include <parc/algol/parc_Memory.h>
-
-#include <hicn/strategies/rnd.h>
-
-static void _strategyRnd_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception);
-static void _strategyRnd_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId);
-
-static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
-static NumberSet *_strategyRnd_ReturnNexthops(StrategyImpl *strategy);
-static unsigned _strategyRnd_CountNexthops(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
-static void _strategyRnd_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyRnd_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId);
-static void _strategyRnd_ImplDestroy(StrategyImpl **strategyPtr);
-static strategy_type _strategyRnd_GetStrategy(StrategyImpl *strategy);
-
-static StrategyImpl _template = {
- .context = NULL,
- .receiveObject = &_strategyRnd_ReceiveObject,
- .onTimeout = &_strategyRnd_OnTimeout,
- .lookupNexthop = &_strategyRnd_LookupNexthop,
-#ifndef WITH_POLICY
- .returnNexthops = &_strategyRnd_ReturnNexthops,
- .countNexthops = &_strategyRnd_CountNexthops,
-#endif /* ! WITH_POLICY */
- .addNexthop = &_strategyRnd_AddNexthop,
- .removeNexthop = &_strategyRnd_RemoveNexthop,
- .destroy = &_strategyRnd_ImplDestroy,
- .getStrategy = &_strategyRnd_GetStrategy,
-};
-
-#ifndef WITH_POLICY
-struct strategy_rnd;
-typedef struct strategy_rnd StrategyRnd;
-
-struct strategy_rnd {
- NumberSet *nexthops;
-};
-#endif /* ! WITH_POLICY */
-
-StrategyImpl *strategyRnd_Create() {
-#ifndef WITH_POLICY
- StrategyRnd *strategy = parcMemory_AllocateAndClear(sizeof(StrategyRnd));
- parcAssertNotNull(strategy, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyRnd));
-
- strategy->nexthops = numberSet_Create();
-#endif /* ! WITH_POLICY */
- srand((unsigned int)time(NULL));
-
- StrategyImpl *impl = parcMemory_AllocateAndClear(sizeof(StrategyImpl));
- parcAssertNotNull(impl, "parcMemory_AllocateAndClear(%zu) returned NULL",
- sizeof(StrategyImpl));
- memcpy(impl, &_template, sizeof(StrategyImpl));
-#ifndef WITH_POLICY
- impl->context = strategy;
-#endif /* ! WITH_POLICY */
- return impl;
-}
-
-// =======================================================
-// Dispatch API
-
-strategy_type _strategyRnd_GetStrategy(StrategyImpl *strategy) {
- return SET_STRATEGY_RANDOM;
-}
-
-#ifndef WITH_POLICY
-static int _select_Nexthop(StrategyRnd *strategy) {
- unsigned len = (unsigned)numberSet_Length(strategy->nexthops);
- if (len == 0) {
- return -1;
- }
-
- int rnd = (rand() % len);
- return numberSet_GetItem(strategy->nexthops, rnd);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyRnd_ReceiveObject(StrategyImpl *strategy,
- const NumberSet *egressId,
- const Message *objectMessage,
- Ticks pitEntryCreation,
- Ticks objReception) {}
-
-static void _strategyRnd_OnTimeout(StrategyImpl *strategy,
- const NumberSet *egressId) {}
-
-static NumberSet *_strategyRnd_LookupNexthop(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage) {
- unsigned out_connection;
- NumberSet *out = numberSet_Create();
-
-#ifdef WITH_POLICY
- // We return one next hop at random
- out_connection = numberSet_GetItem(nexthops, rand() % numberSet_Length(nexthops));
-
-#else
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- unsigned in_connection = message_GetIngressConnectionId(interestMessage);
- unsigned nexthopSize = (unsigned)numberSet_Length(srnd->nexthops);
-
- if ((nexthopSize == 0) ||
- ((nexthopSize == 1) &&
- numberSet_Contains(srnd->nexthops, in_connection))) {
- // there are no output faces or the input face is also the only output face.
- // return null to avoid loops
- return out;
- }
-
- do {
- out_connection = _select_Nexthop(srnd);
- } while (out_connection == in_connection);
-
- if (out_connection == -1) {
- return out;
- }
-#endif /* WITH_POLICY */
-
- numberSet_Add(out, out_connection);
- return out;
-}
-
-#ifndef WITH_POLICY
-static NumberSet *_strategyRnd_ReturnNexthops(StrategyImpl *strategy) {
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- return srnd->nexthops;
-}
-
-unsigned _strategyRnd_CountNexthops(StrategyImpl *strategy) {
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- return (unsigned)numberSet_Length(srnd->nexthops);
-}
-#endif /* ! WITH_POLICY */
-
-static void _strategyRnd_AddNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
-#ifndef WITH_POLICY
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
- if (!numberSet_Contains(srnd->nexthops, connectionId)) {
- numberSet_Add(srnd->nexthops, connectionId);
- }
-#endif /* ! WITH_POLICY */
-}
-
-static void _strategyRnd_RemoveNexthop(StrategyImpl *strategy,
- unsigned connectionId) {
-#ifndef WITH_POLICY
- StrategyRnd *srnd = (StrategyRnd *)strategy->context;
-
- if (numberSet_Contains(srnd->nexthops, connectionId)) {
- numberSet_Remove(srnd->nexthops, connectionId);
- }
-#endif /* ! WITH_POLICY */
-}
-
-static void _strategyRnd_ImplDestroy(StrategyImpl **strategyPtr) {
- parcAssertNotNull(strategyPtr, "Parameter must be non-null double pointer");
- parcAssertNotNull(*strategyPtr,
- "Parameter must dereference to non-null pointer");
-
- StrategyImpl *impl = *strategyPtr;
-
-#ifndef WITH_POLICY
- StrategyRnd *strategy = (StrategyRnd *)impl->context;
- numberSet_Release(&(strategy->nexthops));
- parcMemory_Deallocate((void **)&strategy);
-#endif /* ! WITH_POLICY */
-
- parcMemory_Deallocate((void **)&impl);
- *strategyPtr = NULL;
-}
diff --git a/hicn-light/src/hicn/strategies/strategyImpl.h b/hicn-light/src/hicn/strategies/strategyImpl.h
deleted file mode 100644
index 140da5bf8..000000000
--- a/hicn-light/src/hicn/strategies/strategyImpl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file strategyImpl.h
- * @brief Defines the function structure for a Strategy implementation
- *
- * <#Detailed Description#>
- *
- */
-
-/**
- * A dispatch structure for a concrete implementation of a forwarding strategy.
- */
-
-#ifndef strategyImpl_h
-#define strategyImpl_h
-
-#include <hicn/core/message.h>
-#include <hicn/core/numberSet.h>
-
-struct strategy_impl;
-typedef struct strategy_impl StrategyImpl;
-
-/**
- * @typedef StrategyImpl
- * @abstract Forwarding strategy implementation
- * @constant receiveObject is called when we receive an object and have a
- * measured round trip time. This allows a strategy to update its performance
- * data.
- * @constant lookupNexthop Find the set of nexthops to use for the Interest.
- * May be empty, should not be NULL. Must be destroyed.
- * @constant addNexthop Add a nexthop to the list of available nexthops with a
- * routing protocol-specific cost.
- * @constant destroy cleans up the strategy, freeing all memory and state. A
- * strategy is reference counted, so the final destruction only happens after
- * the last reference is released.
- * @discussion <#Discussion#>
- */
-struct strategy_impl {
- void *context;
- void (*receiveObject)(StrategyImpl *strategy, const NumberSet *egressId,
- const Message *objectMessage, Ticks pitEntryCreation,
- Ticks objReception);
- void (*onTimeout)(StrategyImpl *strategy, const NumberSet *egressId);
- NumberSet *(*lookupNexthop)(StrategyImpl *strategy,
-#ifdef WITH_POLICY
- NumberSet * nexthops,
-#endif /* WITH_POLICY */
- const Message *interestMessage);
-#ifndef WITH_POLICY
- NumberSet *(*returnNexthops)(StrategyImpl *strategy);
- unsigned (*countNexthops)(StrategyImpl *strategy);
-#endif /* ! WITH_POLICY */
- void (*addNexthop)(StrategyImpl *strategy, unsigned connectionId);
- void (*removeNexthop)(StrategyImpl *strategy, unsigned connectionId);
- void (*destroy)(StrategyImpl **strategyPtr);
- strategy_type (*getStrategy)(StrategyImpl *strategy);
-};
-
-#endif // strategyImpl_h