LCOV - code coverage report
Current view: top level - bgp/ermvpn - ermvpn_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 208 0.0 %
Date: 2026-09-21 02:11:39 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/ermvpn/ermvpn_route.h"
       6             : 
       7             : #include <algorithm>
       8             : #include <string>
       9             : #include <vector>
      10             : 
      11             : #include "base/string_util.h"
      12             : #include "bgp/ermvpn/ermvpn_table.h"
      13             : 
      14             : using std::copy;
      15             : using std::string;
      16             : using std::vector;
      17             : 
      18             : // BgpProtoPrefix format for erm-vpn prefix.
      19             : //
      20             : // +------------------------------------+
      21             : // |      RD   (8 octets)               |
      22             : // +------------------------------------+
      23             : // |  Router-Id (4 octets)              |
      24             : // +------------------------------------+
      25             : // |  Multicast Source length (1 octet) |
      26             : // +------------------------------------+
      27             : // |  Multicast Source (4)              |
      28             : // +------------------------------------+
      29             : // |  Multicast Group length (1 octet)  |
      30             : // +------------------------------------+
      31             : // |  Multicast Group (4)               |
      32             : // +------------------------------------+
      33             : 
      34           0 : ErmVpnPrefix::ErmVpnPrefix() : type_(ErmVpnPrefix::Invalid) {
      35           0 : }
      36             : 
      37           0 : ErmVpnPrefix::ErmVpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      38           0 :     const Ip4Address &group, const Ip4Address &source)
      39           0 :     : type_(type), rd_(rd), group_(group), source_(source) {
      40           0 : }
      41             : 
      42           0 : ErmVpnPrefix::ErmVpnPrefix(uint8_t type, const RouteDistinguisher &rd,
      43             :     const Ip4Address &router_id,
      44           0 :     const Ip4Address &group, const Ip4Address &source)
      45           0 :     : type_(type), rd_(rd), router_id_(router_id),
      46           0 :       group_(group), source_(source) {
      47           0 : }
      48             : 
      49           0 : int ErmVpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      50             :     ErmVpnPrefix *prefix) {
      51           0 :     size_t rd_size = RouteDistinguisher::kSize;
      52           0 :     size_t rtid_size = Address::kMaxV4Bytes;
      53           0 :     size_t nlri_size = proto_prefix.prefix.size();
      54           0 :     size_t expected_nlri_size =
      55           0 :         rd_size + rtid_size + 2 * (Address::kMaxV4Bytes + 1);
      56             : 
      57           0 :     if (!IsValidForBgp(proto_prefix.type))
      58           0 :         return -1;
      59           0 :     if (nlri_size != expected_nlri_size)
      60           0 :         return -1;
      61             : 
      62           0 :     prefix->type_ = proto_prefix.type;
      63           0 :     size_t rd_offset = 0;
      64           0 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      65           0 :     size_t rtid_offset = rd_offset + rd_size;
      66             :     prefix->router_id_ =
      67           0 :         Ip4Address(get_value(&proto_prefix.prefix[rtid_offset], rtid_size));
      68             : 
      69           0 :     size_t source_offset = rtid_offset + rtid_size + 1;
      70           0 :     if (proto_prefix.prefix[source_offset - 1] != Address::kMaxV4PrefixLen)
      71           0 :         return -1;
      72           0 :     prefix->source_ = Ip4Address(
      73           0 :         get_value(&proto_prefix.prefix[source_offset], Address::kMaxV4Bytes));
      74             : 
      75           0 :     size_t group_offset = source_offset + Address::kMaxV4Bytes + 1;
      76           0 :     if (proto_prefix.prefix[group_offset - 1] != Address::kMaxV4PrefixLen)
      77           0 :         return -1;
      78           0 :     prefix->group_ = Ip4Address(
      79           0 :         get_value(&proto_prefix.prefix[group_offset], Address::kMaxV4Bytes));
      80             : 
      81           0 :     return 0;
      82             : }
      83             : 
      84           0 : int ErmVpnPrefix::FromProtoPrefix(BgpServer *server,
      85             :                                   const BgpProtoPrefix &proto_prefix,
      86             :                                   const BgpAttr *attr,
      87             :                                   const Address::Family family,
      88             :                                   ErmVpnPrefix *prefix,
      89             :                                   BgpAttrPtr *new_attr, uint32_t *label,
      90             :                                   uint32_t *l3_label) {
      91           0 :     return FromProtoPrefix(proto_prefix, prefix);
      92             : }
      93             : 
      94           0 : void ErmVpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix) const {
      95           0 :     assert(IsValidForBgp(type_));
      96             : 
      97           0 :     size_t rd_size = RouteDistinguisher::kSize;
      98           0 :     size_t rtid_size = Address::kMaxV4Bytes;
      99             : 
     100           0 :     proto_prefix->type = type_;
     101           0 :     proto_prefix->prefix.clear();
     102           0 :     proto_prefix->prefixlen =
     103           0 :         (rd_size + rtid_size +  2 * (1 + Address::kMaxV4Bytes)) * 8;
     104           0 :     proto_prefix->prefix.resize(proto_prefix->prefixlen / 8, 0);
     105             : 
     106           0 :     size_t rd_offset = 0;
     107           0 :     copy(rd_.GetData(), rd_.GetData() + rd_size,
     108           0 :         proto_prefix->prefix.begin() + rd_offset);
     109             : 
     110           0 :     size_t rtid_offset = rd_offset + rd_size;
     111           0 :     const Ip4Address::bytes_type &rtid_bytes = router_id_.to_bytes();
     112           0 :     copy(rtid_bytes.begin(), rtid_bytes.begin() + Address::kMaxV4Bytes,
     113           0 :         proto_prefix->prefix.begin() + rtid_offset);
     114             : 
     115           0 :     size_t source_offset = rtid_offset + rtid_size + 1;
     116           0 :     proto_prefix->prefix[source_offset - 1] = Address::kMaxV4PrefixLen;
     117           0 :     const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
     118           0 :     copy(source_bytes.begin(), source_bytes.begin() + Address::kMaxV4Bytes,
     119           0 :         proto_prefix->prefix.begin() + source_offset);
     120             : 
     121           0 :     size_t group_offset = source_offset + Address::kMaxV4Bytes + 1;
     122           0 :     proto_prefix->prefix[group_offset - 1] = Address::kMaxV4PrefixLen;
     123           0 :     const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
     124           0 :     copy(group_bytes.begin(), group_bytes.begin() + Address::kMaxV4Bytes,
     125           0 :         proto_prefix->prefix.begin() + group_offset);
     126           0 : }
     127             : 
     128           0 : ErmVpnPrefix ErmVpnPrefix::FromString(const string &str,
     129             :     boost::system::error_code *errorp) {
     130           0 :     ErmVpnPrefix prefix, null_prefix;
     131           0 :     string temp_str;
     132             : 
     133             :     // Look for Type.
     134           0 :     size_t pos1 = str.find('-');
     135           0 :     if (pos1 == string::npos) {
     136           0 :         if (errorp != NULL) {
     137           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     138             :         }
     139           0 :         return null_prefix;
     140             :     }
     141           0 :     temp_str = str.substr(0, pos1);
     142           0 :     stringToInteger(temp_str, prefix.type_);
     143           0 :     if (!IsValid(prefix.type_)) {
     144           0 :         if (errorp != NULL) {
     145           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     146             :         }
     147           0 :         return null_prefix;
     148             :     }
     149             : 
     150             :     // Look for RD.
     151           0 :     size_t pos2 = str.find('-', pos1 + 1);
     152           0 :     if (pos2 == string::npos) {
     153           0 :         if (errorp != NULL) {
     154           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     155             :         }
     156           0 :         return null_prefix;
     157             :     }
     158           0 :     temp_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
     159           0 :     boost::system::error_code rd_err;
     160           0 :     prefix.rd_ = RouteDistinguisher::FromString(temp_str, &rd_err);
     161           0 :     if (rd_err.failed()) {
     162           0 :         if (errorp != NULL) {
     163           0 :             *errorp = rd_err;
     164             :         }
     165           0 :         return null_prefix;
     166             :     }
     167             : 
     168             :     // Look for router-id.
     169           0 :     size_t pos3 = str.find(',', pos2 + 1);
     170           0 :     if (pos3 == string::npos) {
     171           0 :         if (errorp != NULL) {
     172           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     173             :         }
     174           0 :         return null_prefix;
     175             :     }
     176           0 :     temp_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
     177           0 :     boost::system::error_code rtid_err;
     178           0 :     prefix.router_id_ = Ip4Address::from_string(temp_str, rtid_err);
     179           0 :     if (rtid_err.failed()) {
     180           0 :         if (errorp != NULL) {
     181           0 :             *errorp = rtid_err;
     182             :         }
     183           0 :         return null_prefix;
     184             :     }
     185             : 
     186             :     // Look for group.
     187           0 :     size_t pos4 = str.find(',', pos3 + 1);
     188           0 :     if (pos4 == string::npos) {
     189           0 :         if (errorp != NULL) {
     190           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     191             :         }
     192           0 :         return null_prefix;
     193             :     }
     194           0 :     temp_str = str.substr(pos3 + 1, pos4 - pos3 - 1);
     195           0 :     boost::system::error_code group_err;
     196           0 :     prefix.group_ = Ip4Address::from_string(temp_str, group_err);
     197           0 :     if (group_err.failed()) {
     198           0 :         if (errorp != NULL) {
     199           0 :             *errorp = group_err;
     200             :         }
     201           0 :         return null_prefix;
     202             :     }
     203             : 
     204             :     // Rest is source.
     205           0 :     temp_str = str.substr(pos4 + 1, string::npos);
     206           0 :     boost::system::error_code source_err;
     207           0 :     prefix.source_ = Ip4Address::from_string(temp_str, source_err);
     208           0 :     if (source_err.failed()) {
     209           0 :         if (errorp != NULL) {
     210           0 :             *errorp = source_err;
     211             :         }
     212           0 :         return null_prefix;
     213             :     }
     214             : 
     215           0 :     return prefix;
     216           0 : }
     217             : 
     218           0 : string ErmVpnPrefix::ToString() const {
     219           0 :     string repr = integerToString(type_);
     220           0 :     repr += "-" + rd_.ToString();
     221           0 :     repr += "-" + router_id_.to_string();
     222           0 :     repr += "," + group_.to_string();
     223           0 :     repr += "," + source_.to_string();
     224           0 :     return repr;
     225           0 : }
     226             : 
     227           0 : string ErmVpnPrefix::ToXmppIdString() const {
     228           0 :     assert(type_ == 0);
     229           0 :     string repr = rd_.ToString();
     230           0 :     repr += ":" + group_.to_string();
     231           0 :     repr += "," + source_.to_string();
     232           0 :     return repr;
     233           0 : }
     234             : 
     235           0 : bool ErmVpnPrefix::IsValidForBgp(uint8_t type) {
     236           0 :     return (type == LocalTreeRoute || type == GlobalTreeRoute);
     237             : }
     238             : 
     239           0 : bool ErmVpnPrefix::IsValid(uint8_t type) {
     240           0 :     return (type == NativeRoute || IsValidForBgp(type));
     241             : }
     242             : 
     243           0 : bool ErmVpnPrefix::operator==(const ErmVpnPrefix &rhs) const {
     244             :     return (
     245           0 :         type_ == rhs.type_ &&
     246           0 :         rd_ == rhs.rd_ &&
     247           0 :         router_id_ == rhs.router_id_ &&
     248           0 :         group_ == rhs.group_ &&
     249           0 :         source_ == rhs.source_);
     250             : }
     251             : 
     252           0 : ErmVpnRoute::ErmVpnRoute(const ErmVpnPrefix &prefix) : prefix_(prefix) {
     253           0 : }
     254             : 
     255           0 : int ErmVpnRoute::CompareTo(const Route &rhs) const {
     256           0 :     const ErmVpnRoute &other = static_cast<const ErmVpnRoute &>(rhs);
     257           0 :     KEY_COMPARE(prefix_.source(), other.prefix_.source());
     258           0 :     KEY_COMPARE(prefix_.group(), other.prefix_.group());
     259           0 :     KEY_COMPARE(prefix_.type(), other.prefix_.type());
     260           0 :     KEY_COMPARE(
     261             :         prefix_.route_distinguisher(), other.prefix_.route_distinguisher());
     262           0 :     KEY_COMPARE(prefix_.router_id(), other.prefix_.router_id());
     263           0 :     return 0;
     264             : }
     265             : 
     266           0 : string ErmVpnRoute::ToString() const {
     267           0 :     return prefix_.ToString();
     268             : }
     269             : 
     270           0 : string ErmVpnRoute::ToXmppIdString() const {
     271           0 :     if (xmpp_id_str_.empty())
     272           0 :         xmpp_id_str_ = prefix_.ToXmppIdString();
     273           0 :     return xmpp_id_str_;
     274             : }
     275             : 
     276           0 : bool ErmVpnRoute::IsValid() const {
     277           0 :     if (!BgpRoute::IsValid())
     278           0 :         return false;
     279             : 
     280           0 :     const BgpAttr *attr = BestPath()->GetAttr();
     281           0 :     switch (prefix_.type()) {
     282           0 :     case ErmVpnPrefix::NativeRoute:
     283           0 :         return attr->label_block().get() != NULL;
     284           0 :     case ErmVpnPrefix::LocalTreeRoute:
     285           0 :         return attr->edge_discovery() != NULL;
     286           0 :     case ErmVpnPrefix::GlobalTreeRoute:
     287           0 :         return attr->edge_forwarding() != NULL;
     288           0 :     case ErmVpnPrefix::Invalid:
     289           0 :         break;
     290             :     }
     291             : 
     292           0 :     return false;
     293             : }
     294             : 
     295           0 : void ErmVpnRoute::SetKey(const DBRequestKey *reqkey) {
     296           0 :     const ErmVpnTable::RequestKey *key =
     297             :         static_cast<const ErmVpnTable::RequestKey *>(reqkey);
     298           0 :     prefix_ = key->prefix;
     299           0 : }
     300             : 
     301           0 : void ErmVpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     302             :     const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
     303           0 :     prefix_.BuildProtoPrefix(prefix);
     304           0 : }
     305             : 
     306           0 : void ErmVpnRoute::BuildBgpProtoNextHop(
     307             :     vector<uint8_t> &nh, IpAddress nexthop) const {
     308           0 :     nh.resize(4);
     309           0 :     const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
     310           0 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
     311           0 : }
     312             : 
     313           0 : DBEntryBase::KeyPtr ErmVpnRoute::GetDBRequestKey() const {
     314             :     ErmVpnTable::RequestKey *key;
     315           0 :     key = new ErmVpnTable::RequestKey(GetPrefix(), NULL);
     316           0 :     return KeyPtr(key);
     317             : }
     318             : 
     319           0 : const std::string ErmVpnPrefix::GetType() const {
     320           0 :     switch (type_) {
     321           0 :     case NativeRoute:
     322           0 :         return "NativeRoute";
     323           0 :     case LocalTreeRoute:
     324           0 :         return "LocalTreeRoute";
     325           0 :     case GlobalTreeRoute:
     326           0 :         return "GlobalTreeRoute";
     327           0 :     case Invalid:
     328           0 :         return "Invalid";
     329             :     }
     330           0 :     return "";
     331             : }
     332             : 
     333           0 : const std::string ErmVpnRoute::GetType() const {
     334           0 :     return GetPrefix().GetType();
     335             : }

Generated by: LCOV version 1.14