summaryrefslogtreecommitdiffstats
path: root/libccnx-transport-rta/ccnx/api/control/cpi_RouteEntry.c
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-transport-rta/ccnx/api/control/cpi_RouteEntry.c')
-rw-r--r--libccnx-transport-rta/ccnx/api/control/cpi_RouteEntry.c466
1 files changed, 466 insertions, 0 deletions
diff --git a/libccnx-transport-rta/ccnx/api/control/cpi_RouteEntry.c b/libccnx-transport-rta/ccnx/api/control/cpi_RouteEntry.c
new file mode 100644
index 00000000..0de5c915
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/cpi_RouteEntry.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <ccnx/api/control/cpi_RouteEntry.h>
+#include <ccnx/api/control/controlPlaneInterface.h>
+#include <parc/algol/parc_Memory.h>
+
+#include <limits.h>
+
+#include <LongBow/runtime.h>
+
+static const char *cpiPrefix = "PREFIX";
+static const char *cpiInterface = "INTERFACE";
+static const char *cpiFlags = "FLAGS";
+static const char *cpiLifetime = "LIFETIME";
+static const char *cpiNexthop = "NEXTHOP";
+static const char *cpiProtocol = "PROTOCOL";
+static const char *cpiRouteType = "ROUTETYPE";
+static const char *cpiCost = "COST";
+static const char *cpiSymbolic = "SYMBOLIC";
+
+struct cpi_route_entry {
+ bool hasInterfaceIndex;
+ unsigned interfaceIndex;
+
+ CCNxName *prefix;
+ char *symbolic;
+ CPIAddress *nexthop;
+ CPINameRouteProtocolType routingProtocol;
+ CPINameRouteType routeType;
+ unsigned cost;
+
+ bool hasLifetime;
+ struct timeval lifetime;
+};
+
+void
+cpiRouteEntry_Destroy(CPIRouteEntry **routeEntryPtr)
+{
+ assertNotNull(routeEntryPtr, "Parameter must be non-null double pointer");
+ assertNotNull(*routeEntryPtr, "Parameter must dereference to non-null pointer");
+ CPIRouteEntry *route = *routeEntryPtr;
+
+ ccnxName_Release(&route->prefix);
+ if (route->nexthop) {
+ cpiAddress_Destroy(&route->nexthop);
+ }
+
+ if (route->symbolic) {
+ parcMemory_Deallocate((void **) &route->symbolic);
+ }
+
+ parcMemory_Deallocate((void **) &route);
+ *routeEntryPtr = NULL;
+}
+
+CPIRouteEntry *
+cpiRouteEntry_CreateRouteToSelf(const CCNxName *prefix)
+{
+ void *optionalLifetime = NULL;
+ void *nexthop = NULL;
+ unsigned cost = 0;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(ccnxName_Copy(prefix),
+ CPI_CURRENT_INTERFACE,
+ nexthop,
+ cpiNameRouteProtocolType_LOCAL,
+ cpiNameRouteType_LONGEST_MATCH,
+ optionalLifetime,
+ cost);
+ return route;
+}
+
+char *
+cpiRouteEntry_ToString(CPIRouteEntry *route)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+
+ parcBufferComposer_Format(composer, "%6d %9.9s %7.7s %u ",
+ route->interfaceIndex,
+ cpiNameRouteProtocolType_ToString(route->routingProtocol),
+ cpiNameRouteType_ToString(route->routeType),
+ route->cost);
+
+ if (route->symbolic != NULL) {
+ parcBufferComposer_PutString(composer, route->symbolic);
+ } else {
+ parcBufferComposer_PutChar(composer, '-');
+ }
+
+ if (route->nexthop != NULL) {
+ cpiAddress_BuildString(cpiRouteEntry_GetNexthop(route), composer);
+ } else {
+ parcBufferComposer_PutChar(composer, '-');
+ }
+
+ if (route->hasLifetime) {
+#if __APPLE__
+ parcBufferComposer_Format(composer, " %ld.%06d ", route->lifetime.tv_sec, route->lifetime.tv_usec);
+#else
+ parcBufferComposer_Format(composer, " %ld.%06ld ", route->lifetime.tv_sec, route->lifetime.tv_usec);
+#endif
+ } else {
+ parcBufferComposer_Format(composer, " %8.8s ", "infinite");
+ }
+
+ char *ccnxName = ccnxName_ToString(cpiRouteEntry_GetPrefix(route));
+ parcBufferComposer_PutString(composer, ccnxName);
+
+ parcMemory_Deallocate((void **) &ccnxName);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ parcBufferComposer_Release(&composer);
+ return result;
+}
+
+CPIRouteEntry *
+cpiRouteEntry_Create(CCNxName *prefix,
+ unsigned interfaceIndex,
+ const CPIAddress *optionalNexthop,
+ CPINameRouteProtocolType routingProtocol,
+ CPINameRouteType routeType,
+ const struct timeval *optionalLifetime,
+ unsigned cost)
+{
+ assertNotNull(prefix, "Parameter prefix must be non-null");
+
+ CPIRouteEntry *route = parcMemory_AllocateAndClear(sizeof(CPIRouteEntry));
+ assertNotNull(route, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(CPIRouteEntry));
+ route->prefix = prefix;
+ route->symbolic = NULL;
+ route->interfaceIndex = interfaceIndex;
+ route->hasInterfaceIndex = true;
+ route->nexthop = optionalNexthop != NULL ? cpiAddress_Copy(optionalNexthop) : NULL;
+ route->routingProtocol = routingProtocol;
+ route->routeType = routeType;
+ route->cost = cost;
+
+ if (optionalLifetime) {
+ route->hasLifetime = true;
+ route->lifetime = *optionalLifetime;
+ } else {
+ route->hasLifetime = false;
+ route->lifetime = (struct timeval) { .tv_sec = INT_MAX, .tv_usec = 0 };
+ }
+
+ return route;
+}
+
+CPIRouteEntry *
+cpiRouteEntry_CreateSymbolic(CCNxName *prefix,
+ const char *symbolicName,
+ CPINameRouteProtocolType routingProtocol,
+ CPINameRouteType routeType,
+ const struct timeval *optionalLifetime,
+ unsigned cost)
+{
+ assertNotNull(prefix, "Parameter prefix must be non-null");
+
+ CPIRouteEntry *route = parcMemory_AllocateAndClear(sizeof(CPIRouteEntry));
+ assertNotNull(route, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(CPIRouteEntry));
+ route->prefix = prefix;
+ route->symbolic = parcMemory_StringDuplicate(symbolicName, strlen(symbolicName));
+ route->interfaceIndex = UINT32_MAX;
+ route->hasInterfaceIndex = false;
+ route->nexthop = NULL;
+ route->routingProtocol = routingProtocol;
+ route->routeType = routeType;
+ route->cost = cost;
+
+ if (optionalLifetime) {
+ route->hasLifetime = true;
+ route->lifetime = *optionalLifetime;
+ } else {
+ route->hasLifetime = false;
+ route->lifetime = (struct timeval) { .tv_sec = INT_MAX, .tv_usec = 0 };
+ }
+
+ return route;
+}
+
+
+CPIRouteEntry *
+cpiRouteEntry_Copy(const CPIRouteEntry *original)
+{
+ assertNotNull(original, "Parameter a must be non-null");
+ CPIRouteEntry *copy;
+
+ if (original->hasInterfaceIndex) {
+ copy = cpiRouteEntry_Create(
+ ccnxName_Copy(original->prefix),
+ original->interfaceIndex,
+ (original->nexthop ? original->nexthop : NULL),
+ original->routingProtocol,
+ original->routeType,
+ (original->hasLifetime ? &original->lifetime : NULL),
+ original->cost);
+
+ if (original->symbolic) {
+ copy->symbolic = parcMemory_StringDuplicate(original->symbolic, strlen(original->symbolic));
+ }
+ } else {
+ copy = cpiRouteEntry_CreateSymbolic(
+ ccnxName_Copy(original->prefix),
+ original->symbolic,
+ original->routingProtocol,
+ original->routeType,
+ (original->hasLifetime ? &original->lifetime : NULL),
+ original->cost);
+ }
+ return copy;
+}
+
+void
+cpiRouteEntry_SetInterfaceIndex(CPIRouteEntry *route, unsigned interfaceIndex)
+{
+ assertNotNull(route, "Parameter a must be non-null");
+ route->interfaceIndex = interfaceIndex;
+ route->hasInterfaceIndex = true;
+}
+
+
+bool
+cpiRouteEntry_Equals(const CPIRouteEntry *a, const CPIRouteEntry *b)
+{
+ assertNotNull(a, "Parameter a must be non-null");
+ assertNotNull(b, "Parameter b must be non-null");
+ if (a == b) {
+ return true;
+ }
+
+ if (a->interfaceIndex == b->interfaceIndex) {
+ if (a->routeType == b->routeType) {
+ if (a->routingProtocol == b->routingProtocol) {
+ if (a->cost == b->cost) {
+ if (ccnxName_Equals(a->prefix, b->prefix)) {
+ if (cpiAddress_Equals(a->nexthop, b->nexthop)) {
+ if (a->hasLifetime == b->hasLifetime) {
+ if (timercmp(&a->lifetime, &b->lifetime, ==)) {
+ if (a->symbolic == b->symbolic || (a->symbolic != NULL && b->symbolic != NULL && strcasecmp(a->symbolic, b->symbolic) == 0)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+const CCNxName *
+cpiRouteEntry_GetPrefix(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->prefix;
+}
+
+unsigned
+cpiRouteEntry_GetInterfaceIndex(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->interfaceIndex;
+}
+
+const CPIAddress *
+cpiRouteEntry_GetNexthop(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->nexthop;
+}
+
+bool
+cpiRouteEntry_HasLifetime(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->hasLifetime;
+}
+
+struct timeval
+cpiRouteEntry_GetLifetime(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->lifetime;
+}
+
+CPINameRouteProtocolType
+cpiRouteEntry_GetRouteProtocolType(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->routingProtocol;
+}
+
+CPINameRouteType
+cpiRouteEntry_GetRouteType(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->routeType;
+}
+
+unsigned
+cpiRouteEntry_GetCost(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->cost;
+}
+
+const char *
+cpiRouteEntry_GetSymbolicName(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+ return route->symbolic;
+}
+
+PARCJSON *
+cpiRouteEntry_ToJson(const CPIRouteEntry *route)
+{
+ assertNotNull(route, "Parameter must be non-null");
+
+ PARCJSON *routeJson = parcJSON_Create();
+ char *uri = ccnxName_ToString(route->prefix);
+ parcJSON_AddString(routeJson, cpiPrefix, uri);
+ parcMemory_Deallocate((void **) &uri);
+
+ if (route->symbolic) {
+ parcJSON_AddString(routeJson, cpiSymbolic, route->symbolic);
+ }
+
+ if (route->hasInterfaceIndex) {
+ parcJSON_AddInteger(routeJson, cpiInterface, route->interfaceIndex);
+ }
+
+ parcJSON_AddInteger(routeJson, cpiFlags, 0);
+
+ if (route->nexthop) {
+ // some registrations can have NULL nexthop, its ok
+ PARCJSON *json = cpiAddress_ToJson(route->nexthop);
+ parcJSON_AddObject(routeJson, cpiNexthop, json);
+ parcJSON_Release(&json);
+ }
+
+ parcJSON_AddString(routeJson, cpiProtocol, cpiNameRouteProtocolType_ToString(route->routingProtocol));
+ parcJSON_AddString(routeJson, cpiRouteType, cpiNameRouteType_ToString(route->routeType));
+ parcJSON_AddInteger(routeJson, cpiCost, route->cost);
+
+ if (route->hasLifetime) {
+ PARCJSONArray *lifetimeJson = parcJSONArray_Create();
+ PARCJSONValue *value = parcJSONValue_CreateFromInteger(route->lifetime.tv_sec);
+ parcJSONArray_AddValue(lifetimeJson, value);
+ parcJSONValue_Release(&value);
+ value = parcJSONValue_CreateFromInteger(route->lifetime.tv_usec);
+ parcJSONArray_AddValue(lifetimeJson, value);
+ parcJSONValue_Release(&value);
+ parcJSON_AddArray(routeJson, cpiLifetime, lifetimeJson);
+ parcJSONArray_Release(&lifetimeJson);
+ }
+
+ return routeJson;
+}
+
+CPIRouteEntry *
+cpiRouteEntry_FromJson(PARCJSON *json)
+{
+ assertNotNull(json, "Parameter json must be non-null");
+ PARCJSON *routeJson = json;
+
+ PARCJSONValue *value = parcJSON_GetValueByName(routeJson, cpiPrefix);
+ assertNotNull(value, "Couldn't locate tag %s in: %s", cpiPrefix, parcJSON_ToString(json));
+ PARCBuffer *sBuf = parcJSONValue_GetString(value);
+ CCNxName *prefix = ccnxName_CreateFromCString(parcBuffer_Overlay(sBuf, 0));
+
+ const char *symbolicName = NULL;
+ value = parcJSON_GetValueByName(routeJson, cpiSymbolic);
+ if (value) {
+ sBuf = parcJSONValue_GetString(value);
+ symbolicName = parcBuffer_Overlay(sBuf, 0);
+ }
+
+ bool hasInterfaceIndex = false;
+ unsigned interfaceIndex = UINT32_MAX;
+ value = parcJSON_GetValueByName(routeJson, cpiInterface);
+ if (value) {
+ hasInterfaceIndex = true;
+ interfaceIndex = (unsigned) parcJSONValue_GetInteger(value);
+ }
+
+ CPIAddress *nexthop = NULL;
+ value = parcJSON_GetValueByName(routeJson, cpiNexthop);
+ if (value != NULL) {
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Json key %s wrong type in json %s",
+ cpiNexthop,
+ parcJSON_ToString(json));
+ PARCJSON *nexthopJson = parcJSONValue_GetJSON(value);
+ nexthop = cpiAddress_CreateFromJson(nexthopJson);
+ }
+
+ value = parcJSON_GetValueByName(routeJson, cpiProtocol);
+ sBuf = parcJSONValue_GetString(value);
+ char *valueString = parcBuffer_Overlay(sBuf, 0);
+ CPINameRouteProtocolType routingProtocol = cpiNameRouteProtocolType_FromString(valueString);
+
+ value = parcJSON_GetValueByName(routeJson, cpiRouteType);
+ sBuf = parcJSONValue_GetString(value);
+ valueString = parcBuffer_Overlay(sBuf, 0);
+ CPINameRouteType routingType = cpiNameRouteType_FromString(valueString);
+
+ value = parcJSON_GetValueByName(routeJson, cpiCost);
+ unsigned cost = (unsigned) parcJSONValue_GetInteger(value);
+
+ value = parcJSON_GetValueByName(routeJson, cpiLifetime);
+ struct timeval *lifetime = NULL;
+
+ struct timeval actual_time = { 0, 0 };
+ if (value != NULL) {
+ assertTrue(parcJSONValue_IsArray(value),
+ "Json key %s wrong typein json %s",
+ cpiNexthop,
+ parcJSON_ToString(json));
+ PARCJSONArray *lifetimeJson = parcJSONValue_GetArray(value);
+
+ actual_time.tv_sec = parcJSONValue_GetInteger(parcJSONArray_GetValue(lifetimeJson, 0));
+ actual_time.tv_usec = (int) parcJSONValue_GetInteger(parcJSONArray_GetValue(lifetimeJson, 1));
+
+ lifetime = &actual_time;
+ }
+
+
+ // == we're now ready to create the object
+ CPIRouteEntry *route;
+ if (symbolicName) {
+ route = cpiRouteEntry_CreateSymbolic(prefix, symbolicName, routingProtocol, routingType, lifetime, cost);
+ if (hasInterfaceIndex) {
+ cpiRouteEntry_SetInterfaceIndex(route, interfaceIndex);
+ }
+ } else {
+ route = cpiRouteEntry_Create(prefix, interfaceIndex, nexthop, routingProtocol, routingType, lifetime, cost);
+ }
+
+ if (nexthop) {
+ cpiAddress_Destroy(&nexthop);
+ }
+
+ return route;
+}