]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/l2vpn.c
pimd: fix mtracebis tool warning
[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
55cd0f61
DS
79 while (!RB_EMPTY(l2vpn_if_head, &l2vpn->if_tree)) {
80 lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree);
81
029c1958 82 RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
8429abe0
RW
83 free(lif);
84 }
55cd0f61
DS
85 while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_tree)) {
86 pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree);
87
20bacaeb 88 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
8429abe0
RW
89 free(pw);
90 }
55cd0f61
DS
91 while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_inactive_tree)) {
92 pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
93
20bacaeb 94 RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
eac6e3f0
RW
95 free(pw);
96 }
8429abe0
RW
97
98 free(l2vpn);
99}
100
101void
102l2vpn_init(struct l2vpn *l2vpn)
103{
104 struct l2vpn_pw *pw;
105
20bacaeb 106 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
107 l2vpn_pw_init(pw);
108}
109
110void
111l2vpn_exit(struct l2vpn *l2vpn)
112{
113 struct l2vpn_pw *pw;
114
20bacaeb 115 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
116 l2vpn_pw_exit(pw);
117}
118
029c1958 119static __inline int
45926e58 120l2vpn_if_compare(const struct l2vpn_if *a, const struct l2vpn_if *b)
029c1958 121{
36de6e0e 122 return if_cmp_name_func(a->ifname, b->ifname);
029c1958
RW
123}
124
8429abe0 125struct l2vpn_if *
52b530fc 126l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname)
8429abe0
RW
127{
128 struct l2vpn_if *lif;
129
130 if ((lif = calloc(1, sizeof(*lif))) == NULL)
131 fatal("l2vpn_if_new: calloc");
132
133 lif->l2vpn = l2vpn;
52b530fc 134 strlcpy(lif->ifname, ifname, sizeof(lif->ifname));
8429abe0
RW
135
136 return (lif);
137}
138
139struct l2vpn_if *
52bd4c23 140l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname)
eac6e3f0 141{
029c1958
RW
142 struct l2vpn_if lif;
143 strlcpy(lif.ifname, ifname, sizeof(lif.ifname));
144 return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
eac6e3f0
RW
145}
146
52b530fc
RW
147void
148l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif)
149{
150 lif->ifindex = kif->ifindex;
988ded8d 151 lif->operative = kif->operative;
52b530fc
RW
152 memcpy(lif->mac, kif->mac, sizeof(lif->mac));
153}
154
26519d8c
RW
155void
156l2vpn_if_update(struct l2vpn_if *lif)
157{
158 struct l2vpn *l2vpn = lif->l2vpn;
159 struct l2vpn_pw *pw;
160 struct map fec;
161 struct nbr *nbr;
162
988ded8d 163 if (lif->operative)
26519d8c
RW
164 return;
165
166 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
167 nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
168 if (nbr == NULL)
169 continue;
170
171 memset(&fec, 0, sizeof(fec));
172 fec.type = MAP_TYPE_PWID;
173 fec.fec.pwid.type = l2vpn->pw_type;
174 fec.fec.pwid.group_id = 0;
175 fec.flags |= F_MAP_PW_ID;
176 fec.fec.pwid.pwid = pw->pwid;
177
178 send_mac_withdrawal(nbr, &fec, lif->mac);
179 }
180}
181
20bacaeb 182static __inline int
45926e58 183l2vpn_pw_compare(const struct l2vpn_pw *a, const struct l2vpn_pw *b)
20bacaeb 184{
36de6e0e 185 return if_cmp_name_func(a->ifname, b->ifname);
20bacaeb 186}
eac6e3f0 187
8429abe0 188struct l2vpn_pw *
52b530fc 189l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname)
8429abe0
RW
190{
191 struct l2vpn_pw *pw;
192
193 if ((pw = calloc(1, sizeof(*pw))) == NULL)
194 fatal("l2vpn_pw_new: calloc");
195
196 pw->l2vpn = l2vpn;
52b530fc 197 strlcpy(pw->ifname, ifname, sizeof(pw->ifname));
8429abe0
RW
198
199 return (pw);
200}
201
202struct l2vpn_pw *
52bd4c23 203l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname)
eac6e3f0
RW
204{
205 struct l2vpn_pw *pw;
20bacaeb 206 struct l2vpn_pw s;
eac6e3f0 207
20bacaeb
RW
208 strlcpy(s.ifname, ifname, sizeof(s.ifname));
209 pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s);
210 if (pw)
211 return (pw);
212 return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
8429abe0
RW
213}
214
5c3f00af
RW
215struct l2vpn_pw *
216l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname)
217{
218 struct l2vpn_pw s;
219
220 strlcpy(s.ifname, ifname, sizeof(s.ifname));
221 return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s));
222}
223
224struct l2vpn_pw *
225l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname)
226{
227 struct l2vpn_pw s;
228
229 strlcpy(s.ifname, ifname, sizeof(s.ifname));
230 return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
231}
232
52b530fc
RW
233void
234l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif)
235{
236 pw->ifindex = kif->ifindex;
237}
238
8429abe0
RW
239void
240l2vpn_pw_init(struct l2vpn_pw *pw)
241{
242 struct fec fec;
87b5f1b7 243 struct zapi_pw zpw;
8429abe0
RW
244
245 l2vpn_pw_reset(pw);
246
6e8cb226 247 pw2zpw(pw, &zpw);
248 lde_imsg_compose_parent(IMSG_KPW_ADD, 0, &zpw, sizeof(zpw));
249
8429abe0 250 l2vpn_pw_fec(pw, &fec);
88d88a9c 251 lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0,
e132dea0 252 0, 0, (void *)pw);
8cb1fc45 253 lde_kernel_update(&fec);
8429abe0
RW
254}
255
256void
257l2vpn_pw_exit(struct l2vpn_pw *pw)
258{
259 struct fec fec;
87b5f1b7 260 struct zapi_pw zpw;
8429abe0
RW
261
262 l2vpn_pw_fec(pw, &fec);
e132dea0 263 lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0, 0);
8cb1fc45 264 lde_kernel_update(&fec);
87b5f1b7
RW
265
266 pw2zpw(pw, &zpw);
267 lde_imsg_compose_parent(IMSG_KPW_DELETE, 0, &zpw, sizeof(zpw));
8429abe0
RW
268}
269
270static void
271l2vpn_pw_fec(struct l2vpn_pw *pw, struct fec *fec)
272{
273 memset(fec, 0, sizeof(*fec));
274 fec->type = FEC_TYPE_PWID;
275 fec->u.pwid.type = pw->l2vpn->pw_type;
276 fec->u.pwid.pwid = pw->pwid;
277 fec->u.pwid.lsr_id = pw->lsr_id;
278}
279
280void
281l2vpn_pw_reset(struct l2vpn_pw *pw)
282{
283 pw->remote_group = 0;
284 pw->remote_mtu = 0;
87b5f1b7
RW
285 pw->local_status = PW_FORWARDING;
286 pw->remote_status = PW_NOT_FORWARDING;
8429abe0
RW
287
288 if (pw->flags & F_PW_CWORD_CONF)
289 pw->flags |= F_PW_CWORD;
290 else
291 pw->flags &= ~F_PW_CWORD;
292
293 if (pw->flags & F_PW_STATUSTLV_CONF)
294 pw->flags |= F_PW_STATUSTLV;
295 else
296 pw->flags &= ~F_PW_STATUSTLV;
4272a064
KS
297
298 if (pw->flags & F_PW_STATUSTLV_CONF) {
299 struct fec_node *fn;
300 struct fec fec;
301 l2vpn_pw_fec(pw, &fec);
302 fn = (struct fec_node *)fec_find(&ft, &fec);
303 if (fn)
304 pw->remote_status = fn->pw_remote_status;
305 }
306
8429abe0
RW
307}
308
309int
310l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
311{
8429abe0 312 /* check for a remote label */
34eeae65
RW
313 if (fnh->remote_label == NO_LABEL) {
314 log_warnx("%s: pseudowire %s: no remote label", __func__,
315 pw->ifname);
6bbdd9e9 316 pw->reason = F_PW_NO_REMOTE_LABEL;
8429abe0 317 return (0);
34eeae65 318 }
8429abe0
RW
319
320 /* MTUs must match */
34eeae65
RW
321 if (pw->l2vpn->mtu != pw->remote_mtu) {
322 log_warnx("%s: pseudowire %s: MTU mismatch detected", __func__,
323 pw->ifname);
6bbdd9e9 324 pw->reason = F_PW_MTU_MISMATCH;
8429abe0 325 return (0);
34eeae65 326 }
8429abe0
RW
327
328 /* check pw status if applicable */
329 if ((pw->flags & F_PW_STATUSTLV) &&
34eeae65
RW
330 pw->remote_status != PW_FORWARDING) {
331 log_warnx("%s: pseudowire %s: remote end is down", __func__,
332 pw->ifname);
6bbdd9e9 333 pw->reason = F_PW_REMOTE_NOT_FWD;
8429abe0 334 return (0);
34eeae65 335 }
8429abe0 336
6bbdd9e9 337 pw->reason = F_PW_NO_ERR;
8429abe0
RW
338 return (1);
339}
340
341int
342l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map)
343{
344 struct l2vpn_pw *pw;
345 struct status_tlv st;
346
347 /* NOTE: thanks martini & friends for all this mess */
348
349 pw = (struct l2vpn_pw *) fn->data;
350 if (pw == NULL)
351 /*
352 * pseudowire not configured, return and record
353 * the mapping later
354 */
355 return (0);
356
357 /* RFC4447 - Section 6.2: control word negotiation */
358 if (fec_find(&ln->sent_map, &fn->fec)) {
359 if ((map->flags & F_MAP_PW_CWORD) &&
360 !(pw->flags & F_PW_CWORD_CONF)) {
361 /* ignore the received label mapping */
362 return (1);
363 } else if (!(map->flags & F_MAP_PW_CWORD) &&
364 (pw->flags & F_PW_CWORD_CONF)) {
365 /* append a "Wrong C-bit" status code */
366 st.status_code = S_WRONG_CBIT;
367 st.msg_id = map->msg_id;
368 st.msg_type = htons(MSG_TYPE_LABELMAPPING);
0bcc2916 369 lde_send_labelwithdraw(ln, fn, NULL, &st);
8429abe0
RW
370
371 pw->flags &= ~F_PW_CWORD;
372 lde_send_labelmapping(ln, fn, 1);
373 }
374 } else if (map->flags & F_MAP_PW_CWORD) {
375 if (pw->flags & F_PW_CWORD_CONF)
376 pw->flags |= F_PW_CWORD;
377 else
378 /* act as if no label mapping had been received */
379 return (1);
380 } else
381 pw->flags &= ~F_PW_CWORD;
382
383 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */
384 if (fec_find(&ln->recv_map, &fn->fec) == NULL &&
385 !(map->flags & F_MAP_PW_STATUS))
386 pw->flags &= ~F_PW_STATUSTLV;
387
388 return (0);
389}
390
391void
0bcc2916 392l2vpn_send_pw_status(struct lde_nbr *ln, uint32_t status, struct fec *fec)
8429abe0
RW
393{
394 struct notify_msg nm;
395
396 memset(&nm, 0, sizeof(nm));
397 nm.status_code = S_PW_STATUS;
398 nm.pw_status = status;
399 nm.flags |= F_NOTIF_PW_STATUS;
400 lde_fec2map(fec, &nm.fec);
401 nm.flags |= F_NOTIF_FEC;
402
0bcc2916
RW
403 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
404 sizeof(nm));
405}
406
407void
408l2vpn_send_pw_status_wcard(struct lde_nbr *ln, uint32_t status,
409 uint16_t pw_type, uint32_t group_id)
410{
411 struct notify_msg nm;
412
413 memset(&nm, 0, sizeof(nm));
414 nm.status_code = S_PW_STATUS;
415 nm.pw_status = status;
416 nm.flags |= F_NOTIF_PW_STATUS;
417 nm.fec.type = MAP_TYPE_PWID;
418 nm.fec.fec.pwid.type = pw_type;
419 nm.fec.fec.pwid.group_id = group_id;
420 nm.flags |= F_NOTIF_FEC;
421
422 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm,
423 sizeof(nm));
8429abe0
RW
424}
425
426void
427l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm)
428{
429 struct fec fec;
430 struct fec_node *fn;
431 struct fec_nh *fnh;
432 struct l2vpn_pw *pw;
433
aba50a83
RW
434 if (nm->fec.type == MAP_TYPE_TYPED_WCARD ||
435 !(nm->fec.flags & F_MAP_PW_ID)) {
0bcc2916 436 l2vpn_recv_pw_status_wcard(ln, nm);
8429abe0 437 return;
0bcc2916 438 }
8429abe0
RW
439
440 lde_map2fec(&nm->fec, ln->id, &fec);
441 fn = (struct fec_node *)fec_find(&ft, &fec);
442 if (fn == NULL)
443 /* unknown fec */
444 return;
445
4272a064
KS
446 fn->pw_remote_status = nm->pw_status;
447
8429abe0
RW
448 pw = (struct l2vpn_pw *) fn->data;
449 if (pw == NULL)
450 return;
451
e132dea0 452 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0, 0, 0);
8429abe0
RW
453 if (fnh == NULL)
454 return;
455
456 /* remote status didn't change */
457 if (pw->remote_status == nm->pw_status)
458 return;
8429abe0
RW
459 pw->remote_status = nm->pw_status;
460
461 if (l2vpn_pw_ok(pw, fnh))
462 lde_send_change_klabel(fn, fnh);
463 else
464 lde_send_delete_klabel(fn, fnh);
465}
466
0bcc2916
RW
467/* RFC4447 PWid group wildcard */
468void
469l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
470{
471 struct fec *f;
472 struct fec_node *fn;
473 struct fec_nh *fnh;
474 struct l2vpn_pw *pw;
aba50a83 475 struct map *wcard = &nm->fec;
0bcc2916
RW
476
477 RB_FOREACH(f, fec_tree, &ft) {
478 fn = (struct fec_node *)f;
479 if (fn->fec.type != FEC_TYPE_PWID)
480 continue;
0bcc2916
RW
481
482 pw = (struct l2vpn_pw *) fn->data;
483 if (pw == NULL)
484 continue;
aba50a83
RW
485
486 switch (wcard->type) {
487 case MAP_TYPE_TYPED_WCARD:
488 if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
489 wcard->fec.twcard.u.pw_type != fn->fec.u.pwid.type)
490 continue;
491 break;
492 case MAP_TYPE_PWID:
493 if (wcard->fec.pwid.type != fn->fec.u.pwid.type)
494 continue;
495 if (wcard->fec.pwid.group_id != pw->remote_group)
496 continue;
497 break;
498 }
0bcc2916
RW
499
500 fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id,
e132dea0 501 0, 0, 0);
0bcc2916
RW
502 if (fnh == NULL)
503 continue;
504
505 /* remote status didn't change */
506 if (pw->remote_status == nm->pw_status)
507 continue;
508 pw->remote_status = nm->pw_status;
509
510 if (l2vpn_pw_ok(pw, fnh))
511 lde_send_change_klabel(fn, fnh);
512 else
513 lde_send_delete_klabel(fn, fnh);
514 }
515}
516
87b5f1b7
RW
517int
518l2vpn_pw_status_update(struct zapi_pw_status *zpw)
519{
520 struct l2vpn *l2vpn;
521 struct l2vpn_pw *pw = NULL;
522 struct lde_nbr *ln;
523 struct fec fec;
524 uint32_t local_status;
525
526 RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
527 pw = l2vpn_pw_find(l2vpn, zpw->ifname);
528 if (pw)
529 break;
530 }
531 if (!pw) {
532 log_warnx("%s: pseudowire %s not found", __func__, zpw->ifname);
533 return (1);
534 }
535
fd563cc7 536 if (zpw->status == PW_FORWARDING) {
87b5f1b7 537 local_status = PW_FORWARDING;
6bbdd9e9 538 pw->reason = F_PW_NO_ERR;
539 } else {
fd563cc7 540 local_status = zpw->status;
6bbdd9e9 541 pw->reason = F_PW_LOCAL_NOT_FWD;
542 }
87b5f1b7
RW
543
544 /* local status didn't change */
545 if (pw->local_status == local_status)
546 return (0);
547 pw->local_status = local_status;
548
549 /* notify remote peer about the status update */
550 ln = lde_nbr_find_by_lsrid(pw->lsr_id);
551 if (ln == NULL)
552 return (0);
553 l2vpn_pw_fec(pw, &fec);
554 if (pw->flags & F_PW_STATUSTLV)
555 l2vpn_send_pw_status(ln, local_status, &fec);
556 else {
557 struct fec_node *fn;
558 fn = (struct fec_node *)fec_find(&ft, &fec);
559 if (fn) {
560 if (pw->local_status == PW_FORWARDING)
561 lde_send_labelmapping(ln, fn, 1);
562 else
563 lde_send_labelwithdraw(ln, fn, NULL, NULL);
564 }
565 }
566
567 return (0);
568}
569
8429abe0
RW
570void
571l2vpn_pw_ctl(pid_t pid)
572{
573 struct l2vpn *l2vpn;
574 struct l2vpn_pw *pw;
575 static struct ctl_pw pwctl;
576
90d7e7bd 577 RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree)
20bacaeb 578 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
8429abe0 579 memset(&pwctl, 0, sizeof(pwctl));
eac6e3f0
RW
580 strlcpy(pwctl.l2vpn_name, pw->l2vpn->name,
581 sizeof(pwctl.l2vpn_name));
8429abe0
RW
582 strlcpy(pwctl.ifname, pw->ifname,
583 sizeof(pwctl.ifname));
584 pwctl.pwid = pw->pwid;
585 pwctl.lsr_id = pw->lsr_id;
fd563cc7 586 pwctl.status = PW_NOT_FORWARDING;
3c5b5220
RW
587 if (pw->enabled &&
588 pw->local_status == PW_FORWARDING &&
87b5f1b7 589 pw->remote_status == PW_FORWARDING)
fd563cc7 590 pwctl.status = PW_FORWARDING;
8429abe0
RW
591
592 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0,
593 pid, &pwctl, sizeof(pwctl));
594 }
595}
596
597void
598l2vpn_binding_ctl(pid_t pid)
599{
600 struct fec *f;
601 struct fec_node *fn;
602 struct lde_map *me;
603 struct l2vpn_pw *pw;
604 static struct ctl_pw pwctl;
605
606 RB_FOREACH(f, fec_tree, &ft) {
607 if (f->type != FEC_TYPE_PWID)
608 continue;
609
610 fn = (struct fec_node *)f;
611 if (fn->local_label == NO_LABEL &&
45926e58 612 RB_EMPTY(lde_map_head, &fn->downstream))
8429abe0
RW
613 continue;
614
615 memset(&pwctl, 0, sizeof(pwctl));
616 pwctl.type = f->u.pwid.type;
617 pwctl.pwid = f->u.pwid.pwid;
618 pwctl.lsr_id = f->u.pwid.lsr_id;
619
620 pw = (struct l2vpn_pw *) fn->data;
621 if (pw) {
622 pwctl.local_label = fn->local_label;
623 pwctl.local_gid = 0;
624 pwctl.local_ifmtu = pw->l2vpn->mtu;
eac6e3f0
RW
625 pwctl.local_cword = (pw->flags & F_PW_CWORD_CONF) ?
626 1 : 0;
6bbdd9e9 627 pwctl.reason = pw->reason;
8429abe0
RW
628 } else
629 pwctl.local_label = NO_LABEL;
630
d3e1887a 631 RB_FOREACH(me, lde_map_head, &fn->downstream)
8429abe0
RW
632 if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr)
633 break;
634
635 if (me) {
636 pwctl.remote_label = me->map.label;
637 pwctl.remote_gid = me->map.fec.pwid.group_id;
638 if (me->map.flags & F_MAP_PW_IFMTU)
639 pwctl.remote_ifmtu = me->map.fec.pwid.ifmtu;
eac6e3f0
RW
640 if (pw)
641 pwctl.remote_cword = (pw->flags & F_PW_CWORD) ?
642 1 : 0;
8429abe0
RW
643
644 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
645 0, pid, &pwctl, sizeof(pwctl));
646 } else if (pw) {
647 pwctl.remote_label = NO_LABEL;
648
649 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING,
650 0, pid, &pwctl, sizeof(pwctl));
651 }
652 }
653}
654
655/* ldpe */
656
657void
658ldpe_l2vpn_init(struct l2vpn *l2vpn)
659{
660 struct l2vpn_pw *pw;
661
20bacaeb 662 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
663 ldpe_l2vpn_pw_init(pw);
664}
665
666void
667ldpe_l2vpn_exit(struct l2vpn *l2vpn)
668{
669 struct l2vpn_pw *pw;
670
20bacaeb 671 RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
8429abe0
RW
672 ldpe_l2vpn_pw_exit(pw);
673}
674
675void
676ldpe_l2vpn_pw_init(struct l2vpn_pw *pw)
677{
678 struct tnbr *tnbr;
679
680 tnbr = tnbr_find(leconf, pw->af, &pw->addr);
681 if (tnbr == NULL) {
eac6e3f0 682 tnbr = tnbr_new(pw->af, &pw->addr);
8429abe0 683 tnbr_update(tnbr);
7989cdba 684 RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
8429abe0
RW
685 }
686
687 tnbr->pw_count++;
688}
689
690void
691ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
692{
693 struct tnbr *tnbr;
694
695 tnbr = tnbr_find(leconf, pw->af, &pw->addr);
696 if (tnbr) {
697 tnbr->pw_count--;
7989cdba 698 tnbr_check(leconf, tnbr);
8429abe0
RW
699 }
700}