1 /*
2  * Copyright (C) 2003 Yasuhiro Ohara
3  *
4  * This file is part of GNU Zebra.
5  *
6  * GNU Zebra is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2, or (at your option) any
9  * later version.
10  *
11  * GNU Zebra is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; see the file COPYING; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <zebra.h>
22 
23 #include "memory.h"
24 #include "log.h"
25 #include "command.h"
26 #include "prefix.h"
27 #include "table.h"
28 #include "vty.h"
29 
30 #include "ospf6_proto.h"
31 #include "ospf6_lsa.h"
32 #include "ospf6_lsdb.h"
33 #include "ospf6_route.h"
34 #include "ospf6d.h"
35 #include "bitfield.h"
36 
ospf6_lsdb_create(void * data)37 struct ospf6_lsdb *ospf6_lsdb_create(void *data)
38 {
39 	struct ospf6_lsdb *lsdb;
40 
41 	lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb));
42 	memset(lsdb, 0, sizeof(struct ospf6_lsdb));
43 
44 	lsdb->data = data;
45 	lsdb->table = route_table_init();
46 	return lsdb;
47 }
48 
ospf6_lsdb_delete(struct ospf6_lsdb * lsdb)49 void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb)
50 {
51 	if (lsdb != NULL) {
52 		ospf6_lsdb_remove_all(lsdb);
53 		route_table_finish(lsdb->table);
54 		XFREE(MTYPE_OSPF6_LSDB, lsdb);
55 	}
56 }
57 
ospf6_lsdb_set_key(struct prefix_ipv6 * key,const void * value,int len)58 static void ospf6_lsdb_set_key(struct prefix_ipv6 *key, const void *value,
59 			       int len)
60 {
61 	assert(key->prefixlen % 8 == 0);
62 
63 	memcpy((caddr_t)&key->prefix + key->prefixlen / 8, (caddr_t)value, len);
64 	key->family = AF_INET6;
65 	key->prefixlen += len * 8;
66 }
67 
68 #ifdef DEBUG
_lsdb_count_assert(struct ospf6_lsdb * lsdb)69 static void _lsdb_count_assert(struct ospf6_lsdb *lsdb)
70 {
71 	struct ospf6_lsa *debug;
72 	unsigned int num = 0;
73 	for (ALL_LSDB(lsdb, debug))
74 		num++;
75 
76 	if (num == lsdb->count)
77 		return;
78 
79 	zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb,
80 		   lsdb->count, num);
81 	for (ALL_LSDB(lsdb, debug))
82 		zlog_debug("%s lsdb[%p]", debug->name, debug->lsdb);
83 	zlog_debug("DUMP END");
84 
85 	assert(num == lsdb->count);
86 }
87 #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
88 #else  /*DEBUG*/
89 #define ospf6_lsdb_count_assert(t) ((void) 0)
90 #endif /*DEBUG*/
91 
ospf6_lsdb_add(struct ospf6_lsa * lsa,struct ospf6_lsdb * lsdb)92 void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
93 {
94 	struct prefix_ipv6 key;
95 	struct route_node *current;
96 	struct ospf6_lsa *old = NULL;
97 
98 	memset(&key, 0, sizeof(key));
99 	ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
100 	ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
101 			   sizeof(lsa->header->adv_router));
102 	ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
103 
104 	current = route_node_get(lsdb->table, (struct prefix *)&key);
105 	old = current->info;
106 	current->info = lsa;
107 	lsa->rn = current;
108 	ospf6_lsa_lock(lsa);
109 
110 	if (!old) {
111 		lsdb->count++;
112 
113 		if (OSPF6_LSA_IS_MAXAGE(lsa)) {
114 			if (lsdb->hook_remove)
115 				(*lsdb->hook_remove)(lsa);
116 		} else {
117 			if (lsdb->hook_add)
118 				(*lsdb->hook_add)(lsa);
119 		}
120 	} else {
121 		if (OSPF6_LSA_IS_CHANGED(old, lsa)) {
122 			if (OSPF6_LSA_IS_MAXAGE(lsa)) {
123 				if (lsdb->hook_remove) {
124 					(*lsdb->hook_remove)(old);
125 					(*lsdb->hook_remove)(lsa);
126 				}
127 			} else if (OSPF6_LSA_IS_MAXAGE(old)) {
128 				if (lsdb->hook_add)
129 					(*lsdb->hook_add)(lsa);
130 			} else {
131 				if (lsdb->hook_remove)
132 					(*lsdb->hook_remove)(old);
133 				if (lsdb->hook_add)
134 					(*lsdb->hook_add)(lsa);
135 			}
136 		}
137 		/* to free the lookup lock in node get*/
138 		route_unlock_node(current);
139 		ospf6_lsa_unlock(old);
140 	}
141 
142 	ospf6_lsdb_count_assert(lsdb);
143 }
144 
ospf6_lsdb_remove(struct ospf6_lsa * lsa,struct ospf6_lsdb * lsdb)145 void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
146 {
147 	struct route_node *node;
148 	struct prefix_ipv6 key;
149 
150 	memset(&key, 0, sizeof(key));
151 	ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type));
152 	ospf6_lsdb_set_key(&key, &lsa->header->adv_router,
153 			   sizeof(lsa->header->adv_router));
154 	ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id));
155 
156 	node = route_node_lookup(lsdb->table, (struct prefix *)&key);
157 	assert(node && node->info == lsa);
158 
159 	node->info = NULL;
160 	lsdb->count--;
161 
162 	if (lsdb->hook_remove)
163 		(*lsdb->hook_remove)(lsa);
164 
165 	route_unlock_node(node); /* to free the lookup lock */
166 	route_unlock_node(node); /* to free the original lock */
167 	ospf6_lsa_unlock(lsa);
168 
169 	ospf6_lsdb_count_assert(lsdb);
170 }
171 
ospf6_lsdb_lookup(uint16_t type,uint32_t id,uint32_t adv_router,struct ospf6_lsdb * lsdb)172 struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
173 				    uint32_t adv_router,
174 				    struct ospf6_lsdb *lsdb)
175 {
176 	struct route_node *node;
177 	struct prefix_ipv6 key;
178 
179 	if (lsdb == NULL)
180 		return NULL;
181 
182 	memset(&key, 0, sizeof(key));
183 	ospf6_lsdb_set_key(&key, &type, sizeof(type));
184 	ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
185 	ospf6_lsdb_set_key(&key, &id, sizeof(id));
186 
187 	node = route_node_lookup(lsdb->table, (struct prefix *)&key);
188 	if (node == NULL || node->info == NULL)
189 		return NULL;
190 
191 	route_unlock_node(node);
192 	return (struct ospf6_lsa *)node->info;
193 }
194 
ospf6_lsdb_lookup_next(uint16_t type,uint32_t id,uint32_t adv_router,struct ospf6_lsdb * lsdb)195 struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
196 					 uint32_t adv_router,
197 					 struct ospf6_lsdb *lsdb)
198 {
199 	struct route_node *node;
200 	struct prefix_ipv6 key;
201 
202 	if (lsdb == NULL)
203 		return NULL;
204 
205 	memset(&key, 0, sizeof(key));
206 	ospf6_lsdb_set_key(&key, &type, sizeof(type));
207 	ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router));
208 	ospf6_lsdb_set_key(&key, &id, sizeof(id));
209 
210 	{
211 		char buf[PREFIX2STR_BUFFER];
212 		prefix2str(&key, buf, sizeof(buf));
213 		zlog_debug("lsdb_lookup_next: key: %s", buf);
214 	}
215 
216 	node = route_table_get_next(lsdb->table, &key);
217 
218 	/* skip to real existing entry */
219 	while (node && node->info == NULL)
220 		node = route_next(node);
221 
222 	if (!node)
223 		return NULL;
224 
225 	route_unlock_node(node);
226 	if (!node->info)
227 		return NULL;
228 
229 	return (struct ospf6_lsa *)node->info;
230 }
231 
ospf6_lsdb_head(struct ospf6_lsdb * lsdb,int argmode,uint16_t type,uint32_t adv_router,struct ospf6_lsa ** lsa)232 const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, int argmode,
233 					 uint16_t type, uint32_t adv_router,
234 					 struct ospf6_lsa **lsa)
235 {
236 	struct route_node *node, *end;
237 
238 	*lsa = NULL;
239 
240 	if (argmode > 0) {
241 		struct prefix_ipv6 key = {.family = AF_INET6, .prefixlen = 0};
242 
243 		ospf6_lsdb_set_key(&key, &type, sizeof(type));
244 		if (argmode > 1)
245 			ospf6_lsdb_set_key(&key, &adv_router,
246 					   sizeof(adv_router));
247 
248 		node = route_table_get_next(lsdb->table, &key);
249 		if (!node || !prefix_match((struct prefix *)&key, &node->p))
250 			return NULL;
251 
252 		for (end = node; end && end->parent
253 				 && end->parent->p.prefixlen >= key.prefixlen;
254 		     end = end->parent)
255 			;
256 	} else {
257 		node = route_top(lsdb->table);
258 		end = NULL;
259 	}
260 
261 	while (node && !node->info)
262 		node = route_next_until(node, end);
263 
264 	if (!node)
265 		return NULL;
266 	if (!node->info) {
267 		route_unlock_node(node);
268 		return NULL;
269 	}
270 
271 	*lsa = node->info;
272 	ospf6_lsa_lock(*lsa);
273 
274 	return end;
275 }
276 
ospf6_lsdb_next(const struct route_node * iterend,struct ospf6_lsa * lsa)277 struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend,
278 				  struct ospf6_lsa *lsa)
279 {
280 	struct route_node *node = lsa->rn;
281 
282 	ospf6_lsa_unlock(lsa);
283 
284 	do
285 		node = route_next_until(node, iterend);
286 	while (node && !node->info);
287 
288 	if (node && node->info) {
289 		struct ospf6_lsa *next = node->info;
290 		ospf6_lsa_lock(next);
291 		return next;
292 	}
293 
294 	if (node)
295 		route_unlock_node(node);
296 	return NULL;
297 }
298 
ospf6_lsdb_remove_all(struct ospf6_lsdb * lsdb)299 void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb)
300 {
301 	struct ospf6_lsa *lsa;
302 
303 	if (lsdb == NULL)
304 		return;
305 
306 	for (ALL_LSDB(lsdb, lsa))
307 		ospf6_lsdb_remove(lsa, lsdb);
308 }
309 
ospf6_lsdb_lsa_unlock(struct ospf6_lsa * lsa)310 void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa)
311 {
312 	if (lsa != NULL) {
313 		if (lsa->rn != NULL)
314 			route_unlock_node(lsa->rn);
315 		ospf6_lsa_unlock(lsa);
316 	}
317 }
318 
ospf6_lsdb_maxage_remover(struct ospf6_lsdb * lsdb)319 int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
320 {
321 	int reschedule = 0;
322 	struct ospf6_lsa *lsa;
323 
324 	for (ALL_LSDB(lsdb, lsa)) {
325 		if (!OSPF6_LSA_IS_MAXAGE(lsa))
326 			continue;
327 		if (lsa->retrans_count != 0) {
328 			reschedule = 1;
329 			continue;
330 		}
331 		if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
332 			zlog_debug("Remove MaxAge %s", lsa->name);
333 
334 		if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) {
335 			UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
336 			/*
337 			 * lsa->header->age = 0;
338 			 */
339 			lsa->header->seqnum =
340 				htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
341 			ospf6_lsa_checksum(lsa->header);
342 
343 			THREAD_OFF(lsa->refresh);
344 			thread_execute(master, ospf6_lsa_refresh, lsa, 0);
345 		} else {
346 			ospf6_lsdb_remove(lsa, lsdb);
347 		}
348 	}
349 
350 	return (reschedule);
351 }
352 
ospf6_lsdb_show(struct vty * vty,enum ospf_lsdb_show_level level,uint16_t * type,uint32_t * id,uint32_t * adv_router,struct ospf6_lsdb * lsdb)353 void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level,
354 		     uint16_t *type, uint32_t *id, uint32_t *adv_router,
355 		     struct ospf6_lsdb *lsdb)
356 {
357 	struct ospf6_lsa *lsa;
358 	const struct route_node *end = NULL;
359 	void (*showfunc)(struct vty *, struct ospf6_lsa *) = NULL;
360 
361 	switch (level) {
362 	case OSPF6_LSDB_SHOW_LEVEL_DETAIL:
363 		showfunc = ospf6_lsa_show;
364 		break;
365 	case OSPF6_LSDB_SHOW_LEVEL_INTERNAL:
366 		showfunc = ospf6_lsa_show_internal;
367 		break;
368 	case OSPF6_LSDB_SHOW_LEVEL_DUMP:
369 		showfunc = ospf6_lsa_show_dump;
370 		break;
371 	case OSPF6_LSDB_SHOW_LEVEL_NORMAL:
372 	default:
373 		showfunc = ospf6_lsa_show_summary;
374 	}
375 
376 	if (type && id && adv_router) {
377 		lsa = ospf6_lsdb_lookup(*type, *id, *adv_router, lsdb);
378 		if (lsa) {
379 			if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
380 				ospf6_lsa_show(vty, lsa);
381 			else
382 				(*showfunc)(vty, lsa);
383 		}
384 		return;
385 	}
386 
387 	if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL)
388 		ospf6_lsa_show_summary_header(vty);
389 
390 	end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router),
391 			      type ? *type : 0, adv_router ? *adv_router : 0,
392 			      &lsa);
393 	while (lsa) {
394 		if ((!adv_router || lsa->header->adv_router == *adv_router)
395 		    && (!id || lsa->header->id == *id))
396 			(*showfunc)(vty, lsa);
397 
398 		lsa = ospf6_lsdb_next(end, lsa);
399 	}
400 }
401 
ospf6_new_ls_id(uint16_t type,uint32_t adv_router,struct ospf6_lsdb * lsdb)402 uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router,
403 			 struct ospf6_lsdb *lsdb)
404 {
405 	struct ospf6_lsa *lsa;
406 	uint32_t id = 1, tmp_id;
407 
408 	/* This routine is curently invoked only for Inter-Prefix LSAs for
409 	 * non-summarized routes (no area/range).
410 	 */
411 	for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) {
412 		tmp_id = ntohl(lsa->header->id);
413 		if (tmp_id < id)
414 			continue;
415 
416 		if (tmp_id > id) {
417 			ospf6_lsdb_lsa_unlock(lsa);
418 			break;
419 		}
420 		id++;
421 	}
422 
423 	return ((uint32_t)htonl(id));
424 }
425 
426 /* Decide new LS sequence number to originate.
427    note return value is network byte order */
ospf6_new_ls_seqnum(uint16_t type,uint32_t id,uint32_t adv_router,struct ospf6_lsdb * lsdb)428 uint32_t ospf6_new_ls_seqnum(uint16_t type, uint32_t id, uint32_t adv_router,
429 			     struct ospf6_lsdb *lsdb)
430 {
431 	struct ospf6_lsa *lsa;
432 	signed long seqnum = 0;
433 
434 	/* if current database copy not found, return InitialSequenceNumber */
435 	lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb);
436 	if (lsa == NULL)
437 		seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
438 	else
439 		seqnum = (signed long)ntohl(lsa->header->seqnum) + 1;
440 
441 	return ((uint32_t)htonl(seqnum));
442 }
443