Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Define new class for FlowEvent queues
1. Define new class for FlowEvent queues. The new class makes it easier to add common functionality needed for all flow-event queues 2. Added functionality to log message if time taken for single run of a queue exceeds a threshold 3. Fix crash in UpdateStats. When FlowEvent is enqueued to work-queue, it can be processed and released before we hit UpdateStats. Ensure that UpdateStats is invoked before enqueuing FlowStats Change-Id: I7fa217b1b200cb01202e7731d792318ea88f3f91 Closes-Bug: #1578660 Partial-Bug: #1568126 Partial-Bug: #1572270 Partial-Bug: #1572471
- Loading branch information
Showing
9 changed files
with
351 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* Copyright (c) 2016 Juniper Networks, Inc. All rights reserved. | ||
*/ | ||
#include <net/address_util.h> | ||
#include <boost/functional/hash.hpp> | ||
#include <init/agent_param.h> | ||
#include <cmn/agent_stats.h> | ||
#include <oper/agent_profile.h> | ||
#include <vrouter/ksync/flowtable_ksync.h> | ||
#include <vrouter/ksync/ksync_init.h> | ||
#include <vrouter/ksync/ksync_flow_index_manager.h> | ||
#include "vrouter/flow_stats/flow_stats_collector.h" | ||
#include "flow_proto.h" | ||
#include "flow_mgmt_dbclient.h" | ||
#include "flow_mgmt.h" | ||
#include "flow_event.h" | ||
|
||
////////////////////////////////////////////////////////////////////////////// | ||
// FlowEventQueue routines | ||
////////////////////////////////////////////////////////////////////////////// | ||
FlowEventQueueBase::FlowEventQueueBase(FlowProto *proto, | ||
const std::string &name, | ||
uint32_t task_id, int task_instance, | ||
FlowTokenPool *pool, | ||
uint16_t latency_limit) : | ||
flow_proto_(proto), token_pool_(pool), task_start_(0), count_(0), | ||
latency_limit_(latency_limit) { | ||
queue_ = new Queue(task_id, task_instance, | ||
boost::bind(&FlowEventQueueBase::Handler, this, _1)); | ||
char buff[100]; | ||
sprintf(buff, "%s-%d", name.c_str(), task_instance); | ||
queue_->set_name(buff); | ||
queue_->SetStartRunnerFunc(boost::bind(&FlowEventQueueBase::TokenCheck, | ||
this)); | ||
if (latency_limit_) { | ||
queue_->SetEntryCallback(boost::bind(&FlowEventQueueBase::TaskEntry, | ||
this)); | ||
queue_->SetExitCallback(boost::bind(&FlowEventQueueBase::TaskExit, | ||
this, _1)); | ||
} | ||
} | ||
|
||
FlowEventQueueBase::~FlowEventQueueBase() { | ||
delete queue_; | ||
} | ||
|
||
void FlowEventQueueBase::Shutdown() { | ||
queue_->Shutdown(); | ||
} | ||
|
||
void FlowEventQueueBase::Enqueue(FlowEvent *event) { | ||
queue_->Enqueue(event); | ||
} | ||
|
||
bool FlowEventQueueBase::TokenCheck() { | ||
return flow_proto_->TokenCheck(token_pool_); | ||
} | ||
|
||
bool FlowEventQueueBase::TaskEntry() { | ||
count_ = 0; | ||
task_start_ = ClockMonotonicUsec(); | ||
getrusage(RUSAGE_THREAD, &rusage_); | ||
return true; | ||
} | ||
|
||
void FlowEventQueueBase::TaskExit(bool done) { | ||
if (task_start_ == 0) | ||
return; | ||
|
||
uint64_t t = ClockMonotonicUsec(); | ||
if (((t - task_start_) / 1000) >= latency_limit_) { | ||
struct rusage r; | ||
getrusage(RUSAGE_THREAD, &r); | ||
|
||
uint32_t user = (r.ru_utime.tv_sec - rusage_.ru_utime.tv_sec) * 100; | ||
user += (r.ru_utime.tv_usec - rusage_.ru_utime.tv_usec); | ||
|
||
uint32_t sys = (r.ru_stime.tv_sec - rusage_.ru_stime.tv_sec) * 100; | ||
sys += (r.ru_stime.tv_usec - rusage_.ru_stime.tv_usec); | ||
|
||
LOG(ERROR, queue_->Description() | ||
<< " Time exceeded " << ((t - task_start_) / 1000) | ||
<< " Count " << count_ | ||
<< " User " << user << " Sys " << sys); | ||
} | ||
return; | ||
} | ||
|
||
bool FlowEventQueueBase::Handler(FlowEvent *event) { | ||
count_++; | ||
return HandleEvent(event); | ||
} | ||
|
||
FlowEventQueue::FlowEventQueue(Agent *agent, FlowProto *proto, | ||
FlowTable *table, FlowTokenPool *pool, | ||
uint16_t latency_limit) : | ||
FlowEventQueueBase(proto, "Flow Event Queue", | ||
agent->task_scheduler()->GetTaskId(kTaskFlowEvent), | ||
table->table_index(), pool, latency_limit), | ||
flow_table_(table) { | ||
} | ||
|
||
FlowEventQueue::~FlowEventQueue() { | ||
} | ||
|
||
bool FlowEventQueue::HandleEvent(FlowEvent *event) { | ||
return flow_proto_->FlowEventHandler(event, flow_table_); | ||
} | ||
|
||
DeleteFlowEventQueue::DeleteFlowEventQueue(Agent *agent, FlowProto *proto, | ||
FlowTable *table, | ||
FlowTokenPool *pool, | ||
uint16_t latency_limit) : | ||
FlowEventQueueBase(proto, "Flow Delete Queue", | ||
agent->task_scheduler()->GetTaskId(kTaskFlowEvent), | ||
table->table_index(), pool, latency_limit), | ||
flow_table_(table) { | ||
} | ||
|
||
DeleteFlowEventQueue::~DeleteFlowEventQueue() { | ||
} | ||
|
||
bool DeleteFlowEventQueue::HandleEvent(FlowEvent *event) { | ||
return flow_proto_->FlowDeleteHandler(event, flow_table_); | ||
} | ||
|
||
KSyncFlowEventQueue::KSyncFlowEventQueue(Agent *agent, FlowProto *proto, | ||
FlowTable *table, | ||
FlowTokenPool *pool, | ||
uint16_t latency_limit) : | ||
FlowEventQueueBase(proto, "Flow KSync Queue", | ||
agent->task_scheduler()->GetTaskId(kTaskFlowEvent), | ||
table->table_index(), pool, latency_limit), | ||
flow_table_(table) { | ||
} | ||
|
||
KSyncFlowEventQueue::~KSyncFlowEventQueue() { | ||
} | ||
|
||
bool KSyncFlowEventQueue::HandleEvent(FlowEvent *event) { | ||
return flow_proto_->FlowKSyncMsgHandler(event, flow_table_); | ||
} | ||
|
||
UpdateFlowEventQueue::UpdateFlowEventQueue(Agent *agent, FlowProto *proto, | ||
FlowTokenPool *pool, | ||
uint16_t latency_limit) : | ||
FlowEventQueueBase(proto, "Flow Update Queue", | ||
agent->task_scheduler()->GetTaskId(kTaskFlowUpdate), 0, | ||
pool, latency_limit) { | ||
} | ||
|
||
UpdateFlowEventQueue::~UpdateFlowEventQueue() { | ||
} | ||
|
||
bool UpdateFlowEventQueue::HandleEvent(FlowEvent *event) { | ||
return flow_proto_->FlowUpdateHandler(event); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.