]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * LSA function | |
3 | * Copyright (C) 1999 Yasuhiro Ohara | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with GNU Zebra; see the file COPYING. If not, write to the | |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | * Boston, MA 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #ifndef OSPF6_LSA_H | |
24 | #define OSPF6_LSA_H | |
25 | ||
26 | #include "ospf6_hook.h" | |
27 | ||
28 | #define ONESECOND_USEC 1000000 | |
29 | #define USEC_TVDIFF(tv2,tv1) \ | |
30 | (((tv2)->tv_sec - (tv1)->tv_sec) * ONESECOND_USEC \ | |
31 | + ((tv2)->tv_usec - (tv1)->tv_usec)) | |
32 | #define SEC_TVDIFF(tv2,tv1) \ | |
33 | (USEC_TVDIFF((tv2),(tv1)) / ONESECOND_USEC) | |
34 | ||
35 | /* LSA definition */ | |
36 | ||
37 | #define MAXLSASIZE 1024 | |
38 | ||
39 | #define OSPF6_LSA_MAXAGE 3600 /* 1 hour */ | |
40 | #define OSPF6_LSA_CHECKAGE 300 /* 5 min */ | |
41 | #define OSPF6_LSA_MAXAGEDIFF 900 /* 15 min */ | |
42 | ||
43 | /* Type */ | |
44 | #define OSPF6_LSA_TYPE_NONE 0x0000 | |
45 | #define OSPF6_LSA_TYPE_ROUTER 0x2001 | |
46 | #define OSPF6_LSA_TYPE_NETWORK 0x2002 | |
47 | #define OSPF6_LSA_TYPE_INTER_PREFIX 0x2003 | |
48 | #define OSPF6_LSA_TYPE_INTER_ROUTER 0x2004 | |
49 | #define OSPF6_LSA_TYPE_AS_EXTERNAL 0x4005 | |
50 | #define OSPF6_LSA_TYPE_GROUP_MEMBERSHIP 0x2006 | |
51 | #define OSPF6_LSA_TYPE_TYPE_7 0x2007 | |
52 | #define OSPF6_LSA_TYPE_LINK 0x0008 | |
53 | #define OSPF6_LSA_TYPE_INTRA_PREFIX 0x2009 | |
54 | #define OSPF6_LSA_TYPE_MAX 0x000a | |
55 | #define OSPF6_LSA_TYPE_SIZE 0x000b | |
56 | ||
57 | /* Masks for LS Type : RFC 2740 A.4.2.1 "LS type" */ | |
58 | #define OSPF6_LSTYPE_UBIT_MASK 0x8000 | |
59 | #define OSPF6_LSTYPE_SCOPE_MASK 0x6000 | |
60 | #define OSPF6_LSTYPE_CODE_MASK 0x1fff | |
61 | ||
62 | #define OSPF6_LSA_TYPESW_MASK OSPF6_LSTYPE_CODE_MASK | |
63 | #define OSPF6_LSA_TYPESW(x) (ntohs((x)) & OSPF6_LSA_TYPESW_MASK) | |
64 | #define OSPF6_LSA_TYPESW_ISKNOWN(x) (OSPF6_LSA_TYPESW(x) < OSPF6_LSA_TYPE_MAX) | |
65 | ||
66 | /* lsa scope */ | |
67 | #define OSPF6_LSA_SCOPE_LINKLOCAL 0x0000 | |
68 | #define OSPF6_LSA_SCOPE_AREA 0x2000 | |
69 | #define OSPF6_LSA_SCOPE_AS 0x4000 | |
70 | #define OSPF6_LSA_SCOPE_RESERVED 0x6000 | |
71 | #define OSPF6_LSA_IS_SCOPE_LINKLOCAL(x) \ | |
72 | (((x) & OSPF6_LSTYPE_SCOPE_MASK) == OSPF6_LSA_SCOPE_LINKLOCAL) | |
73 | #define OSPF6_LSA_IS_SCOPE_AREA(x) \ | |
74 | (((x) & OSPF6_LSTYPE_SCOPE_MASK) == OSPF6_LSA_SCOPE_AREA) | |
75 | #define OSPF6_LSA_IS_SCOPE_AS(x) \ | |
76 | (((x) & OSPF6_LSTYPE_SCOPE_MASK) == OSPF6_LSA_SCOPE_AS) | |
77 | ||
78 | /* NOTE that all LSAs are kept NETWORK BYTE ORDER */ | |
79 | ||
80 | /* Router-LSA */ | |
81 | struct ospf6_router_lsa | |
82 | { | |
83 | u_char bits; | |
84 | u_char options[3]; | |
85 | /* followed by ospf6_router_lsd(s) */ | |
86 | }; | |
87 | ||
88 | #define OSPF6_ROUTER_LSA_BIT_B (1 << 0) | |
89 | #define OSPF6_ROUTER_LSA_BIT_E (1 << 1) | |
90 | #define OSPF6_ROUTER_LSA_BIT_V (1 << 2) | |
91 | #define OSPF6_ROUTER_LSA_BIT_W (1 << 3) | |
92 | ||
93 | #define OSPF6_ROUTER_LSA_SET(x,y) ((x)->bits |= (y)) | |
94 | #define OSPF6_ROUTER_LSA_ISSET(x,y) ((x)->bits & (y)) | |
95 | #define OSPF6_ROUTER_LSA_CLEAR(x,y) ((x)->bits &= ~(y)) | |
96 | #define OSPF6_ROUTER_LSA_CLEAR_ALL_BITS(x) ((x)->bits = 0) | |
97 | ||
98 | /* Link State Description in Router-LSA */ | |
99 | struct ospf6_router_lsd | |
100 | { | |
101 | u_char type; | |
102 | u_char reserved; | |
103 | u_int16_t metric; /* output cost */ | |
104 | u_int32_t interface_id; | |
105 | u_int32_t neighbor_interface_id; | |
106 | u_int32_t neighbor_router_id; | |
107 | }; | |
108 | ||
109 | #define OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT 1 | |
110 | #define OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK 2 | |
111 | #define OSPF6_ROUTER_LSD_TYPE_STUB_NETWORK 3 | |
112 | #define OSPF6_ROUTER_LSD_TYPE_VIRTUAL_LINK 4 | |
113 | ||
114 | /* Network-LSA */ | |
115 | struct ospf6_network_lsa | |
116 | { | |
117 | u_char reserved; | |
118 | u_char options[3]; | |
119 | /* followed by ospf6_netowrk_lsd(s) */ | |
120 | }; | |
121 | ||
122 | /* Link State Description in Router-LSA */ | |
123 | struct ospf6_network_lsd | |
124 | { | |
125 | u_int32_t adv_router; | |
126 | }; | |
127 | ||
128 | /* Link-LSA */ | |
129 | struct ospf6_link_lsa | |
130 | { | |
131 | u_char llsa_rtr_pri; | |
132 | u_char llsa_options[3]; | |
133 | struct in6_addr llsa_linklocal; | |
134 | u_int32_t llsa_prefix_num; | |
135 | /* followed by prefix(es) */ | |
136 | }; | |
137 | ||
138 | /* Intra-Area-Prefix-LSA */ | |
139 | struct ospf6_intra_area_prefix_lsa | |
140 | { | |
141 | u_int16_t prefix_number; | |
142 | u_int16_t refer_lstype; | |
143 | u_int32_t refer_lsid; | |
144 | u_int32_t refer_advrtr; | |
145 | }; | |
146 | ||
147 | /* AS-External-LSA */ | |
148 | struct ospf6_as_external_lsa | |
149 | { | |
150 | u_char ase_bits; | |
151 | u_char ase_pre_metric; /* 1st byte of metric */ | |
152 | u_int16_t ase_metric; /* 2nd, 3rd byte of metric */ | |
153 | #if 1 | |
154 | struct ospf6_prefix ospf6_prefix; | |
155 | #else | |
156 | u_char ase_prefix_len; | |
157 | u_char ase_prefix_opt; | |
158 | u_int16_t ase_refer_lstype; | |
159 | /* followed by one address prefix */ | |
160 | #endif | |
161 | /* followed by none or one forwarding address */ | |
162 | /* followed by none or one external route tag */ | |
163 | /* followed by none or one referenced LS-ID */ | |
164 | }; | |
165 | #define ASE_LSA_BIT_T (1 << 0) | |
166 | #define ASE_LSA_BIT_F (1 << 1) | |
167 | #define ASE_LSA_BIT_E (1 << 2) | |
168 | ||
169 | #define ASE_LSA_SET(x,y) ((x)->ase_bits |= (y)) | |
170 | #define ASE_LSA_ISSET(x,y) ((x)->ase_bits & (y)) | |
171 | #define ASE_LSA_CLEAR(x,y) ((x)->ase_bits &= ~(y)) | |
172 | ||
173 | /* LSA Header */ | |
174 | struct ospf6_lsa_hdr | |
175 | { | |
176 | u_int16_t lsh_age; /* LS age */ | |
177 | u_int16_t lsh_type; /* LS type */ | |
178 | u_int32_t lsh_id; /* Link State ID */ | |
179 | u_int32_t lsh_advrtr; /* Advertising Router */ | |
180 | u_int32_t lsh_seqnum; /* LS sequence number */ | |
181 | u_int16_t lsh_cksum; /* LS checksum */ | |
182 | u_int16_t lsh_len; /* length */ | |
183 | }; | |
184 | struct ospf6_lsa_header | |
185 | { | |
186 | u_int16_t age; /* LS age */ | |
187 | u_int16_t type; /* LS type */ | |
188 | u_int32_t ls_id; /* Link State ID */ | |
189 | u_int32_t advrtr; /* Advertising Router */ | |
190 | u_int32_t seqnum; /* LS sequence number */ | |
191 | u_int16_t checksum; /* LS checksum */ | |
192 | u_int16_t length; /* LSA length */ | |
193 | }; | |
194 | struct ospf6_lsa_header__ | |
195 | { | |
196 | u_int16_t age; /* LS age */ | |
197 | u_int16_t type; /* LS type */ | |
198 | u_int32_t id; /* Link State ID */ | |
199 | u_int32_t adv_router; /* Advertising Router */ | |
200 | u_int32_t seqnum; /* LS sequence number */ | |
201 | u_int16_t checksum; /* LS checksum */ | |
202 | u_int16_t length; /* LSA length */ | |
203 | }; | |
204 | ||
205 | #define OSPF6_LSA_NEXT(x) ((struct ospf6_lsa_header *) \ | |
206 | ((char *)(x) + ntohs ((x)->length))) | |
207 | ||
208 | #define OSPF6_LSA_HEADER_END(header) \ | |
209 | ((void *)((char *)(header) + sizeof (struct ospf6_lsa_header))) | |
210 | ||
211 | struct ospf6_lsa | |
212 | { | |
213 | char str[256]; /* dump string */ | |
214 | ||
215 | u_long lock; /* reference counter */ | |
216 | int summary; /* indicate this is LS header only */ | |
217 | void *scope; /* pointer of scoped data structure */ | |
218 | unsigned char flag; /* to decide ack type and refresh */ | |
219 | struct timeval birth; /* tv_sec when LS age 0 */ | |
220 | struct timeval installed; /* installed time */ | |
221 | struct timeval originated; /* installed time */ | |
222 | struct thread *expire; | |
223 | struct thread *refresh; /* For self-originated LSA */ | |
224 | u_int32_t from; /* from which neighbor */ | |
225 | ||
226 | /* lsa instance */ | |
227 | struct ospf6_lsa_hdr *lsa_hdr; | |
228 | struct ospf6_lsa_header__ *header; | |
229 | ||
230 | /* statistics */ | |
231 | u_long turnover_num; | |
232 | u_long turnover_total; | |
233 | u_long turnover_min; | |
234 | u_long turnover_max; | |
235 | }; | |
236 | ||
237 | struct ospf6_lsa_slot | |
238 | { | |
239 | struct ospf6_lsa_slot *prev; | |
240 | struct ospf6_lsa_slot *next; | |
241 | ||
242 | u_int16_t type; | |
243 | char *name; | |
244 | ||
245 | int (*func_print) (struct ospf6_lsa *lsa); | |
246 | int (*func_show) (struct vty *vty, struct ospf6_lsa *lsa); | |
247 | int (*func_refresh) (void *lsa); | |
248 | ||
249 | int (*database_add) (void *lsa); | |
250 | int (*database_remove) (void *lsa); | |
251 | ||
252 | struct ospf6_hook_master database_hook; | |
253 | ||
254 | struct ospf6_hook hook_neighbor; | |
255 | struct ospf6_hook hook_interface; | |
256 | struct ospf6_hook hook_area; | |
257 | struct ospf6_hook hook_top; | |
258 | struct ospf6_hook hook_database; | |
259 | struct ospf6_hook hook_route; | |
260 | }; | |
261 | ||
262 | #define OSPF6_LSA_FLAG_FLOODBACK 0x01 | |
263 | #define OSPF6_LSA_FLAG_DUPLICATE 0x02 | |
264 | #define OSPF6_LSA_FLAG_IMPLIEDACK 0x04 | |
265 | #define OSPF6_LSA_FLAG_REFRESH 0x08 | |
266 | ||
267 | /* Back pointer check, Is X's reference field bound to Y ? */ | |
268 | #define x_ipl(x) ((struct intra_area_prefix_lsa *)LSH_NEXT((x)->lsa_hdr)) | |
269 | #define is_reference_network_ok(x,y) \ | |
270 | ((x_ipl(x))->intra_prefix_refer_lstype == (y)->lsa_hdr->lsh_type &&\ | |
271 | (x_ipl(x))->intra_prefix_refer_lsid == (y)->lsa_hdr->lsh_id &&\ | |
272 | (x_ipl(x))->intra_prefix_refer_advrtr == (y)->lsa_hdr->lsh_advrtr) | |
273 | /* referencing router's ifid must be 0, | |
274 | see draft-ietf-ospf-ospfv6-06.txt */ | |
275 | #define is_reference_router_ok(x,y) \ | |
276 | ((x_ipl(x))->intra_prefix_refer_lstype == (y)->lsa_hdr->lsh_type &&\ | |
277 | (x_ipl(x))->intra_prefix_refer_lsid == htonl (0) &&\ | |
278 | (x_ipl(x))->intra_prefix_refer_advrtr == (y)->lsa_hdr->lsh_advrtr) | |
279 | ||
280 | /* MaxAge check. */ | |
281 | /* ospf6_lsa_is_maxage (struct ospf6_lsa *lsa) */ | |
282 | #define IS_LSA_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF6_LSA_MAXAGE) | |
283 | ||
284 | struct ospf6_lsa_slot *ospf6_lsa_slot_get (u_int16_t type); | |
285 | int ospf6_lsa_slot_register (struct ospf6_lsa_slot *src); | |
286 | int ospf6_lsa_slot_unregister (u_int16_t type); | |
287 | ||
288 | extern struct ospf6_lsa_slot *slot_head; | |
289 | #define CALL_FOREACH_LSA_HOOK(hook,func,data) \ | |
290 | if (ospf6)\ | |
291 | {\ | |
292 | struct ospf6_lsa_slot *slot;\ | |
293 | for (slot = slot_head; slot; slot = slot->next)\ | |
294 | {\ | |
295 | if (slot->hook.func)\ | |
296 | (*slot->hook.func) (data);\ | |
297 | }\ | |
298 | } | |
299 | #define CALL_LSA_FUNC(type,func,data) \ | |
300 | if (ospf6)\ | |
301 | {\ | |
302 | struct ospf6_lsa_slot *slot;\ | |
303 | slot = ospf6_lsa_slot_get (type);\ | |
304 | if (slot && slot->func)\ | |
305 | {\ | |
306 | (*slot->func) (data);\ | |
307 | }\ | |
308 | else\ | |
309 | {\ | |
310 | zlog_warn ("LSA: No slot for type %#x: %s line:%d",\ | |
311 | ntohs (type), __FILE__, __LINE__);\ | |
312 | }\ | |
313 | } | |
314 | ||
315 | #define CALL_LSA_DATABASE_ADD(type,data) \ | |
316 | if (ospf6)\ | |
317 | {\ | |
318 | struct ospf6_lsa_slot *slot;\ | |
319 | slot = ospf6_lsa_slot_get (type);\ | |
320 | if (slot)\ | |
321 | {\ | |
322 | CALL_ADD_HOOK (&slot->database_hook, data);\ | |
323 | }\ | |
324 | else\ | |
325 | {\ | |
326 | zlog_warn ("LSA: No slot for type %#x: %s line:%d",\ | |
327 | ntohs (type), __FILE__, __LINE__);\ | |
328 | }\ | |
329 | } | |
330 | #define CALL_LSA_DATABASE_CHANGE(type,data) \ | |
331 | if (ospf6)\ | |
332 | {\ | |
333 | struct ospf6_lsa_slot *slot;\ | |
334 | slot = ospf6_lsa_slot_get (type);\ | |
335 | if (slot)\ | |
336 | {\ | |
337 | CALL_CHANGE_HOOK (&slot->database_hook, data);\ | |
338 | }\ | |
339 | else\ | |
340 | {\ | |
341 | zlog_warn ("LSA: No slot for type %#x: %s line:%d",\ | |
342 | ntohs (type), __FILE__, __LINE__);\ | |
343 | }\ | |
344 | } | |
345 | #define CALL_LSA_DATABASE_REMOVE(type,data) \ | |
346 | if (ospf6)\ | |
347 | {\ | |
348 | struct ospf6_lsa_slot *slot;\ | |
349 | slot = ospf6_lsa_slot_get (type);\ | |
350 | if (slot)\ | |
351 | {\ | |
352 | CALL_REMOVE_HOOK (&slot->database_hook, data);\ | |
353 | }\ | |
354 | else\ | |
355 | {\ | |
356 | zlog_warn ("LSA: No slot for type %#x: %s line:%d",\ | |
357 | ntohs (type), __FILE__, __LINE__);\ | |
358 | }\ | |
359 | } | |
360 | ||
361 | void ospf6_lsa_init (); | |
362 | ||
363 | /* Function Prototypes */ | |
364 | ||
365 | struct router_lsd * | |
366 | get_router_lsd (u_int32_t, struct ospf6_lsa *); | |
367 | unsigned long get_ifindex_to_router (u_int32_t, struct ospf6_lsa *); | |
368 | ||
369 | int ospf6_lsa_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2); | |
370 | int ospf6_lsa_match (u_int16_t, u_int32_t, u_int32_t, | |
371 | struct ospf6_lsa_header *); | |
372 | ||
373 | void ospf6_lsa_show (struct vty *, struct ospf6_lsa *); | |
374 | void ospf6_lsa_show_dump (struct vty *, struct ospf6_lsa *); | |
375 | void ospf6_lsa_show_summary (struct vty *, struct ospf6_lsa *); | |
376 | void ospf6_lsa_show_summary_header (struct vty *); | |
377 | ||
378 | struct ospf6_lsa * | |
379 | ospf6_lsa_create (struct ospf6_lsa_header *); | |
380 | struct ospf6_lsa * | |
381 | ospf6_lsa_summary_create (struct ospf6_lsa_header__ *); | |
382 | void | |
383 | ospf6_lsa_delete (struct ospf6_lsa *); | |
384 | ||
385 | void ospf6_lsa_lock (struct ospf6_lsa *); | |
386 | void ospf6_lsa_unlock (struct ospf6_lsa *); | |
387 | ||
388 | unsigned short ospf6_lsa_age_current (struct ospf6_lsa *); | |
389 | int ospf6_lsa_is_maxage (struct ospf6_lsa *); | |
390 | void ospf6_lsa_age_update_to_send (struct ospf6_lsa *, u_int32_t); | |
391 | void ospf6_lsa_premature_aging (struct ospf6_lsa *); | |
392 | ||
393 | int ospf6_lsa_check_recent (struct ospf6_lsa *, struct ospf6_lsa *); | |
394 | ||
395 | int | |
396 | ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header); | |
397 | void * | |
398 | ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header); | |
399 | int | |
400 | ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1, | |
401 | int index2, struct ospf6_lsa_header *lsa_header2); | |
402 | ||
403 | int ospf6_lsa_expire (struct thread *); | |
404 | int ospf6_lsa_refresh (struct thread *); | |
405 | ||
406 | u_short ospf6_lsa_checksum (struct ospf6_lsa_header *); | |
407 | ||
408 | void ospf6_lsa_update_network (char *ifname); | |
409 | void ospf6_lsa_update_link (char *ifname); | |
410 | void ospf6_lsa_update_as_external (u_int32_t ls_id); | |
411 | void ospf6_lsa_update_intra_prefix_transit (char *ifname); | |
412 | void ospf6_lsa_update_intra_prefix_stub (u_int32_t area_id); | |
413 | ||
414 | u_int16_t ospf6_lsa_get_scope_type (u_int16_t); | |
415 | int ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header); | |
416 | ||
417 | char *ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize); | |
418 | char *ospf6_lsa_router_bits_string (u_char router_bits, char *buf, int size); | |
419 | ||
420 | u_long | |
421 | ospf6_lsa_has_elasped (u_int16_t, u_int32_t, u_int32_t, void *); | |
422 | void | |
423 | ospf6_lsa_originate (u_int16_t, u_int32_t, u_int32_t, char *, int, void *); | |
424 | ||
425 | #endif /* OSPF6_LSA_H */ | |
426 |