LCOV - code coverage report
Current view: top level - vnsw/agent/port_ipc - port_ipc_handler.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 148 804 18.4 %
Date: 2026-08-03 02:19:58 Functions: 15 44 34.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #include <ctype.h>
       5             : #include <stdio.h>
       6             : #include <sstream>
       7             : #include <fstream>
       8             : #include <net/if.h>
       9             : #include <boost/uuid/uuid.hpp>
      10             : #include <boost/filesystem.hpp>
      11             : #include <boost/foreach.hpp>
      12             : #include <rapidjson/document.h>
      13             : #include <rapidjson/prettywriter.h>
      14             : #include <rapidjson/stringbuffer.h>
      15             : #include "base/logging.h"
      16             : #include "base/task.h"
      17             : #include "base/string_util.h"
      18             : #include "db/db.h"
      19             : #include "db/db_entry.h"
      20             : #include "db/db_table.h"
      21             : #include "cmn/agent_cmn.h"
      22             : #include "init/agent_param.h"
      23             : #include "cfg/cfg_init.h"
      24             : #include "oper/interface_common.h"
      25             : #include "oper/vm.h"
      26             : #include "oper/vn.h"
      27             : #include "port_ipc/port_ipc_handler.h"
      28             : #include "port_ipc/port_ipc_types.h"
      29             : #include "port_ipc/port_subscribe_table.h"
      30             : 
      31             : using boost::uuids::nil_uuid;
      32             : namespace fs = boost::filesystem;
      33             : 
      34             : /////////////////////////////////////////////////////////////////////////////
      35             : // Utility methods
      36             : /////////////////////////////////////////////////////////////////////////////
      37          60 : static bool GetStringMember(const contrail_rapidjson::Value &d, const char *member,
      38             :                             std::string *data, std::string *err) {
      39          60 :     if (!d.HasMember(member) || !d[member].IsString()) {
      40           0 :         if (err) {
      41           0 :             *err += "Invalid or missing field for <" + string(member) + ">";
      42             :         }
      43           0 :         return false;
      44             :     }
      45             : 
      46          60 :     *data = d[member].GetString();
      47          60 :     return true;
      48             : }
      49             : 
      50          60 : static bool GetUint32Member(const contrail_rapidjson::Value &d, const char *member,
      51             :                             uint32_t *data, std::string *err) {
      52          60 :     if (!d.HasMember(member) || !d[member].IsInt()) {
      53          12 :         if (err) {
      54           0 :             *err += "Invalid or missing field for <" + string(member) + ">";
      55             :         }
      56          12 :         return false;
      57             :     }
      58             : 
      59          48 :     *data = d[member].GetInt();
      60          48 :     return true;
      61             : }
      62             : 
      63          48 : static bool GetUuidMember(const contrail_rapidjson::Value &d, const char *member,
      64             :                           boost::uuids::uuid *u, std::string *err) {
      65          48 :     if (!d.HasMember(member) || !d[member].IsString()) {
      66           0 :         if (err) {
      67           0 :             *err += "Invalid or missing data for <" + string(member) + ">";
      68             :         }
      69           0 :         return false;
      70             :     }
      71             : 
      72          48 :     *u = StringToUuid(d[member].GetString());
      73          48 :     return true;
      74             : }
      75             : 
      76           0 : static void InterfaceResync(Agent *agent, const boost::uuids::uuid &u,
      77             :                             const string &name, bool link_status) {
      78           0 :     InterfaceTable *table = agent->interface_table();
      79           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
      80           0 :     req.key.reset(new VmInterfaceKey(AgentKey::RESYNC, u, name));
      81           0 :     req.data.reset(new VmInterfaceOsOperStateData(link_status));
      82           0 :     table->Enqueue(&req);
      83           0 : }
      84             : 
      85             : /////////////////////////////////////////////////////////////////////////////
      86             : // PortIpcHandler methods
      87             : /////////////////////////////////////////////////////////////////////////////
      88           3 : PortIpcHandler::PortIpcHandler(Agent *agent, const std::string &dir)
      89           3 :     : agent_(agent), ports_dir_(dir), vmvn_dir_(dir + "/vm"), version_(0),
      90           3 :       interface_stale_cleaner_(new InterfaceConfigStaleCleaner(agent)),
      91           6 :        port_subscribe_table_(new PortSubscribeTable(agent_)) {
      92           3 :     interface_stale_cleaner_->set_callback(
      93             :         boost::bind(&InterfaceConfigStaleCleaner::OnInterfaceConfigStaleTimeout,
      94             :                     interface_stale_cleaner_.get(), _1));
      95           3 :     uint32_t timeout_secs = agent->params()->stale_interface_cleanup_timeout();
      96             :     //Set timeout in milliseconds
      97           3 :     interface_stale_cleaner_->set_timeout(timeout_secs * 1000);
      98             : 
      99           3 :     fs::path ports_dir(ports_dir_);
     100           3 :     if (fs::exists(ports_dir) == false) {
     101           0 :         if (!fs::create_directories(ports_dir)) {
     102           0 :             string err_msg = "Creating directory " + ports_dir_ + " failed";
     103           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     104           0 :         }
     105             :     }
     106             : 
     107             :     // Create directory for vm-vn subscription config files
     108           3 :     fs::path vmvn_dir(vmvn_dir_);
     109           3 :     if (fs::exists(vmvn_dir) == false) {
     110           0 :         if (!fs::create_directories(vmvn_dir)) {
     111           0 :             string err_msg = "Creating directory " + vmvn_dir_ + " failed";
     112           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     113           0 :         }
     114             :     }
     115           3 : }
     116             : 
     117           6 : PortIpcHandler::~PortIpcHandler() {
     118           6 : }
     119             : 
     120           0 : void PortIpcHandler::ReloadAllPorts(const std::string &dir, bool check_port,
     121             :                                     bool vm_vn_ports) {
     122           0 :     fs::path ports_dir(dir);
     123           0 :     fs::directory_iterator end_iter;
     124             : 
     125           0 :     if (!fs::exists(ports_dir) || !fs::is_directory(ports_dir)) {
     126           0 :         return;
     127             :     }
     128             : 
     129           0 :     fs::directory_iterator it(ports_dir);
     130           0 :     BOOST_FOREACH(fs::path const &p, std::make_pair(it, end_iter)) {
     131           0 :         if (!fs::is_regular_file(p)) {
     132           0 :             continue;
     133             :         }
     134             :         /* Skip if filename is not in UUID format */
     135           0 :         if (!IsUUID(p.filename().string())) {
     136           0 :             continue;
     137             :         }
     138             : 
     139           0 :         ProcessFile(p.string(), check_port, vm_vn_ports);
     140           0 :     }
     141           0 : }
     142             : 
     143           0 : void PortIpcHandler::ReloadAllPorts(bool check_port) {
     144           0 :     ReloadAllPorts(ports_dir_, check_port, false);
     145             : 
     146             :     /* Process each vm directory under vmvn_dir_ */
     147           0 :     fs::path vmvn_dir(vmvn_dir_);
     148           0 :     fs::directory_iterator end_iter;
     149             : 
     150           0 :     if (!fs::exists(vmvn_dir) || !fs::is_directory(vmvn_dir)) {
     151           0 :         return;
     152             :     }
     153           0 :     fs::directory_iterator it(vmvn_dir);
     154           0 :     BOOST_FOREACH(fs::path const &p, std::make_pair(it, end_iter)) {
     155           0 :         if (!fs::is_directory(p)) {
     156           0 :             continue;
     157             :         }
     158           0 :         ReloadAllPorts(p.string(), check_port, true);
     159           0 :     }
     160           0 : }
     161             : 
     162           0 : void PortIpcHandler::ProcessFile(const string &file, bool check_port,
     163             :                                  bool vm_vn_ports) {
     164           0 :     string err_msg;
     165           0 :     std::ifstream f(file.c_str());
     166           0 :     if (!f.good()) {
     167           0 :         return;
     168             :     }
     169           0 :     std::ostringstream tmp;
     170           0 :     tmp<<f.rdbuf();
     171           0 :     string json = tmp.str();
     172           0 :     f.close();
     173             : 
     174           0 :     if (vm_vn_ports == false)
     175           0 :         AddPortFromJson(json, check_port, err_msg, false);
     176             :     else
     177           0 :         AddVmVnPort(json, check_port, err_msg, false);
     178           0 : }
     179             : 
     180           0 : bool PortIpcHandler::AddPortArrayFromJson(const contrail_rapidjson::Value &d,
     181             :                                           const string &json,
     182             :                                           VmiSubscribeEntryPtrList &req_list,
     183             :                                           bool check_port,
     184             :                                           string &err_msg) {
     185           0 :     for (size_t i = 0; i < d.Size(); i++) {
     186           0 :         const contrail_rapidjson::Value& elem = d[i];
     187           0 :         if (elem.IsObject() == false) {
     188           0 :             err_msg = "Json Array has invalid element ==> " + json;
     189           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     190           0 :             return false;
     191             :         }
     192             : 
     193             :         PortSubscribeEntry *entry =
     194           0 :             MakeAddVmiUuidRequest(elem, check_port, err_msg);
     195           0 :         if (entry == NULL) {
     196           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     197           0 :             return false;
     198             :         }
     199             : 
     200           0 :         req_list.push_back(PortSubscribeEntryPtr(entry));
     201             :     }
     202           0 :     return true;
     203             : }
     204             : 
     205          12 : bool PortIpcHandler::AddPortFromJson(const string &json, bool check_port,
     206             :                                      string &err_msg, bool write_file) {
     207          12 :     contrail_rapidjson::Document d;
     208          12 :     if (d.Parse<0>(const_cast<char *>(json.c_str())).HasParseError()) {
     209           0 :         err_msg = "Invalid Json string ==> " + json;
     210           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     211           0 :         return false;
     212             :     }
     213          12 :     if (!d.IsObject() && !d.IsArray()) {
     214           0 :         err_msg = "Unexpected Json string ==> " + json;
     215           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     216           0 :         return false;
     217             :     }
     218             : 
     219          12 :     if (d.IsArray()) {
     220             :         /* When Json Array is passed, we do 'All or None'. We add all the
     221             :          * elements of the array or none are added. So we do validation in
     222             :          * first pass and addition in second pass */
     223           0 :         VmiSubscribeEntryPtrList req_list;
     224           0 :         if (AddPortArrayFromJson(d, json, req_list, check_port, err_msg)) {
     225           0 :             for (size_t i = 0; i < req_list.size(); i++) {
     226           0 :                 AddVmiUuidEntry(req_list[i], d, write_file, err_msg);
     227             :             }
     228             :         }
     229             : 
     230           0 :         req_list.clear();
     231           0 :         return true;
     232           0 :     }
     233             : 
     234          12 :     PortSubscribeEntryPtr entry(MakeAddVmiUuidRequest(d, check_port, err_msg));
     235          12 :     if (entry.get() == NULL) {
     236           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     237           0 :         return false;
     238             :     }
     239             : 
     240          12 :     AddVmiUuidEntry(entry, d, write_file, err_msg);
     241          12 :     return true;
     242          12 : }
     243             : 
     244          12 : VmiSubscribeEntry *PortIpcHandler::MakeAddVmiUuidRequest
     245             : (const contrail_rapidjson::Value &d, bool check_port,
     246             : std::string &err_msg) const {
     247             :     boost::uuids::uuid vmi_uuid;
     248          12 :     if (GetUuidMember(d, "id", &vmi_uuid, &err_msg) == false) {
     249           0 :         return NULL;
     250             :     }
     251             : 
     252             :     boost::uuids::uuid instance_uuid;
     253          12 :     if (GetUuidMember(d, "instance-id", &instance_uuid, &err_msg) == false) {
     254           0 :         return NULL;
     255             :     }
     256             : 
     257             :     boost::uuids::uuid vn_uuid;
     258          12 :     if (GetUuidMember(d, "vn-id", &vn_uuid, &err_msg) == false) {
     259           0 :         return NULL;
     260             :     }
     261             : 
     262             :     boost::uuids::uuid project_uuid;
     263          12 :     if (GetUuidMember(d, "vm-project-id", &project_uuid, &err_msg) == false) {
     264           0 :         return NULL;
     265             :     }
     266             : 
     267          12 :     string vm_name;
     268          12 :     if (GetStringMember(d, "display-name", &vm_name, &err_msg) == false) {
     269           0 :         return NULL;
     270             :     }
     271             : 
     272          12 :     string ip4_str;
     273          12 :     if (GetStringMember(d, "ip-address", &ip4_str, &err_msg) == false) {
     274           0 :         return NULL;
     275             :     }
     276          12 :     boost::system::error_code ec;
     277          12 :     Ip4Address ip4 = Ip4Address::from_string(ip4_str, ec);
     278             : 
     279          12 :     string ip6_str;
     280          12 :     if (GetStringMember(d, "ip6-address", &ip6_str, &err_msg) == false) {
     281           0 :         return NULL;
     282             :     }
     283          12 :     boost::system::error_code ec6;
     284          12 :     Ip6Address ip6 = Ip6Address::from_string(ip6_str, ec6);
     285             : 
     286             :     uint32_t val;
     287          12 :     if (GetUint32Member(d, "type", &val, &err_msg) == false) {
     288           0 :         return NULL;
     289             :     }
     290             : 
     291          12 :     PortSubscribeEntry::Type vmi_type = PortSubscribeEntry::VMPORT;
     292          12 :     uint32_t link_state = 1;
     293          12 :     if (val == 1) {
     294           0 :         vmi_type = PortSubscribeEntry::NAMESPACE;
     295          12 :     } else if (val == 2) {
     296           0 :         vmi_type = PortSubscribeEntry::REMOTE_PORT;
     297             :         /* Default port-state is disabled for REMOTE_PORT */
     298           0 :         link_state = 0;
     299             :     }
     300          12 :     if (vmi_type == PortSubscribeEntry::VMPORT) {
     301          12 :         if (vn_uuid == nil_uuid()) {
     302           0 :             err_msg = "Invalid VN uuid";
     303           0 :             return NULL;
     304             :         }
     305             :     }
     306             : 
     307          12 :     string ifname;
     308          12 :     if (GetStringMember(d, "system-name", &ifname, &err_msg) == false) {
     309           0 :         return NULL;
     310             :     }
     311             :     // Verify that interface exists in OS
     312          12 :     if (vmi_type != PortSubscribeEntry::REMOTE_PORT) {
     313          12 :         if (check_port && !InterfaceExists(ifname)) {
     314           0 :             err_msg = "Interface does not exist in OS";
     315           0 :             return NULL;
     316             :         }
     317             :     }
     318             : 
     319          12 :     string mac;
     320          12 :     if (GetStringMember(d, "mac-address", &mac, &err_msg) == false) {
     321           0 :         return NULL;
     322             :     }
     323          12 :     if (ValidateMac(mac) == false) {
     324           0 :         err_msg = "Invalid MAC, Use xx:xx:xx:xx:xx:xx format";
     325           0 :         return NULL;
     326             :     }
     327             : 
     328             :     // Sanity check. We should not have isolated_vlan_id set and vlan_id unset
     329          12 :     uint32_t rx_vlan_id = VmInterface::kInvalidVlanId;
     330          12 :     if (GetUint32Member(d, "rx-vlan-id", &rx_vlan_id, &err_msg) == false) {
     331           0 :         return NULL;
     332             :     }
     333             : 
     334          12 :     uint32_t tx_vlan_id = VmInterface::kInvalidVlanId;
     335          12 :     if (GetUint32Member(d, "tx-vlan-id", &tx_vlan_id, &err_msg) == false) {
     336           0 :         return NULL;
     337             :     }
     338             : 
     339          12 :     if ((rx_vlan_id != VmInterface::kInvalidVlanId) &&
     340           0 :         (tx_vlan_id == VmInterface::kInvalidVlanId-1)) {
     341             :         err_msg += "Invalid request. RX (isolated) vlan set, "
     342           0 :             "but TX vlan not set";
     343           0 :         return NULL;
     344             :     }
     345             : 
     346             :     // Dont return in case of error as this is an optional parameter for
     347             :     // DPDK/vhostuser
     348          12 :     uint32_t vhostuser_mode = 0;
     349          12 :     GetUint32Member(d, "vhostuser-mode", &vhostuser_mode, &err_msg);
     350             :     /* Don't return error in case link-state is not found. This is required
     351             :      * for backward compatibility when old files are used with new
     352             :      * vrouter-agent. If field is absent then value as initialized above
     353             :      * for link_state gets used */
     354          12 :     GetUint32Member(d, "link-state", &link_state, NULL);
     355             : 
     356          12 :     CONFIG_TRACE(AddPortEnqueue, "Add", UuidToString(vmi_uuid),
     357             :                  UuidToString(instance_uuid), UuidToString(vn_uuid),
     358             :                  ip4.to_string(), ifname, mac, vm_name, tx_vlan_id, rx_vlan_id,
     359             :                  UuidToString(project_uuid),
     360             :                  PortSubscribeEntry::TypeToString(vmi_type),
     361             :                  ip6.to_string(), version_, vhostuser_mode, link_state);
     362          12 :     return new VmiSubscribeEntry(vmi_type, ifname, version_, vmi_uuid,
     363             :                                  instance_uuid, vm_name, vn_uuid, project_uuid,
     364             :                                  ip4, ip6, mac, tx_vlan_id, rx_vlan_id,
     365          12 :                                  vhostuser_mode, link_state);
     366          12 : }
     367             : 
     368          12 : bool PortIpcHandler::AddVmiUuidEntry(PortSubscribeEntryPtr entry_ref,
     369             :                                      const contrail_rapidjson::Value &d,
     370             :                                      bool write_file, string &err_msg) const {
     371             :     VmiSubscribeEntry *entry =
     372          12 :         dynamic_cast<VmiSubscribeEntry *>(entry_ref.get());
     373             :     // If Writing to file fails return error
     374          12 :     if(write_file && WriteJsonToFile(entry, false) == false) {
     375           0 :         err_msg += "Writing of Json string to file failed for " +
     376           0 :             UuidToString(entry->vmi_uuid());
     377           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     378           0 :         return false;
     379             :     }
     380             : 
     381          12 :     CONFIG_TRACE(AddPortEnqueue, "Add", UuidToString(entry->vmi_uuid()),
     382             :                  UuidToString(entry->vm_uuid()), UuidToString(entry->vn_uuid()),
     383             :                  entry->ip4_addr().to_string(), entry->ifname(),
     384             :                  entry->mac_addr(), entry->vm_name(), entry->tx_vlan_id(),
     385             :                  entry->rx_vlan_id(), UuidToString(entry->project_uuid()),
     386             :                  PortSubscribeEntry::TypeToString(entry->type()),
     387             :                  entry->ip6_addr().to_string(), entry->version(),
     388             :                  entry->vhostuser_mode(), entry->link_state());
     389          12 :     port_subscribe_table_->AddVmi(entry->vmi_uuid(), entry_ref);
     390          12 :     return true;
     391             : }
     392             : 
     393           0 : bool PortIpcHandler::WriteJsonToFile(VmiSubscribeEntry *entry, bool overwrite)
     394             :                                      const {
     395           0 :     string filename = ports_dir_ + "/" + UuidToString(entry->vmi_uuid());
     396           0 :     fs::path file_path(filename);
     397             : 
     398           0 :     bool remove = true;
     399             :     /* Don't overwrite if the file already exists */
     400           0 :     if (!overwrite) {
     401           0 :         remove = !fs::exists(file_path);
     402           0 :         if (!remove) {
     403           0 :             return true;
     404             :         }
     405             :     }
     406             : 
     407           0 :     string info = MakeVmiUuidJson(entry, true);
     408           0 :     if (info.empty()) {
     409           0 :         LOG(ERROR, "Error producing entry JSON for port " << file_path.filename());
     410           0 :         return false;
     411             :     }
     412           0 :     std::ofstream fs(filename.c_str());
     413           0 :     if (fs.fail()) {
     414           0 :         LOG(ERROR, "Cannot open file " << filename << " for writing");
     415           0 :         return false;
     416             :     }
     417           0 :     bool output = (fs << info).good();
     418           0 :     fs.close();
     419           0 :     if (!output) {
     420           0 :         LOG(ERROR, "Cannot write JSON to the file " << filename);
     421           0 :         if (remove) {
     422           0 :             fs::remove(file_path);
     423             :         }
     424             :     }
     425             : 
     426           0 :     return output;
     427           0 : }
     428             : 
     429          12 : bool PortIpcHandler::ValidateMac(const string &mac) const {
     430          12 :     size_t pos = 0;
     431          12 :     int colon = 0;
     432          12 :     if (mac.empty()) {
     433           0 :         return false;
     434             :     }
     435          72 :     while ((pos = mac.find(':', pos)) != std::string::npos) {
     436          60 :         colon++;
     437          60 :         pos += 1;
     438             :     }
     439          12 :     if (colon != 5)
     440           0 :         return false;
     441             : 
     442          12 :     if (MacAddress::FromString(mac).IsZero())
     443           0 :         return false;
     444             : 
     445          12 :     return true;
     446             : }
     447             : 
     448           0 : bool PortIpcHandler::DeletePort(const string &url, string &err_msg) {
     449           0 :     boost::uuids::uuid vmi_uuid = StringToUuid(url);
     450           0 :     if (vmi_uuid != nil_uuid()) {
     451           0 :         DeleteVmiUuidEntry(vmi_uuid, err_msg);
     452           0 :         return true;
     453             :     }
     454             : 
     455           0 :     return true;
     456             : }
     457             : 
     458          14 : void PortIpcHandler::DeleteVmiUuidEntry(
     459             :     const boost::uuids::uuid &u, string &err_msg) {
     460          14 :     uint64_t version = 0;
     461          14 :     PortSubscribeEntryPtr entry = port_subscribe_table_->GetVmi(u);
     462          14 :     if (entry.get() != NULL) {
     463          12 :         version = entry->version();
     464             :     }
     465          14 :     port_subscribe_table_->DeleteVmi(u);
     466          14 :     CONFIG_TRACE(DeletePortEnqueue, "Delete", UuidToString(u), version);
     467             : 
     468          28 :     string file = ports_dir_ + "/" + UuidToString(u);
     469          14 :     fs::path file_path(file);
     470             : 
     471          14 :     if (fs::exists(file_path) && fs::is_regular_file(file_path)) {
     472           0 :         if (remove(file.c_str())) {
     473           0 :             err_msg = "Error deleting file " + file;
     474             :         }
     475             :     }
     476          14 : }
     477             : 
     478           0 : bool PortIpcHandler::EnablePort(const string &url, string &err_msg) {
     479           0 :     boost::uuids::uuid u = StringToUuid(url);
     480           0 :     if (u == nil_uuid()) {
     481           0 :         err_msg = "Port Not found " + url;
     482           0 :         return false;
     483             :     }
     484           0 :     PortSubscribeEntryPtr entry = port_subscribe_table_->GetVmi(u);
     485           0 :     if (entry.get() == NULL) {
     486           0 :         err_msg = "Port Not found " + url;
     487           0 :         return false;
     488             :     }
     489           0 :     if (entry->type() != PortSubscribeEntry::REMOTE_PORT) {
     490           0 :         err_msg = "Incorrect Port type for " + url;
     491           0 :         return false;
     492             :     }
     493             :     VmiSubscribeEntry *ventry =
     494           0 :         dynamic_cast<VmiSubscribeEntry *>(entry.get());
     495           0 :     if (ventry == NULL) {
     496           0 :         err_msg = "Invalid Port " + url;
     497           0 :         return false;
     498             :     }
     499           0 :     int written_to_file = 0;
     500           0 :     if (!ventry->link_state()) {
     501           0 :         ventry->set_link_state(1);
     502           0 :         written_to_file = 1;
     503           0 :         if (WriteJsonToFile(ventry, true) == false) {
     504           0 :             err_msg += "Writing of Json to file failed on enable for " +
     505           0 :                 UuidToString(ventry->vmi_uuid());
     506           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     507           0 :             written_to_file = 0;
     508             :         }
     509             :     }
     510           0 :     InterfaceResync(agent_, u, entry->ifname(), true);
     511           0 :     string msg = "Enable state for " + url + " version " +
     512           0 :         integerToString(entry->version()) + " written to file : " +
     513           0 :         integerToString(written_to_file);
     514           0 :     CONFIG_TRACE(PortInfo, msg);
     515           0 :     return true;
     516           0 : }
     517             : 
     518           0 : bool PortIpcHandler::DisablePort(const string &url, string &err_msg) {
     519           0 :     boost::uuids::uuid u = StringToUuid(url);
     520           0 :     if (u == nil_uuid()) {
     521           0 :         err_msg = "Port Not found " + url;
     522           0 :         return false;
     523             :     }
     524           0 :     PortSubscribeEntryPtr entry = port_subscribe_table_->GetVmi(u);
     525           0 :     if (entry.get() == NULL) {
     526           0 :         err_msg = "Port Not found " + url;
     527           0 :         return false;
     528             :     }
     529           0 :     if (entry->type() != PortSubscribeEntry::REMOTE_PORT) {
     530           0 :         err_msg = "Incorrect Port type for " + url;
     531           0 :         return false;
     532             :     }
     533             :     VmiSubscribeEntry *ventry =
     534           0 :         dynamic_cast<VmiSubscribeEntry *>(entry.get());
     535           0 :     if (ventry == NULL) {
     536           0 :         err_msg = "Invalid Port " + url;
     537           0 :         return false;
     538             :     }
     539           0 :     int written_to_file = 0;
     540           0 :     if (ventry->link_state()) {
     541           0 :         ventry->set_link_state(0);
     542           0 :         written_to_file = 1;
     543           0 :         if (WriteJsonToFile(ventry, true) == false) {
     544           0 :             err_msg += "Writing of Json to file failed on disable for " +
     545           0 :                 UuidToString(ventry->vmi_uuid());
     546           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     547           0 :             written_to_file = 0;
     548             :         }
     549             :     }
     550           0 :     InterfaceResync(agent_, u, entry->ifname(), false);
     551           0 :     string msg = "Disable state for " + url + " version " +
     552           0 :         integerToString(entry->version()) + " written to file : " +
     553           0 :         integerToString(written_to_file);
     554           0 :     CONFIG_TRACE(PortInfo, msg);
     555           0 :     return true;
     556           0 : }
     557             : 
     558           0 : bool PortIpcHandler::IsUUID(const string &uuid_str) const {
     559           0 :     boost::uuids::uuid vmi_uuid = StringToUuid(uuid_str);
     560           0 :     if (vmi_uuid == nil_uuid()) {
     561           0 :         return false;
     562             :     }
     563           0 :     return true;
     564             : }
     565             : 
     566         108 : void PortIpcHandler::AddMember(const char *key, const char *value,
     567             :         contrail_rapidjson::Document *doc) const {
     568         108 :     contrail_rapidjson::Document::AllocatorType &a = doc->GetAllocator();
     569         108 :     contrail_rapidjson::Value v;
     570         108 :     contrail_rapidjson::Value vk;
     571         108 :     doc->AddMember(vk.SetString(key, a), v.SetString(value, a), a);
     572         108 : }
     573             : 
     574          12 : std::string PortIpcHandler::MakeVmiUuidJson(const VmiSubscribeEntry *entry,
     575             :                                             bool meta_info) const {
     576          12 :     contrail_rapidjson::Document doc;
     577          12 :     doc.SetObject();
     578          12 :     contrail_rapidjson::Document::AllocatorType &a = doc.GetAllocator();
     579             : 
     580          12 :     string str1 = UuidToString(entry->vmi_uuid());
     581          12 :     AddMember("id", str1.c_str(), &doc);
     582          12 :     string str2 = UuidToString(entry->vm_uuid());
     583          12 :     AddMember("instance-id", str2.c_str(), &doc);
     584          12 :     AddMember("display-name", entry->vm_name().c_str(), &doc);
     585          12 :     string str3 = entry->ip4_addr().to_string();
     586          12 :     AddMember("ip-address", str3.c_str(), &doc);
     587          12 :     string str4 = entry->ip6_addr().to_string();
     588          12 :     AddMember("ip6-address", str4.c_str(), &doc);
     589          12 :     string str5 = UuidToString(entry->vn_uuid());
     590          12 :     AddMember("vn-id", str5.c_str(), &doc);
     591          12 :     string str6 = UuidToString(entry->project_uuid());
     592          12 :     AddMember("vm-project-id", str6.c_str(), &doc);
     593          12 :     AddMember("mac-address", entry->mac_addr().c_str(), &doc);
     594          12 :     AddMember("system-name", entry->ifname().c_str(), &doc);
     595          12 :     doc.AddMember("type", (int)entry->type(), a);
     596          12 :     doc.AddMember("rx-vlan-id", (int)entry->rx_vlan_id(), a);
     597          12 :     doc.AddMember("tx-vlan-id", (int)entry->tx_vlan_id(), a);
     598          12 :     doc.AddMember("vhostuser-mode", (int)entry->vhostuser_mode(), a);
     599             :     /* link-state has to be persisted for port-type of REMOTE_PORT.
     600             :      * REMOTE_PORT will NOT have corresponding tap interface in OS to pick
     601             :      * operational state. */
     602          12 :     if (entry->type() == PortSubscribeEntry::REMOTE_PORT) {
     603           0 :         doc.AddMember("link-state", (int)entry->link_state(), a);
     604             :     }
     605          12 :     if (meta_info) {
     606           0 :         AddMember("author", agent_->program_name().c_str(), &doc);
     607           0 :         string now = duration_usecs_to_string(UTCTimestampUsec());
     608           0 :         AddMember("time", now.c_str(), &doc);
     609           0 :     }
     610             : 
     611          12 :     contrail_rapidjson::StringBuffer buffer;
     612          12 :     contrail_rapidjson::PrettyWriter<contrail_rapidjson::StringBuffer> writer(buffer);
     613          12 :     doc.Accept(writer);
     614             : 
     615          24 :     return buffer.GetString();
     616          12 : }
     617             : 
     618           0 : bool PortIpcHandler::GetPortInfo(const string &uuid_str, string &info) const {
     619           0 :     boost::uuids::uuid vmi_uuid = StringToUuid(uuid_str);
     620           0 :     if (vmi_uuid == nil_uuid()) {
     621           0 :         return false;
     622             :     }
     623             : 
     624           0 :     return MakeJsonFromVmi(vmi_uuid, info);
     625             : }
     626             : 
     627           0 : void PortIpcHandler::SyncHandler() {
     628           0 :     ++version_;
     629           0 :     interface_stale_cleaner_->StartStaleCleanTimer(version_);
     630           0 :     string msg = " Sync " + integerToString(version_);
     631           0 :     CONFIG_TRACE(PortInfo, msg);
     632           0 : }
     633             : 
     634           3 : void PortIpcHandler::InitDone() {
     635           3 :     port_subscribe_table_->InitDone();
     636           3 : }
     637             : 
     638           3 : void PortIpcHandler::Shutdown() {
     639           3 :     port_subscribe_table_->Shutdown();
     640           3 : }
     641             : 
     642           0 : bool PortIpcHandler::BuildGatewayArrayElement
     643             : (const contrail_rapidjson::Value &d, VirtualGatewayConfig::Subnet *entry) const {
     644           0 :     if (!d.HasMember("ip-address") || !d["ip-address"].IsString()) {
     645           0 :         return false;
     646             :     }
     647             : 
     648           0 :     if (!d.HasMember("prefix-len") || !d["prefix-len"].IsInt()) {
     649           0 :         return false;
     650             :     }
     651           0 :     boost::system::error_code ec;
     652           0 :     entry->ip_ = Ip4Address::from_string(d["ip-address"].GetString(), ec);
     653           0 :     if (ec.failed()) {
     654           0 :         return false;
     655             :     }
     656           0 :     entry->plen_ = d["prefix-len"].GetInt();
     657           0 :     return true;
     658             : }
     659             : 
     660           0 : bool PortIpcHandler::ValidGatewayJsonString
     661             : (const contrail_rapidjson::Value &d, VirtualGatewayConfig::SubnetList *list) const {
     662           0 :     for (size_t i = 0; i < d.Size(); i++) {
     663           0 :         const contrail_rapidjson::Value& elem = d[i];
     664           0 :         if (!elem.IsObject()) {
     665           0 :             return false;
     666             :         }
     667           0 :         VirtualGatewayConfig::Subnet entry;
     668           0 :         if (!BuildGatewayArrayElement(elem, &entry)) {
     669           0 :             return false;
     670             :         }
     671           0 :         list->push_back(entry);
     672           0 :     }
     673           0 :     return true;
     674             : }
     675             : 
     676           0 : bool PortIpcHandler::HasAllGatewayFields(const contrail_rapidjson::Value &d,
     677             :                                          std::string &member_err,
     678             :                                          VirtualGatewayInfo *req) const {
     679           0 :     if (!d.HasMember("interface") || !d["interface"].IsString()) {
     680           0 :         member_err = "interface";
     681           0 :         return false;
     682             :     }
     683             : 
     684           0 :     if (!d.HasMember("routing-instance") || !d["routing-instance"].IsString()) {
     685           0 :         member_err = "routing-instance";
     686           0 :         return false;
     687             :     }
     688             : 
     689           0 :     if (!d.HasMember("subnets") || !d["subnets"].IsArray()) {
     690           0 :         member_err = "subnets";
     691           0 :         return false;
     692             :     }
     693             : 
     694           0 :     if (!ValidGatewayJsonString(d["subnets"], &req->subnets_)) {
     695           0 :         member_err = "subnets value";
     696           0 :         return false;
     697             :     }
     698             : 
     699           0 :     if (!d.HasMember("routes") || !d["routes"].IsArray()) {
     700           0 :         member_err = "routes";
     701           0 :         return false;
     702             :     }
     703             : 
     704           0 :     if (!ValidGatewayJsonString(d["routes"], &req->routes_)) {
     705           0 :         member_err = "routes value";
     706           0 :         return false;
     707             :     }
     708           0 :     req->interface_name_ = d["interface"].GetString();
     709           0 :     req->vrf_name_ = d["routing-instance"].GetString();
     710             : 
     711           0 :     return true;
     712             : }
     713             : 
     714           0 : bool PortIpcHandler::BuildGateway(const contrail_rapidjson::Value &d,
     715             :                                   const string &json, string &err_msg,
     716             :                                   VirtualGatewayInfo *req) const {
     717           0 :     string member_err;
     718           0 :     if (!HasAllGatewayFields(d, member_err, req)) {
     719             :         err_msg = "Json string does not have all required members, "
     720           0 :                          + member_err + " is missing ==> "
     721           0 :                          + json;
     722           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     723           0 :         return false;
     724             :     }
     725           0 :     return true;
     726           0 : }
     727             : 
     728           0 : bool PortIpcHandler::AddVgwFromJson(const string &json, string &err_msg) const {
     729           0 :     contrail_rapidjson::Document d;
     730           0 :     if (d.Parse<0>(const_cast<char *>(json.c_str())).HasParseError()) {
     731           0 :         err_msg = "Invalid Json string ==> " + json;
     732           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     733           0 :         return false;
     734             :     }
     735           0 :     if (!d.IsArray()) {
     736           0 :         err_msg = "Unexpected Json string (not an array) ==> " + json;
     737           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     738           0 :         return false;
     739             :     }
     740             : 
     741           0 :     std::vector<VirtualGatewayInfo> req_list;
     742           0 :     for (size_t i = 0; i < d.Size(); i++) {
     743           0 :         const contrail_rapidjson::Value& elem = d[i];
     744           0 :         if (elem.IsObject()) {
     745           0 :             VirtualGatewayInfo req("");
     746           0 :             if (!BuildGateway(elem, json, err_msg, &req)) {
     747           0 :                 return false;
     748             :             }
     749           0 :             req_list.push_back(req);
     750           0 :         } else {
     751           0 :             err_msg = "Json Array has invalid element ==> " + json;
     752           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     753           0 :             return false;
     754             :         }
     755             :     }
     756             : 
     757           0 :     if (!req_list.empty()) {
     758             :         boost::shared_ptr<VirtualGatewayData>
     759             :             vgw_data(new VirtualGatewayData(VirtualGatewayData::Add, req_list,
     760           0 :                                             0));
     761           0 :         agent_->params()->vgw_config_table()->Enqueue(vgw_data);
     762           0 :         CONFIG_TRACE(VgwEnqueue, "Add", json);
     763           0 :     }
     764           0 :     return true;
     765           0 : }
     766             : 
     767           0 : bool PortIpcHandler::DelVgwFromJson(const string &json, string &err_msg) const {
     768           0 :     contrail_rapidjson::Document d;
     769           0 :     if (d.Parse<0>(const_cast<char *>(json.c_str())).HasParseError()) {
     770           0 :         err_msg = "Invalid Json string ==> " + json;
     771           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     772           0 :         return false;
     773             :     }
     774           0 :     if (!d.IsArray()) {
     775           0 :         err_msg = "Unexpected Json string (not an array) ==> " + json;
     776           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
     777           0 :         return false;
     778             :     }
     779             : 
     780           0 :     std::vector<VirtualGatewayInfo> req_list;
     781           0 :     for (size_t i = 0; i < d.Size(); i++) {
     782           0 :         const contrail_rapidjson::Value& elem = d[i];
     783           0 :         if (elem.IsObject()) {
     784           0 :             if (!elem.HasMember("interface") || !elem["interface"].IsString()) {
     785             :                 err_msg = "Json string does not have or has invalid value for "
     786           0 :                     "member interface ==> " + json;
     787           0 :                 CONFIG_TRACE(PortInfo, err_msg.c_str());
     788           0 :                 return false;
     789             :             }
     790           0 :             VirtualGatewayInfo req(elem["interface"].GetString());
     791           0 :             req_list.push_back(req);
     792           0 :         } else {
     793           0 :             err_msg = "Json Array has invalid element ==> " + json;
     794           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     795           0 :             return false;
     796             :         }
     797             :     }
     798             : 
     799           0 :     if (!req_list.empty()) {
     800             :         boost::shared_ptr<VirtualGatewayData>
     801             :             vgw_data(new VirtualGatewayData(VirtualGatewayData::Delete,
     802           0 :                                             req_list, 0));
     803           0 :         agent_->params()->vgw_config_table()->Enqueue(vgw_data);
     804           0 :         CONFIG_TRACE(VgwEnqueue, "Del", json);
     805           0 :     }
     806           0 :     return true;
     807           0 : }
     808             : 
     809             : /////////////////////////////////////////////////////////////////////////////
     810             : // VM based message related methods
     811             : /////////////////////////////////////////////////////////////////////////////
     812           0 : bool PortIpcHandler::AddVmVnPort(const string &json, bool check_port,
     813             :                                  string &err_msg, bool write_file) {
     814           0 :     contrail_rapidjson::Document d;
     815           0 :     if (d.Parse<0>(const_cast<char *>(json.c_str())).HasParseError()) {
     816           0 :         err_msg = "Invalid Json string ==> " + json;
     817           0 :         CONFIG_TRACE(VmVnPortInfo, err_msg.c_str());
     818           0 :         return false;
     819             :     }
     820             : 
     821           0 :     if (!d.IsObject()) {
     822           0 :         err_msg = "Unexpected Json string ==> " + json;
     823           0 :         CONFIG_TRACE(VmVnPortInfo, err_msg.c_str());
     824           0 :         return false;
     825             :     }
     826             : 
     827           0 :     if (d.IsArray()) {
     828           0 :         err_msg = "Arrays not supported in json for vm ==> " + json;
     829           0 :         CONFIG_TRACE(VmVnPortInfo, err_msg.c_str());
     830           0 :         return false;
     831             :     }
     832             : 
     833           0 :     PortSubscribeEntryPtr entry(MakeAddVmVnPortRequest(d, check_port, err_msg));
     834           0 :     if (entry.get() == NULL) {
     835           0 :         CONFIG_TRACE(VmVnPortInfo, err_msg.c_str());
     836           0 :         return false;
     837             :     }
     838             : 
     839           0 :     AddVmVnPortEntry(entry, d, write_file, err_msg);
     840           0 :     return true;
     841           0 : }
     842             : 
     843           0 : bool PortIpcHandler::AddVmVnPortEntry(PortSubscribeEntryPtr entry_ref,
     844             :                                      const contrail_rapidjson::Value &d,
     845             :                                      bool write_file, string &err_msg) const {
     846             :     VmVnPortSubscribeEntry *entry =
     847           0 :         dynamic_cast<VmVnPortSubscribeEntry *>(entry_ref.get());
     848             :     // If Writing to file fails return error
     849           0 :     if(write_file && WriteJsonToFile(entry) == false) {
     850           0 :         err_msg += "Writing of Json string to file failed for Vm " +
     851           0 :             UuidToString(entry->vm_uuid());
     852           0 :         CONFIG_TRACE(VmVnPortInfo, err_msg.c_str());
     853           0 :         return false;
     854             :     }
     855             : 
     856           0 :     CONFIG_TRACE(AddVmVnPortEnqueue, "Add", UuidToString(entry->vm_uuid()),
     857             :         UuidToString(entry->vn_uuid()), UuidToString(entry->vmi_uuid()),
     858             :         entry->vm_name(), entry->vm_identifier(), entry->ifname(),
     859             :         entry->vm_ifname(), entry->vm_namespace(), version_);
     860           0 :     port_subscribe_table_->AddVmVnPort(entry->vm_uuid(),
     861           0 :         entry->vn_uuid(), entry->vmi_uuid(), entry_ref);
     862           0 :     return true;
     863             : }
     864             : 
     865           0 : VmVnPortSubscribeEntry *PortIpcHandler::MakeAddVmVnPortRequest
     866             : (const contrail_rapidjson::Value &d, bool check_port,
     867             : std::string &err_msg) const {
     868           0 :     PortSubscribeEntry::Type vmi_type = PortSubscribeEntry::VMPORT;
     869             :     boost::uuids::uuid vm_uuid;
     870           0 :     if (GetUuidMember(d, "vm-uuid", &vm_uuid, &err_msg) == false) {
     871           0 :         return NULL;
     872             :     }
     873             : 
     874           0 :     string host_ifname;
     875           0 :     if (GetStringMember(d, "host-ifname", &host_ifname, &err_msg) == false) {
     876           0 :         return NULL;
     877             :     }
     878             :     // Verify that interface exists in OS
     879           0 :     if (vmi_type != PortSubscribeEntry::REMOTE_PORT) {
     880           0 :         if (check_port && !InterfaceExists(host_ifname)) {
     881           0 :             err_msg = "Interface does not exist in OS";
     882           0 :             return NULL;
     883             :         }
     884             :     }
     885             : 
     886           0 :     string vm_name;
     887           0 :     if (GetStringMember(d, "vm-name", &vm_name, &err_msg) == false) {
     888           0 :         return NULL;
     889             :     }
     890             : 
     891           0 :     string vm_identifier;
     892           0 :     GetStringMember(d, "vm-id", &vm_identifier, NULL);
     893             : 
     894           0 :     string vm_ifname;
     895           0 :     GetStringMember(d, "vm-ifname", &vm_ifname, NULL);
     896             : 
     897           0 :     string vm_namespace;
     898           0 :     GetStringMember(d, "vm-namespace", &vm_namespace, NULL);
     899             : 
     900             :     boost::uuids::uuid vn_uuid;
     901           0 :     if (GetUuidMember(d, "vn-uuid", &vn_uuid, &err_msg) == false) {
     902           0 :         return NULL;
     903             :     }
     904             : 
     905             :     boost::uuids::uuid vmi_uuid;
     906           0 :     if (GetUuidMember(d, "vmi-uuid", &vmi_uuid, &err_msg) == false) {
     907           0 :         return NULL;
     908             :     }
     909             : 
     910           0 :     CONFIG_TRACE(AddVmVnPortEnqueue, "Add", UuidToString(vm_uuid),
     911             :                  UuidToString(vn_uuid), UuidToString(vmi_uuid),
     912             :                  vm_name, vm_identifier, host_ifname, vm_ifname,
     913             :                  vm_namespace, version_);
     914             : 
     915           0 :     return new VmVnPortSubscribeEntry(vmi_type, host_ifname, version_, vm_uuid,
     916             :                                       vn_uuid, vmi_uuid, vm_name, vm_identifier,
     917           0 :                                       vm_ifname, vm_namespace);
     918           0 : }
     919             : 
     920           0 : void PortIpcHandler::MakeVmVnPortJson(const VmVnPortSubscribeEntry *entry,
     921             :                                       string &info, bool meta_info) const {
     922           0 :     contrail_rapidjson::Document doc;
     923           0 :     doc.SetObject();
     924             : 
     925           0 :     string str2 = UuidToString(entry->vm_uuid());
     926           0 :     AddMember("vm-uuid", str2.c_str(), &doc);
     927           0 :     str2 = UuidToString(entry->vn_uuid());
     928           0 :     AddMember("vn-uuid", str2.c_str(), &doc);
     929           0 :     str2 = UuidToString(entry->vmi_uuid());
     930           0 :     AddMember("vmi-uuid", str2.c_str(), &doc);
     931           0 :     AddMember("vm-id", entry->vm_identifier().c_str(), &doc);
     932           0 :     AddMember("vm-name", entry->vm_name().c_str(), &doc);
     933           0 :     AddMember("host-ifname", entry->ifname().c_str(), &doc);
     934           0 :     AddMember("vm-ifname", entry->vm_ifname().c_str(), &doc);
     935           0 :     AddMember("vm-namespace", entry->vm_namespace().c_str(), &doc);
     936             : 
     937           0 :     if (meta_info) {
     938           0 :         AddMember("author", agent_->program_name().c_str(), &doc);
     939           0 :         string now = duration_usecs_to_string(UTCTimestampUsec());
     940           0 :         AddMember("time", now.c_str(), &doc);
     941           0 :     }
     942             : 
     943           0 :     contrail_rapidjson::StringBuffer buffer;
     944           0 :     contrail_rapidjson::PrettyWriter<contrail_rapidjson::StringBuffer> writer(buffer);
     945           0 :     doc.Accept(writer);
     946           0 :     info = buffer.GetString();
     947           0 :     return;
     948           0 : }
     949             : 
     950           0 : bool PortIpcHandler::WriteJsonToFile(VmVnPortSubscribeEntry *entry) const {
     951           0 :     string vmvn_dir = vmvn_dir_ + "/" + entry->vm_name();
     952           0 :     fs::path base_dir(vmvn_dir);
     953           0 :     if (fs::exists(base_dir) == false) {
     954           0 :         if (!fs::create_directories(base_dir)) {
     955           0 :             string err_msg = "Creating directory " + vmvn_dir + " failed";
     956           0 :             CONFIG_TRACE(PortInfo, err_msg.c_str());
     957           0 :             return false;
     958           0 :         }
     959             :     }
     960             : 
     961           0 :     string filename = vmvn_dir + "/" + UuidToString(entry->vmi_uuid());
     962           0 :     fs::path file_path(filename);
     963             :     /* Don't overwrite if the file already exists */
     964           0 :     if (fs::exists(file_path)) {
     965           0 :         return true;
     966             :     }
     967             : 
     968           0 :     string info;
     969           0 :     MakeVmVnPortJson(entry, info, true);
     970           0 :     if (info.empty()) {
     971           0 :         LOG(ERROR, "Error producing entry JSON for VM " << entry->vm_name());
     972           0 :         return false;
     973             :     }
     974           0 :     std::ofstream fs(filename.c_str());
     975           0 :     if (fs.fail()) {
     976           0 :         LOG(ERROR, "Cannot open file " << filename << " for writing");
     977           0 :         return false;
     978             :     }
     979           0 :     bool output = (fs << info).good();
     980           0 :     fs.close();
     981           0 :     if (!output) {
     982           0 :         LOG(ERROR, "Cannot write JSON to the file " << filename);
     983           0 :         fs::remove(file_path);
     984             :     }
     985             : 
     986           0 :     return output;
     987           0 : }
     988             : 
     989           0 : bool PortIpcHandler::DeleteVmVnPort(const boost::uuids::uuid &vm_uuid,
     990             :                                     string &err_msg) {
     991             :     uint64_t version;
     992           0 :     bool failed = false;
     993           0 :     string vmvn_dir  = vmvn_dir_ + "/" + UuidToString(vm_uuid);
     994           0 :     std::set<boost::uuids::uuid> vmi_uuid_set;
     995             : 
     996           0 :     if (!port_subscribe_table_->VmVnToVmiSet(vm_uuid, vmi_uuid_set))
     997           0 :         return false;
     998             : 
     999           0 :     std::set<boost::uuids::uuid>::iterator it = vmi_uuid_set.begin();
    1000           0 :     while (it != vmi_uuid_set.end()) {
    1001           0 :         boost::uuids::uuid vmi_uuid = *it;
    1002             :         const PortSubscribeTable::VmiEntry *vmi_entry =
    1003           0 :                 port_subscribe_table_->VmiToEntry(vmi_uuid);
    1004             :         PortSubscribeEntryPtr entry =
    1005             :                 port_subscribe_table_->GetVmVnPort(vm_uuid,
    1006           0 :                         vmi_entry->vn_uuid_, vmi_uuid);
    1007           0 :         if (entry.get() != NULL) {
    1008           0 :             version = entry->version();
    1009             :         } else {
    1010           0 :             version = 0;
    1011             :         }
    1012             : 
    1013           0 :         port_subscribe_table_->DeleteVmVnPort(vm_uuid,
    1014           0 :                     vmi_entry->vn_uuid_, vmi_uuid);
    1015           0 :         CONFIG_TRACE(DeleteVmVnPortEnqueue, "Delete", UuidToString(vm_uuid),
    1016             :                     UuidToString(vmi_entry->vn_uuid_), version);
    1017             : 
    1018           0 :         string file = vmvn_dir + "/" + UuidToString(vmi_uuid);
    1019           0 :         fs::path file_path(file);
    1020           0 :         if (fs::exists(file_path) && fs::is_regular_file(file_path)) {
    1021           0 :             if (remove(file.c_str())) {
    1022           0 :                 err_msg += " Error deleting file " + file;
    1023           0 :                 failed = true;
    1024             :             }
    1025             :         }
    1026           0 :         it++;
    1027           0 :     }
    1028             : 
    1029           0 :     if (failed)
    1030           0 :         return false;
    1031             : 
    1032             :     /* remove vm directory in vmvn_dir_ */
    1033           0 :     fs::path base_dir(vmvn_dir);
    1034           0 :     if (!fs::remove_all(base_dir)) {
    1035           0 :         string err_msg = "Deleting directory " + vmvn_dir + " failed";
    1036           0 :         CONFIG_TRACE(PortInfo, err_msg.c_str());
    1037           0 :     }
    1038             : 
    1039           0 :     return true;
    1040           0 : }
    1041             : 
    1042           0 : bool PortIpcHandler::DeleteVmVnPort(const string &json, const string &vm,
    1043             :                                     string &err_msg) {
    1044           0 :     boost::uuids::uuid vm_uuid = StringToUuid(vm);
    1045           0 :     if (vm_uuid == nil_uuid()) {
    1046           0 :         return true;
    1047             :     }
    1048             : 
    1049           0 :     DeleteVmVnPort(vm_uuid, err_msg);
    1050           0 :     return true;
    1051             : }
    1052             : 
    1053           0 : bool PortIpcHandler::GetVmVnCfgPort(const string &vm, string &info) const {
    1054           0 :     VmTable *vm_table = agent_->vm_table();
    1055           0 :     boost::uuids::uuid vm_uuid = vm_table->GetVmUuid(vm);
    1056           0 :     if (vm_uuid == nil_uuid()) {
    1057           0 :         return false;
    1058             :     }
    1059             : 
    1060           0 :     std::set<boost::uuids::uuid> vmi_uuid_set;
    1061           0 :     if (!port_subscribe_table_->VmVnToVmiSet(vm_uuid, vmi_uuid_set))
    1062           0 :         return false;
    1063             : 
    1064           0 :     std::set<boost::uuids::uuid>::iterator it = vmi_uuid_set.begin();
    1065           0 :     info = '[';
    1066             :     do {
    1067           0 :         boost::uuids::uuid vmi_uuid = *it;
    1068           0 :         if (!MakeJsonFromVmiConfig(vmi_uuid, info))
    1069           0 :             return false;
    1070           0 :         it++;
    1071           0 :         info += ',';
    1072           0 :     } while (it != vmi_uuid_set.end());
    1073           0 :     info.erase(info.size() - 1);
    1074           0 :     info += ']';
    1075             : 
    1076           0 :     return true;
    1077             : 
    1078           0 : }
    1079             : 
    1080           0 : bool PortIpcHandler::MakeJsonFromVmiConfig(const boost::uuids::uuid &vmi_uuid,
    1081             :                                            string &resp) const {
    1082             :     const PortSubscribeTable::VmiEntry *vmi_entry =
    1083           0 :         port_subscribe_table_->VmiToEntry(vmi_uuid);
    1084             : 
    1085           0 :     if (vmi_entry == NULL) {
    1086           0 :         resp = "Interface Entry not found for request. Retry";
    1087           0 :         return false;
    1088             :     }
    1089             : 
    1090           0 :     const VnEntry *vn = agent_->vn_table()->Find(vmi_entry->vn_uuid_);
    1091           0 :     if (vn == NULL) {
    1092           0 :         resp = "VirtualNetwork not found for request. Retry";
    1093           0 :         return false;
    1094             :     }
    1095             : 
    1096           0 :     contrail_rapidjson::Document doc;
    1097           0 :     doc.SetObject();
    1098           0 :     contrail_rapidjson::Document::AllocatorType &a = doc.GetAllocator();
    1099             : 
    1100           0 :     string str1 = UuidToString(vmi_uuid);
    1101           0 :     AddMember("id", str1.c_str(), &doc);
    1102             : 
    1103           0 :     string str2 = UuidToString(vmi_entry->vm_uuid_);
    1104           0 :     AddMember("vm-uuid", str2.c_str(), &doc);
    1105             : 
    1106           0 :     string str5 = UuidToString(vmi_entry->vn_uuid_);
    1107           0 :     AddMember("vn-id", str5.c_str(), &doc);
    1108           0 :     AddMember("vn-name", vn->GetName().c_str(), &doc);
    1109             : 
    1110           0 :     AddMember("mac-address", vmi_entry->mac_.c_str(), &doc);
    1111           0 :     doc.AddMember("sub-interface", (bool)vmi_entry->sub_interface_, a);
    1112           0 :     doc.AddMember("vlan-id", (int)vmi_entry->vlan_tag_, a);
    1113             : 
    1114           0 :     if (vmi_entry->vmi_cfg != NULL) {
    1115             :         const std::vector<autogen::KeyValuePair> annotations =
    1116           0 :             vmi_entry->vmi_cfg->annotations();
    1117           0 :         if (annotations.size()) {
    1118           0 :             string str6;
    1119           0 :             contrail_rapidjson::Value val(contrail_rapidjson::kStringType);
    1120           0 :             contrail_rapidjson::Value array(contrail_rapidjson::kArrayType);
    1121             :             std::vector<autogen::KeyValuePair>::const_iterator it =
    1122           0 :                 annotations.begin();
    1123           0 :             while (it != annotations.end()) {
    1124           0 :                 str6 = "{" + it->key + ":" + it->value + "}";
    1125           0 :                 val.SetString(str6.c_str(), a);
    1126           0 :                 array.PushBack(val, a);
    1127           0 :                 it++;
    1128             :             }
    1129           0 :             doc.AddMember("annotations", array, a);
    1130           0 :         }
    1131           0 :     }
    1132             : 
    1133           0 :     contrail_rapidjson::StringBuffer buffer;
    1134             :     contrail_rapidjson::PrettyWriter<contrail_rapidjson::StringBuffer>
    1135           0 :         writer(buffer);
    1136           0 :     doc.Accept(writer);
    1137           0 :     resp += buffer.GetString();
    1138           0 :     return true;
    1139           0 : }
    1140             : 
    1141           0 : bool PortIpcHandler::GetVmVnPort(const string &vm, const string &vmi,
    1142             :                                  string &info) const {
    1143           0 :     boost::uuids::uuid vm_uuid = StringToUuid(vm);
    1144           0 :     if (vm_uuid == nil_uuid()) {
    1145           0 :         return false;
    1146             :     }
    1147             : 
    1148           0 :     if (vmi.size() > 0) {
    1149           0 :         info = '[';
    1150           0 :         boost::uuids::uuid vmi_uuid = StringToUuid(vmi);
    1151           0 :         if (!MakeJsonFromVmi(vmi_uuid, info))
    1152           0 :             return false;
    1153           0 :         info += ']';
    1154           0 :         return true;
    1155             :     }
    1156             : 
    1157           0 :     std::set<boost::uuids::uuid> vmi_uuid_set;
    1158           0 :     if (!port_subscribe_table_->VmVnToVmiSet(vm_uuid, vmi_uuid_set))
    1159           0 :         return false;
    1160             : 
    1161           0 :     std::set<boost::uuids::uuid>::iterator it = vmi_uuid_set.begin();
    1162           0 :     info = '[';
    1163             :     do {
    1164           0 :         boost::uuids::uuid vmi_uuid = *it;
    1165           0 :         if (!MakeJsonFromVmi(vmi_uuid, info))
    1166           0 :             return false;
    1167           0 :         it++;
    1168           0 :         info += ',';
    1169           0 :     } while (it != vmi_uuid_set.end());
    1170           0 :     info.erase(info.size() - 1);
    1171           0 :     info += ']';
    1172             : 
    1173           0 :     return true;
    1174           0 : }
    1175             : 
    1176           0 : bool PortIpcHandler::MakeJsonFromVmi(
    1177             :     const boost::uuids::uuid &vmi_uuid, string &resp) const {
    1178           0 :     InterfaceConstRef intf_ref = agent_->interface_table()->FindVmi(vmi_uuid);
    1179           0 :     const VmInterface *vmi = static_cast<const VmInterface *>(intf_ref.get());
    1180           0 :     if (vmi == NULL) {
    1181           0 :         resp = "Interface not found for request. Retry";
    1182           0 :         return false;
    1183             :     }
    1184             : 
    1185           0 :     const VmEntry *vm = vmi->vm();
    1186           0 :     if (vm == NULL) {
    1187           0 :         resp = "VirtualMachine not found for request. Retry";
    1188           0 :         return false;
    1189             :     }
    1190             : 
    1191           0 :     const VnEntry *vn = vmi->vn();
    1192           0 :     if (vn == NULL) {
    1193           0 :         resp = "VirtualNetwork not found for request. Retry";
    1194           0 :         return false;
    1195             :     }
    1196             : 
    1197           0 :     const VnIpam *ipam_v4 = vn->GetIpam(vmi->primary_ip_addr());
    1198           0 :     const VnIpam *ipam_v6 = vn->GetIpam(vmi->primary_ip6_addr());
    1199           0 :     if ((ipam_v4 == NULL) && (ipam_v6 == NULL)) {
    1200           0 :         resp = "Missing IPAM entry for request. Retry";
    1201           0 :         return false;
    1202             :     }
    1203             : 
    1204           0 :     contrail_rapidjson::Document doc;
    1205           0 :     doc.SetObject();
    1206           0 :     contrail_rapidjson::Document::AllocatorType &a = doc.GetAllocator();
    1207             : 
    1208           0 :     string str1 = UuidToString(vmi->GetUuid());
    1209           0 :     AddMember("id", str1.c_str(), &doc);
    1210             : 
    1211           0 :     string str2 = UuidToString(vm->GetUuid());
    1212           0 :     AddMember("instance-id", str2.c_str(), &doc);
    1213             : 
    1214           0 :     string str3 = UuidToString(vn->GetUuid());
    1215           0 :     AddMember("vn-id", str3.c_str(), &doc);
    1216             : 
    1217           0 :     string str4 = UuidToString(vmi->vm_project_uuid());
    1218           0 :     AddMember("vm-project-id", str4.c_str(), &doc);
    1219             : 
    1220           0 :     string str5 = vmi->vm_mac().ToString();
    1221           0 :     AddMember("mac-address", str5.c_str(), &doc);
    1222           0 :     AddMember("system-name", vmi->name().c_str(), &doc);
    1223           0 :     doc.AddMember("rx-vlan-id", (int)vmi->rx_vlan_id(), a);
    1224           0 :     doc.AddMember("tx-vlan-id", (int)vmi->tx_vlan_id(), a);
    1225           0 :     doc.AddMember("vhostuser-mode", (int)vmi->vhostuser_mode(), a);
    1226             : 
    1227           0 :     if (ipam_v4) {
    1228           0 :         string str6 = vmi->primary_ip_addr().to_string();
    1229           0 :         AddMember("ip-address", str6.c_str(), &doc);
    1230           0 :         doc.AddMember("plen", ipam_v4->plen, a);
    1231           0 :         string str7 = ipam_v4->dns_server.to_v4().to_string();
    1232           0 :         AddMember("dns-server", str7.c_str(), &doc);
    1233           0 :         string str8 = ipam_v4->default_gw.to_v4().to_string();
    1234           0 :         AddMember("gateway", str8.c_str(), &doc);
    1235           0 :     }
    1236             : 
    1237           0 :     if (ipam_v6) {
    1238           0 :         string str6 = vmi->primary_ip6_addr().to_string();
    1239           0 :         AddMember("v6-ip-address", str6.c_str(), &doc);
    1240           0 :         string str7 = ipam_v6->dns_server.to_v6().to_string();
    1241           0 :         AddMember("v6-dns-server", str7.c_str(), &doc);
    1242           0 :         string str8 = ipam_v6->default_gw.to_v6().to_string();
    1243           0 :         AddMember("v6-gateway", str8.c_str(), &doc);
    1244           0 :     }
    1245             : 
    1246           0 :     AddMember("author", agent_->program_name().c_str(), &doc);
    1247           0 :     string now = duration_usecs_to_string(UTCTimestampUsec());
    1248           0 :     AddMember("time", now.c_str(), &doc);
    1249             : 
    1250           0 :     contrail_rapidjson::StringBuffer buffer;
    1251           0 :     contrail_rapidjson::PrettyWriter<contrail_rapidjson::StringBuffer> writer(buffer);
    1252           0 :     doc.Accept(writer);
    1253           0 :     resp += buffer.GetString();
    1254           0 :     return true;
    1255           0 : }

Generated by: LCOV version 1.14