diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd
index b3400cc78bf..556ddca2293 100644
--- a/src/schema/vnc_cfg.xsd
+++ b/src/schema/vnc_cfg.xsd
@@ -1098,6 +1098,10 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
+
+
diff --git a/src/vnsw/agent/cmn/agent.h b/src/vnsw/agent/cmn/agent.h
index 03d95a58ce1..a7ee7cb34eb 100644
--- a/src/vnsw/agent/cmn/agent.h
+++ b/src/vnsw/agent/cmn/agent.h
@@ -292,7 +292,7 @@ class Agent {
static const uint32_t kFlowKSyncTokens = 25;
static const uint32_t kFlowDelTokens = 16;
static const uint32_t kFlowUpdateTokens = 16;
-
+ static const uint8_t kInvalidQueueId = 255;
enum ForwardingMode {
NONE,
L2_L3,
diff --git a/src/vnsw/agent/init/agent_param.cc b/src/vnsw/agent/init/agent_param.cc
index af9cafc080c..4799f9216f7 100644
--- a/src/vnsw/agent/init/agent_param.cc
+++ b/src/vnsw/agent/init/agent_param.cc
@@ -677,6 +677,53 @@ void AgentParam::ParseServices() {
GetValueFromTree(services_queue_limit_, "SERVICES.queue_limit");
}
+void AgentParam::ParseQueue() {
+ GetValueFromTree(default_nic_queue_, "QUEUE.default_nic_queue");
+
+ if (!tree_.get_child_optional("QUEUE")) {
+ return;
+ }
+
+ BOOST_FOREACH(ptree::value_type &v, tree_.get_child("QUEUE")) {
+ std::string nic_queue = v.first;
+ std::string input = v.second.get_value();
+ std::vector tokens;
+ std::string sep = "[],";
+ boost::split(tokens, input, boost::is_any_of(sep),
+ boost::token_compress_on);
+
+ uint16_t queue;
+ if (sscanf(nic_queue.c_str(), "NIC-QUEUE-%hu", &queue) != 1) {
+ continue;
+ }
+
+ for (std::vector::const_iterator it = tokens.begin();
+ it != tokens.end(); it++) {
+
+ if (*it == Agent::NullString()) {
+ continue;
+ }
+
+ string range = *it;
+ std::vector range_value;
+ if (stringToIntegerList(range, "-", range_value)) {
+ if (range_value.size() == 1) {
+ qos_queue_map_[range_value[0]] = queue;
+ continue;
+ }
+
+ if (range_value[0] > range_value[1]) {
+ continue;
+ }
+
+ for (uint16_t i = range_value[0]; i <= range_value[1]; i++) {
+ qos_queue_map_[i] = queue;
+ }
+ }
+ }
+ }
+}
+
void AgentParam::ParseCollectorDSArguments
(const boost::program_options::variables_map &var_map) {
GetOptValue< vector >(var_map, collector_server_list_,
@@ -990,6 +1037,7 @@ void AgentParam::InitFromConfig() {
ParseNexthopServer();
ParsePlatform();
ParseServices();
+ ParseQueue();
cout << "Config file <" << config_file_ << "> parsing completed.\n";
return;
}
@@ -1427,7 +1475,8 @@ AgentParam::AgentParam(bool enable_flow_options,
tbb_thread_count_(Agent::kMaxTbbThreads),
tbb_exec_delay_(0),
tbb_schedule_delay_(0),
- tbb_keepawake_timeout_(Agent::kDefaultTbbKeepawakeTimeout) {
+ tbb_keepawake_timeout_(Agent::kDefaultTbbKeepawakeTimeout),
+ default_nic_queue_(Agent::kInvalidQueueId) {
// Set common command line arguments supported
boost::program_options::options_description generic("Generic options");
generic.add_options()
diff --git a/src/vnsw/agent/init/agent_param.h b/src/vnsw/agent/init/agent_param.h
index 56961e23648..b9522f5299f 100644
--- a/src/vnsw/agent/init/agent_param.h
+++ b/src/vnsw/agent/init/agent_param.h
@@ -289,6 +289,18 @@ class AgentParam {
void set_pkt0_tx_buffer_count(uint32_t val) { pkt0_tx_buffer_count_ = val; }
bool measure_queue_delay() const { return measure_queue_delay_; }
void set_measure_queue_delay(bool val) { measure_queue_delay_ = val; }
+ uint16_t get_nic_queue(uint16_t queue) {
+ std::map::iterator it = qos_queue_map_.find(queue);
+ if (it != qos_queue_map_.end()) {
+ return it->second;
+ }
+ return default_nic_queue_;
+ }
+
+ void add_nic_queue(uint16_t queue, uint16_t nic_queue) {
+ qos_queue_map_[queue] = nic_queue;
+ }
+
protected:
void set_hypervisor_mode(HypervisorMode m) { hypervisor_mode_ = m; }
virtual void InitFromSystem();
@@ -367,6 +379,7 @@ class AgentParam {
void ParseNexthopServer();
void ParsePlatform();
void ParseServices();
+ void ParseQueue();
void set_agent_mode(const std::string &mode);
void set_gateway_mode(const std::string &mode);
@@ -519,6 +532,8 @@ class AgentParam {
uint32_t tbb_exec_delay_;
uint32_t tbb_schedule_delay_;
uint32_t tbb_keepawake_timeout_;
+ std::map qos_queue_map_;
+ uint16_t default_nic_queue_;
DISALLOW_COPY_AND_ASSIGN(AgentParam);
};
diff --git a/src/vnsw/agent/init/test/cfg.ini b/src/vnsw/agent/init/test/cfg.ini
index 3f1a7062c1d..874e675fc8f 100644
--- a/src/vnsw/agent/init/test/cfg.ini
+++ b/src/vnsw/agent/init/test/cfg.ini
@@ -150,4 +150,8 @@ ip_blocks=1.1.1.1/24
# Routes to be exported in routing_instance. Each route is represented as
# ip/prefix. Multiple routes are represented by separating each with a space
# routes= 10.10.10.1/24 11.11.11.1/24
-
+[QUEUE]
+NIC-QUEUE-1=[1, 3, 5]
+NIC-QUEUE-2=[6-10]
+NIC-QUEUE-3=[110-109]
+default_nic_queue = 8
diff --git a/src/vnsw/agent/init/test/test_agent_init.cc b/src/vnsw/agent/init/test/test_agent_init.cc
index 4a9b97d59d3..36212e9a1f6 100644
--- a/src/vnsw/agent/init/test/test_agent_init.cc
+++ b/src/vnsw/agent/init/test/test_agent_init.cc
@@ -86,6 +86,10 @@ TEST_F(FlowTest, Agent_Conf_file_1) {
EXPECT_TRUE(param.flow_trace_enable());
EXPECT_EQ(param.pkt0_tx_buffer_count(), 2000);
EXPECT_EQ(param.pkt0_tx_buffer_count(), 2000);
+ EXPECT_EQ(param.get_nic_queue(1), 1);
+ EXPECT_EQ(param.get_nic_queue(3), 1);
+ EXPECT_EQ(param.get_nic_queue(8), 2);
+ EXPECT_EQ(param.get_nic_queue(105), 8);
}
TEST_F(FlowTest, Agent_Conf_file_2) {
diff --git a/src/vnsw/agent/oper/agent.sandesh b/src/vnsw/agent/oper/agent.sandesh
index 299c1eeacac..fd34676f2b4 100644
--- a/src/vnsw/agent/oper/agent.sandesh
+++ b/src/vnsw/agent/oper/agent.sandesh
@@ -2113,6 +2113,7 @@ response sandesh AgentQosConfigSandeshResp {
request sandesh AddQosQueue {
1: u32 uuid;
2: string name;
+ 3: u16 id;
}
request sandesh DeleteQosQueue {
diff --git a/src/vnsw/agent/oper/forwarding_class.cc b/src/vnsw/agent/oper/forwarding_class.cc
index 62b361fc7bd..45aae5cf574 100644
--- a/src/vnsw/agent/oper/forwarding_class.cc
+++ b/src/vnsw/agent/oper/forwarding_class.cc
@@ -96,6 +96,12 @@ bool ForwardingClass::Change(const DBRequest *req) {
ret = true;
}
+ if (qos_queue_ref_.get()) {
+ if (nic_queue_id_ != qos_queue_ref_->nic_queue_id()) {
+ nic_queue_id_ = qos_queue_ref_->nic_queue_id();
+ ret = true;
+ }
+ }
return ret;
}
diff --git a/src/vnsw/agent/oper/forwarding_class.h b/src/vnsw/agent/oper/forwarding_class.h
index 9f9468e8666..440f2508ffc 100644
--- a/src/vnsw/agent/oper/forwarding_class.h
+++ b/src/vnsw/agent/oper/forwarding_class.h
@@ -82,6 +82,10 @@ class ForwardingClass :
return name_;
}
+ uint16_t nic_queue_id() const {
+ return nic_queue_id_;
+ }
+
private:
boost::uuids::uuid uuid_;
uint32_t id_;
@@ -90,6 +94,7 @@ class ForwardingClass :
uint32_t mpls_exp_;
QosQueueConstRef qos_queue_ref_;
std::string name_;
+ uint16_t nic_queue_id_;
DISALLOW_COPY_AND_ASSIGN(ForwardingClass);
};
diff --git a/src/vnsw/agent/oper/ifmap_dependency_manager.cc b/src/vnsw/agent/oper/ifmap_dependency_manager.cc
index 1e2cc1083f3..4d0baa00837 100644
--- a/src/vnsw/agent/oper/ifmap_dependency_manager.cc
+++ b/src/vnsw/agent/oper/ifmap_dependency_manager.cc
@@ -716,13 +716,18 @@ void IFMapDependencyManager::InitializeDependencyRules(Agent *agent) {
RegisterConfigHandler(this, "service-health-check",
agent ? agent->health_check_table() : NULL);
- AddDependencyPath("qos-config",
- MakePath("global-qos-config",
+ AddDependencyPath("qos-config",
+ MakePath("global-qos-config-qos-config",
"qos-config", true));
RegisterConfigHandler(this, "qos-config",
agent ? agent->qos_config_table() : NULL);
+
RegisterConfigHandler(this, "qos-queue",
agent ? agent->qos_queue_table() : NULL);
+
+ AddDependencyPath("forwarding-class",
+ MakePath("forwarding-class-qos-queue",
+ "qos-queue", true));
RegisterConfigHandler(this, "forwarding-class",
agent ? agent->forwarding_class_table() : NULL);
}
diff --git a/src/vnsw/agent/oper/qos_queue.cc b/src/vnsw/agent/oper/qos_queue.cc
index 0bb68675828..8160d186829 100644
--- a/src/vnsw/agent/oper/qos_queue.cc
+++ b/src/vnsw/agent/oper/qos_queue.cc
@@ -9,15 +9,13 @@
#include
#include
#include
+#include
QosQueue::QosQueue(const boost::uuids::uuid &uuid):
uuid_(uuid), id_(QosQueueTable::kInvalidIndex) {
}
QosQueue::~QosQueue() {
- if (id_ != QosQueueTable::kInvalidIndex) {
- static_cast(get_table())->ReleaseIndex(this);
- }
}
DBEntryBase::KeyPtr QosQueue::GetDBRequestKey() const {
@@ -49,13 +47,30 @@ bool QosQueue::IsLess(const DBEntry &rhs) const {
return (uuid_ < qos_q.uuid_);
}
+void QosQueue::PostAdd() {
+ AgentDBTable *table = static_cast(get_table());
+ nic_queue_id_ = table->agent()->params()->get_nic_queue(id_);
+}
+
bool QosQueue::Change(const DBRequest *req) {
+ const AgentDBTable *table = static_cast(get_table());
const QosQueueData *data = static_cast(req->data.get());
+ bool ret = false;
if (name_ != data->name_) {
name_ = data->name_;
+ ret = true;
}
- return false;
+
+ if (id_ != data->id_) {
+ id_ = data->id_;
+ if (table) {
+ nic_queue_id_ = table->agent()->params()->get_nic_queue(id_);
+ }
+ ret = true;
+ }
+
+ return ret;
}
void QosQueue::Delete(const DBRequest *req) {
@@ -142,17 +157,16 @@ bool QosQueueTable::ProcessConfig(IFMapNode *node, DBRequest &req,
return false;
}
+ autogen::QosQueue *cfg = static_cast (node->GetObject());
req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
req.key.reset(new QosQueueKey(u));
- req.data.reset(new QosQueueData(agent(), node, node->name()));
+ req.data.reset(new QosQueueData(agent(), node, node->name(),
+ cfg->identifier()));
Enqueue(&req);
return false;
}
void QosQueueTable::ReleaseIndex(QosQueue *qos_q) {
- if (qos_q->id() != kInvalidIndex) {
- index_table_.Remove(qos_q->id());
- }
}
AgentSandeshPtr
@@ -181,7 +195,7 @@ void AddQosQueue::HandleRequest() const {
boost::uuids::uuid u1 = StringToUuid(std::string(str));
req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
req.key.reset(new QosQueueKey(u1));
- req.data.reset(new QosQueueData(NULL, NULL, get_name()));
+ req.data.reset(new QosQueueData(NULL, NULL, get_name(), get_id()));
table->Enqueue(&req);
resp->Response();
}
diff --git a/src/vnsw/agent/oper/qos_queue.h b/src/vnsw/agent/oper/qos_queue.h
index 66e8771411b..d6d7ecfcd43 100644
--- a/src/vnsw/agent/oper/qos_queue.h
+++ b/src/vnsw/agent/oper/qos_queue.h
@@ -28,9 +28,11 @@ struct QosQueueKey : public AgentOperDBKey {
struct QosQueueData : public AgentOperDBData {
- QosQueueData(const Agent *agent, IFMapNode *node, const std::string &name):
- AgentOperDBData(agent, node), name_(name) {}
+ QosQueueData(const Agent *agent, IFMapNode *node, const std::string &name,
+ uint16_t id):
+ AgentOperDBData(agent, node), name_(name), id_(id) {}
std::string name_;
+ uint16_t id_;
};
class QosQueue :
@@ -47,6 +49,7 @@ class QosQueue :
virtual bool Change(const DBRequest *req);
virtual void Delete(const DBRequest *req);
virtual void SetKey(const DBRequestKey *key);
+ virtual void PostAdd();
virtual bool DeleteOnZeroRefCount() const {
return false;
@@ -67,10 +70,16 @@ class QosQueue :
const std::string& name() const {
return name_;
}
+
+ uint16_t nic_queue_id() const {
+ return nic_queue_id_;
+ }
+
private:
boost::uuids::uuid uuid_;
- uint32_t id_;
+ uint16_t id_;
std::string name_;
+ uint16_t nic_queue_id_;
DISALLOW_COPY_AND_ASSIGN(QosQueue);
};
diff --git a/src/vnsw/agent/oper/test/test_forwarding_class.cc b/src/vnsw/agent/oper/test/test_forwarding_class.cc
index 982cbb6e7a3..463e8ad8732 100644
--- a/src/vnsw/agent/oper/test/test_forwarding_class.cc
+++ b/src/vnsw/agent/oper/test/test_forwarding_class.cc
@@ -111,6 +111,32 @@ TEST_F(FwdClassTest, Test3) {
EXPECT_TRUE(agent->forwarding_class_table()->Size() == 0);
}
+TEST_F(FwdClassTest, Test4) {
+ TestForwardingClassData data[] = {
+ {1, 1, 1, 1, 1},
+ };
+
+ Agent::GetInstance()->params()->add_nic_queue(10, 100);
+
+ AddGlobalConfig(data, 1);
+ client->WaitForIdle();
+ EXPECT_TRUE(agent->forwarding_class_table()->Size() == 1);
+ VerifyForwardingClass(agent, data, 1);
+
+ ForwardingClassKey key(MakeUuid(data[0].id_));
+ ForwardingClass *fc = static_cast(
+ agent->forwarding_class_table()->FindActiveEntry(&key));
+ EXPECT_TRUE(fc->nic_queue_id() == Agent::kInvalidQueueId);
+
+ AddQosQueue("qosqueue1", 1, 10);
+ client->WaitForIdle();
+
+ EXPECT_TRUE(fc->nic_queue_id() == 100);
+
+ DelGlobalConfig(data, 1);
+ client->WaitForIdle();
+ EXPECT_TRUE(agent->forwarding_class_table()->Size() == 0);
+}
int main(int argc, char **argv) {
GETUSERARGS();
diff --git a/src/vnsw/agent/test/test_cmn_util.h b/src/vnsw/agent/test/test_cmn_util.h
index 9bb08019e1e..d1925006746 100644
--- a/src/vnsw/agent/test/test_cmn_util.h
+++ b/src/vnsw/agent/test/test_cmn_util.h
@@ -588,4 +588,5 @@ void VerifyForwardingClass(Agent *agent, struct TestForwardingClassData *data,
uint32_t count);
void VerifyQosConfig(Agent *agent, struct TestQosConfigData *data);
void AddQosConfig(struct TestQosConfigData &data);
+void AddQosQueue(const char *name, uint32_t id, uint32_t qos_queue_id);
#endif // vnsw_agent_test_cmn_util_h
diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc
index 7c5af205d9e..60e0d5b886c 100644
--- a/src/vnsw/agent/test/test_util.cc
+++ b/src/vnsw/agent/test/test_util.cc
@@ -4299,6 +4299,20 @@ void VerifyQosConfig(Agent *agent, struct TestQosConfigData *data) {
data->default_forwarding_class_);
}
+void AddQosQueue(const char *name, uint32_t id, uint32_t qos_queue_id) {
+
+ std::stringstream str;
+ str << "" << qos_queue_id << "";
+
+ char buf[10000];
+ int len = 0;
+ memset(buf, 0, 10000);
+ AddXmlHdr(buf, len);
+ AddNodeString(buf, len, "qos-queue", name, id, str.str().c_str());
+ AddXmlTail(buf, len);
+ ApplyXmlString(buf);
+}
+
void AddGlobalConfig(struct TestForwardingClassData *data,
uint32_t count) {
std::stringstream str;
diff --git a/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.cc b/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.cc
index c388cccc547..2adfc0587cc 100644
--- a/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.cc
+++ b/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.cc
@@ -83,6 +83,16 @@ bool ForwardingClassKSyncEntry::Sync(DBEntry *e) {
ret = true;
}
+ uint16_t nic_queue = Agent::kInvalidQueueId;
+ if (fc->qos_queue_ref()) {
+ nic_queue = fc->qos_queue_ref()->nic_queue_id();
+ }
+
+ if (nic_queue_id_ != nic_queue) {
+ nic_queue_id_ = nic_queue;
+ ret = true;
+ }
+
return ret;
}
@@ -108,14 +118,7 @@ int ForwardingClassKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_le
encoder.set_fmr_mpls_qos(mpls_exp_list);
std::vector qos_queue_list;
- const QosQueueKSyncEntry *qos_queue =
- static_cast(qos_queue_ksync_.get());
- if (qos_queue) {
- qos_queue_list.push_back(qos_queue->id());
- } else {
- //Default for now
- qos_queue_list.push_back(0);
- }
+ qos_queue_list.push_back(nic_queue_id_);
encoder.set_fmr_queue_id(qos_queue_list);
int error = 0;
diff --git a/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.h b/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.h
index 4fd2359828b..1ddbcbf7d3a 100644
--- a/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.h
+++ b/src/vnsw/agent/vrouter/ksync/forwarding_class_ksync.h
@@ -50,6 +50,7 @@ class ForwardingClassKSyncEntry : public KSyncNetlinkDBEntry {
uint32_t vlan_priority_;
uint32_t mpls_exp_;
KSyncEntryPtr qos_queue_ksync_;
+ uint16_t nic_queue_id_;
DISALLOW_COPY_AND_ASSIGN(ForwardingClassKSyncEntry);
};