diff options
| author | Renato Westphal <renato@opensourcerouting.org> | 2017-03-03 17:50:22 -0300 |
|---|---|---|
| committer | Renato Westphal <renato@opensourcerouting.org> | 2017-03-03 17:50:22 -0300 |
| commit | 0bcc2916a08dfb762d8a5775e6b01a4885c8936a (patch) | |
| tree | 09d352749f431edd8c51ba9ade3dd2b64ac4b2dc /ldpd/l2vpn.c | |
| parent | be8e0d318815395a49632f8c6546be1f96c17557 (diff) | |
ldpd: implement support for PWid group wildcards
This was missing from our original RFC 4447 VPLS implementation. Now
ldpd understands group wildcards as mandated by the RFC, but we still
don't send them ourselves. I can't see any case in which sending a group
wildcard would be useful, but nonetheless this patch provides a function
called lde_send_labelwithdraw_pwid_wcard() which is ready to be used in
the future anytime we feel like it might be useful.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ldpd/l2vpn.c')
| -rw-r--r-- | ldpd/l2vpn.c | 71 |
1 files changed, 65 insertions, 6 deletions
diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 792608d425..ad3e8199c9 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -330,7 +330,7 @@ l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map) st.status_code = S_WRONG_CBIT; st.msg_id = map->msg_id; st.msg_type = htons(MSG_TYPE_LABELMAPPING); - lde_send_labelwithdraw(ln, fn, NO_LABEL, &st); + lde_send_labelwithdraw(ln, fn, NULL, &st); pw->flags &= ~F_PW_CWORD; lde_send_labelmapping(ln, fn, 1); @@ -353,7 +353,7 @@ l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map) } void -l2vpn_send_pw_status(uint32_t peerid, uint32_t status, struct fec *fec) +l2vpn_send_pw_status(struct lde_nbr *ln, uint32_t status, struct fec *fec) { struct notify_msg nm; @@ -364,8 +364,27 @@ l2vpn_send_pw_status(uint32_t peerid, uint32_t status, struct fec *fec) lde_fec2map(fec, &nm.fec); nm.flags |= F_NOTIF_FEC; - lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, peerid, 0, - &nm, sizeof(nm)); + lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm, + sizeof(nm)); +} + +void +l2vpn_send_pw_status_wcard(struct lde_nbr *ln, uint32_t status, + uint16_t pw_type, uint32_t group_id) +{ + struct notify_msg nm; + + memset(&nm, 0, sizeof(nm)); + nm.status_code = S_PW_STATUS; + nm.pw_status = status; + nm.flags |= F_NOTIF_PW_STATUS; + nm.fec.type = MAP_TYPE_PWID; + nm.fec.fec.pwid.type = pw_type; + nm.fec.fec.pwid.group_id = group_id; + nm.flags |= F_NOTIF_FEC; + + lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0, &nm, + sizeof(nm)); } void @@ -376,9 +395,10 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) struct fec_nh *fnh; struct l2vpn_pw *pw; - /* TODO group wildcard */ - if (!(nm->fec.flags & F_MAP_PW_ID)) + if (!(nm->fec.flags & F_MAP_PW_ID)) { + l2vpn_recv_pw_status_wcard(ln, nm); return; + } lde_map2fec(&nm->fec, ln->id, &fec); fn = (struct fec_node *)fec_find(&ft, &fec); @@ -406,6 +426,45 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) lde_send_delete_klabel(fn, fnh); } +/* RFC4447 PWid group wildcard */ +void +l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm) +{ + struct fec *f; + struct fec_node *fn; + struct fec_nh *fnh; + struct l2vpn_pw *pw; + + RB_FOREACH(f, fec_tree, &ft) { + fn = (struct fec_node *)f; + if (fn->fec.type != FEC_TYPE_PWID) + continue; + if (fn->fec.u.pwid.type != nm->fec.fec.pwid.type) + continue; + + pw = (struct l2vpn_pw *) fn->data; + if (pw == NULL) + continue; + if (pw->remote_group != nm->fec.fec.pwid.group_id) + continue; + + fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, + 0, 0); + if (fnh == NULL) + continue; + + /* remote status didn't change */ + if (pw->remote_status == nm->pw_status) + continue; + pw->remote_status = nm->pw_status; + + if (l2vpn_pw_ok(pw, fnh)) + lde_send_change_klabel(fn, fnh); + else + lde_send_delete_klabel(fn, fnh); + } +} + void l2vpn_sync_pws(int af, union ldpd_addr *addr) { |
