LCOV - code coverage report
Current view: top level - vnsw/agent/vgw - cfg_vgw.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 14 149 9.4 %
Date: 2026-06-08 02:02:55 Functions: 2 11 18.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #include <iostream>
       5             : #include <sys/types.h>
       6             : #include <sys/stat.h>
       7             : #include <unistd.h>
       8             : 
       9             : #include <sys/stat.h>
      10             : 
      11             : #include <boost/property_tree/ini_parser.hpp>
      12             : #include <boost/algorithm/string.hpp>
      13             : #include <boost/foreach.hpp>
      14             : #include <vector>
      15             : #include <pugixml/pugixml.hpp>
      16             : #include <base/logging.h>
      17             : 
      18             : #include <cmn/agent_cmn.h>
      19             : #include <init/agent_param.h>
      20             : #include <cfg/cfg_init.h>
      21             : #include <vgw/cfg_vgw.h>
      22             : #include <oper/interface_common.h>
      23             : #include <vgw/vgw.h>
      24             : 
      25             : using namespace std;
      26             : using namespace boost::property_tree;
      27             : using namespace boost::uuids;
      28             : using boost::optional;
      29             : 
      30             : // Config init. Read the "gateway" node and add the configuration
      31             : // Handle only one gateway config for now
      32           1 : void VirtualGatewayConfigTable::InitFromConfig
      33             : (const boost::property_tree::ptree pt) {
      34           1 :     const std::string gw_str = "GATEWAY";
      35             : 
      36           3 :     BOOST_FOREACH(const ptree::value_type &section, pt) {
      37           1 :         if (section.first.compare(0, gw_str.size(), gw_str) != 0) {
      38           1 :             continue;
      39             :         }
      40           0 :         string vrf = "";
      41           0 :         string interfacestr = "";
      42           0 :         VirtualGatewayConfig::SubnetList subnets;
      43           0 :         VirtualGatewayConfig::SubnetList routes;
      44           0 :         BOOST_FOREACH(const ptree::value_type &key, section.second) {
      45           0 :             if (key.first.compare("routing_instance") == 0) {
      46           0 :                 vrf = key.second.get_value<string>();
      47             :             }
      48           0 :             if (key.first.compare("interface") == 0) {
      49           0 :                 interfacestr = key.second.get_value<string>();
      50             :             }
      51           0 :             if (key.first.compare("ip_blocks") == 0) {
      52           0 :                 BuildSubnetList(key.second.get_value<string>(), subnets);
      53             :             }
      54           0 :             if (key.first.compare("routes") == 0) {
      55           0 :                 BuildSubnetList(key.second.get_value<string>(), routes);
      56             :             }
      57             :         }
      58           0 :         if (vrf == "" || interfacestr == "" || subnets.size() == 0) {
      59           0 :             LOG(ERROR, "Error in config file. Invalid/incomplete gateway "
      60             :                 "section" << section.first);
      61           0 :             continue;
      62           0 :         }
      63             : 
      64           0 :         std::sort(subnets.begin(), subnets.end());
      65           0 :         std::sort(routes.begin(), routes.end());
      66           0 :         table_.insert(VirtualGatewayConfig(interfacestr, vrf,
      67             :                                            subnets, routes, (uint32_t) -1));
      68           0 :     }
      69           2 :     return;
      70           1 : }
      71             : 
      72           0 : void VirtualGatewayConfigTable::BuildSubnetList
      73             :     (const string &subnets, VirtualGatewayConfig::SubnetList &results) {
      74           0 :     Ip4Address addr;
      75             :     int plen;
      76           0 :     boost::system::error_code ec;
      77           0 :     results.clear();
      78           0 :     if (!subnets.empty()) {
      79           0 :         vector<string> tokens;
      80           0 :         boost::split(tokens, subnets, boost::is_any_of(" "));
      81           0 :         vector<string>::iterator it = tokens.begin();
      82           0 :         while (it != tokens.end()) {
      83           0 :             std::string str = *it;
      84           0 :             boost::algorithm::trim(str);
      85           0 :             ++it;
      86           0 :             ec = Ip4PrefixParse(str, &addr, &plen);
      87           0 :             if (ec.failed() || plen >= 32) {
      88           0 :                 LOG(ERROR, "Error in config file. Invalid gateway "
      89             :                     "ip_block/route " << str);
      90           0 :                 continue;
      91           0 :             }
      92           0 :             results.push_back(VirtualGatewayConfig::Subnet(addr, plen));
      93           0 :         }
      94           0 :     }
      95           0 : }
      96             : 
      97           1 : void VirtualGatewayConfigTable::InitDone(Agent *agent) {
      98           1 :     agent_ = agent;
      99           2 :     work_queue_.reset(new WorkQueue<boost::shared_ptr<VirtualGatewayData> >
     100           2 :                       (agent_->task_scheduler()->GetTaskId("db::DBTable"), 0,
     101             :                        boost::bind(&VirtualGatewayConfigTable::ProcessRequest,
     102           1 :                                    this, _1)));
     103           1 :     work_queue_->set_name("VGW");
     104           1 : }
     105             : 
     106           0 : void VirtualGatewayConfigTable::Shutdown() {
     107           0 :     work_queue_->Shutdown();
     108           0 : }
     109             : 
     110           0 : void VirtualGatewayConfigTable::Enqueue(
     111             :                                 boost::shared_ptr<VirtualGatewayData> request) {
     112           0 :     work_queue_->Enqueue(request);
     113           0 : }
     114             : 
     115           0 : bool VirtualGatewayConfigTable::ProcessRequest(
     116             :                                 boost::shared_ptr<VirtualGatewayData> request) {
     117           0 :     switch(request->message_type_) {
     118           0 :         case VirtualGatewayData::Add:
     119           0 :             BOOST_FOREACH(VirtualGatewayInfo &vgw, request->vgw_list_) {
     120           0 :                 AddVgw(vgw, request->version_);
     121             :             }
     122           0 :             break;
     123             : 
     124           0 :         case VirtualGatewayData::Delete:
     125           0 :             BOOST_FOREACH(VirtualGatewayInfo &vgw, request->vgw_list_) {
     126           0 :                 DeleteVgw(vgw.interface_name_);
     127             :             }
     128           0 :             break;
     129             : 
     130           0 :         case VirtualGatewayData::Audit:
     131           0 :             DeleteAllOldVersionVgw(request->version_);
     132           0 :             break;
     133             : 
     134           0 :         default:
     135           0 :             assert(0);
     136             :     }
     137           0 :     return true;
     138             : }
     139             : 
     140             : // Add / modify a virtual gateway
     141           0 : bool VirtualGatewayConfigTable::AddVgw(VirtualGatewayInfo &vgw, uint32_t version) {
     142           0 :     std::sort(vgw.subnets_.begin(), vgw.subnets_.end());
     143           0 :     std::sort(vgw.routes_.begin(), vgw.routes_.end());
     144           0 :     Table::iterator it = table_.find(vgw.interface_name_);
     145           0 :     Interface::Transport transport = Interface::TRANSPORT_ETHERNET;
     146           0 :     if (agent_->vrouter_on_nic_mode() ||
     147           0 :             agent_->vrouter_on_host_dpdk()) {
     148           0 :         transport = Interface::TRANSPORT_PMD;
     149             :     }
     150           0 :     if (it == table_.end()) {
     151             :         // Add new gateway
     152           0 :         table_.insert(VirtualGatewayConfig(vgw.interface_name_, vgw.vrf_name_,
     153           0 :                                            vgw.subnets_, vgw.routes_, version));
     154           0 :         agent_->vgw()->CreateVrf(vgw.vrf_name_);
     155           0 :         agent_->vgw()->CreateInterface(vgw.interface_name_, vgw.vrf_name_,
     156             :                                        transport);
     157             :     } else {
     158             :         // modify existing gateway
     159           0 :         if (vgw.vrf_name_ != it->vrf_name()) {
     160           0 :             LOG(DEBUG, "Virtual Gateway : change of vrf is not allowed; " <<
     161             :                 "Interface : " << vgw.interface_name_ << " Old VRF : " <<
     162             :                 it->vrf_name() << " New VRF : " << vgw.vrf_name_);
     163           0 :             return false;
     164             :         }
     165           0 :         VirtualGatewayConfig::SubnetList add_list, del_list;
     166           0 :         if (FindChange(it->subnets(), vgw.subnets_, add_list, del_list)) {
     167           0 :             agent_->vgw()->SubnetUpdate(*it, add_list, del_list);
     168           0 :             it->set_subnets(vgw.subnets_);
     169             :         }
     170             : 
     171           0 :         add_list.clear();
     172           0 :         del_list.clear();
     173           0 :         if (FindChange(it->routes(), vgw.routes_, add_list, del_list)) {
     174           0 :             agent_->vgw()->RouteUpdate(*it, vgw.routes_, add_list, del_list, true);
     175           0 :             it->set_routes(vgw.routes_);
     176             :         }
     177           0 :         it->set_version(version);
     178           0 :     }
     179           0 :     return true;
     180             : }
     181             : 
     182             : // Delete a virtual gateway
     183           0 : bool VirtualGatewayConfigTable::DeleteVgw(const std::string &interface_name) {
     184           0 :     Table::iterator it = table_.find(interface_name);
     185           0 :     if (it != table_.end()) {
     186           0 :         DeleteVgw(it);
     187           0 :         return true;
     188             :     }
     189             : 
     190           0 :     LOG(DEBUG, "Virtual Gateway delete : interface not present; " <<
     191             :         "Interface : " << interface_name);
     192           0 :     return false;
     193             : }
     194             : 
     195           0 : void VirtualGatewayConfigTable::DeleteVgw(Table::iterator it) {
     196           0 :     VirtualGatewayConfig::SubnetList empty_list;
     197           0 :     agent_->vgw()->SubnetUpdate(*it, empty_list, it->subnets());
     198           0 :     agent_->vgw()->RouteUpdate(*it, empty_list, empty_list,
     199             :                                it->routes(), false);
     200           0 :     agent_->vgw()->DeleteInterface(it->interface_name());
     201           0 :     agent_->vgw()->DeleteVrf(it->vrf_name());
     202           0 :     table_.erase(it);
     203           0 : }
     204             : 
     205             : // delete all entries from previous version
     206           0 : void VirtualGatewayConfigTable::DeleteAllOldVersionVgw(uint32_t version) {
     207           0 :     for (Table::iterator it = table_.begin(); it != table_.end();) {
     208           0 :         if (it->version() < version) {
     209           0 :             DeleteVgw(it++);
     210             :         } else {
     211           0 :             it++;
     212             :         }
     213             :     }
     214           0 : }
     215             : 
     216           0 : bool VirtualGatewayConfigTable::FindChange(
     217             :                                 const VirtualGatewayConfig::SubnetList &old_subnets,
     218             :                                 const VirtualGatewayConfig::SubnetList &new_subnets,
     219             :                                 VirtualGatewayConfig::SubnetList &add_list,
     220             :                                 VirtualGatewayConfig::SubnetList &del_list) {
     221           0 :     bool change = false;
     222           0 :     VirtualGatewayConfig::SubnetList::const_iterator it_old = old_subnets.begin();
     223           0 :     VirtualGatewayConfig::SubnetList::const_iterator it_new = new_subnets.begin();
     224           0 :     while (it_old != old_subnets.end() && it_new != new_subnets.end()) {
     225           0 :         if (*it_old < *it_new) {
     226             :             // old entry is deleted
     227           0 :             del_list.push_back(*it_old);
     228           0 :             change = true;
     229           0 :             it_old++;
     230           0 :         } else if (*it_new < *it_old) {
     231             :             // new entry
     232           0 :             add_list.push_back(*it_new);
     233           0 :             change = true;
     234           0 :             it_new++;
     235             :         } else {
     236             :             // no change in entry
     237           0 :             it_old++;
     238           0 :             it_new++;
     239             :         }
     240             :     }
     241             : 
     242             :     // delete remaining old entries
     243           0 :     for (; it_old != old_subnets.end(); ++it_old) {
     244           0 :         del_list.push_back(*it_old);
     245           0 :         change = true;
     246             :     }
     247             : 
     248             :     // add remaining new entries
     249           0 :     for (; it_new != new_subnets.end(); ++it_new) {
     250           0 :         add_list.push_back(*it_new);
     251           0 :         change = true;
     252             :     }
     253             : 
     254           0 :     return change;
     255             : }

Generated by: LCOV version 1.14