aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/processor
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2019-07-26 23:20:30 +0200
committerMauro Sardara <msardara@cisco.com>2019-07-29 17:13:35 +0200
commit0a1c6b5565e20167d1f1f33a5a8b597f420b18b0 (patch)
tree98c5da8f231fbd3dc2ce6502040e29c8333d9ffc /hicn-light/src/hicn/processor
parent05ca0aa8f612ee48fb66d4dbebe596b7f1e03181 (diff)
[HICN-252] Add per-application policy framework to hicn-light forwarder
Change-Id: I0531cd7a7de179581295ae34766c81cd9cf3e172 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com> Signed-off-by: Mauro Sardara <msardara@cisco.com> Co-authored-by: Mauro Sardara <msardara@cisco.com>
Diffstat (limited to 'hicn-light/src/hicn/processor')
-rw-r--r--hicn-light/src/hicn/processor/fib.c117
-rw-r--r--hicn-light/src/hicn/processor/fib.h4
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.c689
-rw-r--r--hicn-light/src/hicn/processor/fibEntry.h44
-rw-r--r--hicn-light/src/hicn/processor/messageProcessor.c161
-rw-r--r--hicn-light/src/hicn/processor/messageProcessor.h43
-rw-r--r--hicn-light/src/hicn/processor/pitStandard.c4
-rw-r--r--hicn-light/src/hicn/processor/pitVerdict.h4
8 files changed, 1041 insertions, 25 deletions
diff --git a/hicn-light/src/hicn/processor/fib.c b/hicn-light/src/hicn/processor/fib.c
index 19e4db60b..7cb94d4ba 100644
--- a/hicn-light/src/hicn/processor/fib.c
+++ b/hicn-light/src/hicn/processor/fib.c
@@ -81,7 +81,6 @@ void _destroyNode(FibNode *n) {
}
void _destroyFib(FIB *fib) {
- // XXX
// to be done
return;
}
@@ -103,6 +102,13 @@ void fib_Add(FIB *fib, FibEntry *entry) {
NameBitvector *name = name_GetContentName(fibEntry_GetPrefix(entry));
+ //if the name len is 0, we add this entry on the root
+ if(nameBitvector_GetLength(name) == 0){
+ fib->size++;
+ fib->root->entry = entry;
+ return;
+ }
+
// search the name
FibNode *prev = fib->root;
FibNode *curr;
@@ -122,7 +128,7 @@ void fib_Add(FIB *fib, FibEntry *entry) {
}
}
- if (curr->entry != NULL &&
+ if (curr->entry != NULL && curr->pos != NULL_POS &&
nameBitvector_Equals(
name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) {
// there is already an entry with this name
@@ -134,9 +140,10 @@ void fib_Add(FIB *fib, FibEntry *entry) {
// if the name is not in the FIB search for the first different bit between
// the new name to add and the node found in the trie
uint8_t pos = MSB_POS;
- if (curr->entry != NULL)
+ if (curr->entry != NULL && curr->pos != NULL_POS){
pos = nameBitvector_firstDiff(
name, name_GetContentName(fibEntry_GetPrefix(curr->entry)));
+ }
// reset pointer and search the insertion point
prev = fib->root;
@@ -182,6 +189,13 @@ FibEntry *fib_Contains(const FIB *fib, const Name *prefix) {
NameBitvector *name = name_GetContentName(prefix);
+ //if prefix len is 0 it must be stored in the root.
+ //if the root entry is null we need to create it, otherwise
+ //we just need to add an other nexthop
+ if(nameBitvector_GetLength(name) == 0){
+ return fib->root->entry;
+ }
+
// this is the same as the first part of the add function
// we cannnot call this function inside the add because
// we need the pointer prev and curr for the insertion
@@ -204,7 +218,7 @@ FibEntry *fib_Contains(const FIB *fib, const Name *prefix) {
}
}
- if (curr->entry != NULL &&
+ if (curr->entry != NULL && curr->pos != NULL_POS &&
nameBitvector_Equals(
name, name_GetContentName(fibEntry_GetPrefix(curr->entry)))) {
return curr->entry;
@@ -333,7 +347,17 @@ void fib_Remove(FIB *fib, const Name *name, unsigned connId) {
fibEntry_RemoveNexthopByConnectionId(entry, connId);
if (fibEntry_NexthopCount(entry) == 0) {
- _removeNode(fib, name);
+ //if the len is 0, just release the fibEntry on the root node
+ if(nameBitvector_GetLength(
+ name_GetContentName(fibEntry_GetPrefix(entry))) == 0){
+ parcAssertTrue(entry == fib->root->entry,
+ "prefix len == 0, entry is not in the FIB root");
+ fib->size--;
+ fibEntry_Release(&entry);
+ fib->root->entry = NULL;
+ } else {
+ _removeNode(fib, name);
+ }
}
}
@@ -352,10 +376,20 @@ void _removeConnectionId(FibNode *n, unsigned pos, unsigned connectionId,
void fib_RemoveConnectionId(FIB *fib, unsigned connectionId) {
parcAssertNotNull(fib, "Parameter must be non-null");
+ // 0 - remove the connection id from the root
// 1 - we vist the tree to remove the connection id
// 2 - during the visit we collect the fib entry with 0 nexthop
// 3 - after the visit we remove this entries
+ if(fib->root->entry){
+ fibEntry_RemoveNexthopByConnectionId(fib->root->entry, connectionId);
+ if(fibEntry_NexthopCount(fib->root->entry) == 0){
+ fib->size--;
+ fibEntry_Release(&fib->root->entry);
+ fib->root->entry = NULL;
+ }
+ }
+
FibEntryList *list = fibEntryList_Create();
_removeConnectionId(fib->root->left, fib->root->pos, connectionId, list);
@@ -393,7 +427,7 @@ FibEntry *fib_Match(const FIB *fib, const Message *interestMessage) {
while (prev->pos > curr->pos) {
prev = curr;
- if (curr->entry != NULL) {
+ if (curr->entry != NULL && curr->pos != NULL_POS) {
if (nameBitvector_StartsWith(
name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) &&
nameBitvector_GetLength(
@@ -410,7 +444,7 @@ FibEntry *fib_Match(const FIB *fib, const Message *interestMessage) {
curr = curr->left;
}
- if (curr->entry != NULL) {
+ if (curr->entry != NULL && curr->pos != NULL_POS) {
if (nameBitvector_StartsWith(
name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) &&
nameBitvector_GetLength(
@@ -424,10 +458,73 @@ FibEntry *fib_Match(const FIB *fib, const Message *interestMessage) {
if (match != NULL && match->entry != NULL) {
return match->entry;
} else {
- return NULL;
+ //if there is a default route, return it.
+ //the dafualt route is in the route
+ return fib->root->entry;
}
}
+#ifdef WITH_MAPME
+
+FibEntry *fib_LPM(const FIB *fib, const Name * prefix) {
+ parcAssertNotNull(fib, "Parameter must be non-null");
+ parcAssertNotNull(prefix, "Parameter must be non-null");
+
+ NameBitvector *name = name_GetContentName(prefix);
+
+ FibNode *prev = fib->root;
+ FibNode *curr;
+
+ FibNode *match = NULL;
+ unsigned len = 0;
+
+ if (nameBitvector_testBit(name, MSB_POS))
+ curr = fib->root->right;
+ else
+ curr = fib->root->left;
+
+ while (prev->pos > curr->pos) {
+ prev = curr;
+
+ if (curr->entry != NULL && curr->pos != NULL_POS) {
+ if (nameBitvector_StartsWith(
+ name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) &&
+ nameBitvector_GetLength(
+ name_GetContentName(fibEntry_GetPrefix(curr->entry))) > len) {
+ match = curr;
+ len = nameBitvector_GetLength(
+ name_GetContentName(fibEntry_GetPrefix(curr->entry)));
+ }
+ }
+
+ if (nameBitvector_testBit(name, curr->pos))
+ curr = curr->right;
+ else
+ curr = curr->left;
+ }
+
+ if (curr->entry != NULL && curr->pos != NULL_POS) {
+ if (nameBitvector_StartsWith(
+ name, name_GetContentName(fibEntry_GetPrefix(curr->entry))) &&
+ nameBitvector_GetLength(
+ name_GetContentName(fibEntry_GetPrefix(curr->entry))) > len) {
+ match = curr;
+ len = nameBitvector_GetLength(
+ name_GetContentName(fibEntry_GetPrefix(curr->entry)));
+ }
+ }
+
+ if (match != NULL && match->entry != NULL) {
+ return match->entry;
+ } else {
+ //if there is a default route, return it.
+ //the dafualt route is in the route
+ return fib->root->entry;
+ }
+}
+
+#endif /* WITH_MAPME */
+
void _collectFibEntries(FibNode *n, int pos, FibEntryList *list) {
if (n->pos < (unsigned)pos) {
fibEntryList_Append(list, n->entry);
@@ -441,6 +538,10 @@ FibEntryList *fib_GetEntries(const FIB *fib) {
FibEntryList *list = fibEntryList_Create();
+ if(fib->root->entry){
+ fibEntryList_Append(list, fib->root->entry);
+ }
+
_collectFibEntries(fib->root->left, fib->root->pos, list);
_collectFibEntries(fib->root->right, fib->root->pos, list);
diff --git a/hicn-light/src/hicn/processor/fib.h b/hicn-light/src/hicn/processor/fib.h
index 28ea19a0d..8c03537fe 100644
--- a/hicn-light/src/hicn/processor/fib.h
+++ b/hicn-light/src/hicn/processor/fib.h
@@ -37,6 +37,10 @@ void fib_RemoveConnectionId(FIB *fib, unsigned connectionId);
FibEntry *fib_Match(const FIB *fib, const Message *interestMessage);
+#ifdef WITH_MAPME
+FibEntry *fib_LPM(const FIB *fib, const Name * name);
+#endif /* WITH_MAPME */
+
size_t fib_Length(const FIB *fib);
FibEntryList *fib_GetEntries(const FIB *fib);
diff --git a/hicn-light/src/hicn/processor/fibEntry.c b/hicn-light/src/hicn/processor/fibEntry.c
index 6f6b3aa12..15d754168 100644
--- a/hicn-light/src/hicn/processor/fibEntry.c
+++ b/hicn-light/src/hicn/processor/fibEntry.c
@@ -35,18 +35,47 @@
#include <parc/assert/parc_Assert.h>
#include <hicn/utils/commands.h>
+#include <hicn/core/connectionState.h>
+
+#ifdef WITH_POLICY
+#include <hicn/core/forwarder.h>
+#include <hicn/utils/policy.h>
+
+#ifdef WITH_MAPME
+#include <hicn/core/mapMe.h>
+#endif /* WITH_MAPME */
+
+#define ALPHA 0.5
+
+#endif /* WITH_POLICY */
struct fib_entry {
Name *name;
unsigned refcount;
StrategyImpl *fwdStrategy;
+#ifdef WITH_POLICY
+ NumberSet *nexthops;
+ const Forwarder * forwarder;
+ policy_t policy;
+ policy_counters_t policy_counters;
+ NumberSet *available_nexthops;
+#ifdef WITH_MAPME
+ /* In case of no multipath, this stores the previous decision taken by policy */
+ unsigned previous_nexthop;
+#endif /* WITH_MAPME */
+#endif /* WITH_POLICY */
#ifdef WITH_MAPME
void *userData;
void (*userDataRelease)(void **userData);
#endif /* WITH_MAPME */
};
+#ifdef WITH_POLICY
+FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy, const Forwarder * forwarder) {
+ ConnectionTable * table = forwarder_GetConnectionTable(forwarder);
+#else
FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy) {
+#endif /* WITH_POLICY */
FibEntry *fibEntry = parcMemory_AllocateAndClear(sizeof(FibEntry));
parcAssertNotNull(fibEntry, "parcMemory_AllocateAndClear(%zu) returned NULL",
sizeof(FibEntry));
@@ -55,27 +84,47 @@ FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy) {
if (fwdStrategy) {
switch (fwdStrategy) {
case SET_STRATEGY_LOADBALANCER:
+#ifdef WITH_POLICY
+ fibEntry->fwdStrategy = strategyLoadBalancer_Create(table);
+#else
fibEntry->fwdStrategy = strategyLoadBalancer_Create();
+#endif /* WITH_POLICY */
break;
case SET_STRATEGY_RANDOM_PER_DASH_SEGMENT:
+#ifdef WITH_POLICY
+ fibEntry->fwdStrategy = strategyRndSegment_Create(table);
+#else
fibEntry->fwdStrategy = strategyRndSegment_Create();
+#endif /* WITH_POLICY */
break;
case SET_STRATEGY_LOADBALANCER_WITH_DELAY:
+#ifdef WITH_POLICY
+ fibEntry->fwdStrategy = strategyLoadBalancerWithPD_Create(table);
+#else
fibEntry->fwdStrategy = strategyLoadBalancerWithPD_Create();
+#endif /* WITH_POLICY */
break;
default:
- // LB is the defualt strategy
+ // LB is the default strategy
+#ifdef WITH_POLICY
+ fibEntry->fwdStrategy = strategyLoadBalancer_Create(table);
+#else
fibEntry->fwdStrategy = strategyLoadBalancer_Create();
+#endif /* WITH_POLICY */
// the LB strategy is the default one
// other strategies can be set using the appropiate function
break;
}
} else {
+#ifdef WITH_POLICY
+ fibEntry->fwdStrategy = strategyLoadBalancer_Create(table);
+#else
fibEntry->fwdStrategy = strategyLoadBalancer_Create();
+#endif /* WITH_POLICY */
}
fibEntry->refcount = 1;
@@ -85,6 +134,16 @@ FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy) {
fibEntry->userDataRelease = NULL;
#endif /* WITH_MAPME */
+#ifdef WITH_POLICY
+ fibEntry->nexthops = numberSet_Create();
+ fibEntry->forwarder = forwarder;
+ fibEntry->policy = POLICY_NONE;
+ fibEntry->policy_counters = POLICY_COUNTERS_NONE;
+#ifdef WITH_MAPME
+ fibEntry->previous_nexthop = ~0;
+#endif /* WITH_MAPME */
+#endif /* WITH_POLICY */
+
return fibEntry;
}
@@ -114,23 +173,42 @@ void fibEntry_Release(FibEntry **fibEntryPtr) {
void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy) {
StrategyImpl *fwdStrategyImpl;
+#ifdef WITH_POLICY
+ ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
+#endif /* WITH_POLICY */
switch (strategy) {
case SET_STRATEGY_LOADBALANCER:
+#ifdef WITH_POLICY
+ fwdStrategyImpl = strategyLoadBalancer_Create(table);
+#else
fwdStrategyImpl = strategyLoadBalancer_Create();
+#endif /* WITH_POLICY */
break;
case SET_STRATEGY_RANDOM_PER_DASH_SEGMENT:
+#ifdef WITH_POLICY
+ fwdStrategyImpl = strategyRndSegment_Create(table);
+#else
fwdStrategyImpl = strategyRndSegment_Create();
+#endif /* WITH_POLICY */
break;
case SET_STRATEGY_LOADBALANCER_WITH_DELAY:
+#ifdef WITH_POLICY
+ fwdStrategyImpl = strategyLoadBalancerWithPD_Create(table);
+#else
fwdStrategyImpl = strategyLoadBalancerWithPD_Create();
+#endif /* WITH_POLICY */
break;
default:
// LB is the defualt strategy
+#ifdef WITH_POLICY
+ fwdStrategyImpl = strategyLoadBalancer_Create(table);
+#else
fwdStrategyImpl = strategyLoadBalancer_Create();
+#endif /* WITH_POLICY */
// the LB strategy is the default one
// other strategies can be set using the appropiate function
break;
@@ -145,47 +223,648 @@ void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy) {
fibEntry->fwdStrategy->destroy(&(fibEntry->fwdStrategy));
fibEntry->fwdStrategy = fwdStrategyImpl;
}
+
+#ifdef WITH_POLICY
+
+/*
+ * Update available next hops following policy update.
+ */
+NumberSet *
+fibEntry_GetAvailableNextHops(const FibEntry *fibEntry, unsigned in_connection) {
+ ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
+ NumberSet * nexthops;
+ policy_t policy = fibEntry_GetPolicy(fibEntry);
+
+ /* Reset available next hops and start filtering */
+ NumberSet * available_nexthops = numberSet_Create();
+
+ /*
+ * Give absolute preference to local faces, with no policy, unless
+ * in_connection == ~0, which means we are searching faces on which to
+ * advertise our prefix
+ */
+ if (in_connection == ~0) {
+ /* We might advertise among all available up connections */
+ nexthops = numberSet_Create();
+
+ ConnectionList * list = connectionTable_GetEntries(table);
+ for (size_t i = 0; i < connectionList_Length(list); i++) {
+ Connection *conn = connectionList_Get(list, i);
+ if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
+ continue;
+ if (connection_IsLocal(conn))
+ continue;
+ numberSet_Add(nexthops, connection_GetConnectionId(conn));
+ }
+
+ } else {
+ nexthops = (NumberSet*)fibEntry_GetNexthops(fibEntry);
+ for (size_t k = 0; k < numberSet_Length(nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(nexthops, k);
+ /* Filtering out ingress face */
+ if (conn_id == in_connection)
+ continue;
+ /* Filtering out DOWN faces */
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!conn)
+ continue;
+ if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
+ continue;
+ if (!connection_IsLocal(conn))
+ continue;
+ numberSet_Add(available_nexthops, conn_id);
+ }
+
+ if (numberSet_Length(available_nexthops) > 0)
+ return available_nexthops;
+ }
+
+ for (size_t k = 0; k < numberSet_Length(nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(nexthops, k);
+ const Connection * conn;
+
+ /* Filtering out ingress face */
+ if (conn_id == in_connection)
+ continue;
+
+ /* Filtering out DOWN faces */
+ conn = connectionTable_FindById(table, conn_id);
+ if (!conn)
+ continue;
+ if (connection_GetState(conn) == CONNECTION_STATE_DOWN)
+ continue;
+
+ /* Policy filtering : next hops */
+ if ((policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_REQUIRE) &&
+ (!connection_HasTag(conn, POLICY_TAG_WIRED)))
+ continue;
+ if ((policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PROHIBIT) &&
+ (connection_HasTag(conn, POLICY_TAG_WIRED)))
+ continue;
+ if ((policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_REQUIRE) &&
+ (!connection_HasTag(conn, POLICY_TAG_WIFI)))
+ continue;
+ if ((policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PROHIBIT) &&
+ (connection_HasTag(conn, POLICY_TAG_WIFI)))
+ continue;
+ if ((policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_REQUIRE) &&
+ (!connection_HasTag(conn, POLICY_TAG_CELLULAR)))
+ continue;
+ if ((policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PROHIBIT) &&
+ (connection_HasTag(conn, POLICY_TAG_CELLULAR)))
+ continue;
+ if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) &&
+ (!connection_HasTag(conn, POLICY_TAG_TRUSTED)))
+ continue;
+ if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PROHIBIT) &&
+ (connection_HasTag(conn, POLICY_TAG_TRUSTED)))
+ continue;
+
+ numberSet_Add(available_nexthops, conn_id);
+ }
+
+ if (numberSet_Length(available_nexthops) == 0)
+ return available_nexthops;
+
+ /* We have at least one matching next hop, implement heuristic */
+
+ /*
+ * As VPN connections might trigger duplicate uses of one interface, we start
+ * by filtering out interfaces based on trust status.
+ */
+ NumberSet * filtered_nexthops = numberSet_Create();
+ if ((policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_REQUIRE) ||
+ (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PREFER)) {
+ /* Try to filter out NON TRUSTED faces */
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!connection_HasTag(conn, POLICY_TAG_TRUSTED))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ } else {
+ /* Try to filter out TRUSTED faces */
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (connection_HasTag(conn, POLICY_TAG_TRUSTED))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+
+ /* Other preferences */
+ if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_AVOID) {
+ filtered_nexthops = numberSet_Create();
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (connection_HasTag(conn, POLICY_TAG_WIRED))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+ }
+ if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_AVOID) {
+ filtered_nexthops = numberSet_Create();
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (connection_HasTag(conn, POLICY_TAG_WIFI))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+ }
+ if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_AVOID) {
+ filtered_nexthops = numberSet_Create();
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (connection_HasTag(conn, POLICY_TAG_CELLULAR))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+ }
+
+ if (policy.tags[POLICY_TAG_WIRED].state == POLICY_STATE_PREFER) {
+ filtered_nexthops = numberSet_Create();
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!connection_HasTag(conn, POLICY_TAG_WIRED))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+ }
+ if (policy.tags[POLICY_TAG_WIFI].state == POLICY_STATE_PREFER) {
+ filtered_nexthops = numberSet_Create();
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!connection_HasTag(conn, POLICY_TAG_WIFI))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+ }
+ if (policy.tags[POLICY_TAG_CELLULAR].state == POLICY_STATE_PREFER) {
+ filtered_nexthops = numberSet_Create();
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!connection_HasTag(conn, POLICY_TAG_CELLULAR))
+ continue;
+ numberSet_Add(filtered_nexthops, conn_id);
+ }
+ if (numberSet_Length(filtered_nexthops) > 0) {
+ numberSet_Release(&available_nexthops);
+ available_nexthops = numberSet_Create();
+ numberSet_AddSet(available_nexthops, filtered_nexthops);
+ }
+ numberSet_Release(&filtered_nexthops);
+ }
+
+ return available_nexthops;
+}
+
+policy_t fibEntry_GetPolicy(const FibEntry *fibEntry) {
+ return fibEntry->policy;
+}
+
+void fibEntry_ReconsiderPolicy(FibEntry *fibEntry) {
+#ifdef WITH_MAPME
+ NumberSet * available_nexthops = fibEntry_GetAvailableNextHops(fibEntry, ~0);
+
+ if (numberSet_Length(available_nexthops) == 0)
+ goto END;
+
+ /* Multipath */
+ if ((fibEntry->policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_PROHIBIT) &&
+ (fibEntry->policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_AVOID))
+ goto END;
+
+ unsigned nexthop = numberSet_GetItem(available_nexthops, 0);
+ if (nexthop != fibEntry->previous_nexthop) {
+ /* Policy has elected a new nexthop, signal it using MAP-Me */
+ fibEntry->previous_nexthop = nexthop;
+ ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
+ const Connection * conn = connectionTable_FindById(table, nexthop);
+ mapMe_onPolicyUpdate(forwarder_getMapmeInstance(fibEntry->forwarder), conn, fibEntry);
+ }
+
+END:
+ numberSet_Release(&available_nexthops);
+#endif /* WITH_MAPME */
+}
+
+void fibEntry_SetPolicy(FibEntry *fibEntry, policy_t policy) {
+ fibEntry->policy = policy;
+ fibEntry_ReconsiderPolicy(fibEntry);
+}
+
+#endif /* WITH_POLICY */
+
void fibEntry_AddNexthop(FibEntry *fibEntry, unsigned connectionId) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+#ifdef WITH_POLICY
+ if (!numberSet_Contains(fibEntry->nexthops, connectionId)) {
+ numberSet_Add(fibEntry->nexthops, connectionId);
+ }
+#endif /* WITH_POLICY */
fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId);
}
void fibEntry_RemoveNexthopByConnectionId(FibEntry *fibEntry,
unsigned connectionId) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+#ifdef WITH_POLICY
+ if (numberSet_Contains(fibEntry->nexthops, connectionId)) {
+ numberSet_Remove(fibEntry->nexthops, connectionId);
+ }
+#endif /* WITH_POLICY */
fibEntry->fwdStrategy->removeNexthop(fibEntry->fwdStrategy, connectionId);
}
size_t fibEntry_NexthopCount(const FibEntry *fibEntry) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+#ifdef WITH_POLICY
+ return numberSet_Length(fibEntry->nexthops);
+#else
return fibEntry->fwdStrategy->countNexthops(fibEntry->fwdStrategy);
+#endif /* WITH_POLICY */
}
const NumberSet *fibEntry_GetNexthops(const FibEntry *fibEntry) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+#ifdef WITH_POLICY
+ return fibEntry->nexthops;
+#else
return fibEntry->fwdStrategy->returnNexthops(fibEntry->fwdStrategy);
+#endif /* WITH_POLICY */
}
const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy(
+#ifdef WITH_POLICY
+ FibEntry *fibEntry, const Message *interestMessage, bool is_retransmission) {
+#else
const FibEntry *fibEntry, const Message *interestMessage) {
+#endif /* WITH_POLICY */
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+#ifdef WITH_POLICY
+ ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
+ unsigned in_connection = message_GetIngressConnectionId(interestMessage);
+
+ policy_t policy = fibEntry_GetPolicy(fibEntry);
+
+ NumberSet * out;
+
+ /* Filtering */
+ NumberSet * available_nexthops = fibEntry_GetAvailableNextHops(fibEntry, in_connection);
+ if (numberSet_Length(available_nexthops) == 0) {
+ numberSet_Release(&available_nexthops);
+ out = numberSet_Create();
+ return out;
+ }
+
+ /*
+ * Update statistics about loss rates. We only detect losses upon
+ * retransmissions, and assume for the computation that the candidate set of
+ * output faces is the same as previously (i.e. does not take into account
+ * event such as face up/down, policy update, etc. Otherwise we would need to
+ * know what was the previous choice !
+ */
+ if (is_retransmission) {
+ for (size_t k = 0; k < numberSet_Length(available_nexthops); k++) {
+ unsigned conn_id = numberSet_GetItem(available_nexthops, k);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+
+ if (connection_HasTag(conn, POLICY_TAG_WIRED))
+ fibEntry->policy_counters.wired.num_losses++;
+ if (connection_HasTag(conn, POLICY_TAG_WIFI))
+ fibEntry->policy_counters.wifi.num_losses++;
+ if (connection_HasTag(conn, POLICY_TAG_CELLULAR))
+ fibEntry->policy_counters.cellular.num_losses++;
+ fibEntry->policy_counters.all.num_losses++;
+ }
+ }
+
+ /*
+ * NOTE: We might want to call a forwarding strategy even with no nexthop to
+ * take a fallback decision.
+ */
+ if (numberSet_Length(available_nexthops) == 0) {
+ out = numberSet_Create();
+ } else {
+ /* Multipath */
+ if ((policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_PROHIBIT) &&
+ (policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_AVOID)) {
+ out = fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy, available_nexthops,
+ interestMessage);
+ } else {
+ unsigned nexthop = numberSet_GetItem(available_nexthops, 0);
+ out = numberSet_Create();
+ numberSet_Add(out, nexthop);
+ }
+ }
+
+ numberSet_Release(&available_nexthops);
+
+ return out;
+#else
return fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy,
- interestMessage);
+ interestMessage);
+#endif /* WITH_POLICY */
}
+#ifdef WITH_POLICY
+void fibEntry_ReceiveObjectMessage(FibEntry *fibEntry,
+#else
void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry,
+#endif /* WITH_POLICY */
const NumberSet *egressId,
const Message *objectMessage, Ticks rtt) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+
+#ifdef WITH_POLICY
+ ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
+
+ /* Update statistic counters : */
+
+ size_t msg_size = message_Length(objectMessage);
+
+ for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
+ unsigned conn_id = numberSet_GetItem(egressId, i);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!conn)
+ continue;
+ if (connection_HasTag(conn, POLICY_TAG_WIRED)) {
+ fibEntry->policy_counters.wired.num_packets++;
+ fibEntry->policy_counters.wired.num_bytes += msg_size;
+ fibEntry->policy.stats.wired.latency = \
+ ALPHA * fibEntry->policy.stats.wired.latency + \
+ (1 - ALPHA) * (double)rtt;
+ fibEntry->policy_counters.wired.latency_idle = 0;
+ }
+ if (connection_HasTag(conn, POLICY_TAG_WIFI)) {
+ fibEntry->policy_counters.wifi.num_packets++;
+ fibEntry->policy_counters.wifi.num_bytes += msg_size;
+ fibEntry->policy.stats.wifi.latency = \
+ ALPHA * fibEntry->policy.stats.wifi.latency + \
+ (1 - ALPHA) * (double)rtt;
+ fibEntry->policy_counters.wifi.latency_idle = 0;
+
+ }
+ if (connection_HasTag(conn, POLICY_TAG_CELLULAR)) {
+ fibEntry->policy_counters.cellular.num_packets++;
+ fibEntry->policy_counters.cellular.num_bytes += msg_size;
+ fibEntry->policy.stats.cellular.latency = \
+ ALPHA * fibEntry->policy.stats.cellular.latency + \
+ (1 - ALPHA) * (double)rtt;
+ fibEntry->policy_counters.cellular.latency_idle = 0;
+ }
+ }
+
+ fibEntry->policy.stats.all.latency = \
+ ALPHA * fibEntry->policy.stats.all.latency + \
+ (1 - ALPHA) * (double)rtt;
+ fibEntry->policy_counters.all.latency_idle = 0;
+
+ fibEntry->policy_counters.all.num_packets++;
+ fibEntry->policy_counters.all.num_bytes += msg_size;
+
+#endif /* WITH_POLICY */
+
fibEntry->fwdStrategy->receiveObject(fibEntry->fwdStrategy, egressId,
objectMessage, rtt);
}
+#ifdef WITH_POLICY
+void fibEntry_OnTimeout(FibEntry *fibEntry, const NumberSet *egressId) {
+#else
void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId) {
+#endif /* WITH_POLICY */
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
+
+#ifdef WITH_POLICY
+
+ ConnectionTable * table = forwarder_GetConnectionTable(fibEntry->forwarder);
+
+ for (unsigned i = 0; i < numberSet_Length(egressId); i++) {
+ unsigned conn_id = numberSet_GetItem(egressId, i);
+ const Connection * conn = connectionTable_FindById(table, conn_id);
+ if (!conn)
+ continue;
+ if (connection_HasTag(conn, POLICY_TAG_WIRED)) {
+ fibEntry->policy_counters.wired.num_losses++;
+ }
+ if (connection_HasTag(conn, POLICY_TAG_WIFI)) {
+ fibEntry->policy_counters.wifi.num_losses++;
+ }
+ if (connection_HasTag(conn, POLICY_TAG_CELLULAR)) {
+ fibEntry->policy_counters.cellular.num_losses++;
+ }
+ }
+
+ fibEntry->policy_counters.all.num_losses++;
+
+#endif /* WITH_POLICY */
+
fibEntry->fwdStrategy->onTimeout(fibEntry->fwdStrategy, egressId);
}
+#ifdef WITH_POLICY
+void fibEntry_UpdateStats(FibEntry *fibEntry, uint64_t now) {
+ double throughput;
+ double loss_rate;
+
+ if (now == fibEntry->policy_counters.last_update)
+ return ;
+
+ /* WIRED */
+
+ /* a) throughput */
+ if (fibEntry->policy_counters.wired.num_bytes > 0) {
+ throughput = fibEntry->policy_counters.wired.num_bytes / \
+ (now - fibEntry->policy_counters.last_update) ;
+ throughput = throughput * 8 / 1024;
+ if (throughput < 0)
+ throughput = 0;
+ } else {
+ throughput = 0;
+ }
+ fibEntry->policy.stats.wired.throughput = \
+ ALPHA * fibEntry->policy.stats.wired.throughput + \
+ (1-ALPHA) * throughput;
+
+ /* b) loss rate */
+ if ((fibEntry->policy_counters.wired.num_losses > 0) && \
+ (fibEntry->policy_counters.wired.num_packets > 0)){
+ loss_rate = fibEntry->policy_counters.wired.num_losses / \
+ fibEntry->policy_counters.wired.num_packets;
+ loss_rate *= 100;
+ } else {
+ loss_rate = 0;
+ }
+ fibEntry->policy.stats.wired.loss_rate = \
+ ALPHA * fibEntry->policy.stats.wired.loss_rate + \
+ (1-ALPHA) * loss_rate;
+
+ /* Latency */
+ fibEntry->policy_counters.wired.latency_idle++;
+ if (fibEntry->policy_counters.wired.latency_idle > 1)
+ fibEntry->policy.stats.wired.latency = 0;
+ fibEntry->policy_counters.wifi.latency_idle++;
+ if (fibEntry->policy_counters.wifi.latency_idle > 1)
+ fibEntry->policy.stats.wifi.latency = 0;
+ fibEntry->policy_counters.cellular.latency_idle++;
+ if (fibEntry->policy_counters.cellular.latency_idle > 1)
+ fibEntry->policy.stats.cellular.latency = 0;
+ fibEntry->policy_counters.all.latency_idle++;
+ if (fibEntry->policy_counters.all.latency_idle > 1)
+ fibEntry->policy.stats.all.latency = 0;
+
+ fibEntry->policy_counters.wired.num_bytes = 0;
+ fibEntry->policy_counters.wired.num_losses = 0;
+ fibEntry->policy_counters.wired.num_packets = 0;
+
+ /* WIFI */
+
+ /* a) throughput */
+ if (fibEntry->policy_counters.wifi.num_bytes > 0) {
+ throughput = fibEntry->policy_counters.wifi.num_bytes / \
+ (now - fibEntry->policy_counters.last_update);
+ throughput = throughput * 8 / 1024;
+ if (throughput < 0)
+ throughput = 0;
+ } else {
+ throughput = 0;
+ }
+ fibEntry->policy.stats.wifi.throughput = \
+ ALPHA * fibEntry->policy.stats.wifi.throughput + \
+ (1-ALPHA) * throughput;
+
+ /* b) loss rate */
+ if ((fibEntry->policy_counters.wifi.num_losses > 0) && \
+ (fibEntry->policy_counters.wifi.num_packets > 0)) {
+ loss_rate = fibEntry->policy_counters.wifi.num_losses / \
+ fibEntry->policy_counters.wifi.num_packets;
+ loss_rate *= 100;
+ } else {
+ loss_rate = 0;
+ }
+ fibEntry->policy.stats.wifi.loss_rate = \
+ ALPHA * fibEntry->policy.stats.wifi.loss_rate + \
+ (1-ALPHA) * loss_rate;
+
+ fibEntry->policy_counters.wifi.num_bytes = 0;
+ fibEntry->policy_counters.wifi.num_losses = 0;
+ fibEntry->policy_counters.wifi.num_packets = 0;
+
+ /* CELLULAR */
+
+ /* a) throughput */
+ if (fibEntry->policy_counters.cellular.num_bytes > 0) {
+ throughput = fibEntry->policy_counters.cellular.num_bytes / \
+ (now - fibEntry->policy_counters.last_update) ;
+ throughput = throughput * 8 / 1024;
+ if (throughput < 0)
+ throughput = 0;
+ } else {
+ throughput = 0;
+ }
+ fibEntry->policy.stats.cellular.throughput = \
+ ALPHA * fibEntry->policy.stats.cellular.throughput + \
+ (1-ALPHA) * throughput;
+
+ /* b) loss rate */
+ if ((fibEntry->policy_counters.cellular.num_losses > 0) && \
+ (fibEntry->policy_counters.cellular.num_packets > 0)) {
+ loss_rate = fibEntry->policy_counters.cellular.num_losses / \
+ fibEntry->policy_counters.cellular.num_packets;
+ loss_rate *= 100;
+ } else {
+ loss_rate = 0;
+ }
+ fibEntry->policy.stats.cellular.loss_rate = \
+ ALPHA * fibEntry->policy.stats.cellular.loss_rate + \
+ (1-ALPHA) * loss_rate;
+
+ fibEntry->policy_counters.cellular.num_bytes = 0;
+ fibEntry->policy_counters.cellular.num_losses = 0;
+ fibEntry->policy_counters.cellular.num_packets = 0;
+
+ /* ALL */
+
+ /* a) throughput */
+ if (fibEntry->policy_counters.all.num_bytes > 0) {
+ throughput = fibEntry->policy_counters.all.num_bytes / \
+ (now - fibEntry->policy_counters.last_update);
+ throughput = throughput * 8 / 1024;
+ if (throughput < 0)
+ throughput = 0;
+ } else {
+ throughput = 0;
+ }
+ fibEntry->policy.stats.all.throughput = \
+ ALPHA * fibEntry->policy.stats.all.throughput + \
+ (1-ALPHA) * throughput;
+
+ /* b) loss rate */
+ if ((fibEntry->policy_counters.all.num_losses > 0) && \
+ (fibEntry->policy_counters.all.num_packets > 0)) {
+ loss_rate = fibEntry->policy_counters.all.num_losses / \
+ fibEntry->policy_counters.all.num_packets;
+ loss_rate *= 100;
+ } else {
+ loss_rate = 0;
+ }
+ fibEntry->policy.stats.all.loss_rate = \
+ ALPHA * fibEntry->policy.stats.all.loss_rate + \
+ (1-ALPHA) * loss_rate;
+
+ fibEntry->policy_counters.all.num_bytes = 0;
+ fibEntry->policy_counters.all.num_losses = 0;
+ fibEntry->policy_counters.all.num_packets = 0;
+
+ fibEntry->policy_counters.last_update = now;
+}
+#endif /* WITH_POLICY */
+
Name *fibEntry_GetPrefix(const FibEntry *fibEntry) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
return fibEntry->name;
@@ -202,12 +881,6 @@ StrategyImpl *fibEntry_GetFwdStrategy(const FibEntry *fibEntry) {
#ifdef WITH_MAPME
-void fibEntry_AddNexthopByConnectionId(FibEntry *fibEntry,
- unsigned connectionId) {
- parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
- fibEntry->fwdStrategy->addNexthop(fibEntry->fwdStrategy, connectionId);
-}
-
void *fibEntry_getUserData(const FibEntry *fibEntry) {
parcAssertNotNull(fibEntry, "Parameter fibEntry must be non-null");
return fibEntry->userData;
diff --git a/hicn-light/src/hicn/processor/fibEntry.h b/hicn-light/src/hicn/processor/fibEntry.h
index d677ae998..11a00e836 100644
--- a/hicn-light/src/hicn/processor/fibEntry.h
+++ b/hicn-light/src/hicn/processor/fibEntry.h
@@ -40,6 +40,10 @@
#include <hicn/core/name.h>
#include <hicn/strategies/strategyImpl.h>
+#ifdef WITH_POLICY
+#include <hicn/core/connectionTable.h>
+#endif /* WITH_POLICY */
+
#ifdef WITH_MAPME
#include <parc/algol/parc_EventTimer.h>
#include <parc/algol/parc_Iterator.h>
@@ -48,7 +52,12 @@
struct fib_entry;
typedef struct fib_entry FibEntry;
+#ifdef WITH_POLICY
+struct forwarder;
+FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy, const struct forwarder * table);
+#else
FibEntry *fibEntry_Create(Name *name, strategy_type fwdStrategy);
+#endif
/**
* Decrements the reference count by one, and destroys the memory after last
@@ -72,6 +81,16 @@ FibEntry *fibEntry_Acquire(const FibEntry *fibEntry);
void fibEntry_SetStrategy(FibEntry *fibEntry, strategy_type strategy);
+#ifdef WITH_POLICY
+
+policy_t fibEntry_GetPolicy(const FibEntry *fibEntry);
+
+void fibEntry_ReconsiderPolicy(FibEntry *fibEntry);
+
+void fibEntry_SetPolicy(FibEntry *fibEntry, policy_t policy);
+
+#endif /* WITH_POLICY */
+
void fibEntry_AddNexthop(FibEntry *fibEntry, unsigned connectionId);
void fibEntry_RemoveNexthopByConnectionId(FibEntry *fibEntry,
@@ -89,13 +108,29 @@ size_t fibEntry_NexthopCount(const FibEntry *fibEntry);
const NumberSet *fibEntry_GetNexthops(const FibEntry *fibEntry);
const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy(
+#ifdef WITH_POLICY
+ FibEntry *fibEntry, const Message *interestMessage, bool is_retransmission);
+#else
const FibEntry *fibEntry, const Message *interestMessage);
+#endif /* WITH_POLICY */
+#ifdef WITH_POLICY
+void fibEntry_ReceiveObjectMessage(FibEntry *fibEntry,
+#else
void fibEntry_ReceiveObjectMessage(const FibEntry *fibEntry,
+#endif /* WITH_POLICY */
const NumberSet *egressId,
const Message *objectMessage, Ticks rtt);
+#ifdef WITH_POLICY
+void fibEntry_OnTimeout(FibEntry *fibEntry, const NumberSet *egressId);
+#else
void fibEntry_OnTimeout(const FibEntry *fibEntry, const NumberSet *egressId);
+#endif /* WITH_POLICY */
+
+#ifdef WITH_POLICY
+void fibEntry_UpdateStats(FibEntry *fibEntry, uint64_t now);
+#endif /* WITH_POLICY */
strategy_type fibEntry_GetFwdStrategyType(const FibEntry *fibEntry);
@@ -111,15 +146,6 @@ Name *fibEntry_GetPrefix(const FibEntry *fibEntry);
#ifdef WITH_MAPME
/**
- * @function fibEntry_AddNexthopByConnectionId
- * @abstract Adds a next hop directly from the connection id.
- * @param [in] fibEntry - Pointer to the FIB entry.
- * @return The sequence number stored in the FIB entry.
- */
-void fibEntry_AddNexthopByConnectionId(FibEntry *fibEntry,
- unsigned connectionId);
-
-/**
* @function fibEntry_getUserData
* @abstract Returns user data associated to the FIB entry.
* @param [in] fibEntry - Pointer to the FIB entry.
diff --git a/hicn-light/src/hicn/processor/messageProcessor.c b/hicn-light/src/hicn/processor/messageProcessor.c
index 4db1a0eb2..7e0ece257 100644
--- a/hicn-light/src/hicn/processor/messageProcessor.c
+++ b/hicn-light/src/hicn/processor/messageProcessor.c
@@ -19,6 +19,12 @@
#include <parc/algol/parc_ArrayList.h>
#include <parc/algol/parc_Memory.h>
+#ifdef WITH_POLICY
+#include <parc/algol/parc_EventTimer.h>
+#ifdef WITH_MAPME
+#include <hicn/core/connection.h>
+#endif /* WITH_MAPME */
+#endif /* WITH_POLICY */
#include <hicn/processor/messageProcessor.h>
#include <hicn/processor/fib.h>
@@ -28,7 +34,9 @@
#include <hicn/content_store/contentStoreLRU.h>
#include <hicn/strategies/loadBalancer.h>
+#ifndef WITH_POLICY
#include <hicn/strategies/loadBalancerWithPD.h>
+#endif /* ! WITH_POLICY */
#include <hicn/strategies/rnd.h>
#include <hicn/strategies/rndSegment.h>
#include <hicn/strategies/strategyImpl.h>
@@ -43,6 +51,10 @@
#include <hicn/utils/address.h>
+#ifdef WITH_POLICY
+#define STATS_INTERVAL 1000 /* ms */
+#endif /* WITH_POLICY */
+
/*
* Copyright (c) 2017-2019 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -94,6 +106,10 @@ struct message_processor {
bool serve_from_cache;
_ProcessorStats stats;
+
+#ifdef WITH_POLICY
+ void * timer;
+#endif /* WITH_POLICY */
};
static void messageProcessor_Drop(MessageProcessor *processor,
@@ -113,6 +129,23 @@ static void messageProcessor_ForwardToInterfaceId(MessageProcessor *processor,
// ============================================================
// Public API
+#ifdef WITH_POLICY
+static void
+messageProcessor_Tick(int fd, PARCEventType type, void *user_data)
+{
+ MessageProcessor *processor = (MessageProcessor*)user_data;
+ uint64_t now = (uint64_t)forwarder_GetTicks(processor->forwarder);
+
+ /* Loop over FIB entries to compute statistics from counters */
+ FibEntryList *fibList = forwarder_GetFibEntries(processor->forwarder);
+
+ for (size_t i = 0; i < fibEntryList_Length(fibList); i++) {
+ FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i);
+ fibEntry_UpdateStats(entry, now);
+ }
+}
+#endif /* WITH_POLICY */
+
MessageProcessor *messageProcessor_Create(Forwarder *forwarder) {
size_t objectStoreSize =
configuration_GetObjectStoreSize(forwarder_GetConfiguration(forwarder));
@@ -148,6 +181,20 @@ MessageProcessor *messageProcessor_Create(Forwarder *forwarder) {
processor->store_in_cache = true;
processor->serve_from_cache = true;
+#ifdef WITH_POLICY
+ /* Create statistics timer */
+ Dispatcher *dispatcher = forwarder_GetDispatcher(forwarder);
+ if (!dispatcher)
+ goto ERR;
+ processor->timer = dispatcher_CreateTimer(dispatcher, /* repeat */ true,
+ messageProcessor_Tick, processor);
+ if (!processor->timer)
+ goto ERR;
+ struct timeval timeout = {STATS_INTERVAL / 1000, (STATS_INTERVAL % 1000) * 1000};
+ dispatcher_StartTimer(dispatcher, processor->timer, &timeout);
+ERR:
+#endif /* WITH_POLICY */
+
return processor;
}
@@ -201,6 +248,15 @@ void messageProcessor_Destroy(MessageProcessor **processorPtr) {
contentStoreInterface_Release(&processor->contentStore);
pit_Release(&processor->pit);
+#ifdef WITH_POLICY
+ Dispatcher *dispatcher = forwarder_GetDispatcher(processor->forwarder);
+ if (!dispatcher)
+ goto ERR;
+ dispatcher_StopTimer(dispatcher, processor->timer);
+ dispatcher_DestroyTimerEvent(dispatcher, (PARCEventTimer**)&processor->timer);
+ERR:
+#endif /* WITH_POLICY */
+
parcMemory_Deallocate((void **)&processor);
*processorPtr = NULL;
}
@@ -255,22 +311,33 @@ bool messageProcessor_AddOrUpdateRoute(MessageProcessor *processor,
Name *prefix = name_CreateFromAddress(control->addressType, control->address,
control->len);
FibEntry *entry = fib_Contains(processor->fib, prefix);
+#ifndef WITH_POLICY
bool newEntry = false;
+#endif /* ! WITH_POLICY */
if (entry != NULL) {
fibEntry_AddNexthop(entry, ifidx);
} else {
+#ifdef WITH_POLICY
+ entry = fibEntry_Create(prefix, fwdStrategy, processor->forwarder);
+#else
newEntry = true;
entry = fibEntry_Create(prefix, fwdStrategy);
+#endif /* WITH_POLICY */
fibEntry_AddNexthop(entry, ifidx);
fib_Add(processor->fib, entry);
}
name_Release(&prefix);
+
+#ifndef WITH_POLICY
+ /* For policy implementation, we need access to the ConnectionTable in all
+ * Forwarding Strategies, so it is setup during FIB Entry creation */
if (newEntry && (fwdStrategy == SET_STRATEGY_LOADBALANCER_WITH_DELAY)) {
strategyLoadBalancerWithPD_SetConnectionTable(
fibEntry_GetFwdStrategy(entry),
forwarder_GetConnectionTable(processor->forwarder));
}
+#endif /* ! WITH_POLICY */
return true;
}
@@ -286,6 +353,65 @@ bool messageProcessor_RemoveRoute(MessageProcessor *processor,
return true;
}
+#ifdef WITH_POLICY
+
+bool messageProcessor_AddOrUpdatePolicy(MessageProcessor *processor,
+ add_policy_command *control) {
+ Configuration *config = forwarder_GetConfiguration(processor->forwarder);
+
+ const char *prefixStr = utils_PrefixLenToString(
+ control->addressType, &control->address, &control->len);
+
+ Name *prefix = name_CreateFromAddress(control->addressType, control->address,
+ control->len);
+ FibEntry *entry = fib_Contains(processor->fib, prefix);
+ if (!entry) {
+ strategy_type fwdStrategy =
+ configuration_GetForwardingStrategy(config, prefixStr);
+ if (fwdStrategy == LAST_STRATEGY_VALUE) {
+ fwdStrategy = SET_STRATEGY_LOADBALANCER;
+ }
+ entry = fibEntry_Create(prefix, fwdStrategy, processor->forwarder);
+ fib_Add(processor->fib, entry);
+ }
+ fibEntry_SetPolicy(entry, control->policy);
+
+ name_Release(&prefix);
+
+ return true;
+}
+
+bool messageProcessor_RemovePolicy(MessageProcessor *processor,
+ remove_policy_command *control) {
+ Name *prefix = name_CreateFromAddress(control->addressType, control->address,
+ control->len);
+ FibEntry *entry = fib_Contains(processor->fib, prefix);
+ name_Release(&prefix);
+
+ if (!entry)
+ return false;
+
+ fibEntry_SetPolicy(entry, POLICY_NONE);
+
+ return true;
+}
+
+
+#ifdef WITH_MAPME
+void messageProcessor_onConnectionEvent(const MessageProcessor *processor,
+ const Connection *conn_added, connection_event_t event)
+{
+ FibEntryList *fiblist = forwarder_GetFibEntries(processor->forwarder);
+ for (size_t i = 0; i < fibEntryList_Length(fiblist); i++) {
+ FibEntry *fibEntry = (FibEntry *)fibEntryList_Get(fiblist, i);
+ fibEntry_ReconsiderPolicy(fibEntry);
+ }
+
+}
+#endif /* WITH_MAPME */
+
+#endif /* WITH_POLICY */
+
void messageProcessor_RemoveConnectionIdFromRoutes(MessageProcessor *processor,
unsigned connectionId) {
fib_RemoveConnectionId(processor->fib, connectionId);
@@ -295,12 +421,14 @@ void processor_SetStrategy(MessageProcessor *processor, Name *prefix,
strategy_type strategy) {
FibEntry *entry = fib_Contains(processor->fib, prefix);
if (entry != NULL) {
+#ifndef WITH_POLICY
fibEntry_SetStrategy(entry, strategy);
if (strategy == SET_STRATEGY_LOADBALANCER_WITH_DELAY) {
strategyLoadBalancerWithPD_SetConnectionTable(
fibEntry_GetFwdStrategy(entry),
forwarder_GetConnectionTable(processor->forwarder));
}
+#endif /* ! WITH_POLICY */
}
}
@@ -352,8 +480,13 @@ static void messageProcessor_Drop(MessageProcessor *processor,
* @return true if interest aggregagted (no more forwarding needed), false if
* need to keep processing it.
*/
+#ifdef WITH_POLICY
+static PITVerdict messageProcessor_AggregateInterestInPit(MessageProcessor *processor,
+ Message *interestMessage) {
+#else
static bool messageProcessor_AggregateInterestInPit(MessageProcessor *processor,
Message *interestMessage) {
+#endif /* WITH_POLICY */
PITVerdict verdict = pit_ReceiveInterest(processor->pit, interestMessage);
if (verdict == PITVerdict_Aggregate) {
@@ -444,8 +577,13 @@ static bool _satisfyFromContentStore(MessageProcessor *processor,
*
* @return true if we found a route and tried to forward it, false if no route
*/
+#ifdef WITH_POLICY
+static bool messageProcessor_ForwardViaFib(MessageProcessor *processor,
+ Message *interestMessage, PITVerdict verdict) {
+#else
static bool messageProcessor_ForwardViaFib(MessageProcessor *processor,
Message *interestMessage) {
+#endif /* WITH_POLICY */
FibEntry *fibEntry = fib_Match(processor->fib, interestMessage);
if (fibEntry == NULL) {
return false;
@@ -459,7 +597,12 @@ static bool messageProcessor_ForwardViaFib(MessageProcessor *processor,
pitEntry_AddFibEntry(pitEntry, fibEntry);
NumberSet *nexthops = (NumberSet *)fibEntry_GetNexthopsFromForwardingStrategy(
+#ifdef WITH_POLICY
+ fibEntry, interestMessage, verdict);
+#else
fibEntry, interestMessage);
+#endif /* WITH_POLICY */
+
// this requires some additional checks. It may happen that some of the output
// faces selected by the forwarding strategy are not usable. So far all the
// forwarding strategy return only valid faces (or an empty list)
@@ -503,10 +646,23 @@ static void messageProcessor_ReceiveInterest(MessageProcessor *processor,
processor->stats.countInterestsReceived++;
// (1) Try to aggregate in PIT
+#ifdef WITH_POLICY
+ PITVerdict verdict = messageProcessor_AggregateInterestInPit(processor, interestMessage);
+ switch(verdict) {
+ case PITVerdict_Aggregate:
+ //done
+ return;
+
+ case PITVerdict_Forward:
+ case PITVerdict_Retransmit:
+ break;
+ }
+#else
if (messageProcessor_AggregateInterestInPit(processor, interestMessage)) {
// done
return;
}
+#endif /* WITH_POLICY */
// At this point, we just created a PIT entry. If we don't forward the
// interest, we need to remove the PIT entry.
@@ -520,7 +676,11 @@ static void messageProcessor_ReceiveInterest(MessageProcessor *processor,
}
// (3) Try to forward it
+#ifdef WITH_POLICY
+ if (messageProcessor_ForwardViaFib(processor, interestMessage, verdict)) {
+#else
if (messageProcessor_ForwardViaFib(processor, interestMessage)) {
+#endif /* WITH_POLICY */
// done
return;
}
@@ -595,6 +755,7 @@ static void messageProcessor_ReceiveContentObject(MessageProcessor *processor,
}
// (3) Reverse path forward via PIT entries
messageProcessor_ForwardToNexthops(processor, message, ingressSetUnion);
+
}
numberSet_Release(&ingressSetUnion);
diff --git a/hicn-light/src/hicn/processor/messageProcessor.h b/hicn-light/src/hicn/processor/messageProcessor.h
index 64b08272d..6804ba018 100644
--- a/hicn-light/src/hicn/processor/messageProcessor.h
+++ b/hicn-light/src/hicn/processor/messageProcessor.h
@@ -32,6 +32,12 @@
#include <hicn/utils/commands.h>
+#ifdef WITH_POLICY
+#ifdef WITH_MAPME
+#include <hicn/core/connection.h>
+#endif /* WITH_MAPME */
+#endif /* WITH_POLICY */
+
struct message_processor;
typedef struct message_processor MessageProcessor;
@@ -100,6 +106,43 @@ bool messageProcessor_RemoveRoute(MessageProcessor *processor,
remove_route_command *control,
unsigned ifidx);
+#ifdef WITH_POLICY
+
+/**
+ * Adds or updates a policy in the FIB
+ *
+ * If the policy is already set, it is replaced
+ *
+ * @param [in] procesor An allocated message processor
+ * @param [in] control Control message
+ *
+ * @retval true added or updated
+ * @retval false An error
+ */
+bool messageProcessor_AddOrUpdatePolicy(MessageProcessor *processor,
+ add_policy_command *control);
+
+/**
+ * Removes a policy from the FIB
+ *
+ * Reset the policy in the FIB to the default (empty) policy.
+ *
+ * @param [in] procesor An allocated message processor
+ * @param [in] control Control message
+ *
+ * @retval true Policy completely removed
+ * @retval false There is still a nexthop for the policy
+ */
+bool messageProcessor_RemovePolicy(MessageProcessor *processor,
+ remove_policy_command *control);
+
+#ifdef WITH_MAPME
+void messageProcessor_onConnectionEvent(const MessageProcessor *processor,
+ const Connection *conn_added, connection_event_t event);
+#endif /* WITH_MAPME */
+
+#endif /* WITH_POLICY */
+
/**
* Removes a given connection id from all FIB entries
*
diff --git a/hicn-light/src/hicn/processor/pitStandard.c b/hicn-light/src/hicn/processor/pitStandard.c
index 9a3a829bd..edf0b5e98 100644
--- a/hicn-light/src/hicn/processor/pitStandard.c
+++ b/hicn-light/src/hicn/processor/pitStandard.c
@@ -160,7 +160,11 @@ static PITVerdict _pitStandard_ReceiveInterest(PIT *generic,
(void *)interestMessage, pitEntry_GetExpiryTime(pitEntry));
}
+#ifdef WITH_POLICY
+ return PITVerdict_Retransmit;
+#else
return PITVerdict_Forward;
+#endif /* WITH_POLICY */
}
// It is in the PIT but this is the first interest for the reverse path
diff --git a/hicn-light/src/hicn/processor/pitVerdict.h b/hicn-light/src/hicn/processor/pitVerdict.h
index 16631fa51..f37242027 100644
--- a/hicn-light/src/hicn/processor/pitVerdict.h
+++ b/hicn-light/src/hicn/processor/pitVerdict.h
@@ -32,5 +32,9 @@
* @constant PITVerdict_Aggregate The Interest was aggregated in the PIT, does
* not need to be forwarded
*/
+#ifdef WITH_POLICY
+typedef enum { PITVerdict_Forward, PITVerdict_Aggregate, PITVerdict_Retransmit } PITVerdict;
+#else
typedef enum { PITVerdict_Forward, PITVerdict_Aggregate } PITVerdict;
+#endif /* WITH_POLICY */
#endif // pitVerdict_h