Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <cmn/agent_cmn.h>
6 : #include <init/agent_param.h>
7 : #include <base/address_util.h>
8 : #include <oper/operdb_init.h>
9 : #include <oper/route_common.h>
10 : #include <oper/vm.h>
11 : #include <oper/vn.h>
12 : #include <oper/vrf.h>
13 : #include <oper/nexthop.h>
14 : #include <oper/mpls.h>
15 : #include <oper/mirror_table.h>
16 : #include <oper/metadata_ip.h>
17 : #include <oper/interface_common.h>
18 : #include <oper/health_check.h>
19 : #include <oper/vrf_assign.h>
20 : #include <oper/vxlan.h>
21 : #include <oper/oper_dhcp_options.h>
22 : #include <oper/physical_device_vn.h>
23 : #include <oper/global_vrouter.h>
24 : #include <oper/qos_config.h>
25 : #include <oper/bridge_domain.h>
26 : #include <oper/sg.h>
27 : #include <oper/bgp_as_service.h>
28 :
29 : #include <filter/acl.h>
30 : #include <port_ipc/port_ipc_handler.h>
31 : #include <port_ipc/port_subscribe_table.h>
32 : #include <resource_manager/resource_manager.h>
33 : #include <resource_manager/resource_table.h>
34 : #include <resource_manager/mpls_index.h>
35 :
36 : #include <vrouter/ksync/ksync_init.h>
37 : #include <vrouter/ksync/vnswif_listener_base.h>
38 :
39 : using namespace std;
40 : using namespace boost::uuids;
41 : using namespace autogen;
42 :
43 : static IpAddress ipv4_empty_addr = IpAddress::from_string("0.0.0.0");
44 : static IpAddress ipv6_empty_addr = IpAddress::from_string("0::0");
45 : static IpAddress ipv4_max_addr = IpAddress::from_string("255.255.255.255");
46 : static IpAddress ipv6_max_addr =
47 : IpAddress::from_string("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF");
48 :
49 : /////////////////////////////////////////////////////////////////////////////
50 : // Routines to manage VmiToPhysicalDeviceVnTree
51 : /////////////////////////////////////////////////////////////////////////////
52 16 : VmiToPhysicalDeviceVnData::VmiToPhysicalDeviceVnData
53 16 : (const boost::uuids::uuid &dev, const boost::uuids::uuid &vn) :
54 16 : dev_(dev), vn_(vn) {
55 16 : }
56 :
57 48 : VmiToPhysicalDeviceVnData::~VmiToPhysicalDeviceVnData() {
58 48 : }
59 :
60 70 : void InterfaceTable::UpdatePhysicalDeviceVnEntry(const boost::uuids::uuid &vmi,
61 : boost::uuids::uuid &dev,
62 : boost::uuids::uuid &vn,
63 : IFMapNode *vn_node) {
64 : VmiToPhysicalDeviceVnTree::iterator iter =
65 70 : vmi_to_physical_device_vn_tree_.find(vmi);
66 70 : if (iter == vmi_to_physical_device_vn_tree_.end()) {
67 : vmi_to_physical_device_vn_tree_.insert
68 16 : (make_pair(vmi,VmiToPhysicalDeviceVnData(nil_uuid(), nil_uuid())));
69 16 : iter = vmi_to_physical_device_vn_tree_.find(vmi);
70 : }
71 :
72 70 : if (iter->second.dev_ != dev || iter->second.vn_ != vn) {
73 : agent()->physical_device_vn_table()->DeleteConfigEntry
74 24 : (vmi, iter->second.dev_, iter->second.vn_);
75 : }
76 :
77 70 : iter->second.dev_ = dev;
78 70 : iter->second.vn_ = vn;
79 70 : agent()->physical_device_vn_table()->AddConfigEntry(vmi, dev, vn);
80 70 : }
81 :
82 24 : void InterfaceTable::DelPhysicalDeviceVnEntry(const boost::uuids::uuid &vmi) {
83 : VmiToPhysicalDeviceVnTree::iterator iter =
84 24 : vmi_to_physical_device_vn_tree_.find(vmi);
85 24 : if (iter == vmi_to_physical_device_vn_tree_.end())
86 10 : return;
87 :
88 : agent()->physical_device_vn_table()->DeleteConfigEntry
89 14 : (vmi, iter->second.dev_, iter->second.vn_);
90 14 : vmi_to_physical_device_vn_tree_.erase(iter);
91 : }
92 :
93 : /////////////////////////////////////////////////////////////////////////////
94 : // VM Port active status related methods
95 : /////////////////////////////////////////////////////////////////////////////
96 : // Does the VMInterface need a physical device to be present
97 432 : bool VmInterface::NeedDevice() const {
98 432 : bool ret = true;
99 :
100 432 : if (device_type_ == TOR)
101 20 : ret = false;
102 :
103 432 : if (device_type_ == VM_VLAN_ON_VMI)
104 0 : ret = false;
105 :
106 432 : if (vmi_type_ != VHOST && subnet_.is_unspecified() == false) {
107 0 : ret = false;
108 : }
109 :
110 432 : if (transport_ != TRANSPORT_ETHERNET) {
111 20 : ret = false;
112 : }
113 :
114 432 : if (rx_vlan_id_ != VmInterface::kInvalidVlanId) {
115 0 : ret = false;
116 : } else {
117 : // Sanity check. rx_vlan_id is set, make sure tx_vlan_id is also set
118 432 : assert(tx_vlan_id_ == VmInterface::kInvalidVlanId);
119 : }
120 :
121 432 : return ret;
122 : }
123 :
124 417 : bool VmInterface::NeedOsStateWithoutDevice() const {
125 : /* For TRANSPORT_PMD (in dpdk mode) interfaces, the link state is updated
126 : * as part of netlink message sent by vrouter to agent. This state is
127 : * updated in os_oper_state_ field */
128 417 : if (transport_ == TRANSPORT_PMD) {
129 0 : return true;
130 : }
131 417 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
132 417 : if (table) {
133 415 : return NeedDefaultOsOperStateDisabled(table->agent());
134 : }
135 2 : return false;
136 : }
137 :
138 21 : void VmInterface::GetOsParams(Agent *agent) {
139 21 : if (NeedDevice() || NeedOsStateWithoutDevice()) {
140 15 : Interface::GetOsParams(agent);
141 15 : return;
142 : }
143 :
144 6 : os_params_.os_index_ = Interface::kInvalidIndex;
145 6 : os_params_.mac_ = agent->vrrp_mac();
146 : /* In VmWare mode, the default os_oper_state of VMI is false. It needs to be
147 : * explicitly enabled via REST request to agent. This needs to be done
148 : * only for interfaces which are not of transport_ TRANSPORT_ETHERNET */
149 6 : if (!NeedDefaultOsOperStateDisabled(agent)) {
150 6 : os_params_.os_oper_state_ = true;
151 : }
152 : }
153 :
154 : // A VM Interface is L3 active under following conditions,
155 : // - If interface is deleted, it is inactive
156 : // - VN, VRF are set
157 : // - If sub_interface VMIs, parent_ should be set
158 : // (We dont track parent_ and activate sub-interfaces. So, we only check
159 : // parent_ is present and not necessarily active)
160 : // - For non-VMWARE hypervisors,
161 : // The tap interface must be created. This is verified by os_index_
162 : // - MAC address set for the interface
163 593 : bool VmInterface::IsActive() const {
164 593 : if (IsDeleted()) {
165 0 : return false;
166 : }
167 :
168 593 : if (!admin_state_) {
169 0 : return false;
170 : }
171 :
172 : // If sub_interface VMIs, parent_vmi_ should be set
173 : // (We dont track parent_ and activate sub-interfaces. So, we only check
174 : // paremt_vmi is present and not necessarily active)
175 : // Check if parent is not active set the SubInterface also not active
176 593 : const VmInterface *parentIntf = static_cast<const VmInterface *>(parent());
177 593 : if (device_type_ == VM_VLAN_ON_VMI) {
178 0 : if (parentIntf == NULL)
179 0 : return false;
180 0 : else if (parentIntf->IsActive() == false) {
181 0 : return false;
182 : }
183 : }
184 :
185 593 : if (device_type_ == REMOTE_VM_VLAN_ON_VMI) {
186 0 : if (tx_vlan_id_ == VmInterface::kInvalidVlanId ||
187 0 : rx_vlan_id_ == VmInterface::kInvalidVlanId ||
188 0 : parent_.get() == NULL)
189 0 : return false;
190 : }
191 :
192 593 : if (vmi_type_ == VHOST) {
193 : //In case of vhost interface, upon interface
194 : //addition we dont have corresponding VN, hence
195 : //ignore VN name check for ip active
196 43 : if (vrf_.get() == NULL) {
197 0 : return false;
198 : }
199 550 : } else if ((vn_.get() == NULL) || (vrf_.get() == NULL)) {
200 182 : return false;
201 : }
202 :
203 411 : if (vn_.get() && !vn_.get()->admin_state()) {
204 0 : return false;
205 : }
206 :
207 411 : if (NeedOsStateWithoutDevice() && os_oper_state() == false) {
208 : VnswInterfaceListener *vnswif =
209 0 : agent()->ksync()->vnsw_interface_listner();
210 0 : bool link_status = vnswif->IsHostLinkStateUp(name());
211 0 : if ((transport_ == TRANSPORT_PMD) && link_status &&
212 0 : (os_index() != Interface::kInvalidIndex) && (!agent()->test_mode())) {
213 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
214 0 : req.key.reset(new VmInterfaceKey(AgentKey::RESYNC, GetUuid(),
215 0 : name()));
216 0 : req.data.reset(new VmInterfaceOsOperStateData(link_status));
217 0 : agent()->interface_table()->Enqueue(&req);
218 0 : return true;
219 0 : }
220 0 : return false;
221 : }
222 :
223 411 : if (NeedDevice() == false) {
224 14 : return true;
225 : }
226 :
227 397 : if (os_index() == kInvalidIndex)
228 0 : return false;
229 :
230 397 : if (os_oper_state() == false)
231 0 : return false;
232 :
233 397 : return mac_set_;
234 : }
235 :
236 60 : bool VmInterface::IsMetaDataIPActive() const {
237 60 : if (vmi_type_ == VHOST) {
238 3 : return IsActive();
239 : }
240 :
241 57 : if (!layer3_forwarding()) {
242 17 : return false;
243 : }
244 :
245 40 : if (primary_ip6_addr_.is_unspecified()) {
246 2 : if (subnet_.is_unspecified() && primary_ip_addr_.to_ulong() == 0) {
247 0 : return false;
248 : }
249 :
250 2 : if (subnet_.is_unspecified() == false && parent_ == NULL) {
251 0 : return false;
252 : }
253 : }
254 :
255 40 : return IsActive();
256 : }
257 :
258 60 : bool VmInterface::IsMetaDataL2Active() const {
259 60 : if (!bridging()) {
260 20 : return false;
261 : }
262 :
263 40 : return IsActive();
264 : }
265 :
266 60 : bool VmInterface::IsIpv4Active() const {
267 60 : if (vmi_type_ == VHOST) {
268 3 : return IsActive();
269 : }
270 :
271 57 : if (!layer3_forwarding()) {
272 17 : return false;
273 : }
274 :
275 40 : if (subnet_.is_unspecified() && primary_ip_addr_.to_ulong() == 0) {
276 0 : return false;
277 : }
278 :
279 40 : if (subnet_.is_unspecified() == false && parent_ == NULL) {
280 0 : return false;
281 : }
282 :
283 40 : if (!is_hc_active_) {
284 0 : return false;
285 : }
286 :
287 40 : return IsActive();
288 : }
289 :
290 60 : bool VmInterface::IsIpv6Active() const {
291 60 : if (vmi_type_ == VHOST) {
292 3 : return IsActive();
293 : }
294 :
295 57 : if (!layer3_forwarding() || (primary_ip6_addr_.is_unspecified())) {
296 19 : return false;
297 : }
298 :
299 38 : if (!is_hc_active_) {
300 0 : return false;
301 : }
302 :
303 38 : return IsActive();
304 : }
305 :
306 128 : bool VmInterface::IsL2Active() const {
307 128 : if (vmi_type_ == VHOST) {
308 6 : return IsActive();
309 : }
310 :
311 122 : if (!bridging()) {
312 31 : return false;
313 : }
314 :
315 91 : if (!is_hc_active_) {
316 0 : return false;
317 : }
318 :
319 91 : return IsActive();
320 : }
321 :
322 : /////////////////////////////////////////////////////////////////////////////
323 : // Path preference utility methods
324 : /////////////////////////////////////////////////////////////////////////////
325 : // Set path-preference information for the route
326 108 : void VmInterface::SetPathPreference(PathPreference *pref, bool ecmp,
327 : const IpAddress &dependent_ip) const {
328 108 : pref->set_ecmp(ecmp);
329 108 : if (local_preference_ != 0) {
330 0 : pref->set_static_preference(true);
331 0 : pref->set_preference(local_preference_);
332 108 : } else if (ecmp == true) {
333 2 : pref->set_preference(PathPreference::HIGH);
334 : }
335 108 : pref->set_dependent_ip(dependent_ip);
336 108 : pref->set_vrf(vrf()->GetName());
337 108 : }
338 :
339 0 : void VmInterface::SetServiceVlanPathPreference(PathPreference *pref,
340 : const IpAddress &service_ip) const {
341 :
342 0 : bool ecmp_mode = false;
343 0 : IpAddress dependent_ip;
344 :
345 : //Logic for setting ecmp and tracking IP on Service chain route
346 : //Service vlan route can be active when interface is either
347 : //IPV4 active or IPV6 active, hence we have to consider both
348 : //IPV6 and IPV4 IP
349 : //If Service vlan is for Ipv4 route, then priority is as below
350 : //1> Service IP for v4
351 : //3> Primary IP for v4
352 0 : if (service_ip.is_v4()) {
353 0 : if (service_ip_ != Ip4Address(0)) {
354 0 : dependent_ip = service_ip_;
355 0 : ecmp_mode = service_ip_ecmp_;
356 : } else {
357 0 : dependent_ip = primary_ip_addr_;
358 0 : ecmp_mode = ecmp_;
359 : }
360 : }
361 :
362 : //If Service vlan is for Ipv6 route, then priority is as below
363 : //1> Service IP for v6
364 : //3> Primary IP for v6
365 0 : if (service_ip.is_v6()) {
366 0 : if (service_ip6_ != Ip6Address()) {
367 0 : dependent_ip = service_ip6_;
368 0 : ecmp_mode = service_ip_ecmp6_;
369 : } else {
370 0 : dependent_ip = primary_ip6_addr_;
371 0 : ecmp_mode = ecmp6_;
372 : }
373 : }
374 :
375 0 : pref->set_ecmp(ecmp_mode);
376 0 : if (local_preference_ != 0) {
377 0 : pref->set_static_preference(true);
378 0 : pref->set_preference(local_preference_);
379 0 : } else if (ecmp_mode == true) {
380 0 : pref->set_preference(PathPreference::HIGH);
381 : }
382 :
383 0 : pref->set_dependent_ip(dependent_ip);
384 0 : pref->set_vrf(vrf()->GetName());
385 0 : }
386 :
387 29 : void VmInterface::CopyEcmpLoadBalance(EcmpLoadBalance &ecmp_load_balance) {
388 29 : if (ecmp_load_balance_.use_global_vrouter() == false)
389 0 : return ecmp_load_balance.Copy(ecmp_load_balance_);
390 29 : return ecmp_load_balance.Copy(agent()->oper_db()->global_vrouter()->
391 29 : ecmp_load_balance());
392 : }
393 :
394 : /////////////////////////////////////////////////////////////////////////////
395 : // Route utility methods
396 : /////////////////////////////////////////////////////////////////////////////
397 :
398 : // Add EVPN route of type <ip, mac>
399 55 : void VmInterface::AddL2InterfaceRoute(const IpAddress &ip,
400 : const MacAddress &mac,
401 : const IpAddress &dependent_ip) const {
402 55 : assert(peer_.get());
403 : EvpnAgentRouteTable *table =
404 55 : static_cast<EvpnAgentRouteTable *>(vrf_->GetEvpnRouteTable());
405 :
406 55 : SecurityGroupList sg_id_list;
407 55 : CopySgIdList(&sg_id_list);
408 :
409 55 : TagList tag_list;
410 55 : CopyTagIdList(&tag_list);
411 :
412 55 : PathPreference path_preference;
413 55 : SetPathPreference(&path_preference, false, dependent_ip);
414 :
415 55 : uint32_t label = l2_label_;
416 55 : if (pbb_interface()) {
417 0 : label = GetPbbLabel();
418 : }
419 :
420 55 : std::string vn_name = Agent::NullString();
421 55 : if (vn() != NULL) {
422 52 : vn_name = vn()->GetName();
423 : }
424 :
425 110 : table->AddLocalVmRoute(peer_.get(), vrf_->GetName(), mac, this, ip,
426 : label, vn_name, sg_id_list,
427 : tag_list, path_preference,
428 55 : ethernet_tag_, etree_leaf_, name());
429 55 : }
430 :
431 : // Delete EVPN route
432 27 : void VmInterface::DeleteL2InterfaceRoute(const VrfEntry *vrf,
433 : uint32_t ethernet_tag,
434 : const IpAddress &ip,
435 : const MacAddress &mac) const {
436 : EvpnAgentRouteTable *table =
437 27 : static_cast<EvpnAgentRouteTable *>(vrf->GetEvpnRouteTable());
438 27 : if (table == NULL)
439 0 : return;
440 :
441 27 : table->DelLocalVmRoute(peer_.get(), vrf->GetName(), mac, this,
442 : ip, ethernet_tag);
443 : }
444 :
445 : //Add a route for VM port
446 : //If ECMP route, add new composite NH and mpls label for same
447 29 : void VmInterface::AddRoute(const std::string &vrf_name, const IpAddress &addr,
448 : uint32_t plen, const std::string &dest_vn,
449 : bool force_policy, bool ecmp, bool is_local,
450 : bool is_health_check_service,
451 : const IpAddress &service_ip,
452 : const IpAddress &dependent_rt,
453 : const CommunityList &communities, uint32_t label,
454 : const std::string &intf_route_type,
455 : bool is_learnt_route) {
456 :
457 29 : SecurityGroupList sg_id_list;
458 29 : CopySgIdList(&sg_id_list);
459 :
460 29 : TagList tag_list;
461 29 : CopyTagIdList(&tag_list);
462 :
463 29 : PathPreference path_preference;
464 29 : SetPathPreference(&path_preference, ecmp, dependent_rt);
465 :
466 29 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
467 29 : bool native_encap = false;
468 29 : VrfEntry *vrf = table->FindVrfRef(vrf_name);
469 58 : if (addr.is_v4() &&
470 58 : vrf && vrf->forwarding_vrf() == table->agent()->fabric_vrf()) {
471 3 : native_encap = true;
472 : }
473 :
474 29 : VnListType vn_list;
475 29 : vn_list.insert(dest_vn);
476 29 : EcmpLoadBalance ecmp_load_balance;
477 29 : CopyEcmpLoadBalance(ecmp_load_balance);
478 : InetUnicastAgentRouteTable::AddLocalVmRoute
479 29 : (peer_.get(), vrf_name, addr, plen, GetUuid(), vn_list, label,
480 : sg_id_list, tag_list, communities, force_policy, path_preference,
481 : service_ip, ecmp_load_balance, is_local, is_health_check_service,
482 : name(), native_encap, intf_route_type, is_learnt_route);
483 58 : return;
484 29 : }
485 :
486 18 : void VmInterface::DeleteRoute(const std::string &vrf_name,
487 : const IpAddress &addr, uint32_t plen) {
488 18 : InetUnicastAgentRouteTable::Delete(peer_.get(), vrf_name, addr, plen);
489 18 : return;
490 : }
491 :
492 : /////////////////////////////////////////////////////////////////////////////
493 : // Utility methods
494 : /////////////////////////////////////////////////////////////////////////////
495 : // DHCP options applicable to the Interface
496 0 : bool VmInterface::GetInterfaceDhcpOptions
497 : (std::vector<autogen::DhcpOptionType> *options) const {
498 0 : if (oper_dhcp_options().are_dhcp_options_set()) {
499 0 : *options = oper_dhcp_options().dhcp_options();
500 0 : return true;
501 : }
502 :
503 0 : return false;
504 : }
505 :
506 : // DHCP options applicable to the Subnet to which the interface belongs
507 0 : bool VmInterface::GetSubnetDhcpOptions
508 : (std::vector<autogen::DhcpOptionType> *options, bool ipv6) const {
509 0 : if (vn()) {
510 0 : const std::vector<VnIpam> &vn_ipam = vn()->GetVnIpam();
511 : uint32_t index;
512 0 : for (index = 0; index < vn_ipam.size(); ++index) {
513 0 : if (!ipv6 && vn_ipam[index].IsSubnetMember(primary_ip_addr())) {
514 0 : break;
515 : }
516 0 : if (ipv6 && vn_ipam[index].IsSubnetMember(primary_ip6_addr())) {
517 0 : break;
518 : }
519 : }
520 0 : if (index < vn_ipam.size() &&
521 0 : vn_ipam[index].oper_dhcp_options.are_dhcp_options_set()) {
522 0 : *options = vn_ipam[index].oper_dhcp_options.dhcp_options();
523 0 : return true;
524 : }
525 : }
526 :
527 0 : return false;
528 : }
529 :
530 : // DHCP options applicable to the Ipam to which the interface belongs
531 0 : bool VmInterface::GetIpamDhcpOptions
532 : (std::vector<autogen::DhcpOptionType> *options, bool ipv6) const {
533 0 : if (vn()) {
534 0 : std::string ipam_name;
535 0 : autogen::IpamType ipam_type;
536 0 : if (!ipv6 &&
537 0 : vn()->GetIpamData(primary_ip_addr(), &ipam_name, &ipam_type)) {
538 0 : *options = ipam_type.dhcp_option_list.dhcp_option;
539 0 : return true;
540 : }
541 0 : if (ipv6 &&
542 0 : vn()->GetIpamData(primary_ip6_addr(), &ipam_name, &ipam_type)) {
543 0 : *options = ipam_type.dhcp_option_list.dhcp_option;
544 0 : return true;
545 : }
546 0 : }
547 :
548 0 : return false;
549 : }
550 :
551 : const MacAddress&
552 63 : VmInterface::GetIpMac(const IpAddress &ip, uint8_t plen) const {
553 : AllowedAddressPairSet::const_iterator it =
554 63 : allowed_address_pair_list_.list_.begin();
555 63 : while (it != allowed_address_pair_list_.list_.end()) {
556 0 : if (it->addr_ == ip && it->plen_ == plen &&
557 0 : it->mac_ != MacAddress::kZeroMac) {
558 0 : return it->mac_;
559 : }
560 0 : it++;
561 : }
562 : LearntMacIpSet::const_iterator mac_ip_it =
563 63 : learnt_mac_ip_list_.list_.begin();
564 63 : while (mac_ip_it != learnt_mac_ip_list_.list_.end()) {
565 0 : if (mac_ip_it->ip_ == ip &&
566 0 : mac_ip_it->mac_ != MacAddress::kZeroMac) {
567 0 : return mac_ip_it->mac_;
568 : }
569 0 : mac_ip_it++;
570 : }
571 63 : return vm_mac_;
572 : }
573 :
574 : /*
575 : * Check if the passed IP is in the AAP IP list on this interface;
576 : * If so, return true, else return false
577 : */
578 : bool
579 96 : VmInterface::MatchAapIp(const IpAddress &ip, uint8_t plen) const {
580 : AllowedAddressPairSet::const_iterator it =
581 96 : allowed_address_pair_list_.list_.begin();
582 96 : while (it != allowed_address_pair_list_.list_.end()) {
583 0 : if (it->addr_ == ip && it->plen_ == plen) {
584 0 : return true;
585 : }
586 0 : it++;
587 : }
588 96 : return false;
589 : }
590 :
591 0 : bool VmInterface::WaitForTraffic() const {
592 : // do not continue if the interface is inactive or if the VRF is deleted
593 0 : if (IsActive() == false || vrf_->IsDeleted()) {
594 0 : return false;
595 : }
596 :
597 : //Get the instance ip route and its corresponding traffic seen status
598 0 : InetUnicastRouteKey rt_key(peer_.get(), vrf_->GetName(),
599 0 : primary_ip_addr_, 32);
600 : const InetUnicastRouteEntry *rt = static_cast<const InetUnicastRouteEntry *>
601 0 : (vrf_->GetInet4UnicastRouteTable()->FindActiveEntry(&rt_key));
602 0 : if (!rt) {
603 0 : return false;
604 : }
605 :
606 0 : if (rt->FindPath(peer_.get()) == NULL) {
607 0 : return false;
608 : }
609 :
610 0 : return rt->FindPath(peer_.get())->path_preference().wait_for_traffic();
611 0 : }
612 :
613 297 : IpAddress VmInterface::GetServiceIp(const IpAddress &vm_ip) const {
614 297 : IpAddress ip;
615 297 : if (vm_ip.is_v4()) {
616 243 : ip = Ip4Address(0);
617 54 : } else if (vm_ip.is_v6()) {
618 54 : ip = Ip6Address();
619 : }
620 297 : if (vn_.get() == NULL) {
621 68 : return ip;
622 : }
623 :
624 229 : const VnIpam *ipam = NULL;
625 229 : if (subnet_.is_unspecified()) {
626 229 : ipam = vn_->GetIpam(vm_ip);
627 : } else {
628 0 : ipam = vn_->GetIpam(subnet_);
629 : }
630 :
631 229 : if (ipam) {
632 192 : if ((vm_ip.is_v4() && ipam->dns_server.is_v4()) ||
633 0 : (vm_ip.is_v6() && ipam->dns_server.is_v6())) {
634 192 : return ipam->dns_server;
635 : }
636 : }
637 37 : return ip;
638 : }
639 :
640 111 : IpAddress VmInterface::GetGatewayIp(const IpAddress &vm_ip) const {
641 111 : IpAddress ip;
642 111 : if (vn_.get() == NULL) {
643 34 : return ip;
644 : }
645 :
646 77 : const VnIpam *ipam = NULL;
647 77 : if (subnet_.is_unspecified()) {
648 77 : ipam = vn_->GetIpam(vm_ip);
649 : } else {
650 0 : ipam = vn_->GetIpam(subnet_);
651 : }
652 :
653 77 : if (ipam) {
654 40 : if ((vm_ip.is_v4() && ipam->default_gw.is_v4()) ||
655 0 : (vm_ip.is_v6() && ipam->default_gw.is_v6())) {
656 40 : return ipam->default_gw;
657 : }
658 : }
659 37 : return ip;
660 : }
661 :
662 : // Copy the SG List for VM Interface. Used to add route for interface
663 90 : void VmInterface::CopySgIdList(SecurityGroupList *sg_id_list) const {
664 90 : SecurityGroupEntrySet::const_iterator it;
665 99 : for (it = sg_list_.list_.begin(); it != sg_list_.list_.end(); ++it) {
666 9 : if (it->del_pending_)
667 0 : continue;
668 9 : if (it->sg_.get() == NULL)
669 0 : continue;
670 9 : sg_id_list->push_back(it->sg_->GetSgId());
671 : }
672 90 : }
673 :
674 0 : uint32_t VmInterface::GetServiceVlanLabel(const VrfEntry *vrf) const {
675 0 : ServiceVlanSet::const_iterator it = service_vlan_list_.list_.begin();
676 0 : while (it != service_vlan_list_.list_.end()) {
677 0 : if (it->vrf_.get() == vrf) {
678 0 : return it->label_;
679 : }
680 0 : it++;
681 : }
682 0 : return 0;
683 : }
684 :
685 0 : const VrfEntry* VmInterface::GetServiceVlanVrf(uint16_t vlan_tag) const {
686 0 : ServiceVlanSet::const_iterator it = service_vlan_list_.list_.begin();
687 0 : while (it != service_vlan_list_.list_.end()) {
688 0 : if (it->tag_ == vlan_tag) {
689 0 : return it->vrf_.get();
690 : }
691 0 : it++;
692 : }
693 0 : return NULL;
694 : }
695 :
696 32 : bool VmInterface::HasFloatingIp(Address::Family family) const {
697 32 : if (family == Address::INET) {
698 32 : return floating_ip_list_.v4_count_ > 0;
699 : } else {
700 0 : return floating_ip_list_.v6_count_ > 0;
701 : }
702 : }
703 :
704 0 : bool VmInterface::HasFloatingIp() const {
705 0 : return floating_ip_list_.list_.size() != 0;
706 : }
707 :
708 20 : bool VmInterface::IsFloatingIp(const IpAddress &ip) const {
709 : VmInterface::FloatingIpSet::const_iterator it =
710 20 : floating_ip_list_.list_.begin();
711 20 : while(it != floating_ip_list_.list_.end()) {
712 0 : if ((*it).floating_ip_ == ip) {
713 0 : return true;
714 : }
715 0 : it++;
716 : }
717 20 : return false;
718 : }
719 :
720 109 : VrfEntry *VmInterface::GetAliasIpVrf(const IpAddress &ip) const {
721 : // Look for matching Alias IP
722 : VmInterface::AliasIpSet::const_iterator it =
723 109 : alias_ip_list_.list_.begin();
724 109 : for (; it != alias_ip_list_.list_.end(); ++it) {
725 0 : if (it->vrf_.get() == NULL) {
726 0 : continue;
727 : }
728 :
729 0 : if (ip == it->alias_ip_) {
730 0 : return it->vrf_.get();
731 : }
732 : }
733 109 : return NULL;
734 : }
735 :
736 0 : void VmInterface::InsertHealthCheckInstance(HealthCheckInstanceBase *hc_inst) {
737 0 : std::pair<HealthCheckInstanceSet::iterator, bool> ret;
738 0 : ret = hc_instance_set_.insert(hc_inst);
739 0 : assert(ret.second);
740 0 : }
741 :
742 0 : void VmInterface::DeleteHealthCheckInstance(HealthCheckInstanceBase *hc_inst) {
743 : //[CEM-29104 for reference]If service_type of HealthCheck instance is "vn-ip-list"
744 : //while creating the BFD HealthCheck and if it is modified before deleting
745 : //the HealthCheck object, then object hc_inst will not present in hc_instance_set
746 : //and assert will fail while erasing hc_inst from hc_instance_set. So,
747 : //added a check to see if hc_inst is present in the set.
748 0 : if(hc_instance_set_.find(hc_inst) != hc_instance_set_.end()) {
749 0 : std::size_t ret = hc_instance_set_.erase(hc_inst);
750 0 : assert(ret != 0);
751 : }
752 0 : }
753 :
754 : const VmInterface::HealthCheckInstanceSet &
755 0 : VmInterface::hc_instance_set() const {
756 0 : return hc_instance_set_;
757 : }
758 :
759 60 : bool VmInterface::IsHealthCheckEnabled() const {
760 60 : return hc_instance_set_.size() != 0;
761 : }
762 :
763 : // Check if the interface requires to resync the health check service instance
764 : // Resync will be applied for healthcheck types BFD or Segment.
765 60 : void VmInterface::UpdateInterfaceHealthCheckService()
766 : {
767 60 : if (!IsHealthCheckEnabled() || !is_hc_active()) {
768 60 : return;
769 : }
770 :
771 0 : HealthCheckInstanceSet::const_iterator it = hc_instance_set_.begin();
772 0 : while (it != hc_instance_set_.end()) {
773 0 : const HealthCheckInstanceBase *hc_instance = *it;
774 0 : it++;
775 0 : HealthCheckService *hc_service = hc_instance->service();
776 0 : if (hc_service == NULL)
777 0 : continue;
778 :
779 : // resync will be applied healthcheck type is either BFD or Segment.
780 : HealthCheckService::HealthCheckType type =
781 0 : hc_service->health_check_type();
782 0 : if (type != HealthCheckService::BFD &&
783 : type != HealthCheckService::SEGMENT) {
784 0 : continue;
785 : }
786 :
787 : // if either source_ip or destination_ip unspecified,
788 : // resync the healtcheckservice
789 0 : if ((hc_instance->destination_ip().is_unspecified() == false) &&
790 0 : (hc_instance->get_source_ip().is_unspecified() == false)) {
791 0 : continue;
792 : }
793 0 : hc_service->ResyncHealthCheckInterface(hc_service, this);
794 : }
795 : }
796 :
797 31 : const string VmInterface::GetAnalyzer() const {
798 31 : if (mirror_entry()) {
799 0 : return mirror_entry()->GetAnalyzerName();
800 : } else {
801 31 : return std::string();
802 : }
803 : }
804 :
805 33 : const Peer *VmInterface::peer() const {
806 33 : return peer_.get();
807 : }
808 :
809 3 : bool VmInterface::IsFatFlowPortBased(uint8_t protocol, uint16_t port,
810 : FatFlowIgnoreAddressType *ignore_addr) const {
811 :
812 3 : FatFlowEntrySet::iterator start = fat_flow_list_.list_.lower_bound(
813 6 : FatFlowEntry(protocol, port,
814 : IGNORE_ADDRESS_MIN_VAL,
815 : AGGREGATE_PREFIX_MIN_VAL));
816 3 : FatFlowEntrySet::iterator end = fat_flow_list_.list_.upper_bound(
817 6 : FatFlowEntry(protocol, port,
818 : IGNORE_ADDRESS_MAX_VAL,
819 : AGGREGATE_PREFIX_MIN_VAL));
820 :
821 3 : if (start != fat_flow_list_.list_.end()) {
822 3 : while (start != end) {
823 6 : if ((start->protocol == protocol) && (start->port == port) &&
824 3 : (start->prefix_aggregate == AGGREGATE_NONE)) {
825 3 : *ignore_addr = start->ignore_address;
826 3 : return true;
827 : }
828 0 : start++;
829 : }
830 : }
831 0 : return false;
832 : }
833 :
834 0 : bool VmInterface::MatchSrcPrefixPort(uint8_t protocol, uint16_t port,
835 : IpAddress *src_ip,
836 : FatFlowIgnoreAddressType *ignore_addr) const
837 : {
838 : FatFlowPrefixAggregateType prefix_type, max_prefix_type;
839 0 : Ip4Address Ipv4_subnet, Ipv4_ret_subnet;
840 0 : Ip6Address Ipv6_subnet, Ipv6_ret_subnet;
841 : uint8_t max_mask, max_plen;
842 0 : const FatFlowEntry *match_ffe = NULL;
843 :
844 0 : *ignore_addr = VmInterface::IGNORE_NONE;
845 :
846 0 : if (src_ip->is_v4()) {
847 0 : prefix_type = AGGREGATE_SRC_IPV4;
848 : // set max_prefixtype to src_dst_ipv4 so that we can do LPM on src prefix
849 0 : max_prefix_type = AGGREGATE_SRC_DST_IPV4;
850 0 : Ipv4_subnet = Address::GetIp4SubnetAddress(src_ip->to_v4(),
851 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
852 0 : max_mask = 32;
853 0 : max_plen = 32;
854 : } else {
855 0 : prefix_type = AGGREGATE_SRC_IPV6;
856 0 : max_prefix_type = AGGREGATE_SRC_DST_IPV6;
857 0 : Ipv6_subnet = Address::GetIp6SubnetAddress(src_ip->to_v6(),
858 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
859 0 : max_mask = 128;
860 0 : max_plen = 128;
861 : }
862 :
863 : const FatFlowEntry lbffe = FatFlowEntry(protocol, port, "destination",
864 : prefix_type,
865 0 : (src_ip->is_v4()?
866 : IpAddress(Ipv4_subnet):
867 : IpAddress(Ipv6_subnet)),
868 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN,
869 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN,
870 0 : (src_ip->is_v4()?
871 : ipv4_empty_addr: ipv6_empty_addr
872 : ),
873 0 : 0, 0);
874 :
875 0 : FatFlowEntrySet::iterator start = fat_flow_list_.list_.lower_bound(lbffe);
876 :
877 : const FatFlowEntry ubffe =
878 : FatFlowEntry(protocol, port, "none",
879 : max_prefix_type,
880 : *src_ip, max_mask, max_plen,
881 0 : (src_ip->is_v4()?
882 : ipv4_max_addr: ipv6_max_addr
883 : ),
884 0 : max_mask, max_plen);
885 :
886 0 : FatFlowEntrySet::iterator end = fat_flow_list_.list_.upper_bound(ubffe);
887 :
888 0 : if ((start != fat_flow_list_.list_.end()) &&
889 0 : (start->protocol == protocol) && (start->port == port)) {
890 0 : while (start != end) {
891 0 : if (src_ip->is_v4() && start->src_prefix.is_v4() &&
892 0 : IsIp4SubnetMember(src_ip->to_v4(), start->src_prefix.to_v4(),
893 0 : start->src_prefix_mask) &&
894 0 : (start->protocol == protocol) && (start->port == port)) {
895 0 : if ((!match_ffe) ||
896 0 : (start->src_prefix_mask > match_ffe->src_prefix_mask)) {
897 0 : match_ffe = &(*start);
898 : }
899 0 : } else if (src_ip->is_v6() && start->src_prefix.is_v6() &&
900 0 : IsIp6SubnetMember(src_ip->to_v6(), start->src_prefix.to_v6(),
901 0 : start->src_prefix_mask) &&
902 0 : (start->protocol == protocol) && (start->port == port)) {
903 0 : if ((!match_ffe) ||
904 0 : (start->src_prefix_mask > match_ffe->src_prefix_mask)) {
905 0 : match_ffe = &(*start);
906 : }
907 : }
908 0 : start++;
909 : }
910 : }
911 0 : if (match_ffe && (match_ffe->prefix_aggregate == prefix_type)) {
912 0 : if (src_ip->is_v4()) {
913 0 : Ipv4_ret_subnet = Address::GetIp4SubnetAddress(src_ip->to_v4(),
914 0 : match_ffe->src_aggregate_plen);
915 0 : *src_ip = IpAddress(Ipv4_ret_subnet);
916 0 : *ignore_addr = match_ffe->ignore_address;
917 : } else {
918 0 : Ipv6_ret_subnet = Address::GetIp6SubnetAddress(src_ip->to_v6(),
919 0 : match_ffe->src_aggregate_plen);
920 0 : *src_ip = IpAddress(Ipv6_ret_subnet);
921 0 : *ignore_addr = match_ffe->ignore_address;
922 : }
923 0 : return true;
924 : }
925 0 : return false;
926 0 : }
927 :
928 0 : bool VmInterface::MatchSrcPrefixRule(uint8_t protocol, uint16_t *sport,
929 : uint16_t *dport, bool *same_port_num,
930 : IpAddress *SrcIP,
931 : FatFlowIgnoreAddressType *ignore_addr) const
932 : {
933 0 : if ((*sport) < (*dport)) {
934 0 : if (MatchSrcPrefixPort(protocol, *sport, SrcIP, ignore_addr)) {
935 0 : *dport = 0;
936 0 : return true;
937 : }
938 0 : if (MatchSrcPrefixPort(protocol, *dport, SrcIP, ignore_addr)) {
939 0 : *sport = 0;
940 0 : return true;
941 : }
942 : } else {
943 0 : if (MatchSrcPrefixPort(protocol, *dport, SrcIP, ignore_addr)) {
944 0 : if ((*sport) == (*dport)) {
945 0 : *same_port_num = true;
946 : }
947 0 : *sport = 0;
948 0 : return true;
949 : }
950 0 : if (MatchSrcPrefixPort(protocol, *sport, SrcIP, ignore_addr)) {
951 0 : *dport = 0;
952 0 : return true;
953 : }
954 : }
955 0 : if (MatchSrcPrefixPort(protocol, 0, SrcIP, ignore_addr)) {
956 0 : *sport = *dport = 0;
957 0 : return true;
958 : }
959 0 : return false;
960 : }
961 :
962 0 : bool VmInterface::MatchDstPrefixPort(uint8_t protocol, uint16_t port,
963 : IpAddress *dst_ip,
964 : FatFlowIgnoreAddressType *ignore_addr) const
965 : {
966 : FatFlowPrefixAggregateType prefix_type;
967 0 : Ip4Address Ipv4_subnet, Ipv4_ret_subnet;
968 0 : Ip6Address Ipv6_subnet, Ipv6_ret_subnet;
969 : uint8_t max_mask, max_plen;
970 0 : const FatFlowEntry *match_ffe = NULL;
971 :
972 0 : *ignore_addr = VmInterface::IGNORE_NONE;
973 :
974 0 : if (dst_ip->is_v4()) {
975 0 : prefix_type = AGGREGATE_DST_IPV4;
976 0 : Ipv4_subnet = Address::GetIp4SubnetAddress(dst_ip->to_v4(),
977 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
978 0 : max_mask = 32;
979 0 : max_plen = 32;
980 : } else {
981 0 : prefix_type = AGGREGATE_DST_IPV6;
982 0 : Ipv6_subnet = Address::GetIp6SubnetAddress(dst_ip->to_v6(),
983 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
984 0 : max_mask = 128;
985 0 : max_plen = 128;
986 : }
987 :
988 : const FatFlowEntry lbffe =
989 : FatFlowEntry(protocol, port, "source", prefix_type,
990 0 : (dst_ip->is_v4()?
991 : ipv4_empty_addr:
992 : ipv6_empty_addr
993 : ), 0, 0,
994 0 : (dst_ip->is_v4()?
995 : IpAddress(Ipv4_subnet):
996 : IpAddress(Ipv6_subnet)),
997 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN,
998 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
999 :
1000 0 : FatFlowEntrySet::iterator start = fat_flow_list_.list_.lower_bound(lbffe);
1001 :
1002 : const FatFlowEntry ubffe = FatFlowEntry(protocol, port, "none",
1003 : prefix_type,
1004 0 : (dst_ip->is_v4()?
1005 : ipv4_empty_addr:
1006 : ipv6_empty_addr
1007 : ), 0, 0,
1008 0 : *dst_ip, max_mask, max_plen);
1009 :
1010 0 : FatFlowEntrySet::iterator end = fat_flow_list_.list_.upper_bound(ubffe);
1011 :
1012 0 : if ((start != fat_flow_list_.list_.end()) &&
1013 0 : (start->protocol == protocol) && (start->port == port)) {
1014 0 : while (start != end) {
1015 0 : if (dst_ip->is_v4() && start->dst_prefix.is_v4() &&
1016 0 : IsIp4SubnetMember(dst_ip->to_v4(), start->dst_prefix.to_v4(),
1017 0 : start->dst_prefix_mask) &&
1018 0 : (start->protocol == protocol) && (start->port == port)) {
1019 0 : if ((!match_ffe) ||
1020 0 : (start->dst_prefix_mask > match_ffe->dst_prefix_mask)) {
1021 0 : match_ffe = &(*start);
1022 : }
1023 0 : } else if (dst_ip->is_v6() && start->dst_prefix.is_v6() &&
1024 0 : IsIp6SubnetMember(dst_ip->to_v6(), start->dst_prefix.to_v6(),
1025 0 : start->dst_prefix_mask) &&
1026 0 : (start->protocol == protocol) && (start->port == port)) {
1027 0 : if ((!match_ffe) ||
1028 0 : (start->dst_prefix_mask > match_ffe->dst_prefix_mask)) {
1029 0 : match_ffe = &(*start);
1030 : }
1031 : }
1032 0 : start++;
1033 : }
1034 : }
1035 0 : if (match_ffe && (match_ffe->prefix_aggregate == prefix_type)) {
1036 0 : if (dst_ip->is_v4()) {
1037 0 : Ipv4_ret_subnet = Address::GetIp4SubnetAddress(dst_ip->to_v4(),
1038 0 : match_ffe->dst_aggregate_plen);
1039 0 : *dst_ip = IpAddress(Ipv4_ret_subnet);
1040 0 : *ignore_addr = match_ffe->ignore_address;
1041 : } else {
1042 0 : Ipv6_ret_subnet = Address::GetIp6SubnetAddress(dst_ip->to_v6(),
1043 0 : match_ffe->dst_aggregate_plen);
1044 0 : *dst_ip = IpAddress(Ipv6_ret_subnet);
1045 0 : *ignore_addr = match_ffe->ignore_address;
1046 : }
1047 0 : return true;
1048 : }
1049 0 : return false;
1050 0 : }
1051 :
1052 :
1053 0 : bool VmInterface::MatchDstPrefixRule(uint8_t protocol, uint16_t *sport,
1054 : uint16_t *dport, bool *same_port_num,
1055 : IpAddress *DstIP,
1056 : FatFlowIgnoreAddressType *ignore_addr) const
1057 : {
1058 0 : if ((*sport) < (*dport)) {
1059 0 : if (MatchDstPrefixPort(protocol, *sport, DstIP, ignore_addr)) {
1060 0 : *dport = 0;
1061 0 : return true;
1062 : }
1063 0 : if (MatchDstPrefixPort(protocol, *dport, DstIP, ignore_addr)) {
1064 0 : *sport = 0;
1065 0 : return true;
1066 : }
1067 : } else {
1068 0 : if (MatchDstPrefixPort(protocol, *dport, DstIP, ignore_addr)) {
1069 0 : if ((*sport) == (*dport)) {
1070 0 : *same_port_num = true;
1071 : }
1072 0 : *sport = 0;
1073 0 : return true;
1074 : }
1075 0 : if (MatchDstPrefixPort(protocol, *sport, DstIP, ignore_addr)) {
1076 0 : *dport = 0;
1077 0 : return true;
1078 : }
1079 : }
1080 0 : if (MatchDstPrefixPort(protocol, 0, DstIP, ignore_addr)) {
1081 0 : *sport = *dport = 0;
1082 0 : return true;
1083 : }
1084 0 : return false;
1085 : }
1086 :
1087 :
1088 0 : bool VmInterface::MatchSrcDstPrefixPort(uint8_t protocol, uint16_t port,
1089 : IpAddress *src_ip,
1090 : IpAddress *dst_ip) const
1091 : {
1092 : FatFlowPrefixAggregateType prefix_type;
1093 0 : Ip4Address Ipv4_src_subnet, Ipv4_src_ret_subnet;
1094 0 : Ip4Address Ipv4_dst_subnet, Ipv4_dst_ret_subnet;
1095 0 : Ip6Address Ipv6_src_subnet, Ipv6_src_ret_subnet;
1096 0 : Ip6Address Ipv6_dst_subnet, Ipv6_dst_ret_subnet;
1097 : uint8_t max_mask, max_plen;
1098 0 : const FatFlowEntry *match_ffe = NULL;
1099 :
1100 0 : if (src_ip->is_v4()) {
1101 0 : prefix_type = AGGREGATE_SRC_DST_IPV4;
1102 0 : Ipv4_src_subnet = Address::GetIp4SubnetAddress(src_ip->to_v4(),
1103 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
1104 0 : Ipv4_dst_subnet = Address::GetIp4SubnetAddress(dst_ip->to_v4(),
1105 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
1106 0 : max_mask = 32;
1107 0 : max_plen = 32;
1108 : } else {
1109 0 : prefix_type = AGGREGATE_SRC_DST_IPV6;
1110 0 : Ipv6_src_subnet = Address::GetIp6SubnetAddress(src_ip->to_v6(),
1111 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
1112 0 : Ipv6_dst_subnet = Address::GetIp6SubnetAddress(dst_ip->to_v6(),
1113 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
1114 0 : max_mask = 128;
1115 0 : max_plen = 128;
1116 : }
1117 :
1118 : const FatFlowEntry lbffe =
1119 : FatFlowEntry(protocol, port, "none",
1120 : prefix_type,
1121 0 : (src_ip->is_v4()?
1122 : IpAddress(Ipv4_src_subnet):
1123 : IpAddress(Ipv6_src_subnet)),
1124 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN,
1125 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN,
1126 0 : (dst_ip->is_v4()?
1127 : IpAddress(Ipv4_dst_subnet):
1128 : IpAddress(Ipv6_dst_subnet)),
1129 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN,
1130 0 : FAT_FLOW_ENTRY_MIN_PREFIX_LEN);
1131 :
1132 0 : FatFlowEntrySet::iterator start = fat_flow_list_.list_.lower_bound(lbffe);
1133 :
1134 : const FatFlowEntry ubffe = FatFlowEntry(protocol, port, "none", prefix_type,
1135 : *src_ip, max_mask, max_plen,
1136 0 : *dst_ip, max_mask, max_plen);
1137 :
1138 0 : FatFlowEntrySet::iterator end = fat_flow_list_.list_.upper_bound(ubffe);
1139 :
1140 0 : if ((start != fat_flow_list_.list_.end()) &&
1141 0 : (start->protocol == protocol) && (start->port == port)) {
1142 0 : while (start != end) {
1143 0 : if (src_ip->is_v4() && start->src_prefix.is_v4() &&
1144 0 : start->dst_prefix.is_v4() &&
1145 0 : IsIp4SubnetMember(src_ip->to_v4(), start->src_prefix.to_v4(),
1146 0 : start->src_prefix_mask) &&
1147 0 : IsIp4SubnetMember(dst_ip->to_v4(), start->dst_prefix.to_v4(),
1148 0 : start->dst_prefix_mask) &&
1149 0 : (start->protocol == protocol) && (start->port == port)) {
1150 0 : match_ffe = &(*start);
1151 0 : } else if (src_ip->is_v6() && start->src_prefix.is_v6() &&
1152 0 : start->dst_prefix.is_v6() &&
1153 0 : IsIp6SubnetMember(src_ip->to_v6(), start->src_prefix.to_v6(),
1154 0 : start->src_prefix_mask) &&
1155 0 : IsIp6SubnetMember(dst_ip->to_v6(), start->dst_prefix.to_v6(),
1156 0 : start->dst_prefix_mask) &&
1157 0 : (start->protocol == protocol) && (start->port == port)) {
1158 0 : match_ffe = &(*start);
1159 : }
1160 0 : start++;
1161 : }
1162 : }
1163 0 : if (match_ffe && (match_ffe->prefix_aggregate == prefix_type)) {
1164 0 : if (src_ip->is_v4()) {
1165 : Ipv4_src_ret_subnet =
1166 0 : Address::GetIp4SubnetAddress(src_ip->to_v4(),
1167 0 : match_ffe->src_aggregate_plen);
1168 : Ipv4_dst_ret_subnet =
1169 0 : Address::GetIp4SubnetAddress(dst_ip->to_v4(),
1170 0 : match_ffe->dst_aggregate_plen);
1171 0 : *src_ip = IpAddress(Ipv4_src_ret_subnet);
1172 0 : *dst_ip = IpAddress(Ipv4_dst_ret_subnet);
1173 : } else {
1174 : Ipv6_src_ret_subnet =
1175 0 : Address::GetIp6SubnetAddress(src_ip->to_v6(),
1176 0 : match_ffe->src_aggregate_plen);
1177 : Ipv6_dst_ret_subnet =
1178 0 : Address::GetIp6SubnetAddress(dst_ip->to_v6(),
1179 0 : match_ffe->dst_aggregate_plen);
1180 0 : *src_ip = IpAddress(Ipv6_src_ret_subnet);
1181 0 : *dst_ip = IpAddress(Ipv6_dst_ret_subnet);
1182 : }
1183 0 : return true;
1184 : }
1185 0 : return false;
1186 0 : }
1187 :
1188 :
1189 0 : bool VmInterface::MatchSrcDstPrefixRule(uint8_t protocol, uint16_t *sport,
1190 : uint16_t *dport, bool *same_port_num,
1191 : IpAddress *SrcIP, IpAddress *DstIP) const
1192 : {
1193 0 : if ((*sport) < (*dport)) {
1194 0 : if (MatchSrcDstPrefixPort(protocol, *sport, SrcIP, DstIP)) {
1195 0 : *dport = 0;
1196 0 : return true;
1197 : }
1198 0 : if (MatchSrcDstPrefixPort(protocol, *dport, SrcIP, DstIP)) {
1199 0 : *sport = 0;
1200 0 : return true;
1201 : }
1202 : } else {
1203 0 : if (MatchSrcDstPrefixPort(protocol, *dport, SrcIP, DstIP)) {
1204 0 : if ((*sport) == (*dport)) {
1205 0 : *same_port_num = true;
1206 : }
1207 0 : *sport = 0;
1208 0 : return true;
1209 : }
1210 0 : if (MatchSrcDstPrefixPort(protocol, *sport, SrcIP, DstIP)) {
1211 0 : *dport = 0;
1212 0 : return true;
1213 : }
1214 : }
1215 0 : if (MatchSrcDstPrefixPort(protocol, 0, SrcIP, DstIP)) {
1216 0 : *sport = *dport = 0;
1217 0 : return true;
1218 : }
1219 0 : return false;
1220 : }
1221 :
1222 :
1223 0 : bool VmInterface::IsFatFlowPrefixAggregation(bool ingress, uint8_t protocol,
1224 : uint16_t *sport, uint16_t *dport,
1225 : bool *same_port_num,
1226 : IpAddress *SrcIP, IpAddress *DstIP,
1227 : bool *is_fat_flow_src_prefix,
1228 : bool *is_fat_flow_dst_prefix,
1229 : FatFlowIgnoreAddressType
1230 : *ignore_addr) const
1231 : {
1232 0 : uint16_t *src_port = sport,
1233 0 : *dst_port = dport;
1234 0 : IpAddress *src_ip = (ingress? SrcIP: DstIP),
1235 0 : *dst_ip = (ingress? DstIP: SrcIP);
1236 0 : bool *is_src_prefix = (ingress? is_fat_flow_src_prefix : is_fat_flow_dst_prefix);
1237 0 : bool *is_dst_prefix = (ingress? is_fat_flow_dst_prefix : is_fat_flow_src_prefix);
1238 : bool ret;
1239 : FatFlowIgnoreAddressType ign_addr;
1240 :
1241 0 : *is_src_prefix = false;
1242 0 : *is_dst_prefix = false;
1243 :
1244 : /* Match Src prefix rule first */
1245 0 : if (MatchSrcPrefixRule(protocol, src_port, dst_port, same_port_num,
1246 : src_ip, &ign_addr)) {
1247 0 : *is_src_prefix = true;
1248 0 : *ignore_addr = ign_addr;
1249 0 : return true;
1250 : }
1251 : /* Match Dst prefix rule */
1252 0 : if (MatchDstPrefixRule(protocol, src_port, dst_port, same_port_num,
1253 : dst_ip, &ign_addr)) {
1254 0 : *is_dst_prefix = true;
1255 0 : *ignore_addr = ign_addr;
1256 0 : return true;
1257 : }
1258 : /* Match Src+Dst prefix rule */
1259 0 : ret = MatchSrcDstPrefixRule(protocol, src_port, dst_port, same_port_num,
1260 : src_ip, dst_ip);
1261 0 : if (ret) {
1262 0 : *is_src_prefix = true;
1263 0 : *is_dst_prefix = true;
1264 : }
1265 :
1266 0 : return ret;
1267 : }
1268 :
1269 :
1270 3 : bool VmInterface::ExcludeFromFatFlow(Address::Family family,
1271 : const IpAddress &sip,
1272 : const IpAddress &dip) const {
1273 3 : if (family == Address::INET) {
1274 3 : IpAddress gw_ip = GetGatewayIp(primary_ip_addr_);
1275 3 : if ((sip == gw_ip) || (dip == gw_ip)) {
1276 0 : return true;
1277 : }
1278 3 : IpAddress service_ip = GetServiceIp(primary_ip_addr_);
1279 3 : if ((sip == service_ip) || (dip == service_ip)) {
1280 0 : return true;
1281 : }
1282 3 : boost::system::error_code ec;
1283 : Ip4Address ll_subnet = Ip4Address::from_string
1284 3 : (agent()->v4_link_local_subnet(), ec);
1285 3 : if (IsIp4SubnetMember(sip.to_v4(), ll_subnet,
1286 3 : agent()->v4_link_local_plen())) {
1287 0 : return true;
1288 : }
1289 3 : if (IsIp4SubnetMember(dip.to_v4(), ll_subnet,
1290 3 : agent()->v4_link_local_plen())) {
1291 0 : return true;
1292 : }
1293 0 : } else if (family == Address::INET6){
1294 0 : IpAddress gw_ip = GetGatewayIp(primary_ip6_addr_);
1295 0 : if ((sip == gw_ip) || (dip == gw_ip)) {
1296 0 : return true;
1297 : }
1298 0 : IpAddress service_ip = GetServiceIp(primary_ip6_addr_);
1299 0 : if ((sip == service_ip) || (dip == service_ip)) {
1300 0 : return true;
1301 : }
1302 0 : boost::system::error_code ec;
1303 : Ip6Address ll6_subnet = Ip6Address::from_string
1304 0 : (agent()->v6_link_local_subnet(), ec);
1305 0 : if (IsIp6SubnetMember(sip.to_v6(), ll6_subnet,
1306 0 : agent()->v6_link_local_plen())) {
1307 0 : return true;
1308 : }
1309 0 : if (IsIp6SubnetMember(dip.to_v6(), ll6_subnet,
1310 0 : agent()->v6_link_local_plen())) {
1311 0 : return true;
1312 : }
1313 : }
1314 3 : return false;
1315 : }
1316 :
1317 162 : void VmInterface::FillV4ExcludeIp(uint64_t plen, const Ip4Address &ip,
1318 : VmInterface::FatFlowExcludeList *list) const {
1319 162 : uint64_t value = 0;
1320 162 : if (!ip.is_unspecified()) {
1321 128 : value = plen | htonl(ip.to_ulong());
1322 128 : list->fat_flow_v4_exclude_list_.push_back(value);
1323 : }
1324 162 : }
1325 :
1326 162 : void VmInterface::FillV6ExcludeIp(uint16_t plen, const IpAddress &ip,
1327 : VmInterface::FatFlowExcludeList *list) const {
1328 162 : if (ip.is_v6() && !ip.is_unspecified()) {
1329 : uint64_t ip_arr[2];
1330 54 : Ip6AddressToU64Array(ip.to_v6(), ip_arr, 2);
1331 54 : list->fat_flow_v6_exclude_upper_list_.push_back(ip_arr[0]);
1332 54 : list->fat_flow_v6_exclude_lower_list_.push_back(ip_arr[1]);
1333 54 : list->fat_flow_v6_exclude_plen_list_.push_back(plen);
1334 : }
1335 162 : }
1336 :
1337 54 : void VmInterface::BuildFatFlowExcludeList
1338 : (VmInterface::FatFlowExcludeList *list) const {
1339 : /* Build the list afresh each time. So clear the list */
1340 54 : list->Clear();
1341 :
1342 : /* Build IPv4 exclude-list */
1343 54 : IpAddress gw_ip = GetGatewayIp(primary_ip_addr_);
1344 54 : uint64_t plen = (uint64_t(Address::kMaxV4PrefixLen) << 32);
1345 54 : FillV4ExcludeIp(plen, gw_ip.to_v4(), list);
1346 54 : IpAddress service_ip = GetServiceIp(primary_ip_addr_);
1347 54 : FillV4ExcludeIp(plen, service_ip.to_v4(), list);
1348 54 : boost::system::error_code ec;
1349 : Ip4Address ll_subnet = Ip4Address::from_string
1350 54 : (agent()->v4_link_local_subnet(), ec);
1351 54 : plen = (uint64_t(agent()->v4_link_local_plen()) << 32);
1352 54 : FillV4ExcludeIp(plen, ll_subnet, list);
1353 :
1354 : /* Build IPv6 exclude-list */
1355 54 : IpAddress gw6_ip = GetGatewayIp(primary_ip6_addr_);
1356 54 : FillV6ExcludeIp(128, gw6_ip, list);
1357 54 : IpAddress service6_ip = GetServiceIp(primary_ip6_addr_);
1358 54 : FillV6ExcludeIp(128, service6_ip, list);
1359 : Ip6Address ll6_subnet = Ip6Address::from_string
1360 54 : (agent()->v6_link_local_subnet(), ec);
1361 54 : FillV6ExcludeIp(agent()->v6_link_local_plen(), ll6_subnet, list);
1362 54 : }
1363 :
1364 148 : const MacAddress& VmInterface::GetVifMac(const Agent *agent) const {
1365 148 : if (parent()) {
1366 18 : if (device_type_ == VM_VLAN_ON_VMI) {
1367 : const VmInterface *vmi =
1368 0 : static_cast<const VmInterface *>(parent_.get());
1369 0 : return vmi->GetVifMac(agent);
1370 : }
1371 18 : return parent()->mac();
1372 : } else {
1373 130 : return agent->vrrp_mac();
1374 : }
1375 : }
1376 :
1377 0 : bool VmInterface::InstallBridgeRoutes() const {
1378 0 : return (l2_active_ & is_hc_active_);
1379 : }
1380 :
1381 : // Policy is disabled only if user explicitly sets disable policy.
1382 : // If user changes to disable policy. only policy will be enabled in case of
1383 : // link local services & BGP as a service.
1384 60 : bool VmInterface::PolicyEnabled() const {
1385 60 : if (disable_policy_) {
1386 3 : return false;
1387 : }
1388 :
1389 : /* For a l2-only VN's VMI, policy should be implicitly disabled */
1390 57 : if (layer3_forwarding_ == false) {
1391 17 : return false;
1392 : }
1393 40 : return true;
1394 : }
1395 :
1396 : // VN is in VXLAN mode if,
1397 : // - Tunnel type computed is VXLAN and
1398 : // - vxlan_id_ set in VN is non-zero
1399 29 : bool VmInterface::IsVxlanMode() const {
1400 29 : if (TunnelType::ComputeType(TunnelType::AllType()) != TunnelType::VXLAN)
1401 29 : return false;
1402 :
1403 0 : return vxlan_id_ != 0;
1404 : }
1405 :
1406 0 : void VmInterface::BuildIpStringList(Address::Family family,
1407 : std::vector<std::string> *vect) const {
1408 0 : InstanceIpSet list;
1409 0 : if (family == Address::INET) {
1410 0 : list = instance_ipv4_list_.list_;
1411 : } else {
1412 0 : list = instance_ipv6_list_.list_;
1413 : }
1414 0 : InstanceIpSet::iterator it = list.begin();
1415 0 : while (it != list.end()) {
1416 0 : const VmInterface::InstanceIp &rt = *it;
1417 0 : it++;
1418 0 : vect->push_back(rt.ip_.to_string());
1419 : }
1420 0 : }
1421 :
1422 0 : uint32_t VmInterface::GetIsid() const {
1423 0 : BridgeDomainEntrySet::const_iterator it = bridge_domain_list_.list_.begin();
1424 0 : for (; it != bridge_domain_list_.list_.end(); it++) {
1425 0 : return it->bridge_domain_->isid();
1426 : }
1427 0 : return kInvalidIsid;
1428 : }
1429 :
1430 0 : uint32_t VmInterface::GetPbbVrf() const {
1431 0 : BridgeDomainEntrySet::const_iterator it = bridge_domain_list_.list_.begin();
1432 0 : for (; it != bridge_domain_list_.list_.end(); it++) {
1433 0 : if (it->bridge_domain_->vrf()) {
1434 0 : return it->bridge_domain_->vrf()->vrf_id();
1435 : }
1436 : }
1437 0 : return VrfEntry::kInvalidIndex;
1438 : }
1439 :
1440 0 : uint32_t VmInterface::GetPbbLabel() const {
1441 0 : BridgeDomainEntrySet::const_iterator it = bridge_domain_list_.list_.begin();
1442 0 : for (; it != bridge_domain_list_.list_.end(); it++) {
1443 0 : if (it->bridge_domain_->vrf()) {
1444 0 : return it->bridge_domain_->vrf()->table_label();
1445 : }
1446 : }
1447 0 : return MplsTable::kInvalidLabel;
1448 : }
1449 :
1450 : /////////////////////////////////////////////////////////////////////////////
1451 : // Metadata related routines
1452 : /////////////////////////////////////////////////////////////////////////////
1453 0 : MetaDataIp *VmInterface::GetMetaDataIp(const IpAddress &ip) const {
1454 0 : MetaDataIpMap::const_iterator it = metadata_ip_map_.find(ip);
1455 0 : if (it != metadata_ip_map_.end()) {
1456 0 : return it->second;
1457 : }
1458 :
1459 0 : return NULL;
1460 : }
1461 :
1462 24 : void VmInterface::InsertMetaDataIpInfo(MetaDataIp *mip) {
1463 24 : std::pair<MetaDataIpMap::iterator, bool> ret;
1464 24 : ret = metadata_ip_map_.insert(std::pair<IpAddress, MetaDataIp*>
1465 48 : (mip->GetLinkLocalIp(), mip));
1466 24 : assert(ret.second);
1467 24 : }
1468 :
1469 24 : void VmInterface::DeleteMetaDataIpInfo(MetaDataIp *mip) {
1470 24 : std::size_t ret = metadata_ip_map_.erase(mip->GetLinkLocalIp());
1471 24 : if (ret == 0) {
1472 0 : LOG(DEBUG, "Return code for Metadata IP Map Erase: " <<ret<< " for MetaDataIp: " <<mip->GetLinkLocalIp());
1473 : }
1474 24 : }
1475 :
1476 76 : void VmInterface::UpdateMetaDataIpInfo() {
1477 76 : MetaDataIpMap::iterator it = metadata_ip_map_.begin();
1478 216 : while (it != metadata_ip_map_.end()) {
1479 140 : it->second->UpdateInterfaceCb();
1480 140 : it++;
1481 : }
1482 76 : }
1483 :
1484 60 : bool VmInterface::CopyIpAddress(Ip4Address &addr) {
1485 60 : bool ret = false;
1486 60 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
1487 :
1488 : // Support DHCP relay for fabric-ports if IP address is not configured
1489 60 : do_dhcp_relay_ = (fabric_port_ && addr.to_ulong() == 0 && vrf() &&
1490 0 : vrf()->GetName() == table->agent()->fabric_vrf_name());
1491 :
1492 60 : if (do_dhcp_relay_) {
1493 : // Set config_seen flag on DHCP SNoop entry
1494 0 : table->DhcpSnoopSetConfigSeen(name());
1495 : // IP Address not know. Get DHCP Snoop entry.
1496 : // Also sets the config_seen_ flag for DHCP Snoop entry
1497 0 : addr = table->GetDhcpSnoopEntry(name());
1498 0 : dhcp_addr_ = addr;
1499 : }
1500 :
1501 : // Retain the old if new IP could not be got
1502 60 : if (addr.to_ulong() == 0) {
1503 5 : addr = primary_ip_addr_;
1504 : }
1505 :
1506 60 : if (primary_ip_addr_ != addr) {
1507 0 : primary_ip_addr_ = addr;
1508 0 : ret = true;
1509 : }
1510 :
1511 60 : return ret;
1512 : }
1513 :
1514 0 : VmInterface * VmInterface::PortTuplePairedInterface() const {
1515 0 : if (si_other_end_vmi_ == nil_uuid()) {
1516 0 : return NULL;
1517 : }
1518 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
1519 0 : VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, si_other_end_vmi_, "");
1520 0 : VmInterface *intf = static_cast<VmInterface *>(table->Find(&key, false));
1521 0 : return intf;
1522 0 : }
1523 :
1524 90 : void VmInterface::SendTrace(const AgentDBTable *table, Trace event) const {
1525 90 : InterfaceInfo intf_info;
1526 90 : intf_info.set_name(name());
1527 90 : intf_info.set_index(id_);
1528 :
1529 90 : switch(event) {
1530 15 : case ACTIVATED_IPV4:
1531 15 : intf_info.set_op("IPV4 Activated");
1532 15 : break;
1533 15 : case DEACTIVATED_IPV4:
1534 15 : intf_info.set_op("IPV4 Deactivated");
1535 15 : break;
1536 15 : case ACTIVATED_IPV6:
1537 15 : intf_info.set_op("IPV6 Activated");
1538 15 : break;
1539 15 : case DEACTIVATED_IPV6:
1540 15 : intf_info.set_op("IPV6 Deactivated");
1541 15 : break;
1542 15 : case ACTIVATED_L2:
1543 15 : intf_info.set_op("L2 Activated");
1544 15 : break;
1545 15 : case DEACTIVATED_L2:
1546 15 : intf_info.set_op("L2 Deactivated");
1547 15 : break;
1548 0 : case ADD:
1549 0 : intf_info.set_op("Add");
1550 0 : break;
1551 0 : case DEL:
1552 0 : intf_info.set_op("Delete");
1553 0 : break;
1554 :
1555 0 : case FLOATING_IP_CHANGE: {
1556 0 : intf_info.set_op("Floating IP change");
1557 0 : std::vector<FloatingIPInfo> fip_list;
1558 0 : FloatingIpSet::iterator it = floating_ip_list_.list_.begin();
1559 0 : while (it != floating_ip_list_.list_.end()) {
1560 0 : const FloatingIp &ip = *it;
1561 0 : FloatingIPInfo fip;
1562 0 : fip.set_ip_address(ip.floating_ip_.to_string());
1563 0 : fip.set_vrf_name(ip.vrf_->GetName());
1564 0 : fip_list.push_back(fip);
1565 0 : it++;
1566 0 : }
1567 0 : intf_info.set_fip(fip_list);
1568 0 : break;
1569 0 : }
1570 0 : case SERVICE_CHANGE:
1571 0 : break;
1572 :
1573 0 : case VMI_REUSE:
1574 0 : intf_info.set_op("VMI reuse");
1575 0 : intf_info.set_vrf_on_delete(vrf_name_);
1576 0 : break;
1577 :
1578 0 : case VRF_REUSE:
1579 0 : intf_info.set_op("VRF reuse");
1580 0 : intf_info.set_vrf_on_delete(vrf_name_);
1581 0 : break;
1582 : }
1583 :
1584 90 : intf_info.set_ip_address(primary_ip_addr_.to_string());
1585 90 : if (vm_) {
1586 36 : intf_info.set_vm(UuidToString(vm_->GetUuid()));
1587 : }
1588 90 : if (vn_) {
1589 36 : intf_info.set_vn(vn_->GetName());
1590 : }
1591 90 : if (vrf_) {
1592 45 : intf_info.set_vrf(vrf_->GetName());
1593 : }
1594 90 : intf_info.set_vm_project(UuidToString(vm_project_uuid_));
1595 90 : OPER_TRACE_ENTRY(Interface,
1596 : table,
1597 : intf_info);
1598 90 : }
|