|
|
| 26 |
#include "ns3/node.h" |
26 |
#include "ns3/node.h" |
| 27 |
#include "ns3/ipv4.h" |
27 |
#include "ns3/ipv4.h" |
| 28 |
#include "ns3/bridge-net-device.h" |
28 |
#include "ns3/bridge-net-device.h" |
|
|
29 |
#include "ns3/net-device-container.h" |
| 29 |
#include "global-router-interface.h" |
30 |
#include "global-router-interface.h" |
| 30 |
#include <vector> |
31 |
#include <vector> |
| 31 |
|
32 |
|
|
Lines 489-496
GlobalRouter::GetRouterId (void) const
|
Link Here
|
|---|
|
| 489 |
} |
490 |
} |
| 490 |
|
491 |
|
| 491 |
// |
492 |
// |
| 492 |
// Go out and discover any adjacent routers and build the Link State |
493 |
// DiscoverLSAs is called on all nodes in the system that have a GlobalRouter |
| 493 |
// Advertisements that reflect them and their associated networks. |
494 |
// interface aggregated. We need to go out and discover any adjacent routers |
|
|
495 |
// and build the Link State Advertisements that reflect them and their associated |
| 496 |
// networks. |
| 494 |
// |
497 |
// |
| 495 |
uint32_t |
498 |
uint32_t |
| 496 |
GlobalRouter::DiscoverLSAs (void) |
499 |
GlobalRouter::DiscoverLSAs (void) |
|
Lines 501-573
GlobalRouter::DiscoverLSAs (void)
|
Link Here
|
|---|
|
| 501 |
NS_LOG_LOGIC ("For node " << node->GetId () ); |
504 |
NS_LOG_LOGIC ("For node " << node->GetId () ); |
| 502 |
|
505 |
|
| 503 |
ClearLSAs (); |
506 |
ClearLSAs (); |
| 504 |
// |
|
|
| 505 |
// While building the router-LSA, keep a list of those NetDevices for |
| 506 |
// which I am the designated router and need to later build a NetworkLSA |
| 507 |
// |
| 508 |
std::list<Ptr<NetDevice> > listOfDRInterfaces; |
| 509 |
|
507 |
|
| 510 |
// |
508 |
// |
| 511 |
// We're aggregated to a node. We need to ask the node for a pointer to its |
509 |
// While building the Router-LSA, keep a list of those NetDevices for |
| 512 |
// Ipv4 interface. This is where the information regarding the attached |
510 |
// which the current node is the designated router and we will later build |
| 513 |
// interfaces lives. If we're a router, we had better have an Ipv4 interface. |
511 |
// a NetworkLSA for. |
| 514 |
// |
512 |
// |
|
|
513 |
NetDeviceContainer c; |
| 514 |
|
| 515 |
// |
| 516 |
// We're aggregated to a node. We need to ask the node for a pointer to its |
| 517 |
// Ipv4 interface. This is where the information regarding the attached |
| 518 |
// interfaces lives. If we're a router, we had better have an Ipv4 interface. |
| 519 |
// |
| 515 |
Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> (); |
520 |
Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> (); |
| 516 |
NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed"); |
521 |
NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::DiscoverLSAs (): GetObject for <Ipv4> interface failed"); |
| 517 |
// |
522 |
|
| 518 |
// Each node is a router and so originates a Router-LSA |
523 |
// |
| 519 |
// |
524 |
// Every router node originates a Router-LSA |
|
|
525 |
// |
| 520 |
GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; |
526 |
GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; |
| 521 |
pLSA->SetLSType (GlobalRoutingLSA::RouterLSA); |
527 |
pLSA->SetLSType (GlobalRoutingLSA::RouterLSA); |
| 522 |
pLSA->SetLinkStateId (m_routerId); |
528 |
pLSA->SetLinkStateId (m_routerId); |
| 523 |
pLSA->SetAdvertisingRouter (m_routerId); |
529 |
pLSA->SetAdvertisingRouter (m_routerId); |
| 524 |
pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); |
530 |
pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); |
| 525 |
|
531 |
|
| 526 |
// |
532 |
// |
| 527 |
// Ask the node for the number of net devices attached. This isn't necessarily |
533 |
// Ask the node for the number of net devices attached. This isn't necessarily |
| 528 |
// equal to the number of links to adjacent nodes (other routers) as the number |
534 |
// equal to the number of links to adjacent nodes (other routers) as the number |
| 529 |
// of devices may include those for stub networks (e.g., ethernets, etc.) and |
535 |
// of devices may include those for stub networks (e.g., ethernets, etc.) and |
| 530 |
// bridge devices also take up an "extra" net device. |
536 |
// bridge devices also take up an "extra" net device. |
| 531 |
// |
537 |
// |
| 532 |
uint32_t numDevices = node->GetNDevices(); |
538 |
uint32_t numDevices = node->GetNDevices(); |
| 533 |
NS_LOG_LOGIC ("*************************"); |
|
|
| 534 |
NS_LOG_LOGIC ("numDevices = " << numDevices); |
| 535 |
|
| 536 |
// |
| 537 |
// There are two broad classes of devices: bridges in combination with the |
| 538 |
// devices they bridge and everything else. We need to first discover all of |
| 539 |
// the "everything else" class of devices. |
| 540 |
// |
| 541 |
// To do this, we wander through all of the devices on the node looking for |
| 542 |
// bridge net devices. We then add any net devices associated with each bridge |
| 543 |
// to a list of bridged devices. These devices will be treated as a special |
| 544 |
// case later. |
| 545 |
// |
| 546 |
std::vector<Ptr<NetDevice> > bridgedDevices; |
| 547 |
|
| 548 |
for (uint32_t i = 0; i < numDevices; ++i) |
| 549 |
{ |
| 550 |
Ptr<NetDevice> nd = node->GetDevice(i); |
| 551 |
|
| 552 |
if (nd->IsBridge ()) |
| 553 |
{ |
| 554 |
NS_LOG_LOGIC ("**** Net device " << nd << "is a bridge"); |
| 555 |
// |
| 556 |
// XXX There is only one kind of bridge device so far. We agreed to |
| 557 |
// assume that it is Gustavo's learning bridge until there is a need |
| 558 |
// to deal with another. At that time, we'll have to break out a |
| 559 |
// bridge interface. |
| 560 |
// |
| 561 |
Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> (); |
| 562 |
NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed"); |
| 563 |
|
| 564 |
for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j) |
| 565 |
{ |
| 566 |
NS_LOG_LOGIC ("**** Net device " << bnd << "is a bridged device"); |
| 567 |
bridgedDevices.push_back (bnd->GetBridgePort (j)); |
| 568 |
} |
| 569 |
} |
| 570 |
} |
| 571 |
|
539 |
|
| 572 |
// |
540 |
// |
| 573 |
// Iterate through the devices on the node and walk the channel to see what's |
541 |
// Iterate through the devices on the node and walk the channel to see what's |
|
Lines 576-602
GlobalRouter::DiscoverLSAs (void)
|
Link Here
|
|---|
|
| 576 |
for (uint32_t i = 0; i < numDevices; ++i) |
544 |
for (uint32_t i = 0; i < numDevices; ++i) |
| 577 |
{ |
545 |
{ |
| 578 |
Ptr<NetDevice> ndLocal = node->GetDevice(i); |
546 |
Ptr<NetDevice> ndLocal = node->GetDevice(i); |
| 579 |
// |
|
|
| 580 |
// If the device in question is on our list of bridged devices, then we |
| 581 |
// just ignore it. It will be dealt with correctly when we probe the |
| 582 |
// bridge device it belongs to. It is the case that the bridge code |
| 583 |
// assumes that bridged devices must not have IP interfaces, and so it |
| 584 |
// may actually sufficient to perform the test for IP interface below, |
| 585 |
// but that struck me as too indirect a condition. |
| 586 |
// |
| 587 |
for (uint32_t j = 0; j < bridgedDevices.size (); ++j) |
| 588 |
{ |
| 589 |
if (ndLocal == bridgedDevices[j]) |
| 590 |
{ |
| 591 |
NS_LOG_LOGIC ("**** Skipping Bridged Device"); |
| 592 |
|
| 593 |
continue; |
| 594 |
} |
| 595 |
} |
| 596 |
|
547 |
|
| 597 |
// |
548 |
// |
| 598 |
// Check to see if the net device we just got has a corresponding IP |
549 |
// Check to see if the net device we just got has a corresponding IP |
| 599 |
// interface (could be a pure L2 NetDevice that is not a bridge). |
550 |
// interface (could be a pure L2 NetDevice). |
| 600 |
// |
551 |
// |
| 601 |
bool isIp = false; |
552 |
bool isIp = false; |
| 602 |
for (uint32_t i = 0; i < ipv4Local->GetNInterfaces (); ++i ) |
553 |
for (uint32_t i = 0; i < ipv4Local->GetNInterfaces (); ++i ) |
|
Lines 614-883
GlobalRouter::DiscoverLSAs (void)
|
Link Here
|
|---|
|
| 614 |
continue; |
565 |
continue; |
| 615 |
} |
566 |
} |
| 616 |
|
567 |
|
| 617 |
// |
568 |
// |
| 618 |
// We have a net device that we need to check out. If it suports broadcast and |
569 |
// We have a net device that we need to check out. If it suports |
| 619 |
// is not a point-point link, then it will be either a stub network or a transit |
570 |
// broadcast and is not a point-point link, then it will be either a stub |
| 620 |
// network depending on the number of routers. |
571 |
// network or a transit network depending on the number of routers on |
| 621 |
// |
572 |
// the segment. We add the appropriate link record to the LSA. |
|
|
573 |
// |
| 574 |
// If the device is a point to point link, we treat it separately. In |
| 575 |
// that case, there always two link records added. |
| 576 |
// |
| 622 |
if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () ) |
577 |
if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () ) |
| 623 |
{ |
578 |
{ |
| 624 |
NS_LOG_LOGIC ("**** Broadcast link"); |
579 |
NS_LOG_LOGIC ("**** Broadcast link"); |
| 625 |
GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord; |
580 |
ProcessBroadcastLink (ndLocal, pLSA, c); |
| 626 |
// |
|
|
| 627 |
// We need to determine whether we are on a transit or stub network |
| 628 |
// If we find at least one more router on this channel, we are a transit |
| 629 |
// network. If we're the only router, we're on a stub. |
| 630 |
// |
| 631 |
// Now, we have to find the Ipv4 interface whose netdevice is the one we |
| 632 |
// just found. This is still the IP on the local side of the channel. |
| 633 |
// |
| 634 |
uint32_t ifIndexLocal; |
| 635 |
bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); |
| 636 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::DiscoverLSAs (): No interface index associated with device"); |
| 637 |
|
| 638 |
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); |
| 639 |
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); |
| 640 |
NS_LOG_LOGIC ("Working with local address " << addrLocal); |
| 641 |
uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); |
| 642 |
// |
| 643 |
// Check to see if the net device is connected to a channel/network that has |
| 644 |
// another router on it. If there is no other router on the link (but us) then |
| 645 |
// this is a stub network. If we find another router, then what we have here |
| 646 |
// is a transit network. |
| 647 |
// |
| 648 |
if (AnotherRouterOnLink (ndLocal) == false) |
| 649 |
{ |
| 650 |
// |
| 651 |
// This is a net device connected to a stub network |
| 652 |
// |
| 653 |
NS_LOG_LOGIC("**** Router-LSA Stub Network"); |
| 654 |
plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); |
| 655 |
// |
| 656 |
// According to OSPF, the Link ID is the IP network number of |
| 657 |
// the attached network. |
| 658 |
// |
| 659 |
plr->SetLinkId (addrLocal.CombineMask(maskLocal)); |
| 660 |
// |
| 661 |
// and the Link Data is the network mask; converted to Ipv4Address |
| 662 |
// |
| 663 |
Ipv4Address maskLocalAddr; |
| 664 |
maskLocalAddr.Set(maskLocal.Get ()); |
| 665 |
plr->SetLinkData (maskLocalAddr); |
| 666 |
plr->SetMetric (metricLocal); |
| 667 |
pLSA->AddLinkRecord(plr); |
| 668 |
plr = 0; |
| 669 |
continue; |
| 670 |
} |
| 671 |
else |
| 672 |
{ |
| 673 |
// |
| 674 |
// We have multiple routers on a broadcast interface, so this is |
| 675 |
// a transit network. |
| 676 |
// |
| 677 |
NS_LOG_LOGIC ("**** Router-LSA Transit Network"); |
| 678 |
plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork); |
| 679 |
// |
| 680 |
// By definition, the router with the lowest IP address is the |
| 681 |
// designated router for the network. OSPF says that the Link ID |
| 682 |
// gets the IP interface address of the designated router in this |
| 683 |
// case. |
| 684 |
// |
| 685 |
Ipv4Address desigRtr = FindDesignatedRouterForLink (ndLocal); |
| 686 |
if (desigRtr == addrLocal) |
| 687 |
{ |
| 688 |
listOfDRInterfaces.push_back (ndLocal); |
| 689 |
NS_LOG_LOGIC (node->GetId () << " is a DR"); |
| 690 |
} |
| 691 |
plr->SetLinkId (desigRtr); |
| 692 |
// |
| 693 |
// OSPF says that the Link Data is this router's own IP address. |
| 694 |
// |
| 695 |
plr->SetLinkData (addrLocal); |
| 696 |
plr->SetMetric (metricLocal); |
| 697 |
pLSA->AddLinkRecord (plr); |
| 698 |
plr = 0; |
| 699 |
continue; |
| 700 |
} |
| 701 |
} |
581 |
} |
| 702 |
else if (ndLocal->IsPointToPoint () ) |
582 |
else if (ndLocal->IsPointToPoint () ) |
| 703 |
{ |
583 |
{ |
| 704 |
NS_LOG_LOGIC ("**** Router-LSA Point-to-point device"); |
584 |
NS_LOG_LOGIC ("**** Point=to-point link"); |
| 705 |
// |
585 |
ProcessPointToPointLink (ndLocal, pLSA); |
| 706 |
// Now, we have to find the Ipv4 interface whose netdevice is the one we |
|
|
| 707 |
// just found. This is still the IP on the local side of the channel. There |
| 708 |
// is a function to do this used down in the guts of the stack, but it's not |
| 709 |
// exported so we had to whip up an equivalent. |
| 710 |
// |
| 711 |
uint32_t ifIndexLocal; |
| 712 |
bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); |
| 713 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::DiscoverLSAs (): No interface index associated with device"); |
| 714 |
// |
| 715 |
// Now that we have the Ipv4 interface index, we can get the address and mask |
| 716 |
// we need. |
| 717 |
// |
| 718 |
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); |
| 719 |
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); |
| 720 |
NS_LOG_LOGIC ("Working with local address " << addrLocal); |
| 721 |
uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); |
| 722 |
// |
| 723 |
// Now, we're going to walk over to the remote net device on the other end of |
| 724 |
// the point-to-point channel we now know we have. This is where our adjacent |
| 725 |
// router (to use OSPF lingo) is running. |
| 726 |
// |
| 727 |
Ptr<Channel> ch = ndLocal->GetChannel(); |
| 728 |
if (ch == NULL) |
| 729 |
{ |
| 730 |
continue; |
| 731 |
} |
| 732 |
// |
| 733 |
// Get the net device on the other side of the point-to-point channel. |
| 734 |
// |
| 735 |
Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch); |
| 736 |
// |
| 737 |
// The adjacent net device is aggregated to a node. We need to ask that net |
| 738 |
// device for its node, then ask that node for its Ipv4 interface. Note a |
| 739 |
// requirement that nodes on either side of a point-to-point link must have |
| 740 |
// internet stacks. |
| 741 |
// |
| 742 |
Ptr<Node> nodeRemote = ndRemote->GetNode(); |
| 743 |
Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> (); |
| 744 |
NS_ABORT_MSG_UNLESS (ipv4Remote, |
| 745 |
"GlobalRouter::DiscoverLSAs (): GetObject for remote <Ipv4> failed"); |
| 746 |
// |
| 747 |
// Per the OSPF spec, we're going to need the remote router ID, so we might as |
| 748 |
// well get it now. |
| 749 |
// |
| 750 |
// While we're at it, further note the requirement that nodes on either side of |
| 751 |
// a point-to-point link must participateg in global routing and therefore have |
| 752 |
// a GlobalRouter interface aggregated. |
| 753 |
// |
| 754 |
Ptr<GlobalRouter> srRemote = nodeRemote->GetObject<GlobalRouter> (); |
| 755 |
NS_ABORT_MSG_UNLESS(srRemote, |
| 756 |
"GlobalRouter::DiscoverLSAs(): GetObject for remote <GlobalRouter> failed"); |
| 757 |
|
| 758 |
Ipv4Address rtrIdRemote = srRemote->GetRouterId(); |
| 759 |
NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote); |
| 760 |
// |
| 761 |
// Now, just like we did above, we need to get the IP interface index for the |
| 762 |
// net device on the other end of the point-to-point channel. We have yet another |
| 763 |
// assumption that point to point devices are incompatible with bridges and that |
| 764 |
// the remote device must have an associated ip interface. |
| 765 |
// |
| 766 |
uint32_t ifIndexRemote; |
| 767 |
rc = FindIfIndexForDevice(nodeRemote, ndRemote, ifIndexRemote); |
| 768 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::DiscoverLSAs (): No interface index associated with remote device"); |
| 769 |
// |
| 770 |
// Now that we have the Ipv4 interface, we can get the (remote) address and |
| 771 |
// mask we need. |
| 772 |
// |
| 773 |
Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote); |
| 774 |
Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote); |
| 775 |
NS_LOG_LOGIC ("Working with remote address " << addrRemote); |
| 776 |
// |
| 777 |
// Now we can fill out the link records for this link. There are always two |
| 778 |
// link records; the first is a point-to-point record describing the link and |
| 779 |
// the second is a stub network record with the network number. |
| 780 |
// |
| 781 |
GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord; |
| 782 |
plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint); |
| 783 |
plr->SetLinkId (rtrIdRemote); |
| 784 |
plr->SetLinkData (addrLocal); |
| 785 |
plr->SetMetric (metricLocal); |
| 786 |
pLSA->AddLinkRecord (plr); |
| 787 |
plr = 0; |
| 788 |
|
| 789 |
plr = new GlobalRoutingLinkRecord; |
| 790 |
plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); |
| 791 |
plr->SetLinkId (addrRemote); |
| 792 |
plr->SetLinkData (Ipv4Address(maskRemote.Get())); // Frown |
| 793 |
plr->SetMetric (metricLocal); |
| 794 |
pLSA->AddLinkRecord (plr); |
| 795 |
plr = 0; |
| 796 |
} |
586 |
} |
| 797 |
else |
587 |
else |
| 798 |
{ |
588 |
{ |
| 799 |
NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type"); |
589 |
NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type"); |
| 800 |
} |
590 |
} |
| 801 |
} |
591 |
} |
| 802 |
// |
592 |
|
| 803 |
// The LSA goes on a list of LSAs in case we want to begin exporting other |
593 |
NS_LOG_LOGIC ("========== LSA for node " << node->GetId () << " =========="); |
| 804 |
// kinds of advertisements (than Router LSAs). |
594 |
NS_LOG_LOGIC (*pLSA); |
| 805 |
// |
|
|
| 806 |
m_LSAs.push_back (pLSA); |
595 |
m_LSAs.push_back (pLSA); |
| 807 |
NS_LOG_LOGIC ("========== Link State Advertisement for node " << node->GetId () << " =========="); |
596 |
pLSA = 0; |
| 808 |
NS_LOG_LOGIC (*pLSA); |
|
|
| 809 |
|
597 |
|
| 810 |
// |
598 |
// |
| 811 |
// Now, determine whether we need to build a NetworkLSA. This is the case if |
599 |
// Now, determine whether we need to build a NetworkLSA. This is the case if |
| 812 |
// we found at least one designated router. |
600 |
// we found at least one designated router. |
| 813 |
// |
601 |
// |
| 814 |
if (listOfDRInterfaces.size () > 0) |
602 |
uint32_t nDesignatedRouters = c.GetN (); |
|
|
603 |
if (nDesignatedRouters > 0) |
| 815 |
{ |
604 |
{ |
| 816 |
NS_LOG_LOGIC ("Build Network LSA"); |
605 |
NS_LOG_LOGIC ("Build Network LSAs"); |
| 817 |
for (std::list<Ptr<NetDevice> >::iterator i = listOfDRInterfaces.begin (); |
606 |
BuildNetworkLSAs (c); |
| 818 |
i != listOfDRInterfaces.end (); i++) |
|
|
| 819 |
{ |
| 820 |
// |
| 821 |
// Build one NetworkLSA for each net device talking to a netwok that we are the |
| 822 |
// designated router for. |
| 823 |
// |
| 824 |
Ptr<NetDevice> ndLocal = *i; |
| 825 |
|
| 826 |
uint32_t ifIndexLocal; |
| 827 |
bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); |
| 828 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::DiscoverLSAs (): No interface index associated with device"); |
| 829 |
|
| 830 |
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); |
| 831 |
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); |
| 832 |
|
| 833 |
GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; |
| 834 |
pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA); |
| 835 |
pLSA->SetLinkStateId (addrLocal); |
| 836 |
pLSA->SetAdvertisingRouter (m_routerId); |
| 837 |
pLSA->SetNetworkLSANetworkMask (maskLocal); |
| 838 |
pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); |
| 839 |
// |
| 840 |
// Build a list of AttachedRouters by walking the devices in the channel |
| 841 |
// and, if we find a node with a GlobalRouter interface and an IPv4 |
| 842 |
// interface associated with that device, we call it an attached router. |
| 843 |
// |
| 844 |
Ptr<Channel> ch = ndLocal->GetChannel(); |
| 845 |
uint32_t nDevices = ch->GetNDevices(); |
| 846 |
NS_ASSERT (nDevices); |
| 847 |
for (uint32_t i = 0; i < nDevices; i++) |
| 848 |
{ |
| 849 |
Ptr<NetDevice> tempNd = ch->GetDevice (i); |
| 850 |
NS_ASSERT (tempNd); |
| 851 |
Ptr<Node> tempNode = tempNd->GetNode (); |
| 852 |
// |
| 853 |
// Does the node in question have a GlobalRouter interface? If not it can |
| 854 |
// hardly be considered an attached router. |
| 855 |
// |
| 856 |
Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter> (); |
| 857 |
if (rtr == 0) |
| 858 |
{ |
| 859 |
continue; |
| 860 |
} |
| 861 |
|
| 862 |
// |
| 863 |
// Does the attached node have an ipv4 interface for the device we're probing? |
| 864 |
// If not, it can't play router. |
| 865 |
// |
| 866 |
uint32_t tempIfIndex; |
| 867 |
if (FindIfIndexForDevice (tempNode, tempNd, tempIfIndex)) |
| 868 |
{ |
| 869 |
Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> (); |
| 870 |
NS_ASSERT (tempIpv4); |
| 871 |
Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); |
| 872 |
pLSA->AddAttachedRouter (tempAddr); |
| 873 |
} |
| 874 |
} |
| 875 |
m_LSAs.push_back (pLSA); |
| 876 |
NS_LOG_LOGIC (*pLSA); |
| 877 |
} |
| 878 |
} |
607 |
} |
| 879 |
|
608 |
|
| 880 |
return m_LSAs.size (); |
609 |
return m_LSAs.size (); |
|
|
610 |
} |
| 611 |
|
| 612 |
void |
| 613 |
GlobalRouter::ProcessBroadcastLink (Ptr<NetDevice> nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c) |
| 614 |
{ |
| 615 |
NS_LOG_FUNCTION (nd << pLSA << &c); |
| 616 |
|
| 617 |
GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord; |
| 618 |
NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessBroadcastLink(): Can't alloc link record"); |
| 619 |
|
| 620 |
// |
| 621 |
// We have some preliminaries to do to get enough information to proceed. |
| 622 |
// This information we need comes from the internet stack, so notice that |
| 623 |
// there is an implied assumption that global routing is only going to |
| 624 |
// work with devices attached to the internet stack (have an ipv4 interface |
| 625 |
// associated to them. |
| 626 |
// |
| 627 |
Ptr<Node> node = nd->GetNode (); |
| 628 |
|
| 629 |
uint32_t ifIndexLocal; |
| 630 |
bool rc = FindIfIndexForDevice(node, nd, ifIndexLocal); |
| 631 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessBroadcastLink(): No interface index associated with device"); |
| 632 |
|
| 633 |
Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> (); |
| 634 |
NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBroadcastLink (): GetObject for <Ipv4> interface failed"); |
| 635 |
|
| 636 |
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); |
| 637 |
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); |
| 638 |
NS_LOG_LOGIC ("Working with local address " << addrLocal); |
| 639 |
uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); |
| 640 |
|
| 641 |
// |
| 642 |
// Check to see if the net device is connected to a channel/network that has |
| 643 |
// another router on it. If there is no other router on the link (but us) then |
| 644 |
// this is a stub network. If we find another router, then what we have here |
| 645 |
// is a transit network. |
| 646 |
// |
| 647 |
if (AnotherRouterOnLink (nd) == false) |
| 648 |
{ |
| 649 |
// |
| 650 |
// This is a net device connected to a stub network |
| 651 |
// |
| 652 |
NS_LOG_LOGIC("**** Router-LSA Stub Network"); |
| 653 |
plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); |
| 654 |
|
| 655 |
// |
| 656 |
// According to OSPF, the Link ID is the IP network number of |
| 657 |
// the attached network. |
| 658 |
// |
| 659 |
plr->SetLinkId (addrLocal.CombineMask(maskLocal)); |
| 660 |
|
| 661 |
// |
| 662 |
// and the Link Data is the network mask; converted to Ipv4Address |
| 663 |
// |
| 664 |
Ipv4Address maskLocalAddr; |
| 665 |
maskLocalAddr.Set(maskLocal.Get ()); |
| 666 |
plr->SetLinkData (maskLocalAddr); |
| 667 |
plr->SetMetric (metricLocal); |
| 668 |
pLSA->AddLinkRecord(plr); |
| 669 |
plr = 0; |
| 670 |
} |
| 671 |
else |
| 672 |
{ |
| 673 |
// |
| 674 |
// We have multiple routers on a broadcast interface, so this is |
| 675 |
// a transit network. |
| 676 |
// |
| 677 |
NS_LOG_LOGIC ("**** Router-LSA Transit Network"); |
| 678 |
plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork); |
| 679 |
|
| 680 |
// |
| 681 |
// By definition, the router with the lowest IP address is the |
| 682 |
// designated router for the network. OSPF says that the Link ID |
| 683 |
// gets the IP interface address of the designated router in this |
| 684 |
// case. |
| 685 |
// |
| 686 |
Ipv4Address desigRtr = FindDesignatedRouterForLink (nd); |
| 687 |
if (desigRtr == addrLocal) |
| 688 |
{ |
| 689 |
c.Add (nd); |
| 690 |
NS_LOG_LOGIC ("Node " << node->GetId () << " elected a designated router"); |
| 691 |
} |
| 692 |
plr->SetLinkId (desigRtr); |
| 693 |
|
| 694 |
// |
| 695 |
// OSPF says that the Link Data is this router's own IP address. |
| 696 |
// |
| 697 |
plr->SetLinkData (addrLocal); |
| 698 |
plr->SetMetric (metricLocal); |
| 699 |
pLSA->AddLinkRecord (plr); |
| 700 |
plr = 0; |
| 701 |
} |
| 702 |
} |
| 703 |
|
| 704 |
void |
| 705 |
GlobalRouter::ProcessPointToPointLink (Ptr<NetDevice> ndLocal, GlobalRoutingLSA *pLSA) |
| 706 |
{ |
| 707 |
NS_LOG_FUNCTION (ndLocal << pLSA); |
| 708 |
|
| 709 |
// |
| 710 |
// We have some preliminaries to do to get enough information to proceed. |
| 711 |
// This information we need comes from the internet stack, so notice that |
| 712 |
// there is an implied assumption that global routing is only going to |
| 713 |
// work with devices attached to the internet stack (have an ipv4 interface |
| 714 |
// associated to them. |
| 715 |
// |
| 716 |
Ptr<Node> nodeLocal = ndLocal->GetNode (); |
| 717 |
|
| 718 |
uint32_t ifIndexLocal; |
| 719 |
bool rc = FindIfIndexForDevice(nodeLocal, ndLocal, ifIndexLocal); |
| 720 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device"); |
| 721 |
|
| 722 |
Ptr<Ipv4> ipv4Local = nodeLocal->GetObject<Ipv4> (); |
| 723 |
NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed"); |
| 724 |
|
| 725 |
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); |
| 726 |
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); |
| 727 |
NS_LOG_LOGIC ("Working with local address " << addrLocal); |
| 728 |
uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); |
| 729 |
|
| 730 |
// |
| 731 |
// Now, we're going to walk over to the remote net device on the other end of |
| 732 |
// the point-to-point channel we know we have. This is where our adjacent |
| 733 |
// router (to use OSPF lingo) is running. |
| 734 |
// |
| 735 |
Ptr<Channel> ch = ndLocal->GetChannel(); |
| 736 |
|
| 737 |
// |
| 738 |
// Get the net device on the other side of the point-to-point channel. |
| 739 |
// |
| 740 |
Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch); |
| 741 |
|
| 742 |
// |
| 743 |
// The adjacent net device is aggregated to a node. We need to ask that net |
| 744 |
// device for its node, then ask that node for its Ipv4 interface. Note a |
| 745 |
// requirement that nodes on either side of a point-to-point link must have |
| 746 |
// internet stacks; and an assumption that point-to-point links are incompatible |
| 747 |
// with bridging. |
| 748 |
// |
| 749 |
Ptr<Node> nodeRemote = ndRemote->GetNode(); |
| 750 |
Ptr<Ipv4> ipv4Remote = nodeRemote->GetObject<Ipv4> (); |
| 751 |
NS_ABORT_MSG_UNLESS (ipv4Remote, |
| 752 |
"GlobalRouter::ProcessPointToPointLink(): GetObject for remote <Ipv4> failed"); |
| 753 |
|
| 754 |
// |
| 755 |
// Further note the requirement that nodes on either side of a point-to-point |
| 756 |
// link must participate in global routing and therefore have a GlobalRouter |
| 757 |
// interface aggregated. |
| 758 |
// |
| 759 |
Ptr<GlobalRouter> rtrRemote = nodeRemote->GetObject<GlobalRouter> (); |
| 760 |
NS_ABORT_MSG_UNLESS(rtrRemote, |
| 761 |
"GlobalRouter::ProcessPointToPointLinks(): GetObject for remote <GlobalRouter> failed"); |
| 762 |
|
| 763 |
// |
| 764 |
// We're going to need the remote router ID, so we might as well get it now. |
| 765 |
// |
| 766 |
Ipv4Address rtrIdRemote = rtrRemote->GetRouterId(); |
| 767 |
NS_LOG_LOGIC ("Working with remote router " << rtrIdRemote); |
| 768 |
|
| 769 |
// |
| 770 |
// Now, just like we did above, we need to get the IP interface index for the |
| 771 |
// net device on the other end of the point-to-point channel. |
| 772 |
// |
| 773 |
uint32_t ifIndexRemote; |
| 774 |
rc = FindIfIndexForDevice(nodeRemote, ndRemote, ifIndexRemote); |
| 775 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with remote device"); |
| 776 |
|
| 777 |
// |
| 778 |
// Now that we have the Ipv4 interface, we can get the (remote) address and |
| 779 |
// mask we need. |
| 780 |
// |
| 781 |
Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote); |
| 782 |
Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote); |
| 783 |
NS_LOG_LOGIC ("Working with remote address " << addrRemote); |
| 784 |
|
| 785 |
// |
| 786 |
// Now we can fill out the link records for this link. There are always two |
| 787 |
// link records; the first is a point-to-point record describing the link and |
| 788 |
// the second is a stub network record with the network number. |
| 789 |
// |
| 790 |
GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord; |
| 791 |
NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record"); |
| 792 |
plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint); |
| 793 |
plr->SetLinkId (rtrIdRemote); |
| 794 |
plr->SetLinkData (addrLocal); |
| 795 |
plr->SetMetric (metricLocal); |
| 796 |
pLSA->AddLinkRecord (plr); |
| 797 |
plr = 0; |
| 798 |
|
| 799 |
plr = new GlobalRoutingLinkRecord; |
| 800 |
NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record"); |
| 801 |
plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); |
| 802 |
plr->SetLinkId (addrRemote); |
| 803 |
plr->SetLinkData (Ipv4Address(maskRemote.Get())); // Frown |
| 804 |
plr->SetMetric (metricLocal); |
| 805 |
pLSA->AddLinkRecord (plr); |
| 806 |
plr = 0; |
| 807 |
} |
| 808 |
|
| 809 |
void |
| 810 |
GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c) |
| 811 |
{ |
| 812 |
NS_LOG_FUNCTION (&c); |
| 813 |
|
| 814 |
uint32_t nDesignatedRouters = c.GetN (); |
| 815 |
|
| 816 |
for (uint32_t i = 0; i < nDesignatedRouters; ++i) |
| 817 |
{ |
| 818 |
// |
| 819 |
// Build one NetworkLSA for each net device talking to a network that we are the |
| 820 |
// designated router for. These devices are in the provided container. |
| 821 |
// |
| 822 |
Ptr<NetDevice> ndLocal = c.Get (i); |
| 823 |
Ptr<Node> node = ndLocal->GetNode (); |
| 824 |
|
| 825 |
uint32_t ifIndexLocal; |
| 826 |
bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); |
| 827 |
NS_ABORT_MSG_IF (rc == false, "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device"); |
| 828 |
|
| 829 |
Ptr<Ipv4> ipv4Local = node->GetObject<Ipv4> (); |
| 830 |
NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for <Ipv4> interface failed"); |
| 831 |
|
| 832 |
Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); |
| 833 |
Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); |
| 834 |
|
| 835 |
GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; |
| 836 |
NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record"); |
| 837 |
|
| 838 |
pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA); |
| 839 |
pLSA->SetLinkStateId (addrLocal); |
| 840 |
pLSA->SetAdvertisingRouter (m_routerId); |
| 841 |
pLSA->SetNetworkLSANetworkMask (maskLocal); |
| 842 |
pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); |
| 843 |
|
| 844 |
// |
| 845 |
// Build a list of AttachedRouters by walking the devices in the channel |
| 846 |
// and, if we find a node with a GlobalRouter interface and an IPv4 |
| 847 |
// interface associated with that device, we call it an attached router. |
| 848 |
// |
| 849 |
Ptr<Channel> ch = ndLocal->GetChannel(); |
| 850 |
uint32_t nDevices = ch->GetNDevices(); |
| 851 |
NS_ASSERT (nDevices); |
| 852 |
|
| 853 |
for (uint32_t i = 0; i < nDevices; i++) |
| 854 |
{ |
| 855 |
Ptr<NetDevice> tempNd = ch->GetDevice (i); |
| 856 |
NS_ASSERT (tempNd); |
| 857 |
Ptr<Node> tempNode = tempNd->GetNode (); |
| 858 |
|
| 859 |
// |
| 860 |
// Does the node in question have a GlobalRouter interface? If not it can |
| 861 |
// hardly be considered an attached router. |
| 862 |
// |
| 863 |
Ptr<GlobalRouter> rtr = tempNode->GetObject<GlobalRouter> (); |
| 864 |
if (rtr == 0) |
| 865 |
{ |
| 866 |
continue; |
| 867 |
} |
| 868 |
|
| 869 |
// |
| 870 |
// Does the attached node have an ipv4 interface for the device we're probing? |
| 871 |
// If not, it can't play router. |
| 872 |
// |
| 873 |
uint32_t tempIfIndex; |
| 874 |
if (FindIfIndexForDevice (tempNode, tempNd, tempIfIndex)) |
| 875 |
{ |
| 876 |
Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> (); |
| 877 |
NS_ASSERT (tempIpv4); |
| 878 |
Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); |
| 879 |
pLSA->AddAttachedRouter (tempAddr); |
| 880 |
} |
| 881 |
} |
| 882 |
m_LSAs.push_back (pLSA); |
| 883 |
pLSA = 0; |
| 884 |
} |
| 881 |
} |
885 |
} |
| 882 |
|
886 |
|
| 883 |
// |
887 |
// |
|
Lines 1026-1036
GlobalRouter::GetLSA (uint32_t n, Global
|
Link Here
|
|---|
|
| 1026 |
// other end. This only makes sense with a point-to-point channel. |
1030 |
// other end. This only makes sense with a point-to-point channel. |
| 1027 |
// |
1031 |
// |
| 1028 |
Ptr<NetDevice> |
1032 |
Ptr<NetDevice> |
| 1029 |
GlobalRouter::GetAdjacent(Ptr<NetDevice> nd, Ptr<Channel> ch) const |
1033 |
GlobalRouter::GetAdjacent (Ptr<NetDevice> nd, Ptr<Channel> ch) const |
| 1030 |
{ |
1034 |
{ |
| 1031 |
NS_LOG_FUNCTION_NOARGS (); |
1035 |
NS_LOG_FUNCTION_NOARGS (); |
| 1032 |
NS_ASSERT_MSG(ch->GetNDevices() == 2, |
1036 |
NS_ASSERT_MSG(ch->GetNDevices() == 2, "GlobalRouter::GetAdjacent (): Channel with other than two devices"); |
| 1033 |
"GlobalRouter::GetAdjacent (): Channel with other than two devices"); |
|
|
| 1034 |
// |
1037 |
// |
| 1035 |
// This is a point to point channel with two endpoints. Get both of them. |
1038 |
// This is a point to point channel with two endpoints. Get both of them. |
| 1036 |
// |
1039 |
// |
|
Lines 1065-1071
GlobalRouter::GetAdjacent(Ptr<NetDevice>
|
Link Here
|
|---|
|
| 1065 |
// is bridged, there will not be an interface associated directly with the device. |
1068 |
// is bridged, there will not be an interface associated directly with the device. |
| 1066 |
// |
1069 |
// |
| 1067 |
bool |
1070 |
bool |
| 1068 |
GlobalRouter::FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd, uint32_t &index) const |
1071 |
GlobalRouter::FindIfIndexForDevice (Ptr<Node> node, Ptr<NetDevice> nd, uint32_t &index) const |
| 1069 |
{ |
1072 |
{ |
| 1070 |
NS_LOG_FUNCTION_NOARGS (); |
1073 |
NS_LOG_FUNCTION_NOARGS (); |
| 1071 |
NS_LOG_LOGIC("For node " << node->GetId () << " for net device " << nd ); |
1074 |
NS_LOG_LOGIC("For node " << node->GetId () << " for net device " << nd ); |
|
Lines 1087-1093
GlobalRouter::FindIfIndexForDevice(Ptr<N
|
Link Here
|
|---|
|
| 1087 |
} |
1090 |
} |
| 1088 |
} |
1091 |
} |
| 1089 |
|
1092 |
|
| 1090 |
NS_LOG_LOGIC ("**** Device " << nd << " has no associated ipv4 index"); |
1093 |
NS_LOG_LOGIC ("**** Device " << nd << " has no associated ipv4 index"); |
|
|
1094 |
return false; |
| 1095 |
} |
| 1096 |
|
| 1097 |
// |
| 1098 |
// Decide whether or not a given net device is being bridged by a BridgeNetDevice. |
| 1099 |
// |
| 1100 |
bool |
| 1101 |
GlobalRouter::IsNetDeviceBridged (Ptr<NetDevice> nd) const |
| 1102 |
{ |
| 1103 |
Ptr<Node> node = nd->GetNode (); |
| 1104 |
uint32_t nDevices = node->GetNDevices(); |
| 1105 |
|
| 1106 |
// |
| 1107 |
// There is no bit on a net device that says it is being bridged, so we have |
| 1108 |
// to look for bridges on the node to which the device is attached. If we |
| 1109 |
// find a bridge, we need to look through its bridge ports (the devices it |
| 1110 |
// bridges) to see if we find the device in question. |
| 1111 |
// |
| 1112 |
for (uint32_t i = 0; i < nDevices; ++i) |
| 1113 |
{ |
| 1114 |
Ptr<NetDevice> nd = node->GetDevice(i); |
| 1115 |
|
| 1116 |
if (nd->IsBridge ()) |
| 1117 |
{ |
| 1118 |
Ptr<BridgeNetDevice> bnd = nd->GetObject<BridgeNetDevice> (); |
| 1119 |
NS_ABORT_MSG_UNLESS (bnd, "GlobalRouter::DiscoverLSAs (): GetObject for <BridgeNetDevice> failed"); |
| 1120 |
|
| 1121 |
for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j) |
| 1122 |
{ |
| 1123 |
if (bnd->GetBridgePort (j) == nd) |
| 1124 |
{ |
| 1125 |
return true; |
| 1126 |
} |
| 1127 |
} |
| 1128 |
} |
| 1129 |
} |
| 1091 |
return false; |
1130 |
return false; |
| 1092 |
} |
1131 |
} |
| 1093 |
|
1132 |
|