📄 ospf_transmit_update.c
字号:
/* ospf_transmit_update.c - OSPF transmit update *//* Copyright 2000-2003 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02a,14aug03,kkz Fixed compiler warning (removed unused variable)01z,26jun03,agi Re-added early LSA retransmission fix made compatible with new routing table01y,23jun03,agi Backed out SPR#88619 early LSA retransmission changes, not compatible with new routing table01x,26may03,agi Changed rwos_get_system_elapsed_time_second() to ospf_get_system_elapsed_time_second()01w,22may03,dsk SPR 88619 Fix early LSA retransmission, more parts of same fix01v,22may03,dsk SPR 88619 Fix early LSA retransmission01u,17feb03,mwv SPR 85906 - use ip header size in calculation for packet fragmentation01t,29nov02,htm Added fix for SPRs 81633, 81674 (ANVL 12.4, 12.5, 26.7).01s,11oct01,jkw Set pointer to NULL after table_free.01r,22aug01,jkw Added opaque lsa updates.01q,11may01,aos Added null pointer checks and fixed to iteration of the database node.01p,26sep00,reshma Added WindRiver CopyRight01o,25sep00,reshma RFC-1587 implementation for OSPF NSSA Option, also tested against ANVL.01n,07jul00,reshma Unix compatibility related changes.01m,04apr00,reshma Added some MIB support (Read only).Passed all important ANVL OSPF tests.01l,23dec99,reshma Compatibility with VxWorks-IP and VxWorks RTM-interface01k,28dec98,jack Compiled and added some comments01j,11nov98,jack Config changes, linted and big endian changes01i,30oct98,jack Incorporate changes for compilation on Vxworks01h,23aug98,jack ANVL tested OSPF with PATRICIA tree route table and no recursion01g,10aug98,jack PATRICIA Route Table Based OSPF Code Base01f,04jun98,jack Integration with RTM and BGP01e,24apr98,jack RTM changes01d,10jul97,cindy Pre-release v1.52b01c,02oct97,cindy Release Version 1.5201b,22oct96,cindy Release Version 1.5001a,05jun96,cindy First Beta Release*//*DESCRIPTIONospf_transmit_update.c is used for transmitting link state update packets. Thisfile finds all the appropriate link state advertisements in the link statedatabase and adds them to the link state update.This file is used whenever a new OSPF link state update packets need to betransmitted.*/#include "ospf.h"#if defined (__OSPF_VIRTUAL_STACK__)#include "ospf_vs_lib.h"#endif /* __OSPF_VIRTUAL_STACK__ *//*******************************************************************************************************************************//* SPR 88619 start */static void ospf_build_and_send_ls_update_packets (OSPF_LS_DATABASE_NODE *sptr_ls_database_list,ULONG destination_router, OSPF_INTERFACE *sptr_interface,enum BOOLEAN retransmit_flag, enum BOOLEAN advertisement_installed, OSPF_NEIGHBOR *sptr_neighbor);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);/* SPR 88619 end */static enum BOOLEAN ospf_check_if_packet_is_full (OSPF_LS_DATABASE_NODE *sptr_database_node,OSPF_INTERFACE *sptr_interface, ULONG packet_length);static UNION_OSPF_ADVERTISEMENT_HEADER *ospf_add_advertisement_to_ls_update_packet ( OSPF_LS_DATABASE_NODE *sptr_database_node, UNION_OSPF_ADVERTISEMENT_HEADER *sptr_advertisement_header, OSPF_HEADER *sptr_packet, ULONG *sptr_packet_length, enum BOOLEAN advertisement_installed);/* SPR 88619 start */static OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST * ospf_find_timestamp_for_lsdb_entry(OSPF_LS_DATABASE_ENTRY *sptr_ls_database_entry, ULONG destination_router_id, OSPF_INTERFACE *sptr_interface, ULONG *last_tx_time, OSPF_NEIGHBOR *sptr_neighbor);static void ospf_update_lsa_transmit_timestamp(OSPF_LS_DATABASE_ENTRY *sptr_database_entry, OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST *sptr_retx_timestamp_list, ULONG timestamp, ULONG destination_router, OSPF_NEIGHBOR *sptr_neighbor, ULONG if_index);/* SPR 88619 end *//*******************************************************************************//* section 13.3 of OSPF specification (page 138) */void ospf_send_ls_update (OSPF_LS_DATABASE_NODE *sptr_database_list,OSPF_NEIGHBOR *sptr_neighbor,OSPF_INTERFACE *sptr_interface, enum BOOLEAN retransmit_flag, enum BOOLEAN advertisement_installed){ char print_buffer[PRINT_BUFFER_SIZE]; ULONG destination_router; OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "OSPF: Entering ospf_send_ls_update\r\n"); if (sptr_interface->state == OSPF_INTERFACE_IS_DOWN) { OSPF_CONVERT_IP_ADDRESS_TO_DOT_FORMAT_FOR_DEBUG (print_buffer, sptr_interface->address); OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "OSPF: Interface %s is down. Cannot send LS Update packet.\r\n", print_buffer); return; } if ( (sptr_neighbor != NULL) && (retransmit_flag == TRUE) ) /* retransmissions are sent unicast */ { destination_router = sptr_neighbor->address; } else { destination_router = ospf_determine_packet_destination (sptr_interface, sptr_neighbor); } ospf_build_and_send_ls_update_packets (sptr_database_list, destination_router, sptr_interface, retransmit_flag, advertisement_installed, sptr_neighbor); return;}/**********************************************************************************************************************************/static void ospf_build_and_send_ls_update_packets (OSPF_LS_DATABASE_NODE *sptr_ls_database_list,ULONG destination_router, OSPF_INTERFACE *sptr_interface,enum BOOLEAN retransmit_flag, enum BOOLEAN advertisement_installed, OSPF_NEIGHBOR *sptr_neighbor){ OSPF_HEADER *sptr_packet; OSPF_LS_DATABASE_NODE *sptr_database_node; UNION_OSPF_ADVERTISEMENT_HEADER *sptr_advertisement_header; enum BOOLEAN include_node_in_packet; enum BOOLEAN packet_is_full; ULONG packet_length; OSPF_PRINTF_DEBUG (OSPF_DEBUG_PRINTF, "OSPF: Entering ospf_build_and_send_ls_update_packets\r\n"); sptr_packet = ospf_new_link_state_update (&sptr_advertisement_header, sptr_interface); if (sptr_packet == NULL) { OSPF_PRINTF_DEBUG (OSPF_ALARM_PRINTF, "OSPF: ospf_build_and_send_ls_update_packets::ospf_new_link_state_update() failed!\r\n"); return; } packet_length = OSPF_PACKET_SIZE + OSPF_LS_UPDATE_HEADER_SIZE; for (sptr_database_node = sptr_ls_database_list; sptr_database_node != NULL; sptr_database_node = sptr_database_node->sptr_forward_link) { /* SPR 88619 start */ include_node_in_packet = ospf_check_if_advertisement_should_be_sent (sptr_database_node, sptr_interface, destination_router, retransmit_flag, sptr_neighbor); /* SPR 88619 end */ if (include_node_in_packet == FALSE) { continue; /* skip to next node */ } packet_is_full = ospf_check_if_packet_is_full (sptr_database_node, sptr_interface, packet_length); if (packet_is_full == TRUE) /* the packet can't hold any more advertisements, so send it out and start building a new packet */ { if (sptr_packet->rest_of_packet.ls_update.number_of_advertisements == 0x00000000L) { /* the first advertisement we want to put in the packet is huge and won't fit. So skip it and go on the the next one.*/ memset (sptr_packet, 0x0, packet_length); packet_length = OSPF_PACKET_SIZE + OSPF_LS_UPDATE_HEADER_SIZE; continue; /* gon on to the next one */ } else { sptr_packet->rest_of_packet.ls_update.number_of_advertisements = host_to_net_long ( sptr_packet->rest_of_packet.ls_update.number_of_advertisements); ospf_tx_packet (sptr_packet, sptr_interface, OSPF_LINK_STATE_UPDATE_PACKET, packet_length, destination_router, FALSE); if (retransmit_flag == TRUE) /* section 13.6 (page 144) - "When advertisements are to be retransmitted, only the number */ { /* fitting in a single Link State Update packet should be sent." */ ospf_free_an_ospf_send_packet (sptr_packet); return; } memset (sptr_packet, 0x0, packet_length); sptr_advertisement_header = (UNION_OSPF_ADVERTISEMENT_HEADER *) &(sptr_packet->rest_of_packet.ls_update.advertisement_header); packet_length = OSPF_PACKET_SIZE + OSPF_LS_UPDATE_HEADER_SIZE; } } sptr_advertisement_header = ospf_add_advertisement_to_ls_update_packet (sptr_database_node, sptr_advertisement_header, sptr_packet, &packet_length, advertisement_installed); sptr_database_node->periodic_retransmit_time_counter = 0x00000000L; /* reset timer */ } if (sptr_packet->rest_of_packet.ls_update.number_of_advertisements > 0x00000000L) { /* the packet is not as full as it could be, but we ran out of advertisements to fill it up, so send it out anyway */ sptr_packet->rest_of_packet.ls_update.number_of_advertisements = host_to_net_long ( sptr_packet->rest_of_packet.ls_update.number_of_advertisements); ospf_tx_packet (sptr_packet, sptr_interface, OSPF_LINK_STATE_UPDATE_PACKET, packet_length, destination_router, TRUE ); } else { ospf_free_an_ospf_send_packet (sptr_packet); } return;}/* SPR 88619 start *//**********************************************************************************************************************************//* Function ospf_find_timestamp_for_lsdb_entry finds the timestamp of last LSA transmission to a given destination for an LSDB entry 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 OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST * ospf_find_timestamp_for_lsdb_entry ( OSPF_LS_DATABASE_ENTRY *sptr_ls_database_entry, ULONG destination_router_id, OSPF_INTERFACE *sptr_interface, ULONG *last_tx_time, OSPF_NEIGHBOR *sptr_neighbor ) { OSPF_LSA_TIMESTAMP_PER_INTERFACE_LIST *sptr_retx_timestamp_node = NULL; *last_tx_time = 0; for (sptr_retx_timestamp_node = sptr_ls_database_entry->sptr_lsa_retransmit_timestamps_per_neighbor; sptr_retx_timestamp_node != NULL; sptr_retx_timestamp_node = sptr_retx_timestamp_node->sptr_forward_link) { /* unicast case */ if ((sptr_retx_timestamp_node->if_index == sptr_interface->ifnet_index) && (sptr_retx_timestamp_node->neighbor_id == destination_router_id)) { /* found timestamp of last transmission of this LSA to this neighbor. Record timestamp */ *last_tx_time = sptr_retx_timestamp_node->timestamp; break; } /* multicast case */ if ((sptr_neighbor != NULL) && (sptr_neighbor->state == OSPF_NEIGHBOR_FULL)) { if (/* if sending to DR or BDR, timestamp of last multicast transmission to either all SPF routers or to all designated routers (DR and BDR) would do */ (destination_router_id == sptr_interface->designated_router.id) || (destination_router_id == sptr_interface->backup_designated_router.id)) { if ((sptr_retx_timestamp_node->neighbor_id == OSPF_ADDR_ALLSPF) || (sptr_retx_timestamp_node->neighbor_id == OSPF_ADDR_ALLDR)) { /* found timestamp of last transmission of this LSA as multicast (all SPF routers, or all designated routers and this is unicast transmission to DR or BDR. Accept timestamp of last multicast transmission. Record timestamp */ *last_tx_time = sptr_retx_timestamp_node->timestamp; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -