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 <cmn/agent.h>
7 : #include <vnc_cfg_types.h>
8 : #include <agent_types.h>
9 : #include <oper/agent_sandesh.h>
10 : #include <cfg/cfg_init.h>
11 : #include <oper_db.h>
12 : #include <oper/config_manager.h>
13 : #include <oper/interface_common.h>
14 : #include <forwarding_class.h>
15 : #include <qos_config.h>
16 : #include <resource_manager/resource_manager.h>
17 : #include <resource_manager/resource_table.h>
18 : #include <resource_manager/qos_index.h>
19 :
20 : using namespace autogen;
21 1976 : AgentQosConfig::AgentQosConfig(const boost::uuids::uuid uuid):
22 1976 : uuid_(uuid), id_(AgentQosConfigTable::kInvalidIndex) {
23 1976 : }
24 :
25 3952 : AgentQosConfig::~AgentQosConfig() {
26 1976 : if (id_ != AgentQosConfigTable::kInvalidIndex) {
27 0 : static_cast<AgentQosConfigTable *>(get_table())->ReleaseIndex(this);
28 : }
29 3952 : }
30 :
31 0 : DBEntryBase::KeyPtr AgentQosConfig::GetDBRequestKey() const {
32 0 : AgentQosConfigKey *key = new AgentQosConfigKey(uuid_);
33 0 : return DBEntryBase::KeyPtr(key);
34 : }
35 :
36 0 : std::string AgentQosConfig::ToString() const {
37 0 : std::ostringstream buffer;
38 0 : buffer << uuid_;
39 0 : return buffer.str();
40 0 : }
41 :
42 0 : bool AgentQosConfig::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
43 0 : AgentQosConfigSandeshResp *resp =
44 : static_cast<AgentQosConfigSandeshResp *>(sresp);
45 0 : AgentQosConfigSandeshData data;
46 :
47 0 : data.set_uuid(UuidToString(uuid_));
48 0 : data.set_name(name_);
49 0 : data.set_id(id_);
50 0 : if (type_ == VHOST) {
51 0 : data.set_type("vhost");
52 0 : } else if (type_ == FABRIC) {
53 0 : data.set_type("fabric");
54 : } else {
55 0 : data.set_type("default");
56 : }
57 :
58 0 : std::vector<QosForwardingClassSandeshPair> dscp_list;
59 : AgentQosConfig::QosIdForwardingClassMap::const_iterator it =
60 0 : dscp_map_.begin();
61 0 : for(; it != dscp_map_.end(); it++) {
62 0 : QosForwardingClassSandeshPair pair;
63 0 : pair.set_qos_value(it->first);
64 0 : pair.set_forwarding_class_id(it->second);
65 0 : dscp_list.push_back(pair);
66 0 : }
67 :
68 0 : std::vector<QosForwardingClassSandeshPair> vlan_priority_list;
69 0 : it = vlan_priority_map_.begin();
70 0 : for(; it != vlan_priority_map_.end(); it++) {
71 0 : QosForwardingClassSandeshPair pair;
72 0 : pair.set_qos_value(it->first);
73 0 : pair.set_forwarding_class_id(it->second);
74 0 : vlan_priority_list.push_back(pair);
75 0 : }
76 :
77 0 : std::vector<QosForwardingClassSandeshPair> mpls_exp_list;
78 0 : it = mpls_exp_map_.begin();
79 0 : for(; it != mpls_exp_map_.end(); it++) {
80 0 : QosForwardingClassSandeshPair pair;
81 0 : pair.set_qos_value(it->first);
82 0 : pair.set_forwarding_class_id(it->second);
83 0 : mpls_exp_list.push_back(pair);
84 0 : }
85 :
86 0 : data.set_dscp_list(dscp_list);
87 0 : data.set_vlan_priority_list(vlan_priority_list);
88 0 : data.set_mpls_exp_list(mpls_exp_list);
89 0 : data.set_default_forwarding_class(default_forwarding_class_);
90 :
91 : std::vector<AgentQosConfigSandeshData> &list =
92 0 : const_cast<std::vector<AgentQosConfigSandeshData>&>(resp->get_qc_list());
93 0 : list.push_back(data);
94 0 : return true;
95 0 : }
96 :
97 0 : bool AgentQosConfig::IsLess(const DBEntry &rhs) const {
98 0 : const AgentQosConfig &fc = static_cast<const AgentQosConfig &>(rhs);
99 0 : return (uuid_ < fc.uuid_);
100 : }
101 :
102 0 : bool AgentQosConfig::HandleQosForwardingMapChange(const Agent *agent,
103 : QosIdForwardingClassMap &map,
104 : const
105 : AgentQosIdForwardingClassMap
106 : &data_map) {
107 :
108 0 : QosIdForwardingClassMap new_map;
109 0 : AgentQosIdForwardingClassMap::const_iterator it = data_map.begin();
110 0 : for (; it != data_map.end(); it++) {
111 0 : new_map.insert(QosIdForwardingClassPair(it->first, it->second));
112 : }
113 :
114 0 : if (map != new_map) {
115 0 : map = new_map;
116 0 : return true;
117 : }
118 :
119 0 : return false;
120 0 : }
121 :
122 0 : bool AgentQosConfig::VerifyLinkToGlobalQosConfig(const Agent *agent,
123 : const AgentQosConfigData *data) {
124 0 : IFMapNode *node = data->ifmap_node();
125 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
126 :
127 0 : for (DBGraphVertex::adjacency_iterator iter =
128 0 : node->begin(table->GetGraph()); iter != node->end(table->GetGraph());
129 0 : ++iter) {
130 0 : const IFMapNode *adj_node = static_cast<const IFMapNode *>(iter.operator->());
131 0 : if (adj_node->table() == agent->cfg()->cfg_global_qos_table()) {
132 0 : return true;
133 : }
134 : }
135 0 : return false;
136 : }
137 :
138 0 : void AgentQosConfig::HandleVhostQosConfig(const Agent *agent,
139 : const AgentQosConfigData *data, bool deleted) {
140 0 : if (deleted == false) {
141 : //Verify that link to Global QoS config exists
142 0 : if (VerifyLinkToGlobalQosConfig(agent, data) == false) {
143 0 : deleted = true;
144 : }
145 : }
146 :
147 : AgentQosConfigTable *table =
148 0 : static_cast<AgentQosConfigTable *>(agent->qos_config_table());
149 :
150 0 : if (deleted) {
151 0 : table->EraseVhostQosConfig(uuid());
152 : } else {
153 0 : table->InsertVhostQosConfig(uuid());
154 : }
155 :
156 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
157 : VmInterfaceKey *key =
158 0 : new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, boost::uuids::nil_uuid(),
159 0 : agent->vhost_interface_name());
160 0 : key->sub_op_ = AgentKey::RESYNC;
161 0 : boost::uuids::uuid qos_config_uuid = table->GetActiveVhostQosConfig();
162 : InterfaceQosConfigData *qos_data =
163 0 : new InterfaceQosConfigData(agent, NULL, qos_config_uuid);
164 0 : req.key.reset(key);
165 0 : req.data.reset(qos_data);
166 0 : agent->interface_table()->Enqueue(&req);
167 0 : }
168 :
169 0 : void AgentQosConfig::HandleFabricQosConfig(const Agent *agent,
170 : const AgentQosConfigData *data, bool deleted) {
171 :
172 0 : if (deleted == false) {
173 : //Verify that link to Global QoS config exists
174 0 : if (VerifyLinkToGlobalQosConfig(agent, data) == false) {
175 0 : deleted = true;
176 : }
177 : }
178 :
179 : AgentQosConfigTable *table =
180 0 : static_cast<AgentQosConfigTable *>(agent->qos_config_table());
181 :
182 0 : if (deleted) {
183 0 : table->EraseFabricQosConfig(uuid());
184 : } else {
185 0 : table->InsertFabricQosConfig(uuid());
186 : }
187 :
188 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
189 : PhysicalInterfaceKey *key =
190 0 : new PhysicalInterfaceKey(agent->fabric_interface_name());
191 0 : key->sub_op_ = AgentKey::RESYNC;
192 :
193 0 : boost::uuids::uuid qos_config_uuid = table->GetActiveFabricQosConfig();
194 : InterfaceQosConfigData *qos_data =
195 0 : new InterfaceQosConfigData(agent, NULL, qos_config_uuid);
196 0 : req.key.reset(key);
197 0 : req.data.reset(qos_data);
198 0 : agent->interface_table()->Enqueue(&req);
199 0 : }
200 :
201 0 : void AgentQosConfig::HandleGlobalQosConfig(const AgentQosConfigData *data) {
202 0 : if (data->ifmap_node() == NULL) {
203 0 : return;
204 : }
205 0 : if (type_ == VHOST) {
206 0 : HandleVhostQosConfig(data->agent(), data, false);
207 : } else {
208 0 : HandleFabricQosConfig(data->agent(), data, false);
209 : }
210 : }
211 :
212 0 : bool AgentQosConfig::Change(const DBRequest *req) {
213 0 : bool ret = false;
214 : const AgentQosConfigData *data =
215 0 : static_cast<const AgentQosConfigData *>(req->data.get());
216 :
217 : //Ignore change notification if entry node is marked for deletion
218 0 : if ((data->ifmap_node() == NULL) || (data->ifmap_node()->IsDeleted())) {
219 0 : return ret;
220 : }
221 :
222 0 : if (name_ != data->name_) {
223 0 : name_ = data->name_;
224 0 : ret = true;
225 : }
226 :
227 0 : if (HandleQosForwardingMapChange(data->agent(), dscp_map_, data->dscp_map_)) {
228 0 : ret = true;
229 : }
230 :
231 0 : if (HandleQosForwardingMapChange(data->agent(), vlan_priority_map_,
232 0 : data->vlan_priority_map_)) {
233 0 : ret = true;
234 : }
235 :
236 0 : if (HandleQosForwardingMapChange(data->agent(), mpls_exp_map_,
237 0 : data->mpls_exp_map_)) {
238 0 : ret = true;
239 : }
240 :
241 0 : if (type_ != data->type_) {
242 0 : type_ = data->type_;
243 0 : ret = true;
244 : }
245 :
246 0 : if (type_ != DEFAULT) {
247 0 : HandleGlobalQosConfig(data);
248 : }
249 :
250 0 : if (default_forwarding_class_ != data->default_forwarding_class_) {
251 0 : default_forwarding_class_ = data->default_forwarding_class_;
252 0 : ret = true;
253 : }
254 :
255 0 : return ret;
256 : }
257 :
258 0 : void AgentQosConfig::Delete(const DBRequest *req) {
259 0 : Agent *agent = (static_cast<AgentOperDBTable *>(get_table())->agent());
260 0 : if (type_ == VHOST) {
261 0 : HandleVhostQosConfig(agent, NULL, true);
262 0 : } else if (type_ == FABRIC) {
263 0 : HandleFabricQosConfig(agent, NULL, true);
264 : }
265 0 : }
266 :
267 0 : void AgentQosConfig::SetKey(const DBRequestKey *key) {
268 0 : const AgentQosConfigKey *fc_key =
269 : static_cast<const AgentQosConfigKey *>(key);
270 0 : uuid_ = fc_key->uuid_;
271 0 : }
272 :
273 2 : AgentQosConfigTable::AgentQosConfigTable(Agent *agent,
274 2 : DB *db, const std::string &name):
275 2 : AgentOperDBTable(db, name) {
276 2 : set_agent(agent);
277 2 : }
278 :
279 4 : AgentQosConfigTable::~AgentQosConfigTable() {
280 4 : }
281 :
282 : DBTableBase*
283 2 : AgentQosConfigTable::CreateTable(Agent *agent, DB *db, const std::string &name) {
284 2 : AgentQosConfigTable *qos_table = new AgentQosConfigTable(agent, db, name);
285 2 : (static_cast<DBTable *>(qos_table))->Init();
286 2 : return qos_table;
287 : }
288 :
289 : std::unique_ptr<DBEntry>
290 1976 : AgentQosConfigTable::AllocEntry(const DBRequestKey *k) const {
291 1976 : const AgentQosConfigKey *key =
292 : static_cast<const AgentQosConfigKey *>(k);
293 1976 : AgentQosConfig *fc = new AgentQosConfig(key->uuid_);
294 1976 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(fc));
295 : }
296 :
297 0 : DBEntry* AgentQosConfigTable::OperDBAdd(const DBRequest *req) {
298 : const AgentQosConfigKey *key =
299 0 : static_cast<const AgentQosConfigKey *>(req->key.get());
300 0 : AgentQosConfig *qc = new AgentQosConfig(key->uuid_);
301 : ResourceManager::KeyPtr rkey(new QosIndexResourceKey(
302 0 : agent()->resource_manager(), key->uuid_));
303 : int id = static_cast<IndexResourceData *>(agent()->resource_manager()->
304 0 : Allocate(rkey).get())->index();
305 0 : index_table_.InsertAtIndex(id, qc);
306 0 : qc->set_id(id);
307 0 : qc->Change(req);
308 0 : name_map_.insert(AgentQosConfigNamePair(qc->name(), qc));
309 0 : return static_cast<DBEntry *>(qc);
310 0 : }
311 :
312 0 : bool AgentQosConfigTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
313 0 : AgentQosConfig *qc = static_cast<AgentQosConfig *>(entry);
314 0 : return qc->Change(req);
315 : }
316 :
317 0 : bool AgentQosConfigTable::OperDBResync(DBEntry *entry, const DBRequest *req) {
318 0 : return OperDBOnChange(entry, req);
319 : }
320 :
321 0 : bool AgentQosConfigTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
322 0 : AgentQosConfig *qc = static_cast<AgentQosConfig *>(entry);
323 0 : qc->Delete(req);
324 0 : name_map_.erase(qc->name());
325 0 : return true;
326 : }
327 :
328 0 : void AgentQosConfigTable::ReleaseIndex(AgentQosConfig *qc) {
329 0 : if (qc->id() != kInvalidIndex) {
330 0 : agent()->resource_manager()->Release(Resource::QOS_INDEX, qc->id());
331 0 : index_table_.Remove(qc->id());
332 : }
333 0 : }
334 :
335 0 : bool AgentQosConfigTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
336 : const boost::uuids::uuid &u) {
337 0 : assert(!u.is_nil());
338 :
339 0 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
340 0 : req.key.reset(new AgentQosConfigKey(u));
341 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
342 0 : Enqueue(&req);
343 0 : return false;
344 : }
345 :
346 0 : agent()->config_manager()->AddQosConfigNode(node);
347 0 : return false;
348 : }
349 :
350 0 : bool AgentQosConfigTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) {
351 0 : autogen::QosConfig *cfg = static_cast <autogen::QosConfig *> (node->GetObject());
352 0 : assert(cfg);
353 0 : autogen::IdPermsType id_perms = cfg->id_perms();
354 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
355 0 : return true;
356 0 : }
357 :
358 0 : bool AgentQosConfigTable::ProcessConfig(IFMapNode *node, DBRequest &req,
359 : const boost::uuids::uuid &u) {
360 0 : if (node->IsDeleted()) {
361 0 : return false;
362 : }
363 :
364 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
365 0 : req.key.reset(new AgentQosConfigKey(u));
366 0 : req.data.reset(BuildData(node));
367 0 : Enqueue(&req);
368 0 : return false;
369 : }
370 :
371 : AgentQosConfigData*
372 0 : AgentQosConfigTable::BuildData(IFMapNode *node) {
373 0 : AgentQosConfigData *qcd = new AgentQosConfigData(agent(), node);
374 0 : autogen::QosConfig *cfg = static_cast <autogen::QosConfig *> (node->GetObject());
375 :
376 : std::vector<QosIdForwardingClassPair>::const_iterator it =
377 0 : cfg->dscp_entries().begin();
378 0 : for(; it != cfg->dscp_entries().end(); it++) {
379 0 : qcd->dscp_map_[it->key] = it->forwarding_class_id;
380 : }
381 :
382 0 : for(it = cfg->vlan_priority_entries().begin();
383 0 : it != cfg->vlan_priority_entries().end(); it++) {
384 0 : qcd->vlan_priority_map_[it->key] = it->forwarding_class_id;
385 : }
386 :
387 0 : for(it = cfg->mpls_exp_entries().begin();
388 0 : it != cfg->mpls_exp_entries().end(); it++) {
389 0 : qcd->mpls_exp_map_[it->key] = it->forwarding_class_id;
390 : }
391 :
392 0 : qcd->name_ = node->name();
393 0 : if (cfg->type() == "vhost") {
394 0 : qcd->type_ = AgentQosConfig::VHOST;
395 0 : } else if (cfg->type() == "fabric") {
396 0 : qcd->type_ = AgentQosConfig::FABRIC;
397 : } else {
398 0 : qcd->type_ = AgentQosConfig::DEFAULT;
399 : }
400 :
401 0 : qcd->default_forwarding_class_ = cfg->default_forwarding_class_id();
402 :
403 0 : return qcd;
404 : }
405 :
406 : AgentSandeshPtr
407 0 : AgentQosConfigTable::GetAgentSandesh(const AgentSandeshArguments *args,
408 : const std::string &context) {
409 : return AgentSandeshPtr(new AgentQosConfigSandesh(context,
410 0 : args->GetString("uuid"), args->GetString("name"),
411 0 : args->GetString("id")));
412 : }
413 :
414 0 : void AgentQosConfigSandeshReq::HandleRequest() const {
415 0 : AgentSandeshPtr sand(new AgentQosConfigSandesh(context(), get_uuid(),
416 0 : get_name(), get_id()));
417 0 : sand->DoSandesh(sand);
418 0 : }
419 :
420 0 : void AddQosConfig::HandleRequest() const {
421 0 : QosResponse *resp = new QosResponse();
422 0 : resp->set_context(context());
423 :
424 : char str[50];
425 0 : sprintf(str, "00000000-0000-0000-0000-00%010x", get_uuid());
426 0 : boost::uuids::uuid u1 = StringToUuid(std::string(str));
427 :
428 0 : AgentQosConfigData *data = new AgentQosConfigData(Agent::GetInstance(), NULL);
429 :
430 0 : data->dscp_map_.insert(AgentQosIdForwardingClassPair(get_dscp(),
431 0 : get_dscp_forwarding_class_id()));
432 0 : data->vlan_priority_map_.insert(AgentQosIdForwardingClassPair(get_vlan_priority(),
433 0 : get_vlan_priority_forwarding_class_id()));
434 0 : data->mpls_exp_map_.insert(AgentQosIdForwardingClassPair(get_mpls_exp(),
435 0 : get_mpls_exp_forwarding_class_id()));
436 0 : data->name_ = get_name();
437 :
438 0 : if (get_type() == "vhost") {
439 0 : data->type_ = AgentQosConfig::VHOST;
440 0 : } else if (get_type() == "fabric") {
441 0 : data->type_ = AgentQosConfig::FABRIC;
442 : } else {
443 0 : data->type_ = AgentQosConfig::DEFAULT;
444 : }
445 :
446 :
447 0 : DBTable *table = Agent::GetInstance()->qos_config_table();
448 0 : DBRequest req;
449 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
450 0 : req.key.reset(new AgentQosConfigKey(u1));
451 0 : req.data.reset(data);
452 0 : table->Enqueue(&req);
453 0 : resp->set_resp("Success");
454 0 : resp->Response();
455 0 : }
456 :
457 0 : void DeleteQosConfig::HandleRequest() const {
458 0 : QosResponse *resp = new QosResponse();
459 0 : resp->set_context(context());
460 :
461 : char str[50];
462 0 : sprintf(str, "00000000-0000-0000-0000-00%010x", get_uuid());
463 0 : boost::uuids::uuid u1 = StringToUuid(std::string(str));
464 :
465 0 : DBTable *table = Agent::GetInstance()->qos_config_table();
466 0 : DBRequest req;
467 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
468 0 : req.key.reset(new AgentQosConfigKey(u1));
469 0 : req.data.reset(NULL);
470 0 : table->Enqueue(&req);
471 0 : resp->set_resp("Success");
472 0 : resp->Response();
473 0 : }
|