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)
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;
}
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)
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);
}
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,
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");
[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,
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)
{
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;
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 {
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
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