Merge remote-tracking branch 'origin/routing-manager'
[platform/upstream/iotivity.git] / resource / csdk / routing / src / routingtablemanager.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include "routingtablemanager.h"
24 #include "routingutility.h"
25 #include "oic_malloc.h"
26 #include "oic_string.h"
27 #include "include/logger.h"
28
29 /**
30  * Logging tag for module name.
31  */
32 #define TAG "RTM"
33
34 /**
35  * Tag for printing the Routing table.
36  */
37 #define RM_TAG "RAP"
38
39
40 /**
41  * Initial Length of observer list.
42  */
43 #define MAX_OBSERVER_LIST_LENGTH 10
44
45 static const uint64_t USECS_PER_SEC = 1000000;
46
47 OCStackResult RTMInitialize(u_linklist_t **gatewayTable, u_linklist_t **endpointTable)
48 {
49     OC_LOG(DEBUG, TAG, "RTMInitialize IN");
50     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
51     RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
52     if (NULL == *gatewayTable)
53     {
54         *gatewayTable = u_linklist_create();
55         if (NULL == *gatewayTable)
56         {
57             OC_LOG(ERROR, TAG, "Creating Routing Table failed");
58             RTMTerminate(gatewayTable, endpointTable);
59             return OC_STACK_ERROR;
60         }
61     }
62
63     if (NULL == *endpointTable)
64     {
65         *endpointTable = u_linklist_create();
66         if (NULL == *endpointTable)
67         {
68            OC_LOG(ERROR, TAG, "Creating Routing Table failed");
69             RTMTerminate(gatewayTable, endpointTable);
70            return OC_STACK_ERROR;
71         }
72     }
73     OC_LOG(DEBUG, TAG, "RTMInitialize OUT");
74     return OC_STACK_OK;
75 }
76
77 /*
78  * Freeing every char pointer and array list of gateway entry here and frees the table.
79  */
80 OCStackResult RTMFreeGatewayRouteTable(u_linklist_t **gatewayTable)
81 {
82     OC_LOG(DEBUG, TAG, "RTMFreeGatewayRouteTable IN");
83     if (NULL == gatewayTable || NULL == *gatewayTable)
84     {
85         return OC_STACK_OK;
86     }
87
88     u_linklist_iterator_t *iterTable = NULL;
89     u_linklist_init_iterator(*gatewayTable, &iterTable);
90     while (NULL != iterTable)
91     {
92         RTMGatewayEntry_t *hop = u_linklist_get_data(iterTable);
93         if (NULL != hop && NULL != hop->destination)
94         {
95             while (u_arraylist_length(hop->destination->destIntfAddr) > 0)
96             {
97                 if (NULL != hop->destination)
98                 {
99                     RTMDestIntfInfo_t *data = u_arraylist_remove(hop->destination->destIntfAddr, 0);
100                     OICFree(data);
101                 }
102             }
103             u_arraylist_free(&(hop->destination->destIntfAddr));
104             OICFree(hop->destination);
105             // No need to free next hop as it is already freed during it's gateway free
106             OICFree(hop);
107         }
108
109         OCStackResult ret = u_linklist_remove(*gatewayTable, &iterTable);
110         if (OC_STACK_OK != ret)
111         {
112            OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
113            return OC_STACK_ERROR;
114         }
115     }
116     u_linklist_free(gatewayTable);
117     OC_LOG(DEBUG, TAG, "RTMFreeGatewayRouteTable OUT");
118     return OC_STACK_OK;
119 }
120
121 /*
122  * Freeing every char pointer of endpoint entry here frees the table.
123  */
124 OCStackResult RTMFreeEndpointRouteTable(u_linklist_t **endpointTable)
125 {
126     OC_LOG(DEBUG, TAG, "IN");
127     if (NULL == endpointTable || NULL == *endpointTable)
128     {
129         return OC_STACK_OK;
130     }
131
132     u_linklist_iterator_t *iterTable = NULL;
133     u_linklist_init_iterator(*endpointTable, &iterTable);
134     while (NULL != iterTable)
135     {
136         RTMEndpointEntry_t *hop = u_linklist_get_data(iterTable);
137         if (NULL != hop)
138         {
139             OICFree(hop);
140         }
141
142         OCStackResult ret = u_linklist_remove(*endpointTable, &iterTable);
143         if (OC_STACK_OK != ret)
144         {
145             OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
146             return OC_STACK_ERROR;
147         }
148     }
149     u_linklist_free(endpointTable);
150     OC_LOG(DEBUG, TAG, "OUT");
151     return OC_STACK_OK;
152 }
153
154 OCStackResult RTMFreeGatewayIdList(u_linklist_t **gatewayIdTable)
155 {
156     OC_LOG(DEBUG, TAG, "IN");
157     if (NULL == gatewayIdTable || NULL == *gatewayIdTable)
158     {
159         return OC_STACK_OK;
160     }
161
162     u_linklist_iterator_t *iterTable = NULL;
163     u_linklist_init_iterator(*gatewayIdTable, &iterTable);
164     while (iterTable != NULL)
165     {
166         RTMGatewayId_t *hop = u_linklist_get_data(iterTable);
167         if (NULL != hop)
168         {
169             while (u_arraylist_length(hop->destIntfAddr) > 0)
170             {
171                RTMDestIntfInfo_t *data = u_arraylist_remove(hop->destIntfAddr, 0);
172                OICFree(data);
173             }
174             u_arraylist_free(&(hop->destIntfAddr));
175             OICFree(hop);
176
177             OCStackResult ret = u_linklist_remove(*gatewayIdTable, &iterTable);
178             if (OC_STACK_OK != ret)
179             {
180                OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
181                return OC_STACK_ERROR;
182             }
183         }
184         else
185         {
186             OCStackResult res = u_linklist_remove(*gatewayIdTable, &iterTable);
187             if (OC_STACK_OK != res)
188             {
189                 OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
190                 return OC_STACK_ERROR;
191             }
192         }
193     }
194     OC_LOG(DEBUG, TAG, "OUT");
195     return OC_STACK_OK;
196 }
197
198 /*
199  * Freeing memory first and then Freeing linked list for gateway and endpoint.
200  */
201 OCStackResult RTMTerminate(u_linklist_t **gatewayTable, u_linklist_t **endpointTable)
202 {
203     OC_LOG(DEBUG, TAG, "IN");
204
205     OCStackResult ret = RTMFreeGatewayRouteTable(gatewayTable);
206     if (OC_STACK_OK != ret)
207     {
208         OC_LOG(ERROR, TAG, "Deleting Gateway Routing Table failed");
209     }
210     if (NULL != *gatewayTable)
211     {
212         *gatewayTable = NULL;
213     }
214
215     ret = RTMFreeEndpointRouteTable(endpointTable);
216     if (OC_STACK_OK != ret)
217     {
218         OC_LOG(ERROR, TAG, "Deleting Endpoint Routing Table failed");
219     }
220     if (NULL != *endpointTable)
221     {
222         *endpointTable = NULL;
223     }
224     OC_LOG(DEBUG, TAG, "OUT");
225     return OC_STACK_OK;
226 }
227
228 /*
229  * Checks if destination gateway to be added is already present and update if present or
230  * adds new entry if not present.
231  * Adds Entry to head if route cost is 1.
232  * Adds Entry to Tail if route cost is > 1.
233  * Checks for Gateway id Memory and assigns to next hop address to achieve better memory usage.
234  */
235 OCStackResult RTMAddGatewayEntry(uint32_t gatewayId, uint32_t nextHop, uint32_t routeCost,
236                                  const RTMDestIntfInfo_t *destInterfaces, u_linklist_t **gatewayTable)
237 {
238     OC_LOG(DEBUG, TAG, "IN");
239     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
240     if (NULL == *gatewayTable)
241     {
242         *gatewayTable = u_linklist_create();
243     }
244
245     if (1 == routeCost && 0 != nextHop)
246     {
247         OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop should be 0 for route cost 1");
248         return OC_STACK_ERROR;
249     }
250
251     if (0 == routeCost)
252     {
253         OC_LOG(ERROR, TAG, "Adding Gateway Failed as Route cost shouldnot be less than 1");
254         return OC_STACK_ERROR;
255     }
256
257     u_linklist_iterator_t *destNode = NULL;
258     RTMGatewayId_t *gatewayNodeMap = NULL;   // Gateway id ponter can be mapped to NextHop of entry.
259
260     u_linklist_iterator_t *iterTable = NULL;
261     u_linklist_init_iterator(*gatewayTable, &iterTable);
262     // Iterate over gateway list to find if already entry with this gatewayid is present.
263     while (NULL != iterTable)
264     {
265         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
266         if (NULL == entry)
267         {
268             break;
269         }
270
271         // To save node with same gateway id (To update entry instead of add new entry).
272         if (NULL == destNode && NULL != entry->destination &&
273             (gatewayId == entry->destination->gatewayId))
274         {
275             destNode = iterTable;
276         }
277
278         // To find pointer of gateway id for a node provided next hop equals to existing gateway id.
279         if (0 != nextHop && NULL != entry->destination &&
280             nextHop == entry->destination->gatewayId)
281         {
282             gatewayNodeMap = entry->destination;
283         }
284
285         if (NULL != destNode && NULL != gatewayNodeMap)
286         {
287             break;
288         }
289
290         u_linklist_get_next(&iterTable);
291     }
292
293     if (1 < routeCost && NULL == gatewayNodeMap)
294     {
295         OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop is invalid");
296         return OC_STACK_ERROR;
297     }
298
299     //Logic to update entry if it is already destination present or to add new entry.
300     if (NULL != destNode)
301     {
302         RTMGatewayEntry_t *entry = u_linklist_get_data(destNode);
303
304         if (NULL != entry  && 1 == entry->routeCost && 0 == nextHop)
305         {
306             if (NULL == destInterfaces)
307             {
308                 OC_LOG(ERROR, TAG, "Not Adding Gateway destInterfaces is NULL");
309                 return OC_STACK_ERROR;
310             }
311             OCStackResult update = RTMUpdateDestinationIntfAdr(gatewayId, *destInterfaces, true,
312                                                                gatewayTable);
313             if (OC_STACK_OK != update)
314             {
315                 OC_LOG(ERROR, TAG, "RTMUpdateDestinationIntfAdr failed");
316             }
317             return update;
318         }
319         else if (NULL != entry  && entry->routeCost >= routeCost)
320         {
321             if (entry->routeCost == routeCost && NULL != entry->nextHop &&
322                 (nextHop == entry->nextHop->gatewayId))
323             {
324                 OC_LOG(ERROR, TAG, "Not Adding Gateway As it is Duplicate request");
325                 return OC_STACK_DUPLICATE_REQUEST;
326             }
327
328             //Mapped nextHop gateway to another entries having gateway as destination.
329             if (NULL != gatewayNodeMap)
330             {
331                 entry->destination->gatewayId = gatewayId;
332                 entry->nextHop = gatewayNodeMap;
333                 entry->destination->destIntfAddr = NULL;
334                 entry->routeCost = routeCost;
335             }
336             else if (0 == nextHop)
337             {
338                 entry->routeCost = 1;
339                 // Entry can't be updated if Next hop is not same as existing Destinations of Table.
340                 OC_LOG(DEBUG, TAG, "Updating the gateway");
341                 entry->nextHop = NULL;
342                 entry->destination->destIntfAddr = u_arraylist_create();
343                 if (NULL == entry->destination->destIntfAddr)
344                 {
345                     OC_LOG(ERROR, TAG, "Failed to create array list");
346                     return OC_STACK_ERROR;
347                 }
348
349                 RTMDestIntfInfo_t *destAdr =
350                     (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
351                 if (NULL == destAdr)
352                 {
353                     OC_LOG(ERROR, TAG, "Failed to Calloc destAdr");
354                     return OC_STACK_ERROR;
355                 }
356
357                 *destAdr = *destInterfaces;
358                 destAdr->timeElapsed = RTMGetCurrentTime();
359                 destAdr->isValid = true;
360                 bool result =
361                     u_arraylist_add(entry->destination->destIntfAddr, (void *)destAdr);
362                 if (!result)
363                 {
364                     OC_LOG(ERROR, TAG, "Adding node to head failed");
365                     OICFree(destAdr);
366                     return OC_STACK_ERROR;
367                 }
368             }
369             else
370             {
371                 OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next hop is invalid");
372                 return OC_STACK_ERROR;
373             }
374
375         }
376         else if (NULL != entry  && entry->routeCost < routeCost)
377         {
378             OC_LOG(ERROR, TAG, "Adding Gateway Failed as Route cost is more than old");
379             return OC_STACK_ERROR;
380         }
381
382         // Logic to add updated node to Head of list as route cost is 1.
383         if (1 == routeCost && NULL != entry)
384         {
385             OCStackResult res = u_linklist_remove(*gatewayTable, &destNode);
386             if (OC_STACK_OK != res)
387             {
388                 OC_LOG(ERROR, TAG, "Removing node failed");
389             }
390             else
391             {
392                 res = u_linklist_add_head(*gatewayTable, (void *)entry);
393                 if (OC_STACK_OK != res)
394                 {
395                     OC_LOG(ERROR, TAG, "Adding node to head failed");
396                 }
397             }
398         }
399     }
400     else
401     {
402         // Filling new Entry
403         RTMGatewayEntry_t *hopEntry = (RTMGatewayEntry_t *)OICCalloc(1, sizeof(RTMGatewayEntry_t));
404         if (NULL == hopEntry)
405         {
406             OC_LOG(ERROR, TAG, "Calloc failed for hop entry");
407             return OC_STACK_ERROR;
408         }
409
410         hopEntry->destination = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
411         if (NULL == hopEntry->destination)
412         {
413             OC_LOG(ERROR, TAG, "Calloc failed for hop entry destination");
414             OICFree(hopEntry);
415             return OC_STACK_ERROR;
416         }
417
418         hopEntry->destination->gatewayId = gatewayId;
419         if (NULL != destInterfaces && strlen((*destInterfaces).destIntfAddr.addr) > 0)
420         {
421             hopEntry->destination->destIntfAddr = u_arraylist_create();
422             RTMDestIntfInfo_t *destAdr =
423                 (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
424             if (NULL == destAdr)
425             {
426                 OC_LOG(ERROR, TAG, "Calloc failed for destAdr");
427                 u_arraylist_free(&(hopEntry->destination->destIntfAddr));
428                 OICFree(hopEntry->destination);
429                 OICFree(hopEntry);
430                 return OC_STACK_ERROR;
431             }
432
433             *destAdr = *destInterfaces;
434             destAdr->timeElapsed = RTMGetCurrentTime();
435             destAdr->isValid = true;
436             u_arraylist_add(hopEntry->destination->destIntfAddr, (void *)destAdr);
437         }
438         else
439         {
440             hopEntry->destination->destIntfAddr = NULL;
441         }
442
443         hopEntry->routeCost = routeCost;
444         // Mapped nextHop gateway to another entries having gateway as destination.
445         if (NULL != gatewayNodeMap)
446         {
447             hopEntry->nextHop = gatewayNodeMap;
448         }
449         else if (1 == routeCost)
450         {
451             hopEntry->nextHop = NULL;
452         }
453         else
454         {
455             OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop is invalid");
456             while (u_arraylist_length(hopEntry->destination->destIntfAddr) > 0)
457             {
458                 RTMDestIntfInfo_t *data =
459                     u_arraylist_remove(hopEntry->destination->destIntfAddr, 0);
460                 OICFree(data);
461             }
462             u_arraylist_free(&(hopEntry->destination->destIntfAddr));
463             OICFree(hopEntry->destination);
464             OICFree(hopEntry);
465
466             return OC_STACK_ERROR;
467         }
468
469         OCStackResult ret = OC_STACK_OK;
470         if (hopEntry->routeCost == 1)
471         {
472             ret = u_linklist_add_head(*gatewayTable, (void *)hopEntry);
473         }
474         else
475         {
476             ret = u_linklist_add(*gatewayTable, (void *)hopEntry);
477         }
478
479         if (OC_STACK_OK != ret)
480         {
481             OC_LOG(ERROR, TAG, "Adding Gateway Entry to Routing Table failed");
482             while (u_arraylist_length(hopEntry->destination->destIntfAddr) > 0)
483             {
484                 RTMDestIntfInfo_t *data = u_arraylist_remove(hopEntry->destination->destIntfAddr, 0);
485                 OICFree(data);
486             }
487             u_arraylist_free(&(hopEntry->destination->destIntfAddr));
488             OICFree(hopEntry->destination);
489             OICFree(hopEntry);
490             return OC_STACK_ERROR;
491         }
492     }
493     OC_LOG(DEBUG, TAG, "OUT");
494     return OC_STACK_OK;
495 }
496
497 OCStackResult RTMAddEndpointEntry(uint16_t *endpointId, const CAEndpoint_t *destAddr,
498                                   u_linklist_t **endpointTable)
499 {
500     OC_LOG(DEBUG, TAG, "IN");
501     RM_NULL_CHECK_WITH_RET(endpointId, TAG, "endpointId");
502     RM_NULL_CHECK_WITH_RET(destAddr, TAG, "destAddr");
503     RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
504     if (NULL == *endpointTable)
505     {
506         *endpointTable = u_linklist_create();
507     }
508
509     u_linklist_iterator_t *iterTable = NULL;
510     u_linklist_init_iterator(*endpointTable, &iterTable);
511     // Iterate over gateway list to find if already entry with this gatewayid is present.
512     while (NULL != iterTable)
513     {
514         RTMEndpointEntry_t *entry =
515             (RTMEndpointEntry_t *) u_linklist_get_data(iterTable);
516
517         if (NULL != entry && (0 == memcmp(destAddr->addr, entry->destIntfAddr.addr,
518                               strlen(entry->destIntfAddr.addr)))
519             && destAddr->port == entry->destIntfAddr.port)
520         {
521             *endpointId = entry->endpointId;
522             OC_LOG(ERROR, TAG, "Adding failed as Enpoint Entry Already present in Table");
523             return OC_STACK_DUPLICATE_REQUEST;
524         }
525         u_linklist_get_next(&iterTable);
526     }
527
528     // Filling Entry.
529     RTMEndpointEntry_t *hopEntry = (RTMEndpointEntry_t *)OICCalloc(1, sizeof(RTMEndpointEntry_t));
530
531     if (NULL == hopEntry)
532     {
533        OC_LOG(ERROR, TAG, "Malloc failed for hop entry");
534        return OC_STACK_ERROR;
535     }
536
537     hopEntry->endpointId = *endpointId;
538     hopEntry->destIntfAddr = *destAddr;
539
540     OCStackResult ret = u_linklist_add(*endpointTable, (void *)hopEntry);
541     if (OC_STACK_OK != ret)
542     {
543        OC_LOG(ERROR, TAG, "Adding Enpoint Entry to Routing Table failed");
544        OICFree(hopEntry);
545        return OC_STACK_ERROR;
546     }
547     OC_LOG(DEBUG, TAG, "OUT");
548     return OC_STACK_OK;
549 }
550
551 OCStackResult RTMAddObserver(uint32_t obsID, CAEndpoint_t devAddr, u_linklist_t **gatewayTable)
552 {
553     OC_LOG(DEBUG, TAG, "IN");
554     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
555     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
556
557     u_linklist_iterator_t *iterTable = NULL;
558     u_linklist_init_iterator(*gatewayTable, &iterTable);
559     while (NULL != iterTable)
560     {
561         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
562
563         for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
564         {
565             RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
566             if (NULL != destCheck &&
567                 (0 == memcmp(destCheck->destIntfAddr.addr, devAddr.addr, strlen(devAddr.addr)))
568                 && devAddr.port == destCheck->destIntfAddr.port)
569             {
570                 destCheck->observerId = obsID;
571                 OC_LOG(DEBUG, TAG, "OUT");
572                 return OC_STACK_OK;
573             }
574         }
575         u_linklist_get_next(&iterTable);
576     }
577     OC_LOG(DEBUG, TAG, "OUT");
578     return OC_STACK_ERROR;
579 }
580
581 bool RTMIsObserverPresent(CAEndpoint_t devAddr, OCObservationId *obsID,
582                           const u_linklist_t *gatewayTable)
583 {
584     OC_LOG(DEBUG, TAG, "IN");
585     if (NULL == obsID)
586     {
587         OC_LOG(ERROR, TAG, "obsID is null");
588         return false;
589     }
590
591     if (NULL == gatewayTable)
592     {
593         OC_LOG(ERROR, TAG, "gatewayTable is null");
594         return false;
595     }
596
597     u_linklist_iterator_t *iterTable = NULL;
598     u_linklist_init_iterator(gatewayTable, &iterTable);
599     while (NULL != iterTable)
600     {
601         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
602         if (NULL == entry && NULL == entry->destination)
603         {
604             OC_LOG(ERROR, TAG, "entry is NULL");
605             return false;
606         }
607         for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
608         {
609             RTMDestIntfInfo_t *destCheck =
610                 u_arraylist_get(entry->destination->destIntfAddr, i);
611             if (NULL != destCheck && (0 == memcmp(destCheck->destIntfAddr.addr, devAddr.addr,
612                                       strlen(devAddr.addr)))
613                 && devAddr.port == destCheck->destIntfAddr.port && 0 != destCheck->observerId)
614             {
615                 *obsID = destCheck->observerId;
616                 OC_LOG(DEBUG, TAG, "OUT");
617                 return true;
618             }
619         }
620         u_linklist_get_next(&iterTable);
621     }
622     OC_LOG(DEBUG, TAG, "OUT");
623     return false;
624 }
625
626 OCStackResult RTMRemoveGatewayEntry(uint32_t gatewayId, u_linklist_t **removedGatewayNodes,
627                                     u_linklist_t **gatewayTable)
628 {
629     OC_LOG(DEBUG, TAG, "IN");
630     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
631     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
632
633     u_linklist_iterator_t *iterTable = NULL;
634
635     // if link list is not null we can directly add removed nodes to it instead of creating everytime.
636     if (NULL == *removedGatewayNodes)
637     {
638         *removedGatewayNodes = u_linklist_create();
639     }
640     OCStackResult ret = OC_STACK_OK;
641     u_linklist_init_iterator(*gatewayTable, &iterTable);
642     while (NULL != iterTable)
643     {
644         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
645         if (NULL == entry || NULL == entry->destination)
646         {
647             u_linklist_get_next(&iterTable);
648             continue;
649         }
650
651         if (gatewayId == entry->destination->gatewayId || (NULL != entry->nextHop &&
652             (gatewayId == entry->nextHop->gatewayId)))
653         {
654             OC_LOG_V(DEBUG, TAG, "Removing the gateway entry: %u", entry->destination->gatewayId);
655             ret = u_linklist_remove(*gatewayTable, &iterTable);
656             if (OC_STACK_OK != ret)
657             {
658                OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
659                return OC_STACK_ERROR;
660             }
661             else
662             {
663                 u_linklist_add(*removedGatewayNodes, (void *)entry);
664             }
665         }
666         else
667         {
668             u_linklist_get_next(&iterTable);
669         }
670     }
671     OC_LOG(DEBUG, TAG, "RTMRemoveGatewayEntry OUT");
672     return OC_STACK_OK;
673 }
674
675 OCStackResult RTMRemoveGatewayDestEntry(uint32_t gatewayId, uint32_t nextHop,
676                                         const RTMDestIntfInfo_t *destInfAdr,
677                                         RTMGatewayEntry_t **existEntry, u_linklist_t **gatewayTable)
678 {
679     OC_LOG(DEBUG, TAG, "IN");
680     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
681     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
682     RM_NULL_CHECK_WITH_RET(destInfAdr, TAG, "destInfAdr");
683
684     u_linklist_iterator_t *iterTable = NULL;
685
686     OCStackResult ret = -1;
687     u_linklist_init_iterator(*gatewayTable, &iterTable);
688     while (NULL != iterTable)
689     {
690         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
691         if (NULL == entry)
692         {
693             u_linklist_get_next(&iterTable);
694             continue;
695         }
696
697         // Update the time for NextHop entry.
698         if (NULL != entry->destination && nextHop == entry->destination->gatewayId)
699         {
700             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
701             {
702                 RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
703                 if (0 == memcmp(destCheck->destIntfAddr.addr, destInfAdr->destIntfAddr.addr,
704                     strlen(destInfAdr->destIntfAddr.addr))
705                     && destInfAdr->destIntfAddr.port == destCheck->destIntfAddr.port)
706                 {
707                     destCheck->timeElapsed =  RTMGetCurrentTime();
708                     break;
709                 }
710             }
711         }
712
713         // Remove node with given gatewayid and nextHop if not found update exist entry.
714         if (NULL != entry->destination && (gatewayId == entry->destination->gatewayId))
715         {
716             OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", entry->destination->gatewayId);
717             if (NULL != entry->nextHop && nextHop == entry->nextHop->gatewayId)
718             {
719                 ret = u_linklist_remove(*gatewayTable, &iterTable);
720                 if (OC_STACK_OK != ret)
721                 {
722                    OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
723                    return OC_STACK_ERROR;
724                 }
725                 OICFree(entry);
726                 return OC_STACK_OK;
727             }
728
729             *existEntry = entry;
730             OC_LOG(DEBUG, TAG, "OUT");
731             return OC_STACK_ERROR;
732         }
733
734         u_linklist_get_next(&iterTable);
735     }
736     OC_LOG(DEBUG, TAG, "OUT");
737     return OC_STACK_ERROR;
738 }
739
740 OCStackResult RTMRemoveEndpointEntry(uint16_t endpointId, u_linklist_t **endpointTable)
741 {
742     OC_LOG(DEBUG, TAG, "IN");
743     RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
744     RM_NULL_CHECK_WITH_RET(*endpointTable, TAG, "*endpointTable");
745
746     u_linklist_iterator_t *iterTable = NULL;
747     u_linklist_init_iterator(*endpointTable, &iterTable);
748     while (NULL != iterTable)
749     {
750         RTMEndpointEntry_t *entry = u_linklist_get_data(iterTable);
751         if (NULL !=  entry && endpointId == entry->endpointId)
752         {
753             OCStackResult ret = u_linklist_remove(*endpointTable, &iterTable);
754             if (OC_STACK_OK != ret)
755             {
756                OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
757                return OC_STACK_ERROR;
758             }
759             OICFree(entry);
760         }
761         else
762         {
763             u_linklist_get_next(&iterTable);
764         }
765     }
766     OC_LOG(DEBUG, TAG, "OUT");
767     return OC_STACK_OK;
768 }
769
770 OCStackResult RTMRemoveGateways(u_linklist_t **gatewayTable)
771 {
772     OC_LOG(DEBUG, TAG, "IN");
773
774     if (NULL == gatewayTable || NULL == *gatewayTable)
775     {
776         OC_LOG(DEBUG, TAG, "OUT");
777         return OC_STACK_OK;
778     }
779
780     OCStackResult ret = RTMFreeGatewayRouteTable(gatewayTable);
781     if (OC_STACK_OK != ret)
782     {
783         OC_LOG(ERROR, TAG, "Removing Gateways failed");
784         return ret;
785     }
786     OC_LOG(DEBUG, TAG, "OUT");
787     return OC_STACK_OK;
788 }
789
790 OCStackResult RTMRemoveEndpoints(u_linklist_t **endpointTable)
791 {
792     OC_LOG(DEBUG, TAG, "IN");
793     if (NULL == endpointTable || NULL == *endpointTable)
794     {
795         OC_LOG(DEBUG, TAG, "OUT");
796         return OC_STACK_OK;
797     }
798
799     OCStackResult ret = RTMFreeEndpointRouteTable(endpointTable);
800     if (OC_STACK_OK != ret)
801     {
802         OC_LOG(ERROR, TAG, "Freeing Endpoints failed");
803         return OC_STACK_ERROR;
804     }
805     OC_LOG(DEBUG, TAG, "OUT");
806     return OC_STACK_OK;
807 }
808
809 void RTMFreeGateway(RTMGatewayId_t *gateway, u_linklist_t **gatewayTable)
810 {
811     OC_LOG(DEBUG, TAG, "IN");
812     RM_NULL_CHECK_VOID(gateway, TAG, "gateway");
813     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
814     RM_NULL_CHECK_VOID(*gatewayTable, TAG, "*gatewayTable");
815     while (0 < u_arraylist_length(gateway->destIntfAddr))
816     {
817         void *data = u_arraylist_remove(gateway->destIntfAddr, 0);
818         OICFree(data);
819     }
820     u_arraylist_free(&(gateway->destIntfAddr));
821     OICFree(gateway);
822     OC_LOG(DEBUG, TAG, "OUT");
823 }
824
825 void RTMGetNeighbours(u_linklist_t **neighbourNodes, const u_linklist_t *gatewayTable)
826 {
827     OC_LOG(DEBUG, TAG, "IN");
828     RM_NULL_CHECK_VOID(neighbourNodes, TAG, "neighbourNodes");
829     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
830
831     *neighbourNodes = u_linklist_create();
832     u_linklist_iterator_t *iterTable = NULL;
833     u_linklist_init_iterator(gatewayTable, &iterTable);
834     while (NULL != iterTable)
835     {
836         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
837         if (NULL != entry && 1 == entry->routeCost)
838         {
839             u_linklist_add(*neighbourNodes, (void *)entry);
840         }
841         else if (NULL != entry && 1 < entry->routeCost)
842         {
843             OC_LOG(DEBUG, TAG, "OUT");
844             return;
845         }
846
847         u_linklist_get_next(&iterTable);
848     }
849     OC_LOG(DEBUG, TAG, "OUT");
850 }
851
852 RTMGatewayId_t *RTMGetNextHop(uint32_t gatewayId, const u_linklist_t *gatewayTable)
853 {
854     OC_LOG(DEBUG, TAG, "IN");
855     if (0 == gatewayId)
856     {
857         OC_LOG(ERROR, TAG, "gatewayId is invalid");
858         return NULL;
859     }
860
861     if (NULL == gatewayTable)
862     {
863         OC_LOG(ERROR, TAG, "gatewayTable is null");
864         return NULL;
865     }
866
867     u_linklist_iterator_t *iterTable = NULL;
868     u_linklist_init_iterator(gatewayTable, &iterTable);
869     while (NULL != iterTable)
870     {
871         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
872         if (NULL != entry && gatewayId == entry->destination->gatewayId)
873         {
874             if (1 == entry->routeCost)
875             {
876                 OC_LOG(DEBUG, TAG, "OUT");
877                 return entry->destination;
878             }
879             OC_LOG(DEBUG, TAG, "OUT");
880             return entry->nextHop;
881         }
882         u_linklist_get_next(&iterTable);
883     }
884     OC_LOG(DEBUG, TAG, "OUT");
885     return NULL;
886 }
887
888 CAEndpoint_t *RTMGetEndpointEntry(uint16_t endpointId, const u_linklist_t *endpointTable)
889 {
890     OC_LOG(DEBUG, TAG, "IN");
891     if (NULL == endpointTable)
892     {
893         OC_LOG(ERROR, TAG, "endpointTable is null");
894         return NULL;
895     }
896
897     u_linklist_iterator_t *iterTable = NULL;
898     u_linklist_init_iterator(endpointTable, &iterTable);
899
900     while (NULL != iterTable)
901     {
902         RTMEndpointEntry_t *entry = u_linklist_get_data(iterTable);
903         if (NULL != entry && (endpointId == entry->endpointId))
904         {
905             OC_LOG(DEBUG, TAG, "OUT");
906             return &(entry->destIntfAddr);
907         }
908         u_linklist_get_next(&iterTable);
909     }
910     OC_LOG(DEBUG, TAG, "OUT");
911     return NULL;
912 }
913
914 void RTMGetObserverList(OCObservationId **obsList, uint8_t *obsListLen,
915                         const u_linklist_t *gatewayTable)
916 {
917     OC_LOG(DEBUG, TAG, "IN");
918     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
919     RM_NULL_CHECK_VOID(obsList, TAG, "obsList");
920
921     *obsList = (OCObservationId *) OICCalloc(MAX_OBSERVER_LIST_LENGTH, sizeof(OCObservationId));
922     u_linklist_iterator_t *iterTable = NULL;
923     u_linklist_init_iterator(gatewayTable, &iterTable);
924     uint8_t len = 0;
925     while (NULL != iterTable)
926     {
927         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
928         for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
929         {
930             RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
931             if (NULL == destCheck)
932             {
933                 OC_LOG(ERROR, TAG, "destCheck is null");
934                 return;
935             }
936             if (0 != destCheck->observerId)
937             {
938                 OC_LOG_V(DEBUG, TAG, "Observer ID is %d", destCheck->observerId);
939                 *(*obsList + len) = destCheck->observerId;
940                 len++;
941             }
942             if (MAX_OBSERVER_LIST_LENGTH < len)
943             {
944                 *obsList = (OCObservationId *) OICRealloc((void *)*obsList,
945                            (sizeof(OCObservationId) * (len + 1)));
946             }
947             break;
948         }
949         u_linklist_get_next(&iterTable);
950     }
951
952     *obsListLen = len;
953     OC_LOG(DEBUG, TAG, "OUT");
954 }
955
956 OCStackResult RTMUpdateDestinationIntfAdr(uint32_t gatewayId, RTMDestIntfInfo_t destInterfaces,
957                                           bool addAdr, u_linklist_t **gatewayTable)
958 {
959     OC_LOG(DEBUG, TAG, "IN");
960     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
961     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
962
963     u_linklist_iterator_t *iterTable = NULL;
964     u_linklist_init_iterator(*gatewayTable, &iterTable);
965     while (NULL != iterTable)
966     {
967         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
968         if (NULL != entry && NULL != entry->destination &&
969             gatewayId == entry->destination->gatewayId)
970         {
971             if (addAdr)
972             {
973                 for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
974                 {
975                     RTMDestIntfInfo_t *destCheck =
976                         u_arraylist_get(entry->destination->destIntfAddr, i);
977                     if (NULL == destCheck)
978                     {
979                         OC_LOG(ERROR, TAG, "Destination adr get failed");
980                         continue;
981                     }
982
983                     if (0 == memcmp(destCheck->destIntfAddr.addr, destInterfaces.destIntfAddr.addr,
984                         strlen(destInterfaces.destIntfAddr.addr))
985                         && destInterfaces.destIntfAddr.port == destCheck->destIntfAddr.port)
986                     {
987                         destCheck->timeElapsed = RTMGetCurrentTime();
988                         destCheck->isValid = true;
989                         OC_LOG(ERROR, TAG, "destInterfaces already present");
990                         return OC_STACK_ERROR;
991                     }
992                 }
993
994                 RTMDestIntfInfo_t *destAdr =
995                         (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
996                 if (NULL == destAdr)
997                 {
998                     OC_LOG(ERROR, TAG, "Calloc destAdr failed");
999                     return OC_STACK_ERROR;
1000                 }
1001                 *destAdr = destInterfaces;
1002                 destAdr->timeElapsed = RTMGetCurrentTime();
1003                 destAdr->isValid = true;
1004                 bool result =
1005                     u_arraylist_add(entry->destination->destIntfAddr, (void *)destAdr);
1006                 if (!result)
1007                 {
1008                     OC_LOG(ERROR, TAG, "Updating Destinterface address failed");
1009                     OICFree(destAdr);
1010                     return OC_STACK_ERROR;
1011                 }
1012                 OC_LOG(DEBUG, TAG, "OUT");
1013                 return OC_STACK_DUPLICATE_REQUEST;
1014             }
1015
1016             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1017             {
1018                 RTMDestIntfInfo_t *removeAdr =
1019                     u_arraylist_get(entry->destination->destIntfAddr, i);
1020                 if (0 == memcmp(removeAdr->destIntfAddr.addr, destInterfaces.destIntfAddr.addr,
1021                     strlen(destInterfaces.destIntfAddr.addr))
1022                     && destInterfaces.destIntfAddr.port == removeAdr->destIntfAddr.port)
1023                 {
1024                     RTMDestIntfInfo_t *data =
1025                         u_arraylist_remove(entry->destination->destIntfAddr, i);
1026                     OICFree(data);
1027                     break;
1028                 }
1029             }
1030         }
1031         u_linklist_get_next(&iterTable);
1032     }
1033     OC_LOG(DEBUG, TAG, "OUT");
1034     return OC_STACK_OK;
1035 }
1036
1037 OCStackResult RTMUpdateMcastSeqNumber(uint32_t gatewayId, uint16_t seqNum,
1038                                       u_linklist_t **gatewayTable)
1039 {
1040     OC_LOG(DEBUG, TAG, "IN");
1041     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1042     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1043
1044     u_linklist_iterator_t *iterTable = NULL;
1045     u_linklist_init_iterator(*gatewayTable, &iterTable);
1046     while (NULL != iterTable)
1047     {
1048         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
1049         if (NULL != entry && NULL != entry->destination &&
1050             gatewayId == entry->destination->gatewayId)
1051         {
1052             if (0 == entry->mcastMessageSeqNum || entry->mcastMessageSeqNum < seqNum)
1053             {
1054                 entry->mcastMessageSeqNum = seqNum;
1055                 return OC_STACK_OK;
1056             }
1057             else if (entry->mcastMessageSeqNum == seqNum)
1058             {
1059                 return OC_STACK_DUPLICATE_REQUEST;
1060             }
1061             else
1062             {
1063                 return OC_STACK_COMM_ERROR;
1064             }
1065         }
1066         u_linklist_get_next(&iterTable);
1067     }
1068     OC_LOG(DEBUG, TAG, "OUT");
1069     return OC_STACK_OK;
1070 }
1071
1072 uint64_t RTMGetCurrentTime()
1073 {
1074     uint64_t currentTime = 0;
1075
1076 #ifdef __ANDROID__
1077     struct timespec getTs;
1078
1079     clock_gettime(CLOCK_MONOTONIC, &getTs);
1080
1081     currentTime = getTs.tv_sec;
1082 #elif defined __ARDUINO__
1083     currentTime = millis() / 1000;
1084 #else
1085 #if _POSIX_TIMERS > 0
1086     struct timespec ts;
1087     clock_gettime(CLOCK_MONOTONIC, &ts);
1088     currentTime = ts.tv_sec;
1089 #else
1090     struct timeval tv;
1091     gettimeofday(&tv, NULL);
1092     currentTime = tv.tv_sec;
1093 #endif
1094 #endif
1095     return currentTime;
1096 }
1097
1098 OCStackResult RTMUpdateDestAddrValidity(u_linklist_t **invalidTable, u_linklist_t **gatewayTable)
1099 {
1100     OC_LOG(DEBUG, TAG, "IN");
1101     RM_NULL_CHECK_WITH_RET(invalidTable, TAG, "invalidTable");
1102     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1103     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1104
1105     *invalidTable = u_linklist_create();
1106     u_linklist_iterator_t *iterTable = NULL;
1107     uint64_t presentTime = RTMGetCurrentTime();
1108
1109     u_linklist_init_iterator(*gatewayTable, &iterTable);
1110     while (NULL != iterTable)
1111     {
1112         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
1113         if (NULL == entry)
1114         {
1115             u_linklist_get_next(&iterTable);
1116             continue;
1117         }
1118         else if (1 == entry->routeCost)
1119         {
1120             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1121             {
1122                 RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
1123                 if (GATEWAY_ALIVE_TIMEOUT < (presentTime - destCheck->timeElapsed))
1124                 {
1125                     destCheck->isValid = false;
1126                     u_linklist_add(*invalidTable, (void *)destCheck);
1127                 }
1128             }
1129         }
1130         else if (1 < entry->routeCost)
1131         {
1132             break;
1133         }
1134         u_linklist_get_next(&iterTable);
1135     }
1136     OC_LOG(DEBUG, TAG, "OUT");
1137     return OC_STACK_OK;
1138 }
1139
1140 OCStackResult RTMRemoveInvalidGateways(u_linklist_t **invalidTable, u_linklist_t **gatewayTable)
1141 {
1142     OC_LOG(DEBUG, TAG, "IN");
1143     RM_NULL_CHECK_WITH_RET(invalidTable, TAG, "invalidTable");
1144     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1145     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1146
1147     *invalidTable = u_linklist_create();
1148
1149     u_linklist_iterator_t *iterTable = NULL;
1150     u_linklist_init_iterator(*gatewayTable, &iterTable);
1151     while (iterTable != NULL)
1152     {
1153         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
1154
1155         if (NULL == entry)
1156         {
1157             u_linklist_get_next(&iterTable);
1158             continue;
1159         }
1160         else if (NULL != entry->destination && (1 == entry->routeCost))
1161         {
1162             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1163             {
1164                 RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
1165                 if (!destCheck->isValid)
1166                 {
1167                     void *data = u_arraylist_remove(entry->destination->destIntfAddr, i);
1168                     OICFree(data);
1169                     i--;
1170                 }
1171             }
1172
1173             if (0 == u_arraylist_length(entry->destination->destIntfAddr))
1174             {
1175                 u_arraylist_free(&(entry->destination->destIntfAddr));
1176                 OCStackResult res =
1177                     RTMRemoveGatewayEntry(entry->destination->gatewayId, invalidTable, gatewayTable);
1178                 if (OC_STACK_OK != res)
1179                 {
1180                     OC_LOG(ERROR, TAG, "Removing Entries failed");
1181                     return OC_STACK_ERROR;
1182                 }
1183                 u_linklist_get_next(&iterTable);
1184             }
1185             else
1186             {
1187                 u_linklist_get_next(&iterTable);
1188             }
1189         }
1190         else if (1 < entry->routeCost)
1191         {
1192             break;
1193         }
1194         else
1195         {
1196             u_linklist_get_next(&iterTable);
1197         }
1198     }
1199     OC_LOG(DEBUG, TAG, "OUT");
1200     return OC_STACK_OK;
1201 }
1202
1203 OCStackResult RTMUpdateEntryParameters(uint32_t gatewayId, uint32_t seqNum,
1204                                        const RTMDestIntfInfo_t *destAdr, u_linklist_t **gatewayTable,
1205                                        bool forceUpdate)
1206 {
1207     OC_LOG(DEBUG, TAG, "IN");
1208     RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
1209     RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
1210     RM_NULL_CHECK_WITH_RET(destAdr, TAG, "destAdr");
1211
1212     u_linklist_iterator_t *iterTable = NULL;
1213     u_linklist_init_iterator(*gatewayTable, &iterTable);
1214     while (NULL != iterTable)
1215     {
1216         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
1217
1218         if (NULL == entry)
1219         {
1220             u_linklist_get_next(&iterTable);
1221             continue;
1222         }
1223         if (NULL != entry->destination && gatewayId == entry->destination->gatewayId)
1224         {
1225             for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
1226             {
1227                 RTMDestIntfInfo_t *destCheck =
1228                     u_arraylist_get(entry->destination->destIntfAddr, i);
1229                 if (NULL != destCheck &&
1230                     (0 == memcmp(destCheck->destIntfAddr.addr, destAdr->destIntfAddr.addr,
1231                      strlen(destAdr->destIntfAddr.addr)))
1232                      && destAdr->destIntfAddr.port == destCheck->destIntfAddr.port)
1233                 {
1234                     destCheck->timeElapsed = RTMGetCurrentTime();
1235                     destCheck->isValid = true;
1236                 }
1237             }
1238
1239             if (0 != entry->seqNum && seqNum == entry->seqNum)
1240             {
1241                 return OC_STACK_DUPLICATE_REQUEST;
1242             }
1243             else if (0 != entry->seqNum && seqNum != ((entry->seqNum) + 1) && !forceUpdate)
1244             {
1245                 return OC_STACK_COMM_ERROR;
1246             }
1247             else
1248             {
1249                 entry->seqNum = seqNum;
1250                 OC_LOG(DEBUG, TAG, "OUT");
1251                 return OC_STACK_OK;
1252             }
1253         }
1254         u_linklist_get_next(&iterTable);
1255     }
1256     OC_LOG(DEBUG, TAG, "OUT");
1257     return OC_STACK_OK;
1258 }
1259
1260 void RTMPrintTable(const u_linklist_t *gatewayTable, const u_linklist_t *endpointTable)
1261 {
1262     RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
1263     OC_LOG(DEBUG, RM_TAG, "=================Gateway List table============================\n");
1264     u_linklist_iterator_t *iterTable = NULL;
1265     u_linklist_init_iterator(gatewayTable, &iterTable);
1266     while (NULL != iterTable)
1267     {
1268         RTMGatewayEntry_t *hop =
1269             (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
1270         if (NULL == hop)
1271         {
1272             OC_LOG(ERROR, RM_TAG, "Printing Table Failed");
1273             return;
1274         }
1275         if (NULL == hop->nextHop || 0 == hop->nextHop->gatewayId)
1276         {
1277             OC_LOG_V(DEBUG, RM_TAG, "\nDestination : %u\nNextHop : (null)\nHopCount : %d",
1278                      hop->destination->gatewayId, hop->routeCost);
1279             OC_LOG_V(DEBUG, RM_TAG, "\nSequence Number :%u", hop->seqNum);
1280         }
1281         else
1282         {
1283             OC_LOG_V(DEBUG, RM_TAG, "\nDestination : %u\nNextHop : %u\nHopCount : %d",
1284                      hop->destination->gatewayId, hop->nextHop->gatewayId, hop->routeCost);
1285             OC_LOG_V(DEBUG, RM_TAG, "\nSequence Number :%u", hop->seqNum);
1286         }
1287         if (1 == hop->routeCost && NULL != hop->destination &&
1288             hop->destination->destIntfAddr != NULL)
1289         {
1290             for (uint32_t i = 0; i < u_arraylist_length(hop->destination->destIntfAddr); i++)
1291             {
1292                 RTMDestIntfInfo_t *dest = u_arraylist_get(hop->destination->destIntfAddr, i);
1293                 if (NULL != dest)
1294                 {
1295                     OC_LOG_V(DEBUG, RM_TAG, "\nDestination interface addresses: %s Port : %d Obs ID: %d",
1296                              dest->destIntfAddr.addr, dest->destIntfAddr.port, dest->observerId);
1297                     OC_LOG_V(DEBUG, RM_TAG, "Validity: %d", dest->isValid);
1298                 }
1299             }
1300         }
1301         OC_LOG(DEBUG, RM_TAG, "********************************************\n");
1302         u_linklist_get_next(&iterTable);
1303     }
1304
1305     OC_LOG(DEBUG, RM_TAG, "=================Endpoint List table============================\n");
1306     u_linklist_iterator_t *iterEndpointTable = NULL;
1307     u_linklist_init_iterator(endpointTable, &iterEndpointTable);
1308
1309     // Iterate over endpoint list to find if already entry for gatewayid is present.
1310     while (NULL != iterEndpointTable)
1311     {
1312         RTMEndpointEntry_t *hop =
1313             (RTMEndpointEntry_t *) u_linklist_get_data(iterEndpointTable);
1314         if (NULL == hop)
1315         {
1316             OC_LOG(ERROR, RM_TAG, "Printing Table Failed");
1317             return;
1318         }
1319         OC_LOG_V(DEBUG, RM_TAG, "EndpointId : %u\naddr : %s Port : %d",
1320                   hop->endpointId, hop->destIntfAddr.addr, hop->destIntfAddr.port);
1321
1322         OC_LOG(DEBUG, RM_TAG, "********************************************\n");
1323         u_linklist_get_next(&iterEndpointTable);
1324     }
1325 }