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