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