LCOV - code coverage report
Current view: top level - bgp/inet - inet_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 100 104 96.2 %
Date: 2026-06-18 01:51:13 Functions: 14 14 100.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/inet/inet_route.h"
       6             : 
       7             : #include <algorithm>
       8             : 
       9             : #include "bgp/inet/inet_table.h"
      10             : 
      11             : using std::copy;
      12             : using std::string;
      13             : using std::vector;
      14             : 
      15        6894 : int Ip4Prefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      16             :                                Ip4Prefix *prefix) {
      17        6894 :     if (proto_prefix.prefix.size() > Address::kMaxV4Bytes)
      18           1 :         return -1;
      19        6893 :     prefix->prefixlen_ = proto_prefix.prefixlen;
      20        6893 :     Ip4Address::bytes_type bt = { { 0 } };
      21        6893 :     copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin());
      22        6893 :     prefix->ip4_addr_ = Ip4Address(bt);
      23             : 
      24        6893 :     return 0;
      25             : }
      26             : 
      27        6867 : int Ip4Prefix::FromProtoPrefix(BgpServer *server,
      28             :                                const BgpProtoPrefix &proto_prefix,
      29             :                                const BgpAttr *attr,
      30             :                                const Address::Family family,
      31             :                                Ip4Prefix *prefix,
      32             :                                BgpAttrPtr *new_attr, uint32_t *label,
      33             :                                uint32_t *l3_label) {
      34        6867 :     if (family == Address::INET) {
      35        6861 :         return FromProtoPrefix(proto_prefix, prefix);
      36             :     }
      37           6 :     size_t nlri_size = proto_prefix.prefix.size();
      38           6 :     size_t expected_min_nlri_size =
      39             :         BgpProtoPrefix::kLabelSize;
      40             : 
      41           6 :     if (nlri_size < expected_min_nlri_size)
      42           0 :         return -1;
      43           6 :     if (nlri_size > expected_min_nlri_size + Address::kMaxV4Bytes)
      44           0 :         return -1;
      45             : 
      46           6 :     size_t label_offset = 0;
      47           6 :     *label = proto_prefix.ReadLabel(label_offset);
      48           6 :     size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize;
      49           6 :     prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
      50           6 :     Ip4Address::bytes_type bt = { { 0 } };
      51           6 :     copy(proto_prefix.prefix.begin() + prefix_offset,
      52             :         proto_prefix.prefix.end(), bt.begin());
      53           6 :     prefix->ip4_addr_ = Ip4Address(bt);
      54             : 
      55           6 :     return 0;
      56             : }
      57             : 
      58             : 
      59             : 
      60      918787 : string Ip4Prefix::ToString() const {
      61      918787 :     string repr(ip4_addr().to_string());
      62             :     char strplen[4];
      63      918885 :     snprintf(strplen, sizeof(strplen), "/%d", prefixlen());
      64      918865 :     repr.append(strplen);
      65     1837866 :     return repr;
      66           0 : }
      67             : 
      68     6100883 : int Ip4Prefix::CompareTo(const Ip4Prefix &rhs) const {
      69     6100883 :     if (ip4_addr_ < rhs.ip4_addr_) {
      70     3002656 :         return -1;
      71             :     }
      72     3097668 :     if (ip4_addr_ > rhs.ip4_addr_) {
      73     2107597 :         return 1;
      74             :     }
      75      991596 :     if (prefixlen_ < rhs.prefixlen_) {
      76         135 :         return -1;
      77             :     }
      78      991461 :     if (prefixlen_ > rhs.prefixlen_) {
      79          81 :         return 1;
      80             :     }
      81      991380 :     return 0;
      82             : }
      83             : 
      84      168966 : Ip4Prefix Ip4Prefix::FromString(const string &str,
      85             :                                 boost::system::error_code *errorp) {
      86      168966 :     Ip4Prefix prefix;
      87      168966 :     boost::system::error_code pfxerr = Ip4SubnetParse(str, &prefix.ip4_addr_,
      88             :                                        &prefix.prefixlen_);
      89      168965 :     if (errorp != NULL) {
      90      100866 :         *errorp = pfxerr;
      91             :     }
      92      337930 :     return prefix;
      93             : }
      94             : 
      95             : // Check whether 'this' is more specific than rhs.
      96       26737 : bool Ip4Prefix::IsMoreSpecific(const Ip4Prefix &rhs) const {
      97             :     // My prefixlen must be longer in order to be more specific.
      98       26737 :     if (prefixlen_ < rhs.prefixlen()) return false;
      99             : 
     100       26475 :     uint32_t mask = 0;
     101       26475 :     if (rhs.prefixlen())
     102       26425 :        mask = ((uint32_t) ~0) << (Address::kMaxV4PrefixLen - rhs.prefixlen());
     103       26471 :     return (ip4_addr_.to_ulong() & mask) ==
     104       26471 :         (rhs.ip4_addr().to_ulong() & mask);
     105             : }
     106             : 
     107      896648 : InetRoute::InetRoute(const Ip4Prefix &prefix)
     108      896619 :     : prefix_(prefix),
     109      896648 :       prefix_str_(prefix.ToString()) {
     110      896726 : }
     111             : 
     112     6046198 : int InetRoute::CompareTo(const Route &rhs) const {
     113     6046198 :     const InetRoute &rt_other = static_cast<const InetRoute &>(rhs);
     114     6046198 :     return prefix_.CompareTo(rt_other.prefix_);
     115             : }
     116             : 
     117             : // Check whether 'this' is more specific than rhs.
     118        1471 : bool InetRoute::IsMoreSpecific(const string &match) const {
     119        1471 :     boost::system::error_code ec;
     120             : 
     121        1471 :     Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec);
     122        1470 :     if (!ec) {
     123        1461 :         return GetPrefix().IsMoreSpecific(prefix);
     124             :     }
     125             : 
     126           9 :     return false;
     127             : }
     128             : 
     129             : // Check whether 'this' is less specific than rhs.
     130          81 : bool InetRoute::IsLessSpecific(const string &match) const {
     131          81 :     boost::system::error_code ec;
     132             : 
     133          81 :     Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec);
     134          81 :     if (!ec) {
     135          81 :         return prefix.IsMoreSpecific(GetPrefix());
     136             :     }
     137             : 
     138           0 :     return false;
     139             : }
     140             : 
     141      209631 : DBEntryBase::KeyPtr InetRoute::GetDBRequestKey() const {
     142      209631 :     InetTable::RequestKey *key = new InetTable::RequestKey(prefix_, NULL);
     143      209589 :     return KeyPtr(key);
     144             : }
     145             : 
     146           2 : void InetRoute::SetKey(const DBRequestKey *reqkey) {
     147           2 :     const InetTable::RequestKey *key =
     148             :         static_cast<const InetTable::RequestKey *>(reqkey);
     149           2 :     prefix_ = key->prefix;
     150           2 : }
     151             : 
     152        7893 : void InetRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     153             :                                  const BgpAttr *attr,
     154             :                                  const uint32_t label,
     155             :                                  uint32_t l3_label) const {
     156             :     size_t prefix_size;
     157        7893 :     prefix->prefix.clear();
     158        7893 :     if (label) { // Labeled Unicast
     159           3 :         prefix_size = (prefix_.prefixlen() + 7) / 8;
     160           3 :         size_t nlri_size = BgpProtoPrefix::kLabelSize + prefix_size;
     161           3 :         prefix->prefix.resize(nlri_size, 0);
     162           3 :         size_t label_offset = 0;
     163           3 :         prefix->WriteLabel(label_offset, label);
     164           3 :         size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize;
     165           3 :         prefix->prefixlen = prefix_offset * 8 + prefix_.prefixlen();
     166           3 :         const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes();
     167           3 :         copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
     168           6 :             prefix->prefix.begin() + prefix_offset);
     169             :     } else {
     170        7890 :         prefix->prefixlen = prefix_.prefixlen();
     171        7890 :         const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes();
     172        7890 :         prefix_size = (prefix->prefixlen + 7) / 8;
     173        7890 :         copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
     174        7890 :              back_inserter(prefix->prefix));
     175             :     }
     176        7892 : }
     177             : 
     178        4631 : void InetRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
     179             :                                      IpAddress nexthop) const {
     180        4631 :     nh.resize(Address::kMaxV4Bytes);
     181        4631 :     const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
     182        4631 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
     183        4630 : }

Generated by: LCOV version 1.14