summaryrefslogtreecommitdiff
path: root/ldpd/l2vpn.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2017-03-03 17:50:22 -0300
committerRenato Westphal <renato@opensourcerouting.org>2017-03-03 17:50:22 -0300
commit0bcc2916a08dfb762d8a5775e6b01a4885c8936a (patch)
tree09d352749f431edd8c51ba9ade3dd2b64ac4b2dc /ldpd/l2vpn.c
parentbe8e0d318815395a49632f8c6546be1f96c17557 (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.c71
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)
{