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

Generated by: LCOV version 1.14