LCOV - code coverage report
Current view: top level - bgp/mvpn - mvpn_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 571 641 89.1 %
Date: 2026-11-09 02:10:49 Functions: 38 38 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/mvpn/mvpn_route.h"
       7             : 
       8             : #include <algorithm>
       9             : #include <string>
      10             : #include <vector>
      11             : 
      12             : #include "base/string_util.h"
      13             : #include "bgp/mvpn/mvpn_table.h"
      14             : 
      15             : using boost::system::errc::invalid_argument;
      16             : using boost::system::error_code;
      17             : using std::copy;
      18             : using std::string;
      19             : using std::vector;
      20             : 
      21             : const size_t MvpnPrefix::kRdSize = RouteDistinguisher::kSize;
      22             : const size_t MvpnPrefix::kAsnSize = 4;
      23             : const size_t MvpnPrefix::kIp4AddrSize = Address::kMaxV4Bytes;
      24             : const size_t MvpnPrefix::kIp4AddrBitSize = Address::kMaxV4PrefixLen;
      25             : 
      26             : const size_t MvpnPrefix::kPrefixBytes = 2;
      27             : const size_t MvpnPrefix::kIntraASPMSIADRouteSize = kRdSize + kIp4AddrSize;
      28             : const size_t MvpnPrefix::kInterASPMSIADRouteSize = kRdSize + kAsnSize;
      29             : const size_t MvpnPrefix::kSPMSIADRouteSize =
      30             :                           kRdSize + 2 * (1 + kIp4AddrSize) + kIp4AddrSize;
      31             : const size_t MvpnPrefix::kSourceActiveADRouteSize =
      32             :                                          kRdSize + 2 * (1 + kIp4AddrSize);
      33             : const size_t MvpnPrefix::kSourceTreeJoinRouteSize =
      34             :                               kRdSize + kAsnSize + 2 * (1 + kIp4AddrSize);
      35             : 
      36      229884 : MvpnPrefix::MvpnPrefix() : type_(MvpnPrefix::Unspecified), ip_prefixlen_(0),
      37      114942 :         asn_(0) {
      38      114942 : }
      39             : 
      40           2 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      41           2 :     const uint32_t asn)
      42           2 :     : type_(type), rd_(rd), ip_prefixlen_(0), asn_(asn) {
      43             : 
      44           2 :     assert(type == InterASPMSIADRoute);
      45           2 : }
      46             : 
      47        3048 : MvpnPrefix::MvpnPrefix(uint8_t type, const Ip4Address &originator)
      48        3048 :     : type_(type), originator_(originator), ip_prefixlen_(0), asn_(0) {
      49             : 
      50        3048 :     assert(type == LeafADRoute);
      51        3048 : }
      52             : 
      53      112754 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      54      112754 :     const Ip4Address &originator)
      55      112754 :     : type_(type), rd_(rd), originator_(originator), ip_prefixlen_(0),
      56      112754 :       asn_(0) {
      57             : 
      58      112754 :     assert(type == IntraASPMSIADRoute);
      59      112754 : }
      60             : 
      61          89 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      62          89 :     const Ip4Address &group, const Ip4Address &source)
      63         178 :     : type_(type), rd_(rd), group_(group), source_(source),
      64         178 :       ip_prefixlen_(0), asn_(0) {
      65             : 
      66          89 :     assert(type == SourceActiveADRoute);
      67          89 : }
      68             : 
      69        4508 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      70             :     const Ip4Address &originator,
      71        4508 :     const Ip4Address &group, const Ip4Address &source)
      72        4508 :     : type_(type), rd_(rd), originator_(originator),
      73        4508 :       group_(group), source_(source), ip_prefixlen_(0), asn_(0) {
      74             : 
      75        4508 :     assert(type == SPMSIADRoute);
      76        4508 : }
      77             : 
      78       24404 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      79       24404 :     const uint32_t asn, const Ip4Address &group, const Ip4Address &source)
      80       48808 :     : type_(type), rd_(rd), group_(group), source_(source), ip_prefixlen_(0),
      81       48808 :       asn_(asn) {
      82             : 
      83       24404 :     assert((type == SharedTreeJoinRoute) || (type == SourceTreeJoinRoute));
      84       24404 : }
      85             : 
      86        7564 : Ip4Address MvpnPrefix::GetType3OriginatorFromType4Route() const {
      87        7564 :         size_t originator_offset = rt_key_.size() - kIp4AddrSize;
      88             :         return Ip4Address(get_value
      89        7564 :                 (&rt_key_[originator_offset], kIp4AddrSize));
      90             : }
      91             : 
      92         343 : int MvpnPrefix::SpmsiAdRouteFromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      93             :     MvpnPrefix *prefix, size_t rd_offset) {
      94         343 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      95         343 :     size_t source_offset = rd_offset + kRdSize;
      96         343 :     if (proto_prefix.prefix[source_offset++] != kIp4AddrBitSize)
      97           4 :         return -1;
      98         339 :     prefix->source_ = Ip4Address(get_value(
      99         678 :             &proto_prefix.prefix[source_offset], kIp4AddrSize));
     100             : 
     101         339 :     size_t group_offset = source_offset + kIp4AddrSize;
     102         339 :     if (proto_prefix.prefix[group_offset++] != kIp4AddrBitSize)
     103           5 :         return -1;
     104         334 :     prefix->group_ = Ip4Address(get_value(
     105         668 :             &proto_prefix.prefix[group_offset], kIp4AddrSize));
     106         334 :     size_t originator_offset = group_offset + kIp4AddrSize;
     107         334 :     prefix->originator_ = Ip4Address(get_value(
     108         668 :             &proto_prefix.prefix[originator_offset], kIp4AddrSize));
     109         334 :     return 0;
     110             : }
     111             : 
     112        1698 : int MvpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
     113             :     MvpnPrefix *prefix) {
     114        1698 :     size_t nlri_size = proto_prefix.prefix.size();
     115             : 
     116        1698 :     prefix->type_ = proto_prefix.type;
     117        1698 :     switch (prefix->type_) {
     118        1061 :     case IntraASPMSIADRoute: {
     119        1061 :         size_t expected_nlri_size = kIntraASPMSIADRouteSize;
     120        1061 :         if (nlri_size != expected_nlri_size)
     121           0 :             return -1;
     122        1061 :         size_t rd_offset = 0;
     123        1061 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     124        1061 :         size_t originator_offset = rd_offset + kRdSize;
     125        1061 :         prefix->originator_ = Ip4Address(get_value(
     126        2122 :             &proto_prefix.prefix[originator_offset], kIp4AddrSize));
     127        1061 :         break;
     128             :     }
     129           0 :     case InterASPMSIADRoute: {
     130           0 :         size_t expected_nlri_size = kInterASPMSIADRouteSize;
     131           0 :         if (nlri_size != expected_nlri_size)
     132           0 :             return -1;
     133           0 :         size_t rd_offset = 0;
     134           0 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     135           0 :         size_t asn_offset = rd_offset + kRdSize;
     136           0 :         prefix->asn_ = get_value(&proto_prefix.prefix[asn_offset], kAsnSize);
     137           0 :         break;
     138             :     }
     139         156 :     case SPMSIADRoute: {
     140         156 :         size_t expected_nlri_size = kSPMSIADRouteSize;
     141         156 :         if (nlri_size != expected_nlri_size)
     142           3 :             return -1;
     143         153 :         if (SpmsiAdRouteFromProtoPrefix(proto_prefix, prefix, 0))
     144           8 :             return -1;
     145         145 :         break;
     146             :     }
     147         190 :     case LeafADRoute: {
     148             :         size_t expected_nlri_size;
     149         190 :         if (proto_prefix.prefix[0] == SPMSIADRoute) {
     150         190 :             expected_nlri_size = kPrefixBytes + kSPMSIADRouteSize +
     151             :                                  kIp4AddrSize;
     152           0 :         } else if (proto_prefix.prefix[0] == InterASPMSIADRoute) {
     153           0 :             expected_nlri_size = kPrefixBytes + kInterASPMSIADRouteSize +
     154             :                                  kIp4AddrSize;
     155             :         } else {
     156           0 :             return -1;
     157             :         }
     158         190 :         if (nlri_size != expected_nlri_size)
     159           0 :             return -1;
     160         190 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[kPrefixBytes]);
     161         190 :         if (proto_prefix.prefix[0] == SPMSIADRoute) {
     162         190 :             if (SpmsiAdRouteFromProtoPrefix(proto_prefix, prefix,
     163             :                                                        kPrefixBytes)) {
     164           1 :                 return -1;
     165             :             }
     166           0 :         } else if (proto_prefix.prefix[0] == InterASPMSIADRoute) {
     167           0 :             size_t asn_offset = kPrefixBytes + kRdSize;
     168           0 :             prefix->asn_ = get_value(&proto_prefix.prefix[asn_offset], kAsnSize);
     169             :         }
     170         189 :         size_t originator_offset = nlri_size - kIp4AddrSize;
     171         189 :         prefix->rt_key_.resize(originator_offset);
     172         189 :         copy(proto_prefix.prefix.begin(), proto_prefix.prefix.begin() +
     173             :                 originator_offset, prefix->rt_key_.begin());
     174         189 :         prefix->originator_ = Ip4Address(get_value(
     175         378 :             &proto_prefix.prefix[originator_offset], kIp4AddrSize));
     176         189 :         break;
     177             :     }
     178         128 :     case SourceActiveADRoute: {
     179         128 :         size_t expected_nlri_size = kSourceActiveADRouteSize;
     180         128 :         if (nlri_size != expected_nlri_size)
     181           0 :             return -1;
     182         128 :         size_t rd_offset = 0;
     183         128 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     184         128 :         size_t source_offset = rd_offset + kRdSize;
     185         128 :         if (proto_prefix.prefix[source_offset++] != kIp4AddrBitSize)
     186           0 :             return -1;
     187         128 :         prefix->source_ = Ip4Address(get_value(
     188         256 :             &proto_prefix.prefix[source_offset], kIp4AddrSize));
     189             : 
     190         128 :         size_t group_offset = source_offset + kIp4AddrSize;
     191         128 :         if (proto_prefix.prefix[group_offset++] != kIp4AddrBitSize)
     192           0 :             return -1;
     193         128 :         prefix->group_ = Ip4Address(get_value(
     194         256 :             &proto_prefix.prefix[group_offset], kIp4AddrSize));
     195         128 :         break;
     196             :     }
     197         162 :     case SourceTreeJoinRoute:
     198             :     case SharedTreeJoinRoute: {
     199         162 :         size_t expected_nlri_size = kSourceTreeJoinRouteSize;
     200         162 :         if (nlri_size != expected_nlri_size)
     201           0 :             return -1;
     202         162 :         size_t rd_offset = 0;
     203         162 :         prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
     204         162 :         size_t asn_offset = rd_offset + kRdSize;
     205         162 :         uint32_t asn = get_value(&proto_prefix.prefix[asn_offset], kAsnSize);
     206         162 :         prefix->asn_ = asn;
     207         162 :         size_t source_offset = asn_offset + kAsnSize;
     208         162 :         if (proto_prefix.prefix[source_offset++] != kIp4AddrBitSize)
     209           0 :             return -1;
     210         162 :         prefix->source_ = Ip4Address(get_value(
     211         324 :             &proto_prefix.prefix[source_offset], kIp4AddrSize));
     212             : 
     213         162 :         size_t group_offset = source_offset + kIp4AddrSize;
     214         162 :         if (proto_prefix.prefix[group_offset++] != kIp4AddrBitSize)
     215           0 :             return -1;
     216         162 :         prefix->group_ = Ip4Address(get_value(
     217         324 :             &proto_prefix.prefix[group_offset], kIp4AddrSize));
     218         162 :         break;
     219             :     }
     220           1 :     default: {
     221           1 :         return -1;
     222             :     }
     223             :     }
     224             : 
     225        1685 :     return 0;
     226             : }
     227             : 
     228           1 : void MvpnPrefix::set_originator(const Ip4Address &originator) {
     229           1 :     originator_ = originator;
     230           1 : }
     231             : 
     232        1683 : int MvpnPrefix::FromProtoPrefix(BgpServer *server,
     233             :                                 const BgpProtoPrefix &proto_prefix,
     234             :                                 const BgpAttr *attr,
     235             :                                 const Address::Family family,
     236             :                                 MvpnPrefix *prefix,
     237             :                                 BgpAttrPtr *new_attr, uint32_t *label,
     238             :                                 uint32_t *l3_label) {
     239        1683 :     return FromProtoPrefix(proto_prefix, prefix);
     240             : }
     241             : 
     242        1817 : void MvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix) const {
     243        1817 :     proto_prefix->type = type_;
     244        1817 :     proto_prefix->prefix.clear();
     245             : 
     246        1817 :     switch (type_) {
     247        1186 :     case IntraASPMSIADRoute: {
     248        1186 :         size_t nlri_size = kIntraASPMSIADRouteSize;
     249        1186 :         proto_prefix->prefixlen = nlri_size * 8;
     250        1186 :         proto_prefix->prefix.resize(nlri_size, 0);
     251             : 
     252        1186 :         size_t rd_offset = 0;
     253        1186 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     254        1186 :             proto_prefix->prefix.begin() + rd_offset);
     255        1186 :         size_t originator_offset = rd_offset + kRdSize;
     256        1186 :         const Ip4Address::bytes_type &source_bytes = originator_.to_bytes();
     257        1186 :         copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
     258        1186 :             proto_prefix->prefix.begin() + originator_offset);
     259        1186 :         break;
     260             :     }
     261           0 :     case InterASPMSIADRoute: {
     262           0 :         size_t nlri_size = kInterASPMSIADRouteSize;
     263           0 :         proto_prefix->prefixlen = nlri_size * 8;
     264           0 :         proto_prefix->prefix.resize(nlri_size, 0);
     265             : 
     266           0 :         size_t rd_offset = 0;
     267           0 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     268           0 :             proto_prefix->prefix.begin() + rd_offset);
     269           0 :         size_t asn_offset = rd_offset + kRdSize;
     270           0 :         put_value(&proto_prefix->prefix[asn_offset], kAsnSize, asn_);
     271           0 :         break;
     272             :     }
     273         151 :     case SPMSIADRoute: {
     274         151 :         size_t nlri_size = kSPMSIADRouteSize;
     275         151 :         proto_prefix->prefixlen = nlri_size * 8;
     276         151 :         proto_prefix->prefix.resize(nlri_size, 0);
     277             : 
     278         151 :         size_t rd_offset = 0;
     279         151 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     280         151 :             proto_prefix->prefix.begin() + rd_offset);
     281         151 :         size_t source_offset = rd_offset + kRdSize;
     282         151 :         proto_prefix->prefix[source_offset++] = kIp4AddrBitSize;
     283         151 :         const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
     284         151 :         copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
     285         151 :             proto_prefix->prefix.begin() + source_offset);
     286             : 
     287         151 :         size_t group_offset = source_offset + kIp4AddrSize;
     288         151 :         proto_prefix->prefix[group_offset++] = kIp4AddrBitSize;
     289         151 :         const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
     290         151 :         copy(group_bytes.begin(), group_bytes.begin() + kIp4AddrSize,
     291         151 :             proto_prefix->prefix.begin() + group_offset);
     292             : 
     293         151 :         size_t originator_offset = group_offset + kIp4AddrSize;
     294         151 :         const Ip4Address::bytes_type &originator_bytes = originator_.to_bytes();
     295         151 :         copy(originator_bytes.begin(), originator_bytes.begin() +
     296         151 :                 kIp4AddrSize, proto_prefix->prefix.begin() +
     297             :                 originator_offset);
     298         151 :         break;
     299             :     }
     300         190 :     case LeafADRoute: {
     301         190 :         size_t keySize = rt_key_.size();
     302         190 :         size_t nlri_size = keySize + kIp4AddrSize;
     303         190 :         proto_prefix->prefixlen = nlri_size * 8;
     304         190 :         proto_prefix->prefix.resize(nlri_size, 0);
     305             : 
     306         190 :         copy(rt_key_.begin(), rt_key_.begin() + keySize,
     307             :                 proto_prefix->prefix.begin());
     308             : 
     309         190 :         const Ip4Address::bytes_type &originator_bytes = originator_.to_bytes();
     310         190 :         copy(originator_bytes.begin(), originator_bytes.begin() +
     311         190 :                 kIp4AddrSize, proto_prefix->prefix.begin() + keySize);
     312         190 :         break;
     313             :     }
     314         128 :     case SourceActiveADRoute: {
     315         128 :         size_t nlri_size = kSourceActiveADRouteSize;
     316         128 :         proto_prefix->prefixlen = nlri_size * 8;
     317         128 :         proto_prefix->prefix.resize(nlri_size, 0);
     318             : 
     319         128 :         size_t rd_offset = 0;
     320         128 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     321         128 :             proto_prefix->prefix.begin() + rd_offset);
     322         128 :         size_t source_offset = rd_offset + kRdSize;
     323         128 :         proto_prefix->prefix[source_offset++] = kIp4AddrBitSize;
     324         128 :         const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
     325         128 :         copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
     326         128 :             proto_prefix->prefix.begin() + source_offset);
     327             : 
     328         128 :         size_t group_offset = source_offset + kIp4AddrSize;
     329         128 :         proto_prefix->prefix[group_offset++] = kIp4AddrBitSize;
     330         128 :         const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
     331         128 :         copy(group_bytes.begin(), group_bytes.begin() + kIp4AddrSize,
     332         128 :             proto_prefix->prefix.begin() + group_offset);
     333         128 :         break;
     334             :     }
     335         162 :     case SourceTreeJoinRoute:
     336             :     case SharedTreeJoinRoute: {
     337         162 :         size_t nlri_size = kSourceTreeJoinRouteSize;
     338         162 :         proto_prefix->prefixlen = nlri_size * 8;
     339         162 :         proto_prefix->prefix.resize(nlri_size, 0);
     340             : 
     341         162 :         size_t rd_offset = 0;
     342         162 :         copy(rd_.GetData(), rd_.GetData() + kRdSize,
     343         162 :             proto_prefix->prefix.begin() + rd_offset);
     344         162 :         size_t asn_offset = rd_offset + kRdSize;
     345         162 :         put_value(&proto_prefix->prefix[asn_offset], kAsnSize, asn_);
     346         162 :         size_t source_offset = asn_offset + kAsnSize;
     347         162 :         proto_prefix->prefix[source_offset++] = kIp4AddrBitSize;
     348         162 :         const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
     349         162 :         copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
     350         162 :             proto_prefix->prefix.begin() + source_offset);
     351             : 
     352         162 :         size_t group_offset = source_offset + kIp4AddrSize;
     353         162 :         proto_prefix->prefix[group_offset++] = kIp4AddrBitSize;
     354         162 :         const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
     355         162 :         copy(group_bytes.begin(), group_bytes.begin() + kIp4AddrSize,
     356         162 :             proto_prefix->prefix.begin() + group_offset);
     357         162 :         break;
     358             :     }
     359           0 :     default: {
     360           0 :         assert(false);
     361             :         break;
     362             :     }
     363             :     }
     364        1817 : }
     365             : 
     366       46822 : bool MvpnPrefix::GetTypeFromString(MvpnPrefix *prefix, const string &str,
     367             :     error_code *errorp, size_t *pos1) {
     368       46822 :     *pos1 = str.find('-');
     369       46822 :     if (*pos1 == string::npos) {
     370          17 :         if (errorp != NULL) {
     371          17 :             *errorp = make_error_code(invalid_argument);
     372             :         }
     373          17 :         return false;
     374             :     }
     375       46805 :     string temp_str = str.substr(0, *pos1);
     376       46805 :     stringToInteger(temp_str, prefix->type_);
     377       46805 :     if (!IsValid(prefix->type_)) {
     378           1 :         if (errorp != NULL) {
     379           1 :             *errorp = make_error_code(invalid_argument);
     380             :         }
     381           1 :         return false;
     382             :     }
     383       46804 :     return true;
     384       46805 : }
     385             : 
     386       42674 : bool MvpnPrefix::GetRDFromString(MvpnPrefix *prefix, const string &str,
     387             :         size_t pos1, size_t *pos2, error_code *errorp) {
     388       42674 :     *pos2 = str.find(',', pos1 + 1);
     389       42674 :     if (*pos2 == string::npos) {
     390           4 :         if (errorp != NULL) {
     391           4 :             *errorp = make_error_code(invalid_argument);
     392             :         }
     393           4 :         return false;
     394             :     }
     395       42670 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     396       42670 :     error_code rd_err;
     397       42670 :     prefix->rd_ = RouteDistinguisher::FromString(temp_str, &rd_err);
     398       42670 :     if (rd_err.failed()) {
     399           4 :         if (errorp != NULL) {
     400           4 :             *errorp = rd_err;
     401             :         }
     402           4 :         return false;
     403             :     }
     404       42666 :     return true;
     405       42670 : }
     406             : 
     407       15014 : bool MvpnPrefix::GetOriginatorFromString(MvpnPrefix *prefix,
     408             :         const string &str, size_t pos1, error_code *errorp) {
     409       15014 :     string temp_str = str.substr(pos1 + 1, string::npos);
     410       15014 :     error_code originator_err;
     411       15014 :     prefix->originator_ = Ip4Address::from_string(temp_str, originator_err);
     412       15014 :     if (originator_err.failed()) {
     413           3 :         if (errorp != NULL) {
     414           3 :             *errorp = originator_err;
     415             :         }
     416           3 :         return false;
     417             :     }
     418       15011 :     return true;
     419       15014 : }
     420             : 
     421       42018 : bool MvpnPrefix::GetSourceFromString(MvpnPrefix *prefix, const string &str,
     422             :         size_t pos1, size_t *pos2, error_code *errorp) {
     423       42018 :     *pos2 = str.find(',', pos1 + 1);
     424       42018 :     if (*pos2 == string::npos) {
     425           0 :         if (errorp != NULL) {
     426           0 :             *errorp = make_error_code(invalid_argument);
     427             :         }
     428           0 :         return false;
     429             :     }
     430       42018 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     431       42018 :     error_code source_err;
     432       42018 :     prefix->source_ = Ip4Address::from_string(temp_str, source_err);
     433       42018 :     if (source_err.failed()) {
     434           2 :         if (errorp != NULL) {
     435           2 :             *errorp = source_err;
     436             :         }
     437           2 :         return false;
     438             :     }
     439       42016 :     return true;
     440       42018 : }
     441             : 
     442       42016 : bool MvpnPrefix::GetGroupFromString(MvpnPrefix *prefix, const string &str,
     443             :         size_t pos1, size_t *pos2, error_code *errorp,
     444             :         bool last) {
     445       42016 :     *pos2 = str.find(',', pos1 + 1);
     446       42016 :     if (!last && *pos2 == string::npos) {
     447           1 :         if (errorp != NULL) {
     448           1 :             *errorp = make_error_code(invalid_argument);
     449             :         }
     450           1 :         return false;
     451             :     }
     452       42015 :     string temp_str;
     453       42015 :     if (last)
     454       27648 :         temp_str = str.substr(pos1 + 1, string::npos);
     455             :     else
     456       14367 :         temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     457       42015 :     error_code group_err;
     458       42015 :     prefix->group_ = Ip4Address::from_string(temp_str, group_err);
     459       42015 :     if (group_err.failed()) {
     460           2 :         if (errorp != NULL) {
     461           2 :             *errorp = group_err;
     462             :         }
     463           2 :         return false;
     464             :     }
     465       42013 :     return true;
     466       42015 : }
     467             : 
     468       20596 : bool MvpnPrefix::GetAsnFromString(MvpnPrefix *prefix, const string &str,
     469             :         size_t pos1, size_t *pos2, error_code *errorp) {
     470       20596 :     *pos2 = str.find(',', pos1 + 1);
     471       20596 :     if (*pos2 == string::npos) {
     472           0 :         if (errorp != NULL) {
     473           0 :             *errorp = make_error_code(invalid_argument);
     474             :         }
     475           0 :         return false;
     476             :     }
     477       20596 :     string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
     478       20596 :     if (!stringToInteger(temp_str, prefix->asn_)) {
     479           0 :         return false;
     480             :     }
     481       20596 :     return true;
     482       20596 : }
     483             : 
     484       42693 : MvpnPrefix MvpnPrefix::FromString(const string &str, error_code *errorp) {
     485       42693 :     MvpnPrefix prefix, null_prefix;
     486       42693 :     string temp_str;
     487             : 
     488             :     // Look for Type.
     489             :     size_t pos1;
     490       42693 :     if (!GetTypeFromString(&prefix, str, errorp, &pos1))
     491          17 :         return null_prefix;
     492             : 
     493       42676 :     switch (prefix.type_) {
     494         644 :     case IntraASPMSIADRoute: {
     495             :         // Look for RD.
     496             :         size_t pos2;
     497         644 :         if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
     498           3 :             return null_prefix;
     499             :         // rest is originator
     500         642 :         if (!GetOriginatorFromString(&prefix, str, pos2, errorp))
     501           1 :             return null_prefix;
     502         641 :         break;
     503             :     }
     504           8 :     case InterASPMSIADRoute: {
     505             :         // Look for RD.
     506             :         size_t pos2;
     507           8 :         if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
     508           3 :             return null_prefix;
     509             :         // rest is asn
     510           5 :         temp_str = str.substr(pos2 + 1, string::npos);
     511           5 :         if (!stringToInteger(temp_str, prefix.asn_)) {
     512           0 :             return null_prefix;
     513             :         }
     514           5 :         break;
     515             :     }
     516       10246 :     case SPMSIADRoute: {
     517             :         // Look for RD.
     518             :         size_t pos2;
     519       10246 :         if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
     520           5 :             return null_prefix;
     521             :         // Look for source.
     522             :         size_t pos3;
     523       10244 :         if (!GetSourceFromString(&prefix, str, pos2, &pos3, errorp))
     524           0 :             return null_prefix;
     525             : 
     526             :         // Look for group.
     527             :         size_t pos4;
     528       10244 :         if (!GetGroupFromString(&prefix, str, pos3, &pos4, errorp))
     529           2 :             return null_prefix;
     530             : 
     531             :         // rest is originator
     532       10242 :         if (!GetOriginatorFromString(&prefix, str, pos4, errorp))
     533           1 :             return null_prefix;
     534       10241 :         break;
     535             :     }
     536        4130 :     case LeafADRoute: {
     537             :         // First get the originator from the end
     538        4130 :         size_t pos_last = str.find_last_of(',');
     539        4130 :         if (pos_last == string::npos) {
     540           0 :             if (errorp != NULL) {
     541           0 :                 *errorp = make_error_code(invalid_argument);
     542             :             }
     543           6 :             return null_prefix;
     544             :         }
     545        4130 :         if (!GetOriginatorFromString(&prefix, str, pos_last, errorp))
     546           1 :             return null_prefix;
     547        4129 :         temp_str = str.substr(pos1 + 1, string::npos);
     548             :         // Look for type.
     549             :         size_t pos2;
     550        4129 :         if (!GetTypeFromString(&prefix, temp_str, errorp, &pos2))
     551           1 :             return null_prefix;
     552        4128 :         uint8_t src_rt_type = prefix.type_;
     553        4128 :         prefix.type_ = LeafADRoute;
     554        4128 :         size_t key_size = 0;
     555        4128 :         if (src_rt_type == InterASPMSIADRoute) {
     556           1 :             key_size = kPrefixBytes + kInterASPMSIADRouteSize;
     557           1 :             prefix.rt_key_.resize(key_size);
     558           1 :             prefix.rt_key_[0] = InterASPMSIADRoute;
     559           1 :             prefix.rt_key_[1] = kInterASPMSIADRouteSize;
     560        4127 :         } else if (src_rt_type == SPMSIADRoute) {
     561        4127 :             key_size = kPrefixBytes + kSPMSIADRouteSize;
     562        4127 :             prefix.rt_key_.resize(key_size);
     563        4127 :             prefix.rt_key_[0] = SPMSIADRoute;
     564        4127 :             prefix.rt_key_[1] = kSPMSIADRouteSize;
     565             :         }
     566        4128 :         size_t key_offset = 2;
     567             :         // Look for RD.
     568             :         size_t pos3;
     569        4128 :         pos2 = pos1 + 1 + pos2;
     570        4128 :         if (!GetRDFromString(&prefix, str, pos2, &pos3, errorp))
     571           1 :             return null_prefix;
     572        4127 :         copy(prefix.rd_.GetData(), prefix.rd_.GetData() + kRdSize,
     573        4127 :                 prefix.rt_key_.begin() + key_offset);
     574        4127 :         key_offset += kRdSize;
     575             :         // check if source ip or asn
     576             :         size_t pos4;
     577        4127 :         if (src_rt_type == InterASPMSIADRoute) {
     578             :             // check for asn
     579           1 :             if (!GetAsnFromString(&prefix, str, pos3, &pos4, errorp))
     580           0 :                 return null_prefix;
     581           1 :             size_t asn_size = sizeof(prefix.asn_);
     582           1 :             put_value(&prefix.rt_key_[key_offset], asn_size, prefix.asn_);
     583        4124 :             break;
     584             :         }
     585        4126 :         if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
     586           2 :             return null_prefix;
     587        4124 :         const Ip4Address::bytes_type &source_bytes = prefix.source_.to_bytes();
     588        4124 :         prefix.rt_key_[key_offset++] = kIp4AddrBitSize;
     589        4124 :         copy(source_bytes.begin(), source_bytes.begin() +
     590        4124 :                     kIp4AddrSize, prefix.rt_key_.begin() + key_offset);
     591        4124 :         key_offset += kIp4AddrSize;
     592             : 
     593             :         // Look for group.
     594             :         size_t pos5;
     595        4124 :         if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp))
     596           1 :             return null_prefix;
     597        4123 :         const Ip4Address::bytes_type &group_bytes = prefix.group_.to_bytes();
     598        4123 :         prefix.rt_key_[key_offset++] = kIp4AddrBitSize;
     599        4123 :         copy(group_bytes.begin(), group_bytes.begin() +
     600        4123 :                     kIp4AddrSize, prefix.rt_key_.begin() + key_offset);
     601        4123 :         key_offset += kIp4AddrSize;
     602             : 
     603             :         // Look for originator of rt_key and ignore it.
     604        4123 :         size_t pos6 = str.find(',', pos5 + 1);
     605        4123 :         if (pos6 == string::npos) {
     606           0 :             if (errorp != NULL) {
     607           0 :                 *errorp = make_error_code(invalid_argument);
     608             :             }
     609           0 :             return null_prefix;
     610             :         }
     611        4123 :         temp_str = str.substr(pos5 + 1, pos6 - pos5 - 1);
     612        4123 :         error_code originator_err;
     613        4123 :         Ip4Address ip = Ip4Address::from_string(temp_str, originator_err);
     614        4123 :         if (originator_err.failed()) {
     615           0 :             if (errorp != NULL) {
     616           0 :                 *errorp = originator_err;
     617             :             }
     618           0 :             return null_prefix;
     619             :         }
     620        4123 :         const Ip4Address::bytes_type &originator_bytes = ip.to_bytes();
     621        4123 :         copy(originator_bytes.begin(), originator_bytes.begin() +
     622        4123 :                     kIp4AddrSize, prefix.rt_key_.begin() + key_offset);
     623        4123 :         break;
     624             :     }
     625        7053 :     case SourceActiveADRoute: {
     626             :         // Look for RD.
     627             :         size_t pos2;
     628        7053 :         if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
     629           0 :             return null_prefix;
     630             :         // Look for source.
     631             :         size_t pos3;
     632        7053 :         if (!GetSourceFromString(&prefix, str, pos2, &pos3, errorp))
     633           0 :             return null_prefix;
     634             : 
     635             :         // rest is group.
     636             :         size_t pos4;
     637        7053 :         if (!GetGroupFromString(&prefix, str, pos3, &pos4, errorp, true))
     638           0 :             return null_prefix;
     639        7053 :         break;
     640             :     }
     641       20595 :     case SharedTreeJoinRoute:
     642             :     case SourceTreeJoinRoute: {
     643             :         // Look for RD.
     644             :         size_t pos2;
     645       20595 :         if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
     646           0 :             return null_prefix;
     647             :         // Look for asn
     648             :         size_t pos3;
     649       20595 :         if (!GetAsnFromString(&prefix, str, pos2, &pos3, errorp))
     650           0 :             return null_prefix;
     651             :         // Look for source.
     652             :         size_t pos4;
     653       20595 :         if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
     654           0 :             return null_prefix;
     655             : 
     656             :         // rest is group.
     657             :         size_t pos5;
     658       20595 :         if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp, true))
     659           0 :             return null_prefix;
     660       20595 :         break;
     661             :     }
     662             :     }
     663             : 
     664       42659 :     return prefix;
     665       42693 : }
     666             : 
     667      990416 : string MvpnPrefix::ToString() const {
     668      990416 :     string repr = integerToString(type_);
     669      990416 :     switch (type_) {
     670      550371 :         case IntraASPMSIADRoute:
     671      550371 :             repr += "-" + rd_.ToString();
     672      550371 :             repr += "," + originator_.to_string();
     673      550371 :             break;
     674          11 :         case InterASPMSIADRoute:
     675          11 :             repr += "-" + rd_.ToString();
     676          11 :             repr += "," + integerToString(asn_);
     677          11 :             break;
     678      136988 :         case SPMSIADRoute:
     679      136988 :             repr += "-" + rd_.ToString();
     680      136988 :             repr += "," + source_.to_string();
     681      136988 :             repr += "," + group_.to_string();
     682      136988 :             repr += "," + originator_.to_string();
     683      136988 :             break;
     684       30459 :         case LeafADRoute: {
     685       30459 :             size_t key_offset = kPrefixBytes;
     686       30459 :             RouteDistinguisher rd(&rt_key_[key_offset]);
     687       30459 :             uint8_t rt_type = rt_key_[0];
     688       30459 :             if (rt_type == SPMSIADRoute) {
     689       30458 :                 repr += "-3";
     690       30458 :                 repr += "-" + rd.ToString();
     691       30458 :                 key_offset += kRdSize + 1;
     692             :                 Ip4Address ip = Ip4Address(get_value
     693       30458 :                                      (&rt_key_[key_offset], kIp4AddrSize));
     694       30458 :                 repr += "," + ip.to_string();
     695       30457 :                 key_offset += kIp4AddrSize + 1;
     696       30457 :                 ip = Ip4Address(get_value (&rt_key_[key_offset], kIp4AddrSize));
     697       30457 :                 key_offset += kIp4AddrSize;
     698       30457 :                 repr += "," + ip.to_string();
     699       30457 :                 ip = Ip4Address(get_value (&rt_key_[key_offset], kIp4AddrSize));
     700       30457 :                 repr += "," + ip.to_string();
     701           1 :             } else if (rt_type == InterASPMSIADRoute) {
     702           1 :                 repr += "-2";
     703           1 :                 repr += "-" + rd.ToString();
     704           1 :                 key_offset += kRdSize;
     705           1 :                 uint32_t asn = get_value(&rt_key_[key_offset], kAsnSize);
     706           1 :                 repr += "," + integerToString(asn);
     707             :             }
     708       30459 :             repr += "," + originator_.to_string();
     709       30459 :             break;
     710             :         }
     711      128668 :         case SourceActiveADRoute:
     712      128668 :             repr += "-" + rd_.ToString();
     713      128668 :             repr += "," + source_.to_string();
     714      128668 :             repr += "," + group_.to_string();
     715      128668 :             break;
     716      143919 :         case SharedTreeJoinRoute:
     717             :         case SourceTreeJoinRoute:
     718      143919 :             repr += "-" + rd_.ToString();
     719      143919 :             repr += "," + integerToString(asn_);
     720      143919 :             repr += "," + source_.to_string();
     721      143919 :             repr += "," + group_.to_string();
     722      143919 :             break;
     723             :     }
     724      990416 :     return repr;
     725           0 : }
     726             : 
     727     2857781 : int MvpnPrefix::CompareTo(const MvpnPrefix &rhs) const {
     728     2857781 :     KEY_COMPARE(type_, rhs.type_);
     729             : 
     730     2147169 :     switch (type_) {
     731     1489668 :     case IntraASPMSIADRoute:
     732     1489668 :         KEY_COMPARE(rd_, rhs.rd_);
     733      571292 :         KEY_COMPARE(originator_, rhs.originator_);
     734      571190 :         break;
     735           8 :     case InterASPMSIADRoute:
     736           8 :         KEY_COMPARE(rd_, rhs.rd_);
     737           8 :         KEY_COMPARE(asn_, rhs.asn_);
     738           8 :         break;
     739      230698 :     case SPMSIADRoute:
     740      230698 :         KEY_COMPARE(rd_, rhs.rd_);
     741      204046 :         KEY_COMPARE(source_, rhs.source_);
     742      204046 :         KEY_COMPARE(group_, rhs.group_);
     743       98190 :         KEY_COMPARE(originator_, rhs.originator_);
     744       98001 :         break;
     745       66409 :     case LeafADRoute:
     746       66409 :         KEY_COMPARE(rt_key_, rhs.rt_key_);
     747       30559 :         KEY_COMPARE(originator_, rhs.originator_);
     748       30560 :         break;
     749      193820 :     case SourceActiveADRoute:
     750      193820 :         KEY_COMPARE(rd_, rhs.rd_);
     751      168725 :         KEY_COMPARE(source_, rhs.source_);
     752      168712 :         KEY_COMPARE(group_, rhs.group_);
     753      101016 :         break;
     754      166572 :     case SourceTreeJoinRoute:
     755             :     case SharedTreeJoinRoute:
     756      166572 :         KEY_COMPARE(rd_, rhs.rd_);
     757      156833 :         KEY_COMPARE(asn_, rhs.asn_);
     758      156833 :         KEY_COMPARE(source_, rhs.source_);
     759      156806 :         KEY_COMPARE(group_, rhs.group_);
     760       97162 :         break;
     761           0 :     default:
     762           0 :         break;
     763             :     }
     764      897931 :     return 0;
     765             : }
     766             : 
     767             : // Populate LeafADRoute(Type4) rt_key_ from SPMSIADRoute(Type3)
     768        3048 : void MvpnPrefix::SetLeafADPrefixFromSPMSIPrefix(const MvpnPrefix &prefix) {
     769        3048 :     assert(prefix.type() == SPMSIADRoute);
     770             : 
     771        3048 :     size_t key_size = kPrefixBytes + kSPMSIADRouteSize;
     772        3048 :     rt_key_.resize(key_size);
     773        3048 :     size_t key_offset = 0;
     774        3048 :     rt_key_[key_offset++] = SPMSIADRoute;
     775        3048 :     rt_key_[key_offset++] = (uint8_t)kSPMSIADRouteSize;
     776        6096 :     copy(prefix.route_distinguisher().GetData(),
     777        3048 :             prefix.route_distinguisher().GetData() + kRdSize,
     778        3048 :             rt_key_.begin() + key_offset);
     779        3048 :     size_t source_offset = key_offset+ kRdSize;
     780        3048 :     rt_key_[source_offset++] = kIp4AddrBitSize;
     781        3048 :     RouteDistinguisher rd(prefix.route_distinguisher().GetData());
     782        3048 :     rd_ = rd;
     783        3048 :     const Ip4Address::bytes_type &source_bytes = prefix.source().to_bytes();
     784        3048 :     copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
     785        3048 :                                            rt_key_.begin() + source_offset);
     786        3048 :     size_t group_offset = source_offset + kIp4AddrSize;
     787        3048 :     source_ = Ip4Address(prefix.source().to_ulong());
     788        3048 :     rt_key_[group_offset++] = kIp4AddrBitSize;
     789        3048 :     const Ip4Address::bytes_type &group_bytes = prefix.group().to_bytes();
     790        3048 :     copy(group_bytes.begin(), group_bytes.begin() +
     791        3048 :                 kIp4AddrSize, rt_key_.begin() + group_offset);
     792        3048 :     size_t originator_offset = group_offset + kIp4AddrSize;
     793        3048 :     group_ = Ip4Address(prefix.group().to_ulong());
     794             :     const Ip4Address::bytes_type &originator_bytes =
     795        3048 :             prefix.originator().to_bytes();
     796        3048 :     copy(originator_bytes.begin(), originator_bytes.begin() +
     797        3048 :                 kIp4AddrSize, rt_key_.begin() + originator_offset);
     798        3048 : }
     799             : 
     800        3773 : void MvpnPrefix::SetSPMSIPrefixFromLeafADPrefix(const MvpnPrefix &prefix) {
     801        3773 :     assert(prefix.type() == LeafADRoute);
     802        3773 :     RouteDistinguisher rd(prefix.route_distinguisher().GetData());
     803        3773 :     rd_ = rd;
     804        3773 :     source_ = Ip4Address(prefix.source().to_ulong());
     805        3773 :     group_ = Ip4Address(prefix.group().to_ulong());
     806        3773 :     originator_ = prefix.GetType3OriginatorFromType4Route();
     807        3773 :     type_ = SPMSIADRoute;
     808        3773 : }
     809             : 
     810         356 : string MvpnPrefix::ToXmppIdString() const {
     811         356 :     string repr = rd_.ToString();
     812         356 :     repr += ":" + group_.to_string();
     813         356 :     repr += "," + source_.to_string();
     814         356 :     return repr;
     815           0 : }
     816             : 
     817       46818 : bool MvpnPrefix::IsValid(uint8_t type) {
     818       46818 :     return (type > Unspecified) && (type <= SourceTreeJoinRoute);
     819             : }
     820             : 
     821        4122 : bool MvpnPrefix::operator==(const MvpnPrefix &rhs) const {
     822             :     return (
     823        8244 :         type_ == rhs.type_ &&
     824        8244 :         rd_ == rhs.rd_ &&
     825        8244 :         originator_ == rhs.originator_ &&
     826       12366 :         group_ == rhs.group_ &&
     827        8244 :         source_ == rhs.source_);
     828             : }
     829             : 
     830      630569 : MvpnRoute::MvpnRoute(const MvpnPrefix &prefix) : prefix_(prefix) {
     831      630567 : }
     832             : 
     833     2857780 : int MvpnRoute::CompareTo(const Route &rhs) const {
     834     2857780 :     const MvpnRoute &other = static_cast<const MvpnRoute &>(rhs);
     835     2857780 :     return prefix_.CompareTo(other.prefix_);
     836             :     KEY_COMPARE(prefix_.type(), other.prefix_.type());
     837             :     KEY_COMPARE(
     838             :         prefix_.route_distinguisher(), other.prefix_.route_distinguisher());
     839             :     KEY_COMPARE(prefix_.originator(), other.prefix_.originator());
     840             :     KEY_COMPARE(prefix_.source(), other.prefix_.source());
     841             :     KEY_COMPARE(prefix_.group(), other.prefix_.group());
     842             :     KEY_COMPARE(prefix_.asn(), other.prefix_.asn());
     843             :     return 0;
     844             : }
     845             : 
     846      982166 : string MvpnRoute::ToString() const {
     847      982166 :     return prefix_.ToString();
     848             : }
     849             : 
     850      196939 : string MvpnRoute::ToXmppIdString() const {
     851      196939 :     if (xmpp_id_str_.empty())
     852         356 :         xmpp_id_str_ = prefix_.ToXmppIdString();
     853      196939 :     return xmpp_id_str_;
     854             : }
     855             : 
     856           1 : bool MvpnRoute::IsValid() const {
     857           1 :     if (!BgpRoute::IsValid())
     858           1 :         return false;
     859             : 
     860           0 :     return true;
     861             : }
     862             : 
     863           1 : void MvpnRoute::SetKey(const DBRequestKey *reqkey) {
     864           1 :     const MvpnTable::RequestKey *key =
     865             :         static_cast<const MvpnTable::RequestKey *>(reqkey);
     866           1 :     prefix_ = key->prefix;
     867           1 : }
     868             : 
     869        1817 : void MvpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     870             :     const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
     871        1817 :     prefix_.BuildProtoPrefix(prefix);
     872        1817 : }
     873             : 
     874         970 : void MvpnRoute::BuildBgpProtoNextHop(
     875             :     vector<uint8_t> &nh, IpAddress nexthop) const {
     876         970 :     nh.resize(4);
     877         970 :     const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
     878         970 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
     879         970 : }
     880             : 
     881       73973 : DBEntryBase::KeyPtr MvpnRoute::GetDBRequestKey() const {
     882             :     MvpnTable::RequestKey *key;
     883       73973 :     key = new MvpnTable::RequestKey(GetPrefix(), NULL);
     884       73973 :     return KeyPtr(key);
     885             : }
     886             : 
     887      332750 : const string MvpnPrefix::GetType() const {
     888      332750 :     switch (type_) {
     889           0 :         case Unspecified:
     890           0 :             return "Unspecified";
     891      124508 :         case IntraASPMSIADRoute:
     892      124508 :             return "IntraASPMSIADRoute";
     893           2 :         case InterASPMSIADRoute:
     894           2 :             return "InterASPMSIADRoute";
     895       55356 :         case SPMSIADRoute:
     896       55356 :             return "SPMSIADRoute";
     897        8192 :         case LeafADRoute:
     898        8192 :             return "LeafADRoute";
     899       30688 :         case SourceActiveADRoute:
     900       30688 :             return "SourceActiveADRoute";
     901           0 :         case SharedTreeJoinRoute:
     902           0 :             return "SharedTreeJoinRoute";
     903      114004 :         case SourceTreeJoinRoute:
     904      114004 :             return "SourceTreeJoinRoute";
     905             :     }
     906           0 :     return "";
     907             : }
     908             : 
     909      332750 : const string MvpnRoute::GetType() const {
     910      332750 :     return GetPrefix().GetType();
     911             : }

Generated by: LCOV version 1.14