---
 l2vpn.c        | 22 +++++++++++++++++-----
 labelmapping.c | 23 +++++++++++++++++++++++
 lde.c          | 14 ++++++++++++++
 lde.h          |  2 ++
 lde_lib.c      |  7 +++++++
 ldp.h          |  3 +++
 ldpd.8         |  9 +++++++++
 ldpd.h         |  1 +
 logmsg.c       |  8 ++++++++
 9 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/l2vpn.c b/l2vpn.c
index e79caa8..6da3560 100644
--- a/l2vpn.c
+++ b/l2vpn.c
@@ -347,7 +347,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;
        }
@@ -385,19 +386,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);
                if (fnh == NULL)
diff --git a/labelmapping.c b/labelmapping.c
index b0e7131..64c5a70 100644
--- a/labelmapping.c
+++ b/labelmapping.c
@@ -97,6 +97,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:
@@ -629,6 +630,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:
@@ -658,6 +660,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");
                }
@@ -863,6 +871,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/lde.c b/lde.c
index cc8459d..c43801e 100644
--- a/lde.c
+++ b/lde.c
@@ -909,6 +909,20 @@ lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *ln, 
uint16_t af,
 }
 
 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/lde.h b/lde.h
index 23cdaae..a0f85f6 100644
--- a/lde.h
+++ b/lde.h
@@ -138,6 +138,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/lde_lib.c b/lde_lib.c
index e111cba..d867e73 100644
--- a/lde_lib.c
+++ b/lde_lib.c
@@ -814,6 +814,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/ldp.h b/ldp.h
index 71cd9de..b895dcd 100644
--- a/ldp.h
+++ b/ldp.h
@@ -280,8 +280,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.8 b/ldpd.8
index cebc222..66771f3 100644
--- a/ldpd.8
+++ b/ldpd.8
@@ -152,6 +152,15 @@ socket used for communication with
 .Re
 .Pp
 .Rs
+.%A K. Raza
+.%A S. Boutros
+.%A C. Pignataro
+.%D July 2012
+.%R RFC 6667
+.%T LDP 'Typed Wildcard' Forwarding Equivalence Class (FEC) for PWid and 
Generalized PWid FEC Elements
+.Re
+.Pp
+.Rs
 .%A C. Pignataro
 .%A R. Asati
 .%D August 2012
diff --git a/ldpd.h b/ldpd.h
index 1eccef5..1436f76 100644
--- a/ldpd.h
+++ b/ldpd.h
@@ -208,6 +208,7 @@ struct map {
                        uint8_t         type;
                        union {
                                uint16_t        prefix_af;
+                               uint16_t        pw_type;
                        } u;
                } twcard;
        } fec;
diff --git a/logmsg.c b/logmsg.c
index 98cbadf..0862205 100644
--- a/logmsg.c
+++ b/logmsg.c
@@ -183,6 +183,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)
@@ -437,6 +443,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);
-- 
1.9.1

Reply via email to