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