]> git.puffer.fish Git - matthieu/frr.git/commitdiff
fabricd: Add support for TLV 150 (Spine-Leaf-Extension)
authorChristian Franke <chris@opensourcerouting.org>
Fri, 6 Apr 2018 11:49:38 +0000 (13:49 +0200)
committerChristian Franke <chris@opensourcerouting.org>
Wed, 5 Sep 2018 09:38:13 +0000 (11:38 +0200)
To flood the tier calculated by the fabric locality detection,
OpenFabric makes use of TLV 150, defined in
draft-shen-isis-spine-leaf-ext-06, so add support for that TLV.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
isisd/isis_tlvs.c
isisd/isis_tlvs.h

index a433fcdb41a86f3da769b084d55d8c1dfb12ce56..44beb45e43b6e5a402d5a171b165c8bdf8b184bc 100644 (file)
@@ -1329,6 +1329,126 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
        return 0;
 }
 
+/* Functions related to TLV 150 Spine-Leaf-Extension */
+
+static struct isis_spine_leaf *copy_tlv_spine_leaf(
+                               const struct isis_spine_leaf *spine_leaf)
+{
+       if (!spine_leaf)
+               return NULL;
+
+       struct isis_spine_leaf *rv = XMALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+       memcpy(rv, spine_leaf, sizeof(*rv));
+
+       return rv;
+}
+
+static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
+                                 struct sbuf *buf, int indent)
+{
+       if (!spine_leaf)
+               return;
+
+       sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
+       if (spine_leaf->has_tier) {
+               if (spine_leaf->tier == ISIS_TIER_UNDEFINED) {
+                       sbuf_push(buf, indent, "  Tier: undefined\n");
+               } else {
+                       sbuf_push(buf, indent, "  Tier: %" PRIu8 "\n",
+                                 spine_leaf->tier);
+               }
+       }
+
+       sbuf_push(buf, indent, "  Flags:%s%s%s\n",
+                 spine_leaf->is_leaf ? " LEAF" : "",
+                 spine_leaf->is_spine ? " SPINE" : "",
+                 spine_leaf->is_backup ? " BACKUP" : "");
+
+}
+
+static void free_tlv_spine_leaf(struct isis_spine_leaf *spine_leaf)
+{
+       XFREE(MTYPE_ISIS_TLV, spine_leaf);
+}
+
+#define ISIS_SPINE_LEAF_FLAG_TIER 0x08
+#define ISIS_SPINE_LEAF_FLAG_BACKUP 0x04
+#define ISIS_SPINE_LEAF_FLAG_SPINE 0x02
+#define ISIS_SPINE_LEAF_FLAG_LEAF 0x01
+
+static int pack_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
+                              struct stream *s)
+{
+       if (!spine_leaf)
+               return 0;
+
+       uint8_t tlv_len = 2;
+
+       if (STREAM_WRITEABLE(s) < (unsigned)(2 + tlv_len))
+               return 1;
+
+       stream_putc(s, ISIS_TLV_SPINE_LEAF_EXT);
+       stream_putc(s, tlv_len);
+
+       uint16_t spine_leaf_flags = 0;
+
+       if (spine_leaf->has_tier) {
+               spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_TIER;
+               spine_leaf_flags |= spine_leaf->tier << 12;
+       }
+
+       if (spine_leaf->is_leaf)
+               spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_LEAF;
+
+       if (spine_leaf->is_spine)
+               spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_SPINE;
+
+       if (spine_leaf->is_backup)
+               spine_leaf_flags |= ISIS_SPINE_LEAF_FLAG_BACKUP;
+
+       stream_putw(s, spine_leaf_flags);
+
+       return 0;
+}
+
+static int unpack_tlv_spine_leaf(enum isis_tlv_context context,
+                                uint8_t tlv_type, uint8_t tlv_len,
+                                struct stream *s, struct sbuf *log,
+                                void *dest, int indent)
+{
+       struct isis_tlvs *tlvs = dest;
+
+       sbuf_push(log, indent, "Unpacking Spine Leaf Extension TLV...\n");
+       if (tlv_len < 2) {
+               sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
+               stream_forward_getp(s, tlv_len);
+               return 0;
+       }
+
+       if (tlvs->spine_leaf) {
+               sbuf_push(log, indent,
+                         "WARNING: Spine Leaf Extension TLV present multiple times.\n");
+               stream_forward_getp(s, tlv_len);
+               return 0;
+       }
+
+       tlvs->spine_leaf = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->spine_leaf));
+
+       uint16_t spine_leaf_flags = stream_getw(s);
+
+       if (spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_TIER) {
+               tlvs->spine_leaf->has_tier = true;
+               tlvs->spine_leaf->tier = spine_leaf_flags >> 12;
+       }
+
+       tlvs->spine_leaf->is_leaf = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_LEAF;
+       tlvs->spine_leaf->is_spine = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_SPINE;
+       tlvs->spine_leaf->is_backup = spine_leaf_flags & ISIS_SPINE_LEAF_FLAG_BACKUP;
+
+       stream_forward_getp(s, tlv_len - 2);
+       return 0;
+}
+
 /* Functions related to TLV 240 P2P Three-Way Adjacency */
 
 const char *isis_threeway_state_name(enum isis_threeway_state state)
@@ -2187,6 +2307,8 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
 
        rv->threeway_adj = copy_tlv_threeway_adj(tlvs->threeway_adj);
 
+       rv->spine_leaf = copy_tlv_spine_leaf(tlvs->spine_leaf);
+
        return rv;
 }
 
@@ -2250,6 +2372,8 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
                        &tlvs->mt_ipv6_reach, buf, indent);
 
        format_tlv_threeway_adj(tlvs->threeway_adj, buf, indent);
+
+       format_tlv_spine_leaf(tlvs->spine_leaf, buf, indent);
 }
 
 const char *isis_format_tlvs(struct isis_tlvs *tlvs)
@@ -2301,6 +2425,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
        free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
                      &tlvs->mt_ipv6_reach);
        free_tlv_threeway_adj(tlvs->threeway_adj);
+       free_tlv_spine_leaf(tlvs->spine_leaf);
 
        XFREE(MTYPE_ISIS_TLV, tlvs);
 }
@@ -2480,6 +2605,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
                        copy_tlv_threeway_adj(tlvs->threeway_adj);
        }
 
+       rv = pack_tlv_spine_leaf(tlvs->spine_leaf, stream);
+       if (rv)
+               return rv;
+       if (fragment_tlvs) {
+               fragment_tlvs->spine_leaf =
+                       copy_tlv_spine_leaf(tlvs->spine_leaf);
+       }
+
        for (size_t pack_idx = 0; pack_idx < array_size(pack_order);
             pack_idx++) {
                rv = handle_pack_entry(&pack_order[pack_idx], tlvs, stream,
@@ -2679,6 +2812,7 @@ ITEM_TLV_OPS(ipv4_address, "TLV 132 IPv4 Interface Address");
 TLV_OPS(te_router_id, "TLV 134 TE Router ID");
 ITEM_TLV_OPS(extended_ip_reach, "TLV 135 Extended IP Reachability");
 TLV_OPS(dynamic_hostname, "TLV 137 Dynamic Hostname");
+TLV_OPS(spine_leaf, "TLV 150 Spine Leaf Extensions");
 ITEM_TLV_OPS(mt_router_info, "TLV 229 MT Router Information");
 TLV_OPS(threeway_adj, "TLV 240 P2P Three-Way Adjacency");
 ITEM_TLV_OPS(ipv6_address, "TLV 232 IPv6 Interface Address");
@@ -2703,6 +2837,7 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
                [ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
                [ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
                [ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
+               [ISIS_TLV_SPINE_LEAF_EXT] = &tlv_spine_leaf_ops,
                [ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
                [ISIS_TLV_THREE_WAY_ADJ] = &tlv_threeway_adj_ops,
                [ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
@@ -3239,6 +3374,24 @@ void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
        }
 }
 
+void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
+                             bool has_tier, bool is_leaf, bool is_spine,
+                             bool is_backup)
+{
+       assert(!tlvs->spine_leaf);
+
+       tlvs->spine_leaf = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->spine_leaf));
+
+       if (has_tier) {
+               tlvs->spine_leaf->tier = tier;
+       }
+
+       tlvs->spine_leaf->has_tier = has_tier;
+       tlvs->spine_leaf->is_leaf = is_leaf;
+       tlvs->spine_leaf->is_spine = is_spine;
+       tlvs->spine_leaf->is_backup = is_backup;
+}
+
 struct isis_mt_router_info *
 isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
 {
index bd1fa3e6768d3cea582f6b3821393a0bc2b9765a..451321ea98066c11c010cfd78d005eb742706683 100644 (file)
@@ -103,6 +103,17 @@ struct isis_protocols_supported {
        uint8_t *protocols;
 };
 
+#define ISIS_TIER_UNDEFINED 15
+
+struct isis_spine_leaf {
+       uint8_t tier;
+
+       bool has_tier;
+       bool is_leaf;
+       bool is_spine;
+       bool is_backup;
+};
+
 enum isis_threeway_state {
        ISIS_THREEWAY_DOWN = 2,
        ISIS_THREEWAY_INITIALIZING = 1,
@@ -205,6 +216,7 @@ struct isis_tlvs {
        struct isis_item_list ipv6_reach;
        struct isis_mt_item_list mt_ipv6_reach;
        struct isis_threeway_adj *threeway_adj;
+       struct isis_spine_leaf *spine_leaf;
 };
 
 struct isis_subtlvs {
@@ -236,6 +248,7 @@ enum isis_tlv_type {
        ISIS_TLV_TE_ROUTER_ID = 134,
        ISIS_TLV_EXTENDED_IP_REACH = 135,
        ISIS_TLV_DYNAMIC_HOSTNAME = 137,
+       ISIS_TLV_SPINE_LEAF_EXT = 150,
        ISIS_TLV_MT_REACH = 222,
        ISIS_TLV_MT_ROUTER_INFO = 229,
        ISIS_TLV_IPV6_ADDRESS = 232,
@@ -331,6 +344,10 @@ void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
                                const uint8_t *neighbor_id,
                                uint32_t neighbor_circuit_id);
 
+void isis_tlvs_add_spine_leaf(struct isis_tlvs *tlvs, uint8_t tier,
+                             bool has_tier, bool is_leaf, bool is_spine,
+                             bool is_backup);
+
 struct isis_mt_router_info *
 isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
 #endif