Contiki-NG
tsch-roots.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, Amber Agriculture
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. Neither the name of the Institute nor the names of its contributors
13  * may be used to endorse or promote products derived from this software
14  * without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 /**
31  * \file
32  * Keeps track of which neighbors advertise themselves as roots.
33  * This information is used by the Orchestra root rule.
34  *
35  * \author
36  * Atis Elsts <atis.elsts@gmail.com>
37  */
38 
39 #include "contiki.h"
40 #include "lib/list.h"
41 #include "lib/memb.h"
42 #include "net/mac/tsch/tsch.h"
43 
44 /* Log configuration */
45 #include "sys/log.h"
46 #define LOG_MODULE "TSCH"
47 #define LOG_LEVEL LOG_LEVEL_MAC
48 
49 /*---------------------------------------------------------------------------*/
50 #if BUILD_WITH_ORCHESTRA
51 /*---------------------------------------------------------------------------*/
52 #define TSCH_MAX_ROOT_NODES 5
53 #define ROOT_ALIVE_TIME_SECONDS (2 * 60 * 60) /* 2h timeout */
54 #define PERIODIC_PROCESSING_TICKS (60 * CLOCK_SECOND)
55 
56 /*---------------------------------------------------------------------------*/
57 /* TSCH roots data structure */
58 struct tsch_root_info {
59  struct tsch_root_info *next;
60  linkaddr_t address;
61  clock_time_t last_seen_seconds; /* the time when this was last seen */
62 };
63 /*---------------------------------------------------------------------------*/
64 MEMB(tsch_root_memb, struct tsch_root_info, TSCH_MAX_ROOT_NODES);
65 LIST(tsch_roots);
66 static struct ctimer periodic_timer;
67 /*---------------------------------------------------------------------------*/
68 void
69 tsch_roots_add_address(const linkaddr_t *new_root_address)
70 {
71  struct tsch_root_info *root;
72 
73  LOG_INFO("add root address ");
74  LOG_INFO_LLADDR(new_root_address);
75  LOG_INFO_("\n");
76 
77  /* search for an existing entry */
78  root = list_head(tsch_roots);
79  while(root != NULL) {
80  if(linkaddr_cmp(new_root_address, &root->address)) {
81  break;
82  }
83  root = root->next;
84  }
85 
86  if(root == NULL) {
87  /* add a new entry */
88  if((root = memb_alloc(&tsch_root_memb)) == NULL) {
89  LOG_ERR("failed to add root ");
90  LOG_ERR_LLADDR(new_root_address);
91  LOG_ERR_("\n");
92  return;
93  }
94  linkaddr_copy(&root->address, new_root_address);
95  list_add(tsch_roots, root);
96 
97  /* make sure there is a link in the schedule */
98  TSCH_CALLBACK_ROOT_NODE_UPDATED(&root->address, 1);
99  }
100 
101  /* update the entry */
102  root->last_seen_seconds = clock_seconds();
103 }
104 /*---------------------------------------------------------------------------*/
105 void
106 tsch_roots_set_self_to_root(uint8_t is_root)
107 {
108  TSCH_CALLBACK_ROOT_NODE_UPDATED(&linkaddr_node_addr, is_root);
109 }
110 /*---------------------------------------------------------------------------*/
111 int
112 tsch_roots_is_root(const linkaddr_t *address)
113 {
114  struct tsch_root_info *root;
115  if(address == NULL) {
116  return 0;
117  }
118 
119  root = list_head(tsch_roots);
120  while(root != NULL) {
121  if(linkaddr_cmp(address, &root->address)) {
122  return 1;
123  }
124  root = root->next;
125  }
126  return 0;
127 }
128 /*---------------------------------------------------------------------------*/
129 static void
130 periodic(void *ptr)
131 {
132  struct tsch_root_info *root;
133  struct tsch_root_info *next;
134  clock_time_t now;
135 
136  now = clock_seconds();
137  root = list_head(tsch_roots);
138  while(root != NULL) {
139  next = root->next;
140  if((int32_t)(root->last_seen_seconds + ROOT_ALIVE_TIME_SECONDS - now) < 0) {
141  /* the root info has become obsolete; remove its scheduled link */
142  LOG_INFO("remove root address ");
143  LOG_INFO_LLADDR(&root->address);
144  LOG_INFO_("\n");
145  TSCH_CALLBACK_ROOT_NODE_UPDATED(&root->address, 0);
146  /* remove itself from the table */
147  list_remove(tsch_roots, root);
148  memb_free(&tsch_root_memb, root);
149  }
150  root = next;
151  }
152 
153  /* schedule the next time */
154  ctimer_set(&periodic_timer, PERIODIC_PROCESSING_TICKS, periodic, NULL);
155 }
156 /*---------------------------------------------------------------------------*/
157 void
158 tsch_roots_init(void)
159 {
160  list_init(tsch_roots);
161  memb_init(&tsch_root_memb);
162  ctimer_set(&periodic_timer, PERIODIC_PROCESSING_TICKS, periodic, NULL);
163 }
164 /*---------------------------------------------------------------------------*/
165 #else /* BUILD_WITH_ORCHESTRA */
166 /*---------------------------------------------------------------------------*/
167 void
168 tsch_roots_add_address(const linkaddr_t *root_address)
169 {
170 }
171 void
173 {
174 }
175 int
176 tsch_roots_is_root(const linkaddr_t *address)
177 {
178  return 0;
179 }
180 void
182 {
183 }
184 /*---------------------------------------------------------------------------*/
185 #endif /* BUILD_WITH_ORCHESTRA */
186 /*---------------------------------------------------------------------------*/
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:78
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:130
void tsch_roots_add_address(const linkaddr_t *root_address)
Add address as a potential RPL root that is a single-hop neighbor in the TSCH network.
Definition: tsch-roots.c:168
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
int tsch_roots_is_root(const linkaddr_t *address)
Tests whether a given address belongs to a single-hop reachable root node in this network...
Definition: tsch-roots.c:176
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
Main API declarations for TSCH.
void tsch_roots_init(void)
Initialize the list of RPL network roots.
Definition: tsch-roots.c:181
Memory block allocation routines.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
Definition: linkaddr.c:63
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
#define LIST(name)
Declare a linked list.
Definition: list.h:89
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
void tsch_roots_set_self_to_root(uint8_t is_root)
Set the root status of the local node.
Definition: tsch-roots.c:172
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
Header file for the logging system
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90