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