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

Generated by: LCOV version 1.14