From 0bcc2916a08dfb762d8a5775e6b01a4885c8936a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 3 Mar 2017 17:50:22 -0300 Subject: 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 --- ldpd/l2vpn.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 6 deletions(-) (limited to 'ldpd/l2vpn.c') 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) { -- cgit v1.2.3