LCOV - code coverage report
Current view: top level - net - esi.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 80 80 100.0 %
Date: 2026-05-18 11:54:02 Functions: 5 5 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 "net/esi.h"
       6             : 
       7             : #include "base/parse_object.h"
       8             : #include "base/util.h"
       9             : #include "base/string_util.h"
      10             : #include "base/address.h"
      11             : 
      12             : using namespace std;
      13             : 
      14             : static const uint8_t max_esi_bytes[] = {
      15             :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
      16             : };
      17             : 
      18             : const EthernetSegmentId EthernetSegmentId::kZeroEsi;
      19             : const EthernetSegmentId EthernetSegmentId::kMaxEsi(max_esi_bytes);
      20             : 
      21      565955 : EthernetSegmentId::EthernetSegmentId() {
      22      565955 :     memset(data_, 0, kSize);
      23      565955 : }
      24             : 
      25       26784 : EthernetSegmentId::EthernetSegmentId(const uint8_t *data) {
      26       26784 :     memcpy(data_, data, kSize);
      27       26784 : }
      28             : 
      29        6406 : EthernetSegmentId EthernetSegmentId::FromString(const std::string &str,
      30             :     boost::system::error_code *errorp) {
      31        6406 :     if (str == "zero_esi")
      32           1 :         return EthernetSegmentId::kZeroEsi;
      33        6405 :     if (str == "max_esi")
      34           1 :         return EthernetSegmentId::kMaxEsi;
      35             : 
      36        6404 :     size_t num_colons = count(str.begin(), str.end(), ':');
      37        6404 :     if (num_colons != 1 && num_colons != 9) {
      38           4 :         if (errorp != NULL)
      39           4 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      40           4 :         return EthernetSegmentId::kMaxEsi;
      41             :     }
      42             : 
      43             :     uint8_t data[kSize];
      44        6400 :     memset(data, 0, kSize);
      45             : 
      46             :     // AS based or IP based.
      47        6400 :     if (num_colons == 1) {
      48           9 :         size_t pos = str.find(':');
      49           9 :         assert(pos != string::npos);
      50           9 :         string asn_or_ip(str.substr(0, pos));
      51             : 
      52           9 :         size_t num_dots = count(asn_or_ip.begin(), asn_or_ip.end(), '.');
      53           9 :         if (num_dots != 0 && num_dots != 3) {
      54           1 :             if (errorp != NULL)
      55           1 :                 *errorp = make_error_code(boost::system::errc::invalid_argument);
      56           1 :             return EthernetSegmentId::kMaxEsi;
      57             :         }
      58             : 
      59             :         // AS based.
      60           8 :         if (num_dots == 0) {
      61             :             uint32_t asn;
      62           4 :             bool ret = stringToInteger(asn_or_ip, asn);
      63           4 :             if (!ret) {
      64           1 :                 if (errorp != NULL) {
      65           1 :                     *errorp = make_error_code(boost::system::errc::invalid_argument);
      66           1 :                     return EthernetSegmentId::kMaxEsi;
      67             :                 }
      68             :             }
      69             : 
      70           3 :             data[0] = AS_BASED;
      71           3 :             put_value(&data[1], 4, asn);
      72             :         }
      73             : 
      74             :         // IP based.
      75           7 :         if (num_dots == 3) {
      76           4 :             boost::system::error_code ec;
      77           4 :             Ip4Address addr = Ip4Address::from_string(asn_or_ip, ec);
      78           4 :             if (ec.value() != 0) {
      79           1 :                 if (errorp != NULL) {
      80           1 :                     *errorp = make_error_code(boost::system::errc::invalid_argument);
      81           1 :                     return EthernetSegmentId::kMaxEsi;
      82             :                 }
      83             :             }
      84             : 
      85           3 :             data[0] = IP_BASED;
      86           3 :             const Ip4Address::bytes_type &bytes = addr.to_bytes();
      87           3 :             copy(bytes.begin(), bytes.begin() + 4, &data[1]);
      88             :         }
      89             : 
      90             :         // Parse discriminator - common for AS based and IP based.
      91           6 :         string disc_str(str, pos + 1);
      92             :         uint32_t disc;
      93           6 :         bool ret = stringToInteger(disc_str, disc);
      94           6 :         if (!ret) {
      95           2 :             if (errorp != NULL) {
      96           2 :                 *errorp = make_error_code(boost::system::errc::invalid_argument);
      97           2 :                 return EthernetSegmentId::kMaxEsi;
      98             :             }
      99             :         }
     100           4 :         put_value(&data[5], 4, disc);
     101          11 :     }
     102             : 
     103             :     // All other formats - raw colon separated bytes.
     104        6395 :     if (num_colons == 9) {
     105             :         char extra;
     106        6391 :         int ret = sscanf(str.c_str(),
     107             :             "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx%c",
     108             :             &data[0], &data[1], &data[2], &data[3], &data[4],
     109             :             &data[5], &data[6], &data[7], &data[8], &data[9], &extra);
     110        6391 :         if (ret != kSize || strchr(str.c_str(), 'x') || strchr(str.c_str(), 'X')) {
     111           3 :             if (errorp != NULL)
     112           3 :                 *errorp = make_error_code(boost::system::errc::invalid_argument);
     113           3 :             return EthernetSegmentId::kMaxEsi;
     114             :         }
     115             :     }
     116             : 
     117        6392 :     return EthernetSegmentId(data);
     118             : }
     119             : 
     120        3225 : string EthernetSegmentId::ToString() const {
     121        3225 :     if (CompareTo(kZeroEsi) == 0)
     122           2 :         return "zero_esi";
     123        3223 :     if (CompareTo(kMaxEsi) == 0)
     124           2 :         return "max_esi";
     125             : 
     126        3221 :     switch (Type()) {
     127           4 :     case AS_BASED: {
     128           4 :         uint32_t asn = get_value(data_ + 1, 4);
     129           4 :         uint32_t value = get_value(data_ + 5, 4);
     130           8 :         return integerToString(asn) + ":" + integerToString(value);
     131             :         break;
     132             :     }
     133           4 :     case IP_BASED: {
     134           4 :         Ip4Address addr(get_value(data_ + 1, 4));
     135           4 :         uint32_t value = get_value(data_ + 5, 4);
     136           8 :         return addr.to_string() + ":" + integerToString(value);
     137             :         break;
     138             :     }
     139        3213 :     case MAC_BASED:
     140             :     case STP_BASED:
     141             :     case LACP_BASED:
     142             :     case CONFIGURED:
     143             :     default: {
     144             :         char temp[64];
     145        3213 :         snprintf(temp, sizeof(temp),
     146             :             "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
     147        3213 :             data_[0], data_[1], data_[2], data_[3], data_[4],
     148        3213 :             data_[5], data_[6], data_[7], data_[8], data_[9]);
     149        3213 :         return temp;
     150             :     }
     151             :     }
     152             : 
     153             :     return "bad_esi";
     154             : }
     155             : 
     156    28697699 : int EthernetSegmentId::CompareTo(const EthernetSegmentId &rhs) const {
     157    28697699 :     return memcmp(data_, rhs.data_, kSize);
     158             : }

Generated by: LCOV version 1.14