diff --git a/code/bngblaster/src/ospf/ospf_def.h b/code/bngblaster/src/ospf/ospf_def.h index 8a0bf29a..6d4832fa 100644 --- a/code/bngblaster/src/ospf/ospf_def.h +++ b/code/bngblaster/src/ospf/ospf_def.h @@ -18,6 +18,11 @@ #define OSPF_LSA_TYPES 12 +#define OSPF_LSA_LINK_P2P 1 +#define OSPF_LSA_LINK_TRANSIT 2 +#define OSPF_LSA_LINK_STUB 3 +#define OSPF_LSA_LINK_VIRTUAL 4 + #define OSPF_VERSION_2 2 #define OSPF_VERSION_3 3 @@ -30,6 +35,7 @@ #define OSPFV3_DBD_LEN_MIN 28 #define OSPF_TX_BUF_LEN 1500 +#define OSPF_MAX_SELF_LSA_LEN 1024 #define OSPF_OPTION_E_BIT 0x02 #define OSPF_OPTION_LLS_BIT 0x10 @@ -44,6 +50,9 @@ #define OSPF_LSA_SEQ_INIT 0x80000001 #define OSPF_LSA_SEQ_MAX 0x7fffffff +#define OSPF_LSA_BORDER_ROUTER 0x01 +#define OSPF_LSA_EXTERNAL_ROUTER 0x02 + #define OSPF_OFFSET_VERSION 0 #define OSPF_OFFSET_TYPE 1 #define OSPF_OFFSET_PACKET_LEN 2 @@ -264,10 +273,9 @@ typedef struct ospf_neighbor_ { bool master; bool oob_resync; - uint32_t dd; uint32_t dr; uint32_t bdr; - + uint32_t dd; uint8_t state; ospf_lsa_key_s dbd_lsa_start; /* DBD LSA cursor */ @@ -300,6 +308,8 @@ typedef struct ospf_interface_ { uint16_t max_len; /* max OSPF payload len without fragmentation */ uint16_t max_fragment_len; /* max OSPF payload len with fragmentation */ + uint16_t metric; + uint32_t dr; uint32_t bdr; struct { @@ -370,6 +380,14 @@ typedef struct ospf_lsa_header_ { uint16_t length; /* Length */ } __attribute__ ((__packed__)) ospf_lsa_header_s; +typedef struct ospf_lsa_link_s { + uint32_t link_id; /* Link ID */ + uint32_t link_data; /* Link Data */ + uint8_t type; /* Type */ + uint8_t tos; /* Tos */ + uint16_t metric; /* Metric */ +} __attribute__ ((__packed__)) ospf_lsa_link_s; + typedef struct ospf_lsa_ { ospf_instance_s *instance; @@ -395,6 +413,7 @@ typedef struct ospf_lsa_ { uint8_t *lsa; uint16_t lsa_len; + uint16_t lsa_buf_len; } ospf_lsa_s; typedef struct ospf_flood_entry_ { diff --git a/code/bngblaster/src/ospf/ospf_lsa.c b/code/bngblaster/src/ospf/ospf_lsa.c index e6241015..1480b404 100644 --- a/code/bngblaster/src/ospf/ospf_lsa.c +++ b/code/bngblaster/src/ospf/ospf_lsa.c @@ -124,6 +124,144 @@ NEXT: } } +ospf_lsa_s * +ospf_lsa_new(ospf_lsa_key_s *key, ospf_instance_s *ospf_instance) +{ + ospf_lsa_s *lsa = calloc(1, sizeof(ospf_lsa_s)); + lsa->instance = ospf_instance; + memcpy(&lsa->key, key, sizeof(ospf_lsa_key_s)); + return lsa; +} + +static bool +ospf_lsa_add_interface(ospf_lsa_s *lsa, ospf_interface_s *ospf_interface) +{ + ospf_neighbor_s *neighbor = ospf_interface->neighbors; + ospf_lsa_link_s *link = (ospf_lsa_link_s*)(lsa->lsa+lsa->lsa_len); + if(ospf_interface->type == OSPF_INTERFACE_P2P) { + if(!(neighbor && neighbor->state == OSPF_NBSTATE_FULL)) { + return false; + } + link->link_id = neighbor->router_id; + link->link_data = ospf_interface->interface->ip.address; + link->type = OSPF_LSA_LINK_P2P; + } else if(ospf_interface->type == OSPF_INTERFACE_BROADCAST) { + while(neighbor) { + if(neighbor->state == OSPF_NBSTATE_FULL && + (ospf_interface->state == OSPF_IFSTATE_DR || + ospf_interface->dr == neighbor->router_id)) { + break; + } + neighbor = neighbor->next; + } + if(neighbor) { + link->link_id = ospf_interface->dr; + link->link_data = ospf_interface->interface->ip.address; + link->type = OSPF_LSA_LINK_TRANSIT; + } else { + link->link_id = ospf_interface->interface->ip.address & ipv4_len_to_mask(ospf_interface->interface->ip.len); + link->link_data = ipv4_len_to_mask(ospf_interface->interface->ip.len); + link->type = OSPF_LSA_LINK_STUB; + } + } else { + return false; + } + link->tos = 0; + link->metric = htobe16(ospf_interface->metric); + lsa->lsa_len += sizeof(ospf_lsa_link_s); + return true; +} + +/** + * This function adds/updates + * the self originated Type 1 Router. + * + * @param ospf_instance OSPF instance + * @return true (success) / false (error) + */ +bool +ospf_lsa_self_update(ospf_instance_s *ospf_instance) +{ + ospf_interface_s *ospf_interface = ospf_instance->interfaces; + + void **search = NULL; + dict_insert_result result; + + uint8_t options = 0; + uint16_t *links; + + ospf_lsa_s *lsa; + ospf_lsa_header_s *hdr; + ospf_lsa_link_s *link; + + ospf_lsa_key_s key = { + .type = OSPF_LSA_TYPE_1, + .id = ospf_instance->config->router_id, + .router = ospf_instance->config->router_id + }; + + search = hb_tree_search(ospf_instance->lsdb, &key); + if(search) { + /* Update existing LSA. */ + lsa = *search; + } else { + /* Create new LSA. */ + lsa = ospf_lsa_new(&key, ospf_instance); + result = hb_tree_insert(ospf_instance->lsdb, &key); + if(result.inserted) { + *result.datum_ptr = lsa; + } else { + LOG_NOARG(OSPF, "Failed to add LSA to LSDB\n"); + return NULL; + } + } + + if(lsa->lsa_buf_len < OSPF_MAX_SELF_LSA_LEN) { + if(lsa->lsa) free(lsa->lsa); + lsa->lsa = malloc(OSPF_MAX_SELF_LSA_LEN); + lsa->lsa_len = 0; + lsa->lsa_buf_len = OSPF_MAX_SELF_LSA_LEN; + } + + clock_gettime(CLOCK_MONOTONIC, &lsa->timestamp); + if(ospf_instance->teardown) { + lsa->age = OSPF_LSA_MAX_AGE; + } + + hdr = (ospf_lsa_header_s*)lsa->lsa; + hdr->age = htobe16(lsa->age); + hdr->options = options; + hdr->type = OSPF_LSA_TYPE_1; + hdr->id = ospf_instance->config->router_id; + hdr->router = ospf_instance->config->router_id; + hdr->seq = htobe32(lsa->seq); + hdr->checksum = 0; + hdr->length = 0; + lsa->lsa_len = OSPF_LSA_HDR_LEN; + + *(lsa->lsa+lsa->lsa_len++) = OSPF_LSA_BORDER_ROUTER|OSPF_LSA_EXTERNAL_ROUTER; + *(lsa->lsa+lsa->lsa_len++) = 0; + links = (uint16_t*)(lsa->lsa+lsa->lsa_len); + + /* Add loopback */ + link = (ospf_lsa_link_s*)(lsa->lsa+lsa->lsa_len); + lsa->lsa_len += sizeof(ospf_lsa_link_s); + link->link_id = ospf_instance->config->router_id; + link->link_data = 0xffffffff; + link->type = OSPF_LSA_LINK_STUB; + link->tos = 0; + link->metric = 0; + links++; + + while(ospf_interface && lsa->lsa_len+sizeof(ospf_lsa_link_s)<=lsa->lsa_buf_len) { + if(ospf_lsa_add_interface(lsa, ospf_interface)) { + links++; + } + ospf_interface = ospf_interface->next; + } + return true; +} + #if 0 /** * ospf_lsa_process_entries diff --git a/code/bngblaster/src/ospf/ospf_neighbor.c b/code/bngblaster/src/ospf/ospf_neighbor.c index 0e93ba42..e55f0989 100644 --- a/code/bngblaster/src/ospf/ospf_neighbor.c +++ b/code/bngblaster/src/ospf/ospf_neighbor.c @@ -359,7 +359,7 @@ ospf_neighbor_dbd_rx(ospf_interface_s *ospf_interface, bbl_network_interface_s *interface = ospf_interface->interface; ospf_instance_s *ospf_instance = ospf_interface->instance; - ospf_lsa_header_s *lsa_hdr; + ospf_lsa_header_s *hdr; ospf_lsa_s *lsa; void **search = NULL; @@ -483,17 +483,17 @@ ospf_neighbor_dbd_rx(ospf_interface_s *ospf_interface, } while(OSPF_PDU_CURSOR_LEN(pdu) >= OSPF_LSA_HDR_LEN) { - lsa_hdr = (ospf_lsa_header_s*)OSPF_PDU_CURSOR(pdu); + hdr = (ospf_lsa_header_s*)OSPF_PDU_CURSOR(pdu); OSPF_PDU_CURSOR_INC(pdu, OSPF_LSA_HDR_LEN); - search = hb_tree_search(ospf_instance->lsdb, &lsa_hdr->type); + search = hb_tree_search(ospf_instance->lsdb, &hdr->type); if(search) { lsa = *search; - if(be32toh(lsa_hdr->seq) <= lsa->seq) { + if(be32toh(hdr->seq) <= lsa->seq) { continue; } } - hb_tree_insert(ospf_neighbor->request_tree, &lsa_hdr->type); + hb_tree_insert(ospf_neighbor->request_tree, &hdr->type); } if(!(ospf_neighbor->dbd_more || flags & OSPF_DBD_FLAG_M)) {