Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <uve/vn_uve_table_base.h>
6 : #include <uve/agent_uve_base.h>
7 :
8 6 : VnUveTableBase::VnUveTableBase(Agent *agent, uint32_t default_intvl)
9 6 : : uve_vn_map_(), agent_(agent), uve_vn_map_mutex_(),
10 6 : vn_listener_id_(DBTableBase::kInvalidId),
11 6 : intf_listener_id_(DBTableBase::kInvalidId),
12 6 : timer_last_visited_(""),
13 6 : timer_(TimerManager::CreateTimer
14 6 : (*(agent->event_manager())->io_service(),
15 : "VnUveTimer",
16 6 : TaskScheduler::GetInstance()->GetTaskId(kTaskDBExclude), 0)) {
17 6 : expiry_time_ = default_intvl;
18 6 : timer_->Start(expiry_time_,
19 : boost::bind(&VnUveTableBase::TimerExpiry, this));
20 6 : }
21 :
22 6 : VnUveTableBase::~VnUveTableBase() {
23 6 : }
24 :
25 3 : void VnUveTableBase::RegisterDBClients() {
26 3 : VnTable *vn_table = agent_->vn_table();
27 3 : vn_listener_id_ = vn_table->Register
28 3 : (boost::bind(&VnUveTableBase::VnNotify, this, _1, _2));
29 :
30 3 : InterfaceTable *intf_table = agent_->interface_table();
31 3 : intf_listener_id_ = intf_table->Register
32 3 : (boost::bind(&VnUveTableBase::InterfaceNotify, this, _1, _2));
33 3 : Add(FlowHandler::UnknownVn());
34 3 : Add(FlowHandler::LinkLocalVn());
35 3 : }
36 :
37 6 : void VnUveTableBase::Shutdown(void) {
38 6 : if (vn_listener_id_ != DBTableBase::kInvalidId)
39 3 : agent_->vn_table()->Unregister(vn_listener_id_);
40 6 : if (intf_listener_id_ != DBTableBase::kInvalidId)
41 3 : agent_->interface_table()->Unregister(intf_listener_id_);
42 6 : if (timer_) {
43 6 : timer_->Cancel();
44 6 : TimerManager::DeleteTimer(timer_);
45 6 : timer_ = NULL;
46 : }
47 6 : }
48 :
49 0 : bool VnUveTableBase::TimerExpiry() {
50 0 : UveVnMap::iterator it = uve_vn_map_.lower_bound(timer_last_visited_);
51 0 : if (it == uve_vn_map_.end()) {
52 0 : timer_last_visited_ = "";
53 0 : return true;
54 : }
55 :
56 0 : uint32_t count = 0;
57 0 : while (it != uve_vn_map_.end() && count < AgentUveBase::kUveCountPerTimer) {
58 0 : VnUveEntryBase *entry = it->second.get();
59 0 : UveVnMap::iterator prev = it;
60 0 : it++;
61 0 : count++;
62 :
63 0 : if (entry->deleted()) {
64 0 : SendDeleteVnMsg(prev->first);
65 0 : if (!entry->renewed()) {
66 0 : Delete(prev->first);
67 : } else {
68 0 : entry->set_deleted(false);
69 0 : entry->set_renewed(false);
70 0 : entry->set_changed(false);
71 0 : SendVnMsg(entry, entry->vn());
72 : // Send VN ACE stats
73 0 : SendVnAceStats(entry, entry->vn());
74 : }
75 : } else {
76 0 : if (entry->changed()) {
77 0 : SendVnMsg(entry, entry->vn());
78 0 : entry->set_changed(false);
79 : /* Clear renew flag to be on safer side. Not really required */
80 0 : entry->set_renewed(false);
81 : }
82 :
83 : // Send VN ACE stats
84 0 : SendVnAceStats(entry, entry->vn());
85 : }
86 : }
87 :
88 0 : if (it == uve_vn_map_.end()) {
89 0 : timer_last_visited_ = "";
90 0 : set_expiry_time(agent_->uve()->default_interval());
91 : } else {
92 0 : timer_last_visited_ = it->first;
93 0 : set_expiry_time(agent_->uve()->incremental_interval());
94 : }
95 0 : return true;
96 : }
97 :
98 0 : void VnUveTableBase::set_expiry_time(int time) {
99 0 : if (time != expiry_time_) {
100 0 : expiry_time_ = time;
101 0 : timer_->Reschedule(expiry_time_);
102 : }
103 0 : }
104 :
105 0 : void VnUveTableBase::SendVnMsg(VnUveEntryBase *entry, const VnEntry *vn) {
106 0 : UveVirtualNetworkAgent uve;
107 0 : if (vn == NULL) {
108 0 : return;
109 : }
110 0 : if (entry->FrameVnMsg(vn, uve)) {
111 0 : DispatchVnMsg(uve);
112 : }
113 0 : }
114 :
115 0 : void VnUveTableBase::DispatchVnMsg(const UveVirtualNetworkAgent &uve) {
116 0 : UveVirtualNetworkAgentTrace::Send(uve);
117 0 : }
118 :
119 19 : VnUveEntryBase* VnUveTableBase::UveEntryFromVn(const VnEntry *vn) {
120 19 : if (vn->GetName() == agent_->NullString()) {
121 0 : return NULL;
122 : }
123 :
124 19 : UveVnMap::iterator it = uve_vn_map_.find(vn->GetName());
125 19 : if (it == uve_vn_map_.end()) {
126 0 : return NULL;
127 : }
128 19 : return it->second.get();
129 : }
130 :
131 13 : void VnUveTableBase::MarkChanged(const VnEntry *vn) {
132 13 : VnUveEntryBase* entry = UveEntryFromVn(vn);
133 13 : if (entry == NULL) {
134 0 : return;
135 : }
136 :
137 13 : entry->set_changed(true);
138 13 : return;
139 : }
140 :
141 0 : void VnUveTableBase::SendDeleteVnMsg(const string &vn) {
142 0 : UveVirtualNetworkAgent s_vn;
143 0 : s_vn.set_name(vn);
144 0 : s_vn.set_deleted(true);
145 0 : DispatchVnMsg(s_vn);
146 0 : }
147 :
148 0 : void VnUveTableBase::Delete(const std::string &name) {
149 0 : UveVnMap::iterator it = uve_vn_map_.find(name);
150 0 : if (it != uve_vn_map_.end()) {
151 0 : std::scoped_lock lock(uve_vn_map_mutex_);
152 0 : uve_vn_map_.erase(it);
153 0 : }
154 0 : }
155 :
156 20 : VnUveEntryBase* VnUveTableBase::Add(const VnEntry *vn) {
157 20 : VnUveEntryPtr uve = Allocate(vn);
158 20 : pair<UveVnMap::iterator, bool> ret;
159 20 : ret = uve_vn_map_.insert(UveVnPair(vn->GetName(), uve));
160 20 : UveVnMap::iterator it = ret.first;
161 20 : VnUveEntryBase* entry = it->second.get();
162 20 : entry->set_vn(vn);
163 20 : if (entry->deleted()) {
164 18 : entry->set_renewed(true);
165 : }
166 :
167 20 : return entry;
168 20 : }
169 :
170 6 : void VnUveTableBase::Add(const string &vn) {
171 6 : VnUveEntryPtr uve = Allocate();
172 6 : uve_vn_map_.insert(UveVnPair(vn, uve));
173 6 : }
174 :
175 0 : VnUveTableBase::VnUveEntryPtr VnUveTableBase::Allocate(const VnEntry *vn) {
176 0 : VnUveEntryPtr uve(new VnUveEntryBase(agent_, vn));
177 0 : return uve;
178 : }
179 :
180 0 : VnUveTableBase::VnUveEntryPtr VnUveTableBase::Allocate() {
181 0 : VnUveEntryPtr uve(new VnUveEntryBase(agent_));
182 0 : return uve;
183 : }
184 :
185 19 : void VnUveTableBase::VnNotify(DBTablePartBase *partition, DBEntryBase *e) {
186 19 : const VnEntry *vn = static_cast<const VnEntry *>(e);
187 :
188 : DBState *state = static_cast<DBState *>
189 19 : (e->GetState(partition->parent(), vn_listener_id_));
190 :
191 19 : if (e->IsDeleted()) {
192 6 : if (state) {
193 6 : VnUveEntryBase *uve = UveEntryFromVn(vn);
194 6 : if (uve) {
195 : /* The Reset API sets 'deleted' flag and resets 'renewed' and
196 : * 'add_by_vn_notify' flags */
197 6 : uve->Reset();
198 : }
199 :
200 6 : e->ClearState(partition->parent(), vn_listener_id_);
201 6 : delete state;
202 : }
203 6 : return;
204 : }
205 :
206 13 : if (!state) {
207 6 : state = new DBState();
208 6 : e->SetState(partition->parent(), vn_listener_id_, state);
209 :
210 6 : VnUveEntryBase* entry = Add(vn);
211 6 : entry->set_add_by_vn_notify(true);
212 : }
213 13 : MarkChanged(vn);
214 : }
215 :
216 14 : void VnUveTableBase::InterfaceDeleteHandler(const string &vm, const string &vn,
217 : const Interface* intf) {
218 14 : if (vn == agent_->NullString()) {
219 0 : return;
220 : }
221 :
222 14 : UveVnMap::iterator it = uve_vn_map_.find(vn);
223 14 : if (it == uve_vn_map_.end()) {
224 0 : return;
225 : }
226 :
227 14 : VnUveEntryPtr vn_uve_entry_ptr(it->second);
228 14 : VnUveEntryBase *vn_uve_entry = vn_uve_entry_ptr.get();
229 28 : UveVirtualNetworkAgent uve;
230 :
231 14 : vn_uve_entry->VmDelete(vm);
232 14 : vn_uve_entry->InterfaceDelete(intf);
233 14 : vn_uve_entry->set_changed(true);
234 14 : return;
235 14 : }
236 :
237 14 : void VnUveTableBase::InterfaceAddHandler(const VnEntry* vn,
238 : const Interface* intf,
239 : const string &vm_name,
240 : VnUveInterfaceState *state) {
241 : VnUveEntryBase *vn_uve_entry;
242 14 : vn_uve_entry = Add(vn);
243 :
244 28 : UveVirtualNetworkAgent uve;
245 :
246 14 : if (vm_name != state->vm_name_) {
247 0 : if (state->vm_name_.length()) {
248 0 : vn_uve_entry->VmDelete(state->vm_name_);
249 : }
250 : }
251 14 : if (vm_name.length()) {
252 14 : vn_uve_entry->VmAdd(vm_name);
253 : }
254 14 : vn_uve_entry->InterfaceAdd(intf);
255 14 : vn_uve_entry->set_changed(true);
256 28 : return;
257 14 : }
258 :
259 98 : void VnUveTableBase::InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e) {
260 98 : const VmInterface *vm_port = dynamic_cast<const VmInterface*>(e);
261 98 : if (vm_port == NULL) {
262 27 : return;
263 : }
264 :
265 : VnUveInterfaceState *state = static_cast<VnUveInterfaceState *>
266 71 : (e->GetState(partition->parent(), intf_listener_id_));
267 71 : if (e->IsDeleted() || (vm_port->vn() == NULL)) {
268 34 : if (state) {
269 14 : InterfaceDeleteHandler(state->vm_name_, state->vn_name_,
270 : vm_port);
271 14 : e->ClearState(partition->parent(), intf_listener_id_);
272 14 : delete state;
273 : }
274 : } else {
275 37 : const VnEntry *vn = vm_port->vn();
276 37 : const VmEntry *vm = vm_port->vm();
277 37 : std::string vm_name = vm? vm->GetCfgName() : agent_->NullString();
278 :
279 37 : if (!state) {
280 14 : state = new VnUveInterfaceState(vm_name, vn->GetName());
281 14 : e->SetState(partition->parent(), intf_listener_id_, state);
282 14 : InterfaceAddHandler(vn, vm_port, vm_name, state);
283 : } else {
284 23 : if (state->vn_name_.compare(vn->GetName()) != 0) {
285 0 : InterfaceDeleteHandler(state->vm_name_, state->vn_name_,
286 : vm_port);
287 0 : state->vm_name_ = vm_name;
288 0 : state->vn_name_ = vn->GetName();
289 0 : InterfaceAddHandler(vn, vm_port, vm_name, state);
290 0 : return;
291 : }
292 23 : if (state->vm_name_.compare(vm_name) != 0) {
293 0 : InterfaceAddHandler(vn, vm_port, vm_name, state);
294 0 : state->vm_name_ = vm_name;
295 : }
296 : }
297 37 : }
298 71 : return;
299 : }
300 :
301 0 : void VnUveTableBase::SendVnAclRuleCount() {
302 0 : UveVnMap::const_iterator it = uve_vn_map_.begin();
303 0 : while (it != uve_vn_map_.end()) {
304 0 : VnUveEntryBase *entry = it->second.get();
305 0 : ++it;
306 0 : if (entry->deleted()) {
307 0 : continue;
308 : }
309 0 : if (entry->vn()) {
310 0 : UveVirtualNetworkAgent uve;
311 0 : bool send = entry->FrameVnAclRuleCountMsg(entry->vn(), &uve);
312 0 : if (send) {
313 0 : DispatchVnMsg(uve);
314 : }
315 0 : }
316 : }
317 0 : }
|