毅哥铡特:修改后的Bellmanford最短路径路由动画演示

修改背景:毅哥铡特自带的《routing_bellmanford.cpp》,按路由跳数进行更新路由表,但是,卫星互联网的卫星路由器节点,可能需要考虑传播传输时延,对应的,可能需要按照两个网络节点的距离来更新路由表。

修改后的《routing_bellmanford.cpp》:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include "api.h"
#include "network_ip.h"
#include "app_util.h"
#include "routing_bellmanford.h"#include "partition.h"  //JSLS添加:[PARTITION_ReturnNodePointer],用于根据[节点ID]获取[节点指针]
#include "coordinates.h" //JSLS添加:用于计算 两个节点之间的物理距离,用于 路由距离的度量//#define nDEBUG 
//#define nDEBUG_TABLE#define DEBUG  1         //JSLS备注: 去掉前面的 n 字符后,设置为 1,方便 Debug 调试。
#define DEBUG_TABLE  1  //JSLS备注: 去掉前面的 n 字符后,设置为 1,以便调试时查看 路由表//-----------------------------------------------------------------------------
// DEFINES
//-----------------------------------------------------------------------------//
// The route table starts with memory allocated for this many routes.
//#define NUM_INITIAL_ROUTES_ALLOCATED   4//
// Bellman-Ford value for infinite distance.
//// #define BELLMANFORD_INFINITY   16   // 原始代码
#define BELLMANFORD_INFINITY   32767   // JSLS修改:15位bit 全为1 ,数值为 32767(单位:㎞千米)。用于 STK Exata 联合仿真时表示 卫星路由器节点间 距离//
// Each node broadcasts its entire route table (a periodic update)
// at intervals of:
// PERIODIC_UPDATE_INTERVAL + [0, PERIODIC_UPDATE_JITTER) seconds.
//#define PERIODIC_UPDATE_INTERVAL   (10 * SECOND)
#define PERIODIC_UPDATE_JITTER     (150 * MILLI_SECOND)//
// Each node checks for timed-out routes at intervals of:
// CHECK_TIMEOUT_INTERVAL + [0, CHECK_TIMEOUT_JITTER) seconds.
//#define CHECK_TIMEOUT_INTERVAL     (60 * SECOND)
#define CHECK_TIMEOUT_JITTER       (100 * MILLI_SECOND)//
// Triggered updates are scheduled after a delay of:
// TRIGGERED_UPDATE_DELAY + [0, TRIGGERED_UPDATE_JITTER) seconds.
//#define TRIGGERED_UPDATE_DELAY     (0 * SECOND)
#define TRIGGERED_UPDATE_JITTER    (150 * MILLI_SECOND)//
// If a route is >= TIMEOUT_DELAY in age, it is considered timed out.
//#define TIMEOUT_DELAY   (60 * SECOND)//
// Each route-advertisement packet is limited to this many routes.
// If more routes need to be sent, multiple packets are sent.
//#define MAX_ROUTES_PER_ROUTE_ADVERTISEMENT_PACKET   32//-----------------------------------------------------------------------------
// STRUCTS, ENUMS, AND TYPEDEFS
//-----------------------------------------------------------------------------//
// Route in a route table.
//typedef struct
{NodeAddress destAddress;NodeAddress subnetMask;NodeAddress nextHop;int         incomingInterface;int         outgoingInterface;short       distance;BOOL        localRoute;clocktype   refreshTime;BOOL        changed;// This flag is set if its a re-distributed routeBOOL        isPermanent;
} Route;//
// Bellman-Ford state.
//typedef struct
{// General state information.clocktype nextPeriodicUpdateTime;BOOL triggeredUpdateScheduled;// Route table.Route *routeTable;int numRoutesAllocated;int numRoutes;// Statistics.int numPeriodicUpdates;int numTriggeredUpdates;int numRouteTimeouts;int numRouteAdvertisementsReceived;RandomSeed periodicJitterSeed;RandomSeed checkTimeoutSeed;RandomSeed triggeredUpdateSeed;BOOL statsPrinted;
} Bellmanford;//
// Header fields for route-advertisement packet.
//typedef struct
{NodeAddress sourceAddress;  // source IP addressNodeAddress destAddress;    // destination IP addressint         payloadSize;    // size of payload in bytes
} RoutingBellmanfordHeader;//
// Route in a route-advertisement packet.
//typedef struct
{NodeAddress destAddress;NodeAddress subnetMask;NodeAddress nextHop;int         distance;
} AdvertisedRoute;//
// enum for argument passed to SendRouteAdvertisement() to determine
// whether to execute in periodic or triggered update mode.
//typedef enum
{ROUTING_BELLMANFORD_PERIODIC_UPDATE = 0,ROUTING_BELLMANFORD_TRIGGERED_UPDATE
} RouteAdvertisementType;//
// enum for argument passed to PrintRouteTable() to vary what kind of
// output to print to screen.
//typedef enum
{ROUTING_BELLMANFORD_PRE_UPDATE = 0,ROUTING_BELLMANFORD_POST_UPDATE
} PrintRouteTableType;//-----------------------------------------------------------------------------
// PROTOTYPES FOR FUNCTIONS WITH INTERNAL LINKAGE
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// Handler functions for Bellman-Ford internal messages
//-----------------------------------------------------------------------------static void //inline//
HandlePeriodicUpdateAlarm(Node *node);static void //inline//
HandleCheckRouteTimeoutAlarm(Node *node);static void //inline//
HandleTriggeredUpdateAlarm(Node *node);static void //inline//
SendRouteAdvertisement(Node *node, RouteAdvertisementType type);static void //inline//
ScheduleTriggeredUpdate(Node *node);//-----------------------------------------------------------------------------
// Handler functions for messages from the transport layer
//-----------------------------------------------------------------------------static void //inline//
HandleFromTransport(Node *node, Message *msg);static void //inline//
ProcessRouteAdvertisementPacket(Node *node,NodeAddress neighborAddr,int incomingInterfaceIndex,int numOfRTEntries,AdvertisedRoute *neighborRowPtr);//-----------------------------------------------------------------------------
// Route table manipulation functions
//-----------------------------------------------------------------------------static void //inline//
InitRouteTable(Bellmanford *bellmanford);static Route * //inline//
FindRoute(Bellmanford *bellmanford,NodeAddress destAddress);static Route * //inline//
AddRoute(Bellmanford *bellmanford,NodeAddress destAddress,NodeAddress subnetMask,NodeAddress nextHop,int incomingInterfaceIndex,int distance);//-----------------------------------------------------------------------------
// Statistics
//-----------------------------------------------------------------------------static void //inline//
PrintStats(Node *node);//-----------------------------------------------------------------------------
// Debug output functions
//-----------------------------------------------------------------------------static void //inline//
PrintRouteAdvertisementPacket(Node *node,AdvertisedRoute *neighborRowPtr,int numAdvertisedRoutes);static void //inline//
PrintRouteTable(Node *node,PrintRouteTableType type);//-----------------------------------------------------------------------------
// FUNCTIONS WITH EXTERNAL LINKAGE
//-----------------------------------------------------------------------------
// Bellmanford initialization  for tracing
//
// \param node  Pointer to node
// \param nodeInput  Pointer to NodeInput
//void RoutingBellmanfordInitTrace(Node* node, const NodeInput* nodeInput)
{char buf[MAX_STRING_LENGTH];BOOL retVal;BOOL traceAll = TRACE_IsTraceAll(node);BOOL trace = FALSE;static BOOL writeMap = TRUE;IO_ReadString(node->nodeId,ANY_ADDRESS,nodeInput,"TRACE-BELLMANFORD",&retVal,buf);if (retVal){if (strcmp(buf, "YES") == 0){trace = TRUE;}else if (strcmp(buf, "NO") == 0){trace = FALSE;}else{ERROR_ReportError("TRACE-BELLMANFORD should be either \"YES\" or \"NO\".\n");}}else{if (traceAll || node->traceData->layer[TRACE_APPLICATION_LAYER]){trace = TRUE;}}if (trace){TRACE_EnableTraceXML(node, TRACE_BELLMANFORD,"BELLMANFORD", RoutingBellmanfordPrintTraceXML, writeMap);}else{TRACE_DisableTraceXML(node, TRACE_BELLMANFORD,"BELLMANFORD", writeMap);}writeMap = FALSE;
}
//-----------------------------------------------------------------------------
// Print TraceXML function
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION   :: RoutingBellmanfordPrintTraceXML
// LAYER      :: NETWORK
// PURPOSE    :: Print packet trace information in XML format
// PARAMETERS ::
// + node     : Node*    : Pointer to node
// + msg      : Message* : Pointer to packet to print headers from
// RETURN     ::  void   : NULL
//-----------------------------------------------------------------------------void RoutingBellmanfordPrintTraceXML(Node* node, Message* msg)
{char buf[MAX_STRING_LENGTH];char sourceAddr[MAX_STRING_LENGTH];char destinationAddr[MAX_STRING_LENGTH];char nexthopAddr[MAX_STRING_LENGTH];Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;RoutingBellmanfordHeader *header;AdvertisedRoute *payload;int numAdvertisedRoutes;// If bellmanford is not configured here, then discard message.if (!bellmanford){return;}// Obtain pointers to header, payload.header = (RoutingBellmanfordHeader *) msg->packet;payload = (AdvertisedRoute *)(msg->packet + sizeof(RoutingBellmanfordHeader));IO_ConvertIpAddressToString(header->sourceAddress, sourceAddr);IO_ConvertIpAddressToString(header->destAddress , destinationAddr);// Obtain number of rows in update.sprintf(buf, "<bellmanford>");TRACE_WriteToBufferXML(node, buf);sprintf(buf,"%s %s %d",sourceAddr,destinationAddr,header->payloadSize );TRACE_WriteToBufferXML(node, buf);numAdvertisedRoutes = header->payloadSize / sizeof(AdvertisedRoute);for (int i = 0; i < numAdvertisedRoutes; i++) {IO_ConvertIpAddressToString(payload->destAddress , destinationAddr);IO_ConvertIpAddressToString(payload->subnetMask, sourceAddr);IO_ConvertIpAddressToString(payload->nextHop, nexthopAddr);sprintf(buf,"<advertisedRoute>%s %s %s %d </advertisedRoute>",destinationAddr,sourceAddr,nexthopAddr,payload->distance);TRACE_WriteToBufferXML(node, buf);payload++;}sprintf(buf, "</bellmanford>");TRACE_WriteToBufferXML(node, buf);
}//-----------------------------------------------------------------------------
// Init function
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     RoutingBellmanfordInit
// PURPOSE      Initializes the Bellman-Ford model.
//
// Parameters:
//
// Node *node
//     For current node
//
// Notes:
//
// This function is called once per node, for nodes which are running
// the Bellman-Ford model for routing.
//-----------------------------------------------------------------------------void
RoutingBellmanfordInit(Node *node)
{Bellmanford *bellmanford;int i;clocktype randomDelay;Message *newMsg;if (node->get_networkData()->networkProtocol == NETWORK_IPV6){// Bellmanford is an IPv4 Network based routing protocol,// it can not be run on this nodereturn;}// Allocate Bellmanford struct.  Assign pointers.bellmanford = (Bellmanford *) MEM_malloc(sizeof(Bellmanford));node->appData.bellmanford = (void *) bellmanford;//Need for route redistributionNetworkDataIp* ip =  node->get_networkVar();// Init stats.bellmanford->numPeriodicUpdates = 0;bellmanford->numRouteTimeouts = 0;bellmanford->numTriggeredUpdates = 0;bellmanford->numRouteAdvertisementsReceived = 0;bellmanford->statsPrinted = FALSE;// Init random seeds to each be differentRANDOM_SetSeed(bellmanford->periodicJitterSeed,node->globalSeed,node->nodeId,ROUTING_PROTOCOL_BELLMANFORD,1);RANDOM_SetSeed(bellmanford->checkTimeoutSeed,node->globalSeed,node->nodeId,ROUTING_PROTOCOL_BELLMANFORD,2);RANDOM_SetSeed(bellmanford->triggeredUpdateSeed,node->globalSeed,node->nodeId,ROUTING_PROTOCOL_BELLMANFORD,3);// Init Bellman-Ford route table.InitRouteTable(bellmanford);// Add 0-hop routes to local networks.  These are flagged as// local routes.//// Loop through all interfaces, since it's assumed that Bellman-Ford// is running on all interfaces on a node.for (i = 0; i < node->numberInterfaces; i++){NodeAddress destAddress;NodeAddress subnetMask;Route *rowPtr;if (NetworkIpGetInterfaceType(node, i) != NETWORK_IPV4&& NetworkIpGetInterfaceType(node, i) != NETWORK_DUALIP){continue;}if (NetworkIpIsWiredNetwork(node, i)){// This is a wiredlink interface.//// The destAddress is the network address for the interface,// and subnetMask is the subnet mask for the interface.destAddress = NetworkIpGetInterfaceNetworkAddress(node, i);subnetMask = NetworkIpGetInterfaceSubnetMask(node, i);}else{// This is a wireless interface.//// The destAddress is the IP address of the interface// itself, and subnetMask is 255.255.255.255 (ANY_DEST is// an all-one 32-bit value).//// This means that the route applies exactly to the host IP// address of the interface. (not to a network address)destAddress = NetworkIpGetInterfaceAddress(node, i);subnetMask = ANY_DEST;}if (!FindRoute(bellmanford, destAddress)// Dynamic address&& ip->interfaceInfo[i]->addressState != INVALID){rowPtr = AddRoute(bellmanford,destAddress,subnetMask,NetworkIpGetInterfaceAddress(node, i),i,0);rowPtr->localRoute = TRUE;}#ifdef ENTERPRISE_LIBif (ip->interfaceInfo[i]->routingProtocolType== ROUTING_PROTOCOL_BELLMANFORD){RouteRedistributeSetRoutingTableUpdateFunction(node,&BellmanfordHookToRedistribute,i);}
#endif // ENTERPRISE_LIB}// Calculate jitter for first periodic update.randomDelay = RANDOM_nrand(bellmanford->periodicJitterSeed) % PERIODIC_UPDATE_JITTER;// Schedule first periodic update.newMsg = MESSAGE_Alloc(node,APP_LAYER,APP_ROUTING_BELLMANFORD,MSG_APP_PeriodicUpdateAlarm);MESSAGE_Send(node, newMsg, 0);// Record time of periodic update in nextPeriodicUpdateTime.// (ScheduleTriggeredUpdate() uses this value.)bellmanford->nextPeriodicUpdateTime = node->getNodeTime() + randomDelay;// Calculate jitter for first route timeout check.randomDelay = RANDOM_nrand(bellmanford->checkTimeoutSeed) % CHECK_TIMEOUT_JITTER;// Schedule first route timeout.newMsg = MESSAGE_Alloc(node,APP_LAYER,APP_ROUTING_BELLMANFORD,MSG_APP_CheckRouteTimeoutAlarm);MESSAGE_Send(node, newMsg, CHECK_TIMEOUT_INTERVAL + randomDelay);// Dynamic address// registering RoutingBellmanfordHandleAddressChangeEvent functionNetworkIpAddAddressChangedHandlerFunction(node,&RoutingBellmanfordHandleChangeAddressEvent);
}//-----------------------------------------------------------------------------
// Layer function
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     RoutingBellmanfordLayer
// PURPOSE      Layer function for the Bellman-Ford model.
//
// Parameters:
//
// Node *node
//     For current node
// Message *msg
//     Message to be processed
//
// Notes:
//
// The MESSAGE_Free() on msg is called at the end of the function.
//-----------------------------------------------------------------------------void
RoutingBellmanfordLayer(Node *node, Message *msg)
{if (node->get_networkData()->networkProtocol == NETWORK_IPV6){// Bellmanford is an IPv4 Network based routing protocol,// it can not be run on this nodeActionData acnData;acnData.actionType = DROP;acnData.actionComment = DROP_INVALID_NETWORK_PROTOCOL;TRACE_PrintTrace(node,msg,TRACE_APPLICATION_LAYER,PACKET_OUT,&acnData);MESSAGE_Free(node, msg);return;}switch (msg->eventType){// Messages sent within Bellman-Ford.case MSG_APP_PeriodicUpdateAlarm:{HandlePeriodicUpdateAlarm(node);break;}case MSG_APP_CheckRouteTimeoutAlarm:{HandleCheckRouteTimeoutAlarm(node);break;}case MSG_APP_TriggeredUpdateAlarm:{HandleTriggeredUpdateAlarm(node);break;}// Messages sent by UDP to Bellman-Ford.case MSG_APP_FromTransport:{HandleFromTransport(node, msg);break;}default:ERROR_ReportError("Invalid switch value");}// Done with the message, so free it.MESSAGE_Free(node, msg);
}//-----------------------------------------------------------------------------
// Finalize function
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     RoutingBellmanfordFinalize
// PURPOSE      Finalize function for the Bellman-Ford model.
//
// Parameters:
//
// Node *node
//     For current node.
// int interfaceIndex
//     Interface index we are finalizing.
//
// Notes:
//
// Called once per node, per interface that is running Bellman-Ford.
// ...PrintStats() is called only for interfaceIndex 0.  See the
// ...PrintStats() function for more info.
//-----------------------------------------------------------------------------void
RoutingBellmanfordFinalize(Node *node, int interfaceIndex)
{Bellmanford *bellmanford = (Bellmanford *)node->appData.bellmanford;if (node->get_networkData()->networkProtocol == NETWORK_IPV6){// Bellmanford is an IPv4 Network based routing protocol,// it can not be run on this nodereturn;}if (node->appData.routingStats == TRUE&& bellmanford->statsPrinted == FALSE){PrintStats(node);bellmanford->statsPrinted = TRUE;}
}//-----------------------------------------------------------------------------
// FUNCTIONS WITH INTERNAL LINKAGE
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// Handler functions for Bellman-Ford internal messages
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     HandlePeriodicUpdateAlarm
// PURPOSE      Broadcasts a periodic update and schedules another.
//
// Parameters:
//
// Node *node
//     For current node.
//-----------------------------------------------------------------------------static void //inline//
HandlePeriodicUpdateAlarm(Node *node)
{Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;clocktype delay;Message *newMsg;// Send all routes to UDP.  Increment stat.SendRouteAdvertisement(node, ROUTING_BELLMANFORD_PERIODIC_UPDATE);// Schedule next periodic update. (node->getNodeTime() + 10 s + 0-100 ms)delay = PERIODIC_UPDATE_INTERVAL+ (RANDOM_nrand(bellmanford->periodicJitterSeed) % PERIODIC_UPDATE_JITTER);newMsg = MESSAGE_Alloc(node,APP_LAYER,APP_ROUTING_BELLMANFORD,MSG_APP_PeriodicUpdateAlarm);MESSAGE_Send(node, newMsg, delay);// Record time of next periodic update in nextPeriodicUpdateTime.// (ScheduleTriggeredUpdate() uses this value.)bellmanford->nextPeriodicUpdateTime = node->getNodeTime() + delay;
}//-----------------------------------------------------------------------------
// FUNCTION     HandleCheckRouteTimeoutAlarm
// PURPOSE      Checks for route timeouts, schedules triggered update if
//              necessary.  Schedules next route timeout check.
//
// Parameters:
//
// Node *node
//     For current node.
//
// Notes:
//
// All routes (that aren't timed out already) are checked for staleness.
// Stale routes are marked unreachable and a triggered update is
// scheduled.
//-----------------------------------------------------------------------------static void //inline//
HandleCheckRouteTimeoutAlarm(Node *node)
{Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;int i;BOOL routeChanged;Message *newMsg;#ifdef DEBUG{printf("Bellmanford: %s s, node %u, --- Route timeout check\n",TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId);}
#endif // DEBUG// Look for stale routes in route table.routeChanged = FALSE;for (i = 0; i < bellmanford->numRoutes; i++){// Added for redistribution. If its a redistributed route then we//  dont time out.if (bellmanford->routeTable[i].isPermanent == TRUE){// move to the next routecontinue;}// Don't time out local routes, routes already marked unreachable.if (bellmanford->routeTable[i].localRoute == FALSE&& bellmanford->routeTable[i].distance != BELLMANFORD_INFINITY&& node->getNodeTime() - bellmanford->routeTable[i].refreshTime>= TIMEOUT_DELAY){// Found new stale route.#ifdef DEBUG_TABLEif (routeChanged == FALSE){// We have a route change resulting from a route timeout,// and will be updating our route table.// Print pre-update route table.PrintRouteTable(node,ROUTING_BELLMANFORD_PRE_UPDATE);}
#endif // DEBUG_TABLEif (routeChanged == FALSE){routeChanged = TRUE;}// Set nextHop is NETWORK_UNREACHABLE, distance is infinity,// routeChanged flag to TRUE.bellmanford->routeTable[i].nextHop     =(unsigned) NETWORK_UNREACHABLE;bellmanford->routeTable[i].distance    = BELLMANFORD_INFINITY;bellmanford->routeTable[i].refreshTime = node->getNodeTime();bellmanford->routeTable[i].changed     = TRUE;// Update forwarding table to indicate no route to// destAddress.NetworkUpdateForwardingTable(node,bellmanford->routeTable[i].destAddress,bellmanford->routeTable[i].subnetMask,(unsigned) NETWORK_UNREACHABLE,ANY_INTERFACE,bellmanford->routeTable[i].distance,ROUTING_PROTOCOL_BELLMANFORD);// Increment stat for a route timeout.// (If a route times out, becomes valid, and times out// again -- the second timeout also counts.)bellmanford->numRouteTimeouts++;#ifdef DEBUG
#ifndef DEBUG_TABLE{printf("Bellmanford: %s s, node %u, --- Route timeout, dest"" = %d\n",TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId, i);}
#endif // DEBUG_TABLE
#endif // DEBUG}}// If any route timed out, schedule a triggered update.if (routeChanged == TRUE){
#ifdef DEBUG_TABLE// If the table was updated, print post-update route table.PrintRouteTable(node,ROUTING_BELLMANFORD_POST_UPDATE);
#endif // DEBUG_TABLEScheduleTriggeredUpdate(node);}// Schedule next route timeout check.newMsg = MESSAGE_Alloc(node,APP_LAYER,APP_ROUTING_BELLMANFORD,MSG_APP_CheckRouteTimeoutAlarm);MESSAGE_Send(node, newMsg,CHECK_TIMEOUT_INTERVAL+ (RANDOM_nrand(bellmanford->checkTimeoutSeed) % CHECK_TIMEOUT_JITTER));
}//-----------------------------------------------------------------------------
// FUNCTION     HandleTriggeredUpdateAlarm
// PURPOSE      Broadcasts a triggered update.
//
// Parameters:
//
// Node *node
//     For current node.
//
// Notes:
//
// This is called sometime after ScheduleTriggeredUpdate()
// schedules an update.  SendRouteAdvertisement() is
// called to broadcast the triggered update.
//-----------------------------------------------------------------------------static void //inline//
HandleTriggeredUpdateAlarm(Node *node)
{Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;// Send updated routes to UDP.SendRouteAdvertisement(node, ROUTING_BELLMANFORD_TRIGGERED_UPDATE);// Clear flag so that another triggered update can be scheduled if// it becomes necessary.bellmanford->triggeredUpdateScheduled = FALSE;
}//-----------------------------------------------------------------------------
// FUNCTION     SendRouteAdvertisement
// PURPOSE      Broadcasts route-advertisement packets on all interfaces.
//
// Parameters:
//
// Node *node
//     For current node.
// RouteAdvertisementType type
//     ROUTING_BELLMANFORD_PERIODIC_UPDATE
//     or,
//     ROUTING_BELLMANFORD_TRIGGERED_UPDATE
//
// Notes:
//
// If type indicates periodic update, then all routes are advertised.
// If type indicates triggered update, then only flagged routes (routes
// which changed since the last update event) are advertised.
//-----------------------------------------------------------------------------static void //inline//
SendRouteAdvertisement(Node *node, RouteAdvertisementType type)
{NetworkDataIp* ip =  node->get_networkVar();Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;AdvertisedRoute payloadBuf[MAX_ROUTES_PER_ROUTE_ADVERTISEMENT_PACKET];int rowIndex;// In the while loop, send the current node's entire route table to// UDP, using multiple packets if necessary.rowIndex = 0;while (rowIndex < bellmanford->numRoutes){// payloadBuf starts with zero rows copied into it.  Every time we// add a route into payloadBuf, we increment payloadRowIndex.  When// payloadBuf is full, we send payloadBuf out, set payloadRowIndex// to 0, and repeat the process -- until the node's entire route// table has been sent.int payloadRowIndex;int payloadSize;payloadRowIndex = 0;while (rowIndex < bellmanford->numRoutes&& payloadRowIndex< MAX_ROUTES_PER_ROUTE_ADVERTISEMENT_PACKET){if (type == ROUTING_BELLMANFORD_PERIODIC_UPDATE||(type == ROUTING_BELLMANFORD_TRIGGERED_UPDATE&& bellmanford->routeTable[rowIndex].changed == TRUE)){payloadBuf[payloadRowIndex].destAddress =bellmanford->routeTable[rowIndex].destAddress;payloadBuf[payloadRowIndex].subnetMask =bellmanford->routeTable[rowIndex].subnetMask;payloadBuf[payloadRowIndex].nextHop =bellmanford->routeTable[rowIndex].nextHop;payloadBuf[payloadRowIndex].distance =bellmanford->routeTable[rowIndex].distance;if (type == ROUTING_BELLMANFORD_TRIGGERED_UPDATE){// Reset routeChanged flag if this is a triggered// update.bellmanford->routeTable[rowIndex].changed = FALSE;}payloadRowIndex++;}rowIndex++;}payloadSize = sizeof(AdvertisedRoute)* payloadRowIndex;if (payloadSize > 0){int i;for (i = 0; i < node->numberInterfaces; i++){NodeAddress destAddress;RoutingBellmanfordHeader header;if (NetworkIpGetUnicastRoutingProtocolType(node, i)!= ROUTING_PROTOCOL_BELLMANFORD){continue;}if (NetworkIpIsWiredNetwork(node, i)){destAddress =NetworkIpGetInterfaceBroadcastAddress(node, i);}else{destAddress = ANY_DEST;}header.sourceAddress = ip->interfaceInfo[i]->ipAddress;header.destAddress   = destAddress;header.payloadSize   = payloadSize;Message* msg = APP_UdpCreateMessage(node,ip->interfaceInfo[i]->ipAddress,(short) APP_ROUTING_BELLMANFORD,// Dynamic Address// we need to brodacast the packet as new address might// make some nodes in subnet out of brodcast address // rangeANY_DEST,(short) APP_ROUTING_BELLMANFORD,TRACE_BELLMANFORD,IPTOS_PREC_INTERNETCONTROL);APP_UdpSetOutgoingInterface(msg, i); APP_AddPayload(node,msg,payloadBuf,payloadSize);APP_AddHeader(node,msg,&header,sizeof(RoutingBellmanfordHeader));APP_UdpSend(node, msg,RANDOM_nrand(bellmanford->periodicJitterSeed) % PERIODIC_UPDATE_JITTER);if (type == ROUTING_BELLMANFORD_PERIODIC_UPDATE){bellmanford->numPeriodicUpdates++;}else if (type == ROUTING_BELLMANFORD_TRIGGERED_UPDATE){bellmanford->numTriggeredUpdates++;}#ifdef DEBUG{char *typeString;char address[MAX_STRING_LENGTH];if (type == ROUTING_BELLMANFORD_PERIODIC_UPDATE){typeString = "Periodic";}else{typeString = "Triggered";}IO_ConvertIpAddressToString(destAddress, address);printf("Bellmanford: %s s, node %u, ""SND %s update, Sent packet to UDP, dst %s\n",TIME_PrintClockInSecond(node->getNodeTime()).c_str(),node->nodeId, typeString, address);}
#endif // DEBUG}//for//}//if//}//while//
}//-----------------------------------------------------------------------------
// FUNCTION     ScheduleTriggeredUpdate
// PURPOSE      Schedules a triggered update.  Checks if an update event
//              isn't already scheduled.
//
// Parameters:
//
// Node *node
//     For current node.
//-----------------------------------------------------------------------------static void //inline//
ScheduleTriggeredUpdate(Node *node)
{Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;// Schedule a triggered update only if// a) A triggered update is not already scheduled for the node, or// b) Next periodic update is far enough away.if (bellmanford->triggeredUpdateScheduled == FALSE&& bellmanford->nextPeriodicUpdateTime> node->getNodeTime() + TRIGGERED_UPDATE_DELAY + TRIGGERED_UPDATE_JITTER){Message *newMsg;// Schedule triggered update. (node->getNodeTime() + 0-100 ms)newMsg = MESSAGE_Alloc(node,APP_LAYER,APP_ROUTING_BELLMANFORD,MSG_APP_TriggeredUpdateAlarm);MESSAGE_Send(node, newMsg,TRIGGERED_UPDATE_DELAY+ RANDOM_nrand(bellmanford->triggeredUpdateSeed) % TRIGGERED_UPDATE_JITTER);// Set flag indicating a triggered update has been scheduled.bellmanford->triggeredUpdateScheduled = TRUE;}
}//-----------------------------------------------------------------------------
// Handler functions for messages from the transport layer
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     HandleFromTransport
// PURPOSE      Processes a packet from UDP.
//
// Parameters:
//
// Node *node
//     For current node.
// Message *msg
//     Contains the UDP packet contents.
//
// Notes:
//
// Only route advertisement packets are receieved from UDP; there are no
// other types of Bellman-Ford messages sent over the network.
//
// This function will call ProcessRouteAdvertisementPacket().
//-----------------------------------------------------------------------------static void //inline//
HandleFromTransport(Node *node, Message *msg)
{// Received a route-advertisement packet from UDP.  When received,// route advertisements from triggered and periodic updates are// treated the same way.Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;RoutingBellmanfordHeader *header;AdvertisedRoute *payload;int numAdvertisedRoutes;UdpToAppRecv *info = (UdpToAppRecv *) MESSAGE_ReturnInfo(msg);int incomingInterfaceIndex = info->incomingInterfaceIndex;// If bellmanford is not configured here, then discard message.if (!bellmanford){return;}ActionData acnData;acnData.actionType = RECV;acnData.actionComment = NO_COMMENT;TRACE_PrintTrace(node, msg, TRACE_APPLICATION_LAYER, PACKET_IN, &acnData);// Increment stat for number of route-advertisement packets// received.bellmanford->numRouteAdvertisementsReceived++;// Obtain pointers to header, payload.header = (RoutingBellmanfordHeader *) msg->packet;payload = (AdvertisedRoute *)(msg->packet + sizeof(RoutingBellmanfordHeader));// Obtain number of rows in update.numAdvertisedRoutes = header->payloadSize / sizeof(AdvertisedRoute);#ifdef DEBUG{char address[MAX_STRING_LENGTH];IO_ConvertIpAddressToString(header->sourceAddress,address);printf("Bellmanford: %s s, node %u, RCV Route broadcast, ""Received packet from UDP, src %s\n",TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId, address);}
#endif // DEBUG#pragma region  // JSLS添加: 【步骤①】获取源节点[发送节点]的 节点ID[NodeID]int sendNodeID = -1;sendNodeID = msg->originatingNodeId;printf("JSLS: sendNodeID = %d \n", sendNodeID);printf("        recvNodeID = %d \n", node->nodeId);
#pragma endregion // JSLS添加: 【步骤①】获取源节点[发送节点]的 节点ID[NodeID]#pragma region // JSLS添加: 【步骤②】找到[发送节点],以便后续计算【[发送节点]与[接收节点]之间的物理距离】,用于 更新路由表中的路由距离[distance]// JSLS添加:根据[NodeId]找到 Node* 指针//            参考:《 C:\Scalable\Exata6.2Source__DEBUG_1\libraries\cyber\advanced\src\app_modify_packet.cpp 》//                   第149行://                    // get node pointer//                   success = PARTITION_ReturnNodePointer(partition, &node, nodeId, TRUE);bool success = FALSE;Node *sendNode = NULL; //JSLS备注:[发送节点]指针,用于后续计算[发送节点]和[目的节点]之间的距离success = PARTITION_ReturnNodePointer(node->partitionData, &sendNode, sendNodeID, TRUE);printf("JSLS: sendNode = 0x%x \n", ((unsigned int)sendNode));#pragma endregion // JSLS添加: 【步骤②】找到[发送节点],以便后续计算【[发送节点]与[接收节点]之间的物理距离】,用于 更新路由表中的路由距离[distance]#pragma region // JSLS添加:【步骤③】计算【[发送节点]与[接收节点]之间的物理距离】,用于 更新路由表中的路由距离// 需要用到《 C:\Scalable\Exata6.2Source__DEBUG_1\include\coordinates.h 》的 //          第493行:/*BOOL COORD_CalcDistance(int coordinateSystemType,const Coordinates* position1,const Coordinates* position2,CoordinateType* distance);*/double distanceBetweenTwoNodes;  // 单位:米。后续需要转化为 ㎞ 千米。Coordinates sendNodePosition; // 发送节点 的 坐标位置Coordinates recvNodePosition; // 接收节点 的 坐标位置MOBILITY_ReturnCoordinates(sendNode, &sendNodePosition);MOBILITY_ReturnCoordinates(node, &recvNodePosition);printf("JSLS: sendNodePosition and recvNodePosition have been got! \n");COORD_CalcDistance(NODE_GetTerrainPtr(node)->getCoordinateSystem(),&sendNodePosition,&recvNodePosition,&distanceBetweenTwoNodes);printf("JSLS: The distance from [sendNodePosition] to [recvNodePosition] is %f \n", distanceBetweenTwoNodes);std::cout.flush();  // "stdio.h"// JSLS备注: [COORD_CalcDistance]计算出来的距离单位是 米 。后续作为【路由距离度量】时需要用 千米(㎞)int distance_in_km = 0;distance_in_km = (int)(distanceBetweenTwoNodes / 1000);if (0 == distance_in_km) //假如 两个节点之间距离【不够】 1㎞,设置为 1㎞。{distance_in_km = 1;}if (32767 < distance_in_km) //假如 两个节点之间距离【大于】 32767㎞,★这是 short 类型的 最大正数值★,设置为 -1㎞,表示越界。{distance_in_km = -1;  // JSLS@2023年8月11日:暂且假设 两颗卫星路由器之间距离 小于3.2767万㎞ 。否则,设置为 -1 表示越界。}///// JSLS特别备注:★复用 Node->numAtmInterfaces 字段 ★ →→→ 用于存储[distance_in_km],即【路由距离度量(㎞)】//                  表示 node接收节点 与 【(发送路由公告)的发送节点】之间的【路由距离度量(㎞)】///node->numAtmInterfaces = distance_in_km; // ★复用 Node->numAtmInterfaces 字段 ★ 表示【路由距离度量(㎞)】#pragma endregion // JSLS添加:【步骤③】计算【[发送节点]与[接收节点]之间的物理距离】,用于 更新路由表中的路由距离// Process the route-advertisement packet.ProcessRouteAdvertisementPacket(node,header->sourceAddress,incomingInterfaceIndex,numAdvertisedRoutes,payload);///// JSLS特别备注:★一定记得还要【解除复用】 Node->numAtmInterfaces 字段 ★ →→→ 重新设置为 0///node->numAtmInterfaces = 0; // ★【解除复用】 Node->numAtmInterfaces 字段 ★ →→→ 重新设置为 0}//-----------------------------------------------------------------------------
// FUNCTION     ProcessRouteAdvertisementPacket
// PURPOSE      Processes a route broadcast packet from UDP.
//
// Parameters:
//
// Node *node
//     For current node.
// NodeAddress neighborAddress
//     IP address of broadcasting node.
// int numAdvertisedRoutes
//     Number of rows in broadcasted route table.
// AdvertisedRoute *neighborRowPtr
//     Pointer to broadcasted route table.
//
// Notes:
//
// Each row in the broadcasted route table is looked at, and the
// local route table is updated appropriately.  The IP forwarding
// table is also updated, and a triggered update may be scheduled.
//-----------------------------------------------------------------------------static void //inline//
ProcessRouteAdvertisementPacket(Node *node,NodeAddress neighborAddress,int incomingInterfaceIndex,int numAdvertisedRoutes,AdvertisedRoute *neighborRowPtr)
{Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;int i;int j;BOOL routeChanged;NodeAddress destAddress;NodeAddress subnetMask;BOOL newRoute;// Dynamic AddressNetworkDataIp* ip =  node->get_networkVar();BOOL wasFound;routeChanged = FALSE;#ifdef DEBUG// Print update vector from route broadcast.PrintRouteAdvertisementPacket(node,neighborRowPtr,numAdvertisedRoutes);#endif // DEBUGfor (i = 0; i < numAdvertisedRoutes; i++){Route *rowPtr;destAddress = neighborRowPtr[i].destAddress;subnetMask = neighborRowPtr[i].subnetMask;// Skip routes that are for a directly connected network// (for point-to-point interfaces), or to oneself// (all other interface types).wasFound = FALSE;for (j = 0; j < node->numberInterfaces; j++){if (NetworkIpIsWiredNetwork(node, j)){if (NetworkIpGetInterfaceNetworkAddress(node, j)== destAddress&& NetworkIpGetInterfaceSubnetMask(node, j)== subnetMask){// Skip this route.  Node doesn't need to update// for directly connected network.wasFound = TRUE;break;}}else{if (NetworkIpGetInterfaceAddress(node, j) == destAddress){// Skip this route.  Node doesn't need to update// route to self.wasFound = TRUE;break;}}}if (wasFound){continue;}wasFound = FALSE;for (j = 0; j < node->numberInterfaces; j++){if (NetworkIpGetInterfaceAddress(node, j)== neighborRowPtr[i].nextHop){// Split horizon with poisoned reverse.neighborRowPtr[i].distance = BELLMANFORD_INFINITY;wasFound = TRUE;break;}}if (!wasFound){/* // 原始代码// Increment hop count (one hop from neighbor to this node).if (neighborRowPtr[i].distance < BELLMANFORD_INFINITY){neighborRowPtr[i].distance++;}*/#pragma region // JSLS添加:根据【[源节点]到[目的节点]的距离】更新路由表 // JSLS添加:更新路由表时,不是简单地将[distance]路由距离 增加1 ,//                          而是“增加”【[源节点]到[目的节点]的距离】,//            其中,[源节点]用【 msg->originatingNodeId 】来识别。// //// [源节点]用【 msg->originatingNodeId 】来识别  请参考://     《 C:\Scalable\Exata6.2Source__DEBUG_1\core\mac\mac.cpp 》//      第 5792 行:/*printf("Node %d (time %s) received a packet of size %d ""originated from node %d at time %15" TYPES_64BITFMT"d from PHY\n", node->nodeId, TIME_PrintClockInSecond(node->getNodeTime()).c_str(),MESSAGE_ReturnPacketSize(packet), packet->originatingNodeId, packet->packetCreationTime);*//*	从复用的 Node->numAtmInterfaces 字段,提取【路由距离度量(㎞)】///// JSLS特别备注:★复用 Node->numAtmInterfaces 字段 ★ →→→ 用于存储[distance_in_km],即【路由距离度量(㎞)】//                  表示 node接收节点 与 【(发送路由公告)的发送节点】之间的【路由距离度量(㎞)】///node->numAtmInterfaces = distance_in_km; // ★复用 Node->numAtmInterfaces 字段 ★ 表示【路由距离度量(㎞)】*/// JSLS修改:从复用的 Node->numAtmInterfaces 字段,提取【路由距离度量(㎞)】//            表示 node接收节点 与 【(发送路由公告)的发送节点】之间的【路由距离度量(㎞)】。if (neighborRowPtr[i].distance <= BELLMANFORD_INFINITY){int distance_in_km__betweenTwoNodes = node->numAtmInterfaces; // numAtmInterfaces 字段 → 复用表示【路由距离度量(㎞)】neighborRowPtr[i].distance += distance_in_km__betweenTwoNodes;}
#pragma endregion // JSLS添加:根据【[源节点]到[目的节点]的距离】更新路由表 }// Get route that goes to the same destAddress.newRoute = FALSE;rowPtr = FindRoute(bellmanford, destAddress);if (rowPtr == NULL){// Route to destAddress not present in route table.// This is a new route.newRoute = TRUE;}// Update/refresh route in route table if this is a new route,// an advertised route has a better metric, or if the sending// node is a route's next hop.if (newRoute|| neighborRowPtr[i].distance < rowPtr->distance|| neighborAddress == rowPtr->nextHop // Dynamic address&& ip->interfaceInfo[incomingInterfaceIndex]->addressState!= INVALID){if (newRoute|| neighborRowPtr[i].distance != rowPtr->distance|| rowPtr->incomingInterface != incomingInterfaceIndex){
#ifdef DEBUG_TABLEif (routeChanged == FALSE){// We have a route change resulting from this route// broadcast, and will be updating our route table.// Print update vector from route broadcast.PrintRouteAdvertisementPacket(node,neighborRowPtr,numAdvertisedRoutes);// Print pre-update route table.PrintRouteTable(node,ROUTING_BELLMANFORD_PRE_UPDATE);}
#endif // DEBUG_TABLEif (newRoute){rowPtr = AddRoute(bellmanford,destAddress,subnetMask,neighborAddress,incomingInterfaceIndex,neighborRowPtr[i].distance);}// Set new distance.rowPtr->distance = (short) neighborRowPtr[i].distance;// Set new interfacerowPtr->incomingInterface = incomingInterfaceIndex;rowPtr->outgoingInterface = incomingInterfaceIndex;// Distance metric has changed (either increased or// decreased).  Set routeChanged flag for this route// so that the route is later sent on a triggered// update.rowPtr->changed = TRUE;if (routeChanged == FALSE){routeChanged = TRUE;}}//if//// Set nextHop to the sender of the route broadcast, unless// the distance advertised is infinity, in which case the// nextHop is NETWORK_UNREACHABLE.if (neighborRowPtr[i].distance == BELLMANFORD_INFINITY){rowPtr->nextHop = (unsigned) NETWORK_UNREACHABLE;}else{rowPtr->nextHop = neighborAddress;}// Route is refreshed.rowPtr->refreshTime = node->getNodeTime();// Update forwarding table.NetworkUpdateForwardingTable(node,destAddress,subnetMask,rowPtr->nextHop,rowPtr->outgoingInterface,rowPtr->distance,ROUTING_PROTOCOL_BELLMANFORD);}//if//}//for//// If a route has changed, call function which determines whether// to schedule a triggered update.if (routeChanged == TRUE){
#ifdef DEBUG
#ifndef DEBUG_TABLEprintf("Bellmanford: %s s, node %u, --- Route table updated\n",TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId);
#endif // DEBUG_TABLE
#endif // DEBUG
#ifdef DEBUG_TABLE// If the table was updated, print post-update route table.PrintRouteTable(node,ROUTING_BELLMANFORD_POST_UPDATE);
#endif // DEBUG_TABLEScheduleTriggeredUpdate(node);}
#ifdef DEBUGelse{printf("Bellmanford: %s s, node %u, --- Route table not changed\n",TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId);
#ifdef DEBUG_TABLE// If the table was updated, print post-update route table.PrintRouteTable(node,ROUTING_BELLMANFORD_POST_UPDATE);
#endif // DEBUG_TABLE}
#endif // DEBUG
}//-----------------------------------------------------------------------------
// Route table manipulation functions
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     InitRouteTable
// PURPOSE      Initializes a route table.
//
// Parameters:
//
// Bellmanford *bellmanford
//     Pointer to Bellman-Ford state information.
//
// Notes:
//
// This function was designed to be run only once.
// (no re-initializing the route table!)
//-----------------------------------------------------------------------------static void //inline//
InitRouteTable(Bellmanford *bellmanford)
{// Allocate route table.bellmanford->routeTable =(Route *) MEM_malloc(NUM_INITIAL_ROUTES_ALLOCATED * sizeof(Route));bellmanford->numRoutesAllocated = NUM_INITIAL_ROUTES_ALLOCATED;bellmanford->numRoutes = 0;bellmanford->nextPeriodicUpdateTime = 0;bellmanford->triggeredUpdateScheduled = FALSE;
}//-----------------------------------------------------------------------------
// FUNCTION     FindRoute
// PURPOSE      Finds a route for an IP address.
//
// Parameters:
//
// Bellmanford *bellmanford
//     Pointer to Bellman-Ford state information.
// NodeAddress destAddress
//     IP address to find route for.
//
// Returns:
//
// A pointer to the row that matches destAddress.  If a row was not found,
// NULL is returned.
//-----------------------------------------------------------------------------static Route * //inline//
FindRoute(Bellmanford *bellmanford,NodeAddress destAddress)
{int top;int bottom;int middle;Route *rowPtr;// Set row = NULL if cannot find row.// Otherwise set row to the matching one.if (bellmanford->numRoutes == 0){return NULL;}top = 0;bottom = bellmanford->numRoutes - 1;middle = (bottom + top) / 2;if (destAddress == bellmanford->routeTable[top].destAddress){return &bellmanford->routeTable[top];}if (destAddress == bellmanford->routeTable[bottom].destAddress){return &bellmanford->routeTable[bottom];}while (middle != top){rowPtr = &bellmanford->routeTable[middle];if (destAddress == rowPtr->destAddress){return rowPtr;}elseif (destAddress < rowPtr->destAddress){bottom = middle;}else{top = middle;}middle = (bottom + top) / 2;}return NULL;
}//-----------------------------------------------------------------------------
// FUNCTION     AddRoute
// PURPOSE      Adds a route to the route table.
//
// Parameters:
//
// Bellmanford *bellmanford
//     Pointer to Bellman-Ford state information.
// NodeAddress destAddress
//     IP address to add route for.
// NodeAddress subnetMask
//     Subnet mask for the route.
// NodeAddress nextHop
//     IP address of the next hop for the route.
// int distance
//     Distance metric (number of hops) for the route.
//
// Returns:
//
// Pointer to newly-added route.
//
// Notes:
//
// Adding a duplicate route will cause an assertion failure.  Two routes
// with the same destAddress but different subnetMasks is included in
// this limitation. -- Always check if a route exists with the
// ...FindRoute() first, unless it's known that the route doesn't exist.
//-----------------------------------------------------------------------------static Route * //inline//
AddRoute(Bellmanford *bellmanford,NodeAddress destAddress,NodeAddress subnetMask,NodeAddress nextHop,int incomingInterfaceIndex,int distance)
{int index;// There should only be one row per unique destination address.// Check if the table has been filled.if (bellmanford->numRoutes == bellmanford->numRoutesAllocated){Route *oldTable;int i;// Table filled:  Double route table size.oldTable = bellmanford->routeTable;bellmanford->routeTable = (Route *)MEM_malloc(2 * bellmanford->numRoutesAllocated* sizeof(Route));for (i = 0; i < bellmanford->numRoutes; i++){bellmanford->routeTable[i] = oldTable[i];}MEM_free(oldTable);bellmanford->numRoutesAllocated *= 2;}// Insert route.index = bellmanford->numRoutes;bellmanford->numRoutes++;while (1){if (index != 0&& destAddress <= bellmanford->routeTable[index - 1].destAddress){if (destAddress == bellmanford->routeTable[index - 1].destAddress){// Duplicate entry.ERROR_ReportError("Cannot add duplicate route");}bellmanford->routeTable[index] = bellmanford->routeTable[index - 1];index--;continue;}bellmanford->routeTable[index].destAddress = destAddress;bellmanford->routeTable[index].subnetMask  = subnetMask;bellmanford->routeTable[index].nextHop     = nextHop;bellmanford->routeTable[index].incomingInterface =incomingInterfaceIndex;bellmanford->routeTable[index].outgoingInterface =incomingInterfaceIndex;bellmanford->routeTable[index].distance    = (short) distance;bellmanford->routeTable[index].localRoute  = FALSE;bellmanford->routeTable[index].refreshTime = 0;bellmanford->routeTable[index].changed     = FALSE;bellmanford->routeTable[index].isPermanent =  FALSE;return &bellmanford->routeTable[index];}
}//-----------------------------------------------------------------------------
// Statistics
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     PrintStats
// PURPOSE      Prints statistics for Bellman-Ford.
//
// Parameters:
//
// Node *node
//     For current node.
//
// Notes:
//
// Called by RoutingBellmanFordFinalize(), only for interfaceIndex 0.
//
// Note that when an update is sent, it is sent on all interfaces;
// this event is counted as a single periodic update, even though a
// packet is sent out on each interface.  Received updates, on the other
// hand, are counted once per packet received.)
//-----------------------------------------------------------------------------static void //inline//
PrintStats(Node *node)
{Bellmanford *bellmanford = (Bellmanford *)node->appData.bellmanford;char buf[MAX_STRING_LENGTH];sprintf(buf, "Number of periodic updates sent = %d",bellmanford->numPeriodicUpdates);IO_PrintStat(node, "Application", "Bellman-Ford", ANY_DEST, -1, buf);sprintf(buf, "Number of triggered updates sent = %d",bellmanford->numTriggeredUpdates);IO_PrintStat(node, "Application", "Bellman-Ford", ANY_DEST, -1, buf);sprintf(buf, "Number of route timeouts = %d",bellmanford->numRouteTimeouts);IO_PrintStat(node, "Application", "Bellman-Ford", ANY_DEST, -1, buf);sprintf(buf, "Number of update packets received = %d",bellmanford->numRouteAdvertisementsReceived);IO_PrintStat(node, "Application", "Bellman-Ford", ANY_DEST, -1, buf);
}//-----------------------------------------------------------------------------
// Debug output functions
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
// FUNCTION     PrintRouteAdvertisementPacket
// PURPOSE      Prints to screen the contents of a route advertisement
//              packet (an "update vector").
//
// Parameters:
//
// Node *node
//     For current node.
// AdvertisedRoute *neighborRowPtr
//     Pointer to update vector.
// int numAdvertisedRoutes
//     Number of rows in update vector.
//-----------------------------------------------------------------------------static void //inline//
PrintRouteAdvertisementPacket(Node *node,AdvertisedRoute *neighborRowPtr,int numAdvertisedRoutes)
{int i;printf("Bellmanford: %s s, node %u, --- Update vector, ""(dest nextHop dist)\n", TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId);for (i = 0; i < numAdvertisedRoutes; i++){char address[MAX_STRING_LENGTH];IO_ConvertIpAddressToString(neighborRowPtr[i].destAddress, address);printf("Bellmanford:\t%s", address);if (neighborRowPtr[i].nextHop == (unsigned) NETWORK_UNREACHABLE){printf("\t-");}else{IO_ConvertIpAddressToString(neighborRowPtr[i].nextHop, address);printf("\t%s", address);}printf("\t%d\n", neighborRowPtr[i].distance);}
}//-----------------------------------------------------------------------
// FUNCTION     PrintRouteTable
// PURPOSE      Prints to screen the local route table.
//
// Parameters:
//
// Node *node
//     For current node.
// PrintRouteTableType type
//     ROUTING_BELLMANFORD_PRE_UPDATE
//     or,
//     ROUTING_BELLMANFORD_POST_UPDATE
//
// Notes:
//
// Prints the local route table.  The "pre" and "post" options are used
// to print to the screen whether the contents of the route table were
// before or after processing an update vector.
//------------------------------------------------------------------------static void //inline//
PrintRouteTable(Node *node, PrintRouteTableType type)
{Bellmanford *bellmanford = (Bellmanford *) node->appData.bellmanford;int i;printf("Bellmanford: %s s, node %u, ",TIME_PrintClockInSecond(node->getNodeTime()).c_str(), node->nodeId);if (type == ROUTING_BELLMANFORD_PRE_UPDATE){printf("--- Pre-update route table, (dest nextHop dist)\n");}elseif (type == ROUTING_BELLMANFORD_POST_UPDATE){printf("--- Post-update route table, (dest nextHop dist)\n");}else{printf("--- Post-update Route table, (dest nextHop dist)\n");}for (i = 0; i < bellmanford->numRoutes; i++){char address[MAX_STRING_LENGTH];IO_ConvertIpAddressToString(bellmanford->routeTable[i].destAddress, address);printf("Bellmanford:\t%s",address);if (bellmanford->routeTable[i].nextHop== (unsigned) NETWORK_UNREACHABLE){printf("\t-");}else{IO_ConvertIpAddressToString(bellmanford->routeTable[i].nextHop, address);printf("\t%s", address);}printf("\t%d\n", bellmanford->routeTable[i].distance);}
}
//-----------------------------------------------------------------------------
// FUNCTION BellmanfordHookToRedistribute
// PURPOSE      Update or add the redistributed
//              routes into Bellmanford routing table.
// PARAMETERS   Node *node
//                  Pointer to node.
//              NodeAddress destAddress
//                  IP address of destination network or host.
//              NodeAddress destAddressMask
//                  Netmask.
//              NodeAddress nextHopAddress
//                  Next hop IP address.
//              int interfaceIndex
//                    The specify the routing protocol
//              void* routeCost
//                  Metric associate with the route
// RETURN: None
//----------------------------------------------------------------------------
void
BellmanfordHookToRedistribute(Node* node,NodeAddress destAddress,NodeAddress destAddressMask,NodeAddress nextHopAddress,int interfaceIndex,void* routeCost)
{Route* routePtr = NULL;int cost =  *(int*) routeCost;Bellmanford* bellmanford = (Bellmanford*)node->appData.bellmanford;routePtr = FindRoute(bellmanford,destAddress);if (routePtr != NULL){return;}routePtr = AddRoute(bellmanford,destAddress,destAddressMask,nextHopAddress,interfaceIndex,(unsigned) cost);if (routePtr != NULL){// We set this flag so that the route doesnt get time outroutePtr->isPermanent = TRUE;}
}// Dynamic address//---------------------------------------------------------------------------
// FUNCTION   :: RoutingBellmanfordHandleChangeAddressEvent
// PURPOSE    :: Handles any change in the interface address for Bellmanford
// PARAMETERS ::
// + node               : Node* : Pointer to Node structure
// + interfaceIndex     : Int32 : interface index
// + oldAddress         : Address* : current address
// + subnetMask         : NodeAddress : subnetMask
// + networkType        : NetworkType : type of network protocol
// RETURN :: void : NULL
//---------------------------------------------------------------------------void RoutingBellmanfordHandleChangeAddressEvent(Node* node,Int32 interfaceIndex,Address* oldAddress,NodeAddress subnetMask,NetworkType networkType)
{// Get the Bellmanford data structureBellmanford* bellmanford =(Bellmanford*)node->appData.bellmanford;NetworkDataIp* ip = node->get_networkVar();IpInterfaceInfoType* interfaceInfo =ip->interfaceInfo[interfaceIndex];// If Bellmanford is not configured on this interface, because// adress change handler function is registered at node levelif (interfaceInfo->routingProtocolType != ROUTING_PROTOCOL_BELLMANFORD){return;}// Bellmanford is only supported for IPv4if (networkType == NETWORK_IPV6 ){return;}// currently interface address state is invalid, hence no need to update// tables as no communication can occur from this interface while the // interface is in invalid address stateif (interfaceInfo->addressState  == INVALID ){return;}if (networkType == NETWORK_IPV4 || networkType == NETWORK_DUALIP){NodeAddress destAddress;NodeAddress subnetMask;Route* rowPtr;if (NetworkIpIsWiredNetwork(node, interfaceIndex)){// This is a wiredlink interface.// The destAddress is the current network// address for the interface,// and subnetMask is the current subnet mask for the interface.destAddress = NetworkIpGetInterfaceNetworkAddress(node,interfaceIndex);subnetMask = NetworkIpGetInterfaceSubnetMask(node,interfaceIndex);}else{// This is a wireless interface.// The destAddress is the IP address of the interface// itself, and subnetMask is 255.255.255.255 (ANY_DEST is// an all-one 32-bit value).// This means that the route applies exactly to the host IP// address of the interface. (not to a network address)destAddress = NetworkIpGetInterfaceAddress(node, interfaceIndex);subnetMask = ANY_DEST;}// Update forwarding table to inclue new interface addressNetworkUpdateForwardingTable(node,destAddress,subnetMask,0,interfaceIndex,1,ROUTING_PROTOCOL_DEFAULT);// Update the routing table of bellmanford such that the// new address is advertised in updatesif (!FindRoute(bellmanford, destAddress)){rowPtr = AddRoute(bellmanford,destAddress,subnetMask,NetworkIpGetInterfaceAddress(node, interfaceIndex),interfaceIndex,0);rowPtr->localRoute = TRUE;rowPtr->changed = TRUE;}}
}

毅哥铡特仿真动画:注意仿真画布长宽设置大一些,仿真时间设置长一点,发送的测试应用CBR数据多一些。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/87433.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node.js |(四)HTTP协议 | 尚硅谷2023版Node.js零基础视频教程

学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程&#xff0c;nodejs新手到高手 文章目录 &#x1f4da;HTTP概念&#x1f4da;窥探HTTP报文&#x1f4da;请求报文的组成&#x1f407;HTTP请求行&#x1f407;HTTP请求头&#x1f407;HTTP的请求体 &#x1f4da;响应报文…

Linux信号介绍

一、信号处理函数的注册 signal()使用&#xff1a; 1 #include<stdio.h>2 #include <signal.h>3 4 void handler(int signum)5 {6 switch(signum){7 case 2:8 printf("signum %d\n",signum);9 …

Multipass虚拟机设置局域网固定IP同时实现快速openshell的链接

本文只介绍在windows下实现的过程&#xff0c;Ubuntu采用22.04 安装multipass后&#xff0c;在卓面右下角Open shell 就可以链接默认实例Primary&#xff0c;当然如果你有多个虚拟机&#xff0c;可以针对不同内容单独建立终端的链接&#xff0c;而本文仅仅用Primary来说明。 …

GO学习之 微框架(Gin)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

《大型网站技术架构》第二篇 架构-高可用

高可用在公司中的重要性 对公司而言&#xff0c;可用性关系网站的生死存亡。对个人而言&#xff0c;可用性关系到自己的绩效升迁。 工程师对架构做了许多优化、对代码做了很多重构&#xff0c;对性能、扩展性、伸缩性做了很多改善&#xff0c;但别人未必能直观地感受到&#…

【三维编辑】Seal-3D:基于NeRF的交互式像素级编辑

文章目录 摘要一、引言二、方法2.1.基于nerf的编辑问题概述2.2.编辑指导生成2.3.即时预览的两阶段学生训练 三、实验四、代码总结 项目主页: https://windingwind.github.io/seal-3d/ 代码&#xff1a;https://github.com/windingwind/seal-3d/ 论文: https://arxiv.org/pdf/23…

JavaWeb-Servlet服务连接器(一)

目录 1.Servlet生命周期 2.Servlet的配置 3.Servlet的常用方法 4.Servlet体系结构 5.HTTP请求报文 6.HTTP响应报文 1.Servlet生命周期 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称。其主要的功能是交互式地浏览和修改数据&#xff0c;生成一些动态…

Springboot04--vue前端部分+element-ui

注意点&#xff1a; 这边v-model和value的区别&#xff1a;v-model是双向绑定的&#xff0c;value是单向绑定 li的key的问题 vue的组件化开发&#xff1a; 1. NPM&#xff08;类似maven&#xff0c;是管理前段代码的工具&#xff09; 安装完之后可以在cmd里面使用以下指令 2.…

初出茅庐的小李博客之认识编码器

编码器是什么&#xff1a; 一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感器&#xff0c;我们可以通过编码器测量到底位移或者速度信息。编码器通常由一个旋转部分和一个固定部分组成&#xff0c;旋转部分随着被测量的物体进行旋转&#xff0c;固定部分则保持不动…

vue2 封装 webSocket 开箱即用

第一步&#xff1a; 下载 webSocket npm install vue-native-websocket --save 第二步&#xff1a; 需要在 main.js 中 引入 import websocket from vue-native-websocket; Vue.use(websocket, , {connectManually: true, // 手动连接format: json, // json格式reconnection:…

【Ubuntu】简化反向代理和个性化标签页体验

本文将介绍如何使用Docker部署Nginx Proxy Manager和OneNav&#xff0c;两个功能强大且易用的工具。Nginx Proxy Manager用于简化和管理Nginx反向代理服务器的配置&#xff0c;而OneNav则提供个性化的新标签页体验和导航功能。通过本文的指导&#xff0c;您将学习如何安装和配置…

JavaScript类

JavaScript 类(class) 类是用于创建对象的模板。 我们使用 class 关键字来创建一个类&#xff0c;类体在一对大括号 {} 中&#xff0c;我们可以在大括号 {} 中定义类成员的位置&#xff0c;如方法或构造函数。 每个类中包含了一个特殊的方法 constructor()&#xff0c;它是类…

【yolov系列:小白yolov7跑数据集建立环境】

首先在github上面获取别人的源码 这个是github的源码包&#xff0c;直接下载解压使用 打开解压后的文件夹应该可以看到这个页面。 进入文件夹的requirements.txt的页面 这篇文章是为了记录自己的环境配置过程&#xff0c;当作笔记使用来看&#xff0c;目前网上各种安装教程都…

深入浅出:MyBatis的使用方法及最佳实践

这里写目录标题 添加MyBatis框架⽀持配置连接字符串和MyBatis配置连接字符串配置 MyBatis 中的 XML 路径 添加业务代码创建数据库和表添加用户实体类添加 mapper 接⼝添加 UserMapper.xml添加 Service层添加 Controller层 增删改操作增加操作删除操作修改操作 添加MyBatis框架⽀…

浏览器多管闲事之跨域

年少时的梦想就是买一台小霸王游戏机 当时的宣传语就是小霸王其乐无穷~。 大些了&#xff0c;攒够了零花钱&#xff0c;在家长的带领下终于买到了 那一刻我感觉就是最幸福的人 风都是甜的&#xff01; 哪成想... 刚到家就被家长扣下了 “”禁止未成年人玩游戏机 (问过卖家了&a…

泛微E-Office任意文件上传漏洞复现(HW0day)

0x01 产品简介 泛微E-Office是一款标准化的协同 OA 办公软件&#xff0c;泛微协同办公产品系列成员之一,实行通用化产品设计&#xff0c;充分贴合企业管理需求&#xff0c;本着简洁易用、高效智能的原则&#xff0c;为企业快速打造移动化、无纸化、数字化的办公平台。 0x02 漏…

【LeetCode】数据结构题解(13)[设计循环链表]

设计循环链表 &#x1f609; 1.题目来源&#x1f440;2.题目描述&#x1f914;3.解题思路&#x1f973;4.代码展示 所属专栏&#xff1a;玩转数据结构题型❤️ &#x1f680; >博主首页&#xff1a;初阳785❤️ &#x1f680; >代码托管&#xff1a;chuyang785❤️ &…

selenium环境搭建

文章目录 1、下载谷歌浏览器2、下载谷歌驱动 1、下载谷歌浏览器 浏览器下载完成后&#xff0c;在任务管理器中禁止浏览器的自动更新。因为驱动版本必须和浏览器一致&#xff0c;如果浏览器更新了&#xff0c;驱动就用不起了。 2、下载谷歌驱动 谷歌驱动需要和谷歌浏览器版本…

Spring-Cloud-Loadblancer详细分析_3

前两篇文章介绍了加载过程&#xff0c;本文从Feign的入口开始分析执行过程&#xff0c;还是从FeignBlockingLoadBalancerClient.execute来入手 public class FeignBlockingLoadBalancerClient implements Client {private static final Log LOG LogFactory.getLog(FeignBlock…

2023全新UI好看的社区源码下载/反编译版

2023全新UI好看的社区源码下载/反编译版 这次分享一个RuleAPP二开美化版&#xff08;尊重每个作者版权&#xff09;&#xff0c;无加密可反编译版本放压缩包了&#xff0c;自己弄吧&#xff01;&#xff01;&#xff01; RuleAPP本身就是一款免费开源强大的社区&#xff0c;基…