diff --git a/code/bngblaster/src/bbl.c b/code/bngblaster/src/bbl.c index b2f6e4c5..0b3b76b9 100644 --- a/code/bngblaster/src/bbl.c +++ b/code/bngblaster/src/bbl.c @@ -221,6 +221,7 @@ bbl_smear_job(timer_s *timer) UNUSED(timer); /* LCP Keepalive Interval */ if(g_ctx->config.lcp_keepalive_interval) { + /* Adding 1 nanoseconds to enforce a dedicated timer bucket. */ timer_smear_bucket(&g_ctx->timer_root, g_ctx->config.lcp_keepalive_interval, 1); } } diff --git a/code/bngblaster/src/bbl_access.c b/code/bngblaster/src/bbl_access.c index 7adccf7c..fc734250 100644 --- a/code/bngblaster/src/bbl_access.c +++ b/code/bngblaster/src/bbl_access.c @@ -410,12 +410,12 @@ bbl_access_igmp_initial_join(timer_s *timer) session->zapping_count = rand() % g_ctx->config.igmp_zap_count; } - /* Adding 1 nanosecond to enforce a dedicated timer bucket for zapping. */ - timer_add_periodic(&g_ctx->timer_root, &session->timer_zapping, "IGMP Zapping", g_ctx->config.igmp_zap_interval, 1, session, &bbl_access_igmp_zapping); + /* Adding 2 nanoseconds to enforce a dedicated timer bucket for zapping. */ + timer_add_periodic(&g_ctx->timer_root, &session->timer_zapping, "IGMP Zapping", g_ctx->config.igmp_zap_interval, 2, session, &bbl_access_igmp_zapping); LOG(IGMP, "IGMP (ID: %u) ZAPPING start zapping with interval %u\n", session->session_id, g_ctx->config.igmp_zap_interval); - timer_smear_bucket(&g_ctx->timer_root, g_ctx->config.igmp_zap_interval, 1); + timer_smear_bucket(&g_ctx->timer_root, g_ctx->config.igmp_zap_interval, 2); } } diff --git a/code/bngblaster/src/bbl_config.c b/code/bngblaster/src/bbl_config.c index 077b5dc4..29ed4bf4 100644 --- a/code/bngblaster/src/bbl_config.c +++ b/code/bngblaster/src/bbl_config.c @@ -1315,7 +1315,8 @@ json_parse_isis_config(json_t *isis, isis_config_s *isis_config) json_t *sub, *con, *c, *value = NULL; const char *s = NULL; int i, size; - + double number; + isis_external_connection_s *connection = NULL; const char *schema[] = { @@ -1447,7 +1448,12 @@ json_parse_isis_config(json_t *isis, isis_config_s *isis_config) value = json_object_get(isis, "hello-interval"); if(json_is_number(value)) { - isis_config->hello_interval = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->hello-interval (1 - 65535)\n"); + return false; + } + isis_config->hello_interval = number; } else { isis_config->hello_interval = ISIS_DEFAULT_HELLO_INTERVAL; } @@ -1459,49 +1465,84 @@ json_parse_isis_config(json_t *isis, isis_config_s *isis_config) value = json_object_get(isis, "hold-time"); if(json_is_number(value)) { - isis_config->hold_time = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->hold-time (1 - 65535)\n"); + return false; + } + isis_config->hold_time = number; } else { isis_config->hold_time = ISIS_DEFAULT_HOLD_TIME; } value = json_object_get(isis, "lsp-lifetime"); if(json_is_number(value)) { - isis_config->lsp_lifetime = json_number_value(value); + number = json_number_value(value); + if(number < ISIS_DEFAULT_LSP_LIFETIME_MIN || number > ISIS_DEFAULT_LSP_LIFETIME) { + fprintf(stderr, "JSON config error: Invalid value for isis->lsp-lifetime (330 - 65535)\n"); + return false; + } + isis_config->lsp_lifetime = number; } else { isis_config->lsp_lifetime = ISIS_DEFAULT_LSP_LIFETIME; } value = json_object_get(isis, "lsp-refresh-interval"); if(json_is_number(value)) { - isis_config->lsp_refresh_interval = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->lsp-refresh-interval (1 - 65535)\n"); + return false; + } + isis_config->lsp_refresh_interval = number; } else { isis_config->lsp_refresh_interval = ISIS_DEFAULT_LSP_REFRESH_IVL; } value = json_object_get(isis, "lsp-retry-interval"); if(json_is_number(value)) { - isis_config->lsp_retry_interval = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->lsp-retry-interval (1 - 65535)\n"); + return false; + } + isis_config->lsp_retry_interval = number; } else { isis_config->lsp_retry_interval = ISIS_DEFAULT_LSP_RETRY_IVL; } value = json_object_get(isis, "lsp-tx-interval"); if(json_is_number(value)) { - isis_config->lsp_tx_interval = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->lsp-tx-interval (1 - 65535)\n"); + return false; + } + isis_config->lsp_tx_interval = number; } else { isis_config->lsp_tx_interval = ISIS_DEFAULT_LSP_TX_IVL_MS; } value = json_object_get(isis, "lsp-tx-window-size"); if(json_is_number(value)) { - isis_config->lsp_tx_window_size = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->lsp-tx-window-size (1 - 65535)\n"); + return false; + } + isis_config->lsp_tx_window_size = number; } else { isis_config->lsp_tx_window_size = ISIS_DEFAULT_LSP_WINDOWS_SIZE; } value = json_object_get(isis, "csnp-interval"); if(json_is_number(value)) { - isis_config->csnp_interval = json_number_value(value); + number = json_number_value(value); + if(number < 1 || number > UINT16_MAX) { + fprintf(stderr, "JSON config error: Invalid value for isis->csnp-interval (1 - 65535)\n"); + return false; + } + isis_config->csnp_interval = number; } else { isis_config->csnp_interval = ISIS_DEFAULT_CSNP_INTERVAL; } diff --git a/code/bngblaster/src/isis/isis.c b/code/bngblaster/src/isis/isis.c index 4ee52690..9fcd4f3a 100644 --- a/code/bngblaster/src/isis/isis.c +++ b/code/bngblaster/src/isis/isis.c @@ -76,7 +76,7 @@ isis_init() { } if(config->external_mrt_file) { - if(!isis_mrt_load(instance, config->external_mrt_file)) { + if(!isis_mrt_load(instance, config->external_mrt_file, true)) { LOG(ISIS, "Failed to load MRT file %s\n", config->external_mrt_file); return false; } diff --git a/code/bngblaster/src/isis/isis_csnp.c b/code/bngblaster/src/isis/isis_csnp.c index 1e580c51..714013cc 100644 --- a/code/bngblaster/src/isis/isis_csnp.c +++ b/code/bngblaster/src/isis/isis_csnp.c @@ -78,37 +78,52 @@ isis_csnp_job(timer_s *timer) while(next) { lsp = *hb_itor_datum(itor); - /* Calculate remaining lifetime and ignore if already expired. */ - timespec_sub(&ago, &now, &lsp->timestamp); - if(ago.tv_sec < lsp->lifetime) { - remaining_lifetime = lsp->lifetime - ago.tv_sec; - - if(tlv->len > UINT8_MAX-ISIS_LSP_ENTRY_LEN) { - /* Open next LSP entry TLV */ - if(pdu.pdu_len+sizeof(isis_tlv_s)+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { - adjacency->csnp_start = lsp->id; - break; - } - tlv = (isis_tlv_s *)PDU_CURSOR(&pdu); - tlv->type = ISIS_TLV_LSP_ENTRIES; - tlv->len = 0; - PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_tlv_s)); - } else { - if(pdu.pdu_len+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { - /* All entries do not fit into single CSNP. */ - adjacency->csnp_start = lsp->id; - break; - } - } - tlv->len+=sizeof(isis_lsp_entry_s); - entry = (isis_lsp_entry_s *)PDU_CURSOR(&pdu); - entry->lifetime = htobe16(remaining_lifetime); - entry->lsp_id = htobe64(lsp->id); - entry->seq = htobe32(lsp->seq); - entry->checksum = *(uint16_t*)PDU_OFFSET(&lsp->pdu, ISIS_OFFSET_LSP_CHECKSUM); - PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_lsp_entry_s)); - entries++; + if(lsp->deleted) { + /* Ignore deleted LSP. */ + next = hb_itor_next(itor); + continue; } + + /* Calculate remaining lifetime. */ + timespec_sub(&ago, &now, &lsp->timestamp); + if(lsp->expired || ago.tv_sec >= lsp->lifetime) { + /* Expired! */ + remaining_lifetime = 0; + } else { + remaining_lifetime = lsp->lifetime - ago.tv_sec; + } + + if(tlv->len > UINT8_MAX-ISIS_LSP_ENTRY_LEN) { + /* Open next LSP entry TLV. */ + if(pdu.pdu_len+sizeof(isis_tlv_s)+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { + adjacency->csnp_start = lsp->id; + break; + } + tlv = (isis_tlv_s *)PDU_CURSOR(&pdu); + tlv->type = ISIS_TLV_LSP_ENTRIES; + tlv->len = 0; + PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_tlv_s)); + } else { + if(pdu.pdu_len+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { + /* All entries do not fit into single CSNP. */ + adjacency->csnp_start = lsp->id; + break; + } + } + tlv->len+=sizeof(isis_lsp_entry_s); + entry = (isis_lsp_entry_s *)PDU_CURSOR(&pdu); + entry->lsp_id = htobe64(lsp->id); + entry->seq = htobe32(lsp->seq); + if(remaining_lifetime) { + entry->lifetime = htobe16(remaining_lifetime); + entry->checksum = *(uint16_t*)PDU_OFFSET(&lsp->pdu, ISIS_OFFSET_LSP_CHECKSUM); + } else { + entry->lifetime = 0; + entry->checksum = 0; + } + PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_lsp_entry_s)); + entries++; + next = hb_itor_next(itor); } hb_itor_free(itor); @@ -127,7 +142,7 @@ isis_csnp_job(timer_s *timer) } if(!entries) { - /* Do not send empty PSNP. */ + /* Do not send empty CSNP. */ return; } diff --git a/code/bngblaster/src/isis/isis_ctrl.c b/code/bngblaster/src/isis/isis_ctrl.c index d29ee8ca..72900b0c 100644 --- a/code/bngblaster/src/isis/isis_ctrl.c +++ b/code/bngblaster/src/isis/isis_ctrl.c @@ -135,11 +135,18 @@ isis_ctrl_database_entries(hb_tree *lsdb) database = json_array(); while(next) { lsp = *hb_itor_datum(itor); + + if(lsp->deleted) { + /* Ignore deleted LSP. */ + next = hb_itor_next(itor); + continue; + } + timespec_sub(&ago, &now, &lsp->timestamp); - if(ago.tv_sec < lsp->lifetime) { - remaining_lifetime = lsp->lifetime - ago.tv_sec; - } else { + if(lsp->expired || ago.tv_sec >= lsp->lifetime) { remaining_lifetime = 0; + } else { + remaining_lifetime = lsp->lifetime - ago.tv_sec; } if(lsp->source.adjacency) { @@ -253,7 +260,7 @@ isis_ctrl_load_mrt(int fd, uint32_t session_id __attribute__((unused)), json_t * return bbl_ctrl_status(fd, "error", 404, "ISIS instance not found"); } - if(!isis_mrt_load(instance, file_path)) { + if(!isis_mrt_load(instance, file_path, false)) { return bbl_ctrl_status(fd, "error", 500, "failed to load ISIS MRT file"); } return bbl_ctrl_status(fd, "ok", 200, NULL); diff --git a/code/bngblaster/src/isis/isis_def.h b/code/bngblaster/src/isis/isis_def.h index d81c6ca6..e7235862 100644 --- a/code/bngblaster/src/isis/isis_def.h +++ b/code/bngblaster/src/isis/isis_def.h @@ -63,6 +63,7 @@ #define ISIS_DEFAULT_HELLO_INTERVAL 10 #define ISIS_DEFAULT_CSNP_INTERVAL 30 #define ISIS_DEFAULT_HOLD_TIME 30 +#define ISIS_DEFAULT_LSP_LIFETIME_MIN 330 #define ISIS_DEFAULT_LSP_LIFETIME 65535 #define ISIS_DEFAULT_LSP_RETRY_IVL 5 #define ISIS_DEFAULT_LSP_REFRESH_IVL 300 @@ -70,7 +71,6 @@ #define ISIS_DEFAULT_LSP_WINDOWS_SIZE 1 #define ISIS_DEFAULT_TEARDOWN_TIME 5 -#define ISIS_DEFAULT_PURGE_LIFETIME 0 #define ISIS_LSP_GC_INTERVAL 30 @@ -364,6 +364,7 @@ typedef struct isis_lsp_ { uint32_t refcount; bool expired; + bool deleted; uint32_t seq; /* Sequence number */ uint16_t lifetime; /* Remaining lifetime */ diff --git a/code/bngblaster/src/isis/isis_lsp.c b/code/bngblaster/src/isis/isis_lsp.c index 82369d33..779f2b85 100644 --- a/code/bngblaster/src/isis/isis_lsp.c +++ b/code/bngblaster/src/isis/isis_lsp.c @@ -207,6 +207,45 @@ isis_lsp_retry_job(timer_s *timer) } } +void +isis_lsp_purge_job(timer_s *timer) +{ + isis_lsp_s *lsp = timer->data; + lsp->expired = true; + lsp->deleted = true; +} + +void +isis_lsp_lifetime_job(timer_s *timer) +{ + isis_lsp_s *lsp = timer->data; + lsp->expired = true; + + LOG(ISIS, "ISIS %s-LSP %s (source %s seq %u) lifetime expired (%us)\n", + isis_level_string(lsp->level), + isis_lsp_id_to_str(&lsp->id), + isis_source_string(lsp->source.type), + lsp->seq, lsp->lifetime); +} + +void +isis_lsp_lifetime(isis_lsp_s *lsp) +{ + timer_del(lsp->timer_refresh); + if(lsp->lifetime > 0) { + timer_add(&g_ctx->timer_root, + &lsp->timer_lifetime, + "ISIS LIFETIME", lsp->lifetime, 0, lsp, + &isis_lsp_lifetime_job); + } else { + timer_add(&g_ctx->timer_root, + &lsp->timer_lifetime, + "ISIS PURGE", 60, 0, lsp, + &isis_lsp_purge_job); + } + timer_no_smear(lsp->timer_lifetime); +} + void isis_lsp_refresh(isis_lsp_s *lsp) { @@ -214,11 +253,6 @@ isis_lsp_refresh(isis_lsp_s *lsp) lsp->seq++; lsp->expired = false; - timer_add(&g_ctx->timer_root, - &lsp->timer_lifetime, - "ISIS LIFETIME", lsp->lifetime, 0, lsp, - &isis_lsp_lifetime_job); - timer_no_smear(lsp->timer_lifetime); *(uint32_t*)PDU_OFFSET(&lsp->pdu, ISIS_OFFSET_LSP_SEQ) = htobe32(lsp->seq); clock_gettime(CLOCK_MONOTONIC, &lsp->timestamp); @@ -236,19 +270,6 @@ isis_lsp_refresh_job(timer_s *timer) isis_lsp_refresh(lsp); } -void -isis_lsp_lifetime_job(timer_s *timer) -{ - isis_lsp_s *lsp = timer->data; - - LOG(ISIS, "ISIS %s-LSP %s (seq %u) lifetime expired\n", - isis_level_string(lsp->level), - isis_lsp_id_to_str(&lsp->id), - lsp->seq); - - lsp->expired = true; -} - void isis_lsp_sx_job(timer_s *timer) { @@ -336,7 +357,9 @@ isis_lsp_final(isis_lsp_s *lsp) isis_pdu_update_len(pdu); isis_pdu_update_auth(pdu, lsp->auth_key); isis_pdu_update_lifetime(pdu, lsp->lifetime); - isis_pdu_update_checksum(pdu); + if(lsp->lifetime > 0) { + isis_pdu_update_checksum(pdu); + } } static isis_lsp_s * @@ -348,6 +371,7 @@ isis_lsp_fragment(isis_instance_s *instance, uint8_t level, uint8_t fragment, bo isis_pdu_s *pdu = NULL; uint64_t lsp_id = htobe64(fragment); + uint16_t refresh_interval = 0; hb_tree *lsdb; void **search = NULL; @@ -384,12 +408,17 @@ isis_lsp_fragment(isis_instance_s *instance, uint8_t level, uint8_t fragment, bo clock_gettime(CLOCK_MONOTONIC, &lsp->timestamp); if(purge || instance->teardown) { - lsp->lifetime = ISIS_DEFAULT_PURGE_LIFETIME; - timer_del(lsp->timer_refresh); + lsp->lifetime = 0; + isis_lsp_lifetime(lsp); } else { lsp->lifetime = config->lsp_lifetime; + refresh_interval = lsp->lifetime - 300; + if(config->lsp_refresh_interval < refresh_interval) { + refresh_interval = config->lsp_refresh_interval; + } + timer_del(lsp->timer_lifetime); timer_add_periodic(&g_ctx->timer_root, &lsp->timer_refresh, - "ISIS LSP refresh", config->lsp_refresh_interval, 0, lsp, + "ISIS LSP REFRESH", refresh_interval, 3, lsp, &isis_lsp_refresh_job); } @@ -609,6 +638,8 @@ isis_lsp_handler_rx(bbl_network_interface_s *interface, isis_pdu_s *pdu, uint8_t /* Per default we will not overwrite * external LSP. */ if(config->external_auto_refresh) { + /* With external-auto-refresh enabled, + * the sequence number will be increased. */ lsp->seq = seq; isis_lsp_refresh(lsp); } @@ -647,12 +678,7 @@ isis_lsp_handler_rx(bbl_network_interface_s *interface, isis_pdu_s *pdu, uint8_t PDU_CURSOR_RST(pdu); memcpy(&lsp->pdu, pdu, sizeof(isis_pdu_s)); - timer_add(&g_ctx->timer_root, - &lsp->timer_lifetime, - "ISIS LIFETIME", lsp->lifetime, 0, lsp, - &isis_lsp_lifetime_job); - timer_no_smear(lsp->timer_lifetime); - + isis_lsp_lifetime(lsp); isis_lsp_flood(lsp); ACK: @@ -704,10 +730,12 @@ isis_lsp_purge_external(isis_instance_s *instance, uint8_t level) lsp = *hb_itor_datum(itor); if(lsp && lsp->source.type == ISIS_SOURCE_EXTERNAL) { lsp->seq++; - lsp->lifetime = ISIS_DEFAULT_PURGE_LIFETIME; lsp->timestamp.tv_sec = now.tv_sec; lsp->timestamp.tv_nsec = now.tv_nsec; - timer_del(lsp->timer_refresh); + + lsp->lifetime = 0; + lsp->expired = true; + isis_lsp_lifetime(lsp); /* Build PDU */ pdu = &lsp->pdu; @@ -721,7 +749,7 @@ isis_lsp_purge_external(isis_instance_s *instance, uint8_t level) lsp->auth_key = config->level2_key; } - /* PDU header */ + /* PDU header. */ isis_pdu_add_u16(pdu, 0); isis_pdu_add_u16(pdu, 0); isis_pdu_add_u64(pdu, lsp->id); @@ -729,14 +757,17 @@ isis_lsp_purge_external(isis_instance_s *instance, uint8_t level) isis_pdu_add_u16(pdu, 0); isis_pdu_add_u8(pdu, 0x03); - /* TLV section */ + /* TLV section. */ isis_pdu_add_tlv_auth(pdu, auth_type, lsp->auth_key); - /* Update checksum... */ + /* Update length and authentication. */ isis_pdu_update_len(pdu); isis_pdu_update_auth(pdu, lsp->auth_key); - isis_pdu_update_lifetime(pdu, lsp->lifetime); - isis_pdu_update_checksum(pdu); + + /* Set checksum and lifetime to zero. */ + *(uint16_t*)PDU_OFFSET(pdu, ISIS_OFFSET_LSP_LIFETIME) = 0; + *(uint16_t*)PDU_OFFSET(pdu, ISIS_OFFSET_LSP_CHECKSUM) = 0; + isis_lsp_flood(lsp); } next = hb_itor_next(itor); @@ -752,10 +783,12 @@ isis_lsp_purge_external(isis_instance_s *instance, uint8_t level) bool isis_lsp_update_external(isis_instance_s *instance, isis_pdu_s *pdu) { + uint8_t level; + isis_lsp_s *lsp = NULL; - uint64_t lsp_id; - uint32_t seq; - uint8_t level; + uint64_t lsp_id; + uint32_t seq; + uint16_t refresh_interval = 0; hb_tree *lsdb; void **search = NULL; @@ -772,7 +805,7 @@ isis_lsp_update_external(isis_instance_s *instance, isis_pdu_s *pdu) lsp_id = be64toh(*(uint64_t*)PDU_OFFSET(pdu, ISIS_OFFSET_LSP_ID)); seq = be32toh(*(uint32_t*)PDU_OFFSET(pdu, ISIS_OFFSET_LSP_SEQ)); - LOG(DEBUG, "ISIS UPDATE %s-LSP %s (seq %u) from command\n", + LOG(ISIS, "ISIS UPDATE %s-LSP %s (seq %u) from command\n", isis_level_string(level), isis_lsp_id_to_str(&lsp_id), seq); @@ -807,11 +840,24 @@ isis_lsp_update_external(isis_instance_s *instance, isis_pdu_s *pdu) PDU_CURSOR_RST(pdu); memcpy(&lsp->pdu, pdu, sizeof(isis_pdu_s)); - timer_add(&g_ctx->timer_root, - &lsp->timer_lifetime, - "ISIS LIFETIME", lsp->lifetime, 0, lsp, - &isis_lsp_lifetime_job); - timer_no_smear(lsp->timer_lifetime); + if(lsp->lifetime > 0 && instance->config->external_auto_refresh) { + if(level == ISIS_LEVEL_1) { + lsp->auth_key = instance->config->level1_key; + } else { + lsp->auth_key = instance->config->level2_key; + } + if(lsp->lifetime < ISIS_DEFAULT_LSP_LIFETIME_MIN) { + /* Increase ISIS lifetime. */ + lsp->lifetime = ISIS_DEFAULT_LSP_LIFETIME_MIN; + isis_lsp_refresh(lsp); + } + refresh_interval = lsp->lifetime - 300; + timer_add_periodic(&g_ctx->timer_root, &lsp->timer_refresh, + "ISIS LSP REFRESH", refresh_interval, 3, lsp, + &isis_lsp_refresh_job); + } else { + isis_lsp_lifetime(lsp); + } isis_lsp_flood(lsp); return true; diff --git a/code/bngblaster/src/isis/isis_lsp.h b/code/bngblaster/src/isis/isis_lsp.h index 2bcea116..cc156f9a 100644 --- a/code/bngblaster/src/isis/isis_lsp.h +++ b/code/bngblaster/src/isis/isis_lsp.h @@ -24,11 +24,14 @@ isis_lsp_gc_job(timer_s *timer); void isis_lsp_retry_job(timer_s *timer); +void +isis_lsp_refresh(isis_lsp_s *lsp); + void isis_lsp_refresh_job(timer_s *timer); void -isis_lsp_lifetime_job(timer_s *timer); +isis_lsp_lifetime(isis_lsp_s *lsp); void isis_lsp_sx_job(timer_s *timer); diff --git a/code/bngblaster/src/isis/isis_mrt.c b/code/bngblaster/src/isis/isis_mrt.c index 0b6ce503..99071412 100644 --- a/code/bngblaster/src/isis/isis_mrt.c +++ b/code/bngblaster/src/isis/isis_mrt.c @@ -9,7 +9,7 @@ #include "isis.h" bool -isis_mrt_load(isis_instance_s *instance, char *file_path) +isis_mrt_load(isis_instance_s *instance, char *file_path, bool startup) { FILE *mrt_file; @@ -21,6 +21,7 @@ isis_mrt_load(isis_instance_s *instance, char *file_path) isis_lsp_s *lsp = NULL; uint64_t lsp_id; uint32_t seq; + uint16_t refresh_interval = 0; hb_tree *lsdb; void **search = NULL; @@ -117,26 +118,31 @@ isis_mrt_load(isis_instance_s *instance, char *file_path) PDU_CURSOR_RST(&pdu); memcpy(&lsp->pdu, &pdu, sizeof(isis_pdu_s)); - if(instance->config->external_auto_refresh) { + if(lsp->lifetime > 0 && instance->config->external_auto_refresh) { if(level == ISIS_LEVEL_1) { lsp->auth_key = instance->config->level1_key; } else { lsp->auth_key = instance->config->level2_key; } - if(lsp->lifetime < 330) { - lsp->lifetime = 300; + if(lsp->lifetime < ISIS_DEFAULT_LSP_LIFETIME_MIN) { + /* Increase ISIS lifetime. */ + lsp->lifetime = ISIS_DEFAULT_LSP_LIFETIME_MIN; + isis_lsp_refresh(lsp); } + refresh_interval = lsp->lifetime - 300; timer_add_periodic(&g_ctx->timer_root, &lsp->timer_refresh, - "ISIS LSP refresh", lsp->lifetime - 300, 0, lsp, + "ISIS LSP REFRESH", refresh_interval, 3, lsp, &isis_lsp_refresh_job); + } else { + isis_lsp_lifetime(lsp); } - - timer_add(&g_ctx->timer_root, - &lsp->timer_lifetime, - "ISIS LIFETIME", lsp->lifetime, 0, lsp, - &isis_lsp_lifetime_job); - timer_no_smear(lsp->timer_lifetime); } + + if(startup && refresh_interval) { + /* Adding 3 nanoseconds to enforce a dedicated timer bucket. */ + timer_smear_bucket(&g_ctx->timer_root, refresh_interval, 3); + } + fclose(mrt_file); return true; } \ No newline at end of file diff --git a/code/bngblaster/src/isis/isis_mrt.h b/code/bngblaster/src/isis/isis_mrt.h index f4a45999..c6e3f1fe 100644 --- a/code/bngblaster/src/isis/isis_mrt.h +++ b/code/bngblaster/src/isis/isis_mrt.h @@ -19,6 +19,6 @@ typedef struct isis_mrt_hdr_ { } __attribute__ ((__packed__)) isis_mrt_hdr_t; bool -isis_mrt_load(isis_instance_s *instance, char *file_path); +isis_mrt_load(isis_instance_s *instance, char *file_path, bool startup); #endif \ No newline at end of file diff --git a/code/bngblaster/src/isis/isis_p2p_hello.c b/code/bngblaster/src/isis/isis_p2p_hello.c index c02f666c..2cc11d7a 100644 --- a/code/bngblaster/src/isis/isis_p2p_hello.c +++ b/code/bngblaster/src/isis/isis_p2p_hello.c @@ -207,13 +207,16 @@ isis_p2p_hello_handler_rx(bbl_network_interface_s *interface, isis_pdu_s *pdu) } } - if(adjacency->state != new_state && new_state == ISIS_P2P_ADJACENCY_STATE_UP) { - for(int i=0; iisis_adjacency[i]) { - isis_adjacency_up(interface->isis_adjacency[i]); - isis_lsp_self_update(adjacency->instance, i+1); + if(adjacency->state != new_state) { + interface->send_requests |= BBL_IF_SEND_ISIS_P2P_HELLO; + if(new_state == ISIS_P2P_ADJACENCY_STATE_UP) { + for(int i=0; iisis_adjacency[i]) { + isis_adjacency_up(interface->isis_adjacency[i]); + isis_lsp_self_update(adjacency->instance, i+1); + } } } + adjacency->state = new_state; } - adjacency->state = new_state; } \ No newline at end of file diff --git a/code/bngblaster/src/isis/isis_pdu.c b/code/bngblaster/src/isis/isis_pdu.c index 2e5a7832..38cbf6f6 100644 --- a/code/bngblaster/src/isis/isis_pdu.c +++ b/code/bngblaster/src/isis/isis_pdu.c @@ -231,17 +231,19 @@ isis_pdu_update_auth(isis_pdu_s *pdu, char *key) bool isis_pdu_validate_checksum(isis_pdu_s *pdu) { - uint16_t checksum; - uint16_t checksum_orig; + uint16_t checksum = 0; + uint16_t checksum_orig = 0; - switch (pdu->pdu_type) { + switch(pdu->pdu_type) { case ISIS_PDU_L1_LSP: case ISIS_PDU_L2_LSP: checksum_orig = *(uint16_t*)PDU_OFFSET(pdu, ISIS_OFFSET_LSP_CHECKSUM); - checksum = isis_checksum_fletcher16( - pdu->pdu+ISIS_OFFSET_LSP_ID, - pdu->pdu_len-ISIS_OFFSET_LSP_ID, - ISIS_OFFSET_LSP_CHECKSUM-ISIS_OFFSET_LSP_ID); + if(checksum_orig > 0) { + checksum = isis_checksum_fletcher16( + pdu->pdu+ISIS_OFFSET_LSP_ID, + pdu->pdu_len-ISIS_OFFSET_LSP_ID, + ISIS_OFFSET_LSP_CHECKSUM-ISIS_OFFSET_LSP_ID); + } break; default: return true; diff --git a/code/bngblaster/src/isis/isis_psnp.c b/code/bngblaster/src/isis/isis_psnp.c index c76b733b..3f50be52 100644 --- a/code/bngblaster/src/isis/isis_psnp.c +++ b/code/bngblaster/src/isis/isis_psnp.c @@ -70,39 +70,49 @@ isis_psnp_job (timer_s *timer) lsp = *search; hb_tree_remove(adjacency->psnp_tree, &lsp->id); - /* Calculate remaining lifetime and ignore if already expired. */ - timespec_sub(&ago, &now, &lsp->timestamp); - if(ago.tv_sec < lsp->lifetime) { - remaining_lifetime = lsp->lifetime - ago.tv_sec; - - if(tlv->len > UINT8_MAX-ISIS_LSP_ENTRY_LEN) { - /* Open next LSP entry TLV */ - if(pdu.pdu_len+sizeof(isis_tlv_s)+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { - adjacency->csnp_start = lsp->id; - break; - } - tlv = (isis_tlv_s *)PDU_CURSOR(&pdu); - tlv->type = ISIS_TLV_LSP_ENTRIES; - tlv->len = 0; - PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_tlv_s)); - } else { - if(pdu.pdu_len+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { - /* All entries do not fit into single PSNP. */ - adjacency->timer_psnp_started = true; - timer_add(&g_ctx->timer_root, &adjacency->timer_psnp_next, - "ISIS PSNP", 0, 10*MSEC, adjacency, &isis_psnp_job); - break; - } - } - tlv->len+=sizeof(isis_lsp_entry_s); - entry = (isis_lsp_entry_s *)PDU_CURSOR(&pdu); - entry->lifetime = htobe16(remaining_lifetime); - entry->lsp_id = htobe64(lsp->id); - entry->seq = htobe32(lsp->seq); - entry->checksum = *(uint16_t*)PDU_OFFSET(&lsp->pdu, ISIS_OFFSET_LSP_CHECKSUM); - PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_lsp_entry_s)); - entries++; + if(lsp->deleted) { + /* Ignore deleted LSP. */ + search = hb_tree_search_gt(adjacency->psnp_tree, &lsp_id_zero); + continue; } + + /* Calculate remaining lifetime. */ + timespec_sub(&ago, &now, &lsp->timestamp); + if(lsp->expired || ago.tv_sec >= lsp->lifetime) { + /* Expired! */ + remaining_lifetime = 0; + } else { + remaining_lifetime = lsp->lifetime - ago.tv_sec; + } + + if(tlv->len > UINT8_MAX-ISIS_LSP_ENTRY_LEN) { + /* Open next LSP entry TLV. */ + if(pdu.pdu_len+sizeof(isis_tlv_s)+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { + adjacency->csnp_start = lsp->id; + break; + } + tlv = (isis_tlv_s *)PDU_CURSOR(&pdu); + tlv->type = ISIS_TLV_LSP_ENTRIES; + tlv->len = 0; + PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_tlv_s)); + } else { + if(pdu.pdu_len+ISIS_LSP_ENTRY_LEN > ISIS_MAX_PDU_LEN) { + /* All entries do not fit into single PSNP. */ + adjacency->timer_psnp_started = true; + timer_add(&g_ctx->timer_root, &adjacency->timer_psnp_next, + "ISIS PSNP", 0, 10*MSEC, adjacency, &isis_psnp_job); + break; + } + } + tlv->len+=sizeof(isis_lsp_entry_s); + entry = (isis_lsp_entry_s *)PDU_CURSOR(&pdu); + entry->lifetime = htobe16(remaining_lifetime); + entry->lsp_id = htobe64(lsp->id); + entry->seq = htobe32(lsp->seq); + entry->checksum = *(uint16_t*)PDU_OFFSET(&lsp->pdu, ISIS_OFFSET_LSP_CHECKSUM); + PDU_BUMP_WRITE_BUFFER(&pdu, sizeof(isis_lsp_entry_s)); + entries++; + search = hb_tree_search_gt(adjacency->psnp_tree, &lsp_id_zero); } isis_pdu_update_len(&pdu);