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

Generated by: LCOV version 1.14