1*5b133f3fSguenther /* $OpenBSD: lde_lib.c,v 1.71 2023/03/08 04:43:13 guenther Exp $ */
2ab0c2486Smichele
3ab0c2486Smichele /*
45dc9330aSrenato * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5ab0c2486Smichele * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6ab0c2486Smichele *
7ab0c2486Smichele * Permission to use, copy, modify, and distribute this software for any
8ab0c2486Smichele * purpose with or without fee is hereby granted, provided that the above
9ab0c2486Smichele * copyright notice and this permission notice appear in all copies.
10ab0c2486Smichele *
11ab0c2486Smichele * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12ab0c2486Smichele * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13ab0c2486Smichele * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14ab0c2486Smichele * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15ab0c2486Smichele * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16ab0c2486Smichele * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17ab0c2486Smichele * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18ab0c2486Smichele */
19ab0c2486Smichele
20ab0c2486Smichele #include <sys/types.h>
21ab0c2486Smichele #include <sys/socket.h>
22ab0c2486Smichele #include <netmpls/mpls.h>
23ab0c2486Smichele #include <stdlib.h>
24ab0c2486Smichele #include <string.h>
255411bbb6Srenato #include <limits.h>
26ab0c2486Smichele
27ab0c2486Smichele #include "ldpd.h"
28ab0c2486Smichele #include "lde.h"
299246985aSrenato #include "ldpe.h"
305411bbb6Srenato #include "log.h"
31ab0c2486Smichele
32c28a25a1Srenato static __inline int fec_compare(struct fec *, struct fec *);
33c28a25a1Srenato static int lde_nbr_is_nexthop(struct fec_node *,
34c28a25a1Srenato struct lde_nbr *);
35c28a25a1Srenato static void fec_free(void *);
36c28a25a1Srenato static struct fec_node *fec_add(struct fec *fec);
370c0343b7Srenato static struct fec_nh *fec_nh_add(struct fec_node *, int, union ldpd_addr *,
380c0343b7Srenato uint8_t priority);
39c28a25a1Srenato static void fec_nh_del(struct fec_nh *);
40a094a533Sclaudio
41e3948831Sclaudio RB_GENERATE(fec_tree, fec, entry, fec_compare)
42e3948831Sclaudio
436106bae4Srenato struct fec_tree ft = RB_INITIALIZER(&ft);
44b79e02a8Srenato struct event gc_timer;
45ab0c2486Smichele
468fc45048Smiod /* FEC tree functions */
47ab0c2486Smichele void
fec_init(struct fec_tree * fh)48e3948831Sclaudio fec_init(struct fec_tree *fh)
49ab0c2486Smichele {
50e3948831Sclaudio RB_INIT(fh);
51ab0c2486Smichele }
52ab0c2486Smichele
53c28a25a1Srenato static __inline int
fec_compare(struct fec * a,struct fec * b)54e3948831Sclaudio fec_compare(struct fec *a, struct fec *b)
55ab0c2486Smichele {
566399cec1Srenato if (a->type < b->type)
57ab0c2486Smichele return (-1);
586399cec1Srenato if (a->type > b->type)
59ab0c2486Smichele return (1);
60ab0c2486Smichele
616399cec1Srenato switch (a->type) {
626399cec1Srenato case FEC_TYPE_IPV4:
636399cec1Srenato if (ntohl(a->u.ipv4.prefix.s_addr) <
646399cec1Srenato ntohl(b->u.ipv4.prefix.s_addr))
656399cec1Srenato return (-1);
666399cec1Srenato if (ntohl(a->u.ipv4.prefix.s_addr) >
676399cec1Srenato ntohl(b->u.ipv4.prefix.s_addr))
686399cec1Srenato return (1);
696399cec1Srenato if (a->u.ipv4.prefixlen < b->u.ipv4.prefixlen)
706399cec1Srenato return (-1);
716399cec1Srenato if (a->u.ipv4.prefixlen > b->u.ipv4.prefixlen)
726399cec1Srenato return (1);
73ab0c2486Smichele return (0);
74a8c39dc0Srenato case FEC_TYPE_IPV6:
75a8c39dc0Srenato if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix,
76a8c39dc0Srenato sizeof(struct in6_addr)) < 0)
77a8c39dc0Srenato return (-1);
78a8c39dc0Srenato if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix,
79a8c39dc0Srenato sizeof(struct in6_addr)) > 0)
80a8c39dc0Srenato return (1);
81a8c39dc0Srenato if (a->u.ipv6.prefixlen < b->u.ipv6.prefixlen)
82a8c39dc0Srenato return (-1);
83a8c39dc0Srenato if (a->u.ipv6.prefixlen > b->u.ipv6.prefixlen)
84a8c39dc0Srenato return (1);
85a8c39dc0Srenato return (0);
866399cec1Srenato case FEC_TYPE_PWID:
876399cec1Srenato if (a->u.pwid.type < b->u.pwid.type)
886399cec1Srenato return (-1);
896399cec1Srenato if (a->u.pwid.type > b->u.pwid.type)
906399cec1Srenato return (1);
916399cec1Srenato if (a->u.pwid.pwid < b->u.pwid.pwid)
926399cec1Srenato return (-1);
936399cec1Srenato if (a->u.pwid.pwid > b->u.pwid.pwid)
946399cec1Srenato return (1);
9572bfe95eSrenato if (ntohl(a->u.pwid.lsr_id.s_addr) <
9672bfe95eSrenato ntohl(b->u.pwid.lsr_id.s_addr))
976399cec1Srenato return (-1);
9872bfe95eSrenato if (ntohl(a->u.pwid.lsr_id.s_addr) >
9972bfe95eSrenato ntohl(b->u.pwid.lsr_id.s_addr))
1006399cec1Srenato return (1);
1016399cec1Srenato return (0);
102ab0c2486Smichele }
103ab0c2486Smichele
1046399cec1Srenato return (-1);
105ab0c2486Smichele }
106ab0c2486Smichele
107e3948831Sclaudio struct fec *
fec_find(struct fec_tree * fh,struct fec * f)108e3948831Sclaudio fec_find(struct fec_tree *fh, struct fec *f)
109e3948831Sclaudio {
110e3948831Sclaudio return (RB_FIND(fec_tree, fh, f));
111e3948831Sclaudio }
112e3948831Sclaudio
113ab0c2486Smichele int
fec_insert(struct fec_tree * fh,struct fec * f)114e3948831Sclaudio fec_insert(struct fec_tree *fh, struct fec *f)
115ab0c2486Smichele {
116e3948831Sclaudio if (RB_INSERT(fec_tree, fh, f) != NULL)
117ab0c2486Smichele return (-1);
118ab0c2486Smichele return (0);
119ab0c2486Smichele }
120ab0c2486Smichele
121ab0c2486Smichele int
fec_remove(struct fec_tree * fh,struct fec * f)122e3948831Sclaudio fec_remove(struct fec_tree *fh, struct fec *f)
123ab0c2486Smichele {
124e3948831Sclaudio if (RB_REMOVE(fec_tree, fh, f) == NULL) {
125b7b4db73Srenato log_warnx("%s failed for %s", __func__, log_fec(f));
126ab0c2486Smichele return (-1);
127ab0c2486Smichele }
128ab0c2486Smichele return (0);
129ab0c2486Smichele }
130ab0c2486Smichele
131ab0c2486Smichele void
fec_clear(struct fec_tree * fh,void (* free_cb)(void *))132e3948831Sclaudio fec_clear(struct fec_tree *fh, void (*free_cb)(void *))
133e3948831Sclaudio {
134e3948831Sclaudio struct fec *f;
135e3948831Sclaudio
136e3948831Sclaudio while ((f = RB_ROOT(fh)) != NULL) {
137e3948831Sclaudio fec_remove(fh, f);
138e3948831Sclaudio free_cb(f);
139e3948831Sclaudio }
140e3948831Sclaudio }
141e3948831Sclaudio
142a094a533Sclaudio /* routing table functions */
143c28a25a1Srenato static int
lde_nbr_is_nexthop(struct fec_node * fn,struct lde_nbr * ln)1446106bae4Srenato lde_nbr_is_nexthop(struct fec_node *fn, struct lde_nbr *ln)
145b3d43398Srenato {
1466106bae4Srenato struct fec_nh *fnh;
147b3d43398Srenato
1486106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry)
149a8c39dc0Srenato if (lde_address_find(ln, fnh->af, &fnh->nexthop))
150b3d43398Srenato return (1);
151b3d43398Srenato
152b3d43398Srenato return (0);
153b3d43398Srenato }
154b3d43398Srenato
155e3948831Sclaudio void
rt_dump(pid_t pid)156ab0c2486Smichele rt_dump(pid_t pid)
157ab0c2486Smichele {
158e3948831Sclaudio struct fec *f;
1596106bae4Srenato struct fec_node *fn;
160a094a533Sclaudio struct lde_map *me;
161ab0c2486Smichele static struct ctl_rt rtctl;
162ab0c2486Smichele
1636106bae4Srenato RB_FOREACH(f, fec_tree, &ft) {
1646106bae4Srenato fn = (struct fec_node *)f;
1656106bae4Srenato if (fn->local_label == NO_LABEL &&
1666106bae4Srenato LIST_EMPTY(&fn->downstream))
167cf483f25Srenato continue;
168cf483f25Srenato
169a8c39dc0Srenato switch (fn->fec.type) {
170a8c39dc0Srenato case FEC_TYPE_IPV4:
171a8c39dc0Srenato rtctl.af = AF_INET;
172a8c39dc0Srenato rtctl.prefix.v4 = fn->fec.u.ipv4.prefix;
1736399cec1Srenato rtctl.prefixlen = fn->fec.u.ipv4.prefixlen;
174a8c39dc0Srenato break;
175a8c39dc0Srenato case FEC_TYPE_IPV6:
176a8c39dc0Srenato rtctl.af = AF_INET6;
177a8c39dc0Srenato rtctl.prefix.v6 = fn->fec.u.ipv6.prefix;
178a8c39dc0Srenato rtctl.prefixlen = fn->fec.u.ipv6.prefixlen;
179a8c39dc0Srenato break;
180a8c39dc0Srenato default:
181a8c39dc0Srenato continue;
182a8c39dc0Srenato }
183ab0c2486Smichele
184a8c39dc0Srenato rtctl.local_label = fn->local_label;
1856106bae4Srenato LIST_FOREACH(me, &fn->downstream, entry) {
1866106bae4Srenato rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
187a094a533Sclaudio rtctl.nexthop = me->nexthop->id;
18829d4fbdbSrenato rtctl.remote_label = me->map.label;
189a094a533Sclaudio
190a094a533Sclaudio lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
191a094a533Sclaudio &rtctl, sizeof(rtctl));
192a094a533Sclaudio }
1936106bae4Srenato if (LIST_EMPTY(&fn->downstream)) {
194b3d43398Srenato rtctl.in_use = 0;
195b3d43398Srenato rtctl.nexthop.s_addr = INADDR_ANY;
196b3d43398Srenato rtctl.remote_label = NO_LABEL;
197b3d43398Srenato
198b3d43398Srenato lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
199b3d43398Srenato &rtctl, sizeof(rtctl));
200a094a533Sclaudio }
201ab0c2486Smichele }
202ab0c2486Smichele }
203ab0c2486Smichele
204ab0c2486Smichele void
fec_snap(struct lde_nbr * ln)2056106bae4Srenato fec_snap(struct lde_nbr *ln)
206ab0c2486Smichele {
207e3948831Sclaudio struct fec *f;
2086106bae4Srenato struct fec_node *fn;
209ab0c2486Smichele
2106106bae4Srenato RB_FOREACH(f, fec_tree, &ft) {
2116106bae4Srenato fn = (struct fec_node *)f;
2126106bae4Srenato if (fn->local_label == NO_LABEL)
213cf483f25Srenato continue;
214ab0c2486Smichele
2156399cec1Srenato lde_send_labelmapping(ln, fn, 0);
216ab0c2486Smichele }
21734f55a3fSrenato
21834f55a3fSrenato lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0);
2199246985aSrenato
2209246985aSrenato /*
2219246985aSrenato * RFC 5919 - Section 4:
2229246985aSrenato * "An LDP speaker that conforms to this specification SHOULD signal
2239246985aSrenato * completion of its label advertisements to a peer by means of a
2249246985aSrenato * Notification message, if its peer has advertised the Unrecognized
2259246985aSrenato * Notification capability during session establishment. The LDP
2269246985aSrenato * speaker SHOULD send the Notification message (per Forwarding
2279246985aSrenato * Equivalence Class (FEC) Type) to a peer even if the LDP speaker has
2289246985aSrenato * zero Label bindings to advertise to that peer".
2299246985aSrenato */
2309246985aSrenato if (ln->flags & F_NBR_CAP_UNOTIF) {
2319246985aSrenato lde_send_notification_eol_prefix(ln, AF_INET);
2329246985aSrenato lde_send_notification_eol_prefix(ln, AF_INET6);
2339246985aSrenato lde_send_notification_eol_pwid(ln, PW_TYPE_WILDCARD);
2349246985aSrenato }
235ab0c2486Smichele }
236ab0c2486Smichele
237c28a25a1Srenato static void
fec_free(void * arg)2386106bae4Srenato fec_free(void *arg)
239a094a533Sclaudio {
2406106bae4Srenato struct fec_node *fn = arg;
2416106bae4Srenato struct fec_nh *fnh;
242a094a533Sclaudio
2436106bae4Srenato while ((fnh = LIST_FIRST(&fn->nexthops)))
2446106bae4Srenato fec_nh_del(fnh);
2456106bae4Srenato if (!LIST_EMPTY(&fn->downstream))
246b7b4db73Srenato log_warnx("%s: fec %s downstream list not empty", __func__,
2476399cec1Srenato log_fec(&fn->fec));
2486106bae4Srenato if (!LIST_EMPTY(&fn->upstream))
249b7b4db73Srenato log_warnx("%s: fec %s upstream list not empty", __func__,
2506399cec1Srenato log_fec(&fn->fec));
251a094a533Sclaudio
2526106bae4Srenato free(fn);
253a094a533Sclaudio }
254a094a533Sclaudio
255a094a533Sclaudio void
fec_tree_clear(void)2566106bae4Srenato fec_tree_clear(void)
257ab0c2486Smichele {
2586106bae4Srenato fec_clear(&ft, fec_free);
259a094a533Sclaudio }
260a094a533Sclaudio
261c28a25a1Srenato static struct fec_node *
fec_add(struct fec * fec)2626399cec1Srenato fec_add(struct fec *fec)
263a094a533Sclaudio {
2646106bae4Srenato struct fec_node *fn;
265a094a533Sclaudio
2666106bae4Srenato fn = calloc(1, sizeof(*fn));
2676106bae4Srenato if (fn == NULL)
268b7b4db73Srenato fatal(__func__);
269a094a533Sclaudio
2707aa09c5dSrenato fn->fec = *fec;
2716106bae4Srenato fn->local_label = NO_LABEL;
2726106bae4Srenato LIST_INIT(&fn->upstream);
2736106bae4Srenato LIST_INIT(&fn->downstream);
2746106bae4Srenato LIST_INIT(&fn->nexthops);
275a094a533Sclaudio
2766106bae4Srenato if (fec_insert(&ft, &fn->fec))
2776399cec1Srenato log_warnx("failed to add %s to ft tree",
2786399cec1Srenato log_fec(&fn->fec));
279a094a533Sclaudio
2806106bae4Srenato return (fn);
281a094a533Sclaudio }
282a094a533Sclaudio
2836106bae4Srenato struct fec_nh *
fec_nh_find(struct fec_node * fn,int af,union ldpd_addr * nexthop,uint8_t priority)2840c0343b7Srenato fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
2850c0343b7Srenato uint8_t priority)
286a094a533Sclaudio {
2876106bae4Srenato struct fec_nh *fnh;
288a094a533Sclaudio
2896106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry)
290a8c39dc0Srenato if (fnh->af == af &&
2910c0343b7Srenato ldp_addrcmp(af, &fnh->nexthop, nexthop) == 0 &&
2920c0343b7Srenato fnh->priority == priority)
2936106bae4Srenato return (fnh);
29419fce358Srenato
295a094a533Sclaudio return (NULL);
296a094a533Sclaudio }
297a094a533Sclaudio
298c28a25a1Srenato static struct fec_nh *
fec_nh_add(struct fec_node * fn,int af,union ldpd_addr * nexthop,uint8_t priority)2990c0343b7Srenato fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop,
3000c0343b7Srenato uint8_t priority)
301a094a533Sclaudio {
3026106bae4Srenato struct fec_nh *fnh;
303a094a533Sclaudio
3046106bae4Srenato fnh = calloc(1, sizeof(*fnh));
3056106bae4Srenato if (fnh == NULL)
306b7b4db73Srenato fatal(__func__);
307a094a533Sclaudio
308a8c39dc0Srenato fnh->af = af;
309a8c39dc0Srenato fnh->nexthop = *nexthop;
3106106bae4Srenato fnh->remote_label = NO_LABEL;
3110c0343b7Srenato fnh->priority = priority;
3126106bae4Srenato LIST_INSERT_HEAD(&fn->nexthops, fnh, entry);
31310c7a445Srenato
3146106bae4Srenato return (fnh);
315a094a533Sclaudio }
316a094a533Sclaudio
317c28a25a1Srenato static void
fec_nh_del(struct fec_nh * fnh)3186106bae4Srenato fec_nh_del(struct fec_nh *fnh)
319a094a533Sclaudio {
3206106bae4Srenato LIST_REMOVE(fnh, entry);
3216106bae4Srenato free(fnh);
322ab0c2486Smichele }
323ab0c2486Smichele
3243de94509Srenato uint32_t
egress_label(enum fec_type fec_type)3253de94509Srenato egress_label(enum fec_type fec_type)
3263de94509Srenato {
3273de94509Srenato switch (fec_type) {
3283de94509Srenato case FEC_TYPE_IPV4:
329d3e006a4Srenato if (ldeconf->ipv4.flags & F_LDPD_AF_EXPNULL)
3303de94509Srenato return (MPLS_LABEL_IPV4NULL);
331d3e006a4Srenato break;
332a8c39dc0Srenato case FEC_TYPE_IPV6:
333d3e006a4Srenato if (ldeconf->ipv6.flags & F_LDPD_AF_EXPNULL)
334a8c39dc0Srenato return (MPLS_LABEL_IPV6NULL);
335d3e006a4Srenato break;
3363de94509Srenato default:
337d3e006a4Srenato fatalx("egress_label: unexpected fec type");
3383de94509Srenato }
3393de94509Srenato
340d3e006a4Srenato return (MPLS_LABEL_IMPLNULL);
3413de94509Srenato }
3423de94509Srenato
343ab0c2486Smichele void
lde_kernel_insert(struct fec * fec,int af,union ldpd_addr * nexthop,uint8_t priority,int connected,void * data)344a8c39dc0Srenato lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
3450c0343b7Srenato uint8_t priority, int connected, void *data)
346ab0c2486Smichele {
3476106bae4Srenato struct fec_node *fn;
3486106bae4Srenato struct fec_nh *fnh;
349cf483f25Srenato struct lde_map *me;
350cf483f25Srenato struct lde_nbr *ln;
351ab0c2486Smichele
3526399cec1Srenato fn = (struct fec_node *)fec_find(&ft, fec);
3536106bae4Srenato if (fn == NULL)
3546399cec1Srenato fn = fec_add(fec);
3550c0343b7Srenato if (fec_nh_find(fn, af, nexthop, priority) != NULL)
356a7c87e05Smichele return;
357a7c87e05Smichele
35819fce358Srenato log_debug("lde add fec %s nexthop %s",
359a8c39dc0Srenato log_fec(&fn->fec), log_addr(af, nexthop));
36019fce358Srenato
36172bfe95eSrenato if (fn->fec.type == FEC_TYPE_PWID)
36272bfe95eSrenato fn->data = data;
36372bfe95eSrenato
3646106bae4Srenato if (fn->local_label == NO_LABEL) {
3656399cec1Srenato if (connected)
3663de94509Srenato fn->local_label = egress_label(fn->fec.type);
367a094a533Sclaudio else
3686106bae4Srenato fn->local_label = lde_assign_label();
369d7d0957bSmichele
370cf483f25Srenato /* FEC.1: perform lsr label distribution procedure */
3716399cec1Srenato RB_FOREACH(ln, nbr_tree, &lde_nbrs)
3726399cec1Srenato lde_send_labelmapping(ln, fn, 1);
373cf483f25Srenato }
374cf483f25Srenato
3750c0343b7Srenato fnh = fec_nh_add(fn, af, nexthop, priority);
3766106bae4Srenato lde_send_change_klabel(fn, fnh);
37772bfe95eSrenato
37872bfe95eSrenato switch (fn->fec.type) {
37972bfe95eSrenato case FEC_TYPE_IPV4:
380a8c39dc0Srenato case FEC_TYPE_IPV6:
381a8c39dc0Srenato ln = lde_nbr_find_by_addr(af, &fnh->nexthop);
38272bfe95eSrenato break;
38372bfe95eSrenato case FEC_TYPE_PWID:
38472bfe95eSrenato ln = lde_nbr_find_by_lsrid(fn->fec.u.pwid.lsr_id);
38572bfe95eSrenato break;
38672bfe95eSrenato default:
38772bfe95eSrenato ln = NULL;
38872bfe95eSrenato break;
38972bfe95eSrenato }
39072bfe95eSrenato
391cf483f25Srenato if (ln) {
392cf483f25Srenato /* FEC.2 */
3936106bae4Srenato me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
39429d4fbdbSrenato if (me)
395cf483f25Srenato /* FEC.5 */
39629d4fbdbSrenato lde_check_mapping(&me->map, ln);
397cf483f25Srenato }
398ab0c2486Smichele }
399ab0c2486Smichele
400ab0c2486Smichele void
lde_kernel_remove(struct fec * fec,int af,union ldpd_addr * nexthop,uint8_t priority)4010c0343b7Srenato lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
4020c0343b7Srenato uint8_t priority)
4039c6090f2Smichele {
4046106bae4Srenato struct fec_node *fn;
4056106bae4Srenato struct fec_nh *fnh;
4062c06fdf4Srenato struct lde_nbr *ln;
4079c6090f2Smichele
4086399cec1Srenato fn = (struct fec_node *)fec_find(&ft, fec);
4096106bae4Srenato if (fn == NULL)
410a094a533Sclaudio /* route lost */
4119c6090f2Smichele return;
4120c0343b7Srenato fnh = fec_nh_find(fn, af, nexthop, priority);
4136106bae4Srenato if (fnh == NULL)
414cf483f25Srenato /* route lost */
415cf483f25Srenato return;
416cf483f25Srenato
41719fce358Srenato log_debug("lde remove fec %s nexthop %s",
418a8c39dc0Srenato log_fec(&fn->fec), log_addr(af, nexthop));
41919fce358Srenato
4206399cec1Srenato lde_send_delete_klabel(fn, fnh);
4216106bae4Srenato fec_nh_del(fnh);
4223de94509Srenato if (LIST_EMPTY(&fn->nexthops)) {
4232c06fdf4Srenato RB_FOREACH(ln, nbr_tree, &lde_nbrs)
4242c06fdf4Srenato lde_send_labelwithdraw(ln, fn, NULL, NULL);
425e5099c8bSrenato fn->local_label = NO_LABEL;
4263de94509Srenato if (fn->fec.type == FEC_TYPE_PWID)
4273de94509Srenato fn->data = NULL;
4283de94509Srenato }
4299c6090f2Smichele }
4309c6090f2Smichele
4319c6090f2Smichele void
lde_check_mapping(struct map * map,struct lde_nbr * ln)432ab0c2486Smichele lde_check_mapping(struct map *map, struct lde_nbr *ln)
433ab0c2486Smichele {
4346399cec1Srenato struct fec fec;
4356106bae4Srenato struct fec_node *fn;
4366106bae4Srenato struct fec_nh *fnh;
437510d51a3Sclaudio struct lde_req *lre;
438e3948831Sclaudio struct lde_map *me;
4396399cec1Srenato struct l2vpn_pw *pw;
440cf483f25Srenato int msgsource = 0;
4410211d6d6Sclaudio
4426399cec1Srenato lde_map2fec(map, ln->id, &fec);
4436399cec1Srenato fn = (struct fec_node *)fec_find(&ft, &fec);
4446106bae4Srenato if (fn == NULL)
4456399cec1Srenato fn = fec_add(&fec);
446a7c87e05Smichele
447cf483f25Srenato /* LMp.1: first check if we have a pending request running */
4486106bae4Srenato lre = (struct lde_req *)fec_find(&ln->sent_req, &fn->fec);
449fb298019Sclaudio if (lre)
450cf483f25Srenato /* LMp.2: delete record of outstanding label request */
451fb298019Sclaudio lde_req_del(ln, lre, 1);
452510d51a3Sclaudio
4536399cec1Srenato /* RFC 4447 control word and status tlv negotiation */
454cf09440fSrenato if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map))
4556399cec1Srenato return;
4566399cec1Srenato
457fb298019Sclaudio /*
458d0b141dbSrenato * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
459d0b141dbSrenato * mpls networks.
460e3948831Sclaudio */
461cf483f25Srenato
462cf483f25Srenato /* LMp.9 */
4636106bae4Srenato me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
464cf483f25Srenato if (me) {
465cf483f25Srenato /* LMp.10 */
46629d4fbdbSrenato if (me->map.label != map->label && lre == NULL) {
467cf483f25Srenato /* LMp.10a */
4682c06fdf4Srenato lde_send_labelrelease(ln, fn, NULL, me->map.label);
469cf483f25Srenato
4706dfcbc27Srenato /*
4716dfcbc27Srenato * Can not use lde_nbr_find_by_addr() because there's
4726dfcbc27Srenato * the possibility of multipath.
4736dfcbc27Srenato */
4746dfcbc27Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) {
475a8c39dc0Srenato if (lde_address_find(ln, fnh->af,
476a8c39dc0Srenato &fnh->nexthop) == NULL)
4776dfcbc27Srenato continue;
4786dfcbc27Srenato
4796106bae4Srenato lde_send_delete_klabel(fn, fnh);
4806106bae4Srenato fnh->remote_label = NO_LABEL;
481ab0c2486Smichele }
482cf483f25Srenato }
483ab0c2486Smichele }
484ab0c2486Smichele
485cf483f25Srenato /*
486cf483f25Srenato * LMp.11 - 12: consider multiple nexthops in order to
487cf483f25Srenato * support multipath
488cf483f25Srenato */
4896106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) {
49072bfe95eSrenato /* LMp.15: install FEC in FIB */
49172bfe95eSrenato switch (fec.type) {
49272bfe95eSrenato case FEC_TYPE_IPV4:
493a8c39dc0Srenato case FEC_TYPE_IPV6:
494a8c39dc0Srenato if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
4956399cec1Srenato continue;
4966399cec1Srenato
4976106bae4Srenato fnh->remote_label = map->label;
4986106bae4Srenato lde_send_change_klabel(fn, fnh);
4996399cec1Srenato break;
50072bfe95eSrenato case FEC_TYPE_PWID:
50172bfe95eSrenato pw = (struct l2vpn_pw *) fn->data;
50272bfe95eSrenato if (pw == NULL)
50372bfe95eSrenato continue;
50472bfe95eSrenato
5056399cec1Srenato pw->remote_group = map->fec.pwid.group_id;
5066399cec1Srenato if (map->flags & F_MAP_PW_IFMTU)
5076399cec1Srenato pw->remote_mtu = map->fec.pwid.ifmtu;
5086399cec1Srenato if (map->flags & F_MAP_PW_STATUS)
5096399cec1Srenato pw->remote_status = map->pw_status;
51072bfe95eSrenato fnh->remote_label = map->label;
5116399cec1Srenato if (l2vpn_pw_ok(pw, fnh))
5126399cec1Srenato lde_send_change_klabel(fn, fnh);
5136399cec1Srenato break;
51472bfe95eSrenato default:
51572bfe95eSrenato break;
516a094a533Sclaudio }
51772bfe95eSrenato
51872bfe95eSrenato msgsource = 1;
519cf483f25Srenato }
5206399cec1Srenato /* LMp.13 & LMp.16: Record the mapping from this peer */
521e3948831Sclaudio if (me == NULL)
5226106bae4Srenato me = lde_map_add(ln, fn, 0);
5237aa09c5dSrenato me->map = *map;
524ab0c2486Smichele
5256399cec1Srenato if (msgsource == 0)
5266399cec1Srenato /* LMp.13: just return since we use liberal lbl retention */
5276399cec1Srenato return;
528ab0c2486Smichele
529cf483f25Srenato /*
530cf483f25Srenato * LMp.17 - LMp.27 are unnecessary since we don't need to implement
531cf483f25Srenato * loop detection. LMp.28 - LMp.30 are unnecessary because we are
532cf483f25Srenato * merging capable.
533cf483f25Srenato */
534ab0c2486Smichele }
535ab0c2486Smichele
536ab0c2486Smichele void
lde_check_request(struct map * map,struct lde_nbr * ln)537ab0c2486Smichele lde_check_request(struct map *map, struct lde_nbr *ln)
538ab0c2486Smichele {
5396399cec1Srenato struct fec fec;
540e3948831Sclaudio struct lde_req *lre;
5416106bae4Srenato struct fec_node *fn;
5426106bae4Srenato struct fec_nh *fnh;
543ab0c2486Smichele
544c7c5a728Srenato /* wildcard label request */
545c7c5a728Srenato if (map->type == MAP_TYPE_TYPED_WCARD) {
546c7c5a728Srenato lde_check_request_wcard(map, ln);
547c7c5a728Srenato return;
548c7c5a728Srenato }
549c7c5a728Srenato
550d0b141dbSrenato /* LRq.1: skip loop detection (not necessary) */
5510211d6d6Sclaudio
552cf483f25Srenato /* LRq.2: is there a next hop for fec? */
5536399cec1Srenato lde_map2fec(map, ln->id, &fec);
5546399cec1Srenato fn = (struct fec_node *)fec_find(&ft, &fec);
5556106bae4Srenato if (fn == NULL || LIST_EMPTY(&fn->nexthops)) {
556d0b141dbSrenato /* LRq.5: send No Route notification */
55702a212eeSrenato lde_send_notification(ln, S_NO_ROUTE, map->msg_id,
558e4ecb75dSrenato htons(MSG_TYPE_LABELREQUEST));
559ab0c2486Smichele return;
560ab0c2486Smichele }
561ab0c2486Smichele
562cf483f25Srenato /* LRq.3: is MsgSource the next hop? */
5636106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) {
56472bfe95eSrenato switch (fec.type) {
56572bfe95eSrenato case FEC_TYPE_IPV4:
566a8c39dc0Srenato case FEC_TYPE_IPV6:
567a8c39dc0Srenato if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
56872bfe95eSrenato continue;
56972bfe95eSrenato
570d0b141dbSrenato /* LRq.4: send Loop Detected notification */
57102a212eeSrenato lde_send_notification(ln, S_LOOP_DETECTED, map->msg_id,
57202a212eeSrenato htons(MSG_TYPE_LABELREQUEST));
573ab0c2486Smichele return;
57472bfe95eSrenato default:
57572bfe95eSrenato break;
576ab0c2486Smichele }
577a094a533Sclaudio }
578ab0c2486Smichele
579cf483f25Srenato /* LRq.6: first check if we have a pending request running */
5806106bae4Srenato lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
581510d51a3Sclaudio if (lre != NULL)
582cf483f25Srenato /* LRq.7: duplicate request */
583510d51a3Sclaudio return;
584cf483f25Srenato
585cf483f25Srenato /* LRq.8: record label request */
5866106bae4Srenato lre = lde_req_add(ln, &fn->fec, 0);
587fb298019Sclaudio if (lre != NULL)
58860e1e0e7Srenato lre->msg_id = ntohl(map->msg_id);
589510d51a3Sclaudio
590cf483f25Srenato /* LRq.9: perform LSR label distribution */
5916399cec1Srenato lde_send_labelmapping(ln, fn, 1);
592a094a533Sclaudio
593cf483f25Srenato /*
594cf483f25Srenato * LRq.10: do nothing (Request Never) since we use liberal
595cf483f25Srenato * label retention.
596cf483f25Srenato * LRq.11 - 12 are unnecessary since we are merging capable.
597cf483f25Srenato */
598ab0c2486Smichele }
599d5e40e07Sclaudio
600d5e40e07Sclaudio void
lde_check_request_wcard(struct map * map,struct lde_nbr * ln)601c7c5a728Srenato lde_check_request_wcard(struct map *map, struct lde_nbr *ln)
602c7c5a728Srenato {
603c7c5a728Srenato struct fec *f;
604c7c5a728Srenato struct fec_node *fn;
605c7c5a728Srenato struct lde_req *lre;
606c7c5a728Srenato
607c7c5a728Srenato RB_FOREACH(f, fec_tree, &ft) {
608c7c5a728Srenato fn = (struct fec_node *)f;
609c7c5a728Srenato
610c7c5a728Srenato /* only a typed wildcard is possible here */
611c7c5a728Srenato if (lde_wildcard_apply(map, &fn->fec, NULL) == 0)
612c7c5a728Srenato continue;
613c7c5a728Srenato
614c7c5a728Srenato /* LRq.2: is there a next hop for fec? */
615c7c5a728Srenato if (LIST_EMPTY(&fn->nexthops))
616c7c5a728Srenato continue;
617c7c5a728Srenato
618c7c5a728Srenato /* LRq.6: first check if we have a pending request running */
619c7c5a728Srenato lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
620c7c5a728Srenato if (lre != NULL)
621c7c5a728Srenato /* LRq.7: duplicate request */
622c7c5a728Srenato continue;
623c7c5a728Srenato
624c7c5a728Srenato /* LRq.8: record label request */
625c7c5a728Srenato lre = lde_req_add(ln, &fn->fec, 0);
626c7c5a728Srenato if (lre != NULL)
627c7c5a728Srenato lre->msg_id = ntohl(map->msg_id);
628c7c5a728Srenato
629c7c5a728Srenato /* LRq.9: perform LSR label distribution */
630c7c5a728Srenato lde_send_labelmapping(ln, fn, 1);
631c7c5a728Srenato }
6329246985aSrenato
6339246985aSrenato /*
6349246985aSrenato * RFC 5919 - Section 5.3:
6359246985aSrenato * "When an LDP speaker receives a Label Request message for a Typed
6369246985aSrenato * Wildcard FEC (e.g., a particular FEC Element Type) from a peer, the
6379246985aSrenato * LDP speaker determines the set of bindings (as per any local
6389246985aSrenato * filtering policy) to advertise to the peer for the FEC type specified
6399246985aSrenato * by the request. Assuming the peer had advertised the Unrecognized
6409246985aSrenato * Notification capability at session initialization time, the speaker
6419246985aSrenato * should send the peer an End-of-LIB Notification for the FEC type when
6429246985aSrenato * it completes advertisement of the permitted bindings".
6439246985aSrenato */
6449246985aSrenato if (ln->flags & F_NBR_CAP_UNOTIF) {
6459246985aSrenato switch (map->fec.twcard.type) {
6469246985aSrenato case MAP_TYPE_PREFIX:
6479246985aSrenato lde_send_notification_eol_prefix(ln,
6489246985aSrenato map->fec.twcard.u.prefix_af);
6499246985aSrenato break;
6509246985aSrenato case MAP_TYPE_PWID:
6519246985aSrenato lde_send_notification_eol_pwid(ln,
6529246985aSrenato map->fec.twcard.u.pw_type);
6539246985aSrenato break;
6549246985aSrenato default:
6559246985aSrenato break;
6569246985aSrenato }
6579246985aSrenato }
658c7c5a728Srenato }
659c7c5a728Srenato
660c7c5a728Srenato void
lde_check_release(struct map * map,struct lde_nbr * ln)661f1b8b674Sclaudio lde_check_release(struct map *map, struct lde_nbr *ln)
662f1b8b674Sclaudio {
6636399cec1Srenato struct fec fec;
6646106bae4Srenato struct fec_node *fn;
665cf483f25Srenato struct lde_wdraw *lw;
666510d51a3Sclaudio struct lde_map *me;
667510d51a3Sclaudio
6682c06fdf4Srenato /* wildcard label release */
6692c06fdf4Srenato if (map->type == MAP_TYPE_WILDCARD ||
670c7c5a728Srenato map->type == MAP_TYPE_TYPED_WCARD ||
6712c06fdf4Srenato (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
6722c06fdf4Srenato lde_check_release_wcard(map, ln);
6736399cec1Srenato return;
6742c06fdf4Srenato }
6756399cec1Srenato
6766399cec1Srenato lde_map2fec(map, ln->id, &fec);
6776399cec1Srenato fn = (struct fec_node *)fec_find(&ft, &fec);
678cf483f25Srenato /* LRl.1: does FEC match a known FEC? */
6796106bae4Srenato if (fn == NULL)
680510d51a3Sclaudio return;
681510d51a3Sclaudio
682cf483f25Srenato /* LRl.3: first check if we have a pending withdraw running */
6836106bae4Srenato lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
684438d9009Srenato if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
685cf483f25Srenato /* LRl.4: delete record of outstanding label withdraw */
686cf483f25Srenato lde_wdraw_del(ln, lw);
687510d51a3Sclaudio }
688510d51a3Sclaudio
689cf483f25Srenato /* LRl.6: check sent map list and remove it if available */
6906106bae4Srenato me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
69129d4fbdbSrenato if (me && (map->label == NO_LABEL || map->label == me->map.label))
692510d51a3Sclaudio lde_map_del(ln, me, 1);
693510d51a3Sclaudio
694cf483f25Srenato /*
695cf483f25Srenato * LRl.11 - 13 are unnecessary since we remove the label from
696cf483f25Srenato * forwarding/switching as soon as the FEC is unreachable.
697cf483f25Srenato */
698cf483f25Srenato }
699510d51a3Sclaudio
700cf483f25Srenato void
lde_check_release_wcard(struct map * map,struct lde_nbr * ln)701cf483f25Srenato lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
702cf483f25Srenato {
703cf483f25Srenato struct fec *f;
7046106bae4Srenato struct fec_node *fn;
705cf483f25Srenato struct lde_wdraw *lw;
706cf483f25Srenato struct lde_map *me;
707cf483f25Srenato
7086106bae4Srenato RB_FOREACH(f, fec_tree, &ft) {
7096106bae4Srenato fn = (struct fec_node *)f;
7102c06fdf4Srenato me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
7112c06fdf4Srenato
7122c06fdf4Srenato /* LRl.1: does FEC match a known FEC? */
7132c06fdf4Srenato if (lde_wildcard_apply(map, &fn->fec, me) == 0)
7142c06fdf4Srenato continue;
715cf483f25Srenato
716cf483f25Srenato /* LRl.3: first check if we have a pending withdraw running */
7176106bae4Srenato lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
718438d9009Srenato if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
719cf483f25Srenato /* LRl.4: delete record of outstanding lbl withdraw */
720cf483f25Srenato lde_wdraw_del(ln, lw);
721cf483f25Srenato }
722cf483f25Srenato
723cf483f25Srenato /* LRl.6: check sent map list and remove it if available */
724cf483f25Srenato if (me &&
72519fce358Srenato (map->label == NO_LABEL || map->label == me->map.label))
726cf483f25Srenato lde_map_del(ln, me, 1);
727cf483f25Srenato
728cf483f25Srenato /*
729cf483f25Srenato * LRl.11 - 13 are unnecessary since we remove the label from
730cf483f25Srenato * forwarding/switching as soon as the FEC is unreachable.
731cf483f25Srenato */
732cf483f25Srenato }
733510d51a3Sclaudio }
734510d51a3Sclaudio
735510d51a3Sclaudio void
lde_check_withdraw(struct map * map,struct lde_nbr * ln)736510d51a3Sclaudio lde_check_withdraw(struct map *map, struct lde_nbr *ln)
737510d51a3Sclaudio {
7386399cec1Srenato struct fec fec;
7396106bae4Srenato struct fec_node *fn;
7406106bae4Srenato struct fec_nh *fnh;
741510d51a3Sclaudio struct lde_map *me;
74272bfe95eSrenato struct l2vpn_pw *pw;
743510d51a3Sclaudio
7442c06fdf4Srenato /* wildcard label withdraw */
7452c06fdf4Srenato if (map->type == MAP_TYPE_WILDCARD ||
746c7c5a728Srenato map->type == MAP_TYPE_TYPED_WCARD ||
7472c06fdf4Srenato (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
7482c06fdf4Srenato lde_check_withdraw_wcard(map, ln);
7496399cec1Srenato return;
7502c06fdf4Srenato }
7516399cec1Srenato
7526399cec1Srenato lde_map2fec(map, ln->id, &fec);
7536399cec1Srenato fn = (struct fec_node *)fec_find(&ft, &fec);
7546106bae4Srenato if (fn == NULL)
7556399cec1Srenato fn = fec_add(&fec);
756510d51a3Sclaudio
757cf483f25Srenato /* LWd.1: remove label from forwarding/switching use */
7586106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) {
75972bfe95eSrenato switch (fec.type) {
76072bfe95eSrenato case FEC_TYPE_IPV4:
761a8c39dc0Srenato case FEC_TYPE_IPV6:
762a8c39dc0Srenato if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
76372bfe95eSrenato continue;
76472bfe95eSrenato break;
76572bfe95eSrenato case FEC_TYPE_PWID:
76672bfe95eSrenato pw = (struct l2vpn_pw *) fn->data;
76772bfe95eSrenato if (pw == NULL)
76872bfe95eSrenato continue;
76972bfe95eSrenato break;
77072bfe95eSrenato default:
77172bfe95eSrenato break;
77272bfe95eSrenato }
773438d9009Srenato if (map->label != NO_LABEL && map->label != fnh->remote_label)
774438d9009Srenato continue;
775438d9009Srenato
7766106bae4Srenato lde_send_delete_klabel(fn, fnh);
7776106bae4Srenato fnh->remote_label = NO_LABEL;
778cf483f25Srenato }
779cf483f25Srenato
780cf483f25Srenato /* LWd.2: send label release */
7812c06fdf4Srenato lde_send_labelrelease(ln, fn, NULL, map->label);
782510d51a3Sclaudio
783cf483f25Srenato /* LWd.3: check previously received label mapping */
7846106bae4Srenato me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
78529d4fbdbSrenato if (me && (map->label == NO_LABEL || map->label == me->map.label))
786cf483f25Srenato /* LWd.4: remove record of previously received lbl mapping */
787510d51a3Sclaudio lde_map_del(ln, me, 0);
788cf483f25Srenato }
789510d51a3Sclaudio
790cf483f25Srenato void
lde_check_withdraw_wcard(struct map * map,struct lde_nbr * ln)791cf483f25Srenato lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
792cf483f25Srenato {
793cf483f25Srenato struct fec *f;
7946106bae4Srenato struct fec_node *fn;
7956106bae4Srenato struct fec_nh *fnh;
796cf483f25Srenato struct lde_map *me;
797510d51a3Sclaudio
798cf483f25Srenato /* LWd.2: send label release */
7992c06fdf4Srenato lde_send_labelrelease(ln, NULL, map, map->label);
800cf483f25Srenato
8016106bae4Srenato RB_FOREACH(f, fec_tree, &ft) {
8026106bae4Srenato fn = (struct fec_node *)f;
8032c06fdf4Srenato me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
8042c06fdf4Srenato
8052c06fdf4Srenato if (lde_wildcard_apply(map, &fn->fec, me) == 0)
8062c06fdf4Srenato continue;
807cf483f25Srenato
808cf483f25Srenato /* LWd.1: remove label from forwarding/switching use */
8096106bae4Srenato LIST_FOREACH(fnh, &fn->nexthops, entry) {
81072bfe95eSrenato switch (f->type) {
81172bfe95eSrenato case FEC_TYPE_IPV4:
812a8c39dc0Srenato case FEC_TYPE_IPV6:
813a8c39dc0Srenato if (!lde_address_find(ln, fnh->af,
814a8c39dc0Srenato &fnh->nexthop))
81572bfe95eSrenato continue;
81672bfe95eSrenato break;
81772bfe95eSrenato case FEC_TYPE_PWID:
81872bfe95eSrenato if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
81972bfe95eSrenato continue;
82072bfe95eSrenato break;
82172bfe95eSrenato default:
82272bfe95eSrenato break;
82372bfe95eSrenato }
824438d9009Srenato if (map->label != NO_LABEL && map->label !=
825438d9009Srenato fnh->remote_label)
826438d9009Srenato continue;
827438d9009Srenato
8286106bae4Srenato lde_send_delete_klabel(fn, fnh);
8296106bae4Srenato fnh->remote_label = NO_LABEL;
830cf483f25Srenato }
831cf483f25Srenato
832cf483f25Srenato /* LWd.3: check previously received label mapping */
83329d4fbdbSrenato if (me && (map->label == NO_LABEL ||
83429d4fbdbSrenato map->label == me->map.label))
835cf483f25Srenato /*
836cf483f25Srenato * LWd.4: remove record of previously received
837cf483f25Srenato * label mapping
838cf483f25Srenato */
839cf483f25Srenato lde_map_del(ln, me, 0);
840cf483f25Srenato }
841f1b8b674Sclaudio }
842b79e02a8Srenato
8432c06fdf4Srenato int
lde_wildcard_apply(struct map * wcard,struct fec * fec,struct lde_map * me)8442c06fdf4Srenato lde_wildcard_apply(struct map *wcard, struct fec *fec, struct lde_map *me)
8452c06fdf4Srenato {
8462c06fdf4Srenato switch (wcard->type) {
8472c06fdf4Srenato case MAP_TYPE_WILDCARD:
8482c06fdf4Srenato /* full wildcard */
8492c06fdf4Srenato return (1);
850c7c5a728Srenato case MAP_TYPE_TYPED_WCARD:
851c7c5a728Srenato switch (wcard->fec.twcard.type) {
852c7c5a728Srenato case MAP_TYPE_PREFIX:
853c7c5a728Srenato if (wcard->fec.twcard.u.prefix_af == AF_INET &&
854c7c5a728Srenato fec->type != FEC_TYPE_IPV4)
855c7c5a728Srenato return (0);
856c7c5a728Srenato if (wcard->fec.twcard.u.prefix_af == AF_INET6 &&
857c7c5a728Srenato fec->type != FEC_TYPE_IPV6)
858c7c5a728Srenato return (0);
859c7c5a728Srenato return (1);
8606702dd25Srenato case MAP_TYPE_PWID:
8616702dd25Srenato if (fec->type != FEC_TYPE_PWID)
8626702dd25Srenato return (0);
8636702dd25Srenato if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
8646702dd25Srenato wcard->fec.twcard.u.pw_type != fec->u.pwid.type)
8656702dd25Srenato return (0);
8666702dd25Srenato return (1);
867c7c5a728Srenato default:
868c7c5a728Srenato fatalx("lde_wildcard_apply: unexpected fec type");
869c7c5a728Srenato }
870c7c5a728Srenato break;
8712c06fdf4Srenato case MAP_TYPE_PWID:
8722c06fdf4Srenato /* RFC4447 pw-id group wildcard */
8732c06fdf4Srenato if (fec->type != FEC_TYPE_PWID)
8742c06fdf4Srenato return (0);
8752c06fdf4Srenato if (fec->u.pwid.type != wcard->fec.pwid.type)
8762c06fdf4Srenato return (0);
8772c06fdf4Srenato if (me == NULL || (me->map.fec.pwid.group_id !=
8782c06fdf4Srenato wcard->fec.pwid.group_id))
8792c06fdf4Srenato return (0);
8802c06fdf4Srenato return (1);
8812c06fdf4Srenato default:
8822c06fdf4Srenato fatalx("lde_wildcard_apply: unexpected fec type");
8832c06fdf4Srenato }
8842c06fdf4Srenato }
8852c06fdf4Srenato
8863a50f0a9Sjmc /* garbage collector timer: timer to remove dead entries from the LIB */
887b79e02a8Srenato
888b79e02a8Srenato void
lde_gc_timer(int fd,short event,void * arg)889b79e02a8Srenato lde_gc_timer(int fd, short event, void *arg)
890b79e02a8Srenato {
891b79e02a8Srenato struct fec *fec, *safe;
892b79e02a8Srenato struct fec_node *fn;
893b79e02a8Srenato int count = 0;
894b79e02a8Srenato
895b79e02a8Srenato RB_FOREACH_SAFE(fec, fec_tree, &ft, safe) {
896b79e02a8Srenato fn = (struct fec_node *) fec;
897b79e02a8Srenato
898b79e02a8Srenato if (!LIST_EMPTY(&fn->nexthops) ||
899b79e02a8Srenato !LIST_EMPTY(&fn->downstream) ||
900b79e02a8Srenato !LIST_EMPTY(&fn->upstream))
901b79e02a8Srenato continue;
902b79e02a8Srenato
903b79e02a8Srenato fec_remove(&ft, &fn->fec);
904b79e02a8Srenato free(fn);
905b79e02a8Srenato count++;
906b79e02a8Srenato }
907b79e02a8Srenato
908b79e02a8Srenato if (count > 0)
909b79e02a8Srenato log_debug("%s: %u entries removed", __func__, count);
910b79e02a8Srenato
911b79e02a8Srenato lde_gc_start_timer();
912b79e02a8Srenato }
913b79e02a8Srenato
914b79e02a8Srenato void
lde_gc_start_timer(void)915b79e02a8Srenato lde_gc_start_timer(void)
916b79e02a8Srenato {
917b79e02a8Srenato struct timeval tv;
918b79e02a8Srenato
919b79e02a8Srenato timerclear(&tv);
920b79e02a8Srenato tv.tv_sec = LDE_GC_INTERVAL;
921b79e02a8Srenato if (evtimer_add(&gc_timer, &tv) == -1)
922b79e02a8Srenato fatal(__func__);
923b79e02a8Srenato }
924b79e02a8Srenato
925b79e02a8Srenato void
lde_gc_stop_timer(void)926b79e02a8Srenato lde_gc_stop_timer(void)
927b79e02a8Srenato {
928b79e02a8Srenato if (evtimer_pending(&gc_timer, NULL) &&
929b79e02a8Srenato evtimer_del(&gc_timer) == -1)
930b79e02a8Srenato fatal(__func__);
931b79e02a8Srenato }
932