]>
Commit | Line | Data |
---|---|---|
ca10883e DS |
1 | /* |
2 | Copyright (c) 2007, 2008 by Juliusz Chroboczek | |
3 | ||
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 | of this software and associated documentation files (the "Software"), to deal | |
6 | in the Software without restriction, including without limitation the rights | |
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 | copies of the Software, and to permit persons to whom the Software is | |
9 | furnished to do so, subject to the following conditions: | |
10 | ||
11 | The above copyright notice and this permission notice shall be included in | |
12 | all copies or substantial portions of the Software. | |
13 | ||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 | THE SOFTWARE. | |
21 | */ | |
22 | ||
b45ac5f5 DL |
23 | #ifdef HAVE_CONFIG_H |
24 | #include "config.h" | |
25 | #endif | |
26 | ||
ca10883e DS |
27 | #include <stdlib.h> |
28 | #include <stdio.h> | |
29 | #include <string.h> | |
30 | #include <sys/time.h> | |
31 | ||
32 | #include "babel_main.h" | |
33 | #include "babeld.h" | |
34 | #include "util.h" | |
35 | #include "source.h" | |
36 | #include "babel_interface.h" | |
37 | #include "route.h" | |
e33b116c | 38 | #include "babel_errors.h" |
ca10883e DS |
39 | |
40 | struct source *srcs = NULL; | |
41 | ||
42 | struct source* | |
43 | find_source(const unsigned char *id, const unsigned char *p, unsigned char plen, | |
44 | int create, unsigned short seqno) | |
45 | { | |
46 | struct source *src; | |
47 | ||
48 | for(src = srcs; src; src = src->next) { | |
49 | /* This should really be a hash table. For now, check the | |
50 | last byte first. */ | |
51 | if(src->id[7] != id[7]) | |
52 | continue; | |
53 | if(memcmp(src->id, id, 8) != 0) | |
54 | continue; | |
55 | if(src->plen != plen) | |
56 | continue; | |
57 | if(memcmp(src->prefix, p, 16) == 0) | |
58 | return src; | |
59 | } | |
60 | ||
61 | if(!create) | |
62 | return NULL; | |
63 | ||
64 | src = malloc(sizeof(struct source)); | |
65 | if(src == NULL) { | |
5b003f31 | 66 | flog_err(EC_BABEL_MEMORY, "malloc(source): %s", safe_strerror(errno)); |
ca10883e DS |
67 | return NULL; |
68 | } | |
69 | ||
70 | memcpy(src->id, id, 8); | |
71 | memcpy(src->prefix, p, 16); | |
72 | src->plen = plen; | |
73 | src->seqno = seqno; | |
74 | src->metric = INFINITY; | |
75 | src->time = babel_now.tv_sec; | |
76 | src->route_count = 0; | |
77 | src->next = srcs; | |
78 | srcs = src; | |
79 | return src; | |
80 | } | |
81 | ||
82 | struct source * | |
83 | retain_source(struct source *src) | |
84 | { | |
85 | assert(src->route_count < 0xffff); | |
86 | src->route_count++; | |
87 | return src; | |
88 | } | |
89 | ||
90 | void | |
91 | release_source(struct source *src) | |
92 | { | |
93 | assert(src->route_count > 0); | |
94 | src->route_count--; | |
95 | } | |
96 | ||
97 | int | |
98 | flush_source(struct source *src) | |
99 | { | |
100 | if(src->route_count > 0) | |
101 | /* The source is in use by a route. */ | |
102 | return 0; | |
103 | ||
104 | if(srcs == src) { | |
105 | srcs = src->next; | |
106 | } else { | |
107 | struct source *previous = srcs; | |
108 | while(previous->next != src) | |
109 | previous = previous->next; | |
110 | previous->next = src->next; | |
111 | } | |
112 | ||
113 | free(src); | |
114 | return 1; | |
115 | } | |
116 | ||
117 | void | |
118 | update_source(struct source *src, | |
119 | unsigned short seqno, unsigned short metric) | |
120 | { | |
121 | if(metric >= INFINITY) | |
122 | return; | |
123 | ||
124 | /* If a source is expired, pretend that it doesn't exist and update | |
125 | it unconditionally. This makes ensures that old data will | |
126 | eventually be overridden, and prevents us from getting stuck if | |
127 | a router loses its sequence number. */ | |
128 | if(src->time < babel_now.tv_sec - SOURCE_GC_TIME || | |
129 | seqno_compare(src->seqno, seqno) < 0 || | |
130 | (src->seqno == seqno && src->metric > metric)) { | |
131 | src->seqno = seqno; | |
132 | src->metric = metric; | |
133 | } | |
134 | src->time = babel_now.tv_sec; | |
135 | } | |
136 | ||
137 | void | |
4d762f26 | 138 | expire_sources(void) |
ca10883e DS |
139 | { |
140 | struct source *src; | |
141 | ||
142 | src = srcs; | |
143 | while(src) { | |
144 | if(src->time > babel_now.tv_sec) | |
145 | /* clock stepped */ | |
146 | src->time = babel_now.tv_sec; | |
147 | if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) { | |
148 | struct source *old = src; | |
149 | src = src->next; | |
150 | flush_source(old); | |
151 | continue; | |
152 | } | |
153 | src = src->next; | |
154 | } | |
155 | } | |
156 | ||
157 | void | |
158 | check_sources_released(void) | |
159 | { | |
160 | struct source *src; | |
161 | ||
162 | for(src = srcs; src; src = src->next) { | |
163 | if(src->route_count != 0) | |
164 | fprintf(stderr, "Warning: source %s %s has refcount %d.\n", | |
165 | format_eui64(src->id), | |
166 | format_prefix(src->prefix, src->plen), | |
167 | (int)src->route_count); | |
168 | } | |
169 | } |