From 0a1c6b5565e20167d1f1f33a5a8b597f420b18b0 Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Fri, 26 Jul 2019 23:20:30 +0200 Subject: [HICN-252] Add per-application policy framework to hicn-light forwarder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0531cd7a7de179581295ae34766c81cd9cf3e172 Signed-off-by: Jordan Augé Signed-off-by: Mauro Sardara Co-authored-by: Mauro Sardara --- hicn-light/src/hicn/processor/fib.c | 117 +++- hicn-light/src/hicn/processor/fib.h | 4 + hicn-light/src/hicn/processor/fibEntry.c | 689 ++++++++++++++++++++++- hicn-light/src/hicn/processor/fibEntry.h | 44 +- hicn-light/src/hicn/processor/messageProcessor.c | 161 ++++++ hicn-light/src/hicn/processor/messageProcessor.h | 43 ++ hicn-light/src/hicn/processor/pitStandard.c | 4 + hicn-light/src/hicn/processor/pitVerdict.h | 4 + 8 files changed, 1041 insertions(+), 25 deletions(-) (limited to 'hicn-light/src/hicn/processor') 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 #include +#include + +#ifdef WITH_POLICY +#include +#include + +#ifdef WITH_MAPME +#include +#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 #include +#ifdef WITH_POLICY +#include +#endif /* WITH_POLICY */ + #ifdef WITH_MAPME #include #include @@ -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); @@ -110,15 +145,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. 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 #include +#ifdef WITH_POLICY +#include +#ifdef WITH_MAPME +#include +#endif /* WITH_MAPME */ +#endif /* WITH_POLICY */ #include #include @@ -28,7 +34,9 @@ #include #include +#ifndef WITH_POLICY #include +#endif /* ! WITH_POLICY */ #include #include #include @@ -43,6 +51,10 @@ #include +#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 +#ifdef WITH_POLICY +#ifdef WITH_MAPME +#include +#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 -- cgit 1.2.3-korg