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

Generated by: LCOV version 1.14