Linkstate update
While the OSPF algorithm specifies that the link state be exchanged when a system boots up, we will not implement this. Instead, all that will be implemented is the flooding of new link states and the periodic generation of new link states.
The tasks are as follows.
Every 30 seconds, the node generates a new link state announcement. This link state announcement has a new sequence number and contains a list that the links that are currently working. This new link state announcement is reliably flooded to all neighbors.
When a new link state announcement is received, the node should update its link state database, generate a new routing table and reliably flood this new announcement to all neighbors, except the one that sent it.
When a link state announcement is received that has already been received, then it should be ignored. Note, you can tell if a link state announcement has already been received by examining the sequence number.
Details:
Reliable flooding means that a link state announcement is periodically sent to a neighbor until either an acknowledgement for the link state announcement is received or the link becomes non-bi-directional.
Use the struct FloodEntryStruct for reliable flooding.
Make a function
void AddToFloodList(vector<struct FloodEntryStruct> &ToBeFloodedList, struct LinkStateUpdatePktStruct LSAPkt, struct NodeIDStruct To)
This function simply pushes a new link state announcement on to the ToBeFloodedList. Note that the elements of this vector also contain the time at which this LSA must be retransmitted and the node to which this LSA should be sent. When pushing a new LSA, the TimeOut should be set to the current time (GetCurrentTime()) minus 10. Then this entry is late, and will be sent at the next opportunity.
To flood LSA make a function
void CheckFloodList(vector<struct FloodEntryStruct> &ToBeFloodedList, vector<struct LinkStateStruct> &MyLS, struct NodeIDStruct MyID)
This function check the TimeOut field of each element of the vector ToBeFlooded, if any of these TimeOut values are less than the current time then they are sent to the To field and the TimeOut is reset to the current time plus 10.
Specifically, iterate through the ToBeFloodedList and compare iter->TimeOut to the current time. If the current time is larger than iter->TimeOut, then check to see if this link is bi-directional. This is done by iterating thorugh MyLS until iterMyLS->ID is the same as iter->To. Then the link state of this element of MyLS is checked. If iterMyLS-> Bidirectional==0, then this element of the ToBeFloodedList must be erased (ToBeFloodedList.erase(iter)). Note that after erasing en element, you cannot continue iterating through the ToBeFloodedList, as iter does not point to a valid element. Thus, you need to restart iterating through the ToBeFloodedList.
Now, if you find an element of ToBeFlooded with TimeOut that is less than the current time and with a bi-directional link, then the element need to be sent. This is done by, first setting iter->TimeOut=GetCurrentTime() + 10;
struct LinkStateUpdatePktStruct LSAPkt=iter->LSUpdatePkt;
Set the SourceRouterID in LSAPkt to MYID.
Convert LSAPkt to a pkt using LinkStateUpdatePktStructToPkt,
And sent it with SendUDPNumIP. Note that it should be sent to iter->To.
Continue doing this until you iterate through the ToBeFlooded list and don’t find any elements that need to be flooded.
Make sure to call CheckFloodList regularly.
When an Acknowledgement for a LSA is received, the corresponding element in the ToBeFloodedList needs to be erased. To this end make a function
void ReceiveAck(char *pkt, vector<struct FloodEntryStruct> &ToBeFloodedList)
Convert the pkt to an OSPFACKPktStruct using PktToAckStruct.
Iterate through the ToBeFloodedList until the iter-To is the same as Source.IP where Source is the OSPFHeader.SourceRouterID field of the Ack packet returned by PktToAckStruct. Then erase this element from ToBeFloodedList, i.e., ToBeFloodedList.erase(iter);
And break from the loop and end the function.
When an LSA is received, it must be determined if this LSA has been seen before. If it has not been seen, then the link state database should be updated, the LSA should be flooded to all neighbors, but the one that sent it, and a new routing table should be generated.
Specifically:
Make a function
void ReceiveLinkStateUpdate(char *pkt, vector<struct OSPFLinkStateAdvertisementStruct> &AllLSA, vector<struct FloodEntryStruct> &ToBeFloodedList, vector<struct LinkStateStruct> MyLS, struct NodeIDStruct MyID, int &NeedNewRoutingTable)
First convert pkt to struct LinkStateUpdatePktStruct LSP; using PktToLinkStateUpdatePktStruct.
Now, there are two possibilities, this link state announcement is referring to a link state announcement that is already in the database (but might be an update), or is an entirely new announcement from a node never heard from before.
Iterate through the link state datebase, AllLSA. (We’ll call the iterator iter.) Iterate until iter->LinkStateID is the same as LSP.LSAs[0].LinkStateID (note that this means that both the IP and Port field have to match) (also note, that we will only have one element in the LSP.LSAs array.) Now, if IDs match, check if the announcement is new by checking if iter-> LSSeqNum < LSP.LSAs[n].LSSeqNum.
If so, then, set the NeedNewRoutingTable flag, update the database with this new announcement and put this LSA in the ToBeFloodedList.
If the IDs match, but iter-> LSSeqNum >= LSP.LSAs[n].LSSeqNum, then just break from the loop.
Now if, after iterating through the link state database, an element of the database does not have the same ID as the link state announcement, then:
Push this link state announcement on to the link state data base (AllLSA.push_back(LSP.LSAs[n]);)
Set the NeedNewRoutingTable flag and put this new announcement on the ToBeFloodedList.
new link state annoucement
The final task is to generate a new link state announcement. Make sure to call this function every 30 seconds.
Make a function
void FloodMyLSA(vector<struct OSPFLinkStateAdvertisementStruct> &AllLSA, vector<struct LinkStateStruct> MyLS, struct NodeIDStruct MyID, long SeqNum, vector<struct FloodEntryStruct> &ToBeFloodedList)
First, iterate though the link state database and find the entry that refers to the node. That is, iterate until iter->LinkStateIS.IP==MyID.IP and iter->LinkStateIS.Port==MyID.Port.
Then erase this entry and break from iteration.
Now make a new database entry, by calling MakeMyLSA(MyLSA, MyLS, MyID, SeqNum);
Push MyLSA onto the link state datebase (i.e., AllLSA.push_back(MyLSA); )
Make a link state announcement packet by calling
struct LinkStateUpdatePktStruct LSAPkt;
and set LSAPkt.LSAs[0]=MyLSA (which is returned from MakeMyLSA).
Set LSApkt.NumLSA=1;
Also
LSAPkt.OSPFHeader.SourceRouterID=MyID;
LSAPkt.OSPFHeader.Type=OSPF_LINK_STATE_UPDATE_PKT_TYPE;
LSAPkt.Type=OSPF_PKT_TYPE;
Finally, put this LSAPkt on the ToBeFloodedList such that it will be flooded to all neighbors.