Example #1
0
static PARCBuffer *
_encodeControlPlaneInformation(const CCNxControl *cpiControlMessage)
{
    PARCJSON *json = ccnxControl_GetJson(cpiControlMessage);
    char *str = parcJSON_ToCompactString(json);

    // include +1 because we need the NULL byte
    size_t len = strlen(str) + 1;

    size_t packetLength = sizeof(_MetisTlvFixedHeaderV0) + sizeof(MetisTlvType) + len;
    PARCBuffer *packet = parcBuffer_Allocate(packetLength);

    _MetisTlvFixedHeaderV0 hdr;
    memset(&hdr, 0, sizeof(hdr));
    hdr.version = 0;
    hdr.packetType = METIS_PACKET_TYPE_CONTROL;
    hdr.payloadLength = htons(len + sizeof(MetisTlvType));

    parcBuffer_PutArray(packet, sizeof(hdr), (uint8_t *) &hdr);

    MetisTlvType tlv = { .type = htons(T_CPI), .length = htons(len) };
    parcBuffer_PutArray(packet, sizeof(tlv), (uint8_t *) &tlv);

    parcBuffer_PutArray(packet, len, (uint8_t *) str);

    parcMemory_Deallocate((void **) &str);
    return parcBuffer_Flip(packet);
}
Example #2
0
void
metisConfiguration_Receive(MetisConfiguration *config, MetisMessage *message)
{
    assertNotNull(config, "Parameter config must be non-null");
    assertNotNull(message, "Parameter message must be non-null");
    assertTrue(metisMessage_GetType(message) == MetisMessagePacketType_Control,
               "Message must be type CPI, expected %02x got %02x",
               MetisMessagePacketType_Control, metisMessage_GetType(message));

    CCNxControl *control = metisMessage_CreateControlMessage(message);
    unsigned ingressId = metisMessage_GetIngressConnectionId(message);

    if (metisLogger_IsLoggable(config->logger, MetisLoggerFacility_Config, PARCLogLevel_Debug)) {
        char *str = parcJSON_ToCompactString(ccnxControl_GetJson(control));
        metisLogger_Log(config->logger, MetisLoggerFacility_Config, PARCLogLevel_Debug, __func__,
                        "%s received %s\n", __func__, str);
        parcMemory_Deallocate((void **) &str);
    }

    CCNxControl *response = _processControl(config, control, ingressId);
    metisConfiguration_SendResponse(config, response, ingressId);
    ccnxControl_Release(&response);

    ccnxControl_Release(&control);
    metisMessage_Release(&message);
}
CCNxControl *
cpi_CreateResponse(CCNxControl *request, PARCJSON *operation)
{
    PARCJSON *requestJson = ccnxControl_GetJson(request);

    // use the same key as the request
    uint64_t seqnum = controlPlaneInterface_GetSequenceNumber(requestJson);

    PARCJSONValue *value = parcJSON_GetValueByName(requestJson, cpiRequest);
    assertNotNull(value, "Could not get request or response");
    assertTrue(parcJSONValue_IsJSON(value), "cpiRequest should be a JSON object");

    PARCJSON *operationJson = parcJSONValue_GetJSON(value);
    PARCJSONPair *pair = parcJSON_GetPairByIndex(operationJson, 1);
    const PARCBuffer *opKeyBuf = parcJSONPair_GetName(pair);
    const char *opKey = parcBuffer_ToString(opKeyBuf);

    PARCJSON *response = parcJSON_Create();
    parcJSON_AddInteger(response, cpiSeqnum, (int) seqnum);
    parcJSON_AddObject(response, opKey, operation);
    parcMemory_Deallocate(&opKey);

    PARCJSON *responseJson = parcJSON_Create();
    parcJSON_AddObject(responseJson, cpiResponse, response);
    parcJSON_Release(&response);

    CCNxControl *result = ccnxControl_CreateCPIRequest(responseJson);

    parcJSON_Release(&responseJson);

    return result;
}
/**
 * All CPI messages carry a sequence number.
 *
 * Example:
 * @code
 * <#example#>
 * @endcode
 */
uint64_t
cpi_GetSequenceNumber(CCNxControl *control)
{
    PARCJSON *json = ccnxControl_GetJson(control);

    return controlPlaneInterface_GetSequenceNumber(json);
}
/**
 * You should verify that it's a CPI message with cpi_IsCpiMessage() before using this.
 *
 * Example:
 * @code
 * <#example#>
 * @endcode
 */
CpiMessageType
cpi_GetMessageType(const CCNxControl *control)
{
    PARCJSON *json = ccnxControl_GetJson(control);
    CpiMessageType result = controlPlaneInterface_GetCPIMessageType(json);
    return result;
}
Example #6
0
LONGBOW_TEST_CASE(Global, athena_ProcessControl_CPI_REGISTER_PREFIX)
{
    PARCURI *connectionURI;
    Athena *athena = athena_Create(100);

    CCNxName *name = ccnxName_CreateFromCString("ccnx:/foo/bar");
    CCNxControl *control = ccnxControl_CreateAddRouteToSelfRequest(name); // CPI_REGISTER_PREFIX
    CCNxMetaMessage *registerPrefixCommand = ccnxMetaMessage_CreateFromControl(control);
    ccnxControl_Release(&control);

    control = ccnxControl_CreateRemoveRouteToSelfRequest(name); // CPI_UNREGISTER_PREFIX
    CCNxMetaMessage *unregisterPrefixCommand = ccnxMetaMessage_CreateFromControl(control);
    ccnxControl_Release(&control);
    ccnxName_Release(&name);

    connectionURI = parcURI_Parse("tcp://localhost:50100/listener/name=TCPListener");
    const char *result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI);
    assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno));
    parcURI_Release(&connectionURI);

    connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_0");
    result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI);
    assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno));
    parcURI_Release(&connectionURI);

    int linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_0");
    PARCBitVector *ingressVector = parcBitVector_Create();
    parcBitVector_Set(ingressVector, linkId);

    // Call _Receive() once to prime the link. Messages are dropped until _Receive() is called once.
    PARCBitVector *linksRead = NULL;
    CCNxMetaMessage *msg = athenaTransportLinkAdapter_Receive(athena->athenaTransportLinkAdapter, &linksRead, -1);
    assertNull(msg, "Expected to NOT receive a message after the first call to _Receive()");

    CCNxMetaMessage *cpiMessages[2];
    cpiMessages[0] = registerPrefixCommand;    // CPI_REGISTER_PREFIX
    cpiMessages[1] = unregisterPrefixCommand;  // CPI_UNREGISTER_PREFIX

    for (int i = 0; i < 2; i++) {
        CCNxMetaMessage *cpiMessageToSend = cpiMessages[i];
        athena_ProcessMessage(athena, cpiMessageToSend, ingressVector);
        ccnxMetaMessage_Release(&cpiMessageToSend);

        CCNxMetaMessage *ack = athenaTransportLinkAdapter_Receive(athena->athenaTransportLinkAdapter, &linksRead, -1);
        assertNotNull(ack, "Expected a CPI_ACK message back");
        assertTrue(ccnxMetaMessage_IsControl(ack), "Expected a control message back");
        parcBitVector_Release(&linksRead);

        PARCJSON *json = ccnxControl_GetJson(ack);
        const PARCJSONValue *cpiAckResult = parcJSON_GetByPath(json, "CPI_ACK/REQUEST/RESULT");
        bool commandResult = parcJSONValue_GetBoolean(cpiAckResult);
        assertTrue(commandResult, "Expected the ACK to contain RESULT=true");

        ccnxMetaMessage_Release(&ack);
    }

    parcBitVector_Release(&ingressVector);
    athena_Release(&athena);
}
Example #7
0
static CCNxControl *
_createAck(MetisConfiguration *config, CCNxControl *control, unsigned ingressId)
{
    PARCJSON *json = ccnxControl_GetJson(control);
    PARCJSON *jsonAck = cpiAcks_CreateAck(json);

    CCNxControl *response = ccnxControl_CreateCPIRequest(jsonAck);
    parcJSON_Release(&jsonAck);
    return response;
}
/**
 * Return the relevant operation from a REQUEST or a REPSONSE.
 * Do not call on an ACK
 *
 * Example:
 * @code
 * <#example#>
 * @endcode
 */
CpiOperation
cpi_GetMessageOperation(CCNxControl *control)
{
    if (cpiConnectionEthernet_IsAddMessage(control)) {
        return CPI_ADD_CONNECTION_ETHERNET;
    }

    if (cpiConnectionEthernet_IsRemoveMessage(control)) {
        return CPI_REMOVE_CONNECTION_ETHERNET;
    }

    PARCJSON *json = ccnxControl_GetJson(control);

    CpiOperation result = cpi_getCPIOperation2(json);
    return result;
}
LONGBOW_TEST_CASE(Global, cpiCancelFlow_CreateRequest)
{
    const char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"CPI_CANCEL_FLOW\":{\"FLOW_NAME\":\"lci:/who/doesnt/like/pie\"}}}";

    CCNxName *name = ccnxName_CreateFromURI("lci:/who/doesnt/like/pie");
    PARCJSON *cpiRequest = cpiCancelFlow_CreateRequest(name);
    CCNxControl *controlRequest = ccnxControl_CreateCPIRequest(cpiRequest);

    PARCJSON *json = ccnxControl_GetJson(controlRequest);

    char buffer[1024];
    sprintf(buffer, truth_format, cpi_GetSequenceNumber(controlRequest));

    char *test_string = parcJSON_ToCompactString(json);
    assertTrue(strcmp(buffer, test_string) == 0, "Incorrect JSON, expected '%s' got '%s'", buffer, test_string);
    parcMemory_Deallocate((void **) &test_string);

    ccnxControl_Release(&controlRequest);
    parcJSON_Release(&cpiRequest);
    ccnxName_Release(&name);
}
NotifyStatus *
ccnxControl_GetNotifyStatus(const CCNxControl *control)
{
    return notifyStatus_ParseJSON(ccnxControl_GetJson(control));
}
    CCNxName *prefix = ccnxName_CreateFromURI("lci:/howdie/stranger");
    unsigned ifidx = 55;
    CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
    struct timeval lifetime = { 3600, 0 };
    unsigned cost = 200;

    CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);

    CCNxControl *control = ccnxControl_CreateAddRouteRequest(route);

    // get its sequence number
    uint64_t seqnum = cpi_GetSequenceNumber(control);
    sprintf(truth, truth_format, seqnum);

    PARCJSON *test_json = ccnxControl_GetJson(control);
    char *test = parcJSON_ToCompactString(test_json);
    assertTrue(strcasecmp(truth, test) == 0, "Expected '%s', actual '%s'", truth, test);
    parcMemory_Deallocate((void **) &test);

    ccnxControl_Release(&control);
    cpiRouteEntry_Destroy(&route);
    cpiAddress_Destroy(&nexthop);
}

/**
 * Add route without lifeitme
 */
LONGBOW_TEST_CASE(Global, cpiForwarding_AddRoute_2)
{
    // The JSON representation depends on the system sockaddr_in format, which