]> git.puffer.fish Git - mirror/frr.git/commitdiff
isisd: add support for TLV 240 P2P Three-Way Adjacency
authorChristian Franke <chris@opensourcerouting.org>
Mon, 5 Mar 2018 17:51:17 +0000 (18:51 +0100)
committerChristian Franke <chris@opensourcerouting.org>
Sat, 10 Mar 2018 17:38:03 +0000 (18:38 +0100)
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
isisd/isis_tlvs.c
isisd/isis_tlvs.h
tests/isisd/test_fuzz_isis_tlv_tests.h.gz

index 452025bed7d912886aaf4cb46c687ca610b198b8..66a19e150fa35e7504f64ad2a8e0ad93e24c2604 100644 (file)
@@ -1329,6 +1329,119 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
        return 0;
 }
 
+/* Functions related to TLV 240 P2P Three-Way Adjacency */
+
+const char *isis_threeway_state_name(enum isis_threeway_state state)
+{
+       switch (state) {
+       case ISIS_THREEWAY_DOWN:
+               return "Down";
+       case ISIS_THREEWAY_INITIALIZING:
+               return "Initializing";
+       case ISIS_THREEWAY_UP:
+               return "Up";
+       default:
+               return "Invalid!";
+       }
+}
+
+static struct isis_threeway_adj *copy_tlv_threeway_adj(
+                               const struct isis_threeway_adj *threeway_adj)
+{
+       if (!threeway_adj)
+               return NULL;
+
+       struct isis_threeway_adj *rv = XMALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+       memcpy(rv, threeway_adj, sizeof(*rv));
+
+       return rv;
+}
+
+static void format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
+                                    struct sbuf *buf, int indent)
+{
+       if (!threeway_adj)
+               return;
+
+       sbuf_push(buf, indent, "P2P Three-Way Adjacency:\n");
+       sbuf_push(buf, indent, "  State: %s (%d)\n",
+                 isis_threeway_state_name(threeway_adj->state),
+                 threeway_adj->state);
+       sbuf_push(buf, indent, "  Extended Local Circuit ID: %" PRIu32 "\n",
+                 threeway_adj->local_circuit_id);
+       if (!threeway_adj->neighbor_set)
+               return;
+
+       sbuf_push(buf, indent, "  Neighbor System ID: %s\n",
+                 isis_format_id(threeway_adj->neighbor_id, 6));
+       sbuf_push(buf, indent, "  Neighbor Extended Circuit ID: %" PRIu32 "\n",
+                 threeway_adj->neighbor_circuit_id);
+}
+
+static void free_tlv_threeway_adj(struct isis_threeway_adj *threeway_adj)
+{
+       XFREE(MTYPE_ISIS_TLV, threeway_adj);
+}
+
+static int pack_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
+                                 struct stream *s)
+{
+       if (!threeway_adj)
+               return 0;
+
+       uint8_t tlv_len = (threeway_adj->neighbor_set) ? 15 : 5;
+
+       if (STREAM_WRITEABLE(s) < (unsigned)(2 + tlv_len))
+               return 1;
+
+       stream_putc(s, ISIS_TLV_THREE_WAY_ADJ);
+       stream_putc(s, tlv_len);
+       stream_putc(s, threeway_adj->state);
+       stream_putl(s, threeway_adj->local_circuit_id);
+
+       if (threeway_adj->neighbor_set) {
+               stream_put(s, threeway_adj->neighbor_id, 6);
+               stream_putl(s, threeway_adj->neighbor_circuit_id);
+       }
+
+       return 0;
+}
+
+static int unpack_tlv_threeway_adj(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 P2P Three-Way Adjacency TLV...\n");
+       if (tlv_len != 5 && tlv_len != 15) {
+               sbuf_push(log, indent, "WARNING: Unexepected TLV size\n");
+               stream_forward_getp(s, tlv_len);
+               return 0;
+       }
+
+       if (tlvs->threeway_adj) {
+               sbuf_push(log, indent,
+                         "WARNING: P2P Three-Way Adjacency TLV present multiple times.\n");
+               stream_forward_getp(s, tlv_len);
+               return 0;
+       }
+
+       tlvs->threeway_adj = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->threeway_adj));
+
+       tlvs->threeway_adj->state = stream_getc(s);
+       tlvs->threeway_adj->local_circuit_id = stream_getl(s);
+
+       if (tlv_len == 15) {
+               tlvs->threeway_adj->neighbor_set = true;
+               stream_get(tlvs->threeway_adj->neighbor_id, s, 6);
+               tlvs->threeway_adj->neighbor_circuit_id = stream_getl(s);
+       }
+
+       return 0;
+}
+
 /* Functions related to TLVs 236/237 IPv6/MT-IPv6 reach */
 
 static struct isis_item *copy_item_ipv6_reach(struct isis_item *i)
@@ -2067,6 +2180,8 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
        copy_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
                      &tlvs->mt_ipv6_reach, &rv->mt_ipv6_reach);
 
+       rv->threeway_adj = copy_tlv_threeway_adj(tlvs->threeway_adj);
+
        return rv;
 }
 
@@ -2128,6 +2243,8 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
 
        format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
                        &tlvs->mt_ipv6_reach, buf, indent);
+
+       format_tlv_threeway_adj(tlvs->threeway_adj, buf, indent);
 }
 
 const char *isis_format_tlvs(struct isis_tlvs *tlvs)
@@ -2178,6 +2295,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
        free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_REACH, &tlvs->ipv6_reach);
        free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
                      &tlvs->mt_ipv6_reach);
+       free_tlv_threeway_adj(tlvs->threeway_adj);
 
        XFREE(MTYPE_ISIS_TLV, tlvs);
 }
@@ -2349,6 +2467,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
                        copy_tlv_te_router_id(tlvs->te_router_id);
        }
 
+       rv = pack_tlv_threeway_adj(tlvs->threeway_adj, stream);
+       if (rv)
+               return rv;
+       if (fragment_tlvs) {
+               fragment_tlvs->threeway_adj =
+                       copy_tlv_threeway_adj(tlvs->threeway_adj);
+       }
+
        for (size_t pack_idx = 0; pack_idx < array_size(pack_order);
             pack_idx++) {
                rv = handle_pack_entry(&pack_order[pack_idx], tlvs, stream,
@@ -2549,6 +2675,7 @@ 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");
 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");
 ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
 
@@ -2572,6 +2699,7 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
                [ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
                [ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_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,
                [ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
                [ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
@@ -3072,6 +3200,25 @@ void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
        append_item(l, (struct isis_item *)r);
 }
 
+void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
+                               enum isis_threeway_state state,
+                               uint32_t local_circuit_id,
+                               const uint8_t *neighbor_id,
+                               uint32_t neighbor_circuit_id)
+{
+       assert(!tlvs->threeway_adj);
+
+       tlvs->threeway_adj = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->threeway_adj));
+       tlvs->threeway_adj->state = state;
+       tlvs->threeway_adj->local_circuit_id = local_circuit_id;
+
+       if (neighbor_id) {
+               tlvs->threeway_adj->neighbor_set = true;
+               memcpy(tlvs->threeway_adj->neighbor_id, neighbor_id, 6);
+               tlvs->threeway_adj->neighbor_circuit_id = neighbor_circuit_id;
+       }
+}
+
 struct isis_mt_router_info *
 isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid)
 {
index 6ade0af28c05dca80ddf00c17f6fece6ab8f056a..98edbf14e7dc0233c7511d1fd1c217f985665619 100644 (file)
@@ -103,6 +103,20 @@ struct isis_protocols_supported {
        uint8_t *protocols;
 };
 
+enum isis_threeway_state {
+       ISIS_THREEWAY_DOWN = 2,
+       ISIS_THREEWAY_INITIALIZING = 1,
+       ISIS_THREEWAY_UP = 0
+};
+
+struct isis_threeway_adj {
+       enum isis_threeway_state state;
+       uint32_t local_circuit_id;
+       bool neighbor_set;
+       uint8_t neighbor_id[6];
+       uint32_t neighbor_circuit_id;
+};
+
 struct isis_item;
 struct isis_item {
        struct isis_item *next;
@@ -190,6 +204,7 @@ struct isis_tlvs {
        char *hostname;
        struct isis_item_list ipv6_reach;
        struct isis_mt_item_list mt_ipv6_reach;
+       struct isis_threeway_adj *threeway_adj;
 };
 
 struct isis_subtlvs {
@@ -227,6 +242,7 @@ enum isis_tlv_type {
        ISIS_TLV_MT_IP_REACH = 235,
        ISIS_TLV_IPV6_REACH = 236,
        ISIS_TLV_MT_IPV6_REACH = 237,
+       ISIS_TLV_THREE_WAY_ADJ = 240,
        ISIS_TLV_MAX = 256,
 
        ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22
@@ -303,6 +319,14 @@ void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
                                  uint8_t *id, uint32_t metric,
                                  uint8_t *subtlvs, uint8_t subtlv_len);
 
+const char *isis_threeway_state_name(enum isis_threeway_state state);
+
+void isis_tlvs_add_threeway_adj(struct isis_tlvs *tlvs,
+                               enum isis_threeway_state state,
+                               uint32_t local_circuit_id,
+                               const uint8_t *neighbor_id,
+                               uint32_t neighbor_circuit_id);
+
 struct isis_mt_router_info *
 isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
 #endif
index 3eb0205a5db812b83d5818bf4c161dcdeadcd7b3..cca702b138f99f61f49760b0d403c8379f085109 100644 (file)
Binary files a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz and b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz differ