]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: ISC |
8429abe0 RW |
2 | /* $OpenBSD$ */ |
3 | ||
4 | /* | |
5 | * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org> | |
6 | * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> | |
8429abe0 RW |
7 | */ |
8 | ||
eac6e3f0 | 9 | #include <zebra.h> |
8429abe0 RW |
10 | |
11 | #include "ldpd.h" | |
aff1743c | 12 | #include "ldpe.h" |
8429abe0 RW |
13 | #include "lde.h" |
14 | #include "log.h" | |
077d336a | 15 | #include "rlfa.h" |
8429abe0 | 16 | |
eac6e3f0 RW |
17 | #include "mpls.h" |
18 | ||
45926e58 | 19 | static __inline int fec_compare(const struct fec *, const struct fec *); |
03522238 | 20 | static int lde_nbr_is_nexthop(struct fec_node *, struct lde_nbr *); |
21 | static void fec_free(void *); | |
22 | static struct fec_node *fec_add(struct fec *fec); | |
23 | static struct fec_nh *fec_nh_add(struct fec_node *, int, union ldpd_addr *, | |
e132dea0 | 24 | ifindex_t, uint8_t, unsigned short); |
03522238 | 25 | static void fec_nh_del(struct fec_nh *); |
8429abe0 RW |
26 | |
27 | RB_GENERATE(fec_tree, fec, entry, fec_compare) | |
28 | ||
03522238 | 29 | struct fec_tree ft = RB_INITIALIZER(&ft); |
e6685141 | 30 | struct event *gc_timer; |
8429abe0 RW |
31 | |
32 | /* FEC tree functions */ | |
33 | void | |
34 | fec_init(struct fec_tree *fh) | |
35 | { | |
45926e58 | 36 | RB_INIT(fec_tree, fh); |
8429abe0 RW |
37 | } |
38 | ||
39 | static __inline int | |
45926e58 | 40 | fec_compare(const struct fec *a, const struct fec *b) |
8429abe0 RW |
41 | { |
42 | if (a->type < b->type) | |
43 | return (-1); | |
44 | if (a->type > b->type) | |
45 | return (1); | |
46 | ||
47 | switch (a->type) { | |
48 | case FEC_TYPE_IPV4: | |
849d8f2b | 49 | if (ntohl(a->u.ipv4.prefix.s_addr) < ntohl(b->u.ipv4.prefix.s_addr)) |
8429abe0 | 50 | return (-1); |
849d8f2b | 51 | if (ntohl(a->u.ipv4.prefix.s_addr) > ntohl(b->u.ipv4.prefix.s_addr)) |
8429abe0 RW |
52 | return (1); |
53 | if (a->u.ipv4.prefixlen < b->u.ipv4.prefixlen) | |
54 | return (-1); | |
55 | if (a->u.ipv4.prefixlen > b->u.ipv4.prefixlen) | |
56 | return (1); | |
57 | return (0); | |
58 | case FEC_TYPE_IPV6: | |
59 | if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix, | |
60 | sizeof(struct in6_addr)) < 0) | |
61 | return (-1); | |
62 | if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix, | |
63 | sizeof(struct in6_addr)) > 0) | |
64 | return (1); | |
65 | if (a->u.ipv6.prefixlen < b->u.ipv6.prefixlen) | |
66 | return (-1); | |
67 | if (a->u.ipv6.prefixlen > b->u.ipv6.prefixlen) | |
68 | return (1); | |
69 | return (0); | |
70 | case FEC_TYPE_PWID: | |
71 | if (a->u.pwid.type < b->u.pwid.type) | |
72 | return (-1); | |
73 | if (a->u.pwid.type > b->u.pwid.type) | |
74 | return (1); | |
75 | if (a->u.pwid.pwid < b->u.pwid.pwid) | |
76 | return (-1); | |
77 | if (a->u.pwid.pwid > b->u.pwid.pwid) | |
78 | return (1); | |
849d8f2b | 79 | if (ntohl(a->u.pwid.lsr_id.s_addr) < ntohl(b->u.pwid.lsr_id.s_addr)) |
8429abe0 | 80 | return (-1); |
849d8f2b | 81 | if (ntohl(a->u.pwid.lsr_id.s_addr) > ntohl(b->u.pwid.lsr_id.s_addr)) |
8429abe0 RW |
82 | return (1); |
83 | return (0); | |
84 | } | |
85 | ||
86 | return (-1); | |
87 | } | |
88 | ||
89 | struct fec * | |
90 | fec_find(struct fec_tree *fh, struct fec *f) | |
91 | { | |
92 | return (RB_FIND(fec_tree, fh, f)); | |
93 | } | |
94 | ||
95 | int | |
96 | fec_insert(struct fec_tree *fh, struct fec *f) | |
97 | { | |
98 | if (RB_INSERT(fec_tree, fh, f) != NULL) | |
99 | return (-1); | |
100 | return (0); | |
101 | } | |
102 | ||
103 | int | |
104 | fec_remove(struct fec_tree *fh, struct fec *f) | |
105 | { | |
106 | if (RB_REMOVE(fec_tree, fh, f) == NULL) { | |
107 | log_warnx("%s failed for %s", __func__, log_fec(f)); | |
108 | return (-1); | |
109 | } | |
110 | return (0); | |
111 | } | |
112 | ||
113 | void | |
114 | fec_clear(struct fec_tree *fh, void (*free_cb)(void *)) | |
115 | { | |
116 | struct fec *f; | |
117 | ||
55cd0f61 DS |
118 | while (!RB_EMPTY(fec_tree, fh)) { |
119 | f = RB_ROOT(fec_tree, fh); | |
120 | ||
8429abe0 RW |
121 | fec_remove(fh, f); |
122 | free_cb(f); | |
123 | } | |
124 | } | |
125 | ||
126 | /* routing table functions */ | |
127 | static int | |
128 | lde_nbr_is_nexthop(struct fec_node *fn, struct lde_nbr *ln) | |
129 | { | |
130 | struct fec_nh *fnh; | |
131 | ||
132 | LIST_FOREACH(fnh, &fn->nexthops, entry) | |
133 | if (lde_address_find(ln, fnh->af, &fnh->nexthop)) | |
134 | return (1); | |
135 | ||
136 | return (0); | |
137 | } | |
138 | ||
139 | void | |
140 | rt_dump(pid_t pid) | |
141 | { | |
142 | struct fec *f; | |
143 | struct fec_node *fn; | |
144 | struct lde_map *me; | |
145 | static struct ctl_rt rtctl; | |
146 | ||
147 | RB_FOREACH(f, fec_tree, &ft) { | |
148 | fn = (struct fec_node *)f; | |
149 | if (fn->local_label == NO_LABEL && | |
45926e58 | 150 | RB_EMPTY(lde_map_head, &fn->downstream)) |
8429abe0 RW |
151 | continue; |
152 | ||
0f7b5df9 | 153 | memset(&rtctl, 0, sizeof(rtctl)); |
8429abe0 RW |
154 | switch (fn->fec.type) { |
155 | case FEC_TYPE_IPV4: | |
156 | rtctl.af = AF_INET; | |
157 | rtctl.prefix.v4 = fn->fec.u.ipv4.prefix; | |
158 | rtctl.prefixlen = fn->fec.u.ipv4.prefixlen; | |
159 | break; | |
160 | case FEC_TYPE_IPV6: | |
161 | rtctl.af = AF_INET6; | |
162 | rtctl.prefix.v6 = fn->fec.u.ipv6.prefix; | |
163 | rtctl.prefixlen = fn->fec.u.ipv6.prefixlen; | |
164 | break; | |
4a055ac2 | 165 | case FEC_TYPE_PWID: |
8429abe0 RW |
166 | continue; |
167 | } | |
168 | ||
169 | rtctl.local_label = fn->local_label; | |
45926e58 | 170 | if (RB_EMPTY(lde_map_head, &fn->downstream)) { |
8429abe0 RW |
171 | rtctl.in_use = 0; |
172 | rtctl.nexthop.s_addr = INADDR_ANY; | |
173 | rtctl.remote_label = NO_LABEL; | |
0f7b5df9 RW |
174 | rtctl.no_downstream = 1; |
175 | } | |
176 | lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN, 0, pid, &rtctl, | |
177 | sizeof(rtctl)); | |
8429abe0 | 178 | |
0f7b5df9 RW |
179 | RB_FOREACH(me, lde_map_head, &fn->upstream) { |
180 | rtctl.nexthop = me->nexthop->id; | |
181 | lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT, 0, pid, | |
182 | &rtctl, sizeof(rtctl)); | |
183 | } | |
184 | ||
185 | RB_FOREACH(me, lde_map_head, &fn->downstream) { | |
186 | rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop); | |
187 | rtctl.nexthop = me->nexthop->id; | |
188 | rtctl.remote_label = me->map.label; | |
189 | lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD, 0, pid, | |
8429abe0 RW |
190 | &rtctl, sizeof(rtctl)); |
191 | } | |
0f7b5df9 RW |
192 | lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END, 0, pid, &rtctl, |
193 | sizeof(rtctl)); | |
8429abe0 RW |
194 | } |
195 | } | |
196 | ||
197 | void | |
198 | fec_snap(struct lde_nbr *ln) | |
199 | { | |
200 | struct fec *f; | |
201 | struct fec_node *fn; | |
202 | ||
203 | RB_FOREACH(f, fec_tree, &ft) { | |
204 | fn = (struct fec_node *)f; | |
205 | if (fn->local_label == NO_LABEL) | |
206 | continue; | |
207 | ||
208 | lde_send_labelmapping(ln, fn, 0); | |
209 | } | |
210 | ||
211 | lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0); | |
212 | } | |
213 | ||
214 | static void | |
215 | fec_free(void *arg) | |
216 | { | |
217 | struct fec_node *fn = arg; | |
218 | struct fec_nh *fnh; | |
219 | ||
11bf8e13 | 220 | while ((fnh = LIST_FIRST(&fn->nexthops))) { |
8429abe0 | 221 | fec_nh_del(fnh); |
11bf8e13 RW |
222 | assert(fnh != LIST_FIRST(&fn->nexthops)); |
223 | } | |
45926e58 | 224 | if (!RB_EMPTY(lde_map_head, &fn->downstream)) |
8429abe0 RW |
225 | log_warnx("%s: fec %s downstream list not empty", __func__, |
226 | log_fec(&fn->fec)); | |
45926e58 | 227 | if (!RB_EMPTY(lde_map_head, &fn->upstream)) |
8429abe0 RW |
228 | log_warnx("%s: fec %s upstream list not empty", __func__, |
229 | log_fec(&fn->fec)); | |
230 | ||
231 | free(fn); | |
232 | } | |
233 | ||
234 | void | |
235 | fec_tree_clear(void) | |
236 | { | |
237 | fec_clear(&ft, fec_free); | |
238 | } | |
239 | ||
240 | static struct fec_node * | |
241 | fec_add(struct fec *fec) | |
242 | { | |
243 | struct fec_node *fn; | |
244 | ||
245 | fn = calloc(1, sizeof(*fn)); | |
246 | if (fn == NULL) | |
247 | fatal(__func__); | |
248 | ||
249 | fn->fec = *fec; | |
250 | fn->local_label = NO_LABEL; | |
45926e58 RZ |
251 | RB_INIT(lde_map_head, &fn->upstream); |
252 | RB_INIT(lde_map_head, &fn->downstream); | |
8429abe0 RW |
253 | LIST_INIT(&fn->nexthops); |
254 | ||
4272a064 KS |
255 | if (fec->type == FEC_TYPE_PWID) |
256 | fn->pw_remote_status = PW_FORWARDING; | |
257 | ||
8429abe0 | 258 | if (fec_insert(&ft, &fn->fec)) |
849d8f2b | 259 | log_warnx("failed to add %s to ft tree", log_fec(&fn->fec)); |
8429abe0 RW |
260 | |
261 | return (fn); | |
262 | } | |
263 | ||
264 | struct fec_nh * | |
265 | fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop, | |
e132dea0 | 266 | ifindex_t ifindex, uint8_t route_type, unsigned short route_instance) |
8429abe0 RW |
267 | { |
268 | struct fec_nh *fnh; | |
269 | ||
270 | LIST_FOREACH(fnh, &fn->nexthops, entry) | |
271 | if (fnh->af == af && | |
272 | ldp_addrcmp(af, &fnh->nexthop, nexthop) == 0 && | |
88d88a9c | 273 | fnh->ifindex == ifindex && |
e132dea0 RW |
274 | fnh->route_type == route_type && |
275 | fnh->route_instance == route_instance) | |
8429abe0 RW |
276 | return (fnh); |
277 | ||
278 | return (NULL); | |
279 | } | |
280 | ||
281 | static struct fec_nh * | |
282 | fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop, | |
e132dea0 | 283 | ifindex_t ifindex, uint8_t route_type, unsigned short route_instance) |
8429abe0 RW |
284 | { |
285 | struct fec_nh *fnh; | |
286 | ||
287 | fnh = calloc(1, sizeof(*fnh)); | |
288 | if (fnh == NULL) | |
289 | fatal(__func__); | |
290 | ||
291 | fnh->af = af; | |
292 | fnh->nexthop = *nexthop; | |
88d88a9c | 293 | fnh->ifindex = ifindex; |
8429abe0 | 294 | fnh->remote_label = NO_LABEL; |
e132dea0 RW |
295 | fnh->route_type = route_type; |
296 | fnh->route_instance = route_instance; | |
8429abe0 RW |
297 | LIST_INSERT_HEAD(&fn->nexthops, fnh, entry); |
298 | ||
299 | return (fnh); | |
300 | } | |
301 | ||
302 | static void | |
303 | fec_nh_del(struct fec_nh *fnh) | |
304 | { | |
305 | LIST_REMOVE(fnh, entry); | |
306 | free(fnh); | |
307 | } | |
308 | ||
8429abe0 RW |
309 | void |
310 | lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop, | |
e132dea0 RW |
311 | ifindex_t ifindex, uint8_t route_type, unsigned short route_instance, |
312 | int connected, void *data) | |
8429abe0 RW |
313 | { |
314 | struct fec_node *fn; | |
315 | struct fec_nh *fnh; | |
aff1743c | 316 | struct iface *iface; |
8429abe0 RW |
317 | |
318 | fn = (struct fec_node *)fec_find(&ft, fec); | |
319 | if (fn == NULL) | |
320 | fn = fec_add(fec); | |
8cb1fc45 | 321 | if (data) |
8429abe0 RW |
322 | fn->data = data; |
323 | ||
e132dea0 | 324 | fnh = fec_nh_find(fn, af, nexthop, ifindex, route_type, route_instance); |
aff1743c | 325 | if (fnh == NULL) { |
e132dea0 RW |
326 | fnh = fec_nh_add(fn, af, nexthop, ifindex, route_type, |
327 | route_instance); | |
aff1743c KS |
328 | /* |
329 | * Ordered Control: if not a connected route and not a route | |
330 | * learned over an interface not running LDP and not a PW | |
331 | * then mark to wait until we receive labelmap msg before | |
332 | * installing in kernel and sending to peer | |
333 | */ | |
334 | iface = if_lookup(ldeconf, ifindex); | |
849d8f2b | 335 | if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL) && |
aff1743c | 336 | !connected && iface != NULL && fec->type != FEC_TYPE_PWID) |
849d8f2b | 337 | SET_FLAG(fnh->flags, F_FEC_NH_DEFER); |
aff1743c KS |
338 | } |
339 | ||
849d8f2b | 340 | SET_FLAG(fnh->flags, F_FEC_NH_NEW); |
8cb1fc45 | 341 | if (connected) |
849d8f2b | 342 | SET_FLAG(fnh->flags, F_FEC_NH_CONNECTED); |
8429abe0 RW |
343 | } |
344 | ||
345 | void | |
346 | lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop, | |
e132dea0 | 347 | ifindex_t ifindex, uint8_t route_type, unsigned short route_instance) |
8429abe0 RW |
348 | { |
349 | struct fec_node *fn; | |
350 | struct fec_nh *fnh; | |
351 | ||
352 | fn = (struct fec_node *)fec_find(&ft, fec); | |
353 | if (fn == NULL) | |
354 | /* route lost */ | |
355 | return; | |
e132dea0 | 356 | fnh = fec_nh_find(fn, af, nexthop, ifindex, route_type, route_instance); |
8429abe0 RW |
357 | if (fnh == NULL) |
358 | /* route lost */ | |
359 | return; | |
360 | ||
8429abe0 RW |
361 | lde_send_delete_klabel(fn, fnh); |
362 | fec_nh_del(fnh); | |
8429abe0 RW |
363 | } |
364 | ||
134970a2 RW |
365 | /* |
366 | * Whenever a route is changed, zebra advertises its new version without | |
367 | * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD | |
368 | * message, we need to check for nexthops that were removed and, for each of | |
369 | * them (if any), withdraw the associated labels from zebra. | |
370 | */ | |
371 | void | |
8cb1fc45 | 372 | lde_kernel_update(struct fec *fec) |
134970a2 RW |
373 | { |
374 | struct fec_node *fn; | |
375 | struct fec_nh *fnh, *safe; | |
8cb1fc45 RW |
376 | struct lde_nbr *ln; |
377 | struct lde_map *me; | |
aff1743c | 378 | struct iface *iface; |
134970a2 RW |
379 | |
380 | fn = (struct fec_node *)fec_find(&ft, fec); | |
381 | if (fn == NULL) | |
382 | return; | |
383 | ||
384 | LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) { | |
849d8f2b | 385 | if (CHECK_FLAG(fnh->flags, F_FEC_NH_NEW)) { |
386 | UNSET_FLAG(fnh->flags, F_FEC_NH_NEW); | |
aff1743c KS |
387 | /* |
388 | * if LDP configured on interface or a static route | |
389 | * clear flag else treat fec as a connected route | |
390 | */ | |
849d8f2b | 391 | if (CHECK_FLAG(ldeconf->flags, F_LDPD_ENABLED)) { |
95535717 | 392 | iface = if_lookup(ldeconf,fnh->ifindex); |
849d8f2b | 393 | if (CHECK_FLAG(fnh->flags, F_FEC_NH_CONNECTED) || |
95535717 | 394 | iface || |
395 | fnh->route_type == ZEBRA_ROUTE_STATIC) | |
849d8f2b | 396 | UNSET_FLAG(fnh->flags, F_FEC_NH_NO_LDP); |
95535717 | 397 | else |
849d8f2b | 398 | SET_FLAG(fnh->flags, F_FEC_NH_NO_LDP); |
95535717 | 399 | } else |
849d8f2b | 400 | SET_FLAG(fnh->flags, F_FEC_NH_NO_LDP); |
aff1743c | 401 | } else { |
8cb1fc45 RW |
402 | lde_send_delete_klabel(fn, fnh); |
403 | fec_nh_del(fnh); | |
404 | } | |
405 | } | |
406 | ||
407 | if (LIST_EMPTY(&fn->nexthops)) { | |
0bcc2916 RW |
408 | RB_FOREACH(ln, nbr_tree, &lde_nbrs) |
409 | lde_send_labelwithdraw(ln, fn, NULL, NULL); | |
8cb1fc45 | 410 | fn->data = NULL; |
8cb1fc45 | 411 | |
095f12f9 RW |
412 | /* |
413 | * Do not deallocate the local label now, do that only in the | |
414 | * LIB garbage collector. This will prevent ldpd from changing | |
415 | * the input label of some prefixes too often when running on | |
416 | * an unstable network. Also, restart the garbage collector | |
417 | * timer so that labels are deallocated only when the network | |
418 | * is stabilized. | |
419 | */ | |
420 | lde_gc_start_timer(); | |
421 | } else { | |
8cb1fc45 | 422 | fn->local_label = lde_update_label(fn); |
b4fcca6b | 423 | if (fn->local_label != NO_LABEL) |
8cb1fc45 RW |
424 | /* FEC.1: perform lsr label distribution procedure */ |
425 | RB_FOREACH(ln, nbr_tree, &lde_nbrs) | |
426 | lde_send_labelmapping(ln, fn, 1); | |
8cb1fc45 RW |
427 | } |
428 | ||
95535717 | 429 | /* if no label created yet then don't try to program labeled route */ |
430 | if (fn->local_label == NO_LABEL) | |
431 | return; | |
432 | ||
8cb1fc45 RW |
433 | LIST_FOREACH(fnh, &fn->nexthops, entry) { |
434 | lde_send_change_klabel(fn, fnh); | |
435 | ||
436 | switch (fn->fec.type) { | |
437 | case FEC_TYPE_IPV4: | |
438 | case FEC_TYPE_IPV6: | |
439 | ln = lde_nbr_find_by_addr(fnh->af, &fnh->nexthop); | |
440 | break; | |
441 | case FEC_TYPE_PWID: | |
442 | ln = lde_nbr_find_by_lsrid(fn->fec.u.pwid.lsr_id); | |
443 | break; | |
444 | default: | |
445 | ln = NULL; | |
446 | break; | |
447 | } | |
448 | ||
449 | if (ln) { | |
450 | /* FEC.2 */ | |
451 | me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec); | |
452 | if (me) | |
453 | /* FEC.5 */ | |
4272a064 | 454 | lde_check_mapping(&me->map, ln, 0); |
8cb1fc45 | 455 | } |
134970a2 RW |
456 | } |
457 | } | |
458 | ||
8429abe0 | 459 | void |
4272a064 | 460 | lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping) |
8429abe0 RW |
461 | { |
462 | struct fec fec; | |
463 | struct fec_node *fn; | |
464 | struct fec_nh *fnh; | |
465 | struct lde_req *lre; | |
466 | struct lde_map *me; | |
467 | struct l2vpn_pw *pw; | |
aff1743c | 468 | bool send_map = false; |
8429abe0 RW |
469 | |
470 | lde_map2fec(map, ln->id, &fec); | |
45a8eba9 RW |
471 | |
472 | switch (fec.type) { | |
473 | case FEC_TYPE_IPV4: | |
474 | if (lde_acl_check(ldeconf->ipv4.acl_label_accept_from, | |
475 | AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT) | |
476 | return; | |
477 | if (lde_acl_check(ldeconf->ipv4.acl_label_accept_for, | |
478 | AF_INET, (union ldpd_addr *)&fec.u.ipv4.prefix, | |
479 | fec.u.ipv4.prefixlen) != FILTER_PERMIT) | |
480 | return; | |
481 | break; | |
482 | case FEC_TYPE_IPV6: | |
483 | if (lde_acl_check(ldeconf->ipv6.acl_label_accept_from, | |
484 | AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT) | |
485 | return; | |
486 | if (lde_acl_check(ldeconf->ipv6.acl_label_accept_for, | |
487 | AF_INET6, (union ldpd_addr *)&fec.u.ipv6.prefix, | |
488 | fec.u.ipv6.prefixlen) != FILTER_PERMIT) | |
489 | return; | |
490 | break; | |
4a055ac2 | 491 | case FEC_TYPE_PWID: |
45a8eba9 RW |
492 | break; |
493 | } | |
494 | ||
8429abe0 RW |
495 | fn = (struct fec_node *)fec_find(&ft, &fec); |
496 | if (fn == NULL) | |
497 | fn = fec_add(&fec); | |
498 | ||
499 | /* LMp.1: first check if we have a pending request running */ | |
500 | lre = (struct lde_req *)fec_find(&ln->sent_req, &fn->fec); | |
501 | if (lre) | |
502 | /* LMp.2: delete record of outstanding label request */ | |
503 | lde_req_del(ln, lre, 1); | |
504 | ||
505 | /* RFC 4447 control word and status tlv negotiation */ | |
4272a064 | 506 | if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map)) { |
849d8f2b | 507 | if (rcvd_label_mapping && CHECK_FLAG(map->flags, F_MAP_PW_STATUS)) |
4272a064 KS |
508 | fn->pw_remote_status = map->pw_status; |
509 | ||
8429abe0 | 510 | return; |
4272a064 | 511 | } |
8429abe0 RW |
512 | |
513 | /* | |
514 | * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode | |
515 | * mpls networks. | |
516 | */ | |
517 | ||
518 | /* LMp.9 */ | |
519 | me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec); | |
520 | if (me) { | |
521 | /* LMp.10 */ | |
522 | if (me->map.label != map->label && lre == NULL) { | |
523 | /* LMp.10a */ | |
0bcc2916 | 524 | lde_send_labelrelease(ln, fn, NULL, me->map.label); |
8429abe0 RW |
525 | |
526 | /* | |
527 | * Can not use lde_nbr_find_by_addr() because there's | |
528 | * the possibility of multipath. | |
529 | */ | |
530 | LIST_FOREACH(fnh, &fn->nexthops, entry) { | |
849d8f2b | 531 | if (lde_address_find(ln, fnh->af, &fnh->nexthop) == NULL) |
8429abe0 RW |
532 | continue; |
533 | ||
534 | lde_send_delete_klabel(fn, fnh); | |
535 | fnh->remote_label = NO_LABEL; | |
536 | } | |
537 | } | |
538 | } | |
539 | ||
540 | /* | |
541 | * LMp.11 - 12: consider multiple nexthops in order to | |
542 | * support multipath | |
543 | */ | |
544 | LIST_FOREACH(fnh, &fn->nexthops, entry) { | |
545 | /* LMp.15: install FEC in FIB */ | |
546 | switch (fec.type) { | |
547 | case FEC_TYPE_IPV4: | |
548 | case FEC_TYPE_IPV6: | |
549 | if (!lde_address_find(ln, fnh->af, &fnh->nexthop)) | |
550 | continue; | |
551 | ||
aff1743c KS |
552 | /* |
553 | * Ordered Control: labelmap msg received from | |
554 | * NH so clear flag and send labelmap msg to | |
555 | * peer | |
556 | */ | |
849d8f2b | 557 | if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) { |
aff1743c | 558 | send_map = true; |
849d8f2b | 559 | UNSET_FLAG(fnh->flags, F_FEC_NH_DEFER); |
aff1743c | 560 | } |
8429abe0 | 561 | fnh->remote_label = map->label; |
95535717 | 562 | if (fn->local_label != NO_LABEL) |
563 | lde_send_change_klabel(fn, fnh); | |
8429abe0 RW |
564 | break; |
565 | case FEC_TYPE_PWID: | |
566 | pw = (struct l2vpn_pw *) fn->data; | |
567 | if (pw == NULL) | |
568 | continue; | |
569 | ||
570 | pw->remote_group = map->fec.pwid.group_id; | |
849d8f2b | 571 | if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU)) |
8429abe0 | 572 | pw->remote_mtu = map->fec.pwid.ifmtu; |
849d8f2b | 573 | if (rcvd_label_mapping && CHECK_FLAG(map->flags, F_MAP_PW_STATUS)) { |
8429abe0 | 574 | pw->remote_status = map->pw_status; |
4272a064 KS |
575 | fn->pw_remote_status = map->pw_status; |
576 | } | |
87b5f1b7 RW |
577 | else |
578 | pw->remote_status = PW_FORWARDING; | |
8429abe0 RW |
579 | fnh->remote_label = map->label; |
580 | if (l2vpn_pw_ok(pw, fnh)) | |
581 | lde_send_change_klabel(fn, fnh); | |
582 | break; | |
583 | default: | |
584 | break; | |
585 | } | |
8429abe0 | 586 | } |
077d336a RW |
587 | |
588 | /* Update RLFA clients. */ | |
589 | lde_rlfa_update_clients(&fec, ln, map->label); | |
590 | ||
8429abe0 RW |
591 | /* LMp.13 & LMp.16: Record the mapping from this peer */ |
592 | if (me == NULL) | |
593 | me = lde_map_add(ln, fn, 0); | |
594 | me->map = *map; | |
595 | ||
8429abe0 RW |
596 | /* |
597 | * LMp.17 - LMp.27 are unnecessary since we don't need to implement | |
598 | * loop detection. LMp.28 - LMp.30 are unnecessary because we are | |
599 | * merging capable. | |
600 | */ | |
aff1743c KS |
601 | |
602 | /* | |
603 | * Ordered Control: just received a labelmap for this fec from NH so | |
604 | * need to send labelmap to all peers | |
605 | * LMp.20 - LMp21 Execute procedure to send Label Mapping | |
606 | */ | |
607 | if (send_map && fn->local_label != NO_LABEL) | |
608 | RB_FOREACH(ln, nbr_tree, &lde_nbrs) | |
609 | lde_send_labelmapping(ln, fn, 1); | |
8429abe0 RW |
610 | } |
611 | ||
612 | void | |
613 | lde_check_request(struct map *map, struct lde_nbr *ln) | |
614 | { | |
615 | struct fec fec; | |
616 | struct lde_req *lre; | |
617 | struct fec_node *fn; | |
618 | struct fec_nh *fnh; | |
619 | ||
d4afb819 RW |
620 | /* wildcard label request */ |
621 | if (map->type == MAP_TYPE_TYPED_WCARD) { | |
622 | lde_check_request_wcard(map, ln); | |
623 | return; | |
624 | } | |
625 | ||
8429abe0 RW |
626 | /* LRq.1: skip loop detection (not necessary) */ |
627 | ||
628 | /* LRq.2: is there a next hop for fec? */ | |
629 | lde_map2fec(map, ln->id, &fec); | |
630 | fn = (struct fec_node *)fec_find(&ft, &fec); | |
631 | if (fn == NULL || LIST_EMPTY(&fn->nexthops)) { | |
632 | /* LRq.5: send No Route notification */ | |
05aac414 | 633 | lde_send_notification(ln, S_NO_ROUTE, map->msg_id, |
8429abe0 RW |
634 | htons(MSG_TYPE_LABELREQUEST)); |
635 | return; | |
636 | } | |
637 | ||
638 | /* LRq.3: is MsgSource the next hop? */ | |
639 | LIST_FOREACH(fnh, &fn->nexthops, entry) { | |
640 | switch (fec.type) { | |
641 | case FEC_TYPE_IPV4: | |
642 | case FEC_TYPE_IPV6: | |
643 | if (!lde_address_find(ln, fnh->af, &fnh->nexthop)) | |
644 | continue; | |
645 | ||
646 | /* LRq.4: send Loop Detected notification */ | |
05aac414 RW |
647 | lde_send_notification(ln, S_LOOP_DETECTED, map->msg_id, |
648 | htons(MSG_TYPE_LABELREQUEST)); | |
8429abe0 | 649 | return; |
4a055ac2 | 650 | case FEC_TYPE_PWID: |
8429abe0 RW |
651 | break; |
652 | } | |
653 | } | |
654 | ||
655 | /* LRq.6: first check if we have a pending request running */ | |
656 | lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec); | |
657 | if (lre != NULL) | |
658 | /* LRq.7: duplicate request */ | |
659 | return; | |
660 | ||
661 | /* LRq.8: record label request */ | |
662 | lre = lde_req_add(ln, &fn->fec, 0); | |
663 | if (lre != NULL) | |
664 | lre->msg_id = ntohl(map->msg_id); | |
665 | ||
666 | /* LRq.9: perform LSR label distribution */ | |
667 | lde_send_labelmapping(ln, fn, 1); | |
668 | ||
669 | /* | |
670 | * LRq.10: do nothing (Request Never) since we use liberal | |
671 | * label retention. | |
672 | * LRq.11 - 12 are unnecessary since we are merging capable. | |
673 | */ | |
674 | } | |
675 | ||
d4afb819 RW |
676 | void |
677 | lde_check_request_wcard(struct map *map, struct lde_nbr *ln) | |
678 | { | |
679 | struct fec *f; | |
680 | struct fec_node *fn; | |
681 | struct lde_req *lre; | |
682 | ||
683 | RB_FOREACH(f, fec_tree, &ft) { | |
684 | fn = (struct fec_node *)f; | |
685 | ||
686 | /* only a typed wildcard is possible here */ | |
687 | if (lde_wildcard_apply(map, &fn->fec, NULL) == 0) | |
688 | continue; | |
689 | ||
690 | /* LRq.2: is there a next hop for fec? */ | |
691 | if (LIST_EMPTY(&fn->nexthops)) | |
692 | continue; | |
693 | ||
694 | /* LRq.6: first check if we have a pending request running */ | |
695 | lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec); | |
696 | if (lre != NULL) | |
697 | /* LRq.7: duplicate request */ | |
698 | continue; | |
699 | ||
700 | /* LRq.8: record label request */ | |
701 | lre = lde_req_add(ln, &fn->fec, 0); | |
702 | if (lre != NULL) | |
703 | lre->msg_id = ntohl(map->msg_id); | |
704 | ||
705 | /* LRq.9: perform LSR label distribution */ | |
706 | lde_send_labelmapping(ln, fn, 1); | |
707 | } | |
708 | } | |
709 | ||
8429abe0 RW |
710 | void |
711 | lde_check_release(struct map *map, struct lde_nbr *ln) | |
712 | { | |
713 | struct fec fec; | |
714 | struct fec_node *fn; | |
715 | struct lde_wdraw *lw; | |
716 | struct lde_map *me; | |
7c2abbd7 | 717 | struct fec *pending_map; |
8429abe0 | 718 | |
0bcc2916 RW |
719 | /* wildcard label release */ |
720 | if (map->type == MAP_TYPE_WILDCARD || | |
d4afb819 | 721 | map->type == MAP_TYPE_TYPED_WCARD || |
849d8f2b | 722 | (map->type == MAP_TYPE_PWID && !CHECK_FLAG(map->flags, F_MAP_PW_ID))) { |
0bcc2916 | 723 | lde_check_release_wcard(map, ln); |
8429abe0 | 724 | return; |
0bcc2916 | 725 | } |
8429abe0 RW |
726 | |
727 | lde_map2fec(map, ln->id, &fec); | |
728 | fn = (struct fec_node *)fec_find(&ft, &fec); | |
729 | /* LRl.1: does FEC match a known FEC? */ | |
730 | if (fn == NULL) | |
731 | return; | |
732 | ||
7c2abbd7 RW |
733 | /* LRl.6: check sent map list and remove it if available */ |
734 | me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec); | |
735 | if (me && (map->label == NO_LABEL || map->label == me->map.label)) | |
736 | lde_map_del(ln, me, 1); | |
737 | ||
8429abe0 RW |
738 | /* LRl.3: first check if we have a pending withdraw running */ |
739 | lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); | |
be8e0d31 | 740 | if (lw && (map->label == NO_LABEL || map->label == lw->label)) { |
8429abe0 RW |
741 | /* LRl.4: delete record of outstanding label withdraw */ |
742 | lde_wdraw_del(ln, lw); | |
8429abe0 | 743 | |
7c2abbd7 RW |
744 | /* send pending label mapping if any */ |
745 | pending_map = fec_find(&ln->sent_map_pending, &fn->fec); | |
746 | if (pending_map) { | |
747 | lde_send_labelmapping(ln, fn, 1); | |
748 | lde_map_pending_del(ln, pending_map); | |
749 | } | |
750 | } | |
8429abe0 RW |
751 | |
752 | /* | |
753 | * LRl.11 - 13 are unnecessary since we remove the label from | |
754 | * forwarding/switching as soon as the FEC is unreachable. | |
755 | */ | |
756 | } | |
757 | ||
758 | void | |
759 | lde_check_release_wcard(struct map *map, struct lde_nbr *ln) | |
760 | { | |
761 | struct fec *f; | |
762 | struct fec_node *fn; | |
763 | struct lde_wdraw *lw; | |
764 | struct lde_map *me; | |
7c2abbd7 | 765 | struct fec *pending_map; |
8429abe0 RW |
766 | |
767 | RB_FOREACH(f, fec_tree, &ft) { | |
768 | fn = (struct fec_node *)f; | |
0bcc2916 RW |
769 | me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec); |
770 | ||
771 | /* LRl.1: does FEC match a known FEC? */ | |
772 | if (lde_wildcard_apply(map, &fn->fec, me) == 0) | |
773 | continue; | |
8429abe0 | 774 | |
7c2abbd7 RW |
775 | /* LRl.6: check sent map list and remove it if available */ |
776 | if (me && | |
777 | (map->label == NO_LABEL || map->label == me->map.label)) | |
778 | lde_map_del(ln, me, 1); | |
779 | ||
8429abe0 RW |
780 | /* LRl.3: first check if we have a pending withdraw running */ |
781 | lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); | |
be8e0d31 | 782 | if (lw && (map->label == NO_LABEL || map->label == lw->label)) { |
8429abe0 RW |
783 | /* LRl.4: delete record of outstanding lbl withdraw */ |
784 | lde_wdraw_del(ln, lw); | |
8429abe0 | 785 | |
7c2abbd7 RW |
786 | /* send pending label mapping if any */ |
787 | pending_map = fec_find(&ln->sent_map_pending, &fn->fec); | |
788 | if (pending_map) { | |
789 | lde_send_labelmapping(ln, fn, 1); | |
790 | lde_map_pending_del(ln, pending_map); | |
791 | } | |
792 | } | |
8429abe0 RW |
793 | |
794 | /* | |
795 | * LRl.11 - 13 are unnecessary since we remove the label from | |
796 | * forwarding/switching as soon as the FEC is unreachable. | |
797 | */ | |
798 | } | |
799 | } | |
800 | ||
801 | void | |
802 | lde_check_withdraw(struct map *map, struct lde_nbr *ln) | |
803 | { | |
804 | struct fec fec; | |
805 | struct fec_node *fn; | |
806 | struct fec_nh *fnh; | |
807 | struct lde_map *me; | |
808 | struct l2vpn_pw *pw; | |
aff1743c | 809 | struct lde_nbr *lnbr; |
8429abe0 | 810 | |
0bcc2916 RW |
811 | /* wildcard label withdraw */ |
812 | if (map->type == MAP_TYPE_WILDCARD || | |
d4afb819 | 813 | map->type == MAP_TYPE_TYPED_WCARD || |
849d8f2b | 814 | (map->type == MAP_TYPE_PWID && !CHECK_FLAG(map->flags, F_MAP_PW_ID))) { |
0bcc2916 | 815 | lde_check_withdraw_wcard(map, ln); |
8429abe0 | 816 | return; |
0bcc2916 | 817 | } |
8429abe0 RW |
818 | |
819 | lde_map2fec(map, ln->id, &fec); | |
820 | fn = (struct fec_node *)fec_find(&ft, &fec); | |
821 | if (fn == NULL) | |
822 | fn = fec_add(&fec); | |
823 | ||
824 | /* LWd.1: remove label from forwarding/switching use */ | |
825 | LIST_FOREACH(fnh, &fn->nexthops, entry) { | |
826 | switch (fec.type) { | |
827 | case FEC_TYPE_IPV4: | |
828 | case FEC_TYPE_IPV6: | |
829 | if (!lde_address_find(ln, fnh->af, &fnh->nexthop)) | |
830 | continue; | |
831 | break; | |
832 | case FEC_TYPE_PWID: | |
833 | pw = (struct l2vpn_pw *) fn->data; | |
834 | if (pw == NULL) | |
835 | continue; | |
87b5f1b7 | 836 | pw->remote_status = PW_NOT_FORWARDING; |
8429abe0 RW |
837 | break; |
838 | default: | |
839 | break; | |
840 | } | |
be8e0d31 RW |
841 | if (map->label != NO_LABEL && map->label != fnh->remote_label) |
842 | continue; | |
843 | ||
8429abe0 RW |
844 | lde_send_delete_klabel(fn, fnh); |
845 | fnh->remote_label = NO_LABEL; | |
846 | } | |
847 | ||
077d336a RW |
848 | /* Update RLFA clients. */ |
849 | lde_rlfa_update_clients(&fec, ln, MPLS_INVALID_LABEL); | |
850 | ||
8429abe0 | 851 | /* LWd.2: send label release */ |
0bcc2916 | 852 | lde_send_labelrelease(ln, fn, NULL, map->label); |
8429abe0 RW |
853 | |
854 | /* LWd.3: check previously received label mapping */ | |
855 | me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec); | |
856 | if (me && (map->label == NO_LABEL || map->label == me->map.label)) | |
857 | /* LWd.4: remove record of previously received lbl mapping */ | |
858 | lde_map_del(ln, me, 0); | |
8dfdf235 | 859 | else |
860 | /* LWd.13 done */ | |
861 | return; | |
aff1743c KS |
862 | |
863 | /* Ordered Control: additional withdraw steps */ | |
849d8f2b | 864 | if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) { |
aff1743c KS |
865 | /* LWd.8: for each neighbor other that src of withdraw msg */ |
866 | RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) { | |
867 | if (ln->peerid == lnbr->peerid) | |
868 | continue; | |
869 | ||
870 | /* LWd.9: check if previously sent a label mapping */ | |
03522238 | 871 | me = (struct lde_map *)fec_find(&lnbr->sent_map, &fn->fec); |
8dfdf235 | 872 | |
aff1743c KS |
873 | /* |
874 | * LWd.10: does label sent to peer "map" to withdraw | |
875 | * label | |
876 | */ | |
8dfdf235 | 877 | if (me && lde_nbr_is_nexthop(fn, lnbr)) |
aff1743c KS |
878 | /* LWd.11: send label withdraw */ |
879 | lde_send_labelwithdraw(lnbr, fn, NULL, NULL); | |
880 | } | |
881 | } | |
8dfdf235 | 882 | |
8429abe0 RW |
883 | } |
884 | ||
885 | void | |
886 | lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) | |
887 | { | |
888 | struct fec *f; | |
889 | struct fec_node *fn; | |
890 | struct fec_nh *fnh; | |
891 | struct lde_map *me; | |
87b5f1b7 | 892 | struct l2vpn_pw *pw; |
aff1743c | 893 | struct lde_nbr *lnbr; |
8429abe0 RW |
894 | |
895 | /* LWd.2: send label release */ | |
0bcc2916 | 896 | lde_send_labelrelease(ln, NULL, map, map->label); |
8429abe0 RW |
897 | |
898 | RB_FOREACH(f, fec_tree, &ft) { | |
899 | fn = (struct fec_node *)f; | |
0bcc2916 RW |
900 | me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec); |
901 | ||
902 | if (lde_wildcard_apply(map, &fn->fec, me) == 0) | |
903 | continue; | |
8429abe0 RW |
904 | |
905 | /* LWd.1: remove label from forwarding/switching use */ | |
906 | LIST_FOREACH(fnh, &fn->nexthops, entry) { | |
907 | switch (f->type) { | |
908 | case FEC_TYPE_IPV4: | |
909 | case FEC_TYPE_IPV6: | |
03522238 | 910 | if (!lde_address_find(ln, fnh->af, &fnh->nexthop)) |
8429abe0 RW |
911 | continue; |
912 | break; | |
913 | case FEC_TYPE_PWID: | |
914 | if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr) | |
915 | continue; | |
87b5f1b7 RW |
916 | pw = (struct l2vpn_pw *) fn->data; |
917 | if (pw) | |
918 | pw->remote_status = PW_NOT_FORWARDING; | |
8429abe0 RW |
919 | break; |
920 | default: | |
921 | break; | |
922 | } | |
849d8f2b | 923 | if (map->label != NO_LABEL && map->label != fnh->remote_label) |
be8e0d31 RW |
924 | continue; |
925 | ||
8429abe0 RW |
926 | lde_send_delete_klabel(fn, fnh); |
927 | fnh->remote_label = NO_LABEL; | |
928 | } | |
929 | ||
077d336a RW |
930 | /* Update RLFA clients. */ |
931 | lde_rlfa_update_clients(f, ln, MPLS_INVALID_LABEL); | |
932 | ||
8429abe0 | 933 | /* LWd.3: check previously received label mapping */ |
849d8f2b | 934 | if (me && (map->label == NO_LABEL || map->label == me->map.label)) |
8429abe0 RW |
935 | /* |
936 | * LWd.4: remove record of previously received | |
937 | * label mapping | |
938 | */ | |
939 | lde_map_del(ln, me, 0); | |
8dfdf235 | 940 | else |
941 | /* LWd.13 done */ | |
942 | continue; | |
aff1743c KS |
943 | |
944 | /* Ordered Control: additional withdraw steps */ | |
849d8f2b | 945 | if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) { |
8dfdf235 | 946 | /* |
947 | * LWd.8: for each neighbor other that src of | |
948 | * withdraw msg | |
949 | */ | |
aff1743c KS |
950 | RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) { |
951 | if (ln->peerid == lnbr->peerid) | |
952 | continue; | |
953 | ||
8dfdf235 | 954 | /* LWd.9: check if previously sent a label |
955 | * mapping | |
956 | */ | |
849d8f2b | 957 | me = (struct lde_map *)fec_find(&lnbr->sent_map, &fn->fec); |
aff1743c | 958 | /* |
8dfdf235 | 959 | * LWd.10: does label sent to peer "map" to |
960 | * withdraw label | |
aff1743c | 961 | */ |
8dfdf235 | 962 | if (me && lde_nbr_is_nexthop(fn, lnbr)) |
aff1743c | 963 | /* LWd.11: send label withdraw */ |
849d8f2b | 964 | lde_send_labelwithdraw(lnbr, fn, NULL, NULL); |
aff1743c KS |
965 | } |
966 | } | |
8429abe0 RW |
967 | } |
968 | } | |
969 | ||
0bcc2916 RW |
970 | int |
971 | lde_wildcard_apply(struct map *wcard, struct fec *fec, struct lde_map *me) | |
972 | { | |
973 | switch (wcard->type) { | |
974 | case MAP_TYPE_WILDCARD: | |
975 | /* full wildcard */ | |
976 | return (1); | |
d4afb819 RW |
977 | case MAP_TYPE_TYPED_WCARD: |
978 | switch (wcard->fec.twcard.type) { | |
979 | case MAP_TYPE_PREFIX: | |
980 | if (wcard->fec.twcard.u.prefix_af == AF_INET && | |
981 | fec->type != FEC_TYPE_IPV4) | |
982 | return (0); | |
983 | if (wcard->fec.twcard.u.prefix_af == AF_INET6 && | |
984 | fec->type != FEC_TYPE_IPV6) | |
985 | return (0); | |
986 | return (1); | |
aba50a83 RW |
987 | case MAP_TYPE_PWID: |
988 | if (fec->type != FEC_TYPE_PWID) | |
989 | return (0); | |
990 | if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD && | |
991 | wcard->fec.twcard.u.pw_type != fec->u.pwid.type) | |
992 | return (0); | |
993 | return (1); | |
d4afb819 RW |
994 | default: |
995 | fatalx("lde_wildcard_apply: unexpected fec type"); | |
996 | } | |
997 | break; | |
0bcc2916 RW |
998 | case MAP_TYPE_PWID: |
999 | /* RFC4447 pw-id group wildcard */ | |
1000 | if (fec->type != FEC_TYPE_PWID) | |
1001 | return (0); | |
1002 | if (fec->u.pwid.type != wcard->fec.pwid.type) | |
1003 | return (0); | |
1004 | if (me == NULL || (me->map.fec.pwid.group_id != | |
1005 | wcard->fec.pwid.group_id)) | |
1006 | return (0); | |
1007 | return (1); | |
1008 | default: | |
1009 | fatalx("lde_wildcard_apply: unexpected fec type"); | |
1010 | } | |
1011 | } | |
1012 | ||
8429abe0 RW |
1013 | /* gabage collector timer: timer to remove dead entries from the LIB */ |
1014 | ||
1015 | /* ARGSUSED */ | |
e6685141 | 1016 | void lde_gc_timer(struct event *thread) |
8429abe0 RW |
1017 | { |
1018 | struct fec *fec, *safe; | |
1019 | struct fec_node *fn; | |
1020 | int count = 0; | |
1021 | ||
1022 | RB_FOREACH_SAFE(fec, fec_tree, &ft, safe) { | |
1023 | fn = (struct fec_node *) fec; | |
1024 | ||
1025 | if (!LIST_EMPTY(&fn->nexthops) || | |
45926e58 RZ |
1026 | !RB_EMPTY(lde_map_head, &fn->downstream) || |
1027 | !RB_EMPTY(lde_map_head, &fn->upstream)) | |
8429abe0 RW |
1028 | continue; |
1029 | ||
f4ec681c BA |
1030 | if (fn->local_label != NO_LABEL) |
1031 | lde_free_label(fn->local_label); | |
1032 | ||
8429abe0 RW |
1033 | fec_remove(&ft, &fn->fec); |
1034 | free(fn); | |
1035 | count++; | |
1036 | } | |
1037 | ||
1038 | if (count > 0) | |
1039 | log_debug("%s: %u entries removed", __func__, count); | |
1040 | ||
1041 | lde_gc_start_timer(); | |
1042 | } | |
1043 | ||
1044 | void | |
1045 | lde_gc_start_timer(void) | |
1046 | { | |
e16d030c | 1047 | EVENT_OFF(gc_timer); |
907a2395 | 1048 | event_add_timer(master, lde_gc_timer, NULL, LDE_GC_INTERVAL, &gc_timer); |
8429abe0 RW |
1049 | } |
1050 | ||
1051 | void | |
1052 | lde_gc_stop_timer(void) | |
1053 | { | |
e16d030c | 1054 | EVENT_OFF(gc_timer); |
8429abe0 | 1055 | } |