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

Generated by: LCOV version 1.14