From aba50a83ea59e20bb23929f817560625153a0e25 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 3 Mar 2017 17:50:22 -0300 Subject: [PATCH] ldpd: implement RFC 6667 (Typed Wildcard FEC for PWid) Signed-off-by: Renato Westphal --- ldpd/l2vpn.c | 23 +++++++++++++++++------ ldpd/labelmapping.c | 23 +++++++++++++++++++++++ ldpd/lde.c | 14 ++++++++++++++ ldpd/lde.h | 2 ++ ldpd/lde_lib.c | 7 +++++++ ldpd/ldp.h | 3 +++ ldpd/ldpd.h | 1 + ldpd/log.c | 8 ++++++++ 8 files changed, 75 insertions(+), 6 deletions(-) diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index ad3e8199c..8e17ccb25 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -395,7 +395,8 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) struct fec_nh *fnh; struct l2vpn_pw *pw; - if (!(nm->fec.flags & F_MAP_PW_ID)) { + if (nm->fec.type == MAP_TYPE_TYPED_WCARD || + !(nm->fec.flags & F_MAP_PW_ID)) { l2vpn_recv_pw_status_wcard(ln, nm); return; } @@ -417,7 +418,6 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm) /* remote status didn't change */ if (pw->remote_status == nm->pw_status) return; - pw->remote_status = nm->pw_status; if (l2vpn_pw_ok(pw, fnh)) @@ -434,19 +434,30 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm) struct fec_node *fn; struct fec_nh *fnh; struct l2vpn_pw *pw; + struct map *wcard = &nm->fec; 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; + + switch (wcard->type) { + case MAP_TYPE_TYPED_WCARD: + if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD && + wcard->fec.twcard.u.pw_type != fn->fec.u.pwid.type) + continue; + break; + case MAP_TYPE_PWID: + if (wcard->fec.pwid.type != fn->fec.u.pwid.type) + continue; + if (wcard->fec.pwid.group_id != pw->remote_group) + continue; + break; + } fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0, 0); diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c index 4559ae628..55b890ac7 100644 --- a/ldpd/labelmapping.c +++ b/ldpd/labelmapping.c @@ -94,6 +94,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) msg_size += FEC_ELM_TWCARD_MIN_LEN; switch (me->map.fec.twcard.type) { case MAP_TYPE_PREFIX: + case MAP_TYPE_PWID: msg_size += sizeof(uint16_t); break; default: @@ -626,6 +627,7 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) len = FEC_ELM_TWCARD_MIN_LEN; switch (map->fec.twcard.type) { case MAP_TYPE_PREFIX: + case MAP_TYPE_PWID: len += sizeof(uint16_t); break; default: @@ -655,6 +657,12 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) err |= ibuf_add(buf, &family, sizeof(uint16_t)); break; + case MAP_TYPE_PWID: + twcard_len = sizeof(uint16_t); + err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t)); + pw_type = htons(map->fec.twcard.u.pw_type); + err |= ibuf_add(buf, &pw_type, sizeof(uint16_t)); + break; default: fatalx("gen_fec_tlv: unexpected fec type"); } @@ -860,6 +868,21 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, return (-1); } break; + case MAP_TYPE_PWID: + if (twcard_len != sizeof(uint16_t)) { + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, + msg->type); + return (-1); + } + + memcpy(&map->fec.twcard.u.pw_type, buf + off, + sizeof(uint16_t)); + map->fec.twcard.u.pw_type = + ntohs(map->fec.twcard.u.pw_type); + /* ignore the reserved bit as per RFC 6667 */ + map->fec.twcard.u.pw_type &= ~PW_TWCARD_RESERVED_BIT; + off += sizeof(uint16_t); + break; default: send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id, msg->type); diff --git a/ldpd/lde.c b/ldpd/lde.c index 948a4468c..2392dbf6d 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1017,6 +1017,20 @@ lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *ln, uint16_t af, lde_send_labelwithdraw(ln, NULL, &wcard, NULL); } +void +lde_send_labelwithdraw_twcard_pwid(struct lde_nbr *ln, uint16_t pw_type, + uint32_t label) +{ + struct map wcard; + + memset(&wcard, 0, sizeof(wcard)); + wcard.type = MAP_TYPE_TYPED_WCARD; + wcard.fec.twcard.type = MAP_TYPE_PWID; + wcard.fec.twcard.u.pw_type = pw_type; + wcard.label = label; + lde_send_labelwithdraw(ln, NULL, &wcard, NULL); +} + void lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *ln, uint16_t pw_type, uint32_t group_id) diff --git a/ldpd/lde.h b/ldpd/lde.h index 148e58346..b3af1bbaa 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -147,6 +147,8 @@ void lde_send_labelwithdraw(struct lde_nbr *, struct fec_node *, void lde_send_labelwithdraw_wcard(struct lde_nbr *, uint32_t); void lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *, uint16_t, uint32_t); +void lde_send_labelwithdraw_twcard_pwid(struct lde_nbr *, uint16_t, + uint32_t); void lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *, uint16_t, uint32_t); void lde_send_labelrelease(struct lde_nbr *, struct fec_node *, diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 71ab05f04..4444a1e1a 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -845,6 +845,13 @@ lde_wildcard_apply(struct map *wcard, struct fec *fec, struct lde_map *me) fec->type != FEC_TYPE_IPV6) return (0); return (1); + case MAP_TYPE_PWID: + if (fec->type != FEC_TYPE_PWID) + return (0); + if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD && + wcard->fec.twcard.u.pw_type != fec->u.pwid.type) + return (0); + return (1); default: fatalx("lde_wildcard_apply: unexpected fec type"); } diff --git a/ldpd/ldp.h b/ldpd/ldp.h index 2edf0475c..ffdadf8be 100644 --- a/ldpd/ldp.h +++ b/ldpd/ldp.h @@ -278,8 +278,11 @@ struct address_list_tlv { #define CONTROL_WORD_FLAG 0x8000 #define PW_TYPE_ETHERNET_TAGGED 0x0004 #define PW_TYPE_ETHERNET 0x0005 +#define PW_TYPE_WILDCARD 0x7FFF #define DEFAULT_PW_TYPE PW_TYPE_ETHERNET +#define PW_TWCARD_RESERVED_BIT 0x8000 + /* RFC 4447 Sub-TLV record */ struct subtlv { uint8_t type; diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 36594e54e..7d12c66ce 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -224,6 +224,7 @@ struct map { uint8_t type; union { uint16_t prefix_af; + uint16_t pw_type; } u; } twcard; } fec; diff --git a/ldpd/log.c b/ldpd/log.c index 0e85daea2..5ad8ca0ca 100644 --- a/ldpd/log.c +++ b/ldpd/log.c @@ -342,6 +342,12 @@ log_map(const struct map *map) af_name(map->fec.twcard.u.prefix_af)) < 0) return ("???"); break; + case MAP_TYPE_PWID: + if (snprintf(buf + strlen(buf), sizeof(buf) - + strlen(buf), " (pwid, type %s)", + pw_type_name(map->fec.twcard.u.pw_type)) < 0) + return ("???"); + break; default: if (snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " (unknown type)") < 0) @@ -598,6 +604,8 @@ pw_type_name(uint16_t pw_type) return ("Eth Tagged"); case PW_TYPE_ETHERNET: return ("Ethernet"); + case PW_TYPE_WILDCARD: + return ("Wildcard"); default: snprintf(buf, sizeof(buf), "[%0x]", pw_type); return (buf); -- 2.39.2