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