]>
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 | ||
23 | #include <stdlib.h> | |
24 | #include <stdio.h> | |
25 | #include <string.h> | |
26 | #include <sys/time.h> | |
27 | ||
28 | #include "babel_main.h" | |
29 | #include "babeld.h" | |
30 | #include "util.h" | |
31 | #include "source.h" | |
32 | #include "babel_interface.h" | |
33 | #include "route.h" | |
34 | ||
35 | struct source *srcs = NULL; | |
36 | ||
37 | struct source* | |
38 | find_source(const unsigned char *id, const unsigned char *p, unsigned char plen, | |
39 | int create, unsigned short seqno) | |
40 | { | |
41 | struct source *src; | |
42 | ||
43 | for(src = srcs; src; src = src->next) { | |
44 | /* This should really be a hash table. For now, check the | |
45 | last byte first. */ | |
46 | if(src->id[7] != id[7]) | |
47 | continue; | |
48 | if(memcmp(src->id, id, 8) != 0) | |
49 | continue; | |
50 | if(src->plen != plen) | |
51 | continue; | |
52 | if(memcmp(src->prefix, p, 16) == 0) | |
53 | return src; | |
54 | } | |
55 | ||
56 | if(!create) | |
57 | return NULL; | |
58 | ||
59 | src = malloc(sizeof(struct source)); | |
60 | if(src == NULL) { | |
61 | zlog_err("malloc(source): %s", safe_strerror(errno)); | |
62 | return NULL; | |
63 | } | |
64 | ||
65 | memcpy(src->id, id, 8); | |
66 | memcpy(src->prefix, p, 16); | |
67 | src->plen = plen; | |
68 | src->seqno = seqno; | |
69 | src->metric = INFINITY; | |
70 | src->time = babel_now.tv_sec; | |
71 | src->route_count = 0; | |
72 | src->next = srcs; | |
73 | srcs = src; | |
74 | return src; | |
75 | } | |
76 | ||
77 | struct source * | |
78 | retain_source(struct source *src) | |
79 | { | |
80 | assert(src->route_count < 0xffff); | |
81 | src->route_count++; | |
82 | return src; | |
83 | } | |
84 | ||
85 | void | |
86 | release_source(struct source *src) | |
87 | { | |
88 | assert(src->route_count > 0); | |
89 | src->route_count--; | |
90 | } | |
91 | ||
92 | int | |
93 | flush_source(struct source *src) | |
94 | { | |
95 | if(src->route_count > 0) | |
96 | /* The source is in use by a route. */ | |
97 | return 0; | |
98 | ||
99 | if(srcs == src) { | |
100 | srcs = src->next; | |
101 | } else { | |
102 | struct source *previous = srcs; | |
103 | while(previous->next != src) | |
104 | previous = previous->next; | |
105 | previous->next = src->next; | |
106 | } | |
107 | ||
108 | free(src); | |
109 | return 1; | |
110 | } | |
111 | ||
112 | void | |
113 | update_source(struct source *src, | |
114 | unsigned short seqno, unsigned short metric) | |
115 | { | |
116 | if(metric >= INFINITY) | |
117 | return; | |
118 | ||
119 | /* If a source is expired, pretend that it doesn't exist and update | |
120 | it unconditionally. This makes ensures that old data will | |
121 | eventually be overridden, and prevents us from getting stuck if | |
122 | a router loses its sequence number. */ | |
123 | if(src->time < babel_now.tv_sec - SOURCE_GC_TIME || | |
124 | seqno_compare(src->seqno, seqno) < 0 || | |
125 | (src->seqno == seqno && src->metric > metric)) { | |
126 | src->seqno = seqno; | |
127 | src->metric = metric; | |
128 | } | |
129 | src->time = babel_now.tv_sec; | |
130 | } | |
131 | ||
132 | void | |
133 | expire_sources() | |
134 | { | |
135 | struct source *src; | |
136 | ||
137 | src = srcs; | |
138 | while(src) { | |
139 | if(src->time > babel_now.tv_sec) | |
140 | /* clock stepped */ | |
141 | src->time = babel_now.tv_sec; | |
142 | if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) { | |
143 | struct source *old = src; | |
144 | src = src->next; | |
145 | flush_source(old); | |
146 | continue; | |
147 | } | |
148 | src = src->next; | |
149 | } | |
150 | } | |
151 | ||
152 | void | |
153 | check_sources_released(void) | |
154 | { | |
155 | struct source *src; | |
156 | ||
157 | for(src = srcs; src; src = src->next) { | |
158 | if(src->route_count != 0) | |
159 | fprintf(stderr, "Warning: source %s %s has refcount %d.\n", | |
160 | format_eui64(src->id), | |
161 | format_prefix(src->prefix, src->plen), | |
162 | (int)src->route_count); | |
163 | } | |
164 | } |