~ubuntu-branches/ubuntu/jaunty/xorp/jaunty

« back to all changes in this revision

Viewing changes to ospf/peer_manager.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jose Calhariz, Javier Fernandez-Sanguino, Jose Calhariz
  • Date: 2008-01-23 01:24:37 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080123012437-7l2u9r0k8e7op8st
Tags: 1.5~cvs.20080128-1
[ Javier Fernandez-Sanguino ]
* Update to latest CVS contents
* Modify debian/rules to prevent autobuilders from building 
  the binary-independent components: (Closes: #441121)
  - Create a new Build-Depends-Indep with all the TeX
  components used to build documentation
  - Since autobuilders call build, which in turns calls build-indep, hack
    the debian rules file so that the documentation is only built if ps2pdf,
    dvips and pslatex are available. 
* Modify the init.d script:
  - restart action: Do not attempt to stop xorp if not running
  - stop function: fix errors in the script
  - add a try-restart action
  - restructure the init.d script, move the restart code to a function
  - review the use of echo calls and exit values
* Use, as examples, the new boot files at rtrmgr/config/

[ Jose Calhariz ]
* Add depends on ncurses-dev, I don't know why xorp use tigetstr
  function from curses.  This way the depends field change less between
  build environments.
* Removed pushd and popd commands from Makefile and replaced with cd
  commands, was a bashism and FTBFS (closes: #453637)
* debian/control converted to utf-8 (closes: #454026) (closes: #453485)
* init.d/xorp now returns 0 if disabled.
* Added Vcs-Browser and Vcs-Svn fields pointing to the repository of the
  package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
2
2
// vim:set sts=4 ts=8:
3
3
 
4
 
// Copyright (c) 2001-2007 International Computer Science Institute
 
4
// Copyright (c) 2001-2008 International Computer Science Institute
5
5
//
6
6
// Permission is hereby granted, free of charge, to any person obtaining a
7
7
// copy of this software and associated documentation files (the "Software")
13
13
// notice is a summary of the XORP LICENSE file; the license in that file is
14
14
// legally binding.
15
15
 
16
 
#ident "$XORP: xorp/ospf/peer_manager.cc,v 1.144 2007/08/17 22:18:47 atanu Exp $"
 
16
#ident "$XORP: xorp/ospf/peer_manager.cc,v 1.156 2008/01/04 03:16:57 pavlin Exp $"
17
17
 
18
18
// #define DEBUG_LOGGING
19
19
// #define DEBUG_PRINT_FUNCTION_NAME
126
126
    // XXX Should subsume the refreshing of the Router-LSA into the
127
127
    // generic area border router transition method.
128
128
    if (area_border_router_p() != old_border_router_state) {
129
 
        refresh_router_lsas();
130
 
        area_border_router_transition(true /* up */);
 
129
        if (!_ospf.get_testing()) {
 
130
            refresh_router_lsas();
 
131
            area_border_router_transition(true /* up */);
 
132
        }
131
133
    }
132
134
 
133
135
    // Inform this area if any virtual links are configured.
232
234
    // XXX Should subsume the refreshing of the Router-LSA into the
233
235
    // generic area border router transition method.
234
236
    if (area_border_router_p() != old_border_router_state) {
235
 
        refresh_router_lsas();
236
 
        area_border_router_transition(false /* down */);
 
237
        if (!_ospf.get_testing()) {
 
238
            refresh_router_lsas();
 
239
            area_border_router_transition(false /* down */);
 
240
        }
237
241
    }
238
242
 
239
243
    // Flag to the virtual link code that this area is going away.
431
435
}
432
436
 
433
437
template <typename A>
 
438
bool
 
439
PeerManager<A>::enabled(const string& interface, const string& vif, A address)
 
440
{
 
441
    debug_msg("Interface %s Vif %s Address %s\n", interface.c_str(),
 
442
              vif.c_str(), cstring(address));
 
443
 
 
444
    switch (_ospf.get_version()) {
 
445
    case OspfTypes::V2:
 
446
        break;
 
447
    case OspfTypes::V3:
 
448
        // If the address is set to zero then try and get the
 
449
        // link-local address.
 
450
        if (A::ZERO() == address) {
 
451
            if (!_ospf.get_link_local_address(interface, vif, address))
 
452
                if (_ospf.enabled(interface, vif))
 
453
                    XLOG_WARNING("link-local address must be configured "
 
454
                                 "on %s/%s", interface.c_str(), vif.c_str());
 
455
        }
 
456
        break;
 
457
    }
 
458
    return _ospf.enabled(interface, vif, address);
 
459
}
 
460
 
 
461
template <typename A>
434
462
OspfTypes::PeerID
435
463
PeerManager<A>::create_peer(const string& interface, const string& vif,
436
464
                            A source,
451
479
 
452
480
    OspfTypes::PeerID peerid = create_peerid(interface, vif);
453
481
 
454
 
    switch (_ospf.get_version()) {
455
 
    case OspfTypes::V2:
456
 
        break;
457
 
    case OspfTypes::V3:
458
 
        if (OspfTypes::VirtualLink != linktype) {
459
 
            // Note that the source address is going to be replaced with
460
 
            // the link local address, unless this is a virtual link.
461
 
            if (!_ospf.get_link_local_address(interface, vif, source)) {
462
 
                destroy_peerid(interface, vif);
463
 
                xorp_throw(BadPeer, 
464
 
                           c_format("Unable to get link local address for "
465
 
                                    "%s/%s",
466
 
                                    interface.c_str(), vif.c_str()));
467
 
            }
468
 
        }
469
 
        break;
470
 
    }
471
 
 
472
 
    // Get the prefix length.
473
 
    uint16_t interface_prefix_length;
474
 
    if (!_ospf.get_prefix_length(interface, vif, source,
475
 
                                 interface_prefix_length)) {
476
 
        destroy_peerid(interface, vif);
477
 
        xorp_throw(BadPeer, 
478
 
                   c_format("Unable to get prefix length for %s/%s/%s",
479
 
                            interface.c_str(), vif.c_str(), cstring(source)));
480
 
    }
481
 
 
482
 
    // Get the MTU.
483
 
    uint16_t interface_mtu = _ospf.get_mtu(interface);
484
 
    if (0 == interface_mtu) {
485
 
        destroy_peerid(interface, vif);
486
 
        xorp_throw(BadPeer, 
487
 
                   c_format("Unable to get MTU for %s", interface.c_str()));
488
 
    }
489
 
 
490
482
    // If we got this far create_peerid did not throw an exception so
491
483
    // this interface/vif is unique.
492
484
 
493
485
    _peers[peerid] = new PeerOut<A>(_ospf, interface, vif, peerid,
494
 
                                    source, interface_prefix_length,
495
 
                                    interface_mtu, linktype,
496
 
                                    area, area_router->get_area_type());
497
 
 
498
 
    switch (_ospf.get_version()) {
499
 
    case OspfTypes::V2:
500
 
        break;
501
 
    case OspfTypes::V3: {
502
 
        uint32_t interface_id;
503
 
        if (!_ospf.get_interface_id(interface, vif, interface_id)) {
504
 
            delete_peer(peerid);
505
 
            xorp_throw(BadPeer, 
506
 
                       c_format("Unable to get interface ID for %s",
507
 
                                interface.c_str()));
508
 
        }
509
 
        _peers[peerid]->set_interface_id(interface_id);
510
 
    }
511
 
        break;
512
 
    }
 
486
                                    source, linktype, area,
 
487
                                    area_router->get_area_type());
513
488
 
514
489
    // Pass in the option to be sent by the hello packet.
515
490
    _peers[peerid]->set_options(area,
516
491
                                compute_options(area_router->get_area_type()));
517
492
 
518
 
    switch (_ospf.get_version()) {
519
 
    case OspfTypes::V2:
520
 
        _peers[peerid]->set_link_status(_ospf.enabled(interface, vif, source));
521
 
        break;
522
 
    case OspfTypes::V3:
523
 
#if     0
524
 
        // If this is a virtual link bring it up now, otherwise
525
 
        // wait for the call to activate.
526
 
        if (OspfTypes::VirtualLink == linktype) {
527
 
            _peers[peerid]->set_link_status(_ospf.enabled(interface, vif,
528
 
                                                          source));
529
 
        }
530
 
#endif
531
 
        // This call needs to be made only once per invocation of OSPF
532
 
        // but at this point we know that the interface mirror is up
533
 
        // and running.
534
 
        _ospf.register_address_status(callback(this,
535
 
                                               &PeerManager<A>::
536
 
                                               address_status_change));
537
 
        break;
538
 
    }
539
 
 
540
 
    // This call needs to be made only once per invocation of OSPF
541
 
    // but at this point we know that the interface mirror is up
542
 
    // and running.
 
493
    // These two registrations need to be made only once per
 
494
    // invocation of OSPF, however, at this point we know that the interface
 
495
    // mirror is up and running.
543
496
    _ospf.register_vif_status(callback(this,
544
497
                                       &PeerManager<A>::
545
498
                                       vif_status_change));
 
499
    _ospf.register_address_status(callback(this, &PeerManager<A>::
 
500
                                           address_status_change));
546
501
 
547
502
    area_router->add_peer(peerid);
548
503
 
549
 
    // The peer has now been fully configured so initialise it.
550
 
    _peers[peerid]->go(area);
 
504
    // If the interface, vif and source are up the peer will start running.
 
505
    _peers[peerid]->set_link_status(enabled(interface, vif, source));
551
506
 
552
507
    return peerid;
553
508
}
712
667
    recompute_addresses_peer(peerid, area);
713
668
 
714
669
    A source = _peers[peerid]->get_interface_address();
715
 
    _peers[peerid]->set_link_status(_ospf.enabled(interface, vif, source));
 
670
    _peers[peerid]->set_link_status(enabled(interface, vif, source));
716
671
 
717
672
    return true;
718
673
}
757
712
                       "PeerID %u", peerid);
758
713
            return false;
759
714
        }
 
715
        // Before trying to get the addresses verify that this
 
716
        // interface/vif exists and has a usable address configured.
 
717
        if (!enabled(interface, vif, _peers[peerid]->get_interface_address()))
 
718
            return false;
760
719
        list<A> addresses;
761
720
        if (!_ospf.get_addresses(interface, vif, addresses)) {
762
721
            XLOG_ERROR("Unable to find addresses on %s/%s ", interface.c_str(),
849
808
        return;
850
809
    }
851
810
 
 
811
    _peers[peerid]->set_link_status(enabled(interface,
 
812
                                            vif,
 
813
                                            _peers[peerid]->
 
814
                                            get_interface_address()));
 
815
 
852
816
    switch(_ospf.get_version()) {
853
817
    case OspfTypes::V2:
854
818
        break;
928
892
 
929
893
template <typename A>
930
894
bool
 
895
PeerManager<A>::clear_database()
 
896
{
 
897
    // Drop all adjacencies.
 
898
    typename map<OspfTypes::PeerID, PeerOut<A> *>::const_iterator p;
 
899
    for(p = _peers.begin(); p != _peers.end(); p++) {
 
900
        // If this peer is up then taking it down and bringing it up
 
901
        // should drop all adjacencies.
 
902
        if( (*p).second->get_state()) {
 
903
            (*p).second->set_state(false);
 
904
            (*p).second->set_state(true);
 
905
        }
 
906
    }
 
907
 
 
908
    // Clear the AS-External-LSA database.
 
909
    _external.clear_database();
 
910
 
 
911
    // Clear the area databases.
 
912
    typename map<OspfTypes::AreaID, AreaRouter<A> *>::const_iterator a;
 
913
    for (a = _areas.begin(); a != _areas.end(); a++) {
 
914
        // Changing the area type of the router will delete the
 
915
        // Router-LSA generated by this router and revive it.
 
916
        (*a).second->change_area_router_type((*a).second->get_area_type());
 
917
    }
 
918
 
 
919
    // Recompute the routes in all areas to withdraw the routes and
 
920
    // remove virtual links. This will also cause the summary routes
 
921
    // to be withdrawn. Should not be required as dropping the
 
922
    // adjacencies should prompt a route recomputation.
 
923
    routing_recompute_all_areas();
 
924
 
 
925
    typename map<IPNet<A>, Summary>::iterator i;
 
926
    for(i = _summaries.begin(); i != _summaries.end(); i++)
 
927
        XLOG_WARNING("Summary not removed %s %s", cstring(i->first),
 
928
                     cstring(i->second._rtentry));
 
929
 
 
930
    return true;
 
931
}
 
932
 
 
933
template <typename A>
 
934
bool
931
935
PeerManager<A>::queue_lsa(const OspfTypes::PeerID peerid,
932
936
                          const OspfTypes::PeerID peer,
933
937
                          OspfTypes::NeighbourID nid, Lsa::LsaRef lsar,
1827
1831
 
1828
1832
template <typename A>
1829
1833
void
 
1834
PeerManager<A>::external_suppress_lsas(OspfTypes::AreaID area)
 
1835
{
 
1836
    _external.suppress_lsas(area);
 
1837
}
 
1838
 
 
1839
template <typename A>
 
1840
void
1830
1841
PeerManager<A>::routing_recompute_all_areas()
1831
1842
{
1832
1843
    typename map<OspfTypes::AreaID, AreaRouter<A> *>::const_iterator i;
1865
1876
    debug_msg("Area %s net %s rentry %s\n", pr_id(area).c_str(),
1866
1877
              cstring(net), cstring(rt));
1867
1878
 
 
1879
    if (_ospf.get_testing())
 
1880
        return false;
 
1881
 
1868
1882
    // RFC 2328 Section 12.4.3. Summary-LSAs
1869
1883
    // Select routes that are candidate for summarisation.
1870
1884
 
1918
1932
    if (!summary_candidate(area, net, rt))
1919
1933
        return;
1920
1934
 
 
1935
    _external.suppress_route_announce(area, net, rt);
 
1936
 
1921
1937
    // Save this route for possible later replay.
1922
1938
    XLOG_ASSERT(0 == _summaries.count(net));
1923
1939
    Summary s(area, rt);
1942
1958
    if (!summary_candidate(area, net, rt))
1943
1959
        return;
1944
1960
 
 
1961
    _external.suppress_route_withdraw(area, net, rt);
 
1962
 
1945
1963
    // Remove this saved route.
1946
1964
    XLOG_ASSERT(1 == _summaries.count(net));
1947
1965
    _summaries.erase(_summaries.find(net));
1962
1980
 
1963
1981
template <typename A>
1964
1982
void
 
1983
PeerManager<A>::summary_replace(OspfTypes::AreaID area, IPNet<A> net,
 
1984
                                RouteEntry<A>& rt,
 
1985
                                RouteEntry<A>& previous_rt,
 
1986
                                OspfTypes::AreaID previous_area)
 
1987
{
 
1988
    debug_msg("Area %s net %s rentry %s\n", pr_id(area).c_str(),
 
1989
              cstring(net), cstring(rt));
 
1990
 
 
1991
    bool previous = summary_candidate(previous_area, net, previous_rt);
 
1992
    bool current = summary_candidate(area, net, rt);
 
1993
 
 
1994
    if (current != previous) {
 
1995
        if (previous)
 
1996
            summary_withdraw(previous_area, net, previous_rt);
 
1997
        if (current)
 
1998
            summary_announce(area, net, rt);
 
1999
        return;
 
2000
    }
 
2001
 
 
2002
    XLOG_ASSERT(current == previous);
 
2003
 
 
2004
    // Don't need to check for !previous as it is the same as current.
 
2005
    if (!current)
 
2006
        return;
 
2007
 
 
2008
    XLOG_ASSERT(current);
 
2009
    XLOG_ASSERT(previous);
 
2010
 
 
2011
    _external.suppress_route_withdraw(previous_area, net, previous_rt);
 
2012
    _external.suppress_route_announce(area, net, rt);
 
2013
    
 
2014
    XLOG_ASSERT(1 == _summaries.count(net));
 
2015
    _summaries.erase(_summaries.find(net));
 
2016
    Summary s(area, rt);
 
2017
    _summaries.insert(make_pair(net, s));
 
2018
 
 
2019
    typename map<OspfTypes::AreaID, AreaRouter<A> *>::const_iterator i;
 
2020
    for (i = _areas.begin(); i != _areas.end(); i++) {
 
2021
        if ((*i).first == area) {
 
2022
            if (area != previous_area)
 
2023
                (*i).second->summary_withdraw(previous_area, net,
 
2024
                                              previous_rt);
 
2025
            continue;
 
2026
        }
 
2027
        if ((*i).first == previous_area) {
 
2028
            if (area != previous_area)
 
2029
                (*i).second->summary_announce(area, net, rt, false);
 
2030
            continue;
 
2031
        }
 
2032
        (*i).second->summary_replace(area, net, rt, previous_rt,previous_area);
 
2033
    }
 
2034
}
 
2035
 
 
2036
template <typename A>
 
2037
void
1965
2038
PeerManager<A>::summary_push(OspfTypes::AreaID area)
1966
2039
{
1967
2040
    debug_msg("Area %s\n", pr_id(area).c_str());