]> git.puffer.fish Git - mirror/frr.git/commitdiff
ldpd: implement RFC 6667 (Typed Wildcard FEC for PWid)
authorRenato Westphal <renato@opensourcerouting.org>
Fri, 3 Mar 2017 20:50:22 +0000 (17:50 -0300)
committerRenato Westphal <renato@opensourcerouting.org>
Fri, 3 Mar 2017 20:50:22 +0000 (17:50 -0300)
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
ldpd/l2vpn.c
ldpd/labelmapping.c
ldpd/lde.c
ldpd/lde.h
ldpd/lde_lib.c
ldpd/ldp.h
ldpd/ldpd.h
ldpd/log.c

index ad3e8199c98b0ef51cc4fb39dfbc76054a78455c..8e17ccb2585076a46f991827dace8ba9cf8ec173 100644 (file)
@@ -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);
index 4559ae628b2cfec6eeb7a2371d79180cae82de0e..55b890ac70a40c47652190d45fbc5bef675065b8 100644 (file)
@@ -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);
index 948a4468cd600d14178d6cba1364ea3983a1d5fb..2392dbf6d00dfe6ed3e6da5c153198471e640cd8 100644 (file)
@@ -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)
index 148e583466ec9c5e5c87e9a84be2f48dc26a05aa..b3af1bbaa4de91a49ae20f82ef4d5e61b99922f1 100644 (file)
@@ -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 *,
index 71ab05f04d92ceb998ce14455813bf3052c9ef56..4444a1e1ac38e2fcafd20d553aa41305455764e1 100644 (file)
@@ -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");
                }
index 2edf0475c9fae130918e2849e51fecf6088c59bc..ffdadf8be9d23c272670e2c804ea9471c0b43b51 100644 (file)
@@ -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;
index 36594e54ecbefd0b49be5a83cd3249ca905f7df2..7d12c66ceeeaccb6ea480885f8a81626c036a34b 100644 (file)
@@ -224,6 +224,7 @@ struct map {
                        uint8_t         type;
                        union {
                                uint16_t        prefix_af;
+                               uint16_t        pw_type;
                        } u;
                } twcard;
        } fec;
index 0e85daea298261a553f6e2797c4db12e47a67f68..5ad8ca0caf378f0eb849362b809e356a9824ac61 100644 (file)
@@ -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);