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

Generated by: LCOV version 1.14