xorp

path_attribute.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 
00003 // Copyright (c) 2001-2011 XORP, Inc and Others
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, Version 2, June
00007 // 1991 as published by the Free Software Foundation. Redistribution
00008 // and/or modification of this program under the terms of any other
00009 // version of the GNU General Public License is not permitted.
00010 // 
00011 // This program is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00014 // see the GNU General Public License, Version 2, a copy of which can be
00015 // found in the XORP LICENSE.gpl file.
00016 // 
00017 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00018 // http://xorp.net
00019 
00020 // $XORP: xorp/bgp/path_attribute.hh,v 1.54 2008/12/11 21:05:59 mjh Exp $
00021 
00022 #ifndef __BGP_PATH_ATTRIBUTE_HH__
00023 #define __BGP_PATH_ATTRIBUTE_HH__
00024 
00025 #include "libxorp/xorp.h"
00026 #include "libxorp/ipv4.hh"
00027 #include "libxorp/ipv6.hh"
00028 #include "libxorp/ipnet.hh"
00029 #include "libxorp/ref_ptr.hh"
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 #include <openssl/md5.h>
00040 
00041 #include "exceptions.hh"    // for CorruptMessage exception
00042 #include "aspath.hh"
00043 #include "parameter.hh"
00044 class BGPPeerData;
00045 class BGPPeer;
00046 class BGPMain;
00047 
00048 template <class A>
00049 class AttributeManager;
00050 
00051 
00052 
00078 enum PathAttType {
00079     ORIGIN = 1,
00080     AS_PATH = 2,
00081     NEXT_HOP = 3,
00082     MED = 4,
00083     LOCAL_PREF = 5,
00084     ATOMIC_AGGREGATE = 6,
00085     AGGREGATOR = 7,
00086     COMMUNITY = 8,
00087     ORIGINATOR_ID = 9,
00088     CLUSTER_LIST = 10,
00089     MP_REACH_NLRI = 14,
00090     MP_UNREACH_NLRI = 15,
00091     AS4_PATH = 17,
00092     AS4_AGGREGATOR = 18,
00093     UNKNOWN_TESTING1 = 19, // reserved for testing only - should be one
00094                            // more than the highest known attribute.
00095     UNKNOWN_TESTING2 = 20  // reserved for testing only - should be two
00096                            // more than the highest known attribute.
00097 };
00098 
00099 // MAX_ATTRIBUTE must contain the largest attribute number from the enum above
00100 #define MAX_ATTRIBUTE 20
00101 
00102 class PathAttribute :
00103     public NONCOPYABLE
00104 {
00105 public:
00106     enum Flags {
00107     Optional    = 0x80,
00108     Transitive  = 0x40,
00109     Partial     = 0x20,
00110     Extended    = 0x10,
00111     ValidFlags  = 0xf0,
00112     NoFlags     = 0
00113     };
00114 
00122     static PathAttribute *create(const uint8_t* d, uint16_t max_len,
00123                  size_t& actual_length, 
00124                  const BGPPeerData* peerdata,
00125                  uint32_t ip_version) 
00126     throw(CorruptMessage);
00127 
00134     virtual PathAttribute *clone() const = 0;
00135 
00136     /*
00137      * The destructor, invoked after the derived class' destructors,
00138      * frees the internal representation of the object.
00139      */
00140     virtual ~PathAttribute()            { }
00141 
00142     virtual bool encode(uint8_t* buf, size_t &length, const BGPPeerData* peerdata) const = 0;
00143 
00144 
00148     size_t header_size() const              {
00149     return extended() ? 4 : 3;
00150     }
00154     PathAttType type() const            { return (PathAttType)_type; }
00155 
00159     Flags flags() const             { return (Flags)_flags; }
00160 
00164     void set_partial() { _flags |= Partial; }
00165 
00171     bool operator<(const PathAttribute& him) const;
00172     bool operator==(const PathAttribute& him) const;
00173 
00177     void add_hash(MD5_CTX *context) const   {
00178     size_t length = 4096;
00179     uint8_t buf[4096];
00180     // XXX should probably do something more efficient here
00181     if (!encode(buf, length, NULL)) {
00182         XLOG_WARNING("Insufficient space to encode PA list for MD5 hash\n");
00183     }
00184     MD5_Update(context, buf, length);
00185     }
00186 
00187     virtual string str() const;
00188 
00189     void pretty_print();
00190 
00191     bool optional() const           { return _flags & Optional; }
00192     bool transitive() const         { return _flags & Transitive; }
00193     bool partial() const            { return _flags & Partial; }
00194     bool extended() const           { return _flags & Extended; }
00195     bool well_known() const         { return !optional(); }
00196 
00197 protected:
00205     int sorttype() const            {
00206     return type() == NEXT_HOP ? -1 : type();
00207     }
00208 
00212     PathAttribute(Flags f, PathAttType t)
00213         : _flags(f & ValidFlags), _type(t)  {}
00214 
00219     PathAttribute(const uint8_t *d)
00220         : _flags(d[0] & ValidFlags), _type(d[1])    {}
00221 
00227     uint8_t *set_header(uint8_t *data, size_t payload_size, size_t &wire_size) 
00228     const;
00229 
00233     static size_t length(const uint8_t* d)  {
00234     return (d[0] & Extended) ?
00235         ( (d[2]<<8) + d[3] ) : d[2] ;
00236     }
00237 
00242     static size_t total_tlv_length(const uint8_t* d) {
00243     return length(d) + ((d[0] & Extended) ? 4 : 3);
00244     }
00245 
00246     // helper function returning a pointer to the payload
00247     const uint8_t *payload(const uint8_t *d)    {
00248     return d + ((d[0] & Extended) ? 4 : 3);
00249     }
00250 
00251 #if 0
00252     // storage for information in the attribute.
00253 
00254     size_t  _size;  // this is only the size of the payload.
00255     uint8_t *   _data;  // wire representation
00256 #endif
00257     uint8_t _flags;
00258     uint8_t _type;
00259 
00260 private:
00261     PathAttribute();    // Not directly constructible.
00262 };
00263 
00264 
00265 // Origin values
00266 enum OriginType {
00267     IGP = 0,
00268     EGP = 1,
00269     INCOMPLETE = 2
00270 };
00271 
00276 class OriginAttribute : public PathAttribute
00277 {
00278 public:
00279     OriginAttribute(OriginType t);
00280     OriginAttribute(const uint8_t* d) throw(CorruptMessage);
00281     PathAttribute *clone() const;
00282 
00283     string str() const;
00284 
00285     OriginType origin() const           { return _origin; }
00286 
00287     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00288 
00289 private:
00290     OriginType  _origin;
00291 };
00292 
00297 class ASPathAttribute : public PathAttribute
00298 {
00299 public:
00300     ~ASPathAttribute()              { delete _as_path; }
00301 
00302     ASPathAttribute(const ASPath& p);
00303     ASPathAttribute(const uint8_t* d, bool use_4byte_asnums) 
00304     throw(CorruptMessage);
00305     PathAttribute *clone() const;
00306 
00307     string str() const              {
00308     return "AS Path Attribute " + as_path().str();
00309     }
00310 
00311     ASPath &as_path() const     { return (ASPath &)*_as_path; }
00312     AS4Path &as4_path() const       { return (AS4Path &)*_as_path;}
00313 
00314     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00315 
00316 private:
00317     ASPath *_as_path;
00318 };
00319 
00324 class AS4PathAttribute : public PathAttribute
00325 {
00326 public:
00327     ~AS4PathAttribute()             { delete _as_path; }
00328 
00329     AS4PathAttribute(const AS4Path& p);
00330     AS4PathAttribute(const uint8_t* d) throw(CorruptMessage);
00331     PathAttribute *clone() const;
00332 
00333     string str() const              {
00334     return "AS4 Path Attribute " + as_path().str();
00335     }
00336 
00337     ASPath &as_path() const     { return (ASPath &)*_as_path; }
00338     AS4Path &as4_path() const       { return (AS4Path &)*_as_path;}
00339 
00340     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00341 
00342 private:
00343     AS4Path *_as_path;
00344 };
00345 
00349 template <class A>
00350 class NextHopAttribute : public PathAttribute
00351 {
00352 public:
00353     NextHopAttribute(const A& n) throw(CorruptMessage);
00354     NextHopAttribute(const uint8_t* d) throw(CorruptMessage);
00355     PathAttribute *clone() const;
00356 
00357     /* Throw exception if there are problems...do nothing
00358      * otherwise.
00359      */
00360     void verify() throw(CorruptMessage);
00361 
00362     string str() const              {
00363     return "Next Hop Attribute " + _next_hop.str();
00364     }
00365 
00366     A& nexthop()            { return _next_hop; }
00367     // This method is for use in MPReachNLRIAttribute only.
00368     void set_nexthop(const A& n)        { _next_hop = n; }
00369 
00370     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00371 
00372 private:
00373     A _next_hop;
00374 };
00375 
00376 typedef NextHopAttribute<IPv4> IPv4NextHopAttribute;
00377 typedef NextHopAttribute<IPv6> IPv6NextHopAttribute;
00378 
00379 
00383 class MEDAttribute : public PathAttribute
00384 {
00385 public:
00386     MEDAttribute(const uint32_t med);
00387     MEDAttribute(const uint8_t* d) throw(CorruptMessage);
00388     PathAttribute *clone() const;
00389 
00390     string str() const;
00391 
00392     uint32_t med() const            { return _med; }
00393 
00394     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00395 
00396 private:
00397     uint32_t _med;  // XXX stored in host format!
00398 };
00399 
00400 
00404 class LocalPrefAttribute : public PathAttribute
00405 {
00406 public:
00407     LocalPrefAttribute(const uint32_t localpref);
00408     LocalPrefAttribute(const uint8_t* d) throw(CorruptMessage);
00409     PathAttribute *clone() const;
00410 
00411     string str() const;
00412 
00413     uint32_t localpref() const          { return _localpref; }
00414     static uint32_t default_value() {
00415     // The default Local Preference value is 100 according to Halabi.
00416     // This should probably be a configuration option.
00417     return 100;
00418     }
00419 
00420     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00421 
00422 private:
00423     uint32_t _localpref;
00424 
00425 };
00426 
00427 class AtomicAggAttribute : public PathAttribute
00428 {
00429 public:
00430     AtomicAggAttribute();
00431     AtomicAggAttribute(const uint8_t* d) throw(CorruptMessage);
00432     PathAttribute *clone() const;
00433 
00434     string str() const              {
00435     return "Atomic Aggregate Attribute";
00436     }
00437 
00438     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00439 
00440 private:
00441 };
00442 
00443 class AggregatorAttribute : public PathAttribute
00444 {
00445 public:
00446     AggregatorAttribute(const IPv4& speaker, const AsNum& as);
00447     AggregatorAttribute(const uint8_t* d, bool use_4byte_asnums) throw(CorruptMessage);
00448     PathAttribute *clone() const;
00449 
00450     string str() const;
00451 
00452     const IPv4& route_aggregator() const    { return _speaker; }
00453     const AsNum& aggregator_as() const      { return _as; }
00454 
00455     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00456 
00457 private:
00458     IPv4 _speaker;
00459     AsNum _as;
00460 };
00461 
00462 class AS4AggregatorAttribute : public PathAttribute
00463 {
00464 public:
00465     AS4AggregatorAttribute(const IPv4& speaker, const AsNum& as);
00466     AS4AggregatorAttribute(const uint8_t* d) throw(CorruptMessage);
00467     PathAttribute *clone() const;
00468 
00469     string str() const;
00470 
00471     const IPv4& route_aggregator() const    { return _speaker; }
00472     const AsNum& aggregator_as() const      { return _as; }
00473 
00474     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00475 
00476 private:
00477     IPv4 _speaker;
00478     AsNum _as;
00479 };
00480 
00481 class CommunityAttribute : public PathAttribute
00482 {
00483 public:
00484     static const uint32_t NO_EXPORT = 0xFFFFFF01;  // RFC 1997
00485     static const uint32_t NO_ADVERTISE = 0xFFFFFF02;  // RFC 1997
00486     static const uint32_t NO_EXPORT_SUBCONFED = 0xFFFFFF03;  // RFC 1997
00487 
00488     typedef set <uint32_t>::const_iterator const_iterator;
00489     CommunityAttribute();
00490     CommunityAttribute(const uint8_t* d) throw(CorruptMessage);
00491     PathAttribute *clone() const;
00492 
00493     string str() const;
00494 
00495     const set <uint32_t>& community_set() const { return _communities; }
00496     void add_community(uint32_t community);
00497     bool contains(uint32_t community) const;
00498 
00499     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00500 
00501 private:
00502     set <uint32_t> _communities;
00503 };
00504 
00508 class OriginatorIDAttribute : public PathAttribute
00509 {
00510 public:
00511     OriginatorIDAttribute(const IPv4 originator_id);
00512     OriginatorIDAttribute(const uint8_t* d) throw(CorruptMessage);
00513     PathAttribute *clone() const;
00514 
00515     string str() const;
00516 
00517     IPv4 originator_id() const     { return _originator_id; }
00518 
00519     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00520 
00521 private:
00522     IPv4 _originator_id;    
00523 };
00524 
00525 class ClusterListAttribute : public PathAttribute
00526 {
00527 public:
00528     typedef list <IPv4>::const_iterator const_iterator;
00529     ClusterListAttribute();
00530     ClusterListAttribute(const uint8_t* d) throw(CorruptMessage);
00531     PathAttribute *clone() const;
00532 
00533     string str() const;
00534 
00535     const list <IPv4>& cluster_list() const { return _cluster_list; }
00536     void prepend_cluster_id(IPv4 cluster_id);
00537     bool contains(IPv4 cluster_id) const;
00538 
00539     bool encode(uint8_t* buf, size_t &wire_size, const BGPPeerData* peerdata) const;
00540 
00541 private:
00542     list <IPv4> _cluster_list;
00543 };
00544 
00545 
00546 template <class A>
00547 class MPReachNLRIAttribute : public PathAttribute
00548 {
00549 public:
00550     typedef typename list<IPNet<A> >::const_iterator const_iterator;
00551 
00555     MPReachNLRIAttribute(Safi safi);
00556     MPReachNLRIAttribute(const uint8_t* d) throw(CorruptMessage);
00557     PathAttribute *clone() const;
00558 
00559     string str() const;
00560 
00561     const A& nexthop() const        { return _nexthop; }
00562     void set_nexthop(const A& nexthop)  { _nexthop = nexthop; }
00563 
00564     void add_nlri(const IPNet<A>& nlri) {_nlri.push_back(nlri);}
00565     const list<IPNet<A> >& nlri_list() const { return _nlri;}
00566 
00567     // IPv6 specific
00568     const A& link_local_nexthop() const { return _link_local_next_hop; }
00569     void set_link_local_nexthop(const A& n) { _link_local_next_hop = n;}
00570 
00571     // SNPA - Don't deal. (ATM, FRAME RELAY, SMDS)
00572 
00573     Safi safi() const           { return _safi; }
00574 
00575     bool encode(uint8_t* buf, size_t &wire_size, 
00576         const BGPPeerData* peerdata) const;
00577 
00578 private:
00579 
00580     Afi _afi;           // Address Family Identifier.
00581     Safi _safi;         // Subsequent Address Family Identifier.
00582     
00583     A _nexthop;         // Next Hop.
00584 //     list<A> _snpa;       // Subnetwork point of attachment.
00585     list<IPNet<A> > _nlri;  // Network level reachability information.
00586 
00587     A _link_local_next_hop; // Link local next hop IPv6 specific.
00588 };
00589 
00590 template <class A>
00591 class MPUNReachNLRIAttribute : public PathAttribute
00592 {
00593 public:
00594     typedef typename list<IPNet<A> >::const_iterator const_iterator;
00595 
00599     MPUNReachNLRIAttribute(Safi safi);
00600     MPUNReachNLRIAttribute(const uint8_t* d) throw(CorruptMessage);
00601     PathAttribute *clone() const;
00602 
00603     string str() const;
00604 
00605     void add_withdrawn(const IPNet<A>& nlri) {_withdrawn.push_back(nlri);}
00606     const list<IPNet<A> >& wr_list() const { return _withdrawn;}
00607 
00608     Safi safi() const           { return _safi; }
00609 
00610     bool encode(uint8_t* buf, size_t &wire_size, 
00611         const BGPPeerData* peerdata) const;
00612 
00613 private:
00614 
00615     Afi _afi;           // Address Family Identifier.
00616     Safi _safi;         // Subsequent Address Family Identifier.
00617     
00618     list<IPNet<A> > _withdrawn; // Withdrawn routes.
00619 };
00620 
00621 class UnknownAttribute : public PathAttribute
00622 {
00623 public:
00624     UnknownAttribute(const uint8_t* d) throw(CorruptMessage);
00625     UnknownAttribute(uint8_t *data, size_t size, uint8_t flags);
00626     PathAttribute *clone() const;
00627 
00628     string str() const;
00629 
00630     bool encode(uint8_t* buf, size_t &wire_size, 
00631         const BGPPeerData* peerdata) const;
00632 
00633 private:
00634     // storage for information in the attribute.
00635 
00636     size_t  _size;  // this is only the size of the payload.
00637     uint8_t *   _data;  // wire representation
00638 };
00639 
00640 /* it ought to be possible to typedef this, but I don't know how */
00641 #define FPAListRef ref_ptr<FastPathAttributeList<A> >
00642 #define FPAList4Ref ref_ptr<FastPathAttributeList<IPv4> >
00643 #define FPAList6Ref ref_ptr<FastPathAttributeList<IPv6> >
00644 
00645 template<class A>
00646 class FastPathAttributeList;
00647 
00657 template<class A>
00658 class PathAttributeList {
00659 public:
00660     typedef list<PathAttribute*>::const_iterator const_iterator;
00661     typedef list<PathAttribute*>::iterator iterator;
00662 
00663     PathAttributeList();
00664     PathAttributeList(const PathAttributeList<A>& palist);
00665     PathAttributeList(FPAListRef& fpa_list);
00666     virtual ~PathAttributeList();
00667 
00668 
00669     // complete() is true when all the mandatory attributes are present
00670     // normally call this on a FastPathAttributeList
00671     //virtual bool complete() const;
00672 
00673 
00674 
00675     string str() const;
00676 
00677     /* operator< is used to store and search for PathAttributeLists in
00678        STL containers.  In principle, it doesn't matter what the order
00679        is, so long as there is a strict monotonicity to the ordering */
00680     /* In practice, the ordering is important - we want
00681        PathAttributesLists to be ordered first in order of NextHop, as
00682        this makes the RIB-In's task much easier when a nexthop changes */
00683     bool operator< (const PathAttributeList<A> &them) const;
00684 
00685     bool operator== (const PathAttributeList<A> &them) const;
00686 
00687     const uint8_t* canonical_data() const {return _canonical_data;}
00688     size_t canonical_length() const {return _canonical_length;}
00689 
00690     void incr_refcount(uint32_t change) const {
00691     XLOG_ASSERT(0xffffffff - change > _refcount);
00692     _refcount += change;
00693     //  printf("incr_refcount for %p: now %u\n", this, _refcount);
00694     }
00695 
00696     void decr_refcount(uint32_t change) const {
00697     XLOG_ASSERT(_refcount >= change);
00698     _refcount -= change;
00699     //  printf("decr_refcount for %p: now %u\n", this, _refcount);
00700     if (_refcount == 0 && _managed_refcount == 0) {
00701         delete this;
00702     }
00703     }
00704     
00705     uint32_t references() const { return _refcount; }
00706 
00707 
00708     void incr_managed_refcount(uint32_t change) const {
00709     XLOG_ASSERT(0xffffffff - change > _managed_refcount);
00710     _managed_refcount += change;
00711     //  printf("incr_managed_refcount for %p: now %u\n", this, _managed_refcount);
00712     }
00713 
00714     void decr_managed_refcount(uint32_t change) const {
00715     XLOG_ASSERT(_refcount >= change);
00716     _managed_refcount -= change;
00717     //  printf("decr_managed_refcount for %p: now %u\n", this, _managed_refcount);
00718     if (_refcount == 0 && _managed_refcount == 0) {
00719         delete this;
00720     }
00721     }
00722     
00723     uint32_t managed_references() const { return _managed_refcount; }
00724 
00725 protected:
00726     // Canonical data is the path attribute list stored in BGP wire
00727     // format in the most canonical form we know.  For example, AS
00728     // numbers are always 4-byte.  Note that as we speak IPv6, there
00729     // should be no IPv6 NLRI path attributes in here.  They're in the
00730     // prefix instead.  When we send to a particular peer, we will
00731     // typically re-encode a path attribute for that peer, so this
00732     // should not be sent directly - it's only for internal storage.
00733     uint8_t* _canonical_data;
00734     uint16_t _canonical_length;
00735 
00736 private:
00737     //    void assert_rehash() const;
00738     //    const PathAttribute* find_attribute_by_type(PathAttType type) const;
00739 
00740     // ref count is the number of FastPathAttributeList objects
00741     // currently referencing this PathAttributeList.  It's used to
00742     // avoid premature deletion, and to keep track if we've asked for
00743     // this to be deleted.
00744     mutable uint32_t _refcount;
00745 
00746     // managed refcount is the number of routes referencing this PA
00747     // list when this PA list is stored in the attribute manager.
00748     mutable uint32_t _managed_refcount;
00749 
00750     //    uint8_t           _hash[16];  // used for fast comparisons
00751 };
00752 
00753 template<class A>
00754 class PAListRef {
00755 public:
00756     PAListRef(const PathAttributeList<A>* _palist);
00757     PAListRef(const PAListRef& palistref);
00758     PAListRef() : _palist(0) {}
00759     ~PAListRef();
00760     PAListRef& operator=(const PAListRef& palistref);
00761     PAListRef& operator=(FPAListRef& fpalistref);
00762     bool operator==(const PAListRef& palistref) const;
00763     bool operator<(const PAListRef& palistref) const;
00764     const PathAttributeList<A>* operator->() const {
00765     return _palist;
00766     }
00767     const PathAttributeList<A>* operator*() const {
00768     return _palist;
00769     }
00770 
00771     void register_with_attmgr();
00772     void deregister_with_attmgr();
00773 
00774     inline bool is_empty() const {return _palist == 0;}
00775     void release();
00776     const PathAttributeList<A>* attributes() const {return _palist;}
00777     void create_attribute_manager() {
00778     _att_mgr = new AttributeManager<A>();
00779     };
00780 
00784     int number_of_managed_atts() const {
00785     return _att_mgr->number_of_managed_atts();
00786     }
00787 
00788 private:
00789     // this ought not be a pointer, but the the two classes would
00790     // mutually self-reference, and you can't do that.
00791     static AttributeManager<A> *_att_mgr;
00792 
00793     const PathAttributeList<A>* _palist;
00794 };
00795 
00796 
00797 /* FastPathAttributeList is an subclass of a PathAttributeList that is
00798    used to quickly access the path attributes.  It takes a slave
00799    PathAttributeList if it is constructed from one, rather than using
00800    its own storage, because it is intended to be transient and the
00801    slave is intended to be more permanent, so we typically want the
00802    slave to persist when this is deleted */
00803 
00804 template<class A>
00805 class FastPathAttributeList /*: public PathAttributeList<A>*/ {
00806 public:
00807     FastPathAttributeList(PAListRef<A>& palist);
00808     FastPathAttributeList(FastPathAttributeList<A>& fpalist);
00809     FastPathAttributeList(const NextHopAttribute<A> &nexthop,
00810               const ASPathAttribute &aspath,
00811               const OriginAttribute &origin);
00812     FastPathAttributeList();
00813     virtual ~FastPathAttributeList();
00814 
00820     void load_raw_data(const uint8_t *data, size_t size, 
00821                const BGPPeerData* peer, bool have_nlri,
00822                BGPMain *mainprocess,
00823                bool do_checks);
00824 
00825 
00826     /* see commemt on _locked variable */
00827     void lock() const { 
00828     XLOG_ASSERT(_locked == false);
00829     _locked = true;
00830     }
00831     void unlock() const { 
00832     XLOG_ASSERT(_locked == true);
00833     _locked = false;
00834     }
00835 
00836     bool is_locked() const {return _locked;}
00837 
00838     // All known attributes need accessor methods here
00839     NextHopAttribute<A>* nexthop_att();
00840     ASPathAttribute* aspath_att();
00841     AS4PathAttribute* as4path_att();
00842     OriginAttribute* origin_att();
00843     MEDAttribute* med_att();
00844     LocalPrefAttribute* local_pref_att();
00845     AtomicAggAttribute* atomic_aggregate_att();
00846     AggregatorAttribute* aggregator_att();
00847     CommunityAttribute* community_att();
00848     OriginatorIDAttribute* originator_id();
00849     ClusterListAttribute* cluster_list();
00850     template <typename A2> MPReachNLRIAttribute<A2> *mpreach(Safi) ;
00851     template <typename A2> MPUNReachNLRIAttribute<A2> *mpunreach(Safi);
00852 
00853 
00854 
00855     // short cuts
00856     A& nexthop();
00857     ASPath& aspath();
00858     OriginType origin();
00859 
00860     // complete() is true when all the mandatory attributes are present
00861     virtual bool complete() const           {
00862     return ((_att_bytes[NEXT_HOP] || _att[NEXT_HOP]) &&
00863         (_att_bytes[AS_PATH] || _att[AS_PATH]) && 
00864         (_att_bytes[ORIGIN] || _att[ORIGIN]));
00865     }
00866 
00870     void add_path_attribute(const PathAttribute &att);
00871 
00875     void add_path_attribute(PathAttribute *att);
00876 
00880     PathAttribute* find_attribute_by_type(PathAttType type);
00881 
00885     int max_att() const {return _att.size();}
00886 
00892     void process_unknown_attributes();
00893 
00894     void replace_nexthop(const A& nexthop);
00895     void replace_AS_path(const ASPath& as_path);
00896     void replace_origin(const OriginType& origin);
00897     void remove_attribute_by_type(PathAttType type);
00898     void remove_attribute_by_pointer(PathAttribute*);
00899   
00917     bool encode(uint8_t* buf, size_t &wire_size, 
00918         const BGPPeerData* peerdata) const;
00919 
00920     string str() const;
00921 
00922     void canonicalize() const;
00923     const uint8_t* canonical_data() const {return _canonical_data;}
00924     size_t canonical_length() const {return _canonical_length;}
00925     bool canonicalized() const {return _canonicalized;}
00926 
00927     bool operator==(const FastPathAttributeList<A>& him) const;
00928 
00929     bool is_empty() const {
00930     return _attribute_count == 0;
00931     }
00932 
00933     int attribute_count() const {return _attribute_count;}
00934 
00935 private:
00936     void quick_decode(const uint8_t *canonical_data, uint16_t canonical_length);
00937     void replace_attribute(PathAttribute *att);
00938 
00939     uint32_t att_order(uint32_t index) const {
00940     switch(index) {
00941     case 1:
00942         return (uint32_t)NEXT_HOP;
00943     case 2:
00944         return (uint32_t)ORIGIN;
00945     case 3:
00946         return (uint32_t)AS_PATH;
00947     default:
00948         return index;
00949     }
00950     }
00951 
00952     void count_attributes() {
00953     _attribute_count = 0;
00954     for (uint32_t i = 0; i < _att.size(); i++) {
00955         if (_att[i]) {
00956         _attribute_count++;
00957         continue;
00958         }
00959         if (i <= MAX_ATTRIBUTE && _att_bytes[i])
00960         _attribute_count++;
00961     }
00962     }
00963 
00964 
00971     bool encode_and_decode_attribute(const uint8_t* att_data,
00972                      const size_t& att_len,
00973                      uint8_t *buf,
00974                      size_t& wire_size ,
00975                      const BGPPeerData* peerdata) const;
00976 
00977     const PAListRef<A> _slave_pa_list;
00978 
00979     // Break out of the path attribute list by type for quick access.
00980     // bytes and lengths include the header so we preserve the flags.
00981     // _att is only filled out on demand.  These can be arrays because
00982     // we don't fill them out unless they're attributes we know about,
00983     // so the maximum size is bounded.
00984     const uint8_t* _att_bytes[MAX_ATTRIBUTE+1];
00985     size_t _att_lengths[MAX_ATTRIBUTE+1];
00986 
00987     // This is mutable because the nominal content of the class
00988     // doesn't change, but we cache the result we calculate in const
00989     // methods.  
00990     // We use a vector here because we want to be able to
00991     // resize it if we see an unknown path attribute that is greater
00992     // than MAX_ATTRIBUTE.
00993     mutable vector<PathAttribute*> _att;
00994 
00998     int _attribute_count;
00999 
01009     mutable bool _locked;
01010 
01011     // Canonical data is the path attribute list stored in BGP wire
01012     // format in the most canonical form we know.  For example, AS
01013     // numbers are always 4-byte.  Note that as we speak IPv6, there
01014     // should be no IPv6 NLRI path attributes in here.  They're in the
01015     // prefix instead.  When we send to a particular peer, we will
01016     // typically re-encode a path attribute for that peer, so this
01017     // should not be sent directly - it's only for internal storage.
01018     mutable uint8_t* _canonical_data;
01019     mutable uint16_t _canonical_length;
01020     mutable bool _canonicalized; // is the canonical data up-to-date?
01021 };
01022 
01023 template<class A>
01024 template<class A2>
01025 MPReachNLRIAttribute<A2>*
01026 FastPathAttributeList<A>::mpreach(Safi safi)
01027 {
01028     debug_msg("%p\n", this);
01029     PathAttribute* att = find_attribute_by_type(MP_REACH_NLRI);
01030     MPReachNLRIAttribute<A2>* mp_att 
01031     = dynamic_cast<MPReachNLRIAttribute<A2>*>(att);
01032     if (mp_att && safi == mp_att->safi())
01033     return mp_att;
01034     return 0;
01035 }
01036 
01037 template<class A>
01038 template<class A2>
01039 MPUNReachNLRIAttribute<A2>*
01040 FastPathAttributeList<A>::mpunreach(Safi safi)
01041 {
01042     debug_msg("%p\n", this);
01043     PathAttribute* att = find_attribute_by_type(MP_UNREACH_NLRI);
01044     MPUNReachNLRIAttribute<A2>* mp_att 
01045     = dynamic_cast<MPUNReachNLRIAttribute<A2>*>(att);
01046     if (mp_att && safi == mp_att->safi())
01047     return mp_att;
01048     return 0;
01049 }
01050 
01051 
01052 
01053 #endif // __BGP_PATH_ATTRIBUTE_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations