1
0
mirror of https://github.com/rtbrick/bngblaster.git synced 2024-05-06 15:54:57 +00:00

add OSPFv3 link LSA (LSA-8)

This commit is contained in:
Christian Giese
2023-10-12 21:26:09 +00:00
parent 0f437d215f
commit 868db84356
3 changed files with 140 additions and 37 deletions

View File

@@ -324,6 +324,22 @@ typedef struct ospf_lsa_link_ {
uint16_t metric; /* Metric */
} __attribute__ ((__packed__)) ospfv2_lsa_link_s;
typedef struct ospfv3_lsa_prefix_ {
uint8_t prefix_len;
uint8_t prefix_options;
uint16_t metric;
ipv6addr_t prefix;
} __attribute__ ((__packed__)) ospfv3_lsa_prefix_s;
/* Link LSA Format */
typedef struct ospfv3_lsa_link_ {
uint8_t priority; /* Rtr Priority */
uint16_t reserved;
uint8_t options;
ipv6addr_t ll_address;
uint32_t prefix_count;
} __attribute__ ((__packed__)) ospfv3_lsa_link_s;
/* Intra-Area-Prefix LSA Format */
typedef struct ospfv3_lsa_iap_ {
uint16_t prefix_count;
@@ -332,21 +348,14 @@ typedef struct ospfv3_lsa_iap_ {
uint32_t ref_router;
} __attribute__ ((__packed__)) ospfv3_lsa_iap_s;
typedef struct ospfv3_lsa_iap_prefix_ {
uint8_t prefix_len;
uint8_t prefix_options;
uint16_t metric;
ipv6addr_t prefix;
} __attribute__ ((__packed__)) ospfv3_lsa_iap_prefix_s;
typedef struct ospfv3_lsa_nbr_ {
typedef struct ospfv3_lsa_interface_ {
uint8_t type;
uint8_t reserved;
uint16_t metric;
uint32_t interface_id;
uint32_t neighbor_interface_id;
uint32_t neighbor_router_id;
} __attribute__ ((__packed__)) ospfv3_lsa_link_s;
} __attribute__ ((__packed__)) ospfv3_lsa_interface_s;
typedef struct ospf_lsa_key_ {
uint32_t id; /* Link State ID */
@@ -545,6 +554,7 @@ typedef struct ospf_lsa_ {
uint8_t type;
ospf_lsa_key_s key;
ospf_instance_s *instance;
ospf_interface_s *ll_scope;
struct {
ospf_lsa_source type;

View File

@@ -317,6 +317,10 @@ ospf_lsa_flood(ospf_lsa_s *lsa)
ospf_interface = lsa->instance->interfaces;
while(ospf_interface) {
flood_interface = false;
if(lsa->ll_scope && lsa->ll_scope != ospf_interface) {
ospf_interface = ospf_interface->next;
continue;
}
/* Add to neighbors retry list. */
ospf_neighbor = ospf_interface->neighbors;
while(ospf_neighbor) {
@@ -330,7 +334,6 @@ ospf_lsa_flood(ospf_lsa_s *lsa)
}
ospf_neighbor = ospf_neighbor->next;
}
/* Add to interface flood tree if placed on at least one neighbors retry list. */
if(flood_interface) {
ospf_lsa_tree_add(lsa, NULL, ospf_interface->lsa_flood_tree[lsa->type]);
@@ -583,32 +586,32 @@ static uint16_t
ospf_lsa_add_interface_v3(ospf_lsa_s *lsa, ospf_interface_s *ospf_interface)
{
ospf_neighbor_s *ospf_neighbor = ospf_interface->neighbors;
ospfv3_lsa_link_s *link;
uint16_t links = 0;
ospfv3_lsa_interface_s *interface;
uint16_t interfaces = 0;
/* We need space for up to 2 neighbors per interface! */
if(lsa->lsa_len + (sizeof(ospfv3_lsa_link_s)*2) > lsa->lsa_buf_len) {
if(lsa->lsa_len + (sizeof(ospfv3_lsa_interface_s)*2) > lsa->lsa_buf_len) {
return 0;
}
switch(ospf_interface->state) {
case OSPF_IFSTATE_P2P:
if(ospf_interface->neighbors_full) {
link = (ospfv3_lsa_link_s*)(lsa->lsa+lsa->lsa_len);
link->type = OSPF_LSA_LINK_P2P;
link->reserved = 0;
link->metric = htobe16(ospf_interface->metric);
link->interface_id = htobe32(ospf_interface->id);
link->neighbor_interface_id = ospf_neighbor->id;
link->neighbor_router_id = ospf_neighbor->router_id;
lsa->lsa_len += sizeof(ospfv3_lsa_link_s);
links++;
interface = (ospfv3_lsa_interface_s*)(lsa->lsa+lsa->lsa_len);
interface->type = OSPF_LSA_LINK_P2P;
interface->reserved = 0;
interface->metric = htobe16(ospf_interface->metric);
interface->interface_id = htobe32(ospf_interface->id);
interface->neighbor_interface_id = ospf_neighbor->id;
interface->neighbor_router_id = ospf_neighbor->router_id;
lsa->lsa_len += sizeof(ospfv3_lsa_interface_s);
interfaces++;
}
break;
default:
break;
}
return links;
return interfaces;
}
static void
@@ -624,7 +627,7 @@ ospf_lsa_prefix_v3(ospf_instance_s *ospf_instance)
dict_insert_result result;
ospfv3_lsa_iap_s *iap;
ospfv3_lsa_iap_prefix_s *prefix;
ospfv3_lsa_prefix_s *prefix;
uint16_t prefixes = 0;
ospf_lsa_s *lsa;
@@ -678,26 +681,26 @@ ospf_lsa_prefix_v3(ospf_instance_s *ospf_instance)
iap->ref_router = config->router_id;
while(ospf_interface) {
prefix = (ospfv3_lsa_iap_prefix_s*)(lsa->lsa+lsa->lsa_len);
prefix = (ospfv3_lsa_prefix_s*)(lsa->lsa+lsa->lsa_len);
prefix->prefix_len = ospf_interface->interface->ip6.len;
prefix->prefix_options = 0;
prefix->metric = htobe16(ospf_interface->metric);
memcpy(prefix->prefix, ospf_interface->interface->ip6.address, sizeof(ipv6addr_t));
lsa->lsa_len += (sizeof(ospfv3_lsa_iap_prefix_s) - (sizeof(ipv6addr_t)-BITS_TO_BYTES(prefix->prefix_len)));
lsa->lsa_len += (sizeof(ospfv3_lsa_prefix_s) - (sizeof(ipv6addr_t)-BITS_TO_BYTES(prefix->prefix_len)));
prefixes++;
ospf_interface = ospf_interface->next;
}
/* Add external connections */
external_connection = config->external_connection;
while(external_connection && lsa->lsa_len + sizeof(ospfv3_lsa_iap_prefix_s) <= lsa->lsa_buf_len) {
while(external_connection && lsa->lsa_len + sizeof(ospfv3_lsa_prefix_s) <= lsa->lsa_buf_len) {
if(external_connection->ipv6.len) {
prefix = (ospfv3_lsa_iap_prefix_s*)(lsa->lsa+lsa->lsa_len);
prefix = (ospfv3_lsa_prefix_s*)(lsa->lsa+lsa->lsa_len);
prefix->prefix_len = external_connection->ipv6.len;
prefix->prefix_options = 0;
prefix->metric = htobe16(external_connection->metric);
memcpy(prefix->prefix, external_connection->ipv6.address, sizeof(ipv6addr_t));
lsa->lsa_len += (sizeof(ospfv3_lsa_iap_prefix_s) - (sizeof(ipv6addr_t)-BITS_TO_BYTES(prefix->prefix_len)));
lsa->lsa_len += (sizeof(ospfv3_lsa_prefix_s) - (sizeof(ipv6addr_t)-BITS_TO_BYTES(prefix->prefix_len)));
prefixes++;
}
external_connection = external_connection->next;
@@ -709,7 +712,89 @@ ospf_lsa_prefix_v3(ospf_instance_s *ospf_instance)
}
static void
ospf_lsa_links_v3(ospf_lsa_s *lsa)
ospf_lsa_links_v3(ospf_instance_s *ospf_instance)
{
/* Generate Link LSA */
ospf_interface_s *ospf_interface = ospf_instance->interfaces;
ospf_config_s *config = ospf_instance->config;
void **search = NULL;
dict_insert_result result;
ospfv3_lsa_link_s *link;
ospfv3_lsa_prefix_s *prefix;
uint32_t prefixes = 0;
ospf_lsa_s *lsa;
ospf_lsa_header_s *hdr;
ospf_lsa_key_s key = {0};
while(ospf_interface) {
key.id = htobe32(ospf_interface->id);
key.router = config->router_id;
search = hb_tree_search(ospf_instance->lsdb[OSPF_LSA_TYPE_8], &key);
if(search) {
/* Update existing LSA. */
lsa = *search;
if(lsa->lsa && lsa->lsa_buf_len &&
lsa->lsa_buf_len < OSPF_MAX_SELF_LSA_LEN) {
free(lsa->lsa);
lsa->lsa = malloc(OSPF_MAX_SELF_LSA_LEN);
lsa->lsa_buf_len = OSPF_MAX_SELF_LSA_LEN;
}
} else {
/* Create new LSA. */
lsa = ospf_lsa_new(OSPF_LSA_TYPE_8, &key, ospf_instance);
lsa->seq = OSPF_LSA_SEQ_INIT;
lsa->lsa = malloc(OSPF_MAX_SELF_LSA_LEN);
lsa->lsa_buf_len = OSPF_MAX_SELF_LSA_LEN;
result = hb_tree_insert(ospf_instance->lsdb[OSPF_LSA_TYPE_8], &lsa->key);
assert(result.inserted);
if(result.inserted) {
*result.datum_ptr = lsa;
} else {
LOG_NOARG(OSPF, "Failed to add self generated OSPF Type 8 LSA to LSDB\n");
return;
}
}
lsa->ll_scope = ospf_interface;
lsa->source.type = OSPF_SOURCE_SELF;
lsa->source.router_id = config->router_id;
lsa->lsa_len = OSPF_LSA_HDR_LEN;
lsa->expired = false;
lsa->deleted = false;
hdr = (ospf_lsa_header_s*)lsa->lsa;
hdr->options = OSPFV3_FSCOPE_LL;
hdr->type = OSPF_LSA_TYPE_8;
hdr->id = key.id;
hdr->router = key.router;
hdr->seq = htobe32(lsa->seq);
link = (ospfv3_lsa_link_s*)(lsa->lsa+lsa->lsa_len);
lsa->lsa_len += sizeof(ospfv3_lsa_link_s);
link->priority = config->router_priority;
link->reserved = 0;
link->options = OSPF_OPTION_IPV6_BIT|OSPF_OPTION_E_BIT|OSPF_OPTION_R_BIT;
memcpy(link->ll_address, ospf_interface->interface->ip6_ll, sizeof(ipv6addr_t));
if(ospf_interface->interface->ip6.len) {
prefix = (ospfv3_lsa_prefix_s*)(lsa->lsa+lsa->lsa_len);
prefix->prefix_len = ospf_interface->interface->ip6.len;
prefix->prefix_options = 0;
prefix->metric = 0;
memcpy(prefix->prefix, ospf_interface->interface->ip6.address, sizeof(ipv6addr_t));
lsa->lsa_len += (sizeof(ospfv3_lsa_prefix_s) - (sizeof(ipv6addr_t)-BITS_TO_BYTES(prefix->prefix_len)));
prefixes++;
}
link->prefix_count = htobe32(prefixes);
hdr->length = htobe16(lsa->lsa_len);
ospf_lsa_refresh(lsa);
ospf_interface = ospf_interface->next;
}
}
static void
ospf_lsa_interfaces_v3(ospf_lsa_s *lsa)
{
ospf_instance_s *ospf_instance = lsa->instance;
ospf_interface_s *ospf_interface = ospf_instance->interfaces;
@@ -717,15 +802,15 @@ ospf_lsa_links_v3(ospf_lsa_s *lsa)
ospf_external_connection_s *external_connection = NULL;
ospfv3_lsa_link_s *link;
ospfv3_lsa_interface_s *link;
/* Options */
*(uint16_t*)(lsa->lsa+lsa->lsa_len) = OSPF_OPTION_IPV6_BIT|OSPF_OPTION_E_BIT|OSPF_OPTION_R_BIT;;
*(lsa->lsa+lsa->lsa_len+1) = OSPF_OPTION_IPV6_BIT|OSPF_OPTION_E_BIT|OSPF_OPTION_R_BIT;
lsa->lsa_len += sizeof(uint16_t);
/* Add OSPF neighbor interfaces */
while(ospf_interface) {
if(lsa->lsa_len + sizeof(ospfv3_lsa_link_s) <= lsa->lsa_buf_len) {
if(lsa->lsa_len + sizeof(ospfv3_lsa_interface_s) <= lsa->lsa_buf_len) {
ospf_lsa_add_interface_v3(lsa, ospf_interface);
}
ospf_interface = ospf_interface->next;
@@ -733,15 +818,15 @@ ospf_lsa_links_v3(ospf_lsa_s *lsa)
/* Add external connections */
external_connection = config->external_connection;
while(external_connection && lsa->lsa_len + sizeof(ospfv3_lsa_link_s) <= lsa->lsa_buf_len) {
link = (ospfv3_lsa_link_s*)(lsa->lsa+lsa->lsa_len);
while(external_connection && lsa->lsa_len + sizeof(ospfv3_lsa_interface_s) <= lsa->lsa_buf_len) {
link = (ospfv3_lsa_interface_s*)(lsa->lsa+lsa->lsa_len);
link->type = OSPF_LSA_LINK_P2P;
link->reserved = 0;
link->metric = htobe16(external_connection->metric);
link->interface_id = htobe32(external_connection->interface_id);
link->neighbor_interface_id = htobe32(external_connection->neighbor_interface_id);
link->neighbor_router_id = external_connection->router_id;
lsa->lsa_len += sizeof(ospfv3_lsa_link_s);
lsa->lsa_len += sizeof(ospfv3_lsa_interface_s);
external_connection = external_connection->next;
}
}
@@ -986,8 +1071,11 @@ ospf_lsa_self_update(ospf_instance_s *ospf_instance)
} else {
options = OSPFV3_FSCOPE_AREA;
hdr->options = options;
ospf_lsa_links_v3(lsa);
ospf_lsa_interfaces_v3(lsa);
ospf_lsa_links_v3(ospf_instance);
ospf_lsa_prefix_v3(ospf_instance);
}
hdr->length = htobe16(lsa->lsa_len);

View File

@@ -102,6 +102,11 @@ ospf_neighbor_dbd_tx(ospf_neighbor_s *ospf_neighbor)
next = hb_itor_next(itor);
continue;
}
if(lsa->ll_scope && lsa->ll_scope != ospf_neighbor->interface) {
/* Ignore link-local scope LSA belonging to other interfaces. */
next = hb_itor_next(itor);
continue;
}
if((overhead + pdu.pdu_len + OSPF_LLS_HDR_LEN + OSPF_LSA_HDR_LEN) > interface->mtu) {
memcpy(&ospf_neighbor->dbd_lsa_next, &lsa->key, sizeof(ospf_lsa_key_s));
ospf_neighbor->dbd_lsa_type_next = type;