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>
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.
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.
22 #include <sys/types.h>
32 static void l2vpn_pw_fec(struct l2vpn_pw
*, struct fec
*);
35 l2vpn_new(const char *name
)
39 if ((l2vpn
= calloc(1, sizeof(*l2vpn
))) == NULL
)
40 fatal("l2vpn_new: calloc");
42 strlcpy(l2vpn
->name
, name
, sizeof(l2vpn
->name
));
44 /* set default values */
45 l2vpn
->mtu
= DEFAULT_L2VPN_MTU
;
46 l2vpn
->pw_type
= DEFAULT_PW_TYPE
;
48 LIST_INIT(&l2vpn
->if_list
);
49 LIST_INIT(&l2vpn
->pw_list
);
55 l2vpn_find(struct ldpd_conf
*xconf
, const char *name
)
59 LIST_FOREACH(l2vpn
, &xconf
->l2vpn_list
, entry
)
60 if (strcmp(l2vpn
->name
, name
) == 0)
67 l2vpn_del(struct l2vpn
*l2vpn
)
72 while ((lif
= LIST_FIRST(&l2vpn
->if_list
)) != NULL
) {
73 LIST_REMOVE(lif
, entry
);
76 while ((pw
= LIST_FIRST(&l2vpn
->pw_list
)) != NULL
) {
77 LIST_REMOVE(pw
, entry
);
85 l2vpn_init(struct l2vpn
*l2vpn
)
89 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
)
94 l2vpn_exit(struct l2vpn
*l2vpn
)
98 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
)
103 l2vpn_if_new(struct l2vpn
*l2vpn
, struct kif
*kif
)
105 struct l2vpn_if
*lif
;
107 if ((lif
= calloc(1, sizeof(*lif
))) == NULL
)
108 fatal("l2vpn_if_new: calloc");
111 strlcpy(lif
->ifname
, kif
->ifname
, sizeof(lif
->ifname
));
112 lif
->ifindex
= kif
->ifindex
;
113 lif
->flags
= kif
->flags
;
114 lif
->link_state
= kif
->link_state
;
120 l2vpn_if_find(struct l2vpn
*l2vpn
, unsigned int ifindex
)
122 struct l2vpn_if
*lif
;
124 LIST_FOREACH(lif
, &l2vpn
->if_list
, entry
)
125 if (lif
->ifindex
== ifindex
)
132 l2vpn_pw_new(struct l2vpn
*l2vpn
, struct kif
*kif
)
136 if ((pw
= calloc(1, sizeof(*pw
))) == NULL
)
137 fatal("l2vpn_pw_new: calloc");
140 strlcpy(pw
->ifname
, kif
->ifname
, sizeof(pw
->ifname
));
141 pw
->ifindex
= kif
->ifindex
;
147 l2vpn_pw_find(struct l2vpn
*l2vpn
, unsigned int ifindex
)
151 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
)
152 if (pw
->ifindex
== ifindex
)
159 l2vpn_pw_init(struct l2vpn_pw
*pw
)
165 l2vpn_pw_fec(pw
, &fec
);
166 lde_kernel_insert(&fec
, AF_INET
, (union ldpd_addr
*)&pw
->lsr_id
, 0,
171 l2vpn_pw_exit(struct l2vpn_pw
*pw
)
175 l2vpn_pw_fec(pw
, &fec
);
176 lde_kernel_remove(&fec
, AF_INET
, (union ldpd_addr
*)&pw
->lsr_id
, 0);
180 l2vpn_pw_fec(struct l2vpn_pw
*pw
, struct fec
*fec
)
182 memset(fec
, 0, sizeof(*fec
));
183 fec
->type
= FEC_TYPE_PWID
;
184 fec
->u
.pwid
.type
= pw
->l2vpn
->pw_type
;
185 fec
->u
.pwid
.pwid
= pw
->pwid
;
186 fec
->u
.pwid
.lsr_id
= pw
->lsr_id
;
190 l2vpn_pw_reset(struct l2vpn_pw
*pw
)
192 pw
->remote_group
= 0;
194 pw
->remote_status
= 0;
196 if (pw
->flags
& F_PW_CWORD_CONF
)
197 pw
->flags
|= F_PW_CWORD
;
199 pw
->flags
&= ~F_PW_CWORD
;
201 if (pw
->flags
& F_PW_STATUSTLV_CONF
)
202 pw
->flags
|= F_PW_STATUSTLV
;
204 pw
->flags
&= ~F_PW_STATUSTLV
;
208 l2vpn_pw_ok(struct l2vpn_pw
*pw
, struct fec_nh
*fnh
)
213 /* check for a remote label */
214 if (fnh
->remote_label
== NO_LABEL
)
217 /* MTUs must match */
218 if (pw
->l2vpn
->mtu
!= pw
->remote_mtu
)
221 /* check pw status if applicable */
222 if ((pw
->flags
& F_PW_STATUSTLV
) &&
223 pw
->remote_status
!= PW_FORWARDING
)
226 /* check for a working lsp to the nexthop */
227 memset(&fec
, 0, sizeof(fec
));
230 fec
.type
= FEC_TYPE_IPV4
;
231 fec
.u
.ipv4
.prefix
= pw
->addr
.v4
;
232 fec
.u
.ipv4
.prefixlen
= 32;
235 fec
.type
= FEC_TYPE_IPV6
;
236 fec
.u
.ipv6
.prefix
= pw
->addr
.v6
;
237 fec
.u
.ipv6
.prefixlen
= 128;
240 fatalx("l2vpn_pw_ok: unknown af");
243 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
244 if (fn
== NULL
|| fn
->local_label
== NO_LABEL
)
247 * Need to ensure that there's a label binding for all nexthops.
248 * Otherwise, ECMP for this route could render the pseudowire unusable.
250 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
251 if (fnh
->remote_label
== NO_LABEL
)
258 l2vpn_pw_negotiate(struct lde_nbr
*ln
, struct fec_node
*fn
, struct map
*map
)
261 struct status_tlv st
;
263 /* NOTE: thanks martini & friends for all this mess */
265 pw
= (struct l2vpn_pw
*) fn
->data
;
268 * pseudowire not configured, return and record
273 /* RFC4447 - Section 6.2: control word negotiation */
274 if (fec_find(&ln
->sent_map
, &fn
->fec
)) {
275 if ((map
->flags
& F_MAP_PW_CWORD
) &&
276 !(pw
->flags
& F_PW_CWORD_CONF
)) {
277 /* ignore the received label mapping */
279 } else if (!(map
->flags
& F_MAP_PW_CWORD
) &&
280 (pw
->flags
& F_PW_CWORD_CONF
)) {
281 /* append a "Wrong C-bit" status code */
282 st
.status_code
= S_WRONG_CBIT
;
283 st
.msg_id
= map
->msg_id
;
284 st
.msg_type
= htons(MSG_TYPE_LABELMAPPING
);
285 lde_send_labelwithdraw(ln
, fn
, NO_LABEL
, &st
);
287 pw
->flags
&= ~F_PW_CWORD
;
288 lde_send_labelmapping(ln
, fn
, 1);
290 } else if (map
->flags
& F_MAP_PW_CWORD
) {
291 if (pw
->flags
& F_PW_CWORD_CONF
)
292 pw
->flags
|= F_PW_CWORD
;
294 /* act as if no label mapping had been received */
297 pw
->flags
&= ~F_PW_CWORD
;
299 /* RFC4447 - Section 5.4.3: pseudowire status negotiation */
300 if (fec_find(&ln
->recv_map
, &fn
->fec
) == NULL
&&
301 !(map
->flags
& F_MAP_PW_STATUS
))
302 pw
->flags
&= ~F_PW_STATUSTLV
;
308 l2vpn_send_pw_status(uint32_t peerid
, uint32_t status
, struct fec
*fec
)
310 struct notify_msg nm
;
312 memset(&nm
, 0, sizeof(nm
));
313 nm
.status_code
= S_PW_STATUS
;
314 nm
.pw_status
= status
;
315 nm
.flags
|= F_NOTIF_PW_STATUS
;
316 lde_fec2map(fec
, &nm
.fec
);
317 nm
.flags
|= F_NOTIF_FEC
;
319 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, peerid
, 0,
324 l2vpn_recv_pw_status(struct lde_nbr
*ln
, struct notify_msg
*nm
)
331 /* TODO group wildcard */
332 if (!(nm
->fec
.flags
& F_MAP_PW_ID
))
335 lde_map2fec(&nm
->fec
, ln
->id
, &fec
);
336 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
341 pw
= (struct l2vpn_pw
*) fn
->data
;
345 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)&ln
->id
, 0);
349 /* remote status didn't change */
350 if (pw
->remote_status
== nm
->pw_status
)
353 pw
->remote_status
= nm
->pw_status
;
355 if (l2vpn_pw_ok(pw
, fnh
))
356 lde_send_change_klabel(fn
, fnh
);
358 lde_send_delete_klabel(fn
, fnh
);
362 l2vpn_sync_pws(int af
, union ldpd_addr
*addr
)
370 LIST_FOREACH(l2vpn
, &ldeconf
->l2vpn_list
, entry
) {
371 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
) {
372 if (af
!= pw
->af
|| ldp_addrcmp(af
, &pw
->addr
, addr
))
375 l2vpn_pw_fec(pw
, &fec
);
376 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
379 fnh
= fec_nh_find(fn
, AF_INET
, (union ldpd_addr
*)
384 if (l2vpn_pw_ok(pw
, fnh
))
385 lde_send_change_klabel(fn
, fnh
);
387 lde_send_delete_klabel(fn
, fnh
);
393 l2vpn_pw_ctl(pid_t pid
)
397 static struct ctl_pw pwctl
;
399 LIST_FOREACH(l2vpn
, &ldeconf
->l2vpn_list
, entry
)
400 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
) {
401 memset(&pwctl
, 0, sizeof(pwctl
));
402 strlcpy(pwctl
.ifname
, pw
->ifname
,
403 sizeof(pwctl
.ifname
));
404 pwctl
.pwid
= pw
->pwid
;
405 pwctl
.lsr_id
= pw
->lsr_id
;
406 pwctl
.status
= pw
->flags
& F_PW_STATUS_UP
;
408 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW
, 0,
409 pid
, &pwctl
, sizeof(pwctl
));
414 l2vpn_binding_ctl(pid_t pid
)
420 static struct ctl_pw pwctl
;
422 RB_FOREACH(f
, fec_tree
, &ft
) {
423 if (f
->type
!= FEC_TYPE_PWID
)
426 fn
= (struct fec_node
*)f
;
427 if (fn
->local_label
== NO_LABEL
&&
428 LIST_EMPTY(&fn
->downstream
))
431 memset(&pwctl
, 0, sizeof(pwctl
));
432 pwctl
.type
= f
->u
.pwid
.type
;
433 pwctl
.pwid
= f
->u
.pwid
.pwid
;
434 pwctl
.lsr_id
= f
->u
.pwid
.lsr_id
;
436 pw
= (struct l2vpn_pw
*) fn
->data
;
438 pwctl
.local_label
= fn
->local_label
;
440 pwctl
.local_ifmtu
= pw
->l2vpn
->mtu
;
442 pwctl
.local_label
= NO_LABEL
;
444 LIST_FOREACH(me
, &fn
->downstream
, entry
)
445 if (f
->u
.pwid
.lsr_id
.s_addr
== me
->nexthop
->id
.s_addr
)
449 pwctl
.remote_label
= me
->map
.label
;
450 pwctl
.remote_gid
= me
->map
.fec
.pwid
.group_id
;
451 if (me
->map
.flags
& F_MAP_PW_IFMTU
)
452 pwctl
.remote_ifmtu
= me
->map
.fec
.pwid
.ifmtu
;
454 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
455 0, pid
, &pwctl
, sizeof(pwctl
));
457 pwctl
.remote_label
= NO_LABEL
;
459 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_BINDING
,
460 0, pid
, &pwctl
, sizeof(pwctl
));
468 ldpe_l2vpn_init(struct l2vpn
*l2vpn
)
472 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
)
473 ldpe_l2vpn_pw_init(pw
);
477 ldpe_l2vpn_exit(struct l2vpn
*l2vpn
)
481 LIST_FOREACH(pw
, &l2vpn
->pw_list
, entry
)
482 ldpe_l2vpn_pw_exit(pw
);
486 ldpe_l2vpn_pw_init(struct l2vpn_pw
*pw
)
490 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);
492 tnbr
= tnbr_new(leconf
, pw
->af
, &pw
->addr
);
494 LIST_INSERT_HEAD(&leconf
->tnbr_list
, tnbr
, entry
);
501 ldpe_l2vpn_pw_exit(struct l2vpn_pw
*pw
)
505 tnbr
= tnbr_find(leconf
, pw
->af
, &pw
->addr
);