lspgen config reader: read ospf2 and ospf3 configs

This commit is contained in:
Hannes Gredler
2024-01-11 18:56:06 +00:00
parent 0b3f0052c5
commit aac8fa7d2e
3 changed files with 295 additions and 118 deletions
+17 -17
View File
@@ -638,7 +638,6 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx)
attr_template.key.attr_cp[3] = OSPF_SUBTLV_PREFIX_SID;
lsdb_add_node_attr(node, &attr_template);
}
addr += node->node_index;
/* external prefixes */
ext_per_node = ext_left / nodes_left;
@@ -805,21 +804,20 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx)
lspgen_store_addr(addr, attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN);
attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_node_prefix.len;
attr_template.key.prefix.node_flag = true;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_INTRA_AREA_PREFIX;
attr_template.key.attr_cp[2] = OSPF_IA_PREFIX_LSA_PREFIX;
lsdb_add_node_attr(node, &attr_template);
if (ctx->no_sr) {
/* For non-SR use the Intra-Area-Router-LSA */
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_INTRA_AREA_PREFIX;
attr_template.key.attr_cp[2] = OSPF_IA_PREFIX_LSA_PREFIX;
lsdb_add_node_attr(node, &attr_template);
} else {
attr_template.key.ordinal = 1;
if (!ctx->no_sr) {
lsdb_reset_attr_template(&attr_template);
lspgen_store_addr(addr, attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN);
attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_node_prefix.len;
attr_template.key.prefix.sid = node->node_index;
attr_template.key.prefix.adv_sid = true;
/* For SR use the Extended-Intra-Area-Router-LSA */
attr_template.key.ordinal = 1;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_E_INTRA_AREA_PREFIX;
attr_template.key.attr_cp[2] = OSPF_TLV_INTRA_AREA_PREFIX;
@@ -855,7 +853,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx)
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI;
attr_template.key.attr_cp[2] = OSPF_TLV_SID_LABEL_RANGE;
//attr_template.key.ordinal = 1;
attr_template.key.ordinal = 1;
lsdb_add_node_attr(node, &attr_template);
}
@@ -1458,10 +1456,6 @@ main(int argc, char *argv[])
}
}
/*
* Display options.
*/
lspgen_log_ctx(ctx);
/*
* Read the link-state database from a config file.
@@ -1469,7 +1463,13 @@ main(int argc, char *argv[])
if (ctx->config_read && ctx->config_filename) {
lspgen_read_config(ctx);
} else {
/*
/*
* Display default options.
*/
lspgen_log_ctx(ctx);
/*
* Generate a random graph.
*/
lsdb_init_graph(ctx);
+273 -101
View File
@@ -704,8 +704,11 @@ lspgen_write_config(lsdb_ctx_t *ctx)
ctx->config_file = NULL;
}
/*
* Read an ISO Area from a config and add it as an node attribute.
*/
void
lspgen_read_area_config(lsdb_node_t *node, json_t *obj)
lspgen_read_iso_area_config(lsdb_node_t *node, json_t *obj)
{
struct lsdb_attr_ attr_template;
const char *s;
@@ -838,27 +841,58 @@ lspgen_read_common_prefix_config(lsdb_attr_t *attr, json_t *obj)
void
lspgen_read_ipv4_prefix_config(lsdb_node_t *node, json_t *obj)
{
struct lsdb_ctx_ *ctx;
struct lsdb_attr_ attr_template;
char *s;
ctx = node->ctx;
lsdb_reset_attr_template(&attr_template);
if (json_unpack(obj, "{s:s}", "ipv4_prefix", &s) == 0) {
scan_ipv4_prefix(s, &attr_template.key.prefix.ipv4_prefix);
lspgen_read_common_prefix_config(&attr_template, obj);
/*
* 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;
if (ctx->protocol_id == PROTO_ISIS) {
/*
* IS-IS 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_INT_IPV4_REACH;
attr_template.key.attr_type = ISIS_TLV_EXTD_IPV4_REACH;
}
} else if (ctx->protocol_id == PROTO_OSPF2) {
if (attr_template.key.prefix.node_flag &&
attr_template.key.prefix.adv_sid) {
/* OSPF loopback with prefix sid*/
attr_template.key.ordinal = 1;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_EP;
attr_template.key.attr_cp[2] = OSPF_TLV_EXTENDED_PREFIX;
attr_template.key.attr_cp[3] = OSPF_SUBTLV_PREFIX_SID;
} else if (attr_template.key.prefix.ext_flag) {
/* OSPF external */
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_EXTERNAL;
attr_template.key.start_tlv = true;
} else {
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER;
attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB;
}
} else {
attr_template.key.attr_type = ISIS_TLV_EXTD_IPV4_REACH;
}
lsdb_add_node_attr(node, &attr_template);
}
}
@@ -866,15 +900,48 @@ lspgen_read_ipv4_prefix_config(lsdb_node_t *node, json_t *obj)
void
lspgen_read_ipv6_prefix_config(lsdb_node_t *node, json_t *obj)
{
struct lsdb_ctx_ *ctx;
struct lsdb_attr_ attr_template;
char *s;
ctx = node->ctx;
lsdb_reset_attr_template(&attr_template);
if (json_unpack(obj, "{s:s}", "ipv6_prefix", &s) == 0) {
scan_ipv6_prefix(s, &attr_template.key.prefix.ipv6_prefix);
lspgen_read_common_prefix_config(&attr_template, obj);
attr_template.key.attr_type = ISIS_TLV_EXTD_IPV6_REACH;
lsdb_add_node_attr(node, &attr_template);
if (ctx->protocol_id == PROTO_ISIS) {
attr_template.key.attr_type = ISIS_TLV_EXTD_IPV6_REACH;
} else if (ctx->protocol_id == PROTO_OSPF3) {
if (attr_template.key.prefix.node_flag &&
attr_template.key.prefix.adv_sid) {
/* OSPF loopback with prefix sid*/
attr_template.key.ordinal = 1;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_E_INTRA_AREA_PREFIX;
attr_template.key.attr_cp[2] = OSPF_TLV_INTRA_AREA_PREFIX;
attr_template.key.attr_cp[3] = OSPF_SUBTLV_PREFIX_SID;
} else if (attr_template.key.prefix.ext_flag) {
/* OSPF external */
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_EXTERNAL6;
attr_template.key.start_tlv = true;
} else {
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_INTRA_AREA_PREFIX;
attr_template.key.attr_cp[2] = OSPF_IA_PREFIX_LSA_PREFIX;
}
}
lsdb_add_node_attr(node, &attr_template);
}
}
@@ -904,10 +971,13 @@ lspgen_read_label_binding_config(lsdb_node_t *node, json_t *obj)
void
lspgen_read_capability_config(lsdb_node_t *node, json_t *obj)
{
struct lsdb_ctx_ *ctx;
struct lsdb_attr_ attr_template;
json_t *value;
char *s;
ctx = node->ctx;
if (json_unpack(obj, "{s:s}", "router_id", &s) == 0) {
lsdb_reset_attr_template(&attr_template);
@@ -933,7 +1003,14 @@ lspgen_read_capability_config(lsdb_node_t *node, json_t *obj)
attr_template.key.cap.srgb_range = json_integer_value(value);
}
attr_template.key.attr_type = ISIS_TLV_CAP;
if (ctx->protocol_id == PROTO_ISIS) {
attr_template.key.attr_type = ISIS_TLV_CAP;
} else if (ctx->protocol_id == PROTO_OSPF2 || ctx->protocol_id == PROTO_OSPF3) {
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI;
attr_template.key.attr_cp[2] = OSPF_TLV_SID_LABEL_RANGE;
}
attr_template.key.ordinal = 1;
lsdb_add_node_attr(node, &attr_template);
}
@@ -944,6 +1021,7 @@ lspgen_read_link_config(lsdb_ctx_t *ctx, lsdb_node_t *node, json_t *link_obj)
{
struct lsdb_link_ link_template;
struct lsdb_attr_ attr_template;
uint32_t metric;
json_t *value;
char *s;
@@ -951,34 +1029,101 @@ lspgen_read_link_config(lsdb_ctx_t *ctx, lsdb_node_t *node, json_t *link_obj)
memcpy(link_template.key.local_node_id, node->key.node_id, LSDB_MAX_NODE_ID_SIZE);
if (json_unpack(link_obj, "{s:s}", "remote_node_id", &s) == 0) {
lsdb_scan_node_id(link_template.key.remote_node_id, s);
lsdb_scan_node_id(link_template.key.remote_node_id, s);
value = json_object_get(link_obj, "metric");
if (value && json_is_integer(value)) {
link_template.link_metric = json_integer_value(value);
}
lsdb_add_link(ctx, node, &link_template);
value = json_object_get(link_obj, "metric");
if (value && json_is_integer(value)) {
link_template.link_metric = json_integer_value(value);
}
/* Generate an IS reach for the link */
lsdb_reset_attr_template(&attr_template);
if (json_unpack(link_obj, "{s:s}", "local_link_id", &s) == 0) {
lsdb_scan_node_id(link_template.key.local_link_id, s);
}
value = json_object_get(link_obj, "small_metrics");
if (value && json_is_boolean(value)) {
attr_template.key.prefix.small_metrics = json_boolean_value(value);
}
if (json_unpack(link_obj, "{s:s}", "remote_link_id", &s) == 0) {
lsdb_scan_node_id(link_template.key.remote_link_id, s);
}
/*
* TLV type depends on small-metrics.
*/
if (attr_template.key.prefix.small_metrics) {
attr_template.key.attr_type = ISIS_TLV_IS_REACH;
attr_template.key.start_tlv = true;
} else {
attr_template.key.attr_type = ISIS_TLV_EXTD_IS_REACH;
}
memcpy(attr_template.key.link.remote_node_id, link_template.key.remote_node_id, 7);
attr_template.key.link.metric = link_template.link_metric;
lsdb_add_node_attr(node, &attr_template);
lsdb_add_link(ctx, node, &link_template);
/* Generate an attribute for the link */
lsdb_reset_attr_template(&attr_template);
if (ctx->protocol_id == PROTO_ISIS) {
value = json_object_get(link_obj, "small_metrics");
if (value && json_is_boolean(value)) {
attr_template.key.prefix.small_metrics = json_boolean_value(value);
}
/*
* IS-IS TLV type depends on small-metrics.
*/
if (attr_template.key.prefix.small_metrics) {
attr_template.key.attr_type = ISIS_TLV_IS_REACH;
attr_template.key.start_tlv = true;
/*
* Clip metric.
*/
metric = link_template.link_metric;
if (metric > 63) {
metric = 63; /* 2^6 - 1 */
}
attr_template.key.link.metric = metric;
} else {
attr_template.key.attr_type = ISIS_TLV_EXTD_IS_REACH;
/*
* Clip metric.
*/
metric = link_template.link_metric;
if (metric > 16777215) {
metric = 16777215; /* 2^24 - 1 */
}
attr_template.key.link.metric = metric;
}
memcpy(attr_template.key.link.remote_node_id, link_template.key.remote_node_id, 7);
} else if (ctx->protocol_id == PROTO_OSPF2) {
memcpy(attr_template.key.link.remote_node_id, link_template.key.remote_node_id, 4);
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER;
attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_PTP;
/*
* Clip metric.
*/
metric = link_template.link_metric;
if (metric > 65535) {
metric = 65535; /* 2^16 - 1 */
}
attr_template.key.link.metric = metric;
} else if (ctx->protocol_id == PROTO_OSPF3) {
memcpy(attr_template.key.link.remote_node_id, link_template.key.remote_node_id, 4);
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER;
attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_PTP;
/*
* Clip metric.
*/
metric = link_template.link_metric;
if (metric > 65535) {
metric = 65535; /* 2^16 - 1 */
}
attr_template.key.link.metric = metric;
attr_template.link_state_id = 1;
}
lsdb_add_node_attr(node, &attr_template);
}
}
@@ -1008,20 +1153,32 @@ lspgen_read_node_config(lsdb_ctx_t *ctx, json_t *node_obj)
if (node_template.node_name) {
lsdb_reset_attr_template(&attr_template);
attr_template.key.ordinal = 1;
attr_template.key.attr_type = ISIS_TLV_HOSTNAME;
strncpy(attr_template.key.hostname, node_template.node_name, sizeof(attr_template.key.hostname)-1);
if (ctx->protocol_id == PROTO_ISIS) {
attr_template.key.attr_type = ISIS_TLV_HOSTNAME;
} else if (ctx->protocol_id == PROTO_OSPF2) {
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI;
attr_template.key.attr_cp[2] = OSPF_TLV_HOSTNAME;
}
strncpy(attr_template.key.hostname, node_template.node_name, sizeof(attr_template.key.hostname)-1);
lsdb_add_node_attr(node, &attr_template);
}
value = json_object_get(node_obj, "overload");
if (value && json_is_boolean(value)) {
node->overload = json_boolean_value(value);
}
if (ctx->protocol_id == PROTO_ISIS) {
value = json_object_get(node_obj, "overload");
if (value && json_is_boolean(value)) {
node->overload = json_boolean_value(value);
}
}
value = json_object_get(node_obj, "attach");
if (value && json_is_boolean(value)) {
node->attach = json_boolean_value(value);
}
if (ctx->protocol_id == PROTO_ISIS) {
value = json_object_get(node_obj, "attach");
if (value && json_is_boolean(value)) {
node->attach = json_boolean_value(value);
}
}
if (json_unpack(node_obj, "{s:s}", "sequence", &s) == 0) {
node->sequence = strtol(s, NULL, 0);
@@ -1032,37 +1189,45 @@ lspgen_read_node_config(lsdb_ctx_t *ctx, json_t *node_obj)
node->lsp_lifetime = json_integer_value(value);
}
arr = json_object_get(node_obj, "area_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_area_config(node, json_array_get(arr, idx));
}
}
if (ctx->protocol_id == PROTO_ISIS) {
arr = json_object_get(node_obj, "area_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_iso_area_config(node, json_array_get(arr, idx));
}
}
}
arr = json_object_get(node_obj, "protocol_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_protocol_config(node, json_array_get(arr, idx));
}
}
if (ctx->protocol_id == PROTO_ISIS) {
arr = json_object_get(node_obj, "protocol_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_protocol_config(node, json_array_get(arr, idx));
}
}
}
arr = json_object_get(node_obj, "ipv4_address_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_ipv4_addr_config(node, json_array_get(arr, idx));
}
}
if (ctx->protocol_id == PROTO_ISIS) {
arr = json_object_get(node_obj, "ipv4_address_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_ipv4_addr_config(node, json_array_get(arr, idx));
}
}
}
arr = json_object_get(node_obj, "ipv6_address_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_ipv6_addr_config(node, json_array_get(arr, idx));
}
}
if (ctx->protocol_id == PROTO_ISIS) {
arr = json_object_get(node_obj, "ipv6_address_list");
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_ipv6_addr_config(node, json_array_get(arr, idx));
}
}
}
arr = json_object_get(node_obj, "capability_list");
if (arr && json_is_array(arr)) {
@@ -1100,14 +1265,14 @@ lspgen_read_node_config(lsdb_ctx_t *ctx, json_t *node_obj)
if (arr && json_is_array(arr)) {
num_arr = json_array_size(arr);
for (idx = 0; idx < num_arr; idx++) {
lspgen_read_label_binding_config(node, json_array_get(arr, idx));
lspgen_read_label_binding_config(node, json_array_get(arr, idx));
}
}
}
}
void
lspgen_read_level_config(lsdb_ctx_t *ctx, json_t *level_arr)
lspgen_read_lsdb_config(lsdb_ctx_t *ctx, json_t *level_arr)
{
uint32_t num_nodes, idx;
@@ -1123,8 +1288,9 @@ lspgen_read_config(lsdb_ctx_t *ctx)
json_t *root_obj;
json_error_t error;
json_t *protocol, *instance;
json_t *level;
bool level_found;
json_t *lsdb;
bool lsdb_found;
const char *key;
root_obj = json_load_file(ctx->config_filename, 0, &error);
if (!root_obj) {
@@ -1142,7 +1308,7 @@ lspgen_read_config(lsdb_ctx_t *ctx)
LOG(NORMAL, "Reading config file %s\n", ctx->config_filename);
/*
* protocol
* Protocol
*/
protocol = json_object_get(root_obj, "protocol");
if (!protocol) {
@@ -1162,7 +1328,7 @@ lspgen_read_config(lsdb_ctx_t *ctx)
}
/*
* instance
* Instance
*/
instance = json_object_get(root_obj, "instance");
if (!instance) {
@@ -1180,31 +1346,37 @@ lspgen_read_config(lsdb_ctx_t *ctx)
}
ctx->instance_name = strdup(json_string_value(instance));
switch(ctx->protocol_id) {
case PROTO_ISIS:
level_found = false;
level = json_object_get(root_obj, "level1");
if (level && json_is_array(level)) {
ctx->topology_id.level = 1;
level_found = true;
lspgen_read_level_config(ctx, level);
/* Iterate through all top level objects */
lsdb_found = false;
json_object_foreach(root_obj, key, lsdb) {
/*
* Hunt for the level<N>, area<N> lsdb.
*/
if (!json_is_array(lsdb)) {
continue;
}
level = json_object_get(root_obj, "level2");
if (level && json_is_array(level)) {
ctx->topology_id.level = 2;
level_found = true;
lspgen_read_level_config(ctx, level);
/* OSPF */
if (strstr(key, "area")) {
inet_pton(AF_INET, &key[4], &ctx->topology_id.area);
lspgen_read_lsdb_config(ctx, lsdb);
lsdb_found = true;
break;
}
if (!level_found) {
LOG(ERROR, "Error reading config file %s, no level1|2 object found\n",
ctx->config_filename);
/* IS-IS */
if (strstr(key, "level")) {
ctx->topology_id.level = strtol(&key[5], NULL, 10);
lspgen_read_lsdb_config(ctx, lsdb);
lsdb_found = true;
break;
}
break;
default:
LOG(ERROR, "Error reading config file %s, no config reader for protocol %s\n",
ctx->config_filename, json_string_value(protocol));
}
if (!lsdb_found) {
LOG(ERROR, "Error reading config file %s, no level1|2 or area<n.n.n.n> array found\n",
ctx->config_filename);
}
cleanup:
+5
View File
@@ -827,6 +827,11 @@ lsdb_format_ospf_attr(struct lsdb_attr_ *attr)
case OSPF_TLV_HOSTNAME:
len += snprintf(buf+len, sizeof(buf)-len, ": %s", attr->key.hostname);
break;
case OSPF_TLV_SID_LABEL_RANGE:
len += snprintf(buf+len, sizeof(buf)-len, ": base %u, range %u",
attr->key.cap.srgb_base,
attr->key.cap.srgb_range);
break;
default:
break;
}