LONGBOW_TEST_CASE(Global, athenaFIB_CreateEntryList) { TestData *data = longBowTestCase_GetClipBoardData(testCase); athenaFIB_AddRoute(data->testFIB, data->testName1, data->testVector12); PARCBitVector *result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertTrue(parcBitVector_Equals(result, data->testVector12), "Expected lookup to equal test vector"); parcBitVector_Release(&result); PARCList *entryList = athenaFIB_CreateEntryList(data->testFIB); assertTrue(parcList_Size(entryList) == 2, "Expected the EntryList to have 2 elements"); AthenaFIBListEntry *entry = parcList_GetAtIndex(entryList, 0); assertNotNull(entry, "Expect entry at 0 to be non-NULL"); assertTrue(ccnxName_Equals(data->testName1, entry->name), "Expect the name at 0 to be testName1"); assertTrue(entry->linkId == 0, "Expect the routeId at 0 to be 0"); entry = parcList_GetAtIndex(entryList, 1); assertNotNull(entry, "Expect entry at 1 to be non-NULL"); assertTrue(ccnxName_Equals(data->testName1, entry->name), "Expect the name at 1 to be testName1"); assertTrue(entry->linkId == 42, "Expect the routeId at 0 to be 42"); parcList_Release(&entryList); }
LONGBOW_TEST_CASE(Global, athenaFIB_DeleteRoute) { TestData *data = longBowTestCase_GetClipBoardData(testCase); athenaFIB_AddRoute(data->testFIB, data->testName1, data->testVector12); PARCBitVector *result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertTrue(parcBitVector_Equals(result, data->testVector12), "Expected lookup to equal test vector"); parcBitVector_Release(&result); athenaFIB_DeleteRoute(data->testFIB, data->testName1, data->testVector1); result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertTrue(parcBitVector_Equals(result, data->testVector2), "Expected lookup to equal test vector"); parcBitVector_Release(&result); athenaFIB_DeleteRoute(data->testFIB, data->testName1, data->testVector12); result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertNull(result, "Expecting a NULL result from Lookup after Delete Route"); }
LONGBOW_TEST_CASE(Global, athenaFIB_Lookup_EmptyPath) { TestData *data = longBowTestCase_GetClipBoardData(testCase); athenaFIB_AddRoute(data->testFIB, data->testName3, data->testVector1); PARCBitVector *result = athenaFIB_Lookup(data->testFIB, data->testName3, NULL); assertNotNull(result, "Expect non-null match to global path (\"/\")"); assertTrue(parcBitVector_Equals(result, data->testVector1), "Expected lookup to equal test vector"); parcBitVector_Release(&result); result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertNotNull(result, "Expect non-null match to global path (\"/\")"); assertTrue(parcBitVector_Equals(result, data->testVector1), "Expected lookup to equal test vector"); parcBitVector_Release(&result); result = athenaFIB_Lookup(data->testFIB, data->testName2, NULL); assertNotNull(result, "Expect non-null match to global path (\"/\")"); assertTrue(parcBitVector_Equals(result, data->testVector1), "Expected lookup to equal test vector"); parcBitVector_Release(&result); athenaFIB_AddRoute(data->testFIB, data->testName3, data->testVector2); result = athenaFIB_Lookup(data->testFIB, data->testName3, NULL); assertNotNull(result, "Expect non-null match to global path (\"/\")"); assertTrue(parcBitVector_Equals(result, data->testVector12), "Expected lookup to equal test vector"); parcBitVector_Release(&result); result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertNotNull(result, "Expect non-null match to global path (\"/\")"); assertTrue(parcBitVector_Equals(result, data->testVector12), "Expected lookup to equal test vector"); parcBitVector_Release(&result); result = athenaFIB_Lookup(data->testFIB, data->testName2, NULL); assertNotNull(result, "Expect non-null match to global path (\"/\")"); assertTrue(parcBitVector_Equals(result, data->testVector12), "Expected lookup to equal test vector"); parcBitVector_Release(&result); }
LONGBOW_TEST_CASE(Global, athenaFIB_Lookup) { TestData *data = longBowTestCase_GetClipBoardData(testCase); athenaFIB_AddRoute(data->testFIB, data->testName1, data->testVector1); PARCBitVector *result = athenaFIB_Lookup(data->testFIB, data->testName1, NULL); assertTrue(parcBitVector_Equals(result, data->testVector1), "Expected lookup to equal test vector"); parcBitVector_Release(&result); // // Name3 (the default route) contains both vector1 and vector2. // Name1 (a/b/c) contains only vector 1. // Name4 (a/b/c/d) is what we're looking for. // Although Name1 is a match for Name4, it only contains the ingress vector1. // We must the search until we match the default route. Ingress vector1 // must be removed from the returned vector list from the default route. // // Make sure we see only vector2 in the result. // athenaFIB_AddRoute(data->testFIB, data->testName3, data->testVector12); result = athenaFIB_Lookup(data->testFIB, data->testName4, data->testVector1); assertTrue(parcBitVector_Equals(result, data->testVector2), "Expected lookup to equal test vector"); parcBitVector_Release(&result); }
static void _processInterest(Athena *athena, CCNxInterest *interest, PARCBitVector *ingressVector) { uint8_t hoplimit; // // * (0) Hoplimit check, exclusively on interest messages // int linkId = parcBitVector_NextBitSet(ingressVector, 0); if (athenaTransportLinkAdapter_IsNotLocal(athena->athenaTransportLinkAdapter, linkId)) { hoplimit = ccnxInterest_GetHopLimit(interest); if (hoplimit == 0) { // We should never receive a message with a hoplimit of 0 from a non-local source. parcLog_Error(athena->log, "Received a message with a hoplimit of zero from a non-local source (%s).", athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, linkId)); return; } ccnxInterest_SetHopLimit(interest, hoplimit - 1); } // // * (1) if the interest is in the ContentStore, reply and return, // assuming that other PIT entries were satisified when the content arrived. // CCNxMetaMessage *content = athenaContentStore_GetMatch(athena->athenaContentStore, interest); if (content) { const char *ingressVectorString = parcBitVector_ToString(ingressVector); parcLog_Debug(athena->log, "Forwarding content from store to %s", ingressVectorString); parcMemory_Deallocate(&ingressVectorString); PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, content, ingressVector); if (result) { // failed channels - client will resend interest unless we wish to optimize things here parcBitVector_Release(&result); } return; } // // * (2) add it to the PIT, if it was aggregated or there was an error we're done, otherwise we // forward the interest. The expectedReturnVector is populated with information we get from // the FIB and used to verify content objects ingress ports when they arrive. // PARCBitVector *expectedReturnVector; AthenaPITResolution result; if ((result = athenaPIT_AddInterest(athena->athenaPIT, interest, ingressVector, &expectedReturnVector)) != AthenaPITResolution_Forward) { if (result == AthenaPITResolution_Error) { parcLog_Error(athena->log, "PIT resolution error"); } return; } // Divert interests destined to the forwarder, we assume these are control messages CCNxName *ccnxName = ccnxInterest_GetName(interest); if (ccnxName_StartsWith(ccnxName, athena->athenaName) == true) { _processInterestControl(athena, interest, ingressVector); return; } // // * (3) if it's in the FIB, forward, then update the PIT expectedReturnVector so we can verify // when the returned object arrives that it came from an interface it was expected from. // Interest messages with a hoplimit of 0 will never be sent out by the link adapter to a // non-local interface so we need not check that here. // ccnxName = ccnxInterest_GetName(interest); PARCBitVector *egressVector = athenaFIB_Lookup(athena->athenaFIB, ccnxName); if (egressVector != NULL) { // Remove the link the interest came from if it was included in the FIB entry parcBitVector_ClearVector(egressVector, ingressVector); // If no links remain, send a no route interest return message if (parcBitVector_NumberOfBitsSet(egressVector) == 0) { CCNxInterestReturn *interestReturn = ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_NoRoute); PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, interestReturn, ingressVector); parcBitVector_Release(&result); ccnxInterestReturn_Release(&interestReturn); } else { parcBitVector_SetVector(expectedReturnVector, egressVector); PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, interest, egressVector); if (result) { // remove failed channels - client will resend interest unless we wish to optimize here parcBitVector_ClearVector(expectedReturnVector, result); parcBitVector_Release(&result); } } } else { // No FIB entry found, return a NoRoute interest return and remove the entry from the PIT. CCNxInterestReturn *interestReturn = ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_NoRoute); PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, interestReturn, ingressVector); parcBitVector_Release(&result); ccnxInterestReturn_Release(&interestReturn); const char *name = ccnxName_ToString(ccnxName); if (athenaPIT_RemoveInterest(athena->athenaPIT, interest, ingressVector) != true) { parcLog_Error(athena->log, "Unable to remove interest (%s) from the PIT.", name); } parcLog_Debug(athena->log, "Name (%s) not found in FIB and no default route. Message dropped.", name); parcMemory_Deallocate(&name); } }