mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
ISIS enhancements
This commit is contained in:
committed by
Christian Giese
parent
86c1cae2b3
commit
ce7f04706e
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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; i<ISIS_LEVELS; i++) {
|
||||
if(interface->isis_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; i<ISIS_LEVELS; i++) {
|
||||
if(interface->isis_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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user