Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include <boost/uuid/uuid_io.hpp> 6 : #include <vnc_cfg_types.h> 7 : #include <cmn/agent_cmn.h> 8 : 9 : #include <ifmap/ifmap_node.h> 10 : #include <oper/interface_common.h> 11 : #include <oper/vm.h> 12 : #include <oper/mirror_table.h> 13 : #include <oper/agent_sandesh.h> 14 : #include <oper/config_manager.h> 15 : 16 : using namespace std; 17 : using namespace autogen; 18 : using boost::uuids::nil_uuid; 19 : 20 : VmTable *VmTable::vm_table_; 21 : 22 2791 : VmEntry::VmEntry(const boost::uuids::uuid &id) : uuid_(id), name_(""), 23 2791 : drop_new_flows_(false) { 24 2791 : flow_count_ = 0; 25 2791 : linklocal_flow_count_ = 0; 26 2791 : } 27 : 28 5582 : VmEntry::~VmEntry() { 29 2791 : assert(flow_count_ == 0); 30 2791 : assert(linklocal_flow_count_ == 0); 31 5582 : } 32 : 33 11174 : bool VmEntry::IsLess(const DBEntry &rhs) const { 34 11174 : const VmEntry &a = static_cast<const VmEntry &>(rhs); 35 11174 : return (uuid_ < a.uuid_); 36 : } 37 : 38 0 : string VmEntry::ToString() const { 39 0 : return UuidToString(GetUuid()); 40 : } 41 : 42 0 : DBEntryBase::KeyPtr VmEntry::GetDBRequestKey() const { 43 0 : VmKey *key = new VmKey(uuid_); 44 0 : return DBEntryBase::KeyPtr(key); 45 : } 46 : 47 0 : void VmEntry::SetKey(const DBRequestKey *key) { 48 0 : const VmKey *k = static_cast<const VmKey *>(key); 49 0 : uuid_ = k->uuid_; 50 0 : } 51 : 52 0 : bool VmEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const { 53 0 : VmListResp *resp = static_cast<VmListResp *>(sresp); 54 : 55 0 : std::string str_uuid = UuidToString(GetUuid()); 56 0 : if (name.empty() || str_uuid == name) { 57 0 : VmSandeshData data; 58 0 : data.set_uuid(str_uuid); 59 : std::vector<VmSandeshData> &list = 60 0 : const_cast<std::vector<VmSandeshData>&>(resp->get_vm_list()); 61 0 : data.set_drop_new_flows(drop_new_flows_); 62 0 : list.push_back(data); 63 0 : return true; 64 0 : } 65 : 66 0 : return false; 67 0 : } 68 : 69 436 : void VmEntry::update_flow_count(int val) const { 70 436 : VmTable *vm_table = static_cast<VmTable *>(get_table()); 71 436 : int max_flows = vm_table->agent()->max_vm_flows(); 72 436 : int tmp = flow_count_.fetch_add(val); 73 : 74 436 : if (max_flows == FLOWS_LIMIT_UNLIMITED) { 75 : // max_flows are not configured, 76 : // disable drop new flows and return 77 0 : SetInterfacesDropNewFlows(false); 78 0 : return; 79 : } 80 : 81 436 : if (val < 0) { 82 218 : assert(tmp >= val); 83 218 : if ((tmp + val) < 84 218 : ((max_flows * (Agent::kDropNewFlowsRecoveryThreshold))/100)) { 85 218 : SetInterfacesDropNewFlows(false); 86 : } 87 : } else { 88 218 : if ((tmp + val) >= max_flows) { 89 0 : SetInterfacesDropNewFlows(true); 90 : } 91 : } 92 : } 93 : 94 218 : void VmEntry::SetInterfacesDropNewFlows(bool drop_new_flows) const { 95 218 : if (drop_new_flows_ == drop_new_flows) { 96 218 : return; 97 : } 98 0 : drop_new_flows_ = drop_new_flows; 99 0 : VmTable *vm_table = static_cast<VmTable *>(get_table()); 100 0 : DBRequest req; 101 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; 102 0 : std::scoped_lock lock(back_ref_mutex_); 103 0 : std::set<IntrusiveReferrer>::const_iterator it = back_ref_set_.begin(); 104 0 : for (; it != back_ref_set_.end(); it++) { 105 0 : VmInterface *vm_intf = static_cast<VmInterface *>((*it).first); 106 0 : if (vm_intf->max_flows()) 107 0 : continue; 108 0 : req.key.reset(new VmInterfaceKey(AgentKey::RESYNC, 109 0 : vm_intf->GetUuid(), "")); 110 0 : req.data.reset(new VmInterfaceNewFlowDropData(drop_new_flows)); 111 0 : vm_table->agent()->interface_table()->Enqueue(&req); 112 : } 113 0 : } 114 : 115 828 : void VmEntry::SendObjectLog(AgentLogEvent::type event) const { 116 828 : VmObjectLogInfo info; 117 828 : string str; 118 828 : string str_uuid = UuidToString(GetUuid()); 119 828 : vector<string> sg_list; 120 : 121 828 : switch (event) { 122 159 : case AgentLogEvent::ADD: 123 159 : str.assign("Addition "); 124 159 : break; 125 174 : case AgentLogEvent::DEL: 126 174 : str.assign("Deletion "); 127 174 : break; 128 495 : case AgentLogEvent::CHANGE: 129 495 : str.assign("Modification "); 130 495 : break; 131 0 : default: 132 0 : str.assign(""); 133 0 : break; 134 : } 135 828 : info.set_event(str); 136 828 : info.set_uuid(str_uuid); 137 828 : if (event != AgentLogEvent::DEL && sg_list.size()) { 138 0 : info.set_sg_uuid_list(sg_list); 139 : } 140 828 : info.set_ref_count(GetRefCount()); 141 828 : VM_OBJECT_LOG_LOG("AgentVm", SandeshLevel::SYS_INFO, info); 142 828 : } 143 : 144 0 : boost::uuids::uuid VmTable::GetVmUuid(const std::string &name) 145 : { 146 0 : VmNameUuidTree::iterator it = vm_name_uuid_tree_.find(name); 147 0 : if (it != vm_name_uuid_tree_.end()) { 148 0 : return it->second; 149 : } 150 0 : return nil_uuid(); 151 : } 152 : 153 2632 : std::unique_ptr<DBEntry> VmTable::AllocEntry(const DBRequestKey *k) const { 154 2632 : const VmKey *key = static_cast<const VmKey *>(k); 155 2632 : VmEntry *vm = new VmEntry(key->uuid_); 156 2632 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vm)); 157 : } 158 : 159 159 : DBEntry *VmTable::OperDBAdd(const DBRequest *req) { 160 159 : VmKey *key = static_cast<VmKey *>(req->key.get()); 161 159 : VmData *data = static_cast<VmData *>(req->data.get()); 162 159 : VmEntry *vm = new VmEntry(key->uuid_); 163 159 : vm->SetCfgName(data->name_); 164 159 : vm->SendObjectLog(AgentLogEvent::ADD); 165 159 : VmNameUuidTree::iterator it = vm_name_uuid_tree_.find(data->name_); 166 159 : if (it != vm_name_uuid_tree_.end()) { 167 0 : std::swap(vm_name_uuid_tree_[data->name_], key->uuid_); 168 : } else { 169 159 : vm_name_uuid_tree_.insert(std::make_pair(data->name_, key->uuid_)); 170 : } 171 159 : return vm; 172 : } 173 : 174 : // Do DIFF walk for Interface and SG List. 175 495 : bool VmTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) { 176 495 : VmEntry *vm = static_cast<VmEntry *>(entry); 177 495 : vm->SendObjectLog(AgentLogEvent::CHANGE); 178 495 : return false; 179 : } 180 : 181 174 : bool VmTable::OperDBDelete(DBEntry *entry, const DBRequest *req) { 182 174 : VmEntry *vm = static_cast<VmEntry *>(entry); 183 174 : vm->SendObjectLog(AgentLogEvent::DEL); 184 : VmNameUuidTree::const_iterator it = 185 174 : vm_name_uuid_tree_.find(vm->GetCfgName()); 186 174 : if (it != vm_name_uuid_tree_.end()) { 187 159 : vm_name_uuid_tree_.erase(it->first); 188 : } 189 : 190 174 : return true; 191 : } 192 : 193 3 : DBTableBase *VmTable::CreateTable(DB *db, const std::string &name) { 194 3 : vm_table_ = new VmTable(db, name); 195 3 : vm_table_->Init(); 196 3 : return vm_table_; 197 : }; 198 841 : bool VmTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { 199 841 : VirtualMachine *cfg = static_cast <VirtualMachine *> (node->GetObject()); 200 841 : assert(cfg); 201 841 : autogen::IdPermsType id_perms = cfg->id_perms(); 202 841 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); 203 841 : return true; 204 841 : } 205 : 206 841 : bool VmTable::IFNodeToReq(IFMapNode *node, DBRequest &req, 207 : const boost::uuids::uuid &id) { 208 : 209 841 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) { 210 174 : req.key.reset(new VmKey(id)); 211 174 : req.oper = DBRequest::DB_ENTRY_DELETE; 212 174 : return true; 213 : } 214 : 215 667 : agent()->config_manager()->AddVmNode(node); 216 667 : return false; 217 : } 218 : 219 654 : bool VmTable::ProcessConfig(IFMapNode *node, DBRequest &req, 220 : const boost::uuids::uuid &id) { 221 : 222 654 : if (node->IsDeleted()) { 223 0 : return false; 224 : } 225 : 226 654 : req.key.reset(new VmKey(id)); 227 654 : VmData::SGUuidList sg_list(0); 228 654 : req.data.reset(new VmData(agent(), node, node->name(), sg_list)); 229 654 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; 230 654 : return true; 231 654 : } 232 : 233 0 : void VmListReq::HandleRequest() const { 234 0 : AgentSandeshPtr sand(new AgentVmSandesh(context(), get_uuid())); 235 0 : sand->DoSandesh(sand); 236 0 : } 237 : 238 0 : AgentSandeshPtr VmTable::GetAgentSandesh(const AgentSandeshArguments *args, 239 : const std::string &context) { 240 : return AgentSandeshPtr(new AgentVmSandesh(context, 241 0 : args->GetString("name"))); 242 : }