📄 ospf_transmit_update.c
字号:
} } else /* if sending to other router than DR or BDR, timestamp of last multicast transmission to all SPF routers would do */ { if (sptr_retx_timestamp_node->neighbor_id == OSPF_ADDR_ALLSPF) { /* found timestamp of last transmission of this LSA as multicast (all SPF routers), and this is unicast to a router on this interface. Accept timestamp of last multicast transmission. Record timestamp */ *last_tx_time = sptr_retx_timestamp_node->timestamp; break; } } } } /* for every timestamp in the list */ return sptr_retx_timestamp_node; } /* ospf_find_timestamp_for_lsdb_entry *//**********************************************************************************************************************************//* Function ospf_update_lsa_transmit_timestamp updates the LSA transmission timestamp Pseudocode: if transmit timestamp node of database node is given, just update timestamp else create transmit timestamp node update its timestamp enqueue in database node's list of transmit timestamps*/static void ospf_update_lsa_transmit_timestamp ( OSPF_LS_DATABASE_ENTRY *sptr_database_entry, OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST *sptr_timestamp_node, ULONG current_time, ULONG destination_router, OSPF_NEIGHBOR *sptr_neighbor, ULONG if_index ) { OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST *sptr_new_timestamp = NULL; ULONG id = 0L; /* param validation */ if (sptr_database_entry == NULL) { return; } if (sptr_neighbor == NULL) { id = destination_router; } else { id = sptr_neighbor->id; } /* if timestamp of last retransmission exists, update it with current time */ if (sptr_timestamp_node != NULL) { /* just update timestamp in existing node, was already transmitted before */ OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "\n LSA timestamp set from %ld to %ld, LSA type %d, id %08lx, seq. %08lx, to %p, dest %08lx, \n\t timestamp at %p, if %08lx, dst %08lx, ", sptr_timestamp_node->timestamp, current_time, sptr_database_entry->advertisement.sptr_router->ls_header.type, sptr_database_entry->advertisement.sptr_router->ls_header.id, sptr_database_entry->advertisement.sptr_router->ls_header.sequence_number, sptr_neighbor, destination_router, sptr_timestamp_node, sptr_timestamp_node->if_index, sptr_timestamp_node->neighbor_id); sptr_timestamp_node->timestamp = current_time; return; } /* if timestamp of last retransmission does not exist, create it */ sptr_new_timestamp = (OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST *) table_malloc (1, sizeof (OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST)); if (sptr_new_timestamp != NULL) { /* initialize timestamp node */ sptr_new_timestamp->neighbor_id = id; sptr_new_timestamp->if_index = if_index; sptr_new_timestamp->timestamp = current_time; OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "\n LSA timestamp created, LSA type %d, id %08lx, seq. %08lx, to %p, dest %08lx, \n\t timestamp at %p, if %08lx, dst %08lx, timestamp %08lx ", sptr_database_entry->advertisement.sptr_router->ls_header.type, sptr_database_entry->advertisement.sptr_router->ls_header.id, sptr_database_entry->advertisement.sptr_router->ls_header.sequence_number, sptr_neighbor, destination_router, sptr_new_timestamp, sptr_new_timestamp->if_index, sptr_new_timestamp->neighbor_id, sptr_new_timestamp->timestamp); /* queue time stamp node in list of timestamps of its lsdb node */ if (sptr_database_entry->sptr_lsa_retransmit_timestamps_per_neighbor == NULL) { /* first timestamp node */ sptr_database_entry->sptr_lsa_retransmit_timestamps_per_neighbor = sptr_new_timestamp; } else { /* another timestamp for this LSA (LSA was recently transmitted to other destinations / interfaces) */ ospf_add_node_to_end_of_list( (OSPF_GENERIC_NODE *)sptr_new_timestamp, (OSPF_GENERIC_NODE *)sptr_database_entry->sptr_lsa_retransmit_timestamps_per_neighbor); } } } /* ospf_update_lsa_transmit_timestamp *//**********************************************************************************************************************************//* Function ospf_check_if_advertisement_should_be_sent Validates if the LSA should be transmitted on the given interface to the given destination router or not according to RxmtInterval (enabled or not and configured with value per interface) Pseudocode: If flooding not enabled for this LSA, return FALSE (prevent transmitting LSA) Locate LSDB entry for this LSA If LSA not found in LSDB return FALSE (should not flood an LSA that is not in LSDB) Locate timestamp of last LSA transmission of this LSA to this neighbor If timestamp not found (first transmission of this LSA to this neighbor) create timestamp queue timestamp to LSDB node of this LSA return TRUE; (accept transmitting LSA) Compute elapsed time if (elapsed time < sptr_interface->retransmit_interval) return FALSE (prevent transmitting LSA) else record new timestamp of transmission to this neighbor return TRUE (accept transmitting LSA)*/static enum BOOLEAN ospf_check_if_advertisement_should_be_sent ( OSPF_LS_DATABASE_NODE *sptr_database_node, OSPF_INTERFACE *sptr_interface, ULONG destination_router, enum BOOLEAN retransmit_flag, OSPF_NEIGHBOR *sptr_neighbor ) { ULONG current_time = 0, elapsed_time = 0, last_tx_time = 0L; ULONG destination_router_id = 0L; OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST *sptr_lsa_timestamp = NULL; OSPF_LS_DATABASE_ENTRY *sptr_lsdb_entry = NULL; ULONG id = 0; ULONG hash_id = 0; ULONG advertising_router = 0; BYTE_ENUM (OSPF_LS_TYPE) type = 0; OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "OSPF: Entering ospf_check_if_advertisement_should_be_sent\r\n"); if (sptr_database_node == NULL) { return FALSE; } /* Pseudocode: If flooding not enabled for this LSA, return FALSE (prevent transmitting LSA) */ if ((retransmit_flag == FALSE) && (sptr_database_node->flood == FALSE)) { /* should not flood this LSA */ return FALSE; } if (sptr_database_node->sptr_ls_database_entry == NULL) { /* param error, recover */ return FALSE; } /* get current time */ current_time = ospf_get_system_elapsed_time_second (); if ((destination_router == 0L) || (destination_router == OSPF_ADDR_ALLDR)) { /* neighbor to send this LSA to is the DR on this interface */ destination_router_id = sptr_interface->designated_router.id; } else { /* unicast to a neighbor or multicast to all SPF routers */ destination_router_id = destination_router; }/* just for debug start */ OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "\nTransmit LSA of type %d, id %lx, seq.%lx, age %d, ", sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.type, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.id, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.sequence_number, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.age); if (destination_router == OSPF_ADDR_ALLSPF) OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "multicast to %lx ", destination_router_id); else if (destination_router == OSPF_ADDR_ALLDR) OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "unicast to DR %lx sent to %lx ", destination_router, destination_router_id); else OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "unicast to %lx ", destination_router_id); if (sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.age > OSPF_MAXIMUM_AGE) { OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "MAXAGE "); }/* just for debug end */ /* Pseudocode: locate the LSDB node pointing to this LSA, locate its timestamp */ id = ntohl(sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.id); hash_id = id; hash_id = hash_id & OSPF_HASH_MASK; advertising_router = ntohl(sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.advertising_router); type = sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.type; if (sptr_interface != NULL) { sptr_lsdb_entry = ospf_find_LSA (sptr_interface->sptr_area, id, advertising_router, type); if ((sptr_lsdb_entry != NULL) && (sptr_lsdb_entry != sptr_database_node->sptr_ls_database_entry)) { /* Found LSDB entry pointing to same LSA, search timestamp of LSDB entry */ sptr_lsa_timestamp = ospf_find_timestamp_for_lsdb_entry( sptr_lsdb_entry, destination_router_id, sptr_interface, &last_tx_time, sptr_neighbor); } } if (sptr_lsdb_entry == NULL) { OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "\n LSA not found in LSDB of interface %p, area %ld: type %d, id %08lx, advrtr %08lx, seq. %lx ", sptr_interface, sptr_interface->sptr_area->area_id, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.type, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.id, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.advertising_router, sptr_database_node->sptr_ls_database_entry->advertisement.sptr_router->ls_header.sequence_number); /* should not flood an LSA that is not in LSDB (TBD behavior for MAXAGE LSA) */ return FALSE; } /* If this is the first transmission of this LSA (no timestamp of a previous transmission), then create a timestamp for it and accept transmission */ if (sptr_lsa_timestamp == NULL) { ospf_update_lsa_transmit_timestamp(sptr_lsdb_entry, NULL, current_time, destination_router_id, sptr_neighbor, sptr_interface->ifnet_index); OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF,"\n LSA transmit accepted"); return TRUE; } /* This is not first transmission of the LSA, compute elapsed time since last transmission
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -