lib: Update Link State functions to handle IPv6

In order to add Link State Traffic Engineering to IS-IS, Link State library
should have been updated:

- Correct Node and Edge RB Tree comparison functions to support key > 32 bits
- Change Subnet RB Tree comparison function to take into account host part of
  the prefix i.e. 10.0.0.1/24 and 10.0.0.2/24 are considered as different
- Add new function to convert IS-IS ISO system ID into Vertex or Edge key that
  take into account Endianness architecture
- Correct Vertex and Edge creation and search function accordingly
- Add extra Adjacency entries in Link State Attributes for IPv6 Segment Routing
- Update send/received and show TED functions accordingly

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
Olivier Dugeon 2021-06-22 20:09:54 +02:00
parent 173f8887cc
commit 8693b4d66e
2 changed files with 241 additions and 142 deletions

View File

@ -89,7 +89,7 @@ struct ls_node *ls_node_new(struct ls_node_id adv, struct in_addr rid,
}
}
if (!IN6_IS_ADDR_UNSPECIFIED(&rid6)) {
new->router6_id = rid6;
new->router_id6 = rid6;
SET_FLAG(new->flags, LS_NODE_ROUTER_ID6);
}
return new;
@ -127,7 +127,7 @@ int ls_node_same(struct ls_node *n1, struct ls_node *n2)
&& !IPV4_ADDR_SAME(&n1->router_id, &n2->router_id))
return 0;
if (CHECK_FLAG(n1->flags, LS_NODE_ROUTER_ID6)
&& !IPV6_ADDR_SAME(&n1->router6_id, &n2->router6_id))
&& !IPV6_ADDR_SAME(&n1->router_id6, &n2->router_id6))
return 0;
if (CHECK_FLAG(n1->flags, LS_NODE_FLAG)
&& (n1->node_flag != n2->node_flag))
@ -306,36 +306,23 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
if (CHECK_FLAG(l1->flags, LS_ATTR_USE_BW)
&& (l1->extended.used_bw != l2->extended.used_bw))
return 0;
if (CHECK_FLAG(l1->flags, LS_ATTR_ADJ_SID)) {
if ((l1->adj_sid[0].sid != l2->adj_sid[0].sid)
|| (l1->adj_sid[0].flags != l2->adj_sid[0].flags)
|| (l1->adj_sid[0].weight != l2->adj_sid[0].weight))
for (int i = 0; i < LS_ADJ_MAX; i++) {
if (!CHECK_FLAG(l1->flags, (LS_ATTR_ADJ_SID << i)))
continue;
if ((l1->adj_sid[i].sid != l2->adj_sid[i].sid)
|| (l1->adj_sid[i].flags != l2->adj_sid[i].flags)
|| (l1->adj_sid[i].weight != l2->adj_sid[i].weight))
return 0;
if (((l1->adv.origin == ISIS_L1) || (l1->adv.origin == ISIS_L2))
&& (memcmp(&l1->adj_sid[0].neighbor.sysid,
&l2->adj_sid[0].neighbor.sysid, ISO_SYS_ID_LEN)
&& (memcmp(&l1->adj_sid[i].neighbor.sysid,
&l2->adj_sid[i].neighbor.sysid, ISO_SYS_ID_LEN)
!= 0))
return 0;
if (((l1->adv.origin == OSPFv2) || (l1->adv.origin == STATIC)
|| (l1->adv.origin == DIRECT))
&& (!IPV4_ADDR_SAME(&l1->adj_sid[0].neighbor.addr,
&l2->adj_sid[0].neighbor.addr)))
return 0;
}
if (CHECK_FLAG(l1->flags, LS_ATTR_BCK_ADJ_SID)) {
if ((l1->adj_sid[1].sid != l2->adj_sid[1].sid)
|| (l1->adj_sid[1].flags != l2->adj_sid[1].flags)
|| (l1->adj_sid[1].weight != l2->adj_sid[1].weight))
return 0;
if (((l1->adv.origin == ISIS_L1) || (l1->adv.origin == ISIS_L2))
&& (memcmp(&l1->adj_sid[1].neighbor.sysid,
&l2->adj_sid[1].neighbor.sysid, ISO_SYS_ID_LEN)
!= 0))
return 0;
if (((l1->adv.origin == OSPFv2) || (l1->adv.origin == STATIC)
|| (l1->adv.origin == DIRECT))
&& (!IPV4_ADDR_SAME(&l1->adj_sid[1].neighbor.addr,
&l2->adj_sid[1].neighbor.addr)))
&& (i < ADJ_PRI_IPV6)
&& (!IPV4_ADDR_SAME(&l1->adj_sid[i].neighbor.addr,
&l2->adj_sid[i].neighbor.addr)))
return 0;
}
if (CHECK_FLAG(l1->flags, LS_ATTR_SRLG)
@ -417,6 +404,25 @@ int ls_prefix_same(struct ls_prefix *p1, struct ls_prefix *p2)
/**
* Link State Vertices management functions
*/
uint64_t sysid_to_key(const uint8_t sysid[ISO_SYS_ID_LEN])
{
uint64_t key = 0;
#if BYTE_ORDER == LITTLE_ENDIAN
uint8_t *byte = (uint8_t *)&key;
for (int i = 0; i < ISO_SYS_ID_LEN; i++)
byte[i] = sysid[ISO_SYS_ID_LEN - i - 1];
byte[6] = 0;
byte[7] = 0;
#else
memcpy(&key, sysid, ISO_SYS_ID_LEN);
#endif
return key;
}
struct ls_vertex *ls_vertex_add(struct ls_ted *ted, struct ls_node *node)
{
struct ls_vertex *new;
@ -435,7 +441,7 @@ struct ls_vertex *ls_vertex_add(struct ls_ted *ted, struct ls_node *node)
break;
case ISIS_L1:
case ISIS_L2:
memcpy(&key, &node->adv.id.iso.sys_id, ISO_SYS_ID_LEN);
key = sysid_to_key(node->adv.id.iso.sys_id);
break;
default:
key = 0;
@ -557,7 +563,7 @@ struct ls_vertex *ls_find_vertex_by_id(struct ls_ted *ted,
break;
case ISIS_L1:
case ISIS_L2:
memcpy(&vertex.key, &nid.id.iso.sys_id, ISO_SYS_ID_LEN);
vertex.key = sysid_to_key(nid.id.iso.sys_id);
break;
default:
return NULL;
@ -673,6 +679,46 @@ static void ls_edge_connect_to(struct ls_ted *ted, struct ls_edge *edge)
}
}
static uint64_t get_edge_key(struct ls_attributes *attr, bool dst)
{
uint64_t key = 0;
struct ls_standard *std;
if (!attr)
return key;
std = &attr->standard;
if (dst) {
/* Key is the IPv4 remote address */
if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
key = ((uint64_t)ntohl(std->remote.s_addr))
& 0xffffffff;
/* or the 64 bits LSB of IPv6 remote address */
else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
key = ((uint64_t)ntohl(std->remote6.s6_addr32[2]) << 32
| (uint64_t)ntohl(std->remote6.s6_addr32[3]));
/* of remote identifier if no IP addresses are defined */
else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
key = (((uint64_t)std->remote_id) & 0xffffffff)
| ((uint64_t)std->local_id << 32);
} else {
/* Key is the IPv4 local address */
if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
key = ((uint64_t)ntohl(std->local.s_addr)) & 0xffffffff;
/* or the 64 bits LSB of IPv6 local address */
else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
key = ((uint64_t)ntohl(std->local6.s6_addr32[2]) << 32
| (uint64_t)ntohl(std->local6.s6_addr32[3]));
/* of local identifier if no IP addresses are defined */
else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
key = (((uint64_t)std->local_id) & 0xffffffff)
| ((uint64_t)std->remote_id << 32);
}
return key;
}
struct ls_edge *ls_edge_add(struct ls_ted *ted,
struct ls_attributes *attributes)
{
@ -682,23 +728,7 @@ struct ls_edge *ls_edge_add(struct ls_ted *ted,
if (attributes == NULL)
return NULL;
/* Key is the IPv4 local address */
if (!IPV4_NET0(attributes->standard.local.s_addr))
key = ((uint64_t)ntohl(attributes->standard.local.s_addr))
& 0xffffffff;
/* or the IPv6 local address if IPv4 is not defined */
else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.local6))
key = (uint64_t)(attributes->standard.local6.s6_addr32[0]
& 0xffffffff)
| ((uint64_t)attributes->standard.local6.s6_addr32[1]
<< 32);
/* of local identifier if no IP addresses are defined */
else if (attributes->standard.local_id != 0)
key = (uint64_t)(
(attributes->standard.local_id & 0xffffffff)
| ((uint64_t)attributes->standard.remote_id << 32));
/* Check that key is valid */
key = get_edge_key(attributes, false);
if (key == 0)
return NULL;
@ -736,23 +766,7 @@ struct ls_edge *ls_find_edge_by_source(struct ls_ted *ted,
if (attributes == NULL)
return NULL;
edge.key = 0;
/* Key is the IPv4 local address */
if (!IPV4_NET0(attributes->standard.local.s_addr))
edge.key = ((uint64_t)ntohl(attributes->standard.local.s_addr))
& 0xffffffff;
/* or the IPv6 local address if IPv4 is not defined */
else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.local6))
edge.key = (uint64_t)(attributes->standard.local6.s6_addr32[0]
& 0xffffffff)
| ((uint64_t)attributes->standard.local6.s6_addr32[1]
<< 32);
/* of local identifier if no IP addresses are defined */
else if (attributes->standard.local_id != 0)
edge.key = (uint64_t)(
(attributes->standard.local_id & 0xffffffff)
| ((uint64_t)attributes->standard.remote_id << 32));
edge.key = get_edge_key(attributes, false);
if (edge.key == 0)
return NULL;
@ -767,24 +781,7 @@ struct ls_edge *ls_find_edge_by_destination(struct ls_ted *ted,
if (attributes == NULL)
return NULL;
edge.key = 0;
/* Key is the IPv4 remote address */
if (!IPV4_NET0(attributes->standard.remote.s_addr))
edge.key = ((uint64_t)ntohl(attributes->standard.remote.s_addr))
& 0xffffffff;
/* or the IPv6 remote address if IPv4 is not defined */
else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.remote6))
edge.key =
(uint64_t)(attributes->standard.remote6.s6_addr32[0]
& 0xffffffff)
| ((uint64_t)attributes->standard.remote6.s6_addr32[1]
<< 32);
/* of remote identifier if no IP addresses are defined */
else if (attributes->standard.remote_id != 0)
edge.key = (uint64_t)(
(attributes->standard.remote_id & 0xffffffff)
| ((uint64_t)attributes->standard.local_id << 32));
edge.key = get_edge_key(attributes, true);
if (edge.key == 0)
return NULL;
@ -1177,7 +1174,7 @@ static struct ls_node *ls_parse_node(struct stream *s)
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
node->router_id.s_addr = stream_get_ipv4(s);
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
STREAM_GET(&node->router6_id, s, IPV6_MAX_BYTELEN);
STREAM_GET(&node->router_id6, s, IPV6_MAX_BYTELEN);
if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
STREAM_GETC(s, node->node_flag);
if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
@ -1267,26 +1264,32 @@ static struct ls_attributes *ls_parse_attributes(struct stream *s)
if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
STREAM_GETF(s, attr->extended.used_bw);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
STREAM_GETL(s, attr->adj_sid[0].sid);
STREAM_GETC(s, attr->adj_sid[0].flags);
STREAM_GETC(s, attr->adj_sid[0].weight);
if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
STREAM_GET(attr->adj_sid[0].neighbor.sysid, s,
ISO_SYS_ID_LEN);
else if (attr->adv.origin == OSPFv2)
attr->adj_sid[0].neighbor.addr.s_addr =
stream_get_ipv4(s);
STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr =
stream_get_ipv4(s);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
STREAM_GETL(s, attr->adj_sid[1].sid);
STREAM_GETC(s, attr->adj_sid[1].flags);
STREAM_GETC(s, attr->adj_sid[1].weight);
if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
STREAM_GET(attr->adj_sid[1].neighbor.sysid, s,
ISO_SYS_ID_LEN);
else if (attr->adv.origin == OSPFv2)
attr->adj_sid[1].neighbor.addr.s_addr =
stream_get_ipv4(s);
STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr =
stream_get_ipv4(s);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
STREAM_GET(attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid, s,
ISO_SYS_ID_LEN);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s,
ISO_SYS_ID_LEN);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
STREAM_GETC(s, len);
@ -1401,7 +1404,7 @@ static int ls_format_node(struct stream *s, struct ls_node *node)
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
stream_put_ipv4(s, node->router_id.s_addr);
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
stream_put(s, &node->router6_id, IPV6_MAX_BYTELEN);
stream_put(s, &node->router_id6, IPV6_MAX_BYTELEN);
if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
stream_putc(s, node->node_flag);
if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
@ -1487,26 +1490,32 @@ static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
stream_putf(s, attr->extended.used_bw);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
stream_putl(s, attr->adj_sid[0].sid);
stream_putc(s, attr->adj_sid[0].flags);
stream_putc(s, attr->adj_sid[0].weight);
if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
stream_put(s, attr->adj_sid[0].neighbor.sysid,
ISO_SYS_ID_LEN);
else if (attr->adv.origin == OSPFv2)
stream_put_ipv4(s,
attr->adj_sid[0].neighbor.addr.s_addr);
stream_putl(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
stream_put_ipv4(
s, attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
stream_putl(s, attr->adj_sid[1].sid);
stream_putc(s, attr->adj_sid[1].flags);
stream_putc(s, attr->adj_sid[1].weight);
if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
stream_put(s, attr->adj_sid[1].neighbor.sysid,
ISO_SYS_ID_LEN);
else if (attr->adv.origin == OSPFv2)
stream_put_ipv4(s,
attr->adj_sid[1].neighbor.addr.s_addr);
stream_putl(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
stream_put_ipv4(
s, attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
stream_putl(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
stream_put(s, attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid,
ISO_SYS_ID_LEN);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
stream_putl(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid,
ISO_SYS_ID_LEN);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
stream_putc(s, attr->srlg_len);
@ -1955,6 +1964,7 @@ static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
struct listnode *node;
struct ls_node *lsn;
struct ls_edge *edge;
struct ls_attributes *attr;
struct ls_subnet *subnet;
struct sbuf sbuf;
uint32_t upper;
@ -2019,9 +2029,15 @@ static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
} else {
sbuf_push(&sbuf, 6, "To:\t- (0.0.0.0)");
}
sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
&edge->attributes->standard.local,
&edge->attributes->standard.remote);
attr = edge->attributes;
if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
&attr->standard.local,
&attr->standard.remote);
else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
&attr->standard.local6,
&attr->standard.remote6);
}
sbuf_push(&sbuf, 4, "Incoming Edges: %d\n",
@ -2034,9 +2050,15 @@ static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
} else {
sbuf_push(&sbuf, 6, "From:\t- (0.0.0.0)");
}
sbuf_push(&sbuf, 0, "\tRemote: %pI4\tLocal: %pI4\n",
&edge->attributes->standard.local,
&edge->attributes->standard.remote);
attr = edge->attributes;
if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
&attr->standard.local,
&attr->standard.remote);
else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
&attr->standard.local6,
&attr->standard.remote6);
}
sbuf_push(&sbuf, 4, "Subnets: %d\n", listcount(vertex->prefixes));
@ -2071,7 +2093,7 @@ static void ls_show_vertex_json(struct ls_vertex *vertex,
json_object_string_add(json, "router-id", buf);
}
if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID6)) {
snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router6_id);
snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router_id6);
json_object_string_add(json, "router-id-v6", buf);
}
if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
@ -2235,15 +2257,32 @@ static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
sbuf_push(&sbuf, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
attr->extended.used_bw);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
sbuf_push(&sbuf, 4, "Adjacency-SID: %u", attr->adj_sid[0].sid);
sbuf_push(&sbuf, 4, "IPv4 Adjacency-SID: %u",
attr->adj_sid[ADJ_PRI_IPV4].sid);
sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
attr->adj_sid[0].flags, attr->adj_sid[0].weight);
attr->adj_sid[ADJ_PRI_IPV4].flags,
attr->adj_sid[ADJ_PRI_IPV4].weight);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
sbuf_push(&sbuf, 4, "Bck. Adjacency-SID: %u",
attr->adj_sid[1].sid);
sbuf_push(&sbuf, 4, "IPv4 Bck. Adjacency-SID: %u",
attr->adj_sid[ADJ_BCK_IPV4].sid);
sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
attr->adj_sid[1].flags, attr->adj_sid[1].weight);
attr->adj_sid[ADJ_BCK_IPV4].flags,
attr->adj_sid[ADJ_BCK_IPV4].weight);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
sbuf_push(&sbuf, 4, "IPv6 Adjacency-SID: %u",
attr->adj_sid[ADJ_PRI_IPV6].sid);
sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
attr->adj_sid[ADJ_PRI_IPV6].flags,
attr->adj_sid[ADJ_PRI_IPV6].weight);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SID: %u",
attr->adj_sid[ADJ_BCK_IPV6].sid);
sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
attr->adj_sid[ADJ_BCK_IPV6].flags,
attr->adj_sid[ADJ_BCK_IPV6].weight);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
@ -2374,10 +2413,12 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
jsr = json_object_new_array();
json_object_object_add(json, "segment-routing", jsr);
jobj = json_object_new_object();
json_object_int_add(jobj, "adj-sid", attr->adj_sid[0].sid);
snprintfrr(buf, 6, "0x%x", attr->adj_sid[0].flags);
json_object_int_add(jobj, "adj-sid",
attr->adj_sid[ADJ_PRI_IPV4].sid);
snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV4].flags);
json_object_string_add(jobj, "flags", buf);
json_object_int_add(jobj, "weight", attr->adj_sid[0].weight);
json_object_int_add(jobj, "weight",
attr->adj_sid[ADJ_PRI_IPV4].weight);
json_object_array_add(jsr, jobj);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
@ -2386,10 +2427,38 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
json_object_object_add(json, "segment-routing", jsr);
}
jobj = json_object_new_object();
json_object_int_add(jobj, "adj-sid", attr->adj_sid[1].sid);
snprintfrr(buf, 6, "0x%x", attr->adj_sid[1].flags);
json_object_int_add(jobj, "adj-sid",
attr->adj_sid[ADJ_BCK_IPV4].sid);
snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV4].flags);
json_object_string_add(jobj, "flags", buf);
json_object_int_add(jobj, "weight", attr->adj_sid[1].weight);
json_object_int_add(jobj, "weight",
attr->adj_sid[ADJ_BCK_IPV4].weight);
json_object_array_add(jsr, jobj);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
jsr = json_object_new_array();
json_object_object_add(json, "segment-routing", jsr);
jobj = json_object_new_object();
json_object_int_add(jobj, "adj-sid",
attr->adj_sid[ADJ_PRI_IPV6].sid);
snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV6].flags);
json_object_string_add(jobj, "flags", buf);
json_object_int_add(jobj, "weight",
attr->adj_sid[ADJ_PRI_IPV6].weight);
json_object_array_add(jsr, jobj);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
if (!jsr) {
jsr = json_object_new_array();
json_object_object_add(json, "segment-routing", jsr);
}
jobj = json_object_new_object();
json_object_int_add(jobj, "adj-sid",
attr->adj_sid[ADJ_BCK_IPV6].sid);
snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV6].flags);
json_object_string_add(jobj, "flags", buf);
json_object_int_add(jobj, "weight",
attr->adj_sid[ADJ_BCK_IPV6].weight);
json_object_array_add(jsr, jobj);
}
}

View File

@ -122,7 +122,7 @@ struct ls_node {
struct ls_node_id adv; /* Adv. Router of this Link State */
char name[MAX_NAME_LENGTH]; /* Name of the Node (IS-IS only) */
struct in_addr router_id; /* IPv4 Router ID */
struct in6_addr router6_id; /* IPv6 Router ID */
struct in6_addr router_id6; /* IPv6 Router ID */
uint8_t node_flag; /* IS-IS or OSPF Node flag */
enum ls_node_type type; /* Type of Node */
uint32_t as_number; /* Local or neighbor AS number */
@ -166,6 +166,8 @@ struct ls_node {
#define LS_ATTR_USE_BW 0x00400000
#define LS_ATTR_ADJ_SID 0x01000000
#define LS_ATTR_BCK_ADJ_SID 0x02000000
#define LS_ATTR_ADJ_SID6 0x04000000
#define LS_ATTR_BCK_ADJ_SID6 0x08000000
#define LS_ATTR_SRLG 0x10000000
/* Link State Attributes */
@ -200,6 +202,11 @@ struct ls_attributes {
float rsv_bw; /* Reserved Bandwidth */
float used_bw; /* Utilized Bandwidth */
} extended;
#define ADJ_PRI_IPV4 0
#define ADJ_BCK_IPV4 1
#define ADJ_PRI_IPV6 2
#define ADJ_BCK_IPV6 3
#define LS_ADJ_MAX 4
struct ls_adjacency { /* (LAN)-Adjacency SID for OSPF */
uint32_t sid; /* SID as MPLS label or index */
uint8_t flags; /* Flags */
@ -208,7 +215,7 @@ struct ls_attributes {
struct in_addr addr; /* Neighbor @IP for OSPF */
uint8_t sysid[ISO_SYS_ID_LEN]; /* or Sys-ID for ISIS */
} neighbor;
} adj_sid[2]; /* Primary & Backup (LAN)-Adj. SID */
} adj_sid[4]; /* IPv4/IPv6 & Primary/Backup (LAN)-Adj. SID */
uint32_t *srlgs; /* List of Shared Risk Link Group */
uint8_t srlg_len; /* number of SRLG in the list */
};
@ -412,21 +419,34 @@ struct ls_subnet {
macro_inline int vertex_cmp(const struct ls_vertex *node1,
const struct ls_vertex *node2)
{
return (node1->key - node2->key);
return numcmp(node1->key, node2->key);
}
DECLARE_RBTREE_UNIQ(vertices, struct ls_vertex, entry, vertex_cmp);
macro_inline int edge_cmp(const struct ls_edge *edge1,
const struct ls_edge *edge2)
{
return (edge1->key - edge2->key);
return numcmp(edge1->key, edge2->key);
}
DECLARE_RBTREE_UNIQ(edges, struct ls_edge, entry, edge_cmp);
/*
* Prefix comparison are done to the host part so, 10.0.0.1/24
* and 10.0.0.2/24 are considered come different
*/
macro_inline int subnet_cmp(const struct ls_subnet *a,
const struct ls_subnet *b)
const struct ls_subnet *b)
{
return prefix_cmp(&a->key, &b->key);
if (a->key.family != b->key.family)
return numcmp(a->key.family, b->key.family);
if (a->key.prefixlen != b->key.prefixlen)
return numcmp(a->key.prefixlen, b->key.prefixlen);
if (a->key.family == AF_INET)
return memcmp(&a->key.u.val, &b->key.u.val, 4);
return memcmp(&a->key.u.val, &b->key.u.val, 16);
}
DECLARE_RBTREE_UNIQ(subnets, struct ls_subnet, entry, subnet_cmp);
@ -503,6 +523,16 @@ extern struct ls_vertex *ls_vertex_update(struct ls_ted *ted,
*/
extern void ls_vertex_clean(struct ls_ted *ted, struct ls_vertex *vertex,
struct zclient *zclient);
/**
* This function convert the ISIS ISO system ID into a 64 bits unsigned integer
* following the architecture dependent byte order.
*
* @param sysid The ISO system ID
* @return Key as 64 bits unsigned integer
*/
extern uint64_t sysid_to_key(const uint8_t sysid[ISO_SYS_ID_LEN]);
/**
* Find Vertex in the Link State DB by its unique key.
*