summaryrefslogtreecommitdiffstats
path: root/hicn-light/src/core/wldr.c
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/core/wldr.c')
-rwxr-xr-xhicn-light/src/core/wldr.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/hicn-light/src/core/wldr.c b/hicn-light/src/core/wldr.c
new file mode 100755
index 000000000..b94ae76e5
--- /dev/null
+++ b/hicn-light/src/core/wldr.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017-2019 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 <parc/assert/parc_Assert.h>
+#include <parc/logging/parc_LogReporterTextStdout.h>
+#include <src/core/connection.h>
+#include <src/core/forwarder.h>
+#include <src/core/wldr.h>
+#include <stdint.h>
+#include <stdio.h>
+
+struct wldr_buffer {
+ Message *message;
+ uint8_t rtx_counter;
+};
+
+typedef struct wldr_buffer WldrBuffer;
+
+struct wldr_state {
+ uint16_t expected_label;
+ uint16_t next_label;
+ WldrBuffer *buffer[BUFFER_SIZE];
+};
+
+Wldr *wldr_Init() {
+ Wldr *wldr = parcMemory_AllocateAndClear(sizeof(Wldr));
+ parcAssertNotNull(wldr, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(Wldr));
+ wldr->expected_label = 1;
+ wldr->next_label = 1;
+ for (int i = 0; i < BUFFER_SIZE; i++) {
+ WldrBuffer *entry = parcMemory_AllocateAndClear(sizeof(WldrBuffer));
+ parcAssertNotNull(
+ entry,
+ "WldrBuffer init: parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(WldrBuffer));
+ entry->message = NULL;
+ entry->rtx_counter = 0;
+ wldr->buffer[i] = entry;
+ }
+ return wldr;
+}
+
+void wldr_ResetState(Wldr *wldr) {
+ wldr->expected_label = 1;
+ wldr->next_label = 1;
+ for (int i = 0; i < BUFFER_SIZE; i++) {
+ wldr->buffer[i]->message = NULL;
+ wldr->buffer[i]->rtx_counter = 0;
+ }
+}
+
+void wldr_Destroy(Wldr **wldrPtr) {
+ Wldr *wldr = *wldrPtr;
+ for (unsigned i = 0; i < BUFFER_SIZE; i++) {
+ if (wldr->buffer[i]->message != NULL) {
+ message_Release(&(wldr->buffer[i]->message));
+ parcMemory_Deallocate((void **)&(wldr->buffer[i]));
+ }
+ }
+ parcMemory_Deallocate((void **)&wldr);
+ *wldrPtr = NULL;
+}
+
+static void _wldr_RetransmitPacket(Wldr *wldr, const Connection *conn,
+ uint16_t label) {
+ if (wldr->buffer[label % BUFFER_SIZE]->message == NULL) {
+ // the required message for retransmission is not in the buffer
+ return;
+ }
+
+ if (wldr->buffer[label % BUFFER_SIZE]->rtx_counter < MAX_RTX) {
+ Message *msg = wldr->buffer[label % BUFFER_SIZE]->message;
+ message_SetWldrLabel(msg, wldr->next_label);
+
+ if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->message != NULL) {
+ message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message));
+ }
+
+ wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = msg;
+ wldr->buffer[wldr->next_label % BUFFER_SIZE]->rtx_counter =
+ wldr->buffer[label % BUFFER_SIZE]->rtx_counter + 1;
+ message_Acquire(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message);
+ wldr->next_label++;
+ connection_ReSend(conn, msg, false);
+ }
+}
+
+static void _wldr_SendWldrNotificaiton(Wldr *wldr, const Connection *conn,
+ Message *message, uint16_t expected_lbl,
+ uint16_t received_lbl) {
+ // here we need to create a new packet that is used to send the wldr
+ // notification to the prevoius hop. the destionation address of the
+ // notification is the source address of the message for which we want to
+ // create a notification. in fact, if message is an interest the prevoius hop
+ // is identified by the src. if message is a data, we need to send the
+ // notification message with the content name has a source address in this way
+ // the message will be trapped by the pounting rules in the next hop We define
+ // the notification as an interest message so that the NAT in the send function
+ // will set the src address of the local connection. Notice that in this way
+ // the notification packet will be dispaced to the right connection at the next
+ // hop.
+
+ Message *notification =
+ message_CreateWldrNotification(message, expected_lbl, received_lbl);
+ parcAssertNotNull(notification, "Got null from CreateWldrNotification");
+ connection_ReSend(conn, notification, true);
+}
+
+void wldr_SetLabel(Wldr *wldr, Message *message) {
+ // in this function we send the packet for the first time
+ // 1) we set the wldr label
+ message_SetWldrLabel(message, wldr->next_label);
+
+ // 2) we store the pointer to packet in the buffer
+ if (wldr->buffer[wldr->next_label % BUFFER_SIZE]->message != NULL) {
+ // release an old message if necessary
+ message_Release(&(wldr->buffer[wldr->next_label % BUFFER_SIZE]->message));
+ }
+
+ // we need to acquire the message to avoid that it gets destroyed
+ message_Acquire(message);
+
+ wldr->buffer[wldr->next_label % BUFFER_SIZE]->message = message;
+ wldr->buffer[wldr->next_label % BUFFER_SIZE]->rtx_counter = 0;
+ wldr->next_label++;
+ if (wldr->next_label ==
+ 0) // we alwasy skip label 0 beacause it means that wldr is not active
+ wldr->next_label++;
+}
+
+void wldr_DetectLosses(Wldr *wldr, const Connection *conn, Message *message) {
+ if (message_HasWldr(message)) {
+ // this is a normal wldr packet
+ uint16_t pkt_lbl = (uint16_t)message_GetWldrLabel(message);
+ if (pkt_lbl != wldr->expected_label) {
+ // if the received packet label is 1 and the expected packet label >
+ // pkt_lbl usually we are in the case where a remote note disconnected for
+ // a while and reconnected on this same connection, so the two nodes are
+ // out of synch for this reason we do not send any notification, we just
+ // synch the labels
+
+ if ((pkt_lbl != 1) || (wldr->expected_label < pkt_lbl)) {
+ _wldr_SendWldrNotificaiton(wldr, conn, message, wldr->expected_label,
+ pkt_lbl);
+ }
+
+ // here we always synch
+ wldr->expected_label = (uint16_t)(pkt_lbl + 1);
+ } else {
+ wldr->expected_label++;
+ if (wldr->expected_label == 0)
+ wldr->expected_label++; // for the next_label we want to skip 0
+ }
+ }
+}
+
+void wldr_HandleWldrNotification(Wldr *wldr, const Connection *conn,
+ Message *message) {
+ uint16_t expected_lbl = (uint16_t)message_GetWldrExpectedLabel(message);
+ uint16_t received_lbl = (uint16_t)message_GetWldrLastReceived(message);
+ if ((wldr->next_label - expected_lbl) > BUFFER_SIZE) {
+ // the packets are not in the buffer anymore
+ return;
+ }
+ while (expected_lbl < received_lbl) {
+ _wldr_RetransmitPacket(wldr, conn, expected_lbl);
+ expected_lbl++;
+ }
+}