View | Details | Raw Unified | Return to bug 667
Collapse All | Expand All

(-)a/src/routing/global-routing/candidate-queue.cc (-21 / +68 lines)
 Lines 16-21    Link Here 
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 */
17
 */
18
18
19
#include <algorithm>
20
#include <iostream>
19
#include "ns3/log.h"
21
#include "ns3/log.h"
20
#include "ns3/assert.h"
22
#include "ns3/assert.h"
21
#include "candidate-queue.h"
23
#include "candidate-queue.h"
 Lines 25-30    Link Here 
25
27
26
namespace ns3 {
28
namespace ns3 {
27
29
30
std::ostream&
31
operator<< (std::ostream& os, const SPFVertex::VertexType& t)
32
{
33
  switch (t)
34
    {
35
    case SPFVertex::VertexRouter:  os << "router"; break;
36
    case SPFVertex::VertexNetwork: os << "network"; break;
37
    default:                       os << "unknown"; break;
38
    };
39
  return os;
40
}
41
42
std::ostream& 
43
operator<< (std::ostream& os, const CandidateQueue& q)
44
{
45
  typedef CandidateQueue::CandidateList_t List_t;
46
  typedef List_t::const_iterator CIter_t;
47
  const CandidateQueue::CandidateList_t& list = q.m_candidates;
48
49
  os << "*** CandidateQueue Begin (<id, distance, LSA-type>) ***" << std::endl;
50
  for (CIter_t iter = list.begin (); iter != list.end (); iter++)
51
    {
52
      os << "<" 
53
         << (*iter)->GetVertexId () << ", " 
54
         << (*iter)->GetDistanceFromRoot () << ", " 
55
         << (*iter)->GetVertexType () << ">" << std::endl;
56
    }
57
  os << "*** CandidateQueue End ***";
58
  return os;
59
}
60
28
CandidateQueue::CandidateQueue()
61
CandidateQueue::CandidateQueue()
29
  : m_candidates ()
62
  : m_candidates ()
30
{
63
{
 Lines 54-70    Link Here 
54
{
87
{
55
  NS_LOG_FUNCTION (this << vNew);
88
  NS_LOG_FUNCTION (this << vNew);
56
89
57
  CandidateList_t::iterator i = m_candidates.begin ();  
90
  CandidateList_t::iterator i = std::upper_bound (
58
91
    m_candidates.begin (), m_candidates.end (), vNew,
59
  for (; i != m_candidates.end (); i++)
92
    &CandidateQueue::CompareSPFVertex
60
    {
93
    );
61
      SPFVertex *v = *i;
94
  m_candidates.insert (i, vNew);
62
      if (vNew->GetDistanceFromRoot () < v->GetDistanceFromRoot ())
63
        {
64
          break;
65
        }
66
    }
67
  m_candidates.insert(i, vNew);
68
}
95
}
69
96
70
  SPFVertex *
97
  SPFVertex *
 Lines 129-146    Link Here 
129
CandidateQueue::Reorder (void)
156
CandidateQueue::Reorder (void)
130
{
157
{
131
  NS_LOG_FUNCTION_NOARGS ();
158
  NS_LOG_FUNCTION_NOARGS ();
132
  std::list<SPFVertex*> temp;
133
159
134
  while (!m_candidates.empty ()) {
160
  m_candidates.sort (&CandidateQueue::CompareSPFVertex);
135
    SPFVertex *v = m_candidates.front ();
161
  NS_LOG_LOGIC ("After reordering the CandidateQueue");
136
    m_candidates.pop_front ();
162
  NS_LOG_LOGIC (*this);
137
    temp.push_back(v);
163
}
138
  }
139
164
140
  while (!temp.empty ()) {
165
/*
141
    Push (temp.front ());
166
 * In this implementation, SPFVertex follows the ordering where
142
    temp.pop_front ();
167
 * a vertex is ranked first if its GetDistanceFromRoot () is smaller;
143
  }
168
 * In case of a tie, NetworkLSA is always ranked before RouterLSA.
169
 *
170
 * This ordering is necessary for implementing ECMP
171
 */
172
bool 
173
CandidateQueue::CompareSPFVertex (const SPFVertex* v1, const SPFVertex* v2)
174
{
175
  NS_LOG_FUNCTION (&v1 << &v2);
176
177
  bool result = false;
178
  if (v1->GetDistanceFromRoot () < v2->GetDistanceFromRoot ())
179
    {  
180
      result = true;
181
    }
182
  else if (v1->GetDistanceFromRoot () == v2->GetDistanceFromRoot ())
183
    {
184
      if (v1->GetVertexType () == SPFVertex::VertexNetwork 
185
          && v2->GetVertexType () == SPFVertex::VertexRouter)
186
        {
187
          result = true;
188
        }
189
    }
190
  return result;
144
}
191
}
145
192
146
} // namespace ns3
193
} // namespace ns3
(-)a/src/routing/global-routing/candidate-queue.h (+12 lines)
 Lines 178-186    Link Here 
178
 * \param sr object to assign
178
 * \param sr object to assign
179
 */
179
 */
180
  CandidateQueue& operator= (CandidateQueue& sr);
180
  CandidateQueue& operator= (CandidateQueue& sr);
181
/**
182
 * \brief return true if v1 < v2
183
 *
184
 * SPFVertexes are added into the queue according to the ordering
185
 * defined by this method. If v1 should be popped before v2, this 
186
 * method return true; false otherwise
187
 *
188
 * \return True if v1 should be popped before v2; false otherwise
189
 */
190
  static bool CompareSPFVertex (const SPFVertex* v1, const SPFVertex* v2);
181
191
182
  typedef std::list<SPFVertex*> CandidateList_t;
192
  typedef std::list<SPFVertex*> CandidateList_t;
183
  CandidateList_t m_candidates;
193
  CandidateList_t m_candidates;
194
195
  friend std::ostream& operator<< (std::ostream& os, const CandidateQueue& q);
184
};
196
};
185
197
186
} // namespace ns3
198
} // namespace ns3
(-)a/src/routing/global-routing/global-route-manager-impl.cc (-104 / +356 lines)
 Lines 25-30    Link Here 
25
#include <utility>
25
#include <utility>
26
#include <vector>
26
#include <vector>
27
#include <queue>
27
#include <queue>
28
#include <algorithm>
29
#include <iostream>
28
#include "ns3/assert.h"
30
#include "ns3/assert.h"
29
#include "ns3/fatal-error.h"
31
#include "ns3/fatal-error.h"
30
#include "ns3/log.h"
32
#include "ns3/log.h"
 Lines 41-46    Link Here 
41
43
42
namespace ns3 {
44
namespace ns3 {
43
45
46
std::ostream& 
47
operator<< (std::ostream& os, const SPFVertex::NodeExit_t& exit)
48
{
49
  os << "(" << exit.first << " ," << exit.second << ")";
50
  return os;
51
}
52
53
std::ostream& 
54
operator<< (std::ostream& os, const SPFVertex::ListOfSPFVertex_t& vs)
55
{
56
  typedef SPFVertex::ListOfSPFVertex_t::const_iterator CIter_t;
57
  os << "{";
58
  for (CIter_t iter = vs.begin (); iter != vs.end ();)
59
    {
60
      os << (*iter)->m_vertexId;
61
      if (++iter != vs.end ()) 
62
        {
63
          os << ", ";
64
        }
65
      else 
66
        { 
67
          break;
68
        }
69
    }
70
  os << "}";
71
  return os;
72
}
73
44
// ---------------------------------------------------------------------------
74
// ---------------------------------------------------------------------------
45
//
75
//
46
// SPFVertex Implementation
76
// SPFVertex Implementation
 Lines 54-60    Link Here 
54
  m_distanceFromRoot (SPF_INFINITY), 
84
  m_distanceFromRoot (SPF_INFINITY), 
55
  m_rootOif (SPF_INFINITY),
85
  m_rootOif (SPF_INFINITY),
56
  m_nextHop ("0.0.0.0"),
86
  m_nextHop ("0.0.0.0"),
57
  m_parent (0),
87
  m_parents (),
58
  m_children (),
88
  m_children (),
59
  m_vertexProcessed (false)
89
  m_vertexProcessed (false)
60
{
90
{
 Lines 67-77    Link Here 
67
  m_distanceFromRoot (SPF_INFINITY), 
97
  m_distanceFromRoot (SPF_INFINITY), 
68
  m_rootOif (SPF_INFINITY),
98
  m_rootOif (SPF_INFINITY),
69
  m_nextHop ("0.0.0.0"),
99
  m_nextHop ("0.0.0.0"),
70
  m_parent (0),
100
  m_parents (),
71
  m_children (),
101
  m_children (),
72
  m_vertexProcessed (false)
102
  m_vertexProcessed (false)
73
{
103
{
74
  NS_LOG_FUNCTION_NOARGS ();
104
  NS_LOG_FUNCTION_NOARGS ();
105
75
  if (lsa->GetLSType () == GlobalRoutingLSA::RouterLSA) 
106
  if (lsa->GetLSType () == GlobalRoutingLSA::RouterLSA) 
76
    {
107
    {
77
      NS_LOG_LOGIC ("Setting m_vertexType to VertexRouter");
108
      NS_LOG_LOGIC ("Setting m_vertexType to VertexRouter");
 Lines 86-102    Link Here 
86
117
87
SPFVertex::~SPFVertex ()
118
SPFVertex::~SPFVertex ()
88
{
119
{
89
  NS_LOG_FUNCTION_NOARGS ();
120
  NS_LOG_FUNCTION (m_vertexId);
90
  for ( ListOfSPFVertex_t::iterator i = m_children.begin ();
121
  
91
        i != m_children.end ();
122
  NS_LOG_LOGIC ("Children vertices - " << m_children);
92
        i++)
123
  NS_LOG_LOGIC ("Parent verteices - " << m_parents);
124
125
  // find this node from all its parents and remove the entry of this node
126
  // from all its parents
127
  for (ListOfSPFVertex_t::iterator piter = m_parents.begin (); 
128
      piter != m_parents.end (); 
129
      piter++)
93
    {
130
    {
94
      SPFVertex *p = *i;
131
      // remove the current vertex from its parent's children list. Check
132
      // if the size of the list is reduced, or the child<->parent relation
133
      // is not bidirectional
134
      uint32_t orgCount = (*piter)->m_children.size ();
135
      (*piter)->m_children.remove (this);
136
      uint32_t newCount = (*piter)->m_children.size ();
137
      NS_ASSERT_MSG (orgCount > newCount, "Unable to find the current vertex from its parents --- impossible!");
138
    }
139
140
  // delete children
141
  while (m_children.size () > 0)
142
    {
143
      // pop out children one by one. Some children may disapper 
144
      // when deleting some other children in the list. As a result,
145
      // it is necessary to use pop to walk through all children, instead
146
      // of using iterator.
147
      //
148
      // Note that m_children.pop_front () is not necessary as this
149
      // p is removed from the children list when p is deleted
150
      SPFVertex* p = m_children.front ();
151
      // 'p' == 0, this child is already deleted by its other parent
152
      if (p == 0) continue;
153
      NS_LOG_LOGIC ("Parent vertex-" << m_vertexId << " deleting its child vertex-" << p->GetVertexId ());
95
      delete p;
154
      delete p;
96
      p = 0;
155
      p = 0;
97
      *i = 0;
98
    }
156
    }
99
  m_children.clear ();
157
  m_children.clear ();
158
  // delete parents
159
  m_parents.clear ();
160
  // delete root exit direction
161
  m_ecmpRootExits.clear ();
162
163
  NS_LOG_LOGIC ("Vertex-" << m_vertexId << " completed deleted");
100
}
164
}
101
165
102
  void 
166
  void 
 Lines 155-178    Link Here 
155
  return m_distanceFromRoot;
219
  return m_distanceFromRoot;
156
}
220
}
157
221
158
  void 
222
void 
159
SPFVertex::SetOutgoingInterfaceId (int32_t id)
223
SPFVertex::SetOutgoingInterfaceId (int32_t id)
160
{
224
{
161
  NS_LOG_FUNCTION (id);
225
  NS_LOG_FUNCTION (id);
226
227
  // always maintain only one output interface index when using setter/getter methods
162
  m_rootOif = id;
228
  m_rootOif = id;
163
}
229
}
164
230
165
  uint32_t 
231
uint32_t 
166
SPFVertex::GetOutgoingInterfaceId (void) const
232
SPFVertex::GetOutgoingInterfaceId (void) const
167
{
233
{
168
  NS_LOG_FUNCTION_NOARGS ();
234
  NS_LOG_FUNCTION_NOARGS ();
169
  return m_rootOif;
235
  return m_rootOif;
170
}
236
}
171
237
238
//void 
239
//SPFVertex::MergeOutgoingInterfaceId (const SPFVertex* v)
240
//{
241
//  NS_LOG_FUNCTION (v);
242
//
243
//  NS_LOG_LOGIC ("Before merge, list of root out-going interfaces = " << m_rootOif);
244
//  // combine the two lists first, and then remove any duplicated after
245
//  m_rootOif.insert (m_rootOif.end (), 
246
//    v->m_rootOif.begin (), v->m_rootOif.end ());
247
//  // remove duplication
248
//  m_rootOif.sort ();
249
//  m_rootOif.unique ();
250
//  NS_LOG_LOGIC ("After merge, list of root out-going interfaces = " << m_rootOif);
251
//}
252
172
  void 
253
  void 
173
SPFVertex::SetNextHop (Ipv4Address nextHop)
254
SPFVertex::SetNextHop (Ipv4Address nextHop)
174
{
255
{
175
  NS_LOG_FUNCTION (nextHop);
256
  NS_LOG_FUNCTION (nextHop);
257
258
  // always maintain only one nexthop when using setter/getter methods
176
  m_nextHop = nextHop;
259
  m_nextHop = nextHop;
177
}
260
}
178
261
 Lines 187-203    Link Here 
187
SPFVertex::SetParent (SPFVertex* parent)
270
SPFVertex::SetParent (SPFVertex* parent)
188
{
271
{
189
  NS_LOG_FUNCTION (parent);
272
  NS_LOG_FUNCTION (parent);
190
  m_parent = parent;
273
274
  // always maintain only one parent when using setter/getter methods
275
  m_parents.clear ();
276
  m_parents.push_back (parent);
191
}
277
}
192
278
193
  SPFVertex* 
279
  SPFVertex* 
194
SPFVertex::GetParent (void) const
280
SPFVertex::GetParent (uint32_t i) const
195
{
281
{
196
  NS_LOG_FUNCTION_NOARGS ();
282
  NS_LOG_FUNCTION_NOARGS ();
197
  return m_parent;
283
284
  // If the index i is out-of-range, return 0 and do nothing
285
  if (m_parents.size () <= i)
286
    {
287
      NS_LOG_LOGIC ("Index to SPFVertex's parent is out-of-range.");
288
      return 0;
289
    }
290
  ListOfSPFVertex_t::const_iterator iter = m_parents.begin ();
291
  while (i-- > 0) 
292
    {
293
      iter++;
294
    }
295
  return *iter;
198
}
296
}
199
297
200
  uint32_t 
298
void 
299
SPFVertex::MergeParent (const SPFVertex* v)
300
{
301
  NS_LOG_FUNCTION (v);
302
303
  NS_LOG_LOGIC ("Before merge, list of parents = " << m_parents);
304
  // combine the two lists first, and then remove any duplicated after
305
  m_parents.insert (m_parents.end (), 
306
    v->m_parents.begin (), v->m_parents.end ());
307
  // remove duplication
308
  m_parents.sort ();
309
  m_parents.unique ();
310
  NS_LOG_LOGIC ("After merge, list of parents = " << m_parents);
311
}
312
313
void 
314
SPFVertex::SetRootExitDirection (Ipv4Address nextHop, int32_t id)
315
{
316
  NS_LOG_FUNCTION (nextHop << id);
317
  
318
  // always maintain only one root's exit
319
  m_ecmpRootExits.clear ();
320
  m_ecmpRootExits.push_back (NodeExit_t (nextHop, id));
321
  // update the following in order to be backward compatitable with
322
  // GetNextHop and GetOutgoingInterface methods
323
  m_nextHop = nextHop;
324
  m_rootOif = id;
325
}
326
327
void 
328
SPFVertex::SetRootExitDirection (SPFVertex::NodeExit_t exit)
329
{
330
  NS_LOG_FUNCTION (exit);
331
  SetRootExitDirection (exit.first, exit.second);
332
}
333
334
SPFVertex::NodeExit_t
335
SPFVertex::GetRootExitDirection (uint32_t i) const
336
{
337
  NS_LOG_FUNCTION (i);
338
  typedef ListOfNodeExit_t::const_iterator CIter_t;
339
340
  NS_ASSERT_MSG (i < m_ecmpRootExits.size (), "Index out-of-range when accessing SPFVertex::m_ecmpRootExits!");
341
  CIter_t iter = m_ecmpRootExits.begin ();
342
  while (i-- > 0) {iter++;}
343
344
  return *iter;
345
}
346
347
SPFVertex::NodeExit_t 
348
SPFVertex::GetRootExitDirection () const
349
{
350
  NS_LOG_FUNCTION_NOARGS ();
351
352
  NS_ASSERT_MSG (m_ecmpRootExits.size () <= 1, "Assumed there is at most one exit from the root to this vertex");
353
  return GetRootExitDirection (0);
354
}
355
356
void 
357
SPFVertex::MergeRootExitDirections (const SPFVertex* vertex)
358
{
359
  NS_LOG_FUNCTION (vertex);
360
361
  // obtain the external list of exit directions
362
  //
363
  // Append the external list into 'this' and remove duplication afterward
364
  const ListOfNodeExit_t& extList = vertex->m_ecmpRootExits;
365
  m_ecmpRootExits.insert (m_ecmpRootExits.end (), 
366
    extList.begin(), extList.end ());
367
  m_ecmpRootExits.sort ();
368
  m_ecmpRootExits.unique ();
369
}
370
371
void 
372
SPFVertex::InheritAllRootExitDirections (const SPFVertex* vertex)
373
{
374
  NS_LOG_FUNCTION (vertex);
375
376
  // discard all exit direction currently assoicated with this vertex,
377
  // and copy all the exit directions from the given vertex
378
  if (m_ecmpRootExits.size () > 0)
379
    {
380
      NS_LOG_WARN ("x root exit directions in this vertex are going to be discarded");
381
    }
382
  m_ecmpRootExits.clear ();
383
  m_ecmpRootExits.insert (m_ecmpRootExits.end (), 
384
      vertex->m_ecmpRootExits.begin (), vertex->m_ecmpRootExits.end ());
385
}
386
387
uint32_t 
388
SPFVertex::GetNRootExitDirections () const
389
{
390
  NS_LOG_FUNCTION_NOARGS ();
391
  return m_ecmpRootExits.size ();
392
}
393
394
uint32_t 
201
SPFVertex::GetNChildren (void) const
395
SPFVertex::GetNChildren (void) const
202
{
396
{
203
  NS_LOG_FUNCTION_NOARGS ();
397
  NS_LOG_FUNCTION_NOARGS ();
 Lines 376-382    Link Here 
376
570
377
GlobalRouteManagerImpl::GlobalRouteManagerImpl () 
571
GlobalRouteManagerImpl::GlobalRouteManagerImpl () 
378
: 
572
: 
379
  m_spfroot (0) 
573
  m_spfroot (0)
380
{
574
{
381
  NS_LOG_FUNCTION_NOARGS ();
575
  NS_LOG_FUNCTION_NOARGS ();
382
  m_lsdb = new GlobalRouteManagerLSDB ();
576
  m_lsdb = new GlobalRouteManagerLSDB ();
 Lines 536-541    Link Here 
536
//
730
//
537
// Walk the list of nodes in the system.
731
// Walk the list of nodes in the system.
538
//
732
//
733
  NS_LOG_INFO ("About to start SPF calculation");
539
  NodeList::Iterator listEnd = NodeList::End ();
734
  NodeList::Iterator listEnd = NodeList::End ();
540
  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
735
  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
541
    {
736
    {
 Lines 555-560    Link Here 
555
          SPFCalculate (rtr->GetRouterId ());
750
          SPFCalculate (rtr->GetRouterId ());
556
        }
751
        }
557
    }
752
    }
753
  NS_LOG_INFO ("Finished SPF calculation");
558
}
754
}
559
755
560
//
756
//
 Lines 688-702    Link Here 
688
// Is there already vertex w in candidate list?
884
// Is there already vertex w in candidate list?
689
      if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED)
885
      if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED)
690
        {
886
        {
691
692
// prepare vertex w
693
          w = new SPFVertex (w_lsa);
694
// Calculate nexthop to w
887
// Calculate nexthop to w
695
// We need to figure out how to actually get to the new router represented
888
// We need to figure out how to actually get to the new router represented
696
// by <w>.  This will (among other things) find the next hop address to send
889
// by <w>.  This will (among other things) find the next hop address to send
697
// packets destined for this network to, and also find the outbound interface
890
// packets destined for this network to, and also find the outbound interface
698
// used to forward the packets.
891
// used to forward the packets.
699
//
892
893
// prepare vertex w
894
          w = new SPFVertex (w_lsa);
700
          if (SPFNexthopCalculation (v, w, l, distance))
895
          if (SPFNexthopCalculation (v, w, l, distance))
701
            {
896
            {
702
              w_lsa->SetStatus (GlobalRoutingLSA::LSA_SPF_CANDIDATE);
897
              w_lsa->SetStatus (GlobalRoutingLSA::LSA_SPF_CANDIDATE);
 Lines 710-715    Link Here 
710
                v->GetVertexId () << ", distance: " <<
905
                v->GetVertexId () << ", distance: " <<
711
                w->GetDistanceFromRoot ());
906
                w->GetDistanceFromRoot ());
712
            }
907
            }
908
          else
909
            NS_ASSERT_MSG (0, "SPFNexthopCalculation never " 
910
              << "return false, but it does now!");
713
        }
911
        }
714
      else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE)
912
      else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE)
715
        {
913
        {
 Lines 720-741    Link Here 
720
//
918
//
721
// So, locate the vertex in the candidate queue and take a look at the 
919
// So, locate the vertex in the candidate queue and take a look at the 
722
// distance.
920
// distance.
723
          w = candidate.Find (w_lsa->GetLinkStateId ());
921
724
          if (w->GetDistanceFromRoot () < distance)
922
/* (quagga-0.98.6) W is already on the candidate list; call it cw.
923
* Compare the previously calculated cost (cw->distance)
924
* with the cost we just determined (w->distance) to see
925
* if we've found a shorter path.
926
*/
927
          SPFVertex* cw;
928
          cw = candidate.Find (w_lsa->GetLinkStateId ());
929
          if (cw->GetDistanceFromRoot () < distance)
725
            {
930
            {
726
//
931
//
727
// This is not a shorter path, so don't do anything.
932
// This is not a shorter path, so don't do anything.
728
//
933
//
729
              continue;
934
              continue;
730
            }
935
            }
731
          else if (w->GetDistanceFromRoot () == distance)
936
          else if (cw->GetDistanceFromRoot () == distance)
732
            {
937
            {
733
//
938
//
734
// This path is one with an equal cost.  Do nothing for now -- we're not doing
939
// This path is one with an equal cost.  
735
// equal-cost multipath cases yet.
736
//
940
//
941
              NS_LOG_LOGIC ("Equal cost multiple paths found.");
942
943
// At this point, there are two instances 'w' and 'cw' of the
944
// same vertex, the vertex that is currently being considered
945
// for adding into the shortest path tree. 'w' is the instance
946
// as seen from the root via vertex 'v', and 'cw' is the instance 
947
// as seen from the root via some other vertices other than 'v'.
948
// These two instances are being merged in the following code.
949
// In particular, the parent nodes, the next hops, and the root's
950
// output interfaces of the two instances are being merged.
951
// 
952
// Note that this is functionally equivalent to calling
953
// ospf_nexthop_merge (cw->nexthop, w->nexthop) in quagga-0.98.6
954
// (ospf_spf.c::859), although the detail implementation
955
// is very different from quagga (blame ns3::GlobalRouteManagerImpl)
956
957
// prepare vertex w
958
              w = new SPFVertex (w_lsa);
959
              SPFNexthopCalculation (v, w, l, distance);
960
              cw->MergeRootExitDirections (w);
961
              cw->MergeParent (w);
962
// SPFVertexAddParent (w) is necessary as the destructor of 
963
// SPFVertex checks if the vertex and its parent is linked
964
// bidirectionally
965
              SPFVertexAddParent (w);
966
              delete w;
737
            }
967
            }
738
          else
968
          else // cw->GetDistanceFromRoot () > w->GetDistanceFromRoot ()
739
            {
969
            {
740
// 
970
// 
741
// this path represents a new, lower-cost path to <w> (the vertex we found in
971
// this path represents a new, lower-cost path to <w> (the vertex we found in
 Lines 745-751    Link Here 
745
// N.B. the nexthop_calculation is conditional, if it finds a valid nexthop
975
// N.B. the nexthop_calculation is conditional, if it finds a valid nexthop
746
// it will call spf_add_parents, which will flush the old parents
976
// it will call spf_add_parents, which will flush the old parents
747
//
977
//
748
              if (SPFNexthopCalculation (v, w, l, distance))
978
              if (SPFNexthopCalculation (v, cw, l, distance))
749
                {
979
                {
750
//
980
//
751
// If we've changed the cost to get to the vertex represented by <w>, we 
981
// If we've changed the cost to get to the vertex represented by <w>, we 
 Lines 753-759    Link Here 
753
//
983
//
754
                  candidate.Reorder ();
984
                  candidate.Reorder ();
755
                }
985
                }
756
            } // new lower cost path found   
986
            } // new lower cost path found  
757
        } // end W is already on the candidate list
987
        } // end W is already on the candidate list
758
    } // end loop over the links in V's LSA
988
    } // end loop over the links in V's LSA
759
}
989
}
 Lines 847-866    Link Here 
847
// from the root node to the host represented by vertex <w>, you have to send
1077
// from the root node to the host represented by vertex <w>, you have to send
848
// the packet to the next hop address specified in w->m_nextHop.
1078
// the packet to the next hop address specified in w->m_nextHop.
849
//
1079
//
850
          w->SetNextHop (linkRemote->GetLinkData ());
1080
          Ipv4Address nextHop = linkRemote->GetLinkData ();
851
// 
1081
// 
852
// Now find the outgoing interface corresponding to the point to point link
1082
// Now find the outgoing interface corresponding to the point to point link
853
// from the perspective of <v> -- remember that <l> is the link "from"
1083
// from the perspective of <v> -- remember that <l> is the link "from"
854
// <v> "to" <w>.
1084
// <v> "to" <w>.
855
//
1085
//
856
          w->SetOutgoingInterfaceId (
1086
          uint32_t outIf = FindOutgoingInterfaceId (l->GetLinkData ());
857
            FindOutgoingInterfaceId (l->GetLinkData ()));
1087
1088
          w->SetRootExitDirection (nextHop, outIf);
858
          w->SetDistanceFromRoot (distance);
1089
          w->SetDistanceFromRoot (distance);
859
          w->SetParent (v);
1090
          w->SetParent (v);
860
          NS_LOG_LOGIC ("Next hop from " << 
1091
          NS_LOG_LOGIC ("Next hop from " << 
861
            v->GetVertexId () << " to " << w->GetVertexId () << 
1092
            v->GetVertexId () << " to " << w->GetVertexId () << 
862
            " goes through next hop " << w->GetNextHop () <<
1093
            " goes through next hop " << nextHop <<
863
            " via outgoing interface " << w->GetOutgoingInterfaceId () <<
1094
            " via outgoing interface " << outIf <<
864
            " with distance " << distance);
1095
            " with distance " << distance);
865
        }  // end W is a router vertes
1096
        }  // end W is a router vertes
866
      else 
1097
      else 
 Lines 870-883    Link Here 
870
          GlobalRoutingLSA* w_lsa = w->GetLSA ();
1101
          GlobalRoutingLSA* w_lsa = w->GetLSA ();
871
          NS_ASSERT (w_lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA);
1102
          NS_ASSERT (w_lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA);
872
// Find outgoing interface ID for this network
1103
// Find outgoing interface ID for this network
873
          w->SetOutgoingInterfaceId (
1104
          uint32_t outIf = FindOutgoingInterfaceId (w_lsa->GetLinkStateId (), 
874
            FindOutgoingInterfaceId (w_lsa->GetLinkStateId (), 
1105
            w_lsa->GetNetworkLSANetworkMask () );
875
            w_lsa->GetNetworkLSANetworkMask () ));
1106
// Set the next hop to 0.0.0.0 meaning "not exist"
1107
          Ipv4Address nextHop = Ipv4Address::GetZero ();
1108
          w->SetRootExitDirection (nextHop, outIf);
876
          w->SetDistanceFromRoot (distance);
1109
          w->SetDistanceFromRoot (distance);
877
          w->SetParent (v);
1110
          w->SetParent (v);
878
          NS_LOG_LOGIC ("Next hop from " << 
1111
          NS_LOG_LOGIC ("Next hop from " << 
879
            v->GetVertexId () << " to network " << w->GetVertexId () << 
1112
            v->GetVertexId () << " to network " << w->GetVertexId () << 
880
            " via outgoing interface " << w->GetOutgoingInterfaceId () <<
1113
            " via outgoing interface " << outIf <<
881
            " with distance " << distance);
1114
            " with distance " << distance);
882
          return 1;
1115
          return 1;
883
        }
1116
        }
 Lines 901-918    Link Here 
901
 * use can then be derived from the next hop IP address (or 
1134
 * use can then be derived from the next hop IP address (or 
902
 * it can be inherited from the parent network).
1135
 * it can be inherited from the parent network).
903
 */
1136
 */
904
                w->SetNextHop (linkRemote->GetLinkData ());
1137
                Ipv4Address nextHop = linkRemote->GetLinkData ();
905
                w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
1138
                uint32_t outIf = v->GetRootExitDirection ().second;
1139
                w->SetRootExitDirection (nextHop, outIf);
906
                NS_LOG_LOGIC ("Next hop from " << 
1140
                NS_LOG_LOGIC ("Next hop from " << 
907
                  v->GetVertexId () << " to " << w->GetVertexId () << 
1141
                  v->GetVertexId () << " to " << w->GetVertexId () << 
908
                  " goes through next hop " << w->GetNextHop () <<
1142
                  " goes through next hop " << nextHop <<
909
                  " via outgoing interface " << w->GetOutgoingInterfaceId ());
1143
                  " via outgoing interface " << outIf);
910
            }
1144
            }
911
        }
1145
        }
912
      else 
1146
      else 
913
        {
1147
        {
914
          w->SetNextHop (v->GetNextHop ());
1148
          w->SetRootExitDirection (v->GetRootExitDirection ());
915
          w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
916
        }
1149
        }
917
    }
1150
    }
918
  else 
1151
  else 
 Lines 930-937    Link Here 
930
// (shortest) paths.  So the next hop and outoing interface remain the same
1163
// (shortest) paths.  So the next hop and outoing interface remain the same
931
// (are inherited).
1164
// (are inherited).
932
//
1165
//
933
      w->SetNextHop (v->GetNextHop ());
1166
      w->InheritAllRootExitDirections (v);
934
      w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
935
    }
1167
    }
936
//
1168
//
937
// In all cases, we need valid values for the distance metric and a parent.
1169
// In all cases, we need valid values for the distance metric and a parent.
 Lines 1210-1215    Link Here 
1210
// of the routers found in the Global Router Link Records and added tehm to 
1442
// of the routers found in the Global Router Link Records and added tehm to 
1211
// the candidate list.
1443
// the candidate list.
1212
//
1444
//
1445
      NS_LOG_LOGIC (candidate);
1213
      v = candidate.Pop ();
1446
      v = candidate.Pop ();
1214
      NS_LOG_LOGIC ("Popped vertex " << v->GetVertexId ());
1447
      NS_LOG_LOGIC ("Popped vertex " << v->GetVertexId ());
1215
//
1448
//
 Lines 1228-1235    Link Here 
1228
//
1461
//
1229
// Note that when there is a choice of vertices closest to the root, network
1462
// Note that when there is a choice of vertices closest to the root, network
1230
// vertices must be chosen before router vertices in order to necessarily
1463
// vertices must be chosen before router vertices in order to necessarily
1231
// find all equal-cost paths. We don't do this at this moment, we should add
1464
// find all equal-cost paths. 
1232
// the treatment above codes. -- kunihiro. 
1233
//
1465
//
1234
// RFC2328 16.1. (4). 
1466
// RFC2328 16.1. (4). 
1235
//
1467
//
 Lines 1569-1580    Link Here 
1569
          Ipv4Mask tempmask ("255.255.255.0");
1801
          Ipv4Mask tempmask ("255.255.255.0");
1570
          Ipv4Address tempip = l->GetLinkId ();
1802
          Ipv4Address tempip = l->GetLinkId ();
1571
          tempip = tempip.CombineMask (tempmask);
1803
          tempip = tempip.CombineMask (tempmask);
1572
1573
          NS_LOG_LOGIC (" Node " << node->GetId () <<
1574
            " add route to " << tempip <<
1575
            " with mask " << tempmask <<
1576
            " using next hop " << v->GetNextHop () <<
1577
            " via interface " << v->GetOutgoingInterfaceId ());
1578
//
1804
//
1579
// Here's why we did all of that work.  We're going to add a host route to the
1805
// Here's why we did all of that work.  We're going to add a host route to the
1580
// host address found in the m_linkData field of the point-to-point link
1806
// host address found in the m_linkData field of the point-to-point link
 Lines 1596-1615    Link Here 
1596
            }
1822
            }
1597
          Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1823
          Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1598
          NS_ASSERT (gr);
1824
          NS_ASSERT (gr);
1599
          if (v->GetOutgoingInterfaceId () >= 0)
1825
          // walk through all next-hop-IPs and out-going-interfaces for reaching
1826
          // the stub network gateway 'v' from the root node
1827
          for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
1600
            {
1828
            {
1601
              gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ());
1829
              SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
1602
              NS_LOG_LOGIC ("Node " << node->GetId () <<
1830
              Ipv4Address nextHop = exit.first;
1603
                " add network route to " << tempip <<
1831
              int32_t outIf = exit.second;
1604
                " using next hop " << v->GetNextHop () <<
1832
              if (outIf >= 0)
1605
                " via interface " << v->GetOutgoingInterfaceId ());
1833
                {
1606
            }
1834
                  gr->AddNetworkRouteTo (tempip, tempmask, nextHop, outIf);
1607
          else
1835
                  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1608
            {
1836
                    " add network route to " << tempip <<
1609
              NS_LOG_LOGIC ("Node " << node->GetId () <<
1837
                    " using next hop " << nextHop <<
1610
                " NOT able to add network route to " << tempip <<
1838
                    " via interface " << outIf);
1611
                " using next hop " << v->GetNextHop () <<
1839
                }
1612
                " since outgoing interface id is negative");
1840
              else
1841
                {
1842
                  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1843
                    " NOT able to add network route to " << tempip <<
1844
                    " using next hop " << nextHop <<
1845
                    " since outgoing interface id is negative");
1846
                }
1613
            }
1847
            }
1614
          return;
1848
          return;
1615
        } // if
1849
        } // if
 Lines 1802-1812    Link Here 
1802
                {
2036
                {
1803
                  continue;
2037
                  continue;
1804
                }
2038
                }
1805
1806
              NS_LOG_LOGIC (" Node " << node->GetId () <<
1807
                " add route to " << lr->GetLinkData () <<
1808
                " using next hop " << v->GetNextHop () <<
1809
                " via interface " << v->GetOutgoingInterfaceId ());
1810
//
2039
//
1811
// Here's why we did all of that work.  We're going to add a host route to the
2040
// Here's why we did all of that work.  We're going to add a host route to the
1812
// host address found in the m_linkData field of the point-to-point link
2041
// host address found in the m_linkData field of the point-to-point link
 Lines 1827-1848    Link Here 
1827
                }
2056
                }
1828
              Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
2057
              Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1829
              NS_ASSERT (gr);
2058
              NS_ASSERT (gr);
1830
              if (v->GetOutgoingInterfaceId () >= 0)
2059
              // walk through all available exit directions due to ECMP,
1831
                {
2060
              // and add host route for each of the exit direction toward
1832
                  gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (),
2061
              // the vertex 'v'
1833
                    v->GetOutgoingInterfaceId ());
2062
              for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
1834
                  NS_LOG_LOGIC ("Node " << node->GetId () <<
2063
              {
1835
                    " adding host route to " << lr->GetLinkData () <<
2064
                SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
1836
                    " using next hop " << v->GetNextHop () <<
2065
                Ipv4Address nextHop = exit.first;
1837
                    " and outgoing interface " << v->GetOutgoingInterfaceId ());
2066
                int32_t outIf = exit.second;
1838
                }
2067
                if (outIf >= 0)
1839
              else
2068
                  {
1840
                {
2069
                    gr->AddHostRouteTo (lr->GetLinkData (), nextHop,
1841
                  NS_LOG_LOGIC ("Node " << node->GetId () <<
2070
                      outIf);
1842
                    " NOT able to add host route to " << lr->GetLinkData () <<
2071
                    NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1843
                    " using next hop " << v->GetNextHop () <<
2072
                      " adding host route to " << lr->GetLinkData () <<
1844
                    " since outgoing interface id is negative");
2073
                      " using next hop " << nextHop <<
1845
                }
2074
                      " and outgoing interface " << outIf);
2075
                  }
2076
                else
2077
                  {
2078
                    NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
2079
                      " NOT able to add host route to " << lr->GetLinkData () <<
2080
                      " using next hop " << nextHop <<
2081
                      " since outgoing interface id is negative " << outIf);
2082
                  }
2083
              } // for all routes from the root the vertex 'v'
1846
            }
2084
            }
1847
//
2085
//
1848
// Done adding the routes for the selected node.
2086
// Done adding the routes for the selected node.
 Lines 1931-1951    Link Here 
1931
            }
2169
            }
1932
          Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
2170
          Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1933
          NS_ASSERT (gr);
2171
          NS_ASSERT (gr);
1934
          if (v->GetOutgoingInterfaceId () >= 0)
2172
          // walk through all available exit directions due to ECMP,
1935
            {
2173
          // and add host route for each of the exit direction toward
1936
              gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
2174
          // the vertex 'v'
1937
                v->GetOutgoingInterfaceId ());
2175
          for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
1938
              NS_LOG_LOGIC ("Node " << node->GetId () <<
2176
          {
1939
                " add network route to " << tempip <<
2177
            SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
1940
                " using next hop " << v->GetNextHop () <<
2178
            Ipv4Address nextHop = exit.first;
1941
                " via interface " << v->GetOutgoingInterfaceId ());
2179
            int32_t outIf = exit.second;
1942
            }
2180
1943
          else
2181
            if (outIf >= 0)
1944
            {
2182
              {
1945
              NS_LOG_LOGIC ("Node " << node->GetId () <<
2183
                gr->AddNetworkRouteTo (tempip, tempmask, nextHop, outIf);
1946
                " NOT able to add network route to " << tempip <<
2184
                NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1947
                " using next hop " << v->GetNextHop () <<
2185
                  " add network route to " << tempip <<
1948
                " since outgoing interface id is negative");
2186
                  " using next hop " << nextHop <<
2187
                  " via interface " << outIf);
2188
              }
2189
            else
2190
              {
2191
                NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
2192
                  " NOT able to add network route to " << tempip <<
2193
                  " using next hop " << nextHop <<
2194
                  " since outgoing interface id is negative " << outIf);
2195
              }
1949
            }
2196
            }
1950
        }
2197
        }
1951
    } 
2198
    } 
 Lines 1960-1972    Link Here 
1960
// Given a pointer to a vertex, it links back to the vertex's parent that it
2207
// Given a pointer to a vertex, it links back to the vertex's parent that it
1961
// already has set and adds itself to that vertex's list of children.
2208
// already has set and adds itself to that vertex's list of children.
1962
//
2209
//
1963
// For now, only one parent (not doing equal-cost multipath)
1964
//
1965
  void
2210
  void
1966
GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v)
2211
GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v)
1967
{
2212
{
1968
  NS_LOG_FUNCTION (v);
2213
  NS_LOG_FUNCTION (v);
1969
  v->GetParent ()->AddChild (v);
2214
2215
  for (uint32_t i=0;;)
2216
    {
2217
      SPFVertex* parent;
2218
      // check if all parents of vertex v
2219
      if ((parent = v->GetParent (i++)) == 0) break;
2220
      parent->AddChild (v);
2221
    }
1970
}
2222
}
1971
2223
1972
} // namespace ns3
2224
} // namespace ns3
(-)a/src/routing/global-routing/global-route-manager-impl.h (-6 / +159 lines)
 Lines 256-261    Link Here 
256
  void SetDistanceFromRoot (uint32_t distance);
256
  void SetDistanceFromRoot (uint32_t distance);
257
257
258
/**
258
/**
259
 * \deprecated Use GetRootExitDirection instead
260
 *
259
 * @brief Get the interface ID that should be used to begin forwarding packets
261
 * @brief Get the interface ID that should be used to begin forwarding packets
260
 * from the root SPFVertex to "this" SPFVertex.
262
 * from the root SPFVertex to "this" SPFVertex.
261
 * @internal
263
 * @internal
 Lines 295-303    Link Here 
295
 * @returns The interface index to use when forwarding packets to the host
297
 * @returns The interface index to use when forwarding packets to the host
296
 * or network represented by "this" SPFVertex.
298
 * or network represented by "this" SPFVertex.
297
 */
299
 */
298
  uint32_t GetOutgoingInterfaceId (void) const;
300
  uint32_t GetOutgoingInterfaceId (void) const NS_DEPRECATED;
299
301
300
/**
302
/**
303
 * \deprecated Use SetRootExitDirection instead
304
 *
301
 * @brief Set the interface ID that should be used to begin forwarding packets
305
 * @brief Set the interface ID that should be used to begin forwarding packets
302
 * from the root SPFVertex to "this" SPFVertex.
306
 * from the root SPFVertex to "this" SPFVertex.
303
 * @internal
307
 * @internal
 Lines 337-345    Link Here 
337
 * @param id The interface index to use when forwarding packets to the host or
341
 * @param id The interface index to use when forwarding packets to the host or
338
 * network represented by "this" SPFVertex.
342
 * network represented by "this" SPFVertex.
339
 */
343
 */
340
  void SetOutgoingInterfaceId (int32_t id);
344
  void SetOutgoingInterfaceId (int32_t id) NS_DEPRECATED;
341
345
342
/**
346
/**
347
 * \deprecated Use GetRootExitDirection instead
348
 *
343
 * @brief Get the IP address that should be used to begin forwarding packets 
349
 * @brief Get the IP address that should be used to begin forwarding packets 
344
 * from the root SPFVertex to "this" SPFVertex.
350
 * from the root SPFVertex to "this" SPFVertex.
345
 * @internal
351
 * @internal
 Lines 380-388    Link Here 
380
 * @returns The IP address to use when forwarding packets to the host
386
 * @returns The IP address to use when forwarding packets to the host
381
 * or network represented by "this" SPFVertex.
387
 * or network represented by "this" SPFVertex.
382
 */
388
 */
383
  Ipv4Address GetNextHop (void) const;
389
  Ipv4Address GetNextHop (void) const NS_DEPRECATED;
384
390
385
/**
391
/**
392
 * \deprecated Use SetRootExitDirection instead
393
 *
386
 * @brief Set the IP address that should be used to begin forwarding packets 
394
 * @brief Set the IP address that should be used to begin forwarding packets 
387
 * from the root SPFVertex to "this" SPFVertex.
395
 * from the root SPFVertex to "this" SPFVertex.
388
 * @internal
396
 * @internal
 Lines 423-429    Link Here 
423
 * @param nextHop The IP address to use when forwarding packets to the host
431
 * @param nextHop The IP address to use when forwarding packets to the host
424
 * or network represented by "this" SPFVertex.
432
 * or network represented by "this" SPFVertex.
425
 */
433
 */
426
  void SetNextHop (Ipv4Address nextHop);
434
  void SetNextHop (Ipv4Address nextHop) NS_DEPRECATED;
435
/**
436
 * @brief Set the IP address and outgoing interface index that should be used 
437
 * to begin forwarding packets from the root SPFVertex to "this" SPFVertex.
438
 * @internal
439
 *
440
 * Each router node in the simulation is associated with an SPFVertex object.
441
 * When calculating routes, each of these routers is, in turn, chosen as the 
442
 * "root" of the calculation and routes to all of the other routers are
443
 * eventually saved in the routing tables of each of the chosen nodes.
444
 *
445
 * The "Root" vertex is then the SPFVertex representing the router that is
446
 * having its routing tables set.  The "this" SPFVertex is the vertex that
447
 * represents the host or network to which a route is being calculated from 
448
 * the root.  The IP address that we're asking for is the address on the 
449
 * remote side of a link off of the root node that should be used as the
450
 * destination for packets along the path to "this" vertex.
451
 *
452
 * When initializing the root SPFVertex, the IP address used when forwarding
453
 * packets is determined by examining the Global Router Link Records of the
454
 * Link State Advertisement generated by the root node's GlobalRouter.  This
455
 * address is used to forward packets off of the root's network down those
456
 * links.  As other vertices / nodes are discovered which are further away
457
 * from the root, they will be accessible down one of the paths via a link
458
 * described by one of these Global Router Link Records.
459
 * 
460
 * To forward packets to these hosts or networks, the root node must begin
461
 * the forwarding process by sending the packets to a first hop router down
462
 * an interface.  This means that the first hop address and interface ID must
463
 * be the same for all downstream SPFVertices.  We call this "inheriting"
464
 * the interface and next hop.
465
 *
466
 * In this method we are telling the root node which exit direction it should send
467
 * should I send a packet to the network or host represented by 'this' SPFVertex.
468
 *
469
 * @see GlobalRouter
470
 * @see GlobalRoutingLSA
471
 * @see GlobalRoutingLinkRecord
472
 * @param nextHop The IP address to use when forwarding packets to the host
473
 * or network represented by "this" SPFVertex.
474
 * @param id The interface index to use when forwarding packets to the host or
475
 * network represented by "this" SPFVertex.
476
 */
477
  void SetRootExitDirection (Ipv4Address nextHop, int32_t id = SPF_INFINITY);
478
  typedef std::pair<Ipv4Address, int32_t> NodeExit_t;
479
/**
480
 * @brief Set the IP address and outgoing interface index that should be used 
481
 * to begin forwarding packets from the root SPFVertex to "this" SPFVertex.
482
 * @internal
483
 *
484
 * Each router node in the simulation is associated with an SPFVertex object.
485
 * When calculating routes, each of these routers is, in turn, chosen as the 
486
 * "root" of the calculation and routes to all of the other routers are
487
 * eventually saved in the routing tables of each of the chosen nodes.
488
 *
489
 * The "Root" vertex is then the SPFVertex representing the router that is
490
 * having its routing tables set.  The "this" SPFVertex is the vertex that
491
 * represents the host or network to which a route is being calculated from 
492
 * the root.  The IP address that we're asking for is the address on the 
493
 * remote side of a link off of the root node that should be used as the
494
 * destination for packets along the path to "this" vertex.
495
 *
496
 * When initializing the root SPFVertex, the IP address used when forwarding
497
 * packets is determined by examining the Global Router Link Records of the
498
 * Link State Advertisement generated by the root node's GlobalRouter.  This
499
 * address is used to forward packets off of the root's network down those
500
 * links.  As other vertices / nodes are discovered which are further away
501
 * from the root, they will be accessible down one of the paths via a link
502
 * described by one of these Global Router Link Records.
503
 * 
504
 * To forward packets to these hosts or networks, the root node must begin
505
 * the forwarding process by sending the packets to a first hop router down
506
 * an interface.  This means that the first hop address and interface ID must
507
 * be the same for all downstream SPFVertices.  We call this "inheriting"
508
 * the interface and next hop.
509
 *
510
 * In this method we are telling the root node which exit direction it should send
511
 * should I send a packet to the network or host represented by 'this' SPFVertex.
512
 *
513
 * @see GlobalRouter
514
 * @see GlobalRoutingLSA
515
 * @see GlobalRoutingLinkRecord
516
 * @param nextHop The IP address to use when forwarding packets to the host
517
 * or network represented by "this" SPFVertex.
518
 * @param exit The pair of next-hop-IP and outgoing-interface-index to use when 
519
 * forwarding packets to the host or network represented by "this" SPFVertex.
520
 */
521
  void SetRootExitDirection (SPFVertex::NodeExit_t exit);
522
 /**
523
  * \brief Obtain a pair indicating the exit direction from the root
524
  *
525
  * \param i An index to a pair
526
  * \return A pair of next-hop-IP and outgoing-interface-index for 
527
  * indicating an exit direction from the root. It is 0 if the index 'i'
528
  * is out-of-range
529
  */
530
  NodeExit_t GetRootExitDirection (uint32_t i) const;
531
  /**
532
   * \brief Obtain a pair indicating the exit direction from the root
533
   *
534
   * This method assumes there is only a single exit direction from the root.
535
   * Error occur if this assumption is invalid.
536
   *
537
   * \return The pair of next-hop-IP and outgoing-interface-index for reaching
538
   * 'this' vertex from the root
539
   */
540
  NodeExit_t GetRootExitDirection () const;
541
  /**
542
   * \brief Merge into 'this' vertex the list of exit directions from
543
   * another vertex
544
   *
545
   * This merge is necessary when ECMP are found. 
546
   *
547
   * \param vertex From which the list of exit directions are obtain
548
   * and are merged into 'this' vertex
549
   */
550
  void MergeRootExitDirections (const SPFVertex* vertex);
551
  /**
552
   * \brief Inherit all root exit directions from a given vertex to 'this' vertex
553
   * \param vertex The vertex from which all root exit directions are to be inherrited
554
   *
555
   * After the call of this method, the original root exit directions
556
   * in 'this' vertex are all lost.
557
   */
558
  void InheritAllRootExitDirections (const SPFVertex* vertex);
559
  /**
560
   * \brief Get the number of exit directions from root for reaching 'this' vertex
561
   * \return The number of exit directions from root
562
   */
563
  uint32_t GetNRootExitDirections () const;
427
564
428
/**
565
/**
429
 * @brief Get a pointer to the SPFVector that is the parent of "this" 
566
 * @brief Get a pointer to the SPFVector that is the parent of "this" 
 Lines 441-450    Link Here 
441
 * This method returns a pointer to the parent node of "this" SPFVertex
578
 * This method returns a pointer to the parent node of "this" SPFVertex
442
 * (both of which reside in that SPF tree).
579
 * (both of which reside in that SPF tree).
443
 *
580
 *
581
 * @param i The index to one of the parents
444
 * @returns A pointer to the SPFVertex that is the parent of "this" SPFVertex
582
 * @returns A pointer to the SPFVertex that is the parent of "this" SPFVertex
445
 * in the SPF tree.
583
 * in the SPF tree.
446
 */
584
 */
447
  SPFVertex* GetParent (void) const;
585
  SPFVertex* GetParent (uint32_t i = 0) const;
448
586
449
/**
587
/**
450
 * @brief Set the pointer to the SPFVector that is the parent of "this" 
588
 * @brief Set the pointer to the SPFVector that is the parent of "this" 
 Lines 466-471    Link Here 
466
 * SPFVertex* in the SPF tree.
604
 * SPFVertex* in the SPF tree.
467
 */
605
 */
468
  void SetParent (SPFVertex* parent);
606
  void SetParent (SPFVertex* parent);
607
  /**
608
   * \brief Merge the Parent list from the v into this vertex
609
   *
610
   * \param v The vertex from which its list of Parent is read
611
   * and then merged into the list of Parent of *this* vertex.
612
   * Note that the list in v remains intact
613
   */
614
  void MergeParent (const SPFVertex* v);
469
615
470
/**
616
/**
471
 * @brief Get the number of children of "this" SPFVertex.
617
 * @brief Get the number of children of "this" SPFVertex.
 Lines 574-581    Link Here 
574
  uint32_t m_distanceFromRoot;
720
  uint32_t m_distanceFromRoot;
575
  int32_t m_rootOif;
721
  int32_t m_rootOif;
576
  Ipv4Address m_nextHop;
722
  Ipv4Address m_nextHop;
577
  SPFVertex* m_parent;
723
  typedef std::list< NodeExit_t > ListOfNodeExit_t;
724
  /// store the multiple root's exits for supporting ECMP
725
  ListOfNodeExit_t m_ecmpRootExits;
578
  typedef std::list<SPFVertex*> ListOfSPFVertex_t;
726
  typedef std::list<SPFVertex*> ListOfSPFVertex_t;
727
  ListOfSPFVertex_t m_parents;
579
  ListOfSPFVertex_t m_children;
728
  ListOfSPFVertex_t m_children;
580
  bool m_vertexProcessed; 
729
  bool m_vertexProcessed; 
581
730
 Lines 590-595    Link Here 
590
 * need for it and a compiler provided shallow copy would be wrong.
739
 * need for it and a compiler provided shallow copy would be wrong.
591
 */
740
 */
592
  SPFVertex& operator= (SPFVertex& v);
741
  SPFVertex& operator= (SPFVertex& v);
742
743
  //friend std::ostream& operator<< (std::ostream& os, const ListOfIf_t& ifs);
744
  //friend std::ostream& operator<< (std::ostream& os, const ListOfAddr_t& addrs);
745
  friend std::ostream& operator<< (std::ostream& os, const SPFVertex::ListOfSPFVertex_t& vs);
593
};
746
};
594
747
595
/**
748
/**
(-)a/src/routing/global-routing/ipv4-global-routing.cc (-13 / +35 lines)
 Lines 22-28    Link Here 
22
#include "ns3/net-device.h"
22
#include "ns3/net-device.h"
23
#include "ns3/ipv4-route.h"
23
#include "ns3/ipv4-route.h"
24
#include "ns3/ipv4-routing-table-entry.h"
24
#include "ns3/ipv4-routing-table-entry.h"
25
#include "ns3/boolean.h"
25
#include "ipv4-global-routing.h"
26
#include "ipv4-global-routing.h"
27
#include <vector>
26
28
27
NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRouting");
29
NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRouting");
28
30
 Lines 35-45    Link Here 
35
{ 
37
{ 
36
  static TypeId tid = TypeId ("ns3::Ipv4GlobalRouting")
38
  static TypeId tid = TypeId ("ns3::Ipv4GlobalRouting")
37
    .SetParent<Object> ()
39
    .SetParent<Object> ()
40
    .AddAttribute ("RandomEcmpRouting",
41
                   "Set to true if packets are randomly routed among ECMP; set to false for using only one route consistently",
42
                   BooleanValue(false),
43
                   MakeBooleanAccessor (&Ipv4GlobalRouting::m_randomEcmpRouting),
44
                   MakeBooleanChecker ())
38
    ;
45
    ;
39
  return tid;
46
  return tid;
40
}
47
}
41
48
42
Ipv4GlobalRouting::Ipv4GlobalRouting () 
49
Ipv4GlobalRouting::Ipv4GlobalRouting () 
50
: m_randomEcmpRouting (false) 
43
{
51
{
44
  NS_LOG_FUNCTION_NOARGS ();
52
  NS_LOG_FUNCTION_NOARGS ();
45
}
53
}
 Lines 120-128    Link Here 
120
  NS_LOG_FUNCTION_NOARGS ();
128
  NS_LOG_FUNCTION_NOARGS ();
121
  NS_LOG_LOGIC ("Looking for route for destination " << dest);
129
  NS_LOG_LOGIC ("Looking for route for destination " << dest);
122
  Ptr<Ipv4Route> rtentry = 0;
130
  Ptr<Ipv4Route> rtentry = 0;
123
  bool found = false;
124
  Ipv4RoutingTableEntry* route = 0;
131
  Ipv4RoutingTableEntry* route = 0;
132
  // store all available routes that bring packets to their destination
133
  typedef std::vector<Ipv4RoutingTableEntry*> RouteVec_t;
134
  RouteVec_t allRoutes;
125
135
136
  NS_LOG_LOGIC ("Number of m_hostRoutes = " << m_hostRoutes.size ());
126
  for (HostRoutesCI i = m_hostRoutes.begin (); 
137
  for (HostRoutesCI i = m_hostRoutes.begin (); 
127
       i != m_hostRoutes.end (); 
138
       i != m_hostRoutes.end (); 
128
       i++) 
139
       i++) 
 Lines 130-143    Link Here 
130
      NS_ASSERT ((*i)->IsHost ());
141
      NS_ASSERT ((*i)->IsHost ());
131
      if ((*i)->GetDest ().IsEqual (dest)) 
142
      if ((*i)->GetDest ().IsEqual (dest)) 
132
        {
143
        {
133
          NS_LOG_LOGIC ("Found global host route" << *i); 
144
          allRoutes.push_back (*i);
134
          route = (*i);
145
          NS_LOG_LOGIC (allRoutes.size () << "Found global host route" << *i);           
135
          found = true; 
136
          break;
137
        }
146
        }
138
    }
147
    }
139
  if (found == false)
148
  if (allRoutes.size () == 0) // if no host route is found
140
    {
149
    {
150
      NS_LOG_LOGIC ("Number of m_networkRoutes" << m_networkRoutes.size ());
141
      for (NetworkRoutesI j = m_networkRoutes.begin (); 
151
      for (NetworkRoutesI j = m_networkRoutes.begin (); 
142
           j != m_networkRoutes.end (); 
152
           j != m_networkRoutes.end (); 
143
           j++) 
153
           j++) 
 Lines 147-160    Link Here 
147
          Ipv4Address entry = (*j)->GetDestNetwork ();
157
          Ipv4Address entry = (*j)->GetDestNetwork ();
148
          if (mask.IsMatch (dest, entry)) 
158
          if (mask.IsMatch (dest, entry)) 
149
            {
159
            {
150
              NS_LOG_LOGIC ("Found global network route" << *j); 
160
              allRoutes.push_back (*j);
151
              route = (*j);
161
              NS_LOG_LOGIC (allRoutes.size () << "Found global network route" << *j); 
152
              found = true;
153
              break;
154
            }
162
            }
155
        }
163
        }
156
    }
164
    }
157
  if (found == false)
165
  if (allRoutes.size () == 0)  // consider external if no host/network found
158
    {
166
    {
159
      for (ASExternalRoutesI k = m_ASexternalRoutes.begin ();
167
      for (ASExternalRoutesI k = m_ASexternalRoutes.begin ();
160
           k != m_ASexternalRoutes.end ();
168
           k != m_ASexternalRoutes.end ();
 Lines 166-178    Link Here 
166
            {
174
            {
167
              NS_LOG_LOGIC ("Found external route" << *k);
175
              NS_LOG_LOGIC ("Found external route" << *k);
168
              route = (*k);
176
              route = (*k);
169
              found = true;
177
              allRoutes.push_back (*k);
170
              break;
178
              break;
171
            }
179
            }
172
        }
180
        }
173
    }
181
    }
174
  if (found == true)
182
  if (allRoutes.size () > 0 ) // if route(s) is found
175
    {
183
    {
184
      // pick up one of the routes uniformly at random if random
185
      // ECMP routing is enabled, or always select the first route
186
      // consistently if random ECMP routing is disabled
187
      uint32_t selectIndex;
188
      if (m_randomEcmpRouting)
189
        {
190
          selectIndex = m_rand.GetInteger (0, allRoutes.size ()-1);
191
        }
192
      else 
193
        {
194
          selectIndex = 0;
195
        }
196
      route = allRoutes.at (selectIndex);
197
      // create a Ipv4Route object from the selected routing table entry
176
      rtentry = Create<Ipv4Route> ();
198
      rtentry = Create<Ipv4Route> ();
177
      rtentry->SetDestination (route->GetDest ());
199
      rtentry->SetDestination (route->GetDest ());
178
      // XXX handle multi-address case
200
      // XXX handle multi-address case
(-)a/src/routing/global-routing/ipv4-global-routing.h (+6 lines)
 Lines 27-32    Link Here 
27
#include "ns3/ptr.h"
27
#include "ns3/ptr.h"
28
#include "ns3/ipv4.h"
28
#include "ns3/ipv4.h"
29
#include "ns3/ipv4-routing-protocol.h"
29
#include "ns3/ipv4-routing-protocol.h"
30
#include "ns3/random-variable.h"
30
31
31
namespace ns3 {
32
namespace ns3 {
32
33
 Lines 212-217    Link Here 
212
  void DoDispose (void);
213
  void DoDispose (void);
213
214
214
private:
215
private:
216
  /// Set to true if packets are randomly routed among ECMP; set to false for using only one route consistently
217
  bool m_randomEcmpRouting;
218
  /// A uniform random number generator for randomly routing packets among ECMP 
219
  UniformVariable m_rand;
220
215
  typedef std::list<Ipv4RoutingTableEntry *> HostRoutes;
221
  typedef std::list<Ipv4RoutingTableEntry *> HostRoutes;
216
  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator HostRoutesCI;
222
  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator HostRoutesCI;
217
  typedef std::list<Ipv4RoutingTableEntry *>::iterator HostRoutesI;
223
  typedef std::list<Ipv4RoutingTableEntry *>::iterator HostRoutesI;

Return to bug 667