From 0a5d2935ffa1cd48d48e71b9a0bd77faeec24c9e Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Tue, 24 May 2022 11:19:28 +0000 Subject: [PATCH] add support for serializing small-metrics IPv4 REACH TLVs 128 and 130 --- code/lspgen/src/lspgen_config.c | 19 +++++++++++++++++-- code/lspgen/src/lspgen_isis.h | 3 +++ code/lspgen/src/lspgen_lsdb.h | 3 ++- code/lspgen/src/lspgen_packet.c | 21 +++++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/code/lspgen/src/lspgen_config.c b/code/lspgen/src/lspgen_config.c index 58c18ac0..1f897375 100644 --- a/code/lspgen/src/lspgen_config.c +++ b/code/lspgen/src/lspgen_config.c @@ -486,6 +486,10 @@ lspgen_read_common_prefix_config(lsdb_attr_t *attr, json_t *obj) if (value && json_is_boolean(value)) { attr->key.prefix.s_flag = json_boolean_value(value); } + value = json_object_get(obj, "small_metrics"); + if (value && json_is_boolean(value)) { + attr->key.prefix.small_metrics = json_boolean_value(value); + } } void @@ -500,7 +504,18 @@ lspgen_read_ipv4_prefix_config(lsdb_node_t *node, json_t *obj) lspgen_read_common_prefix_config(&attr_template, obj); - attr_template.key.attr_type = ISIS_TLV_EXTD_IPV4_REACH; + /* + * TLV type depends on small-metrics and external flag. + */ + if (attr_template.key.prefix.small_metrics) { + if (attr_template.key.prefix.ext_flag) { + attr_template.key.attr_type = ISIS_TLV_EXT_IPV4_REACH; + } else { + attr_template.key.attr_type = ISIS_TLV_INT_IPV4_REACH; + } + } else { + attr_template.key.attr_type = ISIS_TLV_EXTD_IPV4_REACH; + } lsdb_add_node_attr(node, &attr_template); } } @@ -789,4 +804,4 @@ lspgen_read_config(lsdb_ctx_t *ctx) } json_decref(root_obj); -} \ No newline at end of file +} diff --git a/code/lspgen/src/lspgen_isis.h b/code/lspgen/src/lspgen_isis.h index af34f020..1b6ac04b 100644 --- a/code/lspgen/src/lspgen_isis.h +++ b/code/lspgen/src/lspgen_isis.h @@ -23,9 +23,12 @@ enum { #define TLV_OVERHEAD 2 #define ISIS_TLV_AREA 1 +#define ISIS_TLV_IS_REACH 2 #define ISIS_TLV_AUTH 10 #define ISIS_TLV_EXTD_IS_REACH 22 +#define ISIS_TLV_INT_IPV4_REACH 128 #define ISIS_TLV_PROTOCOLS 129 +#define ISIS_TLV_EXT_IPV4_REACH 130 #define ISIS_TLV_IPV4_ADDR 132 #define ISIS_TLV_EXTD_IPV4_REACH 135 #define ISIS_TLV_HOSTNAME 137 diff --git a/code/lspgen/src/lspgen_lsdb.h b/code/lspgen/src/lspgen_lsdb.h index 3d1575f7..27c74a78 100644 --- a/code/lspgen/src/lspgen_lsdb.h +++ b/code/lspgen/src/lspgen_lsdb.h @@ -216,7 +216,8 @@ typedef struct lsdb_attr_prefix_ { s_flag:1, /* domain wide flooding */ adv_range:1, /* Advertise range (binding TLV) */ adv_sid:1, /* Advertise SID */ - adv_tag:1; /* Advertise Tag */ + adv_tag:1, /* Advertise Tag */ + small_metrics:1; /* old-style 6-bit metrics */ uint8_t sid_algo; uint32_t metric; diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index ce3e8967..aa8c802a 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -329,6 +329,7 @@ lspgen_serialize_prefix_subtlv(lsdb_attr_t *attr, io_buffer_t *buf, void lspgen_serialize_attr(lsdb_attr_t *attr, io_buffer_t *buf) { + uint32_t metric, mask; uint8_t attr_len, flags; bool subtlv_present; @@ -358,6 +359,26 @@ lspgen_serialize_attr(lsdb_attr_t *attr, io_buffer_t *buf) attr_len = strnlen(attr->key.hostname, sizeof(attr->key.hostname)); push_data(buf, (uint8_t *)attr->key.hostname, attr_len); break; + case ISIS_TLV_INT_IPV4_REACH: /* fall through */ + case ISIS_TLV_EXT_IPV4_REACH: + metric = attr->key.prefix.metric; + if (metric > 63) { + metric = 63; /* limit metric to 6 bits */ + } + flags = metric; + if (attr->key.prefix.updown_flag) { + flags |= 0x80; + } + push_be_uint(buf, 1, flags); /* default metric */ + push_be_uint(buf, 1, 0x80); /* delay metric */ + push_be_uint(buf, 1, 0x80); /* expense metric */ + push_be_uint(buf, 1, 0x80); /* error metric */ + push_data(buf, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); + mask = 0xffffffff; + /* convert prefix length to mask */ + mask &= ~((1 << ((32 - attr->key.prefix.ipv4_prefix.len)))-1); + push_be_uint(buf, 4, mask); + break; case ISIS_TLV_EXTD_IPV4_REACH: push_be_uint(buf, 4, attr->key.prefix.metric); /* Metric */ flags = attr->key.prefix.ipv4_prefix.len & 0x3f;