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 274 : VmEntry::VmEntry(const boost::uuids::uuid &id) : uuid_(id), name_(""), 23 274 : drop_new_flows_(false) { 24 274 : flow_count_ = 0; 25 274 : linklocal_flow_count_ = 0; 26 274 : } 27 : 28 548 : VmEntry::~VmEntry() { 29 274 : assert(flow_count_ == 0); 30 274 : assert(linklocal_flow_count_ == 0); 31 548 : } 32 : 33 650 : bool VmEntry::IsLess(const DBEntry &rhs) const { 34 650 : const VmEntry &a = static_cast<const VmEntry &>(rhs); 35 650 : 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 272 : void VmEntry::update_flow_count(int val) const { 70 272 : VmTable *vm_table = static_cast<VmTable *>(get_table()); 71 272 : int max_flows = vm_table->agent()->max_vm_flows(); 72 272 : int tmp = flow_count_.fetch_add(val); 73 : 74 272 : 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 272 : if (val < 0) { 82 136 : assert(tmp >= val); 83 136 : if ((tmp + val) < 84 136 : ((max_flows * (Agent::kDropNewFlowsRecoveryThreshold))/100)) { 85 136 : SetInterfacesDropNewFlows(false); 86 : } 87 : } else { 88 136 : if ((tmp + val) >= max_flows) { 89 0 : SetInterfacesDropNewFlows(true); 90 : } 91 : } 92 : } 93 : 94 136 : void VmEntry::SetInterfacesDropNewFlows(bool drop_new_flows) const { 95 136 : if (drop_new_flows_ == drop_new_flows) { 96 136 : 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 134 : void VmEntry::SendObjectLog(AgentLogEvent::type event) const { 116 134 : VmObjectLogInfo info; 117 134 : string str; 118 134 : string str_uuid = UuidToString(GetUuid()); 119 134 : vector<string> sg_list; 120 : 121 134 : switch (event) { 122 26 : case AgentLogEvent::ADD: 123 26 : str.assign("Addition "); 124 26 : break; 125 28 : case AgentLogEvent::DEL: 126 28 : str.assign("Deletion "); 127 28 : break; 128 80 : case AgentLogEvent::CHANGE: 129 80 : str.assign("Modification "); 130 80 : break; 131 0 : default: 132 0 : str.assign(""); 133 0 : break; 134 : } 135 134 : info.set_event(str); 136 134 : info.set_uuid(str_uuid); 137 134 : if (event != AgentLogEvent::DEL && sg_list.size()) { 138 0 : info.set_sg_uuid_list(sg_list); 139 : } 140 134 : info.set_ref_count(GetRefCount()); 141 134 : VM_OBJECT_LOG_LOG("AgentVm", SandeshLevel::SYS_INFO, info); 142 134 : } 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 248 : std::unique_ptr<DBEntry> VmTable::AllocEntry(const DBRequestKey *k) const { 154 248 : const VmKey *key = static_cast<const VmKey *>(k); 155 248 : VmEntry *vm = new VmEntry(key->uuid_); 156 248 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vm)); 157 : } 158 : 159 26 : DBEntry *VmTable::OperDBAdd(const DBRequest *req) { 160 26 : VmKey *key = static_cast<VmKey *>(req->key.get()); 161 26 : VmData *data = static_cast<VmData *>(req->data.get()); 162 26 : VmEntry *vm = new VmEntry(key->uuid_); 163 26 : vm->SetCfgName(data->name_); 164 26 : vm->SendObjectLog(AgentLogEvent::ADD); 165 26 : VmNameUuidTree::iterator it = vm_name_uuid_tree_.find(data->name_); 166 26 : if (it != vm_name_uuid_tree_.end()) { 167 0 : std::swap(vm_name_uuid_tree_[data->name_], key->uuid_); 168 : } else { 169 26 : vm_name_uuid_tree_.insert(std::make_pair(data->name_, key->uuid_)); 170 : } 171 26 : return vm; 172 : } 173 : 174 : // Do DIFF walk for Interface and SG List. 175 80 : bool VmTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) { 176 80 : VmEntry *vm = static_cast<VmEntry *>(entry); 177 80 : vm->SendObjectLog(AgentLogEvent::CHANGE); 178 80 : return false; 179 : } 180 : 181 28 : bool VmTable::OperDBDelete(DBEntry *entry, const DBRequest *req) { 182 28 : VmEntry *vm = static_cast<VmEntry *>(entry); 183 28 : vm->SendObjectLog(AgentLogEvent::DEL); 184 : VmNameUuidTree::const_iterator it = 185 28 : vm_name_uuid_tree_.find(vm->GetCfgName()); 186 28 : if (it != vm_name_uuid_tree_.end()) { 187 26 : vm_name_uuid_tree_.erase(it->first); 188 : } 189 : 190 28 : return true; 191 : } 192 : 193 2 : DBTableBase *VmTable::CreateTable(DB *db, const std::string &name) { 194 2 : vm_table_ = new VmTable(db, name); 195 2 : vm_table_->Init(); 196 2 : return vm_table_; 197 : }; 198 134 : bool VmTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { 199 134 : VirtualMachine *cfg = static_cast <VirtualMachine *> (node->GetObject()); 200 134 : assert(cfg); 201 134 : autogen::IdPermsType id_perms = cfg->id_perms(); 202 134 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); 203 134 : return true; 204 134 : } 205 : 206 134 : bool VmTable::IFNodeToReq(IFMapNode *node, DBRequest &req, 207 : const boost::uuids::uuid &id) { 208 : 209 134 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) { 210 28 : req.key.reset(new VmKey(id)); 211 28 : req.oper = DBRequest::DB_ENTRY_DELETE; 212 28 : return true; 213 : } 214 : 215 106 : agent()->config_manager()->AddVmNode(node); 216 106 : return false; 217 : } 218 : 219 106 : bool VmTable::ProcessConfig(IFMapNode *node, DBRequest &req, 220 : const boost::uuids::uuid &id) { 221 : 222 106 : if (node->IsDeleted()) { 223 0 : return false; 224 : } 225 : 226 106 : req.key.reset(new VmKey(id)); 227 106 : VmData::SGUuidList sg_list(0); 228 106 : req.data.reset(new VmData(agent(), node, node->name(), sg_list)); 229 106 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; 230 106 : return true; 231 106 : } 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 : }