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