LCOV - code coverage report
Current view: top level - bgp/extended-community - load_balance.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 187 193 96.9 %
Date: 2026-06-18 01:51:13 Functions: 25 25 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/extended-community/load_balance.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : 
       9             : #include <algorithm>
      10             : #include <string>
      11             : #include <vector>
      12             : 
      13             : using std::copy;
      14             : using std::string;
      15             : 
      16             : // Initialize default attribute statically.
      17             : const LoadBalance::LoadBalanceAttribute
      18             :     LoadBalance::LoadBalanceAttribute::kDefaultLoadBalanceAttribute =
      19             :         LoadBalance::LoadBalanceAttribute();
      20             : 
      21     1027644 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute() {
      22     1027644 :     value1 = 0;  // reset all fields
      23     1027644 :     value2 = 0;  // reset all fields
      24     1027644 :     type = BgpExtendedCommunityType::Opaque;
      25     1027644 :     sub_type = BgpExtendedCommunityOpaqueSubType::LoadBalance;
      26             : 
      27     1027644 :     l3_source_address = true;
      28     1027644 :     l3_destination_address = true;
      29     1027644 :     l4_protocol = true;
      30     1027644 :     l4_source_port = true;
      31     1027644 :     l4_destination_port = true;
      32     1027644 :     reserved1 = false;
      33             : 
      34     1027644 :     reserved2 = 0;
      35             : 
      36     1027644 :     source_bias = false;
      37             : 
      38     1027644 :     reserved3 = 0;
      39     1027644 :     reserved4 = 0;
      40     1027644 :     reserved5 = 0;
      41     1027644 : }
      42             : 
      43      130081 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute(
      44      130081 :         uint32_t value1, uint32_t value2) : value1(value1), value2(value2) {
      45      130081 : }
      46             : 
      47       22006 : void LoadBalance::LoadBalanceAttribute::Encode(
      48             :         autogen::LoadBalanceType *lb_type) const {
      49       22006 :     lb_type->load_balance_fields.load_balance_field_list.clear();
      50       22006 :     if (l3_source_address)
      51       22003 :         lb_type->load_balance_fields.load_balance_field_list.push_back(
      52       44006 :                 string("l3-source-address"));
      53       22006 :     if (l3_destination_address)
      54       22000 :         lb_type->load_balance_fields.load_balance_field_list.push_back(
      55       44000 :                 string("l3-destination-address"));
      56       22006 :     if (l4_protocol)
      57       22003 :         lb_type->load_balance_fields.load_balance_field_list.push_back(
      58       44006 :                 string("l4-protocol"));
      59       22006 :     if (l4_source_port)
      60       22000 :         lb_type->load_balance_fields.load_balance_field_list.push_back(
      61       44000 :                 string("l4-source-port"));
      62       22006 :     if (l4_destination_port)
      63       22003 :         lb_type->load_balance_fields.load_balance_field_list.push_back(
      64       44006 :                 string("l4-destination-port"));
      65       22006 :     lb_type->load_balance_decision = source_bias ? "source-bias" : "field-hash";
      66       22006 : }
      67             : 
      68      573914 : bool LoadBalance::LoadBalanceAttribute::operator==(
      69             :         const LoadBalance::LoadBalanceAttribute &other) const {
      70      573914 :     return value1 == other.value1 && value2 == other.value2;
      71             : }
      72             : 
      73       42192 : bool LoadBalance::LoadBalanceAttribute::operator!=(
      74             :         const LoadBalance::LoadBalanceAttribute &other) const {
      75       42192 :     return value1 != other.value1 || value2 != other.value2;
      76             : }
      77             : 
      78      528629 : const bool LoadBalance::LoadBalanceAttribute::IsDefault() const {
      79      528629 :     return *this == kDefaultLoadBalanceAttribute;
      80             : }
      81             : 
      82       86452 : LoadBalance::LoadBalance() {
      83       86452 :     LoadBalanceAttribute attr;
      84       86452 :     put_value(&data_[0], 4, attr.value1);
      85       86452 :     put_value(&data_[4], 4, attr.value2);
      86       86452 : }
      87             : 
      88         476 : LoadBalance::LoadBalance(const bytes_type &data) {
      89         476 :     copy(data.begin(), data.end(), data_.begin());
      90         476 : }
      91             : 
      92           8 : LoadBalance::LoadBalance(const BgpPath *path) {
      93           8 :     LoadBalance();
      94           8 :     if (!path)
      95           0 :         return;
      96           8 :     const BgpAttr *attr = path->GetAttr();
      97           8 :     if (!attr)
      98           0 :         return;
      99           8 :     const ExtCommunity *ext_community = attr->ext_community();
     100           8 :     if (!ext_community)
     101           0 :         return;
     102          32 :     for (const auto &comm : ext_community->communities()) {
     103          32 :         if (ExtCommunity::is_load_balance(comm)) {
     104           8 :             copy(comm.begin(), comm.end(), data_.begin());
     105           8 :             break;
     106             :         }
     107             :     }
     108             : }
     109             : 
     110           5 : LoadBalance::LoadBalance(const LoadBalanceAttribute &attr) {
     111           5 :     put_value(&data_[0], 4, attr.value1);
     112           5 :     put_value(&data_[4], 4, attr.value2);
     113           5 : }
     114             : 
     115       64156 : LoadBalance::LoadBalance(const autogen::LoadBalanceType &lb_type) {
     116       64156 :     LoadBalanceAttribute attr;
     117             : 
     118       64156 :     attr.source_bias = lb_type.load_balance_decision == "source-bias";
     119             : 
     120             :     // autogen::LoadBalanceType fields list empty should imply as standard
     121             :     // 5-tuple fields set. xml schema does not let one specifify default values
     122             :     // for a complex type such as a list in this case.
     123             :     bool load_balance_default =
     124      128303 :         !attr.source_bias && (lb_type.load_balance_fields.begin() ==
     125       64147 :                               lb_type.load_balance_fields.end());
     126       64156 :     attr.l3_source_address = load_balance_default || false;
     127       64156 :     attr.l3_destination_address = load_balance_default || false;
     128       64156 :     attr.l4_protocol = load_balance_default || false;
     129       64156 :     attr.l4_source_port = load_balance_default || false;
     130       64156 :     attr.l4_destination_port = load_balance_default || false;
     131             : 
     132       64156 :     for (autogen::LoadBalanceFieldListType::const_iterator it =
     133       64156 :             lb_type.load_balance_fields.begin();
     134      174069 :             it != lb_type.load_balance_fields.end(); ++it) {
     135      109913 :         const string s = *it;
     136      109913 :         if (s == "l3-source-address") {
     137       21984 :             attr.l3_source_address = true;
     138       21984 :             continue;
     139             :         }
     140       87930 :         if (s == "l3-destination-address") {
     141       21981 :             attr.l3_destination_address = true;
     142       21981 :             continue;
     143             :         }
     144       65949 :         if (s == "l4-protocol") {
     145       21984 :             attr.l4_protocol = true;
     146       21984 :             continue;
     147             :         }
     148       43965 :         if (s == "l4-source-port") {
     149       21981 :             attr.l4_source_port = true;
     150       21981 :             continue;
     151             :         }
     152       21984 :         if (s == "l4-destination-port") {
     153       21984 :             attr.l4_destination_port = true;
     154       21984 :             continue;
     155             :         }
     156      109914 :     }
     157             : 
     158       64156 :     put_value(&data_[0], 4, attr.value1);
     159       64156 :     put_value(&data_[4], 4, attr.value2);
     160       64156 : }
     161             : 
     162           4 : void LoadBalance::FillAttribute(LoadBalanceAttribute *attr) {
     163           4 :     attr->value1 = get_value(&data_[0], 4);
     164           4 :     attr->value2 = get_value(&data_[4], 4);
     165           4 : }
     166             : 
     167      130081 : const LoadBalance::LoadBalanceAttribute LoadBalance::ToAttribute() const {
     168      130081 :     return LoadBalanceAttribute(
     169      130081 :             get_value_unaligned(&data_[0], 4),
     170      260162 :             get_value_unaligned(&data_[4], 4));
     171             : }
     172             : 
     173          35 : void LoadBalance::SetL3SourceAddress(bool flag) {
     174          35 :     LoadBalanceAttribute attr = ToAttribute();
     175          35 :     attr.l3_source_address = flag;
     176             : 
     177          35 :     put_value(&data_[0], 4, attr.value1);
     178          35 :     put_value(&data_[4], 4, attr.value2);
     179          35 : }
     180             : 
     181          35 : void LoadBalance::SetL3DestinationAddress(bool flag) {
     182          35 :     LoadBalanceAttribute attr = ToAttribute();
     183          35 :     attr.l3_destination_address = flag;
     184             : 
     185          35 :     put_value(&data_[0], 4, attr.value1);
     186          35 :     put_value(&data_[4], 4, attr.value2);
     187          35 : }
     188             : 
     189           1 : void LoadBalance::SetL4Protocol(bool flag) {
     190           1 :     LoadBalanceAttribute attr = ToAttribute();
     191           1 :     attr.l4_protocol = flag;
     192             : 
     193           1 :     put_value(&data_[0], 4, attr.value1);
     194           1 :     put_value(&data_[4], 4, attr.value2);
     195           1 : }
     196             : 
     197           1 : void LoadBalance::SetL4SourcePort(bool flag) {
     198           1 :     LoadBalanceAttribute attr = ToAttribute();
     199           1 :     attr.l4_source_port = flag;
     200             : 
     201           1 :     put_value(&data_[0], 4, attr.value1);
     202           1 :     put_value(&data_[4], 4, attr.value2);
     203           1 : }
     204             : 
     205           1 : void LoadBalance::SetL4DestinationPort(bool flag) {
     206           1 :     LoadBalanceAttribute attr = ToAttribute();
     207           1 :     attr.l4_destination_port = flag;
     208             : 
     209           1 :     put_value(&data_[0], 4, attr.value1);
     210           1 :     put_value(&data_[4], 4, attr.value2);
     211           1 : }
     212             : 
     213           1 : void LoadBalance::SetSourceBias(bool flag) {
     214           1 :     LoadBalanceAttribute attr = ToAttribute();
     215           1 :     attr.source_bias = flag;
     216             : 
     217           1 :     put_value(&data_[0], 4, attr.value1);
     218           1 :     put_value(&data_[4], 4, attr.value2);
     219           1 : }
     220             : 
     221       18940 : bool LoadBalance::IsPresent(const BgpPath *path) {
     222       18940 :     if (!path)
     223           0 :         return false;
     224       18940 :     const BgpAttr *attr = path->GetAttr();
     225       18940 :     if (!attr)
     226           0 :         return false;
     227       18940 :     const ExtCommunity *ext_community = attr->ext_community();
     228       18940 :     if (!ext_community)
     229          32 :         return false;
     230       85098 :     BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
     231             :                   ext_community->communities()) {
     232       33287 :         if (ExtCommunity::is_load_balance(comm)) {
     233         192 :             return true;
     234             :         }
     235             :     }
     236       18716 :     return false;
     237             : }
     238             : 
     239       44958 : const bool LoadBalance::IsDefault() const {
     240       44958 :     return ToAttribute() == LoadBalanceAttribute::kDefaultLoadBalanceAttribute;
     241             : }
     242             : 
     243         320 : bool LoadBalance::operator==(const LoadBalance &other) const {
     244         320 :     return ToAttribute() == other.ToAttribute();
     245             : }
     246             : 
     247       42188 : bool LoadBalance::operator!=(const LoadBalance &other) const {
     248       42188 :     return ToAttribute() != other.ToAttribute();
     249             : }
     250             : 
     251           6 : void LoadBalance::ShowAttribute(ShowLoadBalance *show_load_balance) const {
     252           6 :     const LoadBalanceAttribute attr = ToAttribute();
     253           6 :     vector<string> fields = vector<string>();
     254           6 :     if (attr.source_bias) {
     255           3 :         show_load_balance->set_decision_type("source-bias");
     256           3 :         show_load_balance->set_fields(fields);
     257           3 :         return;
     258             :     }
     259             : 
     260           3 :     show_load_balance->set_decision_type("field-hash");
     261           3 :     if (attr.l3_source_address)
     262           2 :         fields.push_back("l3-source-address");
     263           3 :     if (attr.l3_destination_address)
     264           3 :         fields.push_back("l3-destination-address");
     265           3 :     if (attr.l4_protocol)
     266           2 :         fields.push_back("l4-protocol");
     267           3 :     if (attr.l4_source_port)
     268           3 :         fields.push_back("l4-source-port");
     269           3 :     if (attr.l4_destination_port)
     270           2 :         fields.push_back("l4-destination-port");
     271           3 :     show_load_balance->set_fields(fields);
     272           6 : }
     273             : 
     274           6 : string LoadBalance::ToString() const {
     275           6 :     const LoadBalanceAttribute attr = ToAttribute();
     276           6 :     string str("load-balance:");
     277           6 :     str += attr.source_bias ? "source-bias" : "field-hash";
     278          12 :     return str;
     279           0 : }

Generated by: LCOV version 1.14