aboutsummaryrefslogtreecommitdiffstats
path: root/metis/ccnx/forwarder/metis/core/metis_Connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'metis/ccnx/forwarder/metis/core/metis_Connection.c')
-rw-r--r--metis/ccnx/forwarder/metis/core/metis_Connection.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/metis/ccnx/forwarder/metis/core/metis_Connection.c b/metis/ccnx/forwarder/metis/core/metis_Connection.c
new file mode 100644
index 00000000..c3f28e14
--- /dev/null
+++ b/metis/ccnx/forwarder/metis/core/metis_Connection.c
@@ -0,0 +1,257 @@
+/*
+ * 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 <stdio.h>
+#include <limits.h>
+
+#include <ccnx/forwarder/metis/io/metis_IoOperations.h>
+#include <ccnx/forwarder/metis/core/metis_Connection.h>
+#include <ccnx/forwarder/metis/io/metis_AddressPair.h>
+#include <ccnx/forwarder/metis/core/metis_Wldr.h>
+#include <ccnx/forwarder/metis/core/metis_Ticks.h>
+#include <parc/algol/parc_Memory.h>
+#include <LongBow/runtime.h>
+
+struct metis_connection {
+ const MetisAddressPair *addressPair;
+ MetisIoOperations *ops;
+
+ unsigned refCount;
+
+ bool probing_active;
+ unsigned probing_interval;
+ unsigned counter;
+ MetisTicks last_sent;
+ MetisTicks delay;
+
+ MetisWldr *wldr;
+};
+
+MetisConnection *
+metisConnection_Create(MetisIoOperations *ops)
+{
+ assertNotNull(ops, "Parameter ops must be non-null");
+ MetisConnection *conn = parcMemory_AllocateAndClear(sizeof(MetisConnection));
+ assertNotNull(conn, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisConnection));
+ conn->addressPair = metisIoOperations_GetAddressPair(ops);
+ conn->ops = ops;
+ conn->refCount = 1;
+ conn->wldr = NULL;
+ conn->probing_active = false;
+ conn->probing_interval = 0;
+ conn->counter = 0;
+ conn->last_sent = 0;
+ conn->delay = INT_MAX;
+ return conn;
+}
+
+MetisConnection *
+metisConnection_Acquire(MetisConnection *connection)
+{
+ assertNotNull(connection, "Parameter conn must be non-null");
+ connection->refCount++;
+ return connection;
+}
+
+void
+metisConnection_Release(MetisConnection **connectionPtr)
+{
+ assertNotNull(connectionPtr, "Parameter must be non-null double pointer");
+ assertNotNull(*connectionPtr, "Parameter must dereference to non-null pointer");
+ MetisConnection *conn = *connectionPtr;
+
+ assertTrue(conn->refCount > 0, "Invalid state, connection reference count should be positive, got 0.");
+ conn->refCount--;
+ if (conn->refCount == 0) {
+ // don't destroy addressPair, its part of ops.
+ metisIoOperations_Release(&conn->ops);
+ if (conn->wldr != NULL) {
+ metisWldr_Destroy(&(conn->wldr));
+ }
+ parcMemory_Deallocate((void **) &conn);
+ }
+ *connectionPtr = NULL;
+}
+
+bool
+metisConnection_Send(const MetisConnection *conn, MetisMessage *message)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ assertNotNull(message, "Parameter message must be non-null");
+
+ if (metisIoOperations_IsUp(conn->ops)) {
+ uint8_t connectionId = (uint8_t) metisConnection_GetConnectionId(conn);
+ metisMessage_UpdatePathLabel(message, connectionId);
+ if (conn->wldr != NULL) {
+ metisWldr_SetLabel(conn->wldr, message);
+ }
+ return metisIoOperations_Send(conn->ops, NULL, message);
+ }
+ return false;
+}
+
+
+static void
+_sendProbe(MetisConnection *conn, unsigned probeType)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+
+ if (probeType == METIS_PACKET_TYPE_PROBE_REQUEST) {
+ MetisTicks now = metisIoOperations_SendProbe(conn->ops, probeType);
+ if (now != 0) {
+ conn->last_sent = now;
+ }
+ } else {
+ metisIoOperations_SendProbe(conn->ops, probeType);
+ }
+}
+
+
+void
+metisConnection_Probe(MetisConnection *conn)
+{
+ _sendProbe(conn, METIS_PACKET_TYPE_PROBE_REQUEST);
+}
+
+void
+metisConnection_HandleProbe(MetisConnection *conn, uint8_t *pkt, MetisTicks actualTime)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ assertNotNull(pkt, "Parameter pkt must be non-null");
+
+ if (pkt[1] == METIS_PACKET_TYPE_PROBE_REQUEST) {
+ _sendProbe(conn, METIS_PACKET_TYPE_PROBE_REPLY);
+ } else if (pkt[1] == METIS_PACKET_TYPE_PROBE_REPLY) {
+ MetisTicks delay = actualTime - conn->last_sent;
+ if (delay == 0) {
+ delay = 1;
+ }
+ if (delay < conn->delay) {
+ conn->delay = delay;
+ }
+ } else {
+ printf("receivde unkwon probe type\n");
+ }
+}
+
+uint64_t
+metisConnection_GetDelay(MetisConnection *conn)
+{
+ return (uint64_t) conn->delay;
+}
+
+
+MetisIoOperations *
+metisConnection_GetIoOperations(const MetisConnection *conn)
+{
+ return conn->ops;
+}
+
+unsigned
+metisConnection_GetConnectionId(const MetisConnection *conn)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ return metisIoOperations_GetConnectionId(conn->ops);
+}
+
+const MetisAddressPair *
+metisConnection_GetAddressPair(const MetisConnection *conn)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ return metisIoOperations_GetAddressPair(conn->ops);
+}
+
+bool
+metisConnection_IsUp(const MetisConnection *conn)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ return metisIoOperations_IsUp(conn->ops);
+}
+
+bool
+metisConnection_IsLocal(const MetisConnection *conn)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ return metisIoOperations_IsLocal(conn->ops);
+}
+
+const void *
+metisConnection_Class(const MetisConnection *conn)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ return metisIoOperations_Class(conn->ops);
+}
+
+bool
+metisConnection_ReSend(const MetisConnection *conn, MetisMessage *message)
+{
+ assertNotNull(conn, "Parameter conn must be non-null");
+ assertNotNull(message, "Parameter message must be non-null");
+
+ if (metisConnection_IsUp(conn)) {
+ //here the wldr header is alreay set: this message is a retransmission or a notification
+
+ //we don't need to update the path label. In fact the path label was already set in the first
+ //transmission of this packet (in metisConnection_Send). Since we are using pointers this
+ //message has the same path label. However it could be a good idea to remove the path label
+ //so that raaqm will discard this packet for the RTT estimation.
+
+ return metisIoOperations_Send(conn->ops, NULL, message);
+ }
+ return false;
+}
+
+void
+metisConnection_EnableWldr(MetisConnection *conn)
+{
+ if (!metisConnection_IsLocal(conn)) {
+ if (conn->wldr == NULL) {
+ printf("----------------- enable wldr\n");
+ conn->wldr = metisWldr_Init();
+ }
+ }
+}
+
+void
+metisConnection_DisableWldr(MetisConnection *conn)
+{
+ if (!metisConnection_IsLocal(conn)) {
+ if (conn->wldr != NULL) {
+ printf("----------------- disable wldr\n");
+ metisWldr_Destroy(&(conn->wldr));
+ conn->wldr = NULL;
+ }
+ }
+}
+
+
+bool
+metisConnection_HasWldr(const MetisConnection *conn)
+{
+ if (conn->wldr == NULL) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+void
+metisConnection_DetectLosses(MetisConnection *conn, MetisMessage *message)
+{
+ metisWldr_DetectLosses(conn->wldr, conn, message);
+}
+