LCOV - code coverage report
Current view: top level - bgp - bgp_aspath.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 358 422 84.8 %
Date: 2026-06-08 02:02:55 Functions: 40 43 93.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/bgp_aspath.h"
       6             : 
       7             : #include <boost/assign/list_of.hpp>
       8             : #include <sstream>
       9             : 
      10             : #include "bgp/bgp_proto.h"
      11             : 
      12             : using boost::assign::list_of;
      13             : using std::copy;
      14             : using std::ostringstream;
      15             : using std::string;
      16             : using std::vector;
      17             : 
      18             : //
      19             : // Return the left most AS.
      20             : //
      21      485305 : as2_t AsPathSpec::AsLeftMost() const {
      22      485305 :     if (path_segments.empty())
      23       41129 :         return 0;
      24      444180 :     if (path_segments[0]->path_segment_type == PathSegment::AS_SET)
      25           7 :         return 0;
      26      444171 :     if (path_segments[0]->path_segment.empty())
      27        2171 :         return 0;
      28      441986 :     return (path_segments[0]->path_segment[0]);
      29             : }
      30             : 
      31             : //
      32             : // Return true if left most AS matches the input.
      33             : //
      34       87899 : bool AsPathSpec::AsLeftMostMatch(as2_t as) const {
      35       87899 :     if (path_segments.empty())
      36           0 :         return false;
      37       87899 :     if (path_segments[0]->path_segment.empty())
      38           0 :         return false;
      39       87899 :     return (path_segments[0]->path_segment[0] == as);
      40             : }
      41             : 
      42             : //
      43             : // Return the left most public AS.
      44             : //
      45          24 : as2_t AsPathSpec::AsLeftMostPublic() const {
      46          24 :     for (size_t i = 0; i < path_segments.size(); ++i) {
      47          24 :         PathSegment *ps = path_segments[i];
      48          80 :         for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
      49          80 :             if (!AsIsPrivate(ps->path_segment[j]))
      50          24 :                 return ps->path_segment[j];
      51             :         }
      52             :     }
      53           0 :     return 0;
      54             : }
      55             : 
      56       10003 : int AsPathSpec::CompareTo(const BgpAttribute &rhs_attr) const {
      57       10003 :     int ret = BgpAttribute::CompareTo(rhs_attr);
      58       10003 :     if (ret != 0) return ret;
      59       10003 :     const AsPathSpec &rhs = static_cast<const AsPathSpec &>(rhs_attr);
      60       10003 :     KEY_COMPARE(path_segments.size(), rhs.path_segments.size());
      61             : 
      62       20013 :     for (size_t i = 0; i < path_segments.size(); i++) {
      63       10010 :         int ret = path_segments[i]->CompareTo(*rhs.path_segments[i]);
      64       10010 :         if (ret != 0) return ret;
      65             :     }
      66       10003 :     return 0;
      67             : }
      68             : 
      69      117225 : void AsPathSpec::ToCanonical(BgpAttr *attr) {
      70      117225 :     attr->set_as_path(this);
      71      117225 : }
      72             : 
      73      116772 : string AsPathSpec::ToString() const {
      74      116772 :     ostringstream oss;
      75             : 
      76      210933 :     for (size_t i = 0; i < path_segments.size(); i++) {
      77       94128 :         if (i != 0) oss << " ";
      78       94128 :         switch (path_segments[i]->path_segment_type) {
      79           3 :         case AsPathSpec::PathSegment::AS_SET:
      80           3 :             oss << "{";
      81           3 :             for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++) {
      82           2 :                 if (j != 0) oss << " ";
      83           2 :                 oss << path_segments[i]->path_segment[j];
      84             :             }
      85           1 :             oss << "}";
      86           1 :             break;
      87       94124 :         case AsPathSpec::PathSegment::AS_SEQUENCE:
      88      221594 :             for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++) {
      89      127465 :                 if (j != 0) oss << " ";
      90      127465 :                 oss << path_segments[i]->path_segment[j];
      91             :             }
      92       94127 :             break;
      93           0 :         default:
      94           0 :             break;
      95             :         }
      96             :     }
      97             : 
      98      233604 :     return oss.str();
      99      116800 : }
     100             : 
     101      383374 : size_t AsPathSpec::EncodeLength() const {
     102      383374 :     size_t sz = 0;
     103      602846 :     for (size_t i = 0; i < path_segments.size(); i++) {
     104      219441 :         sz += 2;
     105      219441 :         sz += path_segments[i]->path_segment.size() * 2;
     106             :     }
     107      383362 :     return sz;
     108             : }
     109             : 
     110             : //
     111             : // Check AsPathSpec for loops for the given as.
     112             : // Return true if the number of occurrences of as exceeds given max loop count.
     113             : //
     114      317804 : bool AsPathSpec::AsPathLoop(as2_t as, uint8_t max_loop_count) const {
     115      317804 :     uint8_t loop_count = 0;
     116      477450 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     117      489753 :         for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
     118      330103 :             if (path_segments[i]->path_segment[j] == as &&
     119             :                 ++loop_count > max_loop_count) {
     120      135407 :                 return true;
     121             :             }
     122             :         }
     123             :     }
     124      182421 :     return false;
     125             : }
     126             : 
     127             : //
     128             : // Create a new AsPathSpec by prepending the given asn at the beginning.
     129             : //
     130      202500 : AsPathSpec *AsPathSpec::Add(as2_t asn) const {
     131      202500 :     vector<as2_t> asn_list = list_of(asn);
     132      404903 :     return Add(asn_list);
     133      202457 : }
     134             : 
     135             : //
     136             : // Create a new AsPathSpec by prepending the given vector of asns at the
     137             : // beginning.
     138             : //
     139           3 : AsPathSpec *AsPathSpec::Add(const vector<as_t> &asn_list) const {
     140           3 :     AsPathSpec *new_spec = new AsPathSpec;
     141           3 :     PathSegment *ps = new PathSegment;
     142           3 :     ps->path_segment_type = PathSegment::AS_SEQUENCE;
     143          12 :     for (vector<as_t>::const_iterator it = asn_list.begin(); it !=
     144          18 :                       asn_list.end(); it++) {
     145           6 :         if ((*it) <= AS2_MAX)
     146           6 :             ps->path_segment.push_back((as2_t)(*it));
     147             :     }
     148           3 :     size_t first = 0;
     149           3 :     size_t last = path_segments.size();
     150           4 :     if (last &&
     151           4 :         path_segments[0]->path_segment_type == PathSegment::AS_SEQUENCE &&
     152           1 :         path_segments[0]->path_segment.size() + asn_list.size() <= 255) {
     153           1 :         copy(path_segments[0]->path_segment.begin(),
     154           1 :              path_segments[0]->path_segment.end(),
     155           1 :              back_inserter(ps->path_segment));
     156           1 :         new_spec->path_segments.push_back(ps);
     157           1 :         first++;
     158             :     } else {
     159           2 :         new_spec->path_segments.push_back(ps);
     160             :     }
     161           3 :     if (first == last)
     162           3 :         return new_spec;
     163           0 :     for (size_t idx = first; idx < last; ++idx) {
     164           0 :         PathSegment *ps = new PathSegment;
     165           0 :         *ps = *path_segments[idx];
     166           0 :         new_spec->path_segments.push_back(ps);
     167             :     }
     168           0 :     return new_spec;
     169             : }
     170             : 
     171             : //
     172             : // Create a new AsPathSpec by prepending the given vector of asns at the
     173             : // beginning.
     174             : //
     175      202461 : AsPathSpec *AsPathSpec::Add(const vector<as2_t> &asn_list) const {
     176      202461 :     AsPathSpec *new_spec = new AsPathSpec;
     177      202458 :     PathSegment *ps = new PathSegment;
     178      202447 :     ps->path_segment_type = PathSegment::AS_SEQUENCE;
     179      202447 :     ps->path_segment = asn_list;
     180      202419 :     size_t first = 0;
     181      202419 :     size_t last = path_segments.size();
     182      273925 :     if (last &&
     183      273924 :         path_segments[0]->path_segment_type == PathSegment::AS_SEQUENCE &&
     184       71472 :         path_segments[0]->path_segment.size() + asn_list.size() <= 255) {
     185       71466 :         copy(path_segments[0]->path_segment.begin(),
     186       71468 :              path_segments[0]->path_segment.end(),
     187       71468 :              back_inserter(ps->path_segment));
     188       71466 :         new_spec->path_segments.push_back(ps);
     189       71464 :         first++;
     190             :     } else {
     191      130984 :         new_spec->path_segments.push_back(ps);
     192             :     }
     193      202461 :     if (first == last)
     194      202439 :         return new_spec;
     195          96 :     for (size_t idx = first; idx < last; ++idx) {
     196          74 :         PathSegment *ps = new PathSegment;
     197          74 :         *ps = *path_segments[idx];
     198          74 :         new_spec->path_segments.push_back(ps);
     199             :     }
     200          22 :     return new_spec;
     201             : }
     202             : 
     203             : //
     204             : // Create a new AsPathSpec by replacing the old asn with given asn.
     205             : //
     206          46 : AsPathSpec *AsPathSpec::Replace(as2_t old_asn, as2_t asn) const {
     207          46 :     AsPathSpec *new_spec = new AsPathSpec(*this);
     208          94 :     for (size_t i = 0; i < new_spec->path_segments.size(); ++i) {
     209          48 :         PathSegment *ps = new_spec->path_segments[i];
     210         128 :         for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     211          80 :             if (ps->path_segment[j] == old_asn)
     212          24 :                 ps->path_segment[j] = asn;
     213             :         }
     214             :     }
     215          46 :     return new_spec;
     216             : }
     217             : 
     218             : //
     219             : // Create a new AsPathSpec by removing private asns.  Stop looking for private
     220             : // asns when we encounter the first public asn or the peer asn.
     221             : // If all is true, remove all private asns i.e. do not stop when we encounter
     222             : // the first public asn or the peer asn.
     223             : // If asn is non-zero, replace private asns instead of removing them. Use the
     224             : // nearest public asn as the replacement value.  If we haven't found a public
     225             : // asn, then use the given asn.
     226             : // If peer asn is non-zero, do not remove/replace it.
     227             : //
     228         102 : AsPathSpec *AsPathSpec::RemovePrivate(bool all, as2_t asn, as2_t peer_asn) const {
     229         102 :     bool remove_replace_done = false;
     230         102 :     AsPathSpec *new_spec = new AsPathSpec;
     231         210 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     232         108 :         PathSegment *ps = path_segments[i];
     233         108 :         PathSegment *new_ps = new PathSegment;
     234             : 
     235             :         // We've already removed/replaced all private asns that we can.
     236             :         // Copy the entire segment instead of copying one as2_t at a time.
     237         108 :         if (remove_replace_done) {
     238           4 :             *new_ps = *ps;
     239           4 :             new_spec->path_segments.push_back(new_ps);
     240           4 :             continue;
     241             :         }
     242             : 
     243             :         // Examine each as2_t in the path segment to build a modified version.
     244             :         // Note down that we're done removing/replacing when we see a public
     245             :         // asn or the peer asn.
     246         104 :         new_ps->path_segment_type = ps->path_segment_type;
     247         523 :         for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     248         819 :             if (remove_replace_done ||
     249         694 :                 !AsIsPrivate(ps->path_segment[j]) ||
     250         275 :                 ps->path_segment[j] == peer_asn) {
     251         150 :                 new_ps->path_segment.push_back(ps->path_segment[j]);
     252         150 :                 remove_replace_done = !all;
     253         150 :                 if (asn && !AsIsPrivate(ps->path_segment[j])) {
     254          93 :                     asn = ps->path_segment[j];
     255             :                 }
     256         269 :             } else if (asn) {
     257         190 :                 new_ps->path_segment.push_back(asn);
     258             :             }
     259             :         }
     260             : 
     261             :         // Get rid of the new path segment if it's empty.
     262             :         // Otherwise add it to the new spec.
     263         104 :         if (new_ps->path_segment.empty()) {
     264          10 :             delete new_ps;
     265             :         } else {
     266          94 :             new_spec->path_segments.push_back(new_ps);
     267             :         }
     268             :     }
     269             : 
     270         102 :     return new_spec;
     271             : }
     272             : 
     273        8261 : void AsPath::Remove() {
     274        8261 :     aspath_db_->Delete(this);
     275        8261 : }
     276             : 
     277        9742 : AsPathDB::AsPathDB(BgpServer *server) {
     278        9742 : }
     279             : 
     280             : //
     281             : // Return the left most AS.
     282             : //
     283         225 : as_t AsPath4ByteSpec::AsLeftMost() const {
     284         225 :     if (path_segments.empty())
     285          45 :         return 0;
     286         180 :     if (path_segments[0]->path_segment_type == PathSegment::AS_SET)
     287           0 :         return 0;
     288         180 :     if (path_segments[0]->path_segment.empty())
     289           0 :         return 0;
     290         180 :     return (path_segments[0]->path_segment[0]);
     291             : }
     292             : 
     293             : //
     294             : // Return true if left most AS matches the input.
     295             : //
     296         153 : bool AsPath4ByteSpec::AsLeftMostMatch(as_t as) const {
     297         153 :     if (path_segments.empty())
     298           0 :         return false;
     299         153 :     if (path_segments[0]->path_segment.empty())
     300           0 :         return false;
     301         153 :     return (path_segments[0]->path_segment[0] == as);
     302             : }
     303             : 
     304             : //
     305             : // Return the left most public AS.
     306             : //
     307           0 : as_t AsPath4ByteSpec::AsLeftMostPublic() const {
     308           0 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     309           0 :         PathSegment *ps = path_segments[i];
     310           0 :         for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
     311           0 :             if (!AsIsPrivate(ps->path_segment[j]))
     312           0 :                 return ps->path_segment[j];
     313             :         }
     314             :     }
     315           0 :     return 0;
     316             : }
     317             : 
     318           3 : int AsPath4ByteSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     319           3 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     320           3 :     if (ret != 0) return ret;
     321           3 :     const AsPath4ByteSpec &rhs = static_cast<const AsPath4ByteSpec &>(rhs_attr);
     322           3 :     KEY_COMPARE(path_segments.size(), rhs.path_segments.size());
     323             : 
     324           6 :     for (size_t i = 0; i < path_segments.size(); i++) {
     325           3 :         int ret = path_segments[i]->CompareTo(*rhs.path_segments[i]);
     326           3 :         if (ret != 0) return ret;
     327             :     }
     328           3 :     return 0;
     329             : }
     330             : 
     331          94 : void AsPath4ByteSpec::ToCanonical(BgpAttr *attr) {
     332          94 :     attr->set_aspath_4byte(this);
     333          94 : }
     334             : 
     335          66 : string AsPath4ByteSpec::ToString() const {
     336          66 :     ostringstream oss;
     337             : 
     338          99 :     for (size_t i = 0; i < path_segments.size(); i++) {
     339          33 :         if (i != 0) oss << " ";
     340          33 :         switch (path_segments[i]->path_segment_type) {
     341           0 :         case AsPath4ByteSpec::PathSegment::AS_SET:
     342           0 :             oss << "{";
     343           0 :             for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++) {
     344           0 :                 if (j != 0) oss << " ";
     345           0 :                 oss << path_segments[i]->path_segment[j];
     346             :             }
     347           0 :             oss << "}";
     348           0 :             break;
     349          33 :         case AsPath4ByteSpec::PathSegment::AS_SEQUENCE:
     350          66 :             for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++) {
     351          33 :                 if (j != 0) oss << " ";
     352          33 :                 oss << path_segments[i]->path_segment[j];
     353             :             }
     354          33 :             break;
     355           0 :         default:
     356           0 :             break;
     357             :         }
     358             :     }
     359             : 
     360         132 :     return oss.str();
     361          66 : }
     362             : 
     363         205 : size_t AsPath4ByteSpec::EncodeLength() const {
     364         205 :     size_t sz = 0;
     365         275 :     for (size_t i = 0; i < path_segments.size(); i++) {
     366          70 :         sz += 2;
     367          70 :         sz += path_segments[i]->path_segment.size() * 4;
     368             :     }
     369         205 :     return sz;
     370             : }
     371             : 
     372             : //
     373             : // Check AsPath4ByteSpec for loops for the given as.
     374             : // Return true if the number of occurrences of as exceeds given max loop count.
     375             : //
     376         340 : bool AsPath4ByteSpec::AsPathLoop(as_t as, uint8_t max_loop_count) const {
     377         340 :     uint8_t loop_count = 0;
     378         540 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     379         965 :         for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
     380         765 :             if (path_segments[i]->path_segment[j] == as &&
     381             :                 ++loop_count > max_loop_count) {
     382         123 :                 return true;
     383             :             }
     384             :         }
     385             :     }
     386         217 :     return false;
     387             : }
     388             : 
     389             : //
     390             : // Create a new AsPath4ByteSpec by prepending the given asn at the beginning.
     391             : //
     392         233 : AsPath4ByteSpec *AsPath4ByteSpec::Add(as_t asn) const {
     393         233 :     vector<as_t> asn_list = list_of(asn);
     394         466 :     return Add(asn_list);
     395         233 : }
     396             : 
     397             : //
     398             : // Create a new AsPath4ByteSpec by prepending the given vector of asns at the
     399             : // beginning.
     400             : //
     401         236 : AsPath4ByteSpec *AsPath4ByteSpec::Add(const vector<as_t> &asn_list) const {
     402         236 :     AsPath4ByteSpec *new_spec = new AsPath4ByteSpec;
     403         236 :     PathSegment *ps = new PathSegment;
     404         236 :     ps->path_segment_type = PathSegment::AS_SEQUENCE;
     405         236 :     ps->path_segment = asn_list;
     406         236 :     size_t first = 0;
     407         236 :     size_t last = path_segments.size();
     408         421 :     if (last &&
     409         405 :         path_segments[0]->path_segment_type == PathSegment::AS_SEQUENCE &&
     410         169 :         path_segments[0]->path_segment.size() + asn_list.size() <= 255) {
     411         169 :         copy(path_segments[0]->path_segment.begin(),
     412         169 :              path_segments[0]->path_segment.end(),
     413         169 :              back_inserter(ps->path_segment));
     414         169 :         new_spec->path_segments.push_back(ps);
     415         169 :         first++;
     416             :     } else {
     417          67 :         new_spec->path_segments.push_back(ps);
     418             :     }
     419         236 :     if (first == last)
     420         204 :         return new_spec;
     421          64 :     for (size_t idx = first; idx < last; ++idx) {
     422          32 :         PathSegment *ps = new PathSegment;
     423          32 :         *ps = *path_segments[idx];
     424          32 :         new_spec->path_segments.push_back(ps);
     425             :     }
     426          32 :     return new_spec;
     427             : }
     428             : 
     429             : //
     430             : // Create a new AsPath4ByteSpec by replacing the old asn with given asn.
     431             : //
     432           8 : AsPath4ByteSpec *AsPath4ByteSpec::Replace(as_t old_asn, as_t asn) const {
     433           8 :     AsPath4ByteSpec *new_spec = new AsPath4ByteSpec(*this);
     434          16 :     for (size_t i = 0; i < new_spec->path_segments.size(); ++i) {
     435           8 :         PathSegment *ps = new_spec->path_segments[i];
     436          28 :         for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     437          20 :             if (ps->path_segment[j] == old_asn)
     438           0 :                 ps->path_segment[j] = asn;
     439             :         }
     440             :     }
     441           8 :     return new_spec;
     442             : }
     443             : 
     444             : //
     445             : // Create a new AsPath4ByteSpec by removing private asns.  Stop looking for private
     446             : // asns when we encounter the first public asn or the peer asn.
     447             : // If all is true, remove all private asns i.e. do not stop when we encounter
     448             : // the first public asn or the peer asn.
     449             : // If asn is non-zero, replace private asns instead of removing them. Use the
     450             : // nearest public asn as the replacement value.  If we haven't found a public
     451             : // asn, then use the given asn.
     452             : // If peer asn is non-zero, do not remove/replace it.
     453             : //
     454          24 : AsPath4ByteSpec *AsPath4ByteSpec::RemovePrivate(bool all, as_t asn, as_t peer_asn) const {
     455          24 :     bool remove_replace_done = false;
     456          24 :     AsPath4ByteSpec *new_spec = new AsPath4ByteSpec;
     457          48 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     458          24 :         PathSegment *ps = path_segments[i];
     459          24 :         PathSegment *new_ps = new PathSegment;
     460             : 
     461             :         // We've already removed/replaced all private asns that we can.
     462             :         // Copy the entire segment instead of copying one as_t at a time.
     463          24 :         if (remove_replace_done) {
     464           0 :             *new_ps = *ps;
     465           0 :             new_spec->path_segments.push_back(new_ps);
     466           0 :             continue;
     467             :         }
     468             : 
     469             :         // Examine each as_t in the path segment to build a modified version.
     470             :         // Note down that we're done removing/replacing when we see a public
     471             :         // asn or the peer asn.
     472          24 :         new_ps->path_segment_type = ps->path_segment_type;
     473         100 :         for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     474         152 :             if (remove_replace_done ||
     475         132 :                 !AsIsPrivate(ps->path_segment[j]) ||
     476          56 :                 ps->path_segment[j] == peer_asn) {
     477          20 :                 new_ps->path_segment.push_back(ps->path_segment[j]);
     478          20 :                 remove_replace_done = !all;
     479          20 :                 if (asn && !AsIsPrivate(ps->path_segment[j])) {
     480          16 :                     asn = ps->path_segment[j];
     481             :                 }
     482          56 :             } else if (asn) {
     483          40 :                 new_ps->path_segment.push_back(asn);
     484             :             }
     485             :         }
     486             : 
     487             :         // Get rid of the new path segment if it's empty.
     488             :         // Otherwise add it to the new spec.
     489          24 :         if (new_ps->path_segment.empty()) {
     490           4 :             delete new_ps;
     491             :         } else {
     492          20 :             new_spec->path_segments.push_back(new_ps);
     493             :         }
     494             :     }
     495             : 
     496          24 :     return new_spec;
     497             : }
     498             : 
     499         330 : void AsPath4Byte::Remove() {
     500         330 :     aspath_db_->Delete(this);
     501         330 : }
     502             : 
     503        9742 : AsPath4ByteDB::AsPath4ByteDB(BgpServer *server) {
     504        9742 : }
     505             : 
     506             : //
     507             : // Return the left most AS.
     508             : //
     509           0 : as_t As4PathSpec::AsLeftMost() const {
     510           0 :     if (path_segments.empty())
     511           0 :         return 0;
     512           0 :     if (path_segments[0]->path_segment_type == PathSegment::AS_SET)
     513           0 :         return 0;
     514           0 :     if (path_segments[0]->path_segment.empty())
     515           0 :         return 0;
     516           0 :     return (path_segments[0]->path_segment[0]);
     517             : }
     518             : 
     519             : //
     520             : // Return true if left most AS matches the input.
     521             : //
     522          60 : bool As4PathSpec::AsLeftMostMatch(as_t as) const {
     523          60 :     if (path_segments.empty())
     524           0 :         return false;
     525          60 :     if (path_segments[0]->path_segment.empty())
     526           0 :         return false;
     527          60 :     return (path_segments[0]->path_segment[0] == as);
     528             : }
     529             : 
     530             : //
     531             : // Return the left most public AS.
     532             : //
     533           0 : as_t As4PathSpec::AsLeftMostPublic() const {
     534           0 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     535           0 :         PathSegment *ps = path_segments[i];
     536           0 :         for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
     537           0 :             if (!AsIsPrivate(ps->path_segment[j]))
     538           0 :                 return ps->path_segment[j];
     539             :         }
     540             :     }
     541           0 :     return 0;
     542             : }
     543             : 
     544           1 : int As4PathSpec::CompareTo(const BgpAttribute &rhs_attr) const {
     545           1 :     int ret = BgpAttribute::CompareTo(rhs_attr);
     546           1 :     if (ret != 0) return ret;
     547           1 :     const As4PathSpec &rhs = static_cast<const As4PathSpec &>(rhs_attr);
     548           1 :     KEY_COMPARE(path_segments.size(), rhs.path_segments.size());
     549             : 
     550           2 :     for (size_t i = 0; i < path_segments.size(); i++) {
     551           1 :         int ret = path_segments[i]->CompareTo(*rhs.path_segments[i]);
     552           1 :         if (ret != 0) return ret;
     553             :     }
     554           1 :     return 0;
     555             : }
     556             : 
     557           4 : void As4PathSpec::ToCanonical(BgpAttr *attr) {
     558           4 :     attr->set_as4_path(this);
     559           4 : }
     560             : 
     561           9 : string As4PathSpec::ToString() const {
     562           9 :     ostringstream oss;
     563             : 
     564          18 :     for (size_t i = 0; i < path_segments.size(); i++) {
     565           9 :         if (i != 0) oss << " ";
     566           9 :         switch (path_segments[i]->path_segment_type) {
     567           0 :         case As4PathSpec::PathSegment::AS_SET:
     568           0 :             oss << "{";
     569           0 :             for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++) {
     570           0 :                 if (j != 0) oss << " ";
     571           0 :                 oss << path_segments[i]->path_segment[j];
     572             :             }
     573           0 :             oss << "}";
     574           0 :             break;
     575           9 :         case As4PathSpec::PathSegment::AS_SEQUENCE:
     576          45 :             for (size_t j = 0; j < path_segments[i]->path_segment.size(); j++) {
     577          36 :                 if (j != 0) oss << " ";
     578          36 :                 oss << path_segments[i]->path_segment[j];
     579             :             }
     580           9 :             break;
     581           0 :         default:
     582           0 :             break;
     583             :         }
     584             :     }
     585             : 
     586          18 :     return oss.str();
     587           9 : }
     588             : 
     589          15 : size_t As4PathSpec::EncodeLength() const {
     590          15 :     size_t sz = 0;
     591          25 :     for (size_t i = 0; i < path_segments.size(); i++) {
     592          10 :         sz += 2;
     593          10 :         sz += path_segments[i]->path_segment.size() * 4;
     594             :     }
     595          15 :     return sz;
     596             : }
     597             : 
     598             : //
     599             : // Check As4PathSpec for loops for the given as.
     600             : // Return true if the number of occurrences of as exceeds given max loop count.
     601             : //
     602          20 : bool As4PathSpec::AsPathLoop(as_t as, uint8_t max_loop_count) const {
     603          20 :     uint8_t loop_count = 0;
     604          36 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     605          64 :         for (size_t j = 0; j < path_segments[i]->path_segment.size(); ++j) {
     606          48 :             if (path_segments[i]->path_segment[j] == as &&
     607             :                 ++loop_count > max_loop_count) {
     608           4 :                 return true;
     609             :             }
     610             :         }
     611             :     }
     612          16 :     return false;
     613             : }
     614             : 
     615             : //
     616             : // Create a new As4PathSpec by prepending the given asn at the beginning.
     617             : //
     618         247 : As4PathSpec *As4PathSpec::Add(as_t asn) const {
     619         247 :     vector<as_t> asn_list = list_of(asn);
     620         494 :     return Add(asn_list);
     621         247 : }
     622             : 
     623             : //
     624             : // Create a new As4PathSpec by prepending the given vector of asns at the
     625             : // beginning.
     626             : //
     627         247 : As4PathSpec *As4PathSpec::Add(const vector<as_t> &asn_list) const {
     628         247 :     As4PathSpec *new_spec = new As4PathSpec;
     629         247 :     PathSegment *ps = new PathSegment;
     630         247 :     ps->path_segment_type = PathSegment::AS_SEQUENCE;
     631         247 :     ps->path_segment = asn_list;
     632         247 :     size_t first = 0;
     633         247 :     size_t last = path_segments.size();
     634         469 :     if (last &&
     635         469 :         path_segments[0]->path_segment_type == PathSegment::AS_SEQUENCE &&
     636         222 :         path_segments[0]->path_segment.size() + asn_list.size() <= 255) {
     637         222 :         copy(path_segments[0]->path_segment.begin(),
     638         222 :              path_segments[0]->path_segment.end(),
     639         222 :              back_inserter(ps->path_segment));
     640         222 :         new_spec->path_segments.push_back(ps);
     641         222 :         first++;
     642             :     } else {
     643          25 :         new_spec->path_segments.push_back(ps);
     644             :     }
     645         247 :     if (first == last)
     646         231 :         return new_spec;
     647          32 :     for (size_t idx = first; idx < last; ++idx) {
     648          16 :         PathSegment *ps = new PathSegment;
     649          16 :         *ps = *path_segments[idx];
     650          16 :         new_spec->path_segments.push_back(ps);
     651             :     }
     652          16 :     return new_spec;
     653             : }
     654             : 
     655             : //
     656             : // Create a new As4PathSpec by replacing the old asn with given asn.
     657             : //
     658          12 : As4PathSpec *As4PathSpec::Replace(as_t old_asn, as_t asn) const {
     659          12 :     As4PathSpec *new_spec = new As4PathSpec(*this);
     660          24 :     for (size_t i = 0; i < new_spec->path_segments.size(); ++i) {
     661          12 :         PathSegment *ps = new_spec->path_segments[i];
     662          30 :         for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     663          18 :             if (ps->path_segment[j] == old_asn)
     664           6 :                 ps->path_segment[j] = asn;
     665             :         }
     666             :     }
     667          12 :     return new_spec;
     668             : }
     669             : 
     670             : //
     671             : // Create a new As4PathSpec by removing private asns.  Stop looking for private
     672             : // asns when we encounter the first public asn or the peer asn.
     673             : // If all is true, remove all private asns i.e. do not stop when we encounter
     674             : // the first public asn or the peer asn.
     675             : // If asn is non-zero, replace private asns instead of removing them. Use the
     676             : // nearest public asn as the replacement value.  If we haven't found a public
     677             : // asn, then use the given asn.
     678             : // If peer asn is non-zero, do not remove/replace it.
     679             : //
     680          16 : As4PathSpec *As4PathSpec::RemovePrivate(bool all, as_t asn, as_t peer_asn) const {
     681          16 :     bool remove_replace_done = false;
     682          16 :     As4PathSpec *new_spec = new As4PathSpec;
     683          32 :     for (size_t i = 0; i < path_segments.size(); ++i) {
     684          16 :         PathSegment *ps = path_segments[i];
     685          16 :         PathSegment *new_ps = new PathSegment;
     686             : 
     687             :         // We've already removed/replaced all private asns that we can.
     688             :         // Copy the entire segment instead of copying one as_t at a time.
     689          16 :         if (remove_replace_done) {
     690           0 :             *new_ps = *ps;
     691           0 :             new_spec->path_segments.push_back(new_ps);
     692           0 :             continue;
     693             :         }
     694             : 
     695             :         // Examine each as_t in the path segment to build a modified version.
     696             :         // Note down that we're done removing/replacing when we see a public
     697             :         // asn or the peer asn.
     698          16 :         new_ps->path_segment_type = ps->path_segment_type;
     699          72 :         for (size_t j = 0; j < ps->path_segment.size(); ++j) {
     700         112 :             if (remove_replace_done ||
     701          76 :                 !AsIsPrivate(ps->path_segment[j]) ||
     702          20 :                 ps->path_segment[j] == peer_asn) {
     703          36 :                 new_ps->path_segment.push_back(ps->path_segment[j]);
     704          36 :                 remove_replace_done = !all;
     705          36 :                 if (asn && !AsIsPrivate(ps->path_segment[j])) {
     706          36 :                     asn = ps->path_segment[j];
     707             :                 }
     708          20 :             } else if (asn) {
     709          20 :                 new_ps->path_segment.push_back(asn);
     710             :             }
     711             :         }
     712             : 
     713             :         // Get rid of the new path segment if it's empty.
     714             :         // Otherwise add it to the new spec.
     715          16 :         if (new_ps->path_segment.empty()) {
     716           0 :             delete new_ps;
     717             :         } else {
     718          16 :             new_spec->path_segments.push_back(new_ps);
     719             :         }
     720             :     }
     721             : 
     722          16 :     return new_spec;
     723             : }
     724             : 
     725         441 : void As4Path::Remove() {
     726         441 :     aspath_db_->Delete(this);
     727         441 : }
     728             : 
     729        9742 : As4PathDB::As4PathDB(BgpServer *server) {
     730        9742 : }

Generated by: LCOV version 1.14