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 <algorithm>
7 : #include <boost/uuid/uuid_io.hpp>
8 : #include <cmn/agent_cmn.h>
9 :
10 : #include <base/os.h>
11 : #include <base/parse_object.h>
12 : #include <base/util.h>
13 : #include <base/address_util.h>
14 : #include <ifmap/ifmap_link.h>
15 : #include <ifmap/ifmap_table.h>
16 : #include <vnc_cfg_types.h>
17 : #include <agent_types.h>
18 :
19 : #include <cfg/cfg_init.h>
20 : #include <cfg/cfg_mirror.h>
21 :
22 : #include <oper/route_common.h>
23 : #include <oper/interface_common.h>
24 : #include <oper/vn.h>
25 : #include <oper/nexthop.h>
26 : #include <oper/mpls.h>
27 : #include <oper/mirror_table.h>
28 : #include <oper/agent_sandesh.h>
29 : #include <oper/oper_dhcp_options.h>
30 : #include <oper/physical_device_vn.h>
31 : #include <oper/config_manager.h>
32 : #include <oper/global_vrouter.h>
33 : #include <oper/agent_route_resync.h>
34 : #include <oper/qos_config.h>
35 : #include <filter/acl.h>
36 : #include <oper/vxlan_routing_manager.h>
37 :
38 : using namespace autogen;
39 : using namespace std;
40 : using namespace boost;
41 : using boost::assign::map_list_of;
42 : using boost::assign::list_of;
43 :
44 : VnTable *VnTable::vn_table_;
45 :
46 : /////////////////////////////////////////////////////////////////////////////
47 : // VnIpam routines
48 : /////////////////////////////////////////////////////////////////////////////
49 373 : VnIpam::VnIpam(const std::string& ip, uint32_t len, const std::string& gw,
50 : const std::string& dns, bool dhcp, const std::string &name,
51 : const std::vector<autogen::DhcpOptionType> &dhcp_options,
52 : const std::vector<autogen::RouteType> &host_routes,
53 373 : uint32_t alloc)
54 373 : : plen(len), installed(false), dhcp_enable(dhcp), dhcp_enable_v6(dhcp), ipam_name(name),
55 746 : alloc_unit(alloc) {
56 373 : boost::system::error_code ec;
57 373 : ip_prefix = IpAddress::from_string(ip, ec);
58 373 : default_gw = IpAddress::from_string(gw, ec);
59 373 : dns_server = IpAddress::from_string(dns, ec);
60 373 : oper_dhcp_options.set_options(dhcp_options);
61 373 : oper_dhcp_options.set_host_routes(host_routes);
62 373 : }
63 :
64 228 : IpAddress VnIpam::GetSubnetAddress() const {
65 228 : if (ip_prefix.is_v4()) {
66 228 : return Address::GetIp4SubnetAddress(ip_prefix.to_v4(), plen);
67 : }
68 0 : if (ip_prefix.is_v6()) {
69 0 : return Address::GetIp6SubnetAddress(ip_prefix.to_v6(), plen);
70 : }
71 0 : return IpAddress();
72 : }
73 :
74 12176 : bool VnIpam::IsSubnetMember(const IpAddress &ip) const {
75 12176 : if (ip_prefix.is_v4() && ip.is_v4()) {
76 10457 : return ((ip_prefix.to_v4().to_ulong() |
77 10457 : ~(0xFFFFFFFF << (32 - plen))) ==
78 10457 : (ip.to_v4().to_ulong() | ~(0xFFFFFFFF << (32 - plen))));
79 1719 : } else if (ip_prefix.is_v6() && ip.is_v6()) {
80 0 : return IsIp6SubnetMember(ip.to_v6(), ip_prefix.to_v6(), plen);
81 : }
82 1719 : return false;
83 : }
84 :
85 : /////////////////////////////////////////////////////////////////////////////
86 : // VnEntry routines
87 : /////////////////////////////////////////////////////////////////////////////
88 3774 : VnEntry::VnEntry(Agent *agent, boost::uuids::uuid id) :
89 3774 : AgentOperDBEntry(), agent_(agent), uuid_(id), vrf_(NULL, this),
90 3774 : vxlan_id_(0), vnid_(0), active_vxlan_id_(0), bridging_(true),
91 7548 : layer3_forwarding_(true), admin_state_(true), table_label_(0),
92 3774 : enable_rpf_(true), flood_unknown_unicast_(false),
93 7548 : forwarding_mode_(Agent::L2_L3), mirror_destination_(false),
94 3774 : underlay_forwarding_(false), vxlan_routing_vn_(false),
95 7548 : logical_router_uuid_(), cfg_igmp_enable_(false), vn_max_flows_(0),
96 7548 : lr_vrf_(NULL, this) {
97 3774 : }
98 :
99 7548 : VnEntry::~VnEntry() {
100 7548 : }
101 :
102 10334 : bool VnEntry::IsLess(const DBEntry &rhs) const {
103 10334 : const VnEntry &a = static_cast<const VnEntry &>(rhs);
104 10334 : return (uuid_ < a.uuid_);
105 : }
106 :
107 0 : string VnEntry::ToString() const {
108 0 : std::stringstream uuidstring;
109 0 : uuidstring << uuid_;
110 0 : return uuidstring.str();
111 0 : }
112 :
113 0 : DBEntryBase::KeyPtr VnEntry::GetDBRequestKey() const {
114 0 : return DBEntryBase::KeyPtr(new VnKey(uuid_));
115 : }
116 :
117 0 : void VnEntry::SetKey(const DBRequestKey *key) {
118 0 : const VnKey *k = static_cast<const VnKey *>(key);
119 0 : uuid_ = k->uuid_;
120 0 : }
121 :
122 : // Resync operation for VN. Invoked on change of forwarding-mode or global
123 : // vxlan-config mode
124 0 : bool VnEntry::Resync(Agent *agent) {
125 : // Evaluate rebake of vxlan
126 0 : bool ret = UpdateVxlan(agent, false);
127 : // Evaluate forwarding mode change
128 0 : ret |= UpdateForwardingMode(agent);
129 : // Update routes from Ipam
130 0 : ret |= ApplyAllIpam(agent, vrf_.get(), false);
131 0 : return ret;
132 : }
133 :
134 651 : bool VnEntry::ChangeHandler(Agent *agent, const DBRequest *req) {
135 651 : bool ret = false;
136 651 : VnData *data = static_cast<VnData *>(req->data.get());
137 :
138 651 : AclKey key(data->acl_id_);
139 651 : AclDBEntry *acl = static_cast<AclDBEntry *>
140 651 : (agent->acl_table()->FindActiveEntry(&key));
141 651 : if (acl_.get() != acl) {
142 2 : acl_ = acl;
143 2 : ret = true;
144 : }
145 :
146 651 : AclKey mirror_key(data->mirror_acl_id_);
147 651 : AclDBEntry *mirror_acl = static_cast<AclDBEntry *>
148 651 : (agent->acl_table()->FindActiveEntry(&mirror_key));
149 651 : if (mirror_acl_.get() != mirror_acl) {
150 0 : mirror_acl_ = mirror_acl;
151 0 : ret = true;
152 : }
153 :
154 651 : AclKey mirror_cfg_acl_key(data->mirror_cfg_acl_id_);
155 651 : AclDBEntry *mirror_cfg_acl = static_cast<AclDBEntry *>
156 651 : (agent->acl_table()->FindActiveEntry(&mirror_cfg_acl_key));
157 651 : if (mirror_cfg_acl_.get() != mirror_cfg_acl) {
158 0 : mirror_cfg_acl_ = mirror_cfg_acl;
159 0 : ret = true;
160 : }
161 :
162 651 : AgentQosConfigKey qos_config_key(data->qos_config_uuid_);
163 651 : AgentQosConfig *qos_config = static_cast<AgentQosConfig *>
164 651 : (agent->qos_config_table()->FindActiveEntry(&qos_config_key));
165 651 : if (qos_config_.get() != qos_config) {
166 0 : qos_config_ = qos_config;
167 0 : ret = true;
168 : }
169 :
170 651 : VrfKey vrf_key(data->vrf_name_);
171 651 : VrfEntry *vrf = static_cast<VrfEntry *>
172 651 : (agent->vrf_table()->FindActiveEntry(&vrf_key));
173 651 : VrfEntryRef old_vrf = vrf_;
174 651 : bool update_vxlan_state = false;
175 651 : if (vrf != old_vrf.get()) {
176 73 : if (!vrf) {
177 7 : ApplyAllIpam(agent, old_vrf.get(), true);
178 : }
179 73 : vrf_ = vrf;
180 73 : update_vxlan_state = true;
181 73 : ret = true;
182 : }
183 :
184 651 : if (admin_state_ != data->admin_state_) {
185 0 : admin_state_ = data->admin_state_;
186 0 : ret = true;
187 : }
188 :
189 651 : if (forwarding_mode_ != data->forwarding_mode_) {
190 69 : forwarding_mode_ = data->forwarding_mode_;
191 69 : ret = true;
192 : }
193 :
194 : // Recompute the forwarding modes in VN
195 : // Must rebake the routes if any change in forwarding modes
196 651 : bool resync_routes = false;
197 651 : resync_routes = UpdateForwardingMode(agent);
198 651 : ret |= resync_routes;
199 :
200 : // Update the routes derived from IPAM
201 651 : ret |= UpdateIpam(agent, data->ipam_);
202 :
203 651 : if (vn_ipam_data_ != data->vn_ipam_data_) {
204 80 : vn_ipam_data_ = data->vn_ipam_data_;
205 80 : ret = true;
206 : }
207 :
208 651 : if (enable_rpf_ != data->enable_rpf_) {
209 0 : enable_rpf_ = data->enable_rpf_;
210 0 : ret = true;
211 : }
212 :
213 651 : if (vxlan_routing_vn_ != data->vxlan_routing_vn_) {
214 0 : vxlan_routing_vn_ = data->vxlan_routing_vn_;
215 0 : update_vxlan_state = true;
216 0 : ret = true;
217 : }
218 :
219 651 : if (vxlan_id_ != data->vxlan_id_) {
220 67 : vxlan_id_ = data->vxlan_id_;
221 67 : ret = true;
222 67 : if ((agent->vxlan_network_identifier_mode() == Agent::CONFIGURED) || vxlan_routing_vn_ ) {
223 0 : update_vxlan_state = true;
224 : }
225 : }
226 :
227 651 : if (vnid_ != data->vnid_) {
228 67 : vnid_ = data->vnid_;
229 67 : ret = true;
230 67 : if (agent->vxlan_network_identifier_mode() == Agent::AUTOMATIC) {
231 67 : update_vxlan_state = true;
232 : }
233 : }
234 :
235 651 : if (flood_unknown_unicast_ != data->flood_unknown_unicast_) {
236 0 : flood_unknown_unicast_ = data->flood_unknown_unicast_;
237 0 : update_vxlan_state = true;
238 0 : ret = true;
239 : }
240 :
241 651 : if (mirror_destination_ != data->mirror_destination_) {
242 0 : mirror_destination_ = data->mirror_destination_;
243 0 : update_vxlan_state = true;
244 0 : ret = true;
245 : }
246 :
247 651 : if (update_vxlan_state) {
248 140 : ret |= UpdateVxlan(agent, false);
249 : }
250 :
251 651 : if (resync_routes) {
252 0 : if (vrf_.get() != NULL) {
253 : AgentRouteResync *resync =
254 0 : (static_cast<AgentRouteResync *>(route_resync_walker_.get()));
255 0 : resync->UpdateRoutesInVrf(vrf_.get());
256 : }
257 : }
258 :
259 651 : if (pbb_evpn_enable_ != data->pbb_evpn_enable_) {
260 10 : pbb_evpn_enable_ = data->pbb_evpn_enable_;
261 10 : ret = true;
262 : }
263 :
264 651 : if (pbb_etree_enable_ != data->pbb_etree_enable_) {
265 10 : pbb_etree_enable_ = data->pbb_etree_enable_;
266 10 : ret = true;
267 : }
268 :
269 651 : if (layer2_control_word_ != data->layer2_control_word_) {
270 10 : layer2_control_word_ = data->layer2_control_word_;
271 10 : ret = true;
272 : }
273 :
274 651 : if (underlay_forwarding_ != data->underlay_forwarding_) {
275 0 : underlay_forwarding_ = data->underlay_forwarding_;
276 0 : ret = true;
277 : }
278 :
279 651 : if (slo_list_ != data->slo_list_) {
280 0 : slo_list_ = data->slo_list_;
281 : }
282 :
283 651 : if (logical_router_uuid_ != data->logical_router_uuid_) {
284 0 : logical_router_uuid_ = data->logical_router_uuid_;
285 0 : ret = true;
286 : }
287 :
288 651 : if (mp_list_ != data->mp_list_) {
289 0 : mp_list_ = data->mp_list_;
290 : }
291 :
292 651 : if (cfg_igmp_enable_ != data->cfg_igmp_enable_) {
293 0 : cfg_igmp_enable_ = data->cfg_igmp_enable_;
294 : }
295 :
296 651 : if (vn_max_flows_ != data->vn_max_flows_) {
297 0 : vn_max_flows_ = data->vn_max_flows_;
298 0 : ret = true;
299 : }
300 :
301 651 : if (mac_ip_learning_enable_ != data->mac_ip_learning_enable_) {
302 4 : mac_ip_learning_enable_ = data->mac_ip_learning_enable_;
303 4 : ret = true;
304 : }
305 :
306 651 : if (health_check_uuid_ != data->health_check_uuid_) {
307 4 : health_check_uuid_ = data->health_check_uuid_;
308 4 : ret = true;
309 : }
310 :
311 651 : return ret;
312 651 : }
313 :
314 : // Rebake handles
315 : // - vxlan-id change :
316 : // Deletes the config-entry for old-vxlan and adds config-entry for new-vxlan
317 : // Might result in change of vxlan_id_ref_ for the VN
318 : //
319 : // If vxlan_id is 0, or vrf is NULL, its treated as delete of config-entry
320 : // - Delete
321 : // Deletes the vxlan-config entry. Will reset the vxlan-id-ref to NULL
322 336 : bool VnEntry::UpdateVxlan(Agent *agent, bool op_del) {
323 336 : int old_vxlan = active_vxlan_id_;
324 336 : int new_vxlan = GetVxLanId();
325 :
326 336 : if (op_del || old_vxlan != new_vxlan || vrf_.get() == NULL) {
327 336 : if (old_vxlan != 0) {
328 67 : agent->vxlan_table()->Delete(old_vxlan, uuid_);
329 67 : vxlan_id_ref_ = NULL;
330 67 : active_vxlan_id_ = 0;
331 : }
332 : }
333 :
334 336 : if (op_del == false && vrf_.get() != NULL && new_vxlan != 0) {
335 : vxlan_id_ref_ = agent->vxlan_table()->Locate
336 134 : (new_vxlan, uuid_, vrf_->GetName(), flood_unknown_unicast_,
337 67 : mirror_destination_, false, true);
338 67 : active_vxlan_id_ = new_vxlan;
339 : }
340 :
341 336 : return (old_vxlan != new_vxlan);
342 : }
343 :
344 : // Compute the layer3_forwarding_ and bridging mode for the VN.
345 : // Forwarding mode is picked from VN if its defined. Else, picks forwarding
346 : // mode from global-vrouter-config
347 651 : bool VnEntry::UpdateForwardingMode(Agent *agent) {
348 651 : Agent::ForwardingMode forwarding_mode = forwarding_mode_;
349 651 : if (forwarding_mode == Agent::NONE) {
350 : forwarding_mode =
351 651 : agent->oper_db()->global_vrouter()->forwarding_mode();
352 : }
353 :
354 651 : bool ret = false;
355 651 : bool routing = (forwarding_mode == Agent::L2) ? false : true;
356 651 : if (routing != layer3_forwarding_) {
357 0 : layer3_forwarding_ = routing;
358 0 : ret = true;
359 : }
360 :
361 651 : bool bridging = (forwarding_mode == Agent::L3) ? false : true;
362 651 : if (bridging != bridging_) {
363 0 : bridging_ = bridging;
364 0 : ret = true;
365 : }
366 :
367 651 : return ret;
368 : }
369 :
370 : // Update all IPAM configurations. Typically invoked when forwarding-mode
371 : // changes or VRF is set for the VN
372 203 : bool VnEntry::ApplyAllIpam(Agent *agent, VrfEntry *old_vrf, bool del) {
373 203 : bool ret = false;
374 392 : for (unsigned int i = 0; i < ipam_.size(); ++i) {
375 189 : ret |= ApplyIpam(agent, &ipam_[i], old_vrf, del);
376 : }
377 :
378 203 : return ret;
379 : }
380 :
381 : // Add/Delete routes dervied from a single IPAM
382 296 : bool VnEntry::ApplyIpam(Agent *agent, VnIpam *ipam, VrfEntry *old_vrf,
383 : bool del) {
384 296 : if (CanInstallIpam(ipam) == false)
385 27 : del = true;
386 :
387 296 : bool old_installed = ipam->installed;
388 296 : if (del == false) {
389 80 : ipam->installed = AddIpamRoutes(agent, ipam);
390 : } else {
391 216 : DelIpamRoutes(agent, ipam, old_vrf);
392 216 : ipam->installed = false;
393 : }
394 :
395 296 : return old_installed != ipam->installed;
396 : }
397 :
398 586 : bool VnEntry::CanInstallIpam(const VnIpam *ipam) {
399 586 : if (vrf_.get() == NULL || layer3_forwarding_ == false)
400 51 : return false;
401 535 : return true;
402 : }
403 :
404 : // Check the old and new Ipam data and update receive routes for GW addresses
405 651 : bool VnEntry::UpdateIpam(Agent *agent, std::vector<VnIpam> &new_ipam) {
406 651 : std::sort(new_ipam.begin(), new_ipam.end());
407 :
408 651 : std::vector<VnIpam>::iterator it_old = ipam_.begin();
409 651 : std::vector<VnIpam>::iterator it_new = new_ipam.begin();
410 651 : bool change = false;
411 941 : while (it_old != ipam_.end() && it_new != new_ipam.end()) {
412 290 : if (*it_old < *it_new) {
413 : // old entry is deleted
414 0 : ApplyIpam(agent, &(*it_old), vrf_.get(), true);
415 0 : change = true;
416 0 : it_old++;
417 290 : } else if (*it_new < *it_old) {
418 : // new entry
419 0 : ApplyIpam(agent, &(*it_new), vrf_.get(), false);
420 0 : change = true;
421 0 : it_new++;
422 : } else {
423 290 : change |= HandleIpamChange(agent, &(*it_old), &(*it_new));
424 290 : it_old++;
425 290 : it_new++;
426 : }
427 : }
428 :
429 : // delete remaining old entries
430 671 : for (; it_old != ipam_.end(); ++it_old) {
431 20 : ApplyIpam(agent, &(*it_old), vrf_.get(), true);
432 20 : change = true;
433 : }
434 :
435 : // add remaining new entries
436 734 : for (; it_new != new_ipam.end(); ++it_new) {
437 83 : ApplyIpam(agent, &(*it_new), vrf_.get(), false);
438 83 : change = true;
439 : }
440 :
441 651 : ipam_ = new_ipam;
442 651 : return change;
443 : }
444 :
445 160 : static bool IsGwHostRouteRequired(const Agent *agent) {
446 160 : return (!agent->tsn_enabled());
447 : }
448 :
449 : // Evaluate non key members of IPAM for changes. Key fields are not changed
450 : // Handles changes to gateway-ip and service-ip in the IPAM
451 290 : bool VnEntry::HandleIpamChange(Agent *agent, VnIpam *old_ipam,
452 : VnIpam *new_ipam) {
453 290 : bool install = CanInstallIpam(new_ipam);
454 :
455 290 : if (install == false && old_ipam->installed == false)
456 24 : return false;
457 :
458 266 : if (install == false && old_ipam->installed == true) {
459 0 : ApplyIpam(agent, old_ipam, vrf_.get(), true);
460 0 : return true;
461 : }
462 :
463 266 : if (install == true && old_ipam->installed == false) {
464 4 : ApplyIpam(agent, new_ipam, vrf_.get(), false);
465 4 : return true;
466 : }
467 :
468 262 : new_ipam->installed = install;
469 262 : bool changed = false;
470 262 : bool policy = (agent->tsn_enabled()) ? false : true;
471 : // CEM-4646:don't delete route if is used by DNS/GW
472 : // Update: GW changed?NO, DNS changed?YES
473 : // action: check if old DNS address is same as GW address
474 : // Update: GW changed?YES, DNS changed?NO
475 : // action: check if old GW address is same as DNS address
476 : // Update: GW changed?YES, DNS changed?YES
477 : // action: check if new DNS server address is same as old GW address
478 :
479 262 : if (vrf_.get() && (vrf_->GetName() != agent->linklocal_vrf_name())) {
480 262 : if (old_ipam->default_gw != new_ipam->default_gw) {
481 0 : changed = true;
482 0 : if (IsGwHostRouteRequired(agent)) {
483 0 : if (old_ipam->default_gw != new_ipam->dns_server) {
484 0 : UpdateHostRoute(agent, old_ipam->default_gw,
485 0 : new_ipam->default_gw, policy);
486 : } else {
487 0 : AddHostRoute(new_ipam->default_gw, policy);
488 : }
489 : }
490 : }
491 : }
492 :
493 262 : if (old_ipam->dns_server != new_ipam->dns_server) {
494 0 : if (old_ipam->dns_server != new_ipam->default_gw) {
495 0 : UpdateHostRoute(agent, old_ipam->dns_server,
496 0 : new_ipam->dns_server, policy);
497 : } else {
498 0 : AddHostRoute(new_ipam->dns_server, policy);
499 : }
500 0 : changed = true;
501 : }
502 :
503 : // update DHCP options
504 262 : old_ipam->oper_dhcp_options = new_ipam->oper_dhcp_options;
505 :
506 262 : if (old_ipam->dhcp_enable != new_ipam->dhcp_enable) {
507 0 : changed = true;
508 : }
509 :
510 262 : if (old_ipam->dhcp_enable_v6 != new_ipam->dhcp_enable_v6) {
511 0 : changed = true;
512 : }
513 :
514 262 : return changed;
515 : }
516 :
517 0 : void VnEntry::UpdateHostRoute(Agent *agent, const IpAddress &old_address,
518 : const IpAddress &new_address,
519 : bool policy) {
520 0 : AddHostRoute(new_address, policy);
521 0 : DelHostRoute(old_address);
522 0 : }
523 :
524 : // Add all routes derived from IPAM. IPAM generates following routes,
525 : // - Subnet route
526 : // - Gateway route
527 : // - Service-IP route
528 80 : bool VnEntry::AddIpamRoutes(Agent *agent, VnIpam *ipam) {
529 80 : if (vrf_ == NULL)
530 0 : return false;
531 :
532 : // Do not let the gateway configuration overwrite the receive nh.
533 80 : if (vrf_->GetName() == agent->linklocal_vrf_name()) {
534 0 : return false;
535 : }
536 :
537 : // Allways policy will be enabled for default Gateway and
538 : // Dns server to create flows for BGP as service even
539 : // though explicit disable policy config form user.
540 80 : bool policy = (agent->tsn_enabled()) ? false : true;
541 80 : if (IsGwHostRouteRequired(agent))
542 80 : AddHostRoute(ipam->default_gw, policy);
543 80 : AddHostRoute(ipam->dns_server, policy);
544 80 : AddSubnetRoute(ipam);
545 80 : return true;
546 : }
547 :
548 : // Delete routes generated from an IPAM
549 216 : void VnEntry::DelIpamRoutes(Agent *agent, VnIpam *ipam, VrfEntry *vrf) {
550 216 : if (ipam->installed == false)
551 136 : return;
552 :
553 80 : assert(vrf);
554 80 : if (IsGwHostRouteRequired(agent))
555 80 : DelHostRoute(ipam->default_gw);
556 80 : DelHostRoute(ipam->dns_server);
557 80 : DelSubnetRoute(ipam);
558 : }
559 :
560 : // Add host route for gateway-ip or service-ip
561 160 : void VnEntry::AddHostRoute(const IpAddress &address, bool policy) {
562 160 : if (address.is_v4()) {
563 : static_cast<InetUnicastAgentRouteTable *>(vrf_->
564 320 : GetInet4UnicastRouteTable())->AddHostRoute(vrf_->GetName(),
565 320 : address.to_v4(), 32, GetName(), policy);
566 0 : } else if (address.is_v6()) {
567 : static_cast<InetUnicastAgentRouteTable *>(vrf_->
568 0 : GetInet6UnicastRouteTable())->AddHostRoute(vrf_->GetName(),
569 0 : address.to_v6(), 128, GetName(), policy);
570 : }
571 160 : }
572 :
573 : // Del host route for gateway-ip or service-ip
574 160 : void VnEntry::DelHostRoute(const IpAddress &address) {
575 160 : Agent *agent = static_cast<VnTable *>(get_table())->agent();
576 160 : if (address.is_v4()) {
577 : static_cast<InetUnicastAgentRouteTable *>
578 160 : (vrf_->GetInet4UnicastRouteTable())->DeleteReq
579 160 : (agent->local_peer(), vrf_->GetName(), address.to_v4(), 32, NULL);
580 0 : } else if (address.is_v6()) {
581 : static_cast<InetUnicastAgentRouteTable *>
582 0 : (vrf_->GetInet6UnicastRouteTable())->DeleteReq
583 0 : (agent->local_peer(), vrf_->GetName(), address.to_v6(), 128,
584 : NULL);
585 : }
586 160 : }
587 :
588 : // Add subnet route for the IPAM
589 80 : void VnEntry::AddSubnetRoute(VnIpam *ipam) {
590 : static_cast<InetUnicastAgentRouteTable *>(vrf_->
591 80 : GetInetUnicastRouteTable(ipam->ip_prefix))->AddIpamSubnetRoute
592 80 : (vrf_->GetName(), ipam->GetSubnetAddress(), ipam->plen,
593 : GetName());
594 80 : }
595 :
596 : // Del subnet route for the IPAM
597 80 : void VnEntry::DelSubnetRoute(VnIpam *ipam) {
598 80 : Agent *agent = static_cast<VnTable *>(get_table())->agent();
599 : static_cast<InetUnicastAgentRouteTable *>(vrf_->
600 80 : GetInetUnicastRouteTable(ipam->ip_prefix))->DeleteReq
601 80 : (agent->local_peer(), vrf_->GetName(),
602 80 : ipam->GetSubnetAddress(), ipam->plen, NULL);
603 80 : }
604 :
605 69 : void VnEntry::AllocWalker() {
606 69 : assert(route_resync_walker_.get() == NULL);
607 : route_resync_walker_ = new AgentRouteResync("VnRouteResyncWalker",
608 69 : agent_);
609 69 : agent_->oper_db()->agent_route_walk_manager()->
610 69 : RegisterWalker(static_cast<AgentRouteWalker *>
611 : (route_resync_walker_.get()));
612 69 : }
613 :
614 196 : void VnEntry::ReleaseWalker() {
615 196 : if (route_resync_walker_.get() == NULL)
616 127 : return;
617 69 : agent_->oper_db()->agent_route_walk_manager()->
618 69 : ReleaseWalker(route_resync_walker_.get());
619 69 : route_resync_walker_.reset(NULL);
620 : }
621 :
622 0 : bool VnEntry::GetVnHostRoutes(const std::string &ipam,
623 : std::vector<OperDhcpOptions::HostRoute> *routes) const {
624 0 : VnData::VnIpamDataMap::const_iterator it = vn_ipam_data_.find(ipam);
625 0 : if (it != vn_ipam_data_.end()) {
626 0 : *routes = it->second.oper_dhcp_options_.host_routes();
627 0 : return true;
628 : }
629 0 : return false;
630 : }
631 :
632 1816 : bool VnEntry::GetIpamName(const IpAddress &vm_addr,
633 : std::string *ipam_name) const {
634 2139 : for (unsigned int i = 0; i < ipam_.size(); i++) {
635 1345 : if (ipam_[i].IsSubnetMember(vm_addr)) {
636 1022 : *ipam_name = ipam_[i].ipam_name;
637 1022 : return true;
638 : }
639 : }
640 794 : return false;
641 : }
642 :
643 0 : bool VnEntry::GetIpamData(const IpAddress &vm_addr,
644 : std::string *ipam_name,
645 : autogen::IpamType *ipam) const {
646 0 : if (!GetIpamName(vm_addr, ipam_name) ||
647 0 : !agent_->domain_config_table()->GetIpam(*ipam_name, ipam))
648 0 : return false;
649 :
650 0 : return true;
651 : }
652 :
653 11447 : const VnIpam *VnEntry::GetIpam(const IpAddress &ip) const {
654 15464 : for (unsigned int i = 0; i < ipam_.size(); i++) {
655 10746 : if (ipam_[i].IsSubnetMember(ip)) {
656 6729 : return &ipam_[i];
657 : }
658 : }
659 4718 : return NULL;
660 : }
661 :
662 500 : IpAddress VnEntry::GetGatewayFromIpam(const IpAddress &ip) const {
663 500 : const VnIpam *ipam = GetIpam(ip);
664 500 : if (ipam) {
665 500 : return ipam->default_gw;
666 : }
667 0 : return IpAddress();
668 : }
669 :
670 500 : IpAddress VnEntry::GetDnsFromIpam(const IpAddress &ip) const {
671 500 : const VnIpam *ipam = GetIpam(ip);
672 500 : if (ipam) {
673 500 : return ipam->dns_server;
674 : }
675 0 : return IpAddress();
676 : }
677 :
678 1022 : uint32_t VnEntry::GetAllocUnitFromIpam(const IpAddress &ip) const {
679 1022 : const VnIpam *ipam = GetIpam(ip);
680 1022 : if (ipam) {
681 556 : return ipam->alloc_unit;
682 : }
683 466 : return 1;//Default value
684 : }
685 :
686 1816 : bool VnEntry::GetIpamVdnsData(const IpAddress &vm_addr,
687 : autogen::IpamType *ipam_type,
688 : autogen::VirtualDnsType *vdns_type) const {
689 1816 : std::string ipam_name;
690 1816 : if (!GetIpamName(vm_addr, &ipam_name) ||
691 2838 : !agent_->domain_config_table()->GetIpam(ipam_name, ipam_type) ||
692 1022 : ipam_type->ipam_dns_method != "virtual-dns-server")
693 1816 : return false;
694 :
695 0 : if (!agent_->domain_config_table()->GetVDns(
696 0 : ipam_type->ipam_dns_server.virtual_dns_server_name, vdns_type))
697 0 : return false;
698 :
699 0 : return true;
700 1816 : }
701 :
702 0 : bool VnEntry::GetPrefix(const Ip6Address &ip, Ip6Address *prefix,
703 : uint8_t *plen) const {
704 0 : for (uint32_t i = 0; i < ipam_.size(); ++i) {
705 0 : if (!ipam_[i].IsV6()) {
706 0 : continue;
707 : }
708 0 : if (IsIp6SubnetMember(ip, ipam_[i].ip_prefix.to_v6(),
709 0 : ipam_[i].plen)) {
710 0 : *prefix = ipam_[i].ip_prefix.to_v6();
711 0 : *plen = (uint8_t)ipam_[i].plen;
712 0 : return true;
713 : }
714 : }
715 0 : return false;
716 : }
717 :
718 113 : std::string VnEntry::GetProject() const {
719 : // TODO: update to get the project name from project-vn link.
720 : // Currently, this info doesnt come to the agent
721 113 : std::string name(name_.c_str());
722 : char *saveptr;
723 113 : if (strtok_r(const_cast<char *>(name.c_str()), ":", &saveptr) == NULL)
724 0 : return "";
725 113 : char *project = strtok_r(NULL, ":", &saveptr);
726 113 : return (project == NULL) ? "" : std::string(project);
727 113 : }
728 :
729 3128 : int VnEntry::GetVxLanId() const {
730 3128 : if (agent_->vxlan_network_identifier_mode() == Agent::CONFIGURED) {
731 0 : return vxlan_id_;
732 : }
733 3128 : if (vxlan_routing_vn_ && vxlan_id_) {
734 0 : return vxlan_id_;
735 : }
736 3128 : return vnid_;
737 : }
738 :
739 651 : int VnEntry::GetOperVxlanId() const {
740 651 : if (agent_->vxlan_network_identifier_mode() == Agent::CONFIGURED) {
741 0 : return vxlan_id_;
742 : }
743 651 : if (bool(vxlan_id_ref_)) {
744 496 : return vxlan_id_ref_->vxlan_id();
745 : }
746 155 : return 0;
747 : }
748 :
749 : /////////////////////////////////////////////////////////////////////////////
750 : // VnTable routines
751 : /////////////////////////////////////////////////////////////////////////////
752 2 : VnTable::VnTable(DB *db, const std::string &name) : AgentOperDBTable(db, name) {
753 4 : walk_ref_ = AllocWalker(boost::bind(&VnTable::VnEntryWalk, this, _1, _2),
754 : boost::bind(&VnTable::VnEntryWalkDone, this, _1,
755 2 : _2));
756 2 : }
757 :
758 4 : VnTable::~VnTable() {
759 4 : }
760 :
761 0 : void VnTable::Clear() {
762 0 : ReleaseWalker(walk_ref_);
763 0 : }
764 :
765 2 : DBTableBase *VnTable::CreateTable(DB *db, const std::string &name) {
766 2 : vn_table_ = new VnTable(db, name);
767 2 : vn_table_->Init();
768 2 : return vn_table_;
769 : };
770 :
771 1298 : VnEntry *VnTable::Find(const boost::uuids::uuid &u) {
772 1298 : VnKey key(u);
773 2596 : return static_cast<VnEntry *>(FindActiveEntry(&key));
774 1298 : }
775 :
776 3705 : std::unique_ptr<DBEntry> VnTable::AllocEntry(const DBRequestKey *k) const {
777 3705 : const VnKey *key = static_cast<const VnKey *>(k);
778 3705 : VnEntry *vn = new VnEntry(agent(), key->uuid_);
779 3705 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vn));
780 : }
781 :
782 69 : DBEntry *VnTable::OperDBAdd(const DBRequest *req) {
783 69 : VnKey *key = static_cast<VnKey *>(req->key.get());
784 69 : VnData *data = static_cast<VnData *>(req->data.get());
785 69 : VnEntry *vn = new VnEntry(agent(), key->uuid_);
786 69 : vn->name_ = data->name_;
787 69 : vn->AllocWalker();
788 :
789 69 : vn->ChangeHandler(agent(), req);
790 69 : vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::ADD);
791 :
792 69 : if (vn->name_ == agent()->fabric_vn_name()) {
793 : //In case of distributes SNAT we want all
794 : //interfaces to revaluated upon receiving
795 : //the config
796 0 : agent()->set_fabric_vn_uuid(key->uuid_);
797 0 : agent()->cfg()->cfg_vm_interface_table()->NotifyAllEntries();
798 : }
799 69 : return vn;
800 : }
801 :
802 196 : bool VnTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
803 196 : VnEntry *vn = static_cast<VnEntry *>(entry);
804 196 : vn->ApplyAllIpam(agent(), vn->vrf_.get(), true);
805 196 : vn->UpdateVxlan(agent(), true);
806 196 : vn->ReleaseWalker();
807 196 : vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::DEL);
808 :
809 196 : if (vn->name_ == agent()->fabric_vn_name()) {
810 0 : agent()->set_fabric_vn_uuid(boost::uuids::nil_uuid());
811 0 : agent()->cfg()->cfg_vm_interface_table()->NotifyAllEntries();
812 : }
813 196 : return true;
814 : }
815 :
816 582 : bool VnTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
817 582 : VnEntry *vn = static_cast<VnEntry *>(entry);
818 582 : bool ret = vn->ChangeHandler(agent(), req);
819 582 : vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::CHANGE);
820 582 : if (ret) {
821 131 : VnData *data = static_cast<VnData *>(req->data.get());
822 131 : if (data && data->ifmap_node()) {
823 : agent()->oper_db()->dependency_manager()->PropogateNodeChange
824 131 : (data->ifmap_node());
825 : }
826 : }
827 582 : return ret;
828 : }
829 :
830 0 : bool VnTable::OperDBResync(DBEntry *entry, const DBRequest *req) {
831 0 : VnEntry *vn = static_cast<VnEntry *>(entry);
832 0 : return vn->Resync(agent());
833 : }
834 :
835 0 : bool VnTable::VnEntryWalk(DBTablePartBase *partition, DBEntryBase *entry) {
836 0 : VnEntry *vn_entry = static_cast<VnEntry *>(entry);
837 0 : if (vn_entry->GetVrf()) {
838 0 : ResyncReq(vn_entry->GetUuid());
839 : }
840 0 : return true;
841 : }
842 :
843 2 : void VnTable::VnEntryWalkDone(DBTable::DBTableWalkRef walk_ref,
844 : DBTableBase *partition) {
845 2 : agent()->interface_table()->GlobalVrouterConfigChanged();
846 : agent()->physical_device_vn_table()->
847 2 : UpdateVxLanNetworkIdentifierMode();
848 2 : }
849 :
850 2 : void VnTable::GlobalVrouterConfigChanged() {
851 2 : WalkAgain(walk_ref_);
852 2 : }
853 :
854 : /*
855 : * IsVRFServiceChainingInstance
856 : * Helper function to identify the service chain vrf.
857 : * In VN-VRF mapping config can send multiple VRF for same VN.
858 : * Since assumption had been made that VN to VRF is always 1:1 this
859 : * situation needs to be handled.
860 : * This is a temporary solution in which all VRF other than primary VRF
861 : * is ignored.
862 : * Example:
863 : * VN name: domain:vn1
864 : * VRF 1: domain:vn1:vn1 ----> Primary
865 : * VRF 2: domain:vn1:service-vn1_vn2 ----> Second vrf linked to vn1
866 : * Break the VN and VRF name into tokens based on ':'
867 : * So in primary vrf last and second-last token will be same and will be
868 : * equal to last token of VN name. Keep this VRF.
869 : * The second VRF last and second-last token are not same so it will be ignored.
870 : *
871 : */
872 991 : bool IsVRFServiceChainingInstance(const string &vn_name, const string &vrf_name)
873 : {
874 991 : vector<string> vn_token_result;
875 991 : vector<string> vrf_token_result;
876 991 : uint32_t vrf_token_result_size = 0;
877 :
878 991 : split(vn_token_result, vn_name, is_any_of(":"), token_compress_on);
879 991 : split(vrf_token_result, vrf_name, is_any_of(":"), token_compress_on);
880 991 : vrf_token_result_size = vrf_token_result.size();
881 :
882 : /*
883 : * This check is to handle test cases where vrf and vn name
884 : * are single word without discriminator ':'
885 : * e.g. vrf1 or vn1. In these cases we dont ignore and use
886 : * the VRF
887 : */
888 991 : if (vrf_token_result_size == 1) {
889 507 : return false;
890 : }
891 484 : if ((vrf_token_result.at(vrf_token_result_size - 1) ==
892 1452 : vrf_token_result.at(vrf_token_result_size - 2)) &&
893 484 : (vn_token_result.at(vn_token_result.size() - 1) ==
894 484 : vrf_token_result.at(vrf_token_result_size - 1))) {
895 484 : return false;
896 : }
897 0 : return true;
898 991 : }
899 :
900 357 : IFMapNode *VnTable::FindTarget(IFMapAgentTable *table, IFMapNode *node,
901 : std::string node_type) {
902 357 : for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
903 663 : it != node->end(table->GetGraph()); ++it) {
904 598 : IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
905 598 : if (adj_node->table()->Typename() == node_type)
906 292 : return adj_node;
907 : }
908 65 : return NULL;
909 : }
910 :
911 651 : int VnTable::GetCfgVnId(VirtualNetwork *cfg_vn) {
912 651 : if (cfg_vn->IsPropertySet(autogen::VirtualNetwork::NETWORK_ID))
913 602 : return cfg_vn->network_id();
914 : else
915 49 : return cfg_vn->properties().network_id;
916 : }
917 :
918 651 : void VnTable::CfgForwardingFlags(IFMapNode *node,
919 : bool *rpf, bool *flood_unknown_unicast,
920 : Agent::ForwardingMode *forwarding_mode,
921 : bool *mirror_destination) {
922 651 : *rpf = true;
923 :
924 651 : VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
925 651 : autogen::VirtualNetworkType properties = cfg->properties();
926 :
927 651 : if (properties.rpf == "disable") {
928 0 : *rpf = false;
929 : }
930 :
931 651 : *flood_unknown_unicast = cfg->flood_unknown_unicast();
932 651 : *mirror_destination = properties.mirror_destination;
933 651 : *forwarding_mode =
934 651 : agent()->TranslateForwardingMode(properties.forwarding_mode);
935 651 : }
936 :
937 : void
938 292 : VnTable::BuildVnIpamData(const std::vector<autogen::IpamSubnetType> &subnets,
939 : const std::string &ipam_name,
940 : std::vector<VnIpam> *vn_ipam) {
941 665 : for (unsigned int i = 0; i < subnets.size(); ++i) {
942 : // if the DNS server address is not specified, set this
943 : // to be the same as the GW address
944 373 : std::string dns_server_address = subnets[i].dns_server_address;
945 373 : boost::system::error_code ec;
946 : IpAddress dns_server =
947 373 : IpAddress::from_string(dns_server_address, ec);
948 373 : if (ec.value() || dns_server.is_unspecified()) {
949 0 : dns_server_address = subnets[i].default_gateway;
950 : }
951 :
952 : vn_ipam->push_back
953 373 : (VnIpam(subnets[i].subnet.ip_prefix,
954 373 : subnets[i].subnet.ip_prefix_len,
955 373 : subnets[i].default_gateway,
956 : dns_server_address,
957 373 : subnets[i].enable_dhcp, ipam_name,
958 373 : subnets[i].dhcp_option_list.dhcp_option,
959 373 : subnets[i].host_routes.route,
960 373 : subnets[i].alloc_unit));
961 373 : }
962 292 : }
963 :
964 651 : VnData *VnTable::BuildData(IFMapNode *node) {
965 : using boost::uuids::uuid;
966 : using boost::uuids::nil_uuid;
967 651 : boost::uuids::uuid mp_uuid = nil_uuid();
968 651 : UuidList mp_list;
969 :
970 651 : VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
971 651 : assert(cfg);
972 :
973 651 : uuid acl_uuid = nil_uuid();
974 651 : uuid mirror_cfg_acl_uuid = nil_uuid();
975 651 : uuid qos_config_uuid = nil_uuid();
976 651 : string vrf_name = "";
977 651 : std::vector<VnIpam> vn_ipam;
978 651 : VnData::VnIpamDataMap vn_ipam_data;
979 651 : std::string ipam_name;
980 651 : UuidList slo_list;
981 651 : bool underlay_forwarding = false;
982 651 : bool vxlan_routing_vn = false;
983 651 : uuid logical_router_uuid = nil_uuid();
984 651 : uuid health_check_uuid = nil_uuid();
985 :
986 : // Find link with ACL / VRF adjacency
987 651 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
988 651 : DBGraph *graph = table->GetGraph();
989 651 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
990 2485 : iter != node->end(table->GetGraph()); ++iter) {
991 :
992 1834 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
993 1834 : if (agent()->config_manager()->SkipNode(adj_node)) {
994 17 : continue;
995 : }
996 :
997 1817 : if (adj_node->table() == agent()->cfg()->cfg_acl_table()) {
998 : AccessControlList *acl_cfg = static_cast<AccessControlList *>
999 2 : (adj_node->GetObject());
1000 2 : assert(acl_cfg);
1001 2 : autogen::IdPermsType id_perms = acl_cfg->id_perms();
1002 2 : if (acl_cfg->entries().dynamic) {
1003 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1004 : mirror_cfg_acl_uuid);
1005 : } else {
1006 2 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1007 : acl_uuid);
1008 : }
1009 2 : }
1010 :
1011 2317 : if ((adj_node->table() == agent()->cfg()->cfg_vrf_table()) &&
1012 500 : (!IsVRFServiceChainingInstance(node->name(), adj_node->name()))) {
1013 500 : vrf_name = adj_node->name();
1014 : }
1015 :
1016 1817 : if (adj_node->table() == agent()->cfg()->cfg_qos_table()) {
1017 : autogen::QosConfig *qc =
1018 0 : static_cast<autogen::QosConfig *>(adj_node->GetObject());
1019 0 : autogen::IdPermsType id_perms = qc->id_perms();
1020 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1021 : qos_config_uuid);
1022 0 : }
1023 :
1024 1817 : if (adj_node->table() == agent()->cfg()->cfg_slo_table()) {
1025 0 : uuid slo_uuid = nil_uuid();
1026 : autogen::SecurityLoggingObject *slo =
1027 : static_cast<autogen::SecurityLoggingObject *>(adj_node->
1028 0 : GetObject());
1029 0 : autogen::IdPermsType id_perms = slo->id_perms();
1030 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1031 : slo_uuid);
1032 0 : slo_list.push_back(slo_uuid);
1033 0 : }
1034 :
1035 1817 : if (adj_node->table() == agent()->cfg()->cfg_vn_network_ipam_table()) {
1036 357 : if (IFMapNode *ipam_node = FindTarget(table, adj_node,
1037 : "network-ipam")) {
1038 292 : ipam_name = ipam_node->name();
1039 : VirtualNetworkNetworkIpam *vnni =
1040 : static_cast<VirtualNetworkNetworkIpam *>
1041 292 : (adj_node->GetObject());
1042 292 : VnSubnetsType subnets;
1043 292 : if (vnni)
1044 292 : subnets = vnni->data();
1045 :
1046 : autogen::NetworkIpam *network_ipam =
1047 292 : static_cast<autogen::NetworkIpam *>(ipam_node->GetObject());
1048 : const std::string subnet_method =
1049 292 : boost::to_lower_copy(network_ipam->ipam_subnet_method());
1050 :
1051 292 : if (subnet_method == "flat-subnet") {
1052 0 : BuildVnIpamData(network_ipam->ipam_subnets(),
1053 : ipam_name, &vn_ipam);
1054 : } else {
1055 292 : BuildVnIpamData(subnets.ipam_subnets, ipam_name, &vn_ipam);
1056 : }
1057 :
1058 292 : VnIpamLinkData ipam_data;
1059 292 : ipam_data.oper_dhcp_options_.set_host_routes(subnets.host_routes.route);
1060 292 : vn_ipam_data.insert(VnData::VnIpamDataPair(ipam_name, ipam_data));
1061 292 : }
1062 : }
1063 :
1064 1817 : if (adj_node->table() == agent()->cfg()->cfg_vn_table()) {
1065 0 : if (agent()->fabric_vn_name() == adj_node->name()) {
1066 0 : underlay_forwarding = true;
1067 : }
1068 : }
1069 :
1070 1817 : if (strcmp(adj_node->table()->Typename(),
1071 1817 : "logical-router-virtual-network") == 0) {
1072 : autogen::LogicalRouterVirtualNetwork *lr_vn_node =
1073 0 : dynamic_cast<autogen::LogicalRouterVirtualNetwork *>
1074 0 : (adj_node->GetObject());
1075 0 : autogen::LogicalRouter *lr = NULL;
1076 : IFMapNode *lr_adj_node =
1077 0 : agent()->config_manager()->FindAdjacentIFMapNode(adj_node,
1078 : "logical-router");
1079 0 : if (lr_adj_node) {
1080 0 : lr = dynamic_cast<autogen::LogicalRouter *>(lr_adj_node->
1081 0 : GetObject());
1082 : }
1083 :
1084 0 : if (lr_vn_node && lr) {
1085 0 : autogen::IdPermsType id_perms = lr->id_perms();
1086 0 : CfgUuidSet(id_perms.uuid.uuid_mslong,
1087 : id_perms.uuid.uuid_lslong,
1088 : logical_router_uuid);
1089 : autogen::LogicalRouterVirtualNetworkType data =
1090 0 : lr_vn_node->data();
1091 0 : if (data.logical_router_virtual_network_type ==
1092 : "InternalVirtualNetwork")
1093 : {
1094 0 : vxlan_routing_vn = true;
1095 : }
1096 0 : }
1097 : }
1098 :
1099 3634 : if (adj_node->table() ==
1100 1817 : agent()->cfg()->cfg_multicast_policy_table()) {
1101 : MulticastPolicy *mcast_group = static_cast<MulticastPolicy *>
1102 0 : (adj_node->GetObject());
1103 0 : assert(mcast_group);
1104 0 : autogen::IdPermsType id_perms = mcast_group->id_perms();
1105 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1106 : mp_uuid);
1107 0 : mp_list.push_back(mp_uuid);
1108 0 : }
1109 :
1110 3634 : if (adj_node->table() ==
1111 1817 : agent()->cfg()->cfg_health_check_table()) {
1112 : autogen::ServiceHealthCheck *hc =
1113 0 : static_cast<autogen::ServiceHealthCheck *> (adj_node->GetObject());
1114 0 : assert(hc);
1115 0 : if (hc->properties().health_check_type.find("vn-ip-list") == std::string::npos)
1116 0 : continue;
1117 0 : autogen::IdPermsType id_perms = hc->id_perms();
1118 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1119 : health_check_uuid);
1120 0 : }
1121 : }
1122 :
1123 651 : uuid mirror_acl_uuid = agent()->mirror_cfg_table()->GetMirrorUuid(node->name());
1124 651 : std::sort(vn_ipam.begin(), vn_ipam.end());
1125 :
1126 : // Fetch VN forwarding Properties
1127 : bool enable_rpf;
1128 : bool flood_unknown_unicast;
1129 : bool mirror_destination;
1130 651 : bool pbb_evpn_enable = cfg->pbb_evpn_enable();
1131 651 : bool pbb_etree_enable = cfg->pbb_etree_enable();
1132 651 : bool layer2_control_word = cfg->layer2_control_word();
1133 651 : bool cfg_igmp_enable = cfg->igmp_enable();
1134 651 : uint32_t vn_max_flows = cfg->properties().max_flows;
1135 651 : bool mac_ip_learning_enable = cfg->mac_ip_learning_enable();
1136 : Agent::ForwardingMode forwarding_mode;
1137 651 : CfgForwardingFlags(node, &enable_rpf, &flood_unknown_unicast,
1138 : &forwarding_mode, &mirror_destination);
1139 651 : return new VnData(agent(), node, node->name(), acl_uuid, vrf_name,
1140 : mirror_acl_uuid, mirror_cfg_acl_uuid, vn_ipam,
1141 651 : vn_ipam_data, cfg->properties().vxlan_network_identifier,
1142 651 : GetCfgVnId(cfg), cfg->id_perms().enable, enable_rpf,
1143 : flood_unknown_unicast, forwarding_mode,
1144 : qos_config_uuid, mirror_destination, pbb_etree_enable,
1145 : pbb_evpn_enable, layer2_control_word, slo_list,
1146 : underlay_forwarding, vxlan_routing_vn,
1147 : logical_router_uuid, mp_list, cfg_igmp_enable,
1148 : vn_max_flows, mac_ip_learning_enable,
1149 1302 : health_check_uuid);
1150 651 : }
1151 :
1152 1225 : bool VnTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) {
1153 1225 : VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
1154 1225 : assert(cfg);
1155 1225 : autogen::IdPermsType id_perms = cfg->id_perms();
1156 1225 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
1157 1225 : return true;
1158 1225 : }
1159 :
1160 1225 : bool VnTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
1161 : const boost::uuids::uuid &u) {
1162 :
1163 1225 : assert(!u.is_nil());
1164 :
1165 1225 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
1166 196 : req.key.reset(new VnKey(u));
1167 196 : req.oper = DBRequest::DB_ENTRY_DELETE;
1168 196 : Enqueue(&req);
1169 196 : return false;
1170 : }
1171 :
1172 1029 : agent()->config_manager()->AddVnNode(node);
1173 1029 : return false;
1174 : }
1175 :
1176 654 : bool VnTable::ProcessConfig(IFMapNode *node, DBRequest &req,
1177 : const boost::uuids::uuid &u) {
1178 :
1179 654 : if (node->IsDeleted()) {
1180 3 : return false;
1181 : }
1182 :
1183 651 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1184 651 : req.key.reset(new VnKey(u));
1185 651 : req.data.reset(BuildData(node));
1186 651 : Enqueue(&req);
1187 651 : return false;
1188 : }
1189 :
1190 0 : void VnTable::AddVn(const boost::uuids::uuid &vn_uuid, const string &name,
1191 : const boost::uuids::uuid &acl_id, const string &vrf_name,
1192 : const std::vector<VnIpam> &ipam,
1193 : const VnData::VnIpamDataMap &vn_ipam_data, int vn_id,
1194 : int vxlan_id, bool admin_state, bool enable_rpf,
1195 : bool flood_unknown_unicast, bool pbb_etree_enable,
1196 : bool pbb_evpn_enable, bool layer2_control_word) {
1197 : using boost::uuids::nil_uuid;
1198 :
1199 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1200 0 : UuidList empty_list;
1201 0 : req.key.reset(new VnKey(vn_uuid));
1202 0 : bool mirror_destination = false;
1203 0 : VnData *data = new VnData(agent(), NULL, name, acl_id, vrf_name, nil_uuid(),
1204 0 : nil_uuid(), ipam, vn_ipam_data,
1205 : vxlan_id, vn_id, admin_state, enable_rpf,
1206 0 : flood_unknown_unicast, Agent::NONE, nil_uuid(),
1207 : mirror_destination, pbb_etree_enable,
1208 : pbb_evpn_enable, layer2_control_word, empty_list,
1209 0 : false, false, nil_uuid(), empty_list, false, 0,
1210 0 : false, nil_uuid());
1211 :
1212 0 : req.data.reset(data);
1213 0 : Enqueue(&req);
1214 0 : }
1215 :
1216 0 : void VnTable::DelVn(const boost::uuids::uuid &vn_uuid) {
1217 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1218 0 : req.key.reset(new VnKey(vn_uuid));
1219 0 : req.data.reset(NULL);
1220 0 : Enqueue(&req);
1221 0 : }
1222 :
1223 0 : void VnTable::ResyncReq(const boost::uuids::uuid &vn) {
1224 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1225 0 : VnKey *key = new VnKey(vn);
1226 0 : key->sub_op_ = AgentKey::RESYNC;
1227 0 : req.key.reset(key);
1228 0 : req.data.reset(NULL);
1229 0 : Enqueue(&req);
1230 0 : }
1231 :
1232 : /////////////////////////////////////////////////////////////////////////////
1233 : // Introspect routines
1234 : /////////////////////////////////////////////////////////////////////////////
1235 0 : bool VnEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
1236 0 : VnListResp *resp = static_cast<VnListResp *>(sresp);
1237 :
1238 0 : VnSandeshData data;
1239 0 : data.set_name(GetName());
1240 0 : data.set_uuid(UuidToString(GetUuid()));
1241 0 : data.set_vxlan_id(GetVxLanId());
1242 0 : data.set_config_vxlan_id(vxlan_id_);
1243 0 : data.set_vn_id(vnid_);
1244 0 : if (GetAcl()) {
1245 0 : data.set_acl_uuid(UuidToString(GetAcl()->GetUuid()));
1246 : } else {
1247 0 : data.set_acl_uuid("");
1248 : }
1249 :
1250 0 : if (GetVrf()) {
1251 0 : data.set_vrf_name(GetVrf()->GetName());
1252 : } else {
1253 0 : data.set_vrf_name("");
1254 : }
1255 :
1256 0 : if (GetMirrorAcl()) {
1257 0 : data.set_mirror_acl_uuid(UuidToString(GetMirrorAcl()->GetUuid()));
1258 : } else {
1259 0 : data.set_mirror_acl_uuid("");
1260 : }
1261 :
1262 0 : if (GetMirrorCfgAcl()) {
1263 0 : data.set_mirror_cfg_acl_uuid(UuidToString(GetMirrorCfgAcl()->GetUuid()));
1264 : } else {
1265 0 : data.set_mirror_cfg_acl_uuid("");
1266 : }
1267 :
1268 0 : std::vector<VnIpamData> vn_subnet_sandesh_list;
1269 0 : const std::vector<VnIpam> &vn_ipam = GetVnIpam();
1270 0 : for (unsigned int i = 0; i < vn_ipam.size(); ++i) {
1271 0 : VnIpamData entry;
1272 0 : entry.set_ip_prefix(vn_ipam[i].ip_prefix.to_string());
1273 0 : entry.set_prefix_len(vn_ipam[i].plen);
1274 0 : entry.set_gateway(vn_ipam[i].default_gw.to_string());
1275 0 : entry.set_ipam_name(vn_ipam[i].ipam_name);
1276 0 : entry.set_dhcp_enable(vn_ipam[i].dhcp_enable ? "true" : "false");
1277 0 : entry.set_dhcp_enable_v6(vn_ipam[i].dhcp_enable_v6 ? "true" : "false");
1278 0 : entry.set_dns_server(vn_ipam[i].dns_server.to_string());
1279 0 : vn_subnet_sandesh_list.push_back(entry);
1280 0 : }
1281 0 : data.set_ipam_data(vn_subnet_sandesh_list);
1282 :
1283 0 : std::vector<VnIpamHostRoutes> vn_ipam_host_routes_list;
1284 0 : for (VnData::VnIpamDataMap::const_iterator it = vn_ipam_data_.begin();
1285 0 : it != vn_ipam_data_.end(); ++it) {
1286 0 : VnIpamHostRoutes vn_ipam_host_routes;
1287 0 : vn_ipam_host_routes.ipam_name = it->first;
1288 : const std::vector<OperDhcpOptions::HostRoute> &host_routes =
1289 0 : it->second.oper_dhcp_options_.host_routes();
1290 0 : for (uint32_t i = 0; i < host_routes.size(); ++i) {
1291 0 : vn_ipam_host_routes.host_routes.push_back(
1292 0 : host_routes[i].ToString());
1293 : }
1294 0 : vn_ipam_host_routes_list.push_back(vn_ipam_host_routes);
1295 0 : }
1296 0 : data.set_ipam_host_routes(vn_ipam_host_routes_list);
1297 0 : data.set_ipv4_forwarding(layer3_forwarding());
1298 0 : data.set_layer2_forwarding(bridging());
1299 0 : data.set_bridging(bridging());
1300 0 : data.set_admin_state(admin_state());
1301 0 : data.set_enable_rpf(enable_rpf());
1302 0 : data.set_flood_unknown_unicast(flood_unknown_unicast());
1303 0 : data.set_pbb_etree_enabled(pbb_etree_enable());
1304 0 : data.set_layer2_control_word(layer2_control_word());
1305 0 : std::vector<SecurityLoggingObjectLink> slo_list;
1306 0 : UuidList::const_iterator sit = slo_list_.begin();
1307 0 : while (sit != slo_list_.end()) {
1308 0 : SecurityLoggingObjectLink slo_entry;
1309 0 : slo_entry.set_slo_uuid(to_string(*sit));
1310 0 : slo_list.push_back(slo_entry);
1311 0 : ++sit;
1312 0 : }
1313 0 : data.set_slo_list(slo_list);
1314 : std::vector<VnSandeshData> &list =
1315 0 : const_cast<std::vector<VnSandeshData>&>(resp->get_vn_list());
1316 0 : std::vector<MulticastPolicyLink> mp_list;
1317 0 : UuidList::const_iterator mpit = mp_list_.begin();
1318 0 : while (mpit != mp_list_.end()) {
1319 0 : MulticastPolicyLink mp_entry;
1320 0 : mp_entry.set_mp_uuid(to_string(*mpit));
1321 0 : mp_list.push_back(mp_entry);
1322 0 : ++mpit;
1323 0 : }
1324 0 : data.set_mp_list(mp_list);
1325 0 : data.set_cfg_igmp_enable(cfg_igmp_enable());
1326 0 : data.set_max_flows(vn_max_flows());
1327 0 : data.set_mac_ip_learning_enable(mac_ip_learning_enable());
1328 0 : data.set_health_check_uuid(to_string(health_check_uuid()));
1329 0 : data.set_logical_router_uuid(UuidToString(logical_router_uuid()));
1330 0 : data.set_vxlan_routing_vn(vxlan_routing_vn());
1331 :
1332 0 : list.push_back(data);
1333 0 : return true;
1334 0 : }
1335 :
1336 847 : void VnEntry::SendObjectLog(SandeshTraceBufferPtr buf,
1337 : AgentLogEvent::type event) const {
1338 1694 : VnObjectLogInfo info;
1339 847 : string str;
1340 847 : string vn_uuid = UuidToString(GetUuid());
1341 847 : const AclDBEntry *acl = GetAcl();
1342 847 : const AclDBEntry *mirror_acl = GetMirrorAcl();
1343 847 : const AclDBEntry *mirror_cfg_acl = GetMirrorCfgAcl();
1344 847 : string acl_uuid;
1345 847 : string mirror_acl_uuid;
1346 847 : string mirror_cfg_acl_uuid;
1347 :
1348 847 : info.set_uuid(vn_uuid);
1349 847 : info.set_name(GetName());
1350 847 : switch (event) {
1351 69 : case AgentLogEvent::ADD:
1352 69 : str.assign("Addition ");
1353 69 : break;
1354 196 : case AgentLogEvent::DEL:
1355 196 : str.assign("Deletion ");
1356 196 : info.set_event(str);
1357 196 : VN_OBJECT_LOG_LOG("AgentVn", SandeshLevel::SYS_INFO, info);
1358 196 : return;
1359 582 : case AgentLogEvent::CHANGE:
1360 582 : str.assign("Modification ");
1361 582 : break;
1362 0 : default:
1363 0 : str.assign("");
1364 0 : break;
1365 : }
1366 :
1367 651 : info.set_event(str);
1368 651 : if (acl) {
1369 2 : acl_uuid.assign(UuidToString(acl->GetUuid()));
1370 2 : info.set_acl_uuid(acl_uuid);
1371 : }
1372 651 : if (mirror_acl) {
1373 0 : mirror_acl_uuid.assign(UuidToString(mirror_acl->GetUuid()));
1374 0 : info.set_mirror_acl_uuid(mirror_acl_uuid);
1375 : }
1376 651 : if (mirror_cfg_acl) {
1377 0 : mirror_cfg_acl_uuid.assign(UuidToString(mirror_cfg_acl->GetUuid()));
1378 0 : info.set_mirror_cfg_acl_uuid(mirror_cfg_acl_uuid);
1379 : }
1380 651 : VrfEntry *vrf = GetVrf();
1381 651 : if (vrf) {
1382 496 : info.set_vrf(vrf->GetName());
1383 : }
1384 1302 : vector<VnObjectLogIpam> ipam_list;
1385 651 : VnObjectLogIpam sandesh_ipam;
1386 651 : vector<VnIpam>::const_iterator it = ipam_.begin();
1387 1024 : while (it != ipam_.end()) {
1388 373 : VnIpam ipam = *it;
1389 373 : sandesh_ipam.set_ip_prefix(ipam.ip_prefix.to_string());
1390 373 : sandesh_ipam.set_prefix_len(ipam.plen);
1391 373 : sandesh_ipam.set_gateway_ip(ipam.default_gw.to_string());
1392 373 : sandesh_ipam.set_ipam_name(ipam.ipam_name);
1393 373 : sandesh_ipam.set_dhcp_enable(ipam.dhcp_enable ? "true" : "false");
1394 373 : sandesh_ipam.set_dhcp_enable_v6(ipam.dhcp_enable_v6 ? "true" : "false");
1395 373 : sandesh_ipam.set_dns_server(ipam.dns_server.to_string());
1396 373 : ipam_list.push_back(sandesh_ipam);
1397 373 : ++it;
1398 373 : }
1399 :
1400 651 : if (ipam_list.size()) {
1401 292 : info.set_ipam_list(ipam_list);
1402 : }
1403 651 : info.set_bridging(bridging());
1404 651 : info.set_oper_vxlan_id(GetOperVxlanId());
1405 651 : info.set_ipv4_forwarding(layer3_forwarding());
1406 651 : info.set_admin_state(admin_state());
1407 651 : info.set_logical_router_uuid(UuidToString(logical_router_uuid()));
1408 651 : info.set_vxlan_routing_vn(vxlan_routing_vn());
1409 651 : VN_OBJECT_LOG_LOG("AgentVn", SandeshLevel::SYS_INFO, info);
1410 651 : VN_OBJECT_TRACE_TRACE(buf, info);
1411 1827 : }
1412 :
1413 0 : void VnListReq::HandleRequest() const {
1414 0 : AgentSandeshPtr sand(new AgentVnSandesh(context(), get_name(), get_uuid(),
1415 0 : get_vxlan_id(), get_ipam_name()));
1416 0 : sand->DoSandesh(sand);
1417 0 : }
1418 :
1419 0 : AgentSandeshPtr VnTable::GetAgentSandesh(const AgentSandeshArguments *args,
1420 : const std::string &context) {
1421 : return AgentSandeshPtr
1422 0 : (new AgentVnSandesh(context, args->GetString("name"),
1423 0 : args->GetString("uuid"),
1424 0 : args->GetString("vxlan_id"),
1425 0 : args->GetString("ipam_name")));
1426 : }
1427 :
1428 : /////////////////////////////////////////////////////////////////////////////
1429 : // DomainConfig routines
1430 : /////////////////////////////////////////////////////////////////////////////
1431 2 : DomainConfig::DomainConfig(Agent *agent) {
1432 2 : }
1433 :
1434 4 : DomainConfig::~DomainConfig() {
1435 4 : }
1436 :
1437 2 : void DomainConfig::Init() {
1438 2 : }
1439 :
1440 2 : void DomainConfig::Terminate() {
1441 2 : }
1442 :
1443 2 : void DomainConfig::RegisterIpamCb(Callback cb) {
1444 2 : ipam_callback_.push_back(cb);
1445 2 : }
1446 :
1447 2 : void DomainConfig::RegisterVdnsCb(Callback cb) {
1448 2 : vdns_callback_.push_back(cb);
1449 2 : }
1450 :
1451 : // Callback is invoked only if there is change in IPAM properties.
1452 : // In case of change in a link with IPAM, callback is not invoked.
1453 91 : void DomainConfig::IpamDelete(IFMapNode *node) {
1454 91 : CallIpamCb(node);
1455 91 : ipam_config_.erase(node->name());
1456 91 : return;
1457 : }
1458 :
1459 36 : void DomainConfig::IpamAddChange(IFMapNode *node) {
1460 : autogen::NetworkIpam *network_ipam =
1461 36 : static_cast <autogen::NetworkIpam *> (node->GetObject());
1462 36 : assert(network_ipam);
1463 :
1464 36 : bool change = false;
1465 36 : IpamDomainConfigMap::iterator it = ipam_config_.find(node->name());
1466 36 : if (it != ipam_config_.end()) {
1467 11 : if (IpamChanged(it->second, network_ipam->mgmt())) {
1468 0 : it->second = network_ipam->mgmt();
1469 0 : change = true;
1470 : }
1471 : } else {
1472 25 : ipam_config_.insert(IpamDomainConfigPair(node->name(),
1473 25 : network_ipam->mgmt()));
1474 25 : change = true;
1475 : }
1476 36 : if (change)
1477 25 : CallIpamCb(node);
1478 36 : }
1479 :
1480 0 : void DomainConfig::VDnsDelete(IFMapNode *node) {
1481 0 : CallVdnsCb(node);
1482 0 : vdns_config_.erase(node->name());
1483 0 : return;
1484 : }
1485 :
1486 0 : void DomainConfig::VDnsAddChange(IFMapNode *node) {
1487 : autogen::VirtualDns *virtual_dns =
1488 0 : static_cast <autogen::VirtualDns *> (node->GetObject());
1489 0 : assert(virtual_dns);
1490 :
1491 0 : VdnsDomainConfigMap::iterator it = vdns_config_.find(node->name());
1492 0 : if (it != vdns_config_.end()) {
1493 0 : it->second = virtual_dns->data();
1494 : } else {
1495 0 : vdns_config_.insert(VdnsDomainConfigPair(node->name(),
1496 0 : virtual_dns->data()));
1497 : }
1498 0 : CallVdnsCb(node);
1499 0 : }
1500 :
1501 116 : void DomainConfig::CallIpamCb(IFMapNode *node) {
1502 232 : for (unsigned int i = 0; i < ipam_callback_.size(); ++i) {
1503 116 : ipam_callback_[i](node);
1504 : }
1505 116 : }
1506 :
1507 0 : void DomainConfig::CallVdnsCb(IFMapNode *node) {
1508 0 : for (unsigned int i = 0; i < vdns_callback_.size(); ++i) {
1509 0 : vdns_callback_[i](node);
1510 : }
1511 0 : }
1512 :
1513 11 : bool DomainConfig::IpamChanged(const autogen::IpamType &old,
1514 : const autogen::IpamType &cur) const {
1515 22 : if (old.ipam_method != cur.ipam_method ||
1516 11 : old.ipam_dns_method != cur.ipam_dns_method)
1517 0 : return true;
1518 :
1519 22 : if ((old.ipam_dns_server.virtual_dns_server_name !=
1520 22 : cur.ipam_dns_server.virtual_dns_server_name) ||
1521 11 : (old.ipam_dns_server.tenant_dns_server_address.ip_address !=
1522 11 : cur.ipam_dns_server.tenant_dns_server_address.ip_address))
1523 0 : return true;
1524 :
1525 22 : if (old.cidr_block.ip_prefix != cur.cidr_block.ip_prefix ||
1526 11 : old.cidr_block.ip_prefix_len != cur.cidr_block.ip_prefix_len)
1527 0 : return true;
1528 :
1529 22 : if (old.dhcp_option_list.dhcp_option.size() !=
1530 11 : cur.dhcp_option_list.dhcp_option.size())
1531 0 : return true;
1532 :
1533 11 : for (uint32_t i = 0; i < old.dhcp_option_list.dhcp_option.size(); i++) {
1534 0 : if ((old.dhcp_option_list.dhcp_option[i].dhcp_option_name !=
1535 0 : cur.dhcp_option_list.dhcp_option[i].dhcp_option_name) ||
1536 0 : (old.dhcp_option_list.dhcp_option[i].dhcp_option_value !=
1537 0 : cur.dhcp_option_list.dhcp_option[i].dhcp_option_value) ||
1538 0 : (old.dhcp_option_list.dhcp_option[i].dhcp_option_value_bytes !=
1539 0 : cur.dhcp_option_list.dhcp_option[i].dhcp_option_value_bytes))
1540 0 : return true;
1541 : }
1542 :
1543 11 : if (old.host_routes.route.size() != cur.host_routes.route.size())
1544 0 : return true;
1545 :
1546 11 : for (uint32_t i = 0; i < old.host_routes.route.size(); i++) {
1547 0 : if ((old.host_routes.route[i].prefix !=
1548 0 : cur.host_routes.route[i].prefix) ||
1549 0 : (old.host_routes.route[i].next_hop !=
1550 0 : cur.host_routes.route[i].next_hop) ||
1551 0 : (old.host_routes.route[i].next_hop_type !=
1552 0 : cur.host_routes.route[i].next_hop_type) ||
1553 0 : (old.host_routes.route[i].community_attributes.community_attribute !=
1554 0 : cur.host_routes.route[i].community_attributes.community_attribute))
1555 0 : return true;
1556 : }
1557 :
1558 11 : return false;
1559 : }
1560 :
1561 1022 : bool DomainConfig::GetIpam(const std::string &name, autogen::IpamType *ipam) {
1562 1022 : IpamDomainConfigMap::iterator it = ipam_config_.find(name);
1563 1022 : if (it == ipam_config_.end())
1564 0 : return false;
1565 1022 : *ipam = it->second;
1566 1022 : return true;
1567 : }
1568 :
1569 0 : bool DomainConfig::GetVDns(const std::string &vdns,
1570 : autogen::VirtualDnsType *vdns_type) {
1571 0 : VdnsDomainConfigMap::iterator it = vdns_config_.find(vdns);
1572 0 : if (it == vdns_config_.end())
1573 0 : return false;
1574 0 : *vdns_type = it->second;
1575 0 : return true;
1576 : }
1577 :
1578 : /////////////////////////////////////////////////////////////////////////////
1579 : // OperNetworkIpam routines
1580 : /////////////////////////////////////////////////////////////////////////////
1581 2 : OperNetworkIpam::OperNetworkIpam(Agent *agent, DomainConfig *domain_config) :
1582 2 : OperIFMapTable(agent), domain_config_(domain_config) {
1583 2 : }
1584 :
1585 4 : OperNetworkIpam::~OperNetworkIpam() {
1586 4 : }
1587 :
1588 91 : void OperNetworkIpam::ConfigDelete(IFMapNode *node) {
1589 91 : domain_config_->IpamDelete(node);
1590 91 : }
1591 :
1592 36 : void OperNetworkIpam::ConfigAddChange(IFMapNode *node) {
1593 36 : domain_config_->IpamAddChange(node);
1594 36 : }
1595 :
1596 98 : void OperNetworkIpam::ConfigManagerEnqueue(IFMapNode *node) {
1597 98 : agent()->config_manager()->AddNetworkIpamNode(node);
1598 98 : }
1599 :
1600 2 : OperVirtualDns::OperVirtualDns(Agent *agent, DomainConfig *domain_config) :
1601 2 : OperIFMapTable(agent), domain_config_(domain_config) {
1602 2 : }
1603 :
1604 4 : OperVirtualDns::~OperVirtualDns() {
1605 4 : }
1606 :
1607 0 : void OperVirtualDns::ConfigDelete(IFMapNode *node) {
1608 0 : domain_config_->VDnsDelete(node);
1609 0 : }
1610 :
1611 0 : void OperVirtualDns::ConfigAddChange(IFMapNode *node) {
1612 0 : domain_config_->VDnsAddChange(node);
1613 0 : }
1614 :
1615 0 : void OperVirtualDns::ConfigManagerEnqueue(IFMapNode *node) {
1616 0 : agent()->config_manager()->AddVirtualDnsNode(node);
1617 0 : }
|