]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/l2vpn.c
zebra: On shutdown don't count removals
[mirror_frr.git] / ldpd / l2vpn.c
CommitLineData
8429abe0
RW
1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
7 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
eac6e3f0 22#include <zebra.h>
8429abe0
RW
23
24#include "ldpd.h"
25#include "ldpe.h"
26#include "lde.h"
27#include "log.h"
28
90d7e7bd 29static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
45926e58
RZ
30static __inline int l2vpn_compare(const struct l2vpn *, const struct l2vpn *);
31static __inline int l2vpn_if_compare(const struct l2vpn_if *, const struct l2vpn_if *);
32static __inline int l2vpn_pw_compare(const struct l2vpn_pw *, const struct l2vpn_pw *);
90d7e7bd
RW
33
34RB_GENERATE(l2vpn_head, l2vpn, entry, l2vpn_compare)
029c1958 35RB_GENERATE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare)
20bacaeb 36RB_GENERATE(l2vpn_pw_head, l2vpn_pw, entry, l2vpn_pw_compare)
90d7e7bd
RW
37
38static __inline int
45926e58 39l2vpn_compare(const struct l2vpn *a, const struct l2vpn *b)
90d7e7bd
RW
40{
41 return (strcmp(a->name, b->name));
42}
8429abe0
RW
43
44struct l2vpn *
45l2vpn_new(const char *name)
46{
47 struct l2vpn *l2vpn;
48
49 if ((l2vpn = calloc(1, sizeof(*l2vpn))) == NULL)
50 fatal("l2vpn_new: calloc");
51
52 strlcpy(l2vpn->name, name, sizeof(l2vpn->name));
53
54 /* set default values */
55 l2vpn->mtu = DEFAULT_L2VPN_MTU;
56 l2vpn->pw_type = DEFAULT_PW_TYPE;
57
45926e58
RZ
58 RB_INIT(l2vpn_if_head, &l2vpn->if_tree);
59 RB_INIT(l2vpn_pw_head, &l2vpn->pw_tree);
60 RB_INIT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
8429abe0
RW
61
62 return (l2vpn);
63}
64
65struct l2vpn *
66l2vpn_find(struct ldpd_conf *xconf, const char *name)
67{
90d7e7bd
RW
68 struct l2vpn l2vpn;
69 strlcpy(l2vpn.name, name, sizeof(l2vpn.name));
70 return (RB_FIND(l2vpn_head, &xconf->l2vpn_tree, &l2vpn));
8429abe0
RW
71}
72
73void
74l2vpn_del(struct l2vpn *l2vpn)
75{
76 struct l2vpn_if *lif;
77 struct l2vpn_pw *pw;
78
45926e58 79 while ((lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree)) != NULL) {
029c1958 80 RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
8429abe0
RW
81 free(lif);
82 }
45926e58 83 while ((pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree)) != NULL) {
20bacaeb 84 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
8429abe0
RW
85 free(pw);
86 }
45926e58
RZ
87 while ((pw = RB_ROOT(l2vpn_pw_head,
88 &l2vpn->pw_inactive_tree)) != NULL) {
20bacaeb 89 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
eac6e3f0
RW
90 free(pw);
91 }
8429abe0
RW
92
93 free(l2vpn);
94}
95
96void
97l2vpn_init(struct l2vpn *l2vpn)
98{
99 struct l2vpn_pw *pw;
100
20bacaeb 101 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
102 l2vpn_pw_init(pw);
103}
104
105void
106l2vpn_exit(struct l2vpn *l2vpn)
107{
108 struct l2vpn_pw *pw;
109
20bacaeb 110 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
111 l2vpn_pw_exit(pw);
112}
113
029c1958 114static __inline int
45926e58 115l2vpn_if_compare(const struct l2vpn_if *a, const struct l2vpn_if *b)
029c1958 116{
9e452e5d 117 return (if_cmp_name_func((char *)a->ifname, (char *)b->ifname));
029c1958
RW
118}
119
8429abe0 120struct l2vpn_if *
52b530fc 121l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname)
8429abe0
RW
122{
123 struct l2vpn_if *lif;
124
125 if ((lif = calloc(1, sizeof(*lif))) == NULL)
126 fatal("l2vpn_if_new: calloc");
127
128 lif->l2vpn = l2vpn;
52b530fc 129 strlcpy(lif->ifname, ifname, sizeof(lif->ifname));
8429abe0
RW
130
131 return (lif);
132}
133
134struct l2vpn_if *
52bd4c23 135l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname)
eac6e3f0 136{
029c1958
RW
137 struct l2vpn_if lif;
138 strlcpy(lif.ifname, ifname, sizeof(lif.ifname));
139 return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
eac6e3f0
RW
140}
141
52b530fc
RW
142void
143l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif)
144{
145 lif->ifindex = kif->ifindex;
988ded8d 146 lif->operative = kif->operative;
52b530fc
RW
147 memcpy(lif->mac, kif->mac, sizeof(lif->mac));
148}
149
26519d8c
RW
150void
151l2vpn_if_update(struct l2vpn_if *lif)
152{
153 struct l2vpn *l2vpn = lif->l2vpn;
154 struct l2vpn_pw *pw;
155 struct map fec;
156 struct nbr *nbr;
157
988ded8d 158 if (lif->operative)
26519d8c
RW
159 return;
160
161 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
162 nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
163 if (nbr == NULL)
164 continue;
165
166 memset(&fec, 0, sizeof(fec));
167 fec.type = MAP_TYPE_PWID;
168 fec.fec.pwid.type = l2vpn->pw_type;
169 fec.fec.pwid.group_id = 0;
170 fec.flags |= F_MAP_PW_ID;
171 fec.fec.pwid.pwid = pw->pwid;
172
173 send_mac_withdrawal(nbr, &fec, lif->mac);
174 }
175}
176
20bacaeb 177static __inline int
45926e58 178l2vpn_pw_compare(const struct l2vpn_pw *a, const struct l2vpn_pw *b)
20bacaeb 179{
9e452e5d 180 return (if_cmp_name_func((char *)a->ifname, (char *)b->ifname));
20bacaeb 181}
eac6e3f0 182
8429abe0 183struct l2vpn_pw *
52b530fc 184l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname)
8429abe0
RW
185{
186 struct l2vpn_pw *pw;
187
188 if ((pw = calloc(1, sizeof(*pw))) == NULL)
189 fatal("l2vpn_pw_new: calloc");
190
191 pw->l2vpn = l2vpn;
52b530fc 192 strlcpy(pw->ifname, ifname, sizeof(pw->ifname));
8429abe0
RW
193
194 return (pw);
195}
196
197struct l2vpn_pw *
52bd4c23 198l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname)
eac6e3f0
RW
199{
200 struct l2vpn_pw *pw;
20bacaeb 201 struct l2vpn_pw s;
eac6e3f0 202
20bacaeb
RW
203 strlcpy(s.ifname, ifname, sizeof(s.ifname));
204 pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s);
205 if (pw)
206 return (pw);
207 return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
8429abe0
RW
208}
209
5c3f00af
RW
210struct l2vpn_pw *
211l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname)
212{
213 struct l2vpn_pw s;
214
215 strlcpy(s.ifname, ifname, sizeof(s.ifname));
216 return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s));
217}
218
219struct l2vpn_pw *
220l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname)
221{
222 struct l2vpn_pw s;
223
224 strlcpy(s.ifname, ifname, sizeof(s.ifname));
225 return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
226}
227
52b530fc
RW
228void
229l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif)
230{
231 pw->ifindex = kif->ifindex;
232}
233
8429abe0
RW
234void
235l2vpn_pw_init(struct l2vpn_pw *pw)
236{
237 struct fec fec;
87b5f1b7 238 struct zapi_pw zpw;
8429abe0
RW
239
240 l2vpn_pw_reset(pw);
241
6e8cb226 242 pw2zpw(pw, &zpw);
243 lde_imsg_compose_parent(IMSG_KPW_ADD, 0, &zpw, sizeof(zpw));
244
8429abe0 245 l2vpn_pw_fec(pw, &fec);
88d88a9c 246 lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0,
8429abe0 247 0, (void *)pw);
8cb1fc45 248 lde_kernel_update(&fec);
8429abe0
RW
249}
250
251void
252l2vpn_pw_exit(struct l2vpn_pw *pw)
253{
254 struct fec fec;
87b5f1b7 255 struct zapi_pw zpw;
8429abe0
RW
256
257 l2vpn_pw_fec(pw, &fec);
88d88a9c 258 lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0);
8cb1fc45 259 lde_kernel_update(&fec);
87b5f1b7
RW
260
261 pw2zpw(pw, &zpw);
262 lde_imsg_compose_parent(IMSG_KPW_DELETE, 0, &zpw, sizeof(zpw));
8429abe0
RW
263}
264
265static void
266l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec)
267{
268 memset(fec, 0, sizeof(*fec));
269 fec->type = FEC_TYPE_PWID;
270 fec->u.pwid.type = pw->l2vpn->pw_type;
271 fec->u.pwid.pwid = pw->pwid;
272 fec->u.pwid.lsr_id = pw->lsr_id;
273}
274
275void
276l2vpn_pw_reset(struct l2vpn_pw *pw)
277{
278 pw->remote_group = 0;
279 pw->remote_mtu = 0;
87b5f1b7
RW
280 pw->local_status = PW_FORWARDING;
281 pw->remote_status = PW_NOT_FORWARDING;
8429abe0
RW
282
283 if (pw->flags & F_PW_CWORD_CONF)
284 pw->flags |= F_PW_CWORD;
285 else
286 pw->flags &= ~F_PW_CWORD;
287
288 if (pw->flags & F_PW_STATUSTLV_CONF)
289 pw->flags |= F_PW_STATUSTLV;
290 else
291 pw->flags &= ~F_PW_STATUSTLV;
292}
293
294int
295l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
296{
8429abe0 297 /* check for a remote label */
34eeae65
RW
298 if (fnh->remote_label == NO_LABEL) {
299 log_warnx("%s: pseudowire %s: no remote label", __func__,
300 pw->ifname);
8429abe0 301 return (0);
34eeae65 302 }
8429abe0
RW
303
304 /* MTUs must match */
34eeae65
RW
305 if (pw->l2vpn->mtu != pw->remote_mtu) {
306 log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__,
307 pw->ifname);
8429abe0 308 return (0);
34eeae65 309 }
8429abe0
RW
310
311 /* check pw status if applicable */
312 if ((pw->flags & F_PW_STATUSTLV) &&
34eeae65
RW
313 pw->remote_status != PW_FORWARDING) {
314 log_warnx("%s: pseudowire %s: remote end is down", __func__,
315 pw->ifname);
8429abe0 316 return (0);
34eeae65 317 }
8429abe0 318
8429abe0
RW
319 return (1);
320}
321
322int
323l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map)
324{
325 struct l2vpn_pw *pw;
326 struct status_tlv st;
327
328 /* NOTE: thanks martini & friends for all this mess */
329
330 pw = (struct l2vpn_pw *) fn->data;
331 if (pw == NULL)
332 /*
333 * pseudowire not configured, return and record
334 * the mapping later
335 */
336 return (0);
337
338 /* RFC4447 - Section 6.2: control word negotiation */
339 if (fec_find(&ln->sent_map, &fn->fec)) {
340 if ((map->flags & F_MAP_PW_CWORD) &&
341 !(pw->flags & F_PW_CWORD_CONF)) {
342 /* ignore the received label mapping */
343 return (1);
344 } else if (!(map->flags & F_MAP_PW_CWORD) &&
345 (pw->flags & F_PW_CWORD_CONF)) {
346 /* append a "Wrong C-bit" status code */
347 st.status_code = S_WRONG_CBIT;
348 st.msg_id = map->msg_id;
349 st.msg_type = htons(MSG_TYPE_LABELMAPPING);
0bcc2916 350 lde_send_labelwithdraw(ln, fn, NULL, &st);
8429abe0
RW
351
352 pw->flags &= ~F_PW_CWORD;
353 lde_send_labelmapping(ln, fn, 1);
354 }
355 } else if (map->flags & F_MAP_PW_CWORD) {
356 if (pw->flags & F_PW_CWORD_CONF)
357 pw->flags |= F_PW_CWORD;
358 else
359 /* act as if no label mapping had been received */
360 return (1);
361 } else
362 pw->flags &= ~F_PW_CWORD;
363
364 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */
365 if (fec_find(&ln->recv_map, &fn->fec) == NULL &&
366 !(map->flags & F_MAP_PW_STATUS))
367 pw->flags &= ~F_PW_STATUSTLV;
368
369 return (0);
370}
371
372void
0bcc2916 373l2vpn_send_pw_status(struct lde_nbr *ln, uint32_t status, struct fec *fec)
8429abe0
RW
374{
375 struct notify_msg nm;
376
377 memset(&nm, 0, sizeof(nm));
378 nm.status_code = S_PW_STATUS;
379 nm.pw_status = status;
380 nm.flags |= F_NOTIF_PW_STATUS;
381 lde_fec2map(fec, &nm.fec);
382 nm.flags |= F_NOTIF_FEC;
383
0bcc2916
RW
384 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
385 sizeof(nm));
386}
387
388void
389l2vpn_send_pw_status_wcard(struct lde_nbr *ln, uint32_t status,
390 uint16_t pw_type, uint32_t group_id)
391{
392 struct notify_msg nm;
393
394 memset(&nm, 0, sizeof(nm));
395 nm.status_code = S_PW_STATUS;
396 nm.pw_status = status;
397 nm.flags |= F_NOTIF_PW_STATUS;
398 nm.fec.type = MAP_TYPE_PWID;
399 nm.fec.fec.pwid.type = pw_type;
400 nm.fec.fec.pwid.group_id = group_id;
401 nm.flags |= F_NOTIF_FEC;
402
403 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
404 sizeof(nm));
8429abe0
RW
405}
406
407void
408l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm)
409{
410 struct fec fec;
411 struct fec_node *fn;
412 struct fec_nh *fnh;
413 struct l2vpn_pw *pw;
414
aba50a83
RW
415 if (nm->fec.type == MAP_TYPE_TYPED_WCARD ||
416 !(nm->fec.flags & F_MAP_PW_ID)) {
0bcc2916 417 l2vpn_recv_pw_status_wcard(ln, nm);
8429abe0 418 return;
0bcc2916 419 }
8429abe0
RW
420
421 lde_map2fec(&nm->fec, ln->id, &fec);
422 fn = (struct fec_node *)fec_find(&ft, &fec);
423 if (fn == NULL)
424 /* unknown fec */
425 return;
426
427 pw = (struct l2vpn_pw *) fn->data;
428 if (pw == NULL)
429 return;
430
88d88a9c 431 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0, 0);
8429abe0
RW
432 if (fnh == NULL)
433 return;
434
435 /* remote status didn't change */
436 if (pw->remote_status == nm->pw_status)
437 return;
8429abe0
RW
438 pw->remote_status = nm->pw_status;
439
440 if (l2vpn_pw_ok(pw, fnh))
441 lde_send_change_klabel(fn, fnh);
442 else
443 lde_send_delete_klabel(fn, fnh);
444}
445
0bcc2916
RW
446/* RFC4447 PWid group wildcard */
447void
448l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
449{
450 struct fec *f;
451 struct fec_node *fn;
452 struct fec_nh *fnh;
453 struct l2vpn_pw *pw;
aba50a83 454 struct map *wcard = &nm->fec;
0bcc2916
RW
455
456 RB_FOREACH(f, fec_tree, &ft) {
457 fn = (struct fec_node *)f;
458 if (fn->fec.type != FEC_TYPE_PWID)
459 continue;
0bcc2916
RW
460
461 pw = (struct l2vpn_pw *) fn->data;
462 if (pw == NULL)
463 continue;
aba50a83
RW
464
465 switch (wcard->type) {
466 case MAP_TYPE_TYPED_WCARD:
467 if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
468 wcard->fec.twcard.u.pw_type != fn->fec.u.pwid.type)
469 continue;
470 break;
471 case MAP_TYPE_PWID:
472 if (wcard->fec.pwid.type != fn->fec.u.pwid.type)
473 continue;
474 if (wcard->fec.pwid.group_id != pw->remote_group)
475 continue;
476 break;
477 }
0bcc2916
RW
478
479 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id,
480 0, 0);
481 if (fnh == NULL)
482 continue;
483
484 /* remote status didn't change */
485 if (pw->remote_status == nm->pw_status)
486 continue;
487 pw->remote_status = nm->pw_status;
488
489 if (l2vpn_pw_ok(pw, fnh))
490 lde_send_change_klabel(fn, fnh);
491 else
492 lde_send_delete_klabel(fn, fnh);
493 }
494}
495
87b5f1b7
RW
496int
497l2vpn_pw_status_update(struct zapi_pw_status *zpw)
498{
499 struct l2vpn *l2vpn;
500 struct l2vpn_pw *pw = NULL;
501 struct lde_nbr *ln;
502 struct fec fec;
503 uint32_t local_status;
504
505 RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
506 pw = l2vpn_pw_find(l2vpn, zpw->ifname);
507 if (pw)
508 break;
509 }
510 if (!pw) {
511 log_warnx("%s: pseudowire %s not found", __func__, zpw->ifname);
512 return (1);
513 }
514
515 if (zpw->status == PW_STATUS_UP)
516 local_status = PW_FORWARDING;
517 else
518 local_status = PW_NOT_FORWARDING;
519
520 /* local status didn't change */
521 if (pw->local_status == local_status)
522 return (0);
523 pw->local_status = local_status;
524
525 /* notify remote peer about the status update */
526 ln = lde_nbr_find_by_lsrid(pw->lsr_id);
527 if (ln == NULL)
528 return (0);
529 l2vpn_pw_fec(pw, &fec);
530 if (pw->flags & F_PW_STATUSTLV)
531 l2vpn_send_pw_status(ln, local_status, &fec);
532 else {
533 struct fec_node *fn;
534 fn = (struct fec_node *)fec_find(&ft, &fec);
535 if (fn) {
536 if (pw->local_status == PW_FORWARDING)
537 lde_send_labelmapping(ln, fn, 1);
538 else
539 lde_send_labelwithdraw(ln, fn, NULL, NULL);
540 }
541 }
542
543 return (0);
544}
545
8429abe0
RW
546void
547l2vpn_pw_ctl(pid_t pid)
548{
549 struct l2vpn *l2vpn;
550 struct l2vpn_pw *pw;
551 static struct ctl_pw pwctl;
552
90d7e7bd 553 RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree)
20bacaeb 554 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
8429abe0 555 memset(&pwctl, 0, sizeof(pwctl));
eac6e3f0
RW
556 strlcpy(pwctl.l2vpn_name, pw->l2vpn->name,
557 sizeof(pwctl.l2vpn_name));
8429abe0
RW
558 strlcpy(pwctl.ifname, pw->ifname,
559 sizeof(pwctl.ifname));
560 pwctl.pwid = pw->pwid;
561 pwctl.lsr_id = pw->lsr_id;
3c5b5220
RW
562 if (pw->enabled &&
563 pw->local_status == PW_FORWARDING &&
87b5f1b7
RW
564 pw->remote_status == PW_FORWARDING)
565 pwctl.status = 1;
8429abe0
RW
566
567 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0,
568 pid, &pwctl, sizeof(pwctl));
569 }
570}
571
572void
573l2vpn_binding_ctl(pid_t pid)
574{
575 struct fec *f;
576 struct fec_node *fn;
577 struct lde_map *me;
578 struct l2vpn_pw *pw;
579 static struct ctl_pw pwctl;
580
581 RB_FOREACH(f, fec_tree, &ft) {
582 if (f->type != FEC_TYPE_PWID)
583 continue;
584
585 fn = (struct fec_node *)f;
586 if (fn->local_label == NO_LABEL &&
45926e58 587 RB_EMPTY(lde_map_head, &fn->downstream))
8429abe0
RW
588 continue;
589
590 memset(&pwctl, 0, sizeof(pwctl));
591 pwctl.type = f->u.pwid.type;
592 pwctl.pwid = f->u.pwid.pwid;
593 pwctl.lsr_id = f->u.pwid.lsr_id;
594
595 pw = (struct l2vpn_pw *) fn->data;
596 if (pw) {
597 pwctl.local_label = fn->local_label;
598 pwctl.local_gid = 0;
599 pwctl.local_ifmtu = pw->l2vpn->mtu;
eac6e3f0
RW
600 pwctl.local_cword = (pw->flags & F_PW_CWORD_CONF) ?
601 1 : 0;
8429abe0
RW
602 } else
603 pwctl.local_label = NO_LABEL;
604
d3e1887a 605 RB_FOREACH(me, lde_map_head, &fn->downstream)
8429abe0
RW
606 if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr)
607 break;
608
609 if (me) {
610 pwctl.remote_label = me->map.label;
611 pwctl.remote_gid = me->map.fec.pwid.group_id;
612 if (me->map.flags & F_MAP_PW_IFMTU)
613 pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu;
eac6e3f0
RW
614 if (pw)
615 pwctl.remote_cword = (pw->flags & F_PW_CWORD) ?
616 1 : 0;
8429abe0
RW
617
618 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
619 0, pid, &pwctl, sizeof(pwctl));
620 } else if (pw) {
621 pwctl.remote_label = NO_LABEL;
622
623 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
624 0, pid, &pwctl, sizeof(pwctl));
625 }
626 }
627}
628
629/* ldpe */
630
631void
632ldpe_l2vpn_init(struct l2vpn *l2vpn)
633{
634 struct l2vpn_pw *pw;
635
20bacaeb 636 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
637 ldpe_l2vpn_pw_init(pw);
638}
639
640void
641ldpe_l2vpn_exit(struct l2vpn *l2vpn)
642{
643 struct l2vpn_pw *pw;
644
20bacaeb 645 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
646 ldpe_l2vpn_pw_exit(pw);
647}
648
649void
650ldpe_l2vpn_pw_init(struct l2vpn_pw *pw)
651{
652 struct tnbr *tnbr;
653
654 tnbr = tnbr_find(leconf, pw->af, &pw->addr);
655 if (tnbr == NULL) {
eac6e3f0 656 tnbr = tnbr_new(pw->af, &pw->addr);
8429abe0 657 tnbr_update(tnbr);
7989cdba 658 RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
8429abe0
RW
659 }
660
661 tnbr->pw_count++;
662}
663
664void
665ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
666{
667 struct tnbr *tnbr;
668
669 tnbr = tnbr_find(leconf, pw->af, &pw->addr);
670 if (tnbr) {
671 tnbr->pw_count--;
7989cdba 672 tnbr_check(leconf, tnbr);
8429abe0
RW
673 }
674}