Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 : #include <cmn/agent_cmn.h>
6 : #include <init/agent_param.h>
7 : #include <oper/operdb_init.h>
8 : #include <oper/route_common.h>
9 : #include <oper/vm.h>
10 : #include <oper/vn.h>
11 : #include <oper/vrf.h>
12 : #include <oper/nexthop.h>
13 : #include <oper/mpls.h>
14 : #include <oper/mirror_table.h>
15 : #include <oper/metadata_ip.h>
16 : #include <oper/interface_common.h>
17 : #include <oper/health_check.h>
18 : #include <oper/vrf_assign.h>
19 : #include <oper/vxlan.h>
20 : #include <oper/oper_dhcp_options.h>
21 : #include <oper/physical_device_vn.h>
22 : #include <oper/global_vrouter.h>
23 : #include <oper/qos_config.h>
24 : #include <oper/bridge_domain.h>
25 : #include <oper/sg.h>
26 : #include <oper/tag.h>
27 : #include <base/address_util.h>
28 : #include <filter/acl.h>
29 : #include <filter/policy_set.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 : using namespace std;
37 : using namespace boost::uuids;
38 : using namespace autogen;
39 : VmInterface::IgnoreAddressMap VmInterface::fatflow_ignore_addr_map_ =
40 : InitIgnoreAddressMap();
41 :
42 : const char *VmInterface::kInterface = "interface";
43 : const char *VmInterface::kServiceInterface = "service-interface";
44 : const char *VmInterface::kInterfaceStatic = "interface-static";
45 :
46 : /////////////////////////////////////////////////////////////////////////////
47 : // VM-Interface entry routines
48 : /////////////////////////////////////////////////////////////////////////////
49 26350 : VmInterface::VmInterface(const boost::uuids::uuid &uuid,
50 : const std::string &name,
51 : bool os_oper_state,
52 26350 : const boost::uuids::uuid &logical_router_uuid) :
53 : Interface(Interface::VM_INTERFACE, uuid, name, NULL, os_oper_state,
54 : logical_router_uuid),
55 26350 : vm_(NULL, this), vn_(NULL), primary_ip_addr_(0), subnet_bcast_addr_(0),
56 26350 : primary_ip6_addr_(), vm_mac_(MacAddress::kZeroMac), policy_enabled_(false),
57 26350 : mirror_entry_(NULL), mirror_direction_(MIRROR_RX_TX), cfg_name_(""),
58 26350 : fabric_port_(true), need_linklocal_ip_(false), drop_new_flows_(false),
59 26350 : dhcp_enable_(true), dhcp_enable_v6_(false), do_dhcp_relay_(false), proxy_arp_mode_(PROXY_ARP_NONE),
60 52700 : vm_name_(), vm_project_uuid_(nil_uuid()), vxlan_id_(0), bridging_(false),
61 26350 : layer3_forwarding_(true), flood_unknown_unicast_(false),
62 52700 : mac_set_(false), ecmp_(false), ecmp6_(false), disable_policy_(false),
63 26350 : tx_vlan_id_(kInvalidVlanId), rx_vlan_id_(kInvalidVlanId), parent_(NULL, this),
64 26350 : local_preference_(0), oper_dhcp_options_(),
65 26350 : cfg_igmp_enable_(false), igmp_enabled_(false),
66 26350 : mac_ip_learning_enable_(false), max_flows_(0),
67 26350 : mac_vm_binding_state_(new MacVmBindingState()),
68 26350 : nexthop_state_(new NextHopState()),
69 26350 : vrf_table_label_state_(new VrfTableLabelState()),
70 26350 : metadata_ip_state_(new MetaDataIpState()),
71 26350 : metadata_ip6_state_(new MetaDataIpState(false)),
72 26350 : resolve_route_state_(new ResolveRouteState()),
73 26350 : interface_route_state_(new VmiRouteState()),
74 26350 : sg_list_(), tag_list_(), floating_ip_list_(), alias_ip_list_(), service_vlan_list_(),
75 26350 : static_route_list_(), allowed_address_pair_list_(),
76 26350 : instance_ipv4_list_(true), instance_ipv6_list_(false), fat_flow_list_(),
77 52700 : vrf_assign_rule_list_(), vm_ip_service_addr_(0),
78 26350 : device_type_(VmInterface::DEVICE_TYPE_INVALID),
79 26350 : vmi_type_(VmInterface::VMI_TYPE_INVALID),
80 26350 : hbs_intf_type_(VmInterface::HBS_INTF_INVALID),
81 26350 : configurer_(0), subnet_(0), subnet_plen_(0), ethernet_tag_(0),
82 26350 : logical_interface_(nil_uuid()), nova_ip_addr_(0), nova_ip6_addr_(),
83 26350 : dhcp_addr_(0), metadata_ip_map_(), hc_instance_set_(),
84 26350 : ecmp_load_balance_(), service_health_check_ip_(), is_vn_qos_config_(false),
85 26350 : learning_enabled_(false), etree_leaf_(false), layer2_control_word_(false),
86 26350 : slo_list_(), forwarding_vrf_(NULL), vhostuser_mode_(vHostUserClient),
87 26350 : is_left_si_(false),
88 26350 : service_mode_(VmInterface::SERVICE_MODE_ERROR),
89 26350 : service_intf_type_(""),
90 184450 : parent_list_() {
91 26350 : metadata_ip_active_ = false;
92 26350 : metadata_l2_active_ = false;
93 26350 : ipv4_active_ = false;
94 26350 : ipv6_active_ = false;
95 26350 : l2_active_ = false;
96 26350 : flow_count_ = 0;
97 26350 : vrf_name_ = "";
98 26350 : }
99 :
100 169 : VmInterface::VmInterface(const boost::uuids::uuid &uuid,
101 : const std::string &name,
102 : const Ip4Address &addr, const MacAddress &mac,
103 : const std::string &vm_name,
104 : const boost::uuids::uuid &vm_project_uuid,
105 : uint16_t tx_vlan_id, uint16_t rx_vlan_id,
106 : Interface *parent, const Ip6Address &a6,
107 : DeviceType device_type, VmiType vmi_type,
108 : uint8_t vhostuser_mode, bool os_oper_state,
109 169 : const boost::uuids::uuid &logical_router_uuid) :
110 : Interface(Interface::VM_INTERFACE, uuid, name, NULL, os_oper_state,
111 : logical_router_uuid),
112 169 : vm_(NULL, this), vn_(NULL), primary_ip_addr_(addr), subnet_bcast_addr_(0),
113 169 : primary_ip6_addr_(a6), vm_mac_(mac), policy_enabled_(false),
114 169 : mirror_entry_(NULL), mirror_direction_(MIRROR_RX_TX), cfg_name_(""),
115 169 : fabric_port_(true), need_linklocal_ip_(false), drop_new_flows_(false),
116 169 : dhcp_enable_(true), dhcp_enable_v6_(false), do_dhcp_relay_(false), proxy_arp_mode_(PROXY_ARP_NONE),
117 169 : vm_name_(vm_name), vm_project_uuid_(vm_project_uuid), vxlan_id_(0),
118 169 : bridging_(false), layer3_forwarding_(true),
119 169 : flood_unknown_unicast_(false), mac_set_(false),
120 338 : ecmp_(false), ecmp6_(false), disable_policy_(false),
121 169 : tx_vlan_id_(tx_vlan_id), rx_vlan_id_(rx_vlan_id), parent_(parent, this),
122 169 : local_preference_(0), oper_dhcp_options_(),
123 169 : cfg_igmp_enable_(false), igmp_enabled_(false),
124 169 : mac_ip_learning_enable_(false), max_flows_(0),
125 169 : mac_vm_binding_state_(new MacVmBindingState()),
126 169 : nexthop_state_(new NextHopState()),
127 169 : vrf_table_label_state_(new VrfTableLabelState()),
128 169 : metadata_ip_state_(new MetaDataIpState()),
129 169 : metadata_ip6_state_(new MetaDataIpState(false)),
130 169 : resolve_route_state_(new ResolveRouteState()),
131 169 : interface_route_state_(new VmiRouteState()),
132 169 : sg_list_(), tag_list_(),
133 169 : floating_ip_list_(), alias_ip_list_(), service_vlan_list_(),
134 169 : static_route_list_(), allowed_address_pair_list_(),
135 169 : instance_ipv4_list_(true), instance_ipv6_list_(false), fat_flow_list_(),
136 169 : vrf_assign_rule_list_(), device_type_(device_type),
137 169 : vmi_type_(vmi_type), hbs_intf_type_(VmInterface::HBS_INTF_INVALID),
138 169 : configurer_(0), subnet_(0),
139 169 : subnet_plen_(0), ethernet_tag_(0), logical_interface_(nil_uuid()),
140 169 : nova_ip_addr_(0), nova_ip6_addr_(), dhcp_addr_(0), metadata_ip_map_(),
141 338 : hc_instance_set_(), service_health_check_ip_(), is_vn_qos_config_(false),
142 169 : learning_enabled_(false), etree_leaf_(false), layer2_control_word_(false),
143 169 : slo_list_(), forwarding_vrf_(NULL), vhostuser_mode_(vhostuser_mode),
144 169 : is_left_si_(false),
145 169 : service_mode_(VmInterface::SERVICE_MODE_ERROR),
146 169 : service_intf_type_(""),
147 1183 : parent_list_() {
148 169 : metadata_ip_active_ = false;
149 169 : metadata_l2_active_ = false;
150 169 : ipv4_active_ = false;
151 169 : ipv6_active_ = false;
152 169 : l2_active_ = false;
153 169 : flow_count_ = 0;
154 169 : vrf_name_ = "";
155 169 : }
156 :
157 53038 : VmInterface::~VmInterface() {
158 : // Release metadata first to ensure metadata_ip_map_ is empty
159 26519 : metadata_ip_state_.reset(NULL);
160 26519 : metadata_ip6_state_.reset(NULL);
161 26519 : assert(metadata_ip_map_.empty());
162 26519 : assert(hc_instance_set_.empty());
163 53038 : }
164 :
165 1496 : void VmInterface::SetConfigurer(VmInterface::Configurer type) {
166 1496 : configurer_ |= (1 << type);
167 1496 : }
168 :
169 334 : void VmInterface::ResetConfigurer(VmInterface::Configurer type) {
170 334 : configurer_ &= ~(1 << type);
171 334 : }
172 :
173 169 : bool VmInterface::IsConfigurerSet(VmInterface::Configurer type) {
174 169 : return ((configurer_ & (1 << type)) != 0);
175 : }
176 :
177 125737 : bool VmInterface::CmpInterface(const DBEntry &rhs) const {
178 125737 : const VmInterface &intf=static_cast<const VmInterface &>(rhs);
179 125737 : if (uuid_ == nil_uuid() && intf.uuid_ == nil_uuid()) {
180 310 : return name() < intf.name();
181 : }
182 :
183 125427 : return uuid_ < intf.uuid_;
184 : }
185 :
186 0 : string VmInterface::ToString() const {
187 0 : return "VM-PORT <" + name() + ">";
188 : }
189 :
190 1540 : DBEntryBase::KeyPtr VmInterface::GetDBRequestKey() const {
191 1540 : InterfaceKey *key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, uuid_, name());
192 1540 : return DBEntryBase::KeyPtr(key);
193 : }
194 :
195 169 : void VmInterface::Add() {
196 169 : peer_.reset(new LocalVmPortPeer(LOCAL_VM_PORT_PEER_NAME, id_));
197 169 : }
198 :
199 169 : bool VmInterface::Delete(const DBRequest *req) {
200 169 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
201 : const VmInterfaceData *vm_data = static_cast<const VmInterfaceData *>
202 169 : (req->data.get());
203 169 : if (vrf_ && vrf_->GetName() != "") {
204 169 : vrf_name_ = vrf_->GetName();
205 : }
206 169 : vm_data->OnDelete(table, this);
207 169 : if (configurer_) {
208 0 : return false;
209 : }
210 169 : table->DeleteDhcpSnoopEntry(name());
211 169 : return true;
212 : }
213 :
214 : // When VMInterface is added from Config (sub-interface, gateway interface etc.)
215 : // the RESYNC is not called and some of the config like VN and VRF are not
216 : // applied on the interface (See Add() API above). Force change to ensure
217 : // RESYNC is called
218 169 : void VmInterface::PostAdd() {
219 169 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
220 169 : IFMapNode *node = ifmap_node();
221 169 : if (node == NULL) {
222 : PortSubscribeTable *subscribe_table =
223 167 : table->agent()->port_ipc_handler()->port_subscribe_table();
224 167 : if (subscribe_table)
225 167 : node = subscribe_table->UuidToIFNode(GetUuid());
226 167 : if (node == NULL)
227 167 : return;
228 : }
229 :
230 : // Config notification would have been ignored till Nova message is
231 : // received. Update config now
232 : IFMapAgentTable *ifmap_table =
233 2 : static_cast<IFMapAgentTable *>(node->table());
234 2 : DBRequest req(DBRequest::DB_ENTRY_NOTIFY);
235 2 : req.key = node->GetDBRequestKey();
236 : IFMapTable::RequestKey *key =
237 2 : dynamic_cast<IFMapTable::RequestKey *>(req.key.get());
238 2 : key->id_type = "virtual-machine-interface";
239 2 : ifmap_table->Enqueue(&req);
240 2 : }
241 :
242 167 : bool VmInterface::ResetVrfDelete(const InterfaceTable *table,
243 : const std::string &vrf_name) {
244 167 : Agent *agent = table->agent();
245 167 : VrfKey vrf_key(vrf_name);
246 167 : VrfEntry *vrf = static_cast<VrfEntry *>(
247 167 : agent->vrf_table()->Find(&vrf_key, true));
248 167 : if (vrf && vrf->IsDeleted()) {
249 0 : SendTrace(table, VRF_REUSE);
250 0 : return vrf->ResetVrfDelete();
251 : }
252 167 : return true;
253 167 : }
254 :
255 4 : bool VmInterface::OnChange(VmInterfaceData *data) {
256 4 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
257 4 : if (IsDeleted()) {
258 0 : SendTrace(table, VMI_REUSE);
259 0 : ResetVrfDelete(table, vrf_name());
260 : }
261 4 : return Resync(table, data);
262 : }
263 :
264 : // Handle RESYNC DB Request. Handles multiple sub-types,
265 : // - CONFIG : RESYNC from config message
266 : // - IP_ADDR: RESYNC due to learning IP from DHCP
267 : // - MIRROR : RESYNC due to change in mirror config
268 1333 : bool VmInterface::Resync(const InterfaceTable *table,
269 : const VmInterfaceData *data) {
270 1333 : bool ret = false;
271 :
272 : // Copy old values used to update config below
273 1333 : bool old_ipv4_active = ipv4_active_;
274 1333 : bool old_ipv6_active = ipv6_active_;
275 1333 : bool old_l2_active = l2_active_;
276 1333 : bool old_policy = policy_enabled_;
277 1333 : VrfEntryRef old_vrf = vrf_;
278 1333 : bool force_update = false;
279 1333 : Ip4Address old_subnet = subnet_;
280 1333 : uint8_t old_subnet_plen = subnet_plen_;
281 1333 : bool old_metadata_ip_active = metadata_ip_active_;
282 1333 : bool old_metadata_l2_active = metadata_l2_active_;
283 :
284 1333 : if (data) {
285 1333 : ret = data->OnResync(table, this, &force_update);
286 1333 : std::string ri_name = "";
287 1333 : if (data->vrf_name_ == "" && vrf_name_ == "") {
288 325 : if (vn()) {
289 167 : std::string fqdn_name = vn()->GetName();
290 167 : size_t pos = fqdn_name.rfind(":");
291 167 : if (pos != std::string::npos)
292 74 : pos = pos + 1;
293 : else
294 93 : pos = 0;
295 167 : ri_name = fqdn_name + ":" + fqdn_name.substr(pos, fqdn_name.length());
296 167 : }
297 : } else {
298 1008 : ri_name = data->vrf_name_;
299 : }
300 1333 : if (ri_name != "" && ri_name != vrf_name_) {
301 167 : if (ResetVrfDelete(table, ri_name))
302 167 : vrf_name_ = ri_name;
303 : }
304 1333 : }
305 :
306 1333 : metadata_ip_active_ = IsMetaDataIPActive();
307 1333 : metadata_l2_active_ = IsMetaDataL2Active();
308 1333 : ipv4_active_ = IsIpv4Active();
309 1333 : ipv6_active_ = IsIpv6Active();
310 1333 : l2_active_ = IsL2Active();
311 :
312 1333 : if (metadata_ip_active_ != old_metadata_ip_active) {
313 338 : ret = true;
314 : }
315 :
316 1333 : if (metadata_l2_active_ != old_metadata_l2_active) {
317 334 : ret = true;
318 : }
319 :
320 1333 : if (ipv4_active_ != old_ipv4_active) {
321 338 : InterfaceTable *intf_table = static_cast<InterfaceTable *>(get_table());
322 338 : if (ipv4_active_)
323 169 : intf_table->incr_active_vmi_count();
324 : else
325 169 : intf_table->decr_active_vmi_count();
326 338 : ret = true;
327 : }
328 :
329 1333 : if (ipv6_active_ != old_ipv6_active) {
330 30 : ret = true;
331 : }
332 :
333 1333 : if (l2_active_ != old_l2_active) {
334 338 : ret = true;
335 : }
336 :
337 1333 : policy_enabled_ = PolicyEnabled();
338 1333 : if (policy_enabled_ != old_policy) {
339 334 : ret = true;
340 : }
341 :
342 : //Update DHCP and DNS flag in Interface Class.
343 1333 : if (dhcp_enable_) {
344 790 : dhcp_enabled_ = true;
345 : } else {
346 543 : dhcp_enabled_ = false;
347 : }
348 :
349 : //Update DHCP and DNS flag for v6 in Interface Class.
350 1333 : if (dhcp_enable_v6_) {
351 0 : dhcp_enabled_v6_ = true;
352 : }else {
353 1333 : dhcp_enabled_v6_ = false;
354 : }
355 :
356 1333 : if (dhcp_enabled_ || dhcp_enable_v6_)
357 790 : dns_enabled_ = true;
358 : else
359 543 : dns_enabled_ = false;
360 :
361 : // Compute service-ip for the interface
362 1333 : vm_ip_service_addr_ = GetServiceIp(primary_ip_addr()).to_v4();
363 :
364 : // Add/Update L2
365 1333 : if (l2_active_) {
366 996 : UpdateL2();
367 : }
368 :
369 : // Apply config based on old and new values
370 1333 : ApplyConfig(old_ipv4_active, old_l2_active, old_ipv6_active,
371 : old_subnet, old_subnet_plen);
372 :
373 : // Check if Healthcheck service resync is required
374 1333 : UpdateInterfaceHealthCheckService();
375 1333 : return ret;
376 1333 : }
377 :
378 :
379 : // Apply the latest configuration
380 1333 : void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active,
381 : bool old_ipv6_active,
382 : const Ip4Address &old_subnet,
383 : uint8_t old_subnet_plen) {
384 1333 : VmInterfaceState::Op l2_force_op = VmInterfaceState::INVALID;
385 1333 : VmInterfaceState::Op l3_force_op = VmInterfaceState::INVALID;
386 :
387 : // For following intf type we dont generate any things like l2 routes,
388 : // l3 routes etc
389 : // VM_SRIOV, VMI_ON_LR
390 1333 : if ((device_type_ == VmInterface::VM_SRIOV) ||
391 1333 : (device_type_ == VmInterface::VMI_ON_LR)) {
392 0 : l2_force_op = VmInterfaceState::DEL;
393 0 : l3_force_op = VmInterfaceState::DEL;
394 : }
395 :
396 : /////////////////////////////////////////////////////////////////////////
397 : // PHASE-1 Updates follows.
398 : //
399 : // Changes independnt of any state
400 : // NOTE: Dont move updates below across PHASE-1 block
401 : /////////////////////////////////////////////////////////////////////////
402 :
403 : // DHCP MAC IP binding
404 1333 : UpdateState(mac_vm_binding_state_.get(), l2_force_op, l3_force_op);
405 :
406 1333 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
407 : //Update security group and tag list first so that route can
408 : //build the tag list and security group list
409 1333 : sg_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
410 1333 : tag_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
411 :
412 : // Fat flow configuration
413 1333 : fat_flow_list_.UpdateList(agent, this);
414 :
415 : // Bridge Domain configuration
416 1333 : bridge_domain_list_.Update(agent, this);
417 1333 : if (bridge_domain_list_.list_.size() == 0) {
418 1333 : pbb_interface_ = false;
419 : }
420 :
421 : // NOTE : The updates are independnt of any state and agent-mode. They
422 : // must not move beyond this part
423 :
424 : // Need not apply config for TOR VMI as it is more of an inidicative
425 : // interface. No route addition or NH addition happens for this interface.
426 : // Also, when parent is not updated for a non-Nova interface, device type
427 : // remains invalid.
428 3995 : if ((device_type_ == VmInterface::TOR ||
429 1341 : device_type_ == VmInterface::DEVICE_TYPE_INVALID) &&
430 8 : (old_subnet.is_unspecified() && old_subnet_plen == 0)) {
431 : // TODO : Should force_op be set to VmInterfaceState::DEL instead?
432 4 : return;
433 : }
434 :
435 : /////////////////////////////////////////////////////////////////////////
436 : // PHASE-2 Updates follows.
437 : //
438 : // Appy changes independent of L2/L3 modes first
439 : // NOTE: Dont move updates below across PHASE-2 block
440 : /////////////////////////////////////////////////////////////////////////
441 :
442 : // Update VRF Table Label
443 1329 : UpdateState(vrf_table_label_state_.get(), l2_force_op, l3_force_op);
444 :
445 : // Update NextHop parameters
446 1329 : UpdateState(nexthop_state_.get(), l2_force_op, l3_force_op);
447 1329 : GetNextHopInfo();
448 :
449 : // Add/Update L3 Metadata for v4 and v6 standards
450 1329 : UpdateState(metadata_ip_state_.get(), l2_force_op, l3_force_op);
451 1329 : UpdateState(metadata_ip6_state_.get(), l2_force_op, l3_force_op);
452 :
453 : /////////////////////////////////////////////////////////////////////////
454 : // PHASE-3 Updates follows.
455 : //
456 : // Updates dependent on l2-active state and healtch-check-state
457 : // NOTE : Dont move updates below across PHASE-3
458 : /////////////////////////////////////////////////////////////////////////
459 :
460 : // Dont add any l2-states if l2 is not active
461 2658 : if (device_type() == VmInterface::TOR ||
462 1329 : device_type() == VmInterface::DEVICE_TYPE_INVALID) {
463 0 : l2_force_op = VmInterfaceState::DEL;
464 : }
465 1329 : if (l2_active_ == false || is_hc_active_ == false) {
466 335 : l2_force_op = VmInterfaceState::DEL;
467 : }
468 :
469 : // Add EVPN and L3 route for do_dhcp_relay_ before instance-ip routes
470 1329 : UpdateState(interface_route_state_.get(), l2_force_op, l3_force_op);
471 :
472 : // Add/Update L3/L2 routes routes resulting from instance-ip
473 1329 : instance_ipv4_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
474 :
475 : // Add/Update L3/L2 routes routes resulting from instance-ip
476 1329 : instance_ipv6_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
477 :
478 : // Update floating-ip related configuration
479 1329 : floating_ip_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
480 :
481 1329 : alias_ip_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
482 :
483 1329 : UpdateState(resolve_route_state_.get(), l2_force_op, l3_force_op);
484 :
485 1329 : static_route_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
486 :
487 1329 : service_vlan_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
488 :
489 1329 : vrf_assign_rule_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
490 :
491 1329 : allowed_address_pair_list_.UpdateList(agent, this, l2_force_op,
492 : l3_force_op);
493 1329 : receive_route_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
494 1329 : learnt_mac_ip_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
495 :
496 : /////////////////////////////////////////////////////////////////////////
497 : // PHASE-3 Updates follows.
498 : // Only cleanup and deletes follow below
499 : //
500 : // NOTE : Dont move updates below across PHASE-3
501 : /////////////////////////////////////////////////////////////////////////
502 :
503 : // Delete NextHop if inactive
504 1329 : DeleteState(nexthop_state_.get());
505 1329 : GetNextHopInfo();
506 :
507 : // Del L3 Metadata after deleting L3 information
508 1329 : DeleteState(metadata_ip_state_.get());
509 1329 : DeleteState(metadata_ip6_state_.get());
510 :
511 : // Remove floating-ip entries marked for deletion
512 1329 : CleanupFloatingIpList();
513 :
514 : // Remove Alias-ip entries marked for deletion
515 1329 : CleanupAliasIpList();
516 :
517 1329 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
518 1329 : if (old_l2_active != l2_active_) {
519 334 : if (l2_active_) {
520 167 : SendTrace(table, ACTIVATED_L2);
521 : } else {
522 167 : SendTrace(table, DEACTIVATED_L2);
523 : }
524 : }
525 :
526 1329 : if (old_ipv4_active != ipv4_active_) {
527 334 : if (ipv4_active_) {
528 167 : SendTrace(table, ACTIVATED_IPV4);
529 : } else {
530 167 : SendTrace(table, DEACTIVATED_IPV4);
531 : }
532 : }
533 :
534 1329 : if (old_ipv6_active != ipv6_active_) {
535 30 : if (ipv6_active_) {
536 15 : SendTrace(table, ACTIVATED_IPV6);
537 : } else {
538 15 : SendTrace(table, DEACTIVATED_IPV6);
539 : }
540 : }
541 : }
542 :
543 996 : void VmInterface::UpdateL2() {
544 1990 : if (device_type() == VmInterface::TOR ||
545 994 : device_type() == VmInterface::DEVICE_TYPE_INVALID)
546 2 : return;
547 :
548 994 : int new_vxlan_id = vn_.get() ? vn_->GetVxLanId() : 0;
549 994 : if (l2_active_ && ((vxlan_id_ == 0) ||
550 975 : (vxlan_id_ != new_vxlan_id))) {
551 19 : vxlan_id_ = new_vxlan_id;
552 : }
553 994 : ethernet_tag_ = IsVxlanMode() ? vxlan_id_ : 0;
554 : }
555 :
556 : ////////////////////////////////////////////////////////////////////////////
557 : // VmInterface attribute methods
558 : ////////////////////////////////////////////////////////////////////////////
559 10838 : bool VmInterface::UpdateState(const VmInterfaceState *state,
560 : VmInterfaceState::Op l2_force_op,
561 : VmInterfaceState::Op l3_force_op) {
562 10838 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
563 10838 : return state->Update(agent, this, l2_force_op, l3_force_op);
564 : }
565 :
566 3987 : bool VmInterface::DeleteState(VmInterfaceState *state) {
567 3987 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
568 3987 : bool ret = true;
569 3987 : if (state->l2_installed_) {
570 1161 : if (state->DeleteL2(agent, this))
571 167 : state->l2_installed_ = false;
572 : else
573 994 : ret = false;
574 : }
575 3987 : if (state->l3_installed_) {
576 3475 : if (state->DeleteL3(agent, this))
577 497 : state->l3_installed_ = false;
578 : else
579 2978 : ret = false;
580 : }
581 3987 : return ret;
582 : }
583 :
584 : /////////////////////////////////////////////////////////////////////////////
585 : // VmInterfaceAttr basic routines
586 : /////////////////////////////////////////////////////////////////////////////
587 22280 : VmInterfaceState::Op VmInterfaceState::RecomputeOp(Op old_op, Op new_op) {
588 22280 : return (new_op > old_op) ? new_op : old_op;
589 : }
590 :
591 10838 : bool VmInterfaceState::Update(const Agent *agent, VmInterface *vmi,
592 : Op l2_force_op, Op l3_force_op) const {
593 10838 : Op l2_op = RecomputeOp(l2_force_op, GetOpL2(agent, vmi));
594 10838 : Op l3_op = RecomputeOp(l3_force_op, GetOpL3(agent, vmi));
595 :
596 10838 : if ((l2_op == DEL || l2_op == DEL_ADD) && l2_installed_) {
597 443 : DeleteL2(agent, vmi);
598 443 : l2_installed_ = false;
599 : }
600 10838 : if ((l3_op == DEL || l3_op == DEL_ADD) && l3_installed_) {
601 458 : DeleteL3(agent, vmi);
602 458 : l3_installed_ = false;
603 : }
604 :
605 10838 : Copy(agent, vmi);
606 :
607 10838 : if (l3_op == ADD || l3_op == DEL_ADD) {
608 7225 : if (AddL3(agent, vmi))
609 4737 : l3_installed_ = true;
610 : }
611 10838 : if (l2_op == ADD || l2_op == DEL_ADD) {
612 2740 : if (AddL2(agent, vmi))
613 2738 : l2_installed_ = true;
614 : }
615 :
616 10838 : return true;
617 : }
618 :
619 : // Force operation to be DEL if del_pending_ is set
620 3062 : VmInterfaceState::Op VmInterface::ListEntry::GetOp(VmInterfaceState::Op op)
621 : const {
622 3062 : if (del_pending_ == false)
623 2458 : return op;
624 :
625 604 : return VmInterfaceState::RecomputeOp(op, VmInterfaceState::DEL);
626 : }
627 :
628 630 : static bool GetIpActiveState(const IpAddress &ip, const VmInterface *vmi) {
629 630 : if (ip.is_v6())
630 4 : return vmi->ipv6_active();
631 :
632 626 : return vmi->ipv4_active();
633 : }
634 :
635 : ////////////////////////////////////////////////////////////////////////////
636 : // MacVmBinding attribute method
637 : // Adds a path to MacVmBinding is responsible to update flood-dhcp flag
638 : ////////////////////////////////////////////////////////////////////////////
639 26519 : MacVmBindingState::MacVmBindingState() :
640 26519 : VmInterfaceState(), vrf_(NULL), dhcp_enabled_(false), dhcp_enabled_v6_(false) {
641 26519 : }
642 :
643 53038 : MacVmBindingState::~MacVmBindingState() {
644 53038 : }
645 :
646 1333 : VmInterfaceState::Op MacVmBindingState::GetOpL3(const Agent *agent,
647 : const VmInterface *vmi) const {
648 1333 : if (vmi->IsActive() == false)
649 337 : return VmInterfaceState::DEL;
650 :
651 996 : if (vrf_ != vmi->vrf())
652 169 : return VmInterfaceState::DEL_ADD;
653 :
654 827 : return VmInterfaceState::ADD;
655 : }
656 :
657 169 : bool MacVmBindingState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
658 : BridgeAgentRouteTable *table =
659 169 : static_cast<BridgeAgentRouteTable *>(vrf_->GetBridgeRouteTable());
660 : // return if table is already marked for deletion, bridge route delete might
661 : // already be processed in ReComputePathDeletion
662 169 : if (table == NULL)
663 0 : return true;
664 338 : table->DeleteMacVmBindingRoute(agent->mac_vm_binding_peer(),
665 169 : vrf_->GetName(), vmi->vm_mac(), vmi);
666 169 : return true;
667 : }
668 :
669 1333 : void MacVmBindingState::Copy(const Agent *agent, const VmInterface *vmi) const {
670 1333 : vrf_ = vmi->vrf();
671 1333 : dhcp_enabled_ = vmi->dhcp_enable_config();
672 1333 : }
673 :
674 996 : bool MacVmBindingState::AddL3(const Agent *agent, VmInterface *vmi) const {
675 : BridgeAgentRouteTable *table =
676 996 : static_cast<BridgeAgentRouteTable *>(vrf_->GetBridgeRouteTable());
677 : // flood_dhcp must be set in route if dhcp is disabled for interface
678 996 : bool flood_dhcp = !vmi->dhcp_enable_config();
679 996 : table->AddMacVmBindingRoute(agent->mac_vm_binding_peer(), vrf_->GetName(),
680 : vmi->vm_mac(), vmi, flood_dhcp);
681 996 : return true;
682 : }
683 :
684 : /////////////////////////////////////////////////////////////////////////////
685 : // SecurityGroup routines
686 : // Does not generate any new state. Only holds reference to SG for interface
687 : /////////////////////////////////////////////////////////////////////////////
688 3 : void VmInterface::SecurityGroupEntryList::Insert
689 : (const SecurityGroupEntry *rhs) {
690 3 : list_.insert(*rhs);
691 3 : }
692 :
693 0 : void VmInterface::SecurityGroupEntryList::Update
694 : (const SecurityGroupEntry *lhs, const SecurityGroupEntry *rhs) {
695 0 : }
696 :
697 3 : void VmInterface::SecurityGroupEntryList::Remove
698 : (SecurityGroupEntrySet::iterator &it) {
699 3 : it->set_del_pending(true);
700 3 : }
701 :
702 1333 : bool VmInterface::SecurityGroupEntryList::UpdateList
703 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
704 : VmInterfaceState::Op l3_force_op) {
705 1333 : SecurityGroupEntrySet::iterator it = list_.begin();
706 1339 : while (it != list_.end()) {
707 6 : SecurityGroupEntrySet::iterator prev = it++;
708 6 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
709 6 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
710 6 : vmi->UpdateState(&(*prev), l2_op, l3_op);
711 6 : if (prev->del_pending()) {
712 3 : list_.erase(prev);
713 : }
714 : }
715 :
716 1333 : return true;
717 : }
718 :
719 28267 : VmInterface::SecurityGroupEntry::SecurityGroupEntry() :
720 28267 : ListEntry(), VmInterfaceState(), uuid_(nil_uuid()) {
721 28267 : }
722 :
723 12 : VmInterface::SecurityGroupEntry::SecurityGroupEntry
724 12 : (const SecurityGroupEntry &rhs) :
725 12 : ListEntry(rhs.del_pending_),
726 12 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
727 12 : uuid_(rhs.uuid_) {
728 12 : }
729 :
730 3 : VmInterface::SecurityGroupEntry::SecurityGroupEntry(const uuid &u) :
731 3 : ListEntry(), VmInterfaceState(), uuid_(u) {
732 3 : }
733 :
734 28282 : VmInterface::SecurityGroupEntry::~SecurityGroupEntry() {
735 28282 : }
736 :
737 0 : bool VmInterface::SecurityGroupEntry::operator ==
738 : (const SecurityGroupEntry &rhs) const {
739 0 : return uuid_ == rhs.uuid_;
740 : }
741 :
742 0 : bool VmInterface::SecurityGroupEntry::operator()
743 : (const SecurityGroupEntry &lhs, const SecurityGroupEntry &rhs) const {
744 0 : return lhs.IsLess(&rhs);
745 : }
746 :
747 0 : bool VmInterface::SecurityGroupEntry::IsLess
748 : (const SecurityGroupEntry *rhs) const {
749 0 : return uuid_ < rhs->uuid_;
750 : }
751 :
752 : // Remove reference to SG when list entry is deleted. Note, the SG states are
753 : // not dependent on any interface active state
754 6 : VmInterfaceState::Op VmInterface::SecurityGroupEntry::GetOpL3
755 : (const Agent *agent, const VmInterface *vmi) const {
756 6 : if (del_pending_)
757 3 : return VmInterfaceState::INVALID;
758 :
759 3 : return VmInterfaceState::ADD;
760 : }
761 :
762 3 : bool VmInterface::SecurityGroupEntry::AddL3(const Agent *agent,
763 : VmInterface *vmi) const {
764 3 : if (sg_.get() != NULL)
765 0 : return false;
766 :
767 3 : SgKey sg_key(uuid_);
768 3 : sg_ = static_cast<SgEntry *>(agent->sg_table()->FindActiveEntry(&sg_key));
769 3 : return true;
770 3 : }
771 :
772 3 : bool VmInterface::SecurityGroupEntry::DeleteL3(const Agent *agent,
773 : VmInterface *vmi) const {
774 3 : sg_ = NULL;
775 3 : return true;
776 : }
777 :
778 : /////////////////////////////////////////////////////////////////////////////
779 : // Fat Flow list routines
780 : // Only updates fat-flow configuraion in interface
781 : // NOTE: Its not derived from VmInterfaceState and also does not generate
782 : // any new states
783 : /////////////////////////////////////////////////////////////////////////////
784 9 : VmInterface::FatFlowEntry::FatFlowEntry(const uint8_t proto, const uint16_t p,
785 : std::string ignore_addr_value,
786 : FatFlowPrefixAggregateType in_prefix_aggregate,
787 : IpAddress in_src_prefix, uint8_t in_src_prefix_mask,
788 : uint8_t in_src_aggregate_plen,
789 : IpAddress in_dst_prefix, uint8_t in_dst_prefix_mask,
790 9 : uint8_t in_dst_aggregate_plen) :
791 9 : protocol(proto), port(p) {
792 9 : ignore_address = fatflow_ignore_addr_map_.find(ignore_addr_value)->second;
793 9 : prefix_aggregate = in_prefix_aggregate;
794 9 : src_prefix = in_src_prefix;
795 9 : src_prefix_mask = in_src_prefix_mask;
796 9 : src_aggregate_plen = in_src_aggregate_plen;
797 9 : dst_prefix = in_dst_prefix;
798 9 : dst_prefix_mask = in_dst_prefix_mask;
799 9 : dst_aggregate_plen = in_dst_aggregate_plen;
800 9 : }
801 :
802 :
803 : VmInterface::FatFlowEntry
804 9 : VmInterface::FatFlowEntry::MakeFatFlowEntry(const std::string &proto, const int &port,
805 : const std::string &ignore_addr_str,
806 : const std::string &in_src_prefix_str, const int &in_src_prefix_mask,
807 : const int &in_src_aggregate_plen,
808 : const std::string &in_dst_prefix_str, const int &in_dst_prefix_mask,
809 : const int &in_dst_aggregate_plen) {
810 9 : uint8_t protocol = (uint8_t) Agent::ProtocolStringToInt(proto);
811 9 : IpAddress src_prefix;
812 9 : uint8_t src_prefix_mask = 0, src_aggregate_plen = 0;
813 9 : IpAddress dst_prefix, empty_prefix, empty_prefix_v6 = IpAddress::from_string("0::0");
814 9 : uint8_t dst_prefix_mask = 0, dst_aggregate_plen = 0;
815 9 : FatFlowPrefixAggregateType prefix_aggregate = AGGREGATE_NONE;
816 : FatFlowIgnoreAddressType ignore_address =
817 9 : fatflow_ignore_addr_map_.find(ignore_addr_str)->second;
818 9 : int port_num = port;
819 :
820 : /*
821 : * Protocol is taken as 1 for both IPv4 & IPv6 and Port no should be 0 for ICMP/ICMPv6,
822 : * override if we get something else from config
823 : */
824 9 : if ((protocol == IPPROTO_ICMP) || (protocol == IPPROTO_ICMPV6)) {
825 0 : protocol = IPPROTO_ICMP;
826 0 : port_num = 0;
827 : }
828 :
829 9 : if (in_src_prefix_str.length() > 0) {
830 :
831 0 : src_prefix = IpAddress::from_string(in_src_prefix_str);
832 0 : src_prefix_mask = in_src_prefix_mask;
833 0 : src_aggregate_plen = in_src_aggregate_plen;
834 0 : if (src_prefix.is_v4()) {
835 : // convert to prefix
836 0 : src_prefix = IpAddress(Address::GetIp4SubnetAddress(src_prefix.to_v4(),
837 0 : src_prefix_mask));
838 0 : prefix_aggregate = AGGREGATE_SRC_IPV4;
839 : } else {
840 0 : src_prefix = IpAddress(Address::GetIp6SubnetAddress(src_prefix.to_v6(),
841 0 : src_prefix_mask));
842 0 : prefix_aggregate = AGGREGATE_SRC_IPV6;
843 : }
844 : }
845 9 : if (in_dst_prefix_str.length() > 0) {
846 0 : dst_prefix = IpAddress::from_string(in_dst_prefix_str);
847 0 : dst_prefix_mask = in_dst_prefix_mask;
848 0 : dst_aggregate_plen = in_dst_aggregate_plen;
849 0 : if (dst_prefix.is_v4()) {
850 0 : dst_prefix = IpAddress(Address::GetIp4SubnetAddress(dst_prefix.to_v4(),
851 0 : dst_prefix_mask));
852 : } else {
853 0 : dst_prefix = IpAddress(Address::GetIp6SubnetAddress(dst_prefix.to_v6(),
854 0 : dst_prefix_mask));
855 : }
856 :
857 0 : if (prefix_aggregate == AGGREGATE_NONE) {
858 0 : if (dst_prefix.is_v4()) {
859 0 : prefix_aggregate = AGGREGATE_DST_IPV4;
860 : } else {
861 0 : prefix_aggregate = AGGREGATE_DST_IPV6;
862 : }
863 : } else {
864 0 : if (dst_prefix.is_v4()) {
865 0 : prefix_aggregate = AGGREGATE_SRC_DST_IPV4;
866 : } else {
867 0 : prefix_aggregate = AGGREGATE_SRC_DST_IPV6;
868 : }
869 : }
870 : }
871 9 : if (ignore_address == IGNORE_SOURCE) {
872 0 : if ((prefix_aggregate == AGGREGATE_SRC_IPV4) || (prefix_aggregate == AGGREGATE_SRC_IPV6)) {
873 0 : src_prefix = empty_prefix;
874 0 : src_prefix_mask = 0;
875 0 : src_aggregate_plen = 0;
876 0 : prefix_aggregate = AGGREGATE_NONE;
877 0 : } else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV4) {
878 0 : src_prefix = empty_prefix;
879 0 : src_prefix_mask = 0;
880 0 : src_aggregate_plen = 0;
881 0 : prefix_aggregate = AGGREGATE_DST_IPV4;
882 0 : } else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV6) {
883 0 : src_prefix = empty_prefix_v6;
884 0 : src_prefix_mask = 0;
885 0 : src_aggregate_plen = 0;
886 0 : prefix_aggregate = AGGREGATE_DST_IPV6;
887 : }
888 9 : } else if (ignore_address == IGNORE_DESTINATION) {
889 0 : if ((prefix_aggregate == AGGREGATE_DST_IPV4) || (prefix_aggregate == AGGREGATE_DST_IPV6)) {
890 0 : dst_prefix = empty_prefix;
891 0 : dst_prefix_mask = 0;
892 0 : dst_aggregate_plen = 0;
893 0 : prefix_aggregate = AGGREGATE_NONE;
894 0 : } else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV4) {
895 0 : dst_prefix = empty_prefix;
896 0 : dst_prefix_mask = 0;
897 0 : dst_aggregate_plen = 0;
898 0 : prefix_aggregate = AGGREGATE_SRC_IPV4;
899 0 : } else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV6) {
900 0 : dst_prefix = empty_prefix_v6;
901 0 : dst_prefix_mask = 0;
902 0 : dst_aggregate_plen = 0;
903 0 : prefix_aggregate = AGGREGATE_SRC_IPV6;
904 : }
905 : }
906 :
907 9 : if ((in_src_prefix_str.length() == 0) && (prefix_aggregate == AGGREGATE_DST_IPV6)) {
908 0 : src_prefix = empty_prefix_v6;
909 : }
910 9 : if ((in_dst_prefix_str.length() == 0) && (prefix_aggregate == AGGREGATE_SRC_IPV6)) {
911 0 : dst_prefix = empty_prefix_v6;
912 : }
913 :
914 : VmInterface::FatFlowEntry entry(protocol, port_num,
915 : ignore_addr_str, prefix_aggregate, src_prefix, src_prefix_mask,
916 9 : src_aggregate_plen, dst_prefix, dst_prefix_mask, dst_aggregate_plen);
917 18 : return entry;
918 : }
919 :
920 0 : void VmInterface::FatFlowEntry::print(void) const {
921 0 : LOG(ERROR, "Protocol:" << (int) protocol << " Port:" << port << " IgnoreAddr:" << ignore_address
922 : << " PrefixAggr:" << prefix_aggregate << " SrcPrefix:" << src_prefix.to_string() << "/" << (int) src_prefix_mask
923 : << " SrcAggrPlen:" << (int) src_aggregate_plen << " DstPrefix:" << dst_prefix.to_string() << "/" << (int) dst_prefix_mask
924 : << " DstAggrPlen:" << (int) dst_aggregate_plen);
925 0 : }
926 :
927 12 : void VmInterface::FatFlowList::Insert(const FatFlowEntry *rhs) {
928 12 : list_.insert(*rhs);
929 12 : }
930 :
931 6 : void VmInterface::FatFlowList::Update(const FatFlowEntry *lhs,
932 : const FatFlowEntry *rhs) {
933 6 : lhs->ignore_address = rhs->ignore_address;
934 6 : lhs->prefix_aggregate = rhs->prefix_aggregate;
935 6 : lhs->src_prefix = rhs->src_prefix;
936 6 : lhs->src_prefix_mask = rhs->src_prefix_mask;
937 6 : lhs->src_aggregate_plen = rhs->src_aggregate_plen;
938 6 : lhs->dst_prefix = rhs->dst_prefix;
939 6 : lhs->dst_prefix_mask = rhs->dst_prefix_mask;
940 6 : lhs->dst_aggregate_plen = rhs->dst_aggregate_plen;
941 6 : }
942 :
943 3 : void VmInterface::FatFlowList::Remove(FatFlowEntrySet::iterator &it) {
944 3 : it->set_del_pending(true);
945 3 : }
946 :
947 1333 : bool VmInterface::FatFlowList::UpdateList(const Agent *agent,
948 : VmInterface *vmi) {
949 1333 : FatFlowEntrySet::iterator it = list_.begin();
950 1345 : while (it != list_.end()) {
951 12 : FatFlowEntrySet::iterator prev = it++;
952 12 : if (prev->del_pending_) {
953 3 : list_.erase(prev);
954 : }
955 : }
956 1333 : return true;
957 : }
958 :
959 0 : void VmInterface::FatFlowList::DumpList(void) const {
960 0 : LOG(ERROR, "Dumping FatFlowList:\n");
961 0 : for (FatFlowEntrySet::iterator it = list_.begin(); it != list_.end(); it++) {
962 0 : it->print();
963 : }
964 0 : }
965 :
966 : ////////////////////////////////////////////////////////////////////////////
967 : // Bridge Domain List
968 : // NOTE: Its not derived from VmInterfaceState and also does not generate
969 : // any new states
970 : ////////////////////////////////////////////////////////////////////////////
971 0 : void VmInterface::BridgeDomainList::Insert(const BridgeDomain *rhs) {
972 0 : list_.insert(*rhs);
973 0 : }
974 :
975 0 : void VmInterface::BridgeDomainList::Update(const BridgeDomain *lhs,
976 : const BridgeDomain *rhs) {
977 0 : }
978 :
979 0 : void VmInterface::BridgeDomainList::Remove(BridgeDomainEntrySet::iterator &it) {
980 0 : it->set_del_pending(true);
981 0 : }
982 :
983 1333 : bool VmInterface::BridgeDomainList::Update(const Agent *agent,
984 : VmInterface *vmi) {
985 1333 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
986 1333 : BridgeDomainEntrySet::iterator it = list_.begin();
987 1333 : while (it != list_.end()) {
988 0 : BridgeDomainEntrySet::iterator prev = it++;
989 0 : if (prev->del_pending_ == false) {
990 0 : BridgeDomainKey key(prev->uuid_);
991 0 : prev->bridge_domain_ = static_cast<const BridgeDomainEntry *>
992 0 : (table->agent()->bridge_domain_table()->FindActiveEntry(&key));
993 : // Ignore bridge domain without VRF
994 : // Interface will get config update again when VRF is created
995 0 : if (prev->bridge_domain_->vrf() == NULL) {
996 0 : prev->del_pending_ = true;
997 : }
998 0 : }
999 :
1000 0 : if (prev->del_pending_) {
1001 0 : list_.erase(prev);
1002 : }
1003 : }
1004 :
1005 1333 : return true;
1006 : }
1007 :
1008 : ////////////////////////////////////////////////////////////////////////////
1009 : // VRF Table label
1010 : // Create VRF-NextHop based on interface-type. The NextHop is not explicitly
1011 : // deleted. It gets deleted when reference count drops to 0
1012 : ////////////////////////////////////////////////////////////////////////////
1013 26519 : VrfTableLabelState::VrfTableLabelState() : VmInterfaceState() {
1014 26519 : }
1015 :
1016 53038 : VrfTableLabelState::~VrfTableLabelState() {
1017 53038 : }
1018 :
1019 1329 : VmInterfaceState::Op VrfTableLabelState::GetOpL3(const Agent *agent,
1020 : const VmInterface *vmi) const {
1021 1329 : return VmInterfaceState::ADD;
1022 : }
1023 :
1024 : // Take care of only adding VRF Table label. The label will be freed when
1025 : // VRF is deleted
1026 1329 : bool VrfTableLabelState::AddL3(const Agent *agent, VmInterface *vmi) const {
1027 1329 : if (vmi->vrf() == NULL || vmi->vmi_type() != VmInterface::GATEWAY) {
1028 1329 : return false;
1029 : }
1030 :
1031 0 : vmi->vrf()->CreateTableLabel(false, false, false, false);
1032 0 : return false;
1033 : }
1034 :
1035 : ////////////////////////////////////////////////////////////////////////////
1036 : // NextHop attribute
1037 : //
1038 : // L2 nexthops:
1039 : // These L2 nexthop are used by multicast and bridge. Presence of multicast
1040 : // forces it to be present in ipv4 mode(l3-only).
1041 : //
1042 : // L3 nexthops:
1043 : // Also creates L3 interface NH, if layer3_forwarding is set.
1044 : // It does not depend on oper state of ip forwarding.
1045 : // Needed as health check can disable oper ip_active and will result in flow
1046 : // key pointing to L2 interface NH. This has to be avoided as interface still
1047 : // points to l3 nh and flow should use same. For this fix it is also required
1048 : // that l3 i/f nh is also created on seeing config and not oper state of l3.
1049 : // Reason being if vmi(irrespective of health check) is coming up and
1050 : // transitioning from ipv4_inactive to ip4_active and during this transition
1051 : // a flow is added then flow_key in vmi will return null because l3 config is
1052 : // set and interface nh not created yet.
1053 : ////////////////////////////////////////////////////////////////////////////
1054 26519 : NextHopState::NextHopState() : VmInterfaceState() {
1055 26519 : }
1056 :
1057 53038 : NextHopState::~NextHopState() {
1058 53038 : }
1059 :
1060 : // The nexthops are deleted after all update processing by explicitly
1061 : // calling delete. So, dont return DEL operation from here
1062 1329 : VmInterfaceState::Op NextHopState::GetOpL2(const Agent *agent,
1063 : const VmInterface *vmi) const {
1064 1329 : if (vmi->IsActive() == false)
1065 335 : return VmInterfaceState::INVALID;
1066 994 : return VmInterfaceState::ADD;
1067 : }
1068 :
1069 : // The nexthops must be deleted after all update processing. So, dont return
1070 : // DEL operation from here
1071 1329 : VmInterfaceState::Op NextHopState::GetOpL3(const Agent *agent,
1072 : const VmInterface *vmi) const {
1073 1329 : if ((vmi->IsActive() == false) || (vmi->layer3_forwarding() == false))
1074 335 : return VmInterfaceState::INVALID;
1075 :
1076 994 : return VmInterfaceState::ADD;
1077 : }
1078 :
1079 994 : bool NextHopState::AddL2(const Agent *agent, VmInterface *vmi) const {
1080 1988 : InterfaceNH::CreateL2VmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1081 : vmi->forwarding_vrf()->GetName(),
1082 994 : vmi->learning_enabled(),
1083 994 : vmi->etree_leaf(),
1084 994 : vmi->layer2_control_word(),
1085 : vmi->name());
1086 :
1087 : InterfaceNHKey key1(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1088 994 : vmi->GetUuid(), vmi->name()),
1089 1988 : true, InterfaceNHFlags::BRIDGE, vmi->vm_mac());
1090 : l2_nh_policy_ = static_cast<NextHop *>
1091 994 : (agent->nexthop_table()->FindActiveEntry(&key1));
1092 :
1093 : InterfaceNHKey key2(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1094 994 : vmi->GetUuid(), vmi->name()),
1095 1988 : false, InterfaceNHFlags::BRIDGE, vmi->vm_mac());
1096 : l2_nh_no_policy_ = static_cast<NextHop *>
1097 994 : (agent->nexthop_table()->FindActiveEntry(&key2));
1098 :
1099 : // Update L2 mpls label from nh entry
1100 994 : if (vmi->policy_enabled()) {
1101 992 : l2_label_ = l2_nh_policy_->mpls_label()->label();
1102 : } else {
1103 2 : l2_label_ = l2_nh_no_policy_->mpls_label()->label();
1104 : }
1105 :
1106 994 : return true;
1107 994 : }
1108 :
1109 1161 : bool NextHopState::DeleteL2(const Agent *agent, VmInterface *vmi) const {
1110 : // Delete is called independent of interface active-state.
1111 : // Dont delete NH if interface is still active
1112 1161 : if (vmi->IsActive())
1113 994 : return false;
1114 :
1115 167 : l2_nh_policy_.reset();
1116 167 : l2_nh_no_policy_.reset();
1117 167 : l2_label_ = MplsTable::kInvalidLabel;
1118 167 : InterfaceNH::DeleteL2InterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1119 : vmi->name());
1120 167 : return true;
1121 : }
1122 :
1123 994 : bool NextHopState::AddL3(const Agent *agent, VmInterface *vmi) const {
1124 1988 : InterfaceNH::CreateL3VmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1125 : vmi->forwarding_vrf()->GetName(),
1126 994 : vmi->learning_enabled(),
1127 : vmi->name());
1128 :
1129 994 : InterfaceNH::CreateMulticastVmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1130 : vmi->forwarding_vrf()->GetName(),
1131 : vmi->name());
1132 :
1133 : InterfaceNHKey key1(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1134 994 : vmi->GetUuid(), vmi->name()),
1135 1988 : true, InterfaceNHFlags::INET4, vmi->vm_mac());
1136 : l3_nh_policy_ = static_cast<NextHop *>
1137 994 : (agent->nexthop_table()->FindActiveEntry(&key1));
1138 :
1139 : InterfaceNHKey key2(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1140 994 : vmi->GetUuid(), vmi->name()),
1141 1988 : false, InterfaceNHFlags::INET4, vmi->vm_mac());
1142 : l3_nh_no_policy_ = static_cast<NextHop *>
1143 994 : (agent->nexthop_table()->FindActiveEntry(&key2));
1144 :
1145 : InterfaceNHKey key3(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1146 994 : vmi->GetUuid(), vmi->name()), false,
1147 : (InterfaceNHFlags::INET4|
1148 : InterfaceNHFlags::MULTICAST),
1149 1988 : vmi->vm_mac());
1150 : l3_mcast_nh_no_policy_ = static_cast<NextHop *>
1151 994 : (agent->nexthop_table()->FindActiveEntry(&key3));
1152 :
1153 : // Update L3 mpls label from nh entry
1154 994 : if (vmi->policy_enabled()) {
1155 992 : l3_label_ = l3_nh_policy_->mpls_label()->label();
1156 : } else {
1157 2 : l3_label_ = l3_nh_no_policy_->mpls_label()->label();
1158 : }
1159 :
1160 994 : return true;
1161 994 : }
1162 :
1163 1161 : bool NextHopState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
1164 : // Delete is called independent of interface active-state.
1165 : // Keep NH as long as interface is active and layer3-forwarding is enabled
1166 : // TODO : It should be ok to keep the NH even if l3-forwarding is disabled?
1167 1161 : if (vmi->IsActive() && vmi->layer3_forwarding())
1168 994 : return false;
1169 :
1170 167 : l3_mcast_nh_no_policy_.reset();
1171 167 : l3_nh_policy_.reset();
1172 167 : l3_nh_no_policy_.reset();
1173 167 : l3_label_ = MplsTable::kInvalidLabel;
1174 167 : InterfaceNH::DeleteMulticastVmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1175 : vmi->name());
1176 167 : InterfaceNH::DeleteL3InterfaceNH(vmi->GetUuid(), vmi->vm_mac(), vmi->name());
1177 167 : return true;
1178 : }
1179 :
1180 0 : const NextHop* VmInterface::l3_interface_nh_no_policy() const {
1181 0 : return nexthop_state_->l3_nh_no_policy_.get();
1182 : }
1183 :
1184 0 : const NextHop* VmInterface::l2_interface_nh_no_policy() const {
1185 0 : return nexthop_state_->l2_nh_no_policy_.get();
1186 : }
1187 :
1188 0 : const NextHop* VmInterface::l2_interface_nh_policy() const {
1189 0 : return nexthop_state_->l2_nh_policy_.get();
1190 : }
1191 :
1192 0 : uint32_t VmInterface::label_op() const {
1193 0 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
1194 0 : if (nexthop_state_->GetOpL3(agent, this) == VmInterfaceState::INVALID)
1195 0 : return MplsTable::kInvalidLabel;
1196 :
1197 0 : if (policy_enabled_)
1198 0 : return nexthop_state_->l3_nh_no_policy_->mpls_label()->label();
1199 : else
1200 0 : return nexthop_state_->l3_nh_policy_->mpls_label()->label();
1201 : }
1202 :
1203 2658 : void VmInterface::GetNextHopInfo() {
1204 2658 : l2_label_ = nexthop_state_->l2_label();
1205 2658 : label_ = nexthop_state_->l3_label();
1206 : // If Layer3 forwarding is configured irrespective of ipv4/v6 status,
1207 : // flow_key_nh should be l3 based.
1208 2658 : if (layer3_forwarding()) {
1209 2012 : flow_key_nh_ = nexthop_state_->l3_nh_policy_;
1210 : } else {
1211 646 : flow_key_nh_ = nexthop_state_->l2_nh_policy_;
1212 : }
1213 2658 : }
1214 :
1215 : ////////////////////////////////////////////////////////////////////////////
1216 : // MetaData Ip Routines
1217 : ////////////////////////////////////////////////////////////////////////////
1218 53038 : MetaDataIpState::MetaDataIpState(bool ipv4)
1219 : :
1220 53038 : VmInterfaceState(), mdata_ip_(), ipv4_(ipv4) {
1221 53038 : }
1222 :
1223 106076 : MetaDataIpState::~MetaDataIpState() {
1224 53038 : mdata_ip_.reset(NULL);
1225 106076 : }
1226 :
1227 : // metadata-ip is deleted after all update processing by explicitly
1228 : // calling delete. So, dont return DEL operation from here
1229 2658 : VmInterfaceState::Op MetaDataIpState::GetOpL3(const Agent *agent,
1230 : const VmInterface *vmi) const {
1231 4978 : if (vmi->need_linklocal_ip() == false ||
1232 2320 : vmi->metadata_ip_active() == false)
1233 674 : return VmInterfaceState::INVALID;
1234 :
1235 1984 : return VmInterfaceState::ADD;
1236 : }
1237 :
1238 1984 : bool MetaDataIpState::AddL3(const Agent *agent, VmInterface *vmi) const {
1239 1984 : if (mdata_ip_.get() == NULL) {
1240 330 : mdata_ip_.reset(new MetaDataIp(
1241 330 : ipv4_ ? agent->metadata_ip_allocator() :
1242 165 : agent->metadata_ip6_allocator(),
1243 : vmi,
1244 330 : vmi->id(), ipv4_));
1245 : }
1246 1984 : mdata_ip_->set_active(true);
1247 1984 : vmi->UpdateMetaDataIpInfo();
1248 1984 : return true;
1249 : }
1250 :
1251 : // Delete meta-data route
1252 2314 : bool MetaDataIpState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
1253 2314 : if (vmi->metadata_ip_active() && vmi->need_linklocal_ip())
1254 1984 : return false;
1255 :
1256 330 : if (mdata_ip_.get() == NULL) {
1257 0 : return true;
1258 : }
1259 :
1260 : // Call UpdateMetaDataIpInfo before setting mdata_ip_ state to inactive
1261 330 : vmi->UpdateMetaDataIpInfo();
1262 330 : mdata_ip_->set_active(false);
1263 330 : return true;
1264 : }
1265 :
1266 0 : Ip4Address VmInterface::mdata_ip_addr() const {
1267 0 : if (metadata_ip_state_.get() == NULL)
1268 0 : return Ip4Address(0);
1269 :
1270 0 : if (metadata_ip_state_->mdata_ip_.get() == NULL) {
1271 0 : return Ip4Address(0);
1272 : }
1273 :
1274 0 : return metadata_ip_state_->mdata_ip_->GetLinkLocalIp4();
1275 : }
1276 :
1277 165 : Ip6Address VmInterface::mdata_ip6_addr() const {
1278 165 : if (metadata_ip6_state_.get() == NULL)
1279 0 : return Ip6Address();
1280 :
1281 165 : if (metadata_ip6_state_->mdata_ip_.get() == NULL) {
1282 0 : return Ip6Address();
1283 : }
1284 :
1285 165 : return metadata_ip6_state_->mdata_ip_->GetLinkLocalIp6();
1286 : }
1287 :
1288 : ////////////////////////////////////////////////////////////////////////////
1289 : // ResolveRoute Attribute Routines
1290 : ////////////////////////////////////////////////////////////////////////////
1291 26519 : ResolveRouteState::ResolveRouteState() :
1292 26519 : VmInterfaceState(), vrf_(NULL), subnet_(), plen_(0) {
1293 26519 : }
1294 :
1295 53038 : ResolveRouteState::~ResolveRouteState() {
1296 53038 : }
1297 :
1298 1329 : void ResolveRouteState::Copy(const Agent *agent, const VmInterface *vmi) const {
1299 1329 : vrf_ = vmi->forwarding_vrf();
1300 1329 : subnet_ = vmi->subnet();
1301 1329 : plen_ = vmi->subnet_plen();
1302 1329 : }
1303 :
1304 1329 : VmInterfaceState::Op ResolveRouteState::GetOpL3(const Agent *agent,
1305 : const VmInterface *vmi) const {
1306 1329 : if (vmi->ipv4_active() == false)
1307 335 : return VmInterfaceState::DEL;
1308 :
1309 1821 : if (vrf_ != vmi->forwarding_vrf() || subnet_ != vmi->subnet() ||
1310 827 : plen_ != vmi->subnet_plen())
1311 167 : return VmInterfaceState::DEL_ADD;
1312 :
1313 827 : return VmInterfaceState::ADD;
1314 : }
1315 :
1316 2 : bool ResolveRouteState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
1317 2 : if (vrf_ == NULL)
1318 0 : return false;
1319 :
1320 2 : vmi->DeleteRoute(vrf_->GetName(), subnet_, plen_);
1321 2 : return true;
1322 : }
1323 :
1324 994 : bool ResolveRouteState::AddL3(const Agent *agent, VmInterface *vmi) const {
1325 : /* No need to add resolve route for VHOST in case of l3mh */
1326 994 : if (agent && agent->is_l3mh() && vmi->vmi_type() == VmInterface::VHOST) {
1327 0 : return true;
1328 : }
1329 :
1330 994 : if (vrf_ == NULL || subnet_.is_unspecified())
1331 992 : return false;
1332 :
1333 2 : if (vmi->vmi_type() != VmInterface::VHOST) {
1334 0 : if (vmi->vn() == NULL) {
1335 0 : return false;
1336 : }
1337 : }
1338 :
1339 2 : SecurityGroupList sg_id_list;
1340 2 : vmi->CopySgIdList(&sg_id_list);
1341 :
1342 2 : TagList tag_id_list;
1343 2 : vmi->CopyTagIdList(&tag_id_list);
1344 :
1345 2 : std::string vn_name;
1346 2 : if (vmi->vn() != NULL) {
1347 0 : vn_name = vmi->vn()->GetName();
1348 : }
1349 :
1350 2 : bool policy = vmi->policy_enabled();
1351 2 : if (vmi->vmi_type() == VmInterface::VHOST) {
1352 2 : policy = false;
1353 : }
1354 :
1355 2 : VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, vmi->GetUuid(), vmi->name());
1356 : InetUnicastAgentRouteTable::AddResolveRoute
1357 2 : (vmi->peer(), vrf_->GetName(),
1358 2 : Address::GetIp4SubnetAddress(subnet_, plen_), plen_, key,
1359 2 : vrf_->table_label(), policy, vn_name,
1360 : sg_id_list, tag_id_list);
1361 2 : return true;
1362 2 : }
1363 :
1364 : // If the interface is Gateway we need to add a receive route,
1365 : // such the packet gets routed. Bridging on gateway
1366 : // interface is not supported
1367 1329 : VmInterfaceState::Op ResolveRouteState::GetOpL2(const Agent *agent,
1368 : const VmInterface *vmi) const {
1369 2658 : if ((vmi->vmi_type() != VmInterface::GATEWAY &&
1370 1329 : vmi->vmi_type() != VmInterface::REMOTE_VM))
1371 1329 : return VmInterfaceState::DEL;
1372 :
1373 0 : if (vmi->bridging() == false)
1374 0 : return VmInterfaceState::DEL;
1375 :
1376 0 : if (vrf_ != vmi->forwarding_vrf())
1377 0 : return VmInterfaceState::DEL_ADD;
1378 :
1379 0 : return VmInterfaceState::ADD;
1380 : }
1381 :
1382 0 : bool ResolveRouteState::DeleteL2(const Agent *agent, VmInterface *vmi) const {
1383 0 : if (vrf_ == NULL)
1384 0 : return false;
1385 :
1386 0 : BridgeAgentRouteTable::Delete(vmi->peer(), vrf_->GetName(),
1387 : vmi->GetVifMac(agent), 0);
1388 0 : return true;
1389 : }
1390 :
1391 0 : bool ResolveRouteState::AddL2(const Agent *agent, VmInterface *vmi) const {
1392 0 : if (vrf_ == NULL || vmi->vn() == NULL)
1393 0 : return false;
1394 :
1395 : BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
1396 0 : (vrf_->GetRouteTable(Agent::BRIDGE));
1397 0 : table->AddBridgeReceiveRoute(vmi->peer(), vrf_->GetName(), 0,
1398 : vmi->GetVifMac(agent), vmi->vn()->GetName());
1399 0 : return true;
1400 : }
1401 :
1402 : ////////////////////////////////////////////////////////////////////////////
1403 : // VmiRouteState Routines
1404 : // This is responsible to manage following routes,
1405 : // - Manages the <0.0.0.0, MAC> EVPN route for the interface
1406 : // - Manage the L3 route for dhcp-relay when do_dhcp_relay_ is enabled
1407 : // ip_ here is set to primary-ip when do_dhcp_relay_ is enabled
1408 : // When do_dhcp_relay_ is enabled, adds route for ip_ along with service-ip.
1409 : //
1410 : // Note, instance-ip can also potentially add/delete route for same ip-address
1411 : ////////////////////////////////////////////////////////////////////////////
1412 26519 : VmiRouteState::VmiRouteState() :
1413 53038 : VmInterfaceState(), vrf_(NULL), ip_(), ethernet_tag_(0),
1414 26519 : do_dhcp_relay_(false) {
1415 26519 : }
1416 :
1417 53038 : VmiRouteState::~VmiRouteState() {
1418 53038 : }
1419 :
1420 1329 : void VmiRouteState::Copy(const Agent *agent, const VmInterface *vmi) const {
1421 1329 : vrf_ = vmi->vrf();
1422 1329 : ethernet_tag_ = vmi->ethernet_tag();
1423 1329 : do_dhcp_relay_ = vmi->do_dhcp_relay();
1424 1329 : ip_ = do_dhcp_relay_ ? ip_ = vmi->dhcp_addr() : Ip4Address(0);
1425 1329 : }
1426 :
1427 1329 : VmInterfaceState::Op VmiRouteState::GetOpL3
1428 : (const Agent *agent, const VmInterface *vmi) const {
1429 1329 : if (vmi->ipv4_active() == false)
1430 335 : return VmInterfaceState::DEL;
1431 :
1432 : // On do_dhcp_relay_ change from enable to disbale, delete the route
1433 : // Normally, we should not look at old value of do_dhcp_relay_ here, but
1434 : // ignoring it will result in delete and add of route for primary-ip
1435 : // Check old value of do_dhcp_relay_ to avoid this
1436 : //
1437 : // Even on transition, if instance-ip is present matching the primary-ip
1438 : // the route will added again due to instance-ip later
1439 994 : if (do_dhcp_relay_ && vmi->do_dhcp_relay() == false)
1440 0 : return VmInterfaceState::DEL;
1441 :
1442 994 : if (vrf_ != vmi->vrf())
1443 167 : return VmInterfaceState::DEL_ADD;
1444 :
1445 827 : if (ip_ != vmi->dhcp_addr())
1446 0 : return VmInterfaceState::DEL_ADD;
1447 :
1448 : // Dont have to add L3 route if DHCP Relay not enabled
1449 827 : if (vmi->do_dhcp_relay() == false)
1450 827 : return VmInterfaceState::INVALID;
1451 :
1452 0 : return VmInterfaceState::ADD;
1453 : }
1454 :
1455 0 : bool VmiRouteState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
1456 0 : if (vrf_ == NULL || ip_.is_unspecified())
1457 0 : return false;
1458 :
1459 0 : vmi->DeleteRoute(vrf_->GetName(), ip_, 32);
1460 0 : return true;
1461 : }
1462 :
1463 167 : bool VmiRouteState::AddL3(const Agent *agent, VmInterface *vmi) const {
1464 167 : if (vrf_ == NULL || vmi->vn() == NULL || ip_.is_unspecified())
1465 167 : return false;
1466 :
1467 : /* expected only for instance IP */
1468 0 : vmi->AddRoute(vrf_->GetName(), ip_, 32, vmi->vn()->GetName(), false,
1469 0 : vmi->ecmp(), false, false, vmi->vm_ip_service_addr(),
1470 0 : Ip4Address(0), CommunityList(), vmi->label(),
1471 : VmInterface::kInterface);
1472 0 : return true;
1473 : }
1474 :
1475 1329 : VmInterfaceState::Op VmiRouteState::GetOpL2
1476 : (const Agent *agent, const VmInterface *vmi) const {
1477 1329 : if (vmi->l2_active() == false || vmi->is_hc_active() == false)
1478 335 : return VmInterfaceState::DEL;
1479 :
1480 994 : if (vrf_ != vmi->vrf())
1481 167 : return VmInterfaceState::DEL_ADD;
1482 :
1483 827 : if (ethernet_tag_ != vmi->ethernet_tag())
1484 0 : return VmInterfaceState::DEL_ADD;
1485 :
1486 827 : return VmInterfaceState::ADD;
1487 : }
1488 :
1489 165 : bool VmiRouteState::DeleteL2(const Agent *agent, VmInterface *vmi) const {
1490 165 : if (vrf_ == NULL)
1491 0 : return false;
1492 :
1493 165 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, Ip4Address(0),
1494 : vmi->vm_mac());
1495 165 : return true;
1496 : }
1497 :
1498 994 : bool VmiRouteState::AddL2(const Agent *agent, VmInterface *vmi) const {
1499 994 : if (vrf_ == NULL || vmi->vn() == NULL)
1500 2 : return false;
1501 :
1502 992 : vmi->AddL2InterfaceRoute(Ip4Address(), vmi->vm_mac(), Ip4Address(0));
1503 : BridgeAgentRouteTable *table =
1504 992 : static_cast<BridgeAgentRouteTable *>(vrf_->GetRouteTable(Agent::BRIDGE));
1505 992 : if(table != NULL){
1506 992 : if(table->FindRoute(agent->vrrp_mac())){
1507 992 : return true;
1508 : }else{
1509 0 : table->AddBridgeReceiveRoute(agent->local_vm_peer(),
1510 0 : vrf_->GetName(),
1511 : 0,
1512 : agent->vrrp_mac(),
1513 : "");
1514 : }
1515 : }
1516 0 : return true;
1517 : }
1518 :
1519 : /////////////////////////////////////////////////////////////////////////////
1520 : // InstanceIp routines. Manages following,
1521 : // - Manages the L3 and L2 routes derived from the instance-ip.
1522 : /////////////////////////////////////////////////////////////////////////////
1523 182 : void VmInterface::InstanceIpList::Insert(const InstanceIp *rhs) {
1524 182 : list_.insert(*rhs);
1525 182 : }
1526 :
1527 838 : void VmInterface::InstanceIpList::Update(const InstanceIp *lhs,
1528 : const InstanceIp *rhs) {
1529 838 : lhs->ecmp_ = rhs->ecmp_;
1530 838 : lhs->is_service_ip_ = rhs->is_service_ip_;
1531 838 : lhs->is_service_health_check_ip_ = rhs->is_service_health_check_ip_;
1532 838 : lhs->is_local_ = rhs->is_local_;
1533 838 : lhs->tracking_ip_ = rhs->tracking_ip_;
1534 :
1535 838 : lhs->set_del_pending(false);
1536 838 : }
1537 :
1538 182 : void VmInterface::InstanceIpList::Remove(InstanceIpSet::iterator &it) {
1539 182 : it->set_del_pending(true);
1540 182 : }
1541 :
1542 2658 : bool VmInterface::InstanceIpList::UpdateList
1543 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
1544 : VmInterfaceState::Op l3_force_op) {
1545 2658 : InstanceIpSet::iterator it = list_.begin();
1546 : // Apply the instance-ip configured for interface
1547 3862 : while (it != list_.end()) {
1548 1204 : InstanceIpSet::iterator prev = it++;
1549 1204 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
1550 1204 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
1551 1204 : if (prev->del_pending() == false)
1552 1024 : prev->SetPrefixForAllocUnitIpam(vmi);
1553 1204 : vmi->UpdateState(&(*prev), l2_op, l3_op);
1554 1204 : if (prev->del_pending()) {
1555 180 : list_.erase(prev);
1556 : }
1557 : }
1558 :
1559 2658 : return true;
1560 : }
1561 :
1562 55858 : VmInterface::InstanceIp::InstanceIp() :
1563 111716 : ListEntry(), VmInterfaceState(), ip_(), plen_(), ecmp_(false),
1564 55858 : is_primary_(false), is_service_ip_(false),
1565 55858 : is_service_health_check_ip_(false), is_local_(false),
1566 55858 : tracking_ip_(), vrf_(NULL), ethernet_tag_(0) {
1567 55858 : }
1568 :
1569 4828 : VmInterface::InstanceIp::InstanceIp(const InstanceIp &rhs) :
1570 4828 : ListEntry(rhs.del_pending_),
1571 4828 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
1572 9656 : ip_(rhs.ip_), plen_(rhs.plen_), ecmp_(rhs.ecmp_),
1573 4828 : is_primary_(rhs.is_primary_), is_service_ip_(rhs.is_service_ip_),
1574 4828 : is_service_health_check_ip_(rhs.is_service_health_check_ip_),
1575 4828 : is_local_(rhs.is_local_), tracking_ip_(rhs.tracking_ip_),
1576 4828 : vrf_(NULL), ethernet_tag_(0) {
1577 4828 : }
1578 :
1579 1986 : VmInterface::InstanceIp::InstanceIp(const IpAddress &addr, uint8_t plen,
1580 : bool ecmp, bool is_primary,
1581 : bool is_service_ip,
1582 : bool is_service_health_check_ip,
1583 : bool is_local,
1584 1986 : const IpAddress &tracking_ip) :
1585 3972 : ListEntry(), VmInterfaceState(), ip_(addr), plen_(plen), ecmp_(ecmp),
1586 1986 : is_primary_(is_primary), is_service_ip_(is_service_ip),
1587 1986 : is_service_health_check_ip_(is_service_health_check_ip),
1588 1986 : is_local_(is_local), tracking_ip_(tracking_ip), vrf_(NULL),
1589 1986 : ethernet_tag_(0) {
1590 1986 : }
1591 :
1592 62672 : VmInterface::InstanceIp::~InstanceIp() {
1593 62672 : }
1594 :
1595 1920 : bool VmInterface::InstanceIp::operator() (const InstanceIp &lhs,
1596 : const InstanceIp &rhs) const {
1597 1920 : return lhs.IsLess(&rhs);
1598 : }
1599 :
1600 3596 : bool VmInterface::InstanceIp::IsLess(const InstanceIp *rhs) const {
1601 3596 : return ip_ < rhs->ip_;
1602 : }
1603 :
1604 1024 : void VmInterface::InstanceIp::SetPrefixForAllocUnitIpam(VmInterface *vmi) const{
1605 1024 : if (vmi->vn() == NULL)
1606 2 : return;
1607 :
1608 1022 : uint32_t alloc_unit = vmi->vn()->GetAllocUnitFromIpam(ip_);
1609 :
1610 1022 : uint8_t alloc_prefix = 0;
1611 1022 : if (alloc_unit > 0) {
1612 466 : alloc_prefix = log2(alloc_unit);
1613 : }
1614 :
1615 1022 : if (ip_.is_v4()) {
1616 994 : plen_ = Address::kMaxV4PrefixLen - alloc_prefix;
1617 28 : } else if (ip_.is_v6()) {
1618 28 : plen_ = Address::kMaxV6PrefixLen - alloc_prefix;
1619 : }
1620 : }
1621 :
1622 2408 : static bool GetInstanceIpActiveState(const VmInterface::InstanceIp *instance_ip,
1623 : const VmInterface *vmi) {
1624 2408 : if (instance_ip->is_service_health_check_ip_) {
1625 : // for service health check instance ip keep the route based on
1626 : // metadata-active state
1627 0 : return vmi->metadata_ip_active();
1628 : }
1629 :
1630 2408 : if (instance_ip->ip_.is_v6()) {
1631 82 : return vmi->ipv6_active();
1632 : }
1633 :
1634 2326 : return vmi->ipv4_active();
1635 : }
1636 :
1637 1204 : VmInterfaceState::Op VmInterface::InstanceIp::GetOpL2
1638 : (const Agent *agent, const VmInterface *vmi) const {
1639 1204 : if (GetInstanceIpActiveState(this, vmi) == false)
1640 182 : return VmInterfaceState::DEL;
1641 :
1642 1022 : if (!is_service_ip_ && vmi->vmi_type() != VmInterface::VHOST) {
1643 : // Add route only when vn IPAM exists for the IP
1644 1020 : if (vmi->vn() && vmi->vn()->GetIpam(ip_) == NULL)
1645 466 : return VmInterfaceState::DEL;
1646 : }
1647 :
1648 556 : if (IsL3Only())
1649 0 : return VmInterfaceState::DEL;
1650 :
1651 556 : if (vrf_ != vmi->vrf())
1652 26 : return VmInterfaceState::DEL_ADD;
1653 :
1654 530 : if (ethernet_tag_ != vmi->ethernet_tag())
1655 0 : return VmInterfaceState::DEL_ADD;
1656 :
1657 530 : return VmInterfaceState::ADD;
1658 : }
1659 :
1660 556 : bool VmInterface::InstanceIp::AddL2(const Agent *agent,
1661 : VmInterface *vmi) const {
1662 556 : if (vrf_ == NULL)
1663 0 : return false;
1664 :
1665 556 : vmi->AddL2InterfaceRoute(ip_, vmi->vm_mac(), tracking_ip_);
1666 556 : return true;
1667 : }
1668 :
1669 165 : bool VmInterface::InstanceIp::DeleteL2(const Agent *agent,
1670 : VmInterface *vmi) const {
1671 165 : if (vrf_ == NULL)
1672 0 : return false;
1673 :
1674 165 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, ip_, vmi->vm_mac());
1675 165 : return true;
1676 : }
1677 :
1678 1204 : VmInterfaceState::Op VmInterface::InstanceIp::GetOpL3
1679 : (const Agent *agent, const VmInterface *vmi) const {
1680 : // TODO : Should be check health-check state here?
1681 1204 : if (GetInstanceIpActiveState(this, vmi) == false)
1682 182 : return VmInterfaceState::DEL;
1683 :
1684 1022 : if (!is_service_ip_ && vmi->vmi_type() != VmInterface::VHOST) {
1685 : // Add route only when vn IPAM exists for the IP
1686 1020 : if (vmi->vn() && vmi->vn()->GetIpam(ip_) == NULL)
1687 466 : return VmInterfaceState::DEL;
1688 : }
1689 :
1690 556 : if (vrf_ != vmi->vrf())
1691 26 : return VmInterfaceState::DEL_ADD;
1692 :
1693 530 : return VmInterfaceState::ADD;
1694 : }
1695 :
1696 556 : bool VmInterface::InstanceIp::AddL3(const Agent *agent,
1697 : VmInterface *vmi) const {
1698 556 : if (vrf_ == NULL)
1699 0 : return false;
1700 556 : assert(ip_.is_unspecified() == false);
1701 556 : std::string vn_name;
1702 556 : if (vmi->vn()) {
1703 554 : vn_name = vmi->vn()->GetName();
1704 2 : } else if (vmi->vmi_type() == VHOST) {
1705 2 : vn_name = agent->fabric_vn_name();
1706 : }
1707 :
1708 2224 : vmi->AddRoute(vmi->vrf()->GetName(), ip_, plen_, vn_name,
1709 556 : is_force_policy(), ecmp_,is_local_,
1710 556 : is_service_health_check_ip_, vmi->GetServiceIp(ip_),
1711 1112 : tracking_ip_, CommunityList(), vmi->label(),
1712 556 : is_service_ip_ ? kServiceInterface : kInterface);
1713 556 : return true;
1714 556 : }
1715 :
1716 165 : bool VmInterface::InstanceIp::DeleteL3(const Agent *agent,
1717 : VmInterface *vmi) const {
1718 165 : if (vrf_ == NULL)
1719 0 : return false;
1720 165 : vmi->DeleteRoute(vrf_->GetName(), ip_, plen_);
1721 165 : return true;
1722 : }
1723 :
1724 1204 : void VmInterface::InstanceIp::Copy(const Agent *agent,
1725 : const VmInterface *vmi) const {
1726 1204 : vrf_ = vmi->vrf();
1727 1204 : ethernet_tag_ = vmi->ethernet_tag();
1728 1204 : }
1729 :
1730 : /////////////////////////////////////////////////////////////////////////////
1731 : // MacIp routines. Manages following,
1732 : // - Manages the L3 and L2 routes derived from the instance-ip.
1733 : /////////////////////////////////////////////////////////////////////////////
1734 0 : void VmInterface::LearntMacIpList::Insert(const LearntMacIp *rhs) {
1735 0 : list_.insert(*rhs);
1736 0 : }
1737 :
1738 0 : void VmInterface::LearntMacIpList::Update(const LearntMacIp *lhs,
1739 : const LearntMacIp *rhs) {
1740 :
1741 0 : lhs->set_del_pending(rhs->del_pending());
1742 0 : }
1743 :
1744 0 : void VmInterface::LearntMacIpList::Remove(const LearntMacIp *rhs) {
1745 0 : LearntMacIpSet::iterator it = list_.find(*rhs);
1746 0 : if (it != list_.end()) {
1747 0 : it->set_del_pending(true);
1748 : }
1749 0 : }
1750 :
1751 1329 : bool VmInterface::LearntMacIpList::UpdateList
1752 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
1753 : VmInterfaceState::Op l3_force_op) {
1754 1329 : LearntMacIpSet::iterator it = list_.begin();
1755 : // Apply the instance-ip configured for interface
1756 1329 : while (it != list_.end()) {
1757 0 : LearntMacIpSet::iterator prev = it++;
1758 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
1759 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
1760 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
1761 0 : if (prev->del_pending()) {
1762 0 : list_.erase(prev);
1763 : }
1764 : }
1765 :
1766 1329 : return true;
1767 : }
1768 :
1769 26519 : VmInterface::LearntMacIp::LearntMacIp() :
1770 26519 : ListEntry(), VmInterfaceState(), ip_(), mac_(),
1771 53038 : vrf_(NULL), ethernet_tag_(0) {
1772 26519 : }
1773 :
1774 0 : VmInterface::LearntMacIp::LearntMacIp(const LearntMacIp &rhs) :
1775 0 : ListEntry(rhs.del_pending_),
1776 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
1777 0 : ip_(rhs.ip_), mac_(rhs.mac_),
1778 0 : vrf_(NULL), ethernet_tag_(0) {
1779 0 : }
1780 :
1781 0 : VmInterface::LearntMacIp::LearntMacIp(const IpAddress &ip_addr,
1782 0 : const MacAddress &mac) :
1783 0 : ListEntry(), VmInterfaceState(), ip_(ip_addr), mac_(mac),
1784 0 : vrf_(NULL), ethernet_tag_(0) {
1785 0 : }
1786 :
1787 26519 : VmInterface::LearntMacIp::~LearntMacIp() {
1788 26519 : }
1789 :
1790 0 : static bool GetMacIpActiveState(const VmInterface::LearntMacIp *mac_ip,
1791 : const VmInterface *vmi) {
1792 : // supporting either L2 mode and L2/L3 mode
1793 0 : if (!vmi->l2_active()) {
1794 0 : return false;
1795 : }
1796 0 : if (mac_ip->ip_.is_v6()) {
1797 0 : return vmi->ipv6_active();
1798 : }
1799 :
1800 0 : return vmi->ipv4_active();
1801 : }
1802 0 : bool VmInterface::LearntMacIp::operator() (const LearntMacIp &lhs,
1803 : const LearntMacIp &rhs) const {
1804 0 : return lhs.IsLess(&rhs);
1805 : }
1806 :
1807 0 : bool VmInterface::LearntMacIp::IsLess(const LearntMacIp *rhs) const {
1808 0 : return ip_ < rhs->ip_;
1809 : }
1810 :
1811 0 : VmInterfaceState::Op VmInterface::LearntMacIp::GetOpL2
1812 : (const Agent *agent, const VmInterface *vmi) const {
1813 0 : if (del_pending() == true)
1814 0 : return VmInterfaceState::DEL;
1815 :
1816 :
1817 0 : if (vrf_ != vmi->vrf())
1818 0 : return VmInterfaceState::DEL_ADD;
1819 :
1820 0 : if (ethernet_tag_ != vmi->ethernet_tag())
1821 0 : return VmInterfaceState::DEL_ADD;
1822 :
1823 0 : return VmInterfaceState::ADD;
1824 : }
1825 :
1826 0 : bool VmInterface::LearntMacIp::AddL2(const Agent *agent,
1827 : VmInterface *vmi) const {
1828 : // IPVLAN subinterface will have the same mac as the parent interface mac
1829 : // skip adding the route, as these routes are already installed as part
1830 : // of parent interface add.
1831 0 : if (mac_.ToString() == vmi->vm_mac().ToString())
1832 0 : return true;
1833 :
1834 0 : if (vrf_ == NULL)
1835 0 : return false;
1836 0 : InterfaceNH::CreateL2VmInterfaceNH(vmi->GetUuid(), mac_,
1837 : vmi->forwarding_vrf()->GetName(),
1838 0 : vmi->learning_enabled(),
1839 0 : vmi->etree_leaf(),
1840 0 : vmi->layer2_control_word(),
1841 : vmi->name());
1842 :
1843 : InterfaceNHKey key1(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1844 0 : vmi->GetUuid(), vmi->name()),
1845 0 : true, InterfaceNHFlags::BRIDGE, mac_);
1846 : l2_nh_policy_ = static_cast<NextHop *>
1847 0 : (agent->nexthop_table()->FindActiveEntry(&key1));
1848 :
1849 : InterfaceNHKey key2(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1850 0 : vmi->GetUuid(), vmi->name()),
1851 0 : false, InterfaceNHFlags::BRIDGE, mac_);
1852 : l2_nh_no_policy_ = static_cast<NextHop *>
1853 0 : (agent->nexthop_table()->FindActiveEntry(&key2));
1854 :
1855 : // Update L2 mpls label from nh entry
1856 0 : if (vmi->policy_enabled()) {
1857 0 : l2_label_ = l2_nh_policy_->mpls_label()->label();
1858 : } else {
1859 0 : l2_label_ = l2_nh_no_policy_->mpls_label()->label();
1860 : }
1861 :
1862 0 : vmi->AddL2InterfaceRoute(IpAddress(), mac_, IpAddress());
1863 0 : return true;
1864 0 : }
1865 :
1866 0 : bool VmInterface::LearntMacIp::DeleteL2(const Agent *agent,
1867 : VmInterface *vmi) const {
1868 0 : if (vrf_ == NULL)
1869 0 : return false;
1870 :
1871 : // IPVLAN subinterface will have the same mac as the parent interface mac
1872 : // skip deleting the route as the parent interface is not deleted.
1873 0 : if (mac_.ToString() == vmi->vm_mac().ToString())
1874 0 : return true;
1875 :
1876 0 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, Ip4Address(0),
1877 0 : mac_);
1878 0 : l2_nh_policy_.reset();
1879 0 : l2_nh_no_policy_.reset();
1880 0 : l2_label_ = MplsTable::kInvalidLabel;
1881 0 : InterfaceNH::DeleteL2InterfaceNH(vmi->GetUuid(), mac_,
1882 : vmi->name());
1883 0 : return true;
1884 : }
1885 :
1886 0 : VmInterfaceState::Op VmInterface::LearntMacIp::GetOpL3
1887 : (const Agent *agent, const VmInterface *vmi) const {
1888 : // TODO : Should be check health-check state here?
1889 0 : if (GetMacIpActiveState(this, vmi) == false)
1890 0 : return VmInterfaceState::DEL;
1891 :
1892 0 : if (vrf_ != vmi->vrf())
1893 0 : return VmInterfaceState::DEL_ADD;
1894 :
1895 0 : if (ethernet_tag_ != vmi->ethernet_tag())
1896 0 : return VmInterfaceState::DEL_ADD;
1897 :
1898 0 : return VmInterfaceState::ADD;
1899 : }
1900 :
1901 0 : bool VmInterface::LearntMacIp::AddL3(const Agent *agent,
1902 : VmInterface *vmi) const {
1903 0 : if (vrf_ == NULL)
1904 0 : return false;
1905 0 : InterfaceNH::CreateL3VmInterfaceNH(vmi->GetUuid(), mac_,
1906 : vmi->forwarding_vrf()->GetName(),
1907 0 : vmi->learning_enabled(),
1908 : vmi->name());
1909 : InterfaceNHKey key1(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1910 0 : vmi->GetUuid(), vmi->name()),
1911 0 : true, InterfaceNHFlags::INET4, mac_);
1912 : l3_nh_policy_ = static_cast<NextHop *>
1913 0 : (agent->nexthop_table()->FindActiveEntry(&key1));
1914 :
1915 : InterfaceNHKey key2(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1916 0 : vmi->GetUuid(), vmi->name()),
1917 0 : false, InterfaceNHFlags::INET4, mac_);
1918 : l3_nh_no_policy_ = static_cast<NextHop *>
1919 0 : (agent->nexthop_table()->FindActiveEntry(&key2));
1920 : // Update L3 mpls label from nh entry
1921 0 : if (vmi->policy_enabled()) {
1922 0 : l3_label_ = l3_nh_policy_->mpls_label()->label();
1923 : } else {
1924 0 : l3_label_ = l3_nh_no_policy_->mpls_label()->label();
1925 : }
1926 0 : std::string vn_name;
1927 0 : if (vmi->vn()) {
1928 0 : vn_name = vmi->vn()->GetName();
1929 : }
1930 0 : uint32_t plen = 0;
1931 0 : if (ip_.is_v4()) {
1932 0 : plen = Address::kMaxV4PrefixLen;
1933 : } else {
1934 0 : plen = Address::kMaxV6PrefixLen;
1935 : }
1936 :
1937 :
1938 0 : vmi->AddL2InterfaceRoute(ip_, mac_, IpAddress());
1939 0 : vmi->AddRoute(vrf_->GetName(), ip_, plen, vmi->vn()->GetName(), false,
1940 0 : false, false, false, vmi->vm_ip_service_addr(),
1941 0 : Ip4Address(0), CommunityList(), l3_label_,
1942 : VmInterface::kInterface, true);
1943 0 : return true;
1944 0 : }
1945 :
1946 0 : bool VmInterface::LearntMacIp::DeleteL3(const Agent *agent,
1947 : VmInterface *vmi) const {
1948 0 : if (vrf_ == NULL)
1949 0 : return false;
1950 0 : uint32_t plen = 0;
1951 0 : if (ip_.is_v4()) {
1952 0 : plen = Address::kMaxV4PrefixLen;
1953 : } else {
1954 0 : plen = Address::kMaxV6PrefixLen;
1955 : }
1956 0 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, ip_, mac_);
1957 0 : vmi->DeleteRoute(vrf_->GetName(), ip_, plen);
1958 0 : InterfaceNH::DeleteL3InterfaceNH(vmi->GetUuid(),
1959 0 : mac_, vmi->name());
1960 0 : l3_nh_policy_.reset();
1961 0 : l3_nh_no_policy_.reset();
1962 0 : return true;
1963 : }
1964 :
1965 0 : void VmInterface::LearntMacIp::Copy(const Agent *agent,
1966 : const VmInterface *vmi) const {
1967 0 : vrf_ = vmi->vrf();
1968 0 : ethernet_tag_ = vmi->ethernet_tag();
1969 0 : }
1970 :
1971 0 : bool VmInterface::IsMaxMacIpLearnt() const {
1972 0 : if (learnt_mac_ip_list_.list_.size() >= kMaxMacIpLimit) {
1973 0 : return true;
1974 : }
1975 0 : return false;
1976 : }
1977 : /////////////////////////////////////////////////////////////////////////////
1978 : // FloatingIp routines
1979 : /////////////////////////////////////////////////////////////////////////////
1980 1329 : void VmInterface::CleanupFloatingIpList() {
1981 1329 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
1982 1329 : FloatingIpSet::iterator it = floating_ip_list_.list_.begin();
1983 1638 : while (it != floating_ip_list_.list_.end()) {
1984 309 : FloatingIpSet::iterator prev = it++;
1985 309 : if (prev->del_pending_ == false)
1986 196 : continue;
1987 :
1988 : // The floating-ip is leaving the interface configuration, which is
1989 : // the only trigger that withdraws its DNS record. DeleteL3() does not
1990 : // withdraw, so that the record survives the instance being powered
1991 : // off, and an entry configured while the interface was inactive never
1992 : // reached DeleteL3() in the first place.
1993 : //
1994 : // vn_ has been reset by FloatingIp::Copy() by now, hence the lookup by
1995 : // uuid. It returns NULL once the VN is deleted, which is not a missed
1996 : // withdraw: DnsProto::VnNotify() withdraws and erases every record of
1997 : // a deleted VN, so there is nothing left to withdraw by then.
1998 113 : if (table->update_floatingip_cb().empty() == false) {
1999 113 : VnEntry *vn = table->FindVnRef(prev->vn_uuid_);
2000 113 : if (vn != NULL) {
2001 113 : table->update_floatingip_cb()(this, vn, prev->floating_ip_,
2002 : true);
2003 : }
2004 : }
2005 :
2006 113 : if (prev->floating_ip_.is_v4()) {
2007 113 : floating_ip_list_.v4_count_--;
2008 : assert(floating_ip_list_.v4_count_ >= 0);
2009 : } else {
2010 0 : floating_ip_list_.v6_count_--;
2011 : assert(floating_ip_list_.v6_count_ >= 0);
2012 : }
2013 113 : floating_ip_list_.list_.erase(prev);
2014 : }
2015 1329 : }
2016 :
2017 113 : void VmInterface::FloatingIpList::Insert(const FloatingIp *rhs) {
2018 113 : std::pair<FloatingIpSet::iterator, bool> ret = list_.insert(*rhs);
2019 113 : if (ret.second) {
2020 113 : if (rhs->floating_ip_.is_v4()) {
2021 113 : v4_count_++;
2022 : } else {
2023 0 : v6_count_++;
2024 : }
2025 : }
2026 113 : }
2027 :
2028 78 : void VmInterface::FloatingIpList::Update(const FloatingIp *lhs,
2029 : const FloatingIp *rhs) {
2030 78 : if (lhs->fixed_ip_ != rhs->fixed_ip_) {
2031 78 : lhs->fixed_ip_ = rhs->fixed_ip_;
2032 : }
2033 :
2034 78 : lhs->direction_ = rhs->direction_;
2035 78 : lhs->port_map_enabled_ = rhs->port_map_enabled_;
2036 78 : lhs->src_port_map_ = rhs->src_port_map_;
2037 78 : lhs->dst_port_map_ = rhs->dst_port_map_;
2038 78 : lhs->set_del_pending(false);
2039 78 : }
2040 :
2041 113 : void VmInterface::FloatingIpList::Remove(FloatingIpSet::iterator &it) {
2042 113 : it->set_del_pending(true);
2043 113 : }
2044 :
2045 1329 : bool VmInterface::FloatingIpList::UpdateList(const Agent *agent,
2046 : VmInterface *vmi,
2047 : VmInterfaceState::Op l2_force_op,
2048 : VmInterfaceState::Op l3_force_op) {
2049 1329 : FloatingIpSet::iterator it = list_.begin();
2050 1638 : while (it != list_.end()) {
2051 309 : FloatingIpSet::iterator prev = it++;
2052 309 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2053 309 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2054 309 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2055 : }
2056 1329 : return true;
2057 : }
2058 :
2059 30144 : VmInterface::FloatingIp::FloatingIp() :
2060 30144 : ListEntry(), VmInterfaceState(), floating_ip_(), vn_(NULL),
2061 30144 : vrf_(NULL, this), vrf_name_(""), vn_uuid_(),
2062 30144 : fixed_ip_(), direction_(DIRECTION_BOTH), port_map_enabled_(false),
2063 60288 : src_port_map_(), dst_port_map_(), ethernet_tag_(0), port_nat_(false) {
2064 30144 : }
2065 :
2066 1223 : VmInterface::FloatingIp::FloatingIp(const FloatingIp &rhs) :
2067 1223 : ListEntry(rhs.del_pending_),
2068 1223 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2069 1223 : floating_ip_(rhs.floating_ip_), vn_(rhs.vn_), vrf_(rhs.vrf_, this),
2070 1223 : vrf_name_(rhs.vrf_name_), vn_uuid_(rhs.vn_uuid_), fixed_ip_(rhs.fixed_ip_),
2071 1223 : direction_(rhs.direction_), port_map_enabled_(rhs.port_map_enabled_),
2072 1223 : src_port_map_(rhs.src_port_map_), dst_port_map_(rhs.dst_port_map_),
2073 1223 : ethernet_tag_(rhs.ethernet_tag_), port_nat_(rhs.port_nat_) {
2074 1223 : }
2075 :
2076 191 : VmInterface::FloatingIp::FloatingIp(const IpAddress &addr,
2077 : const std::string &vrf,
2078 : const boost::uuids::uuid &vn_uuid,
2079 : const IpAddress &fixed_ip,
2080 : Direction direction,
2081 : bool port_map_enabled,
2082 : const PortMap &src_port_map,
2083 : const PortMap &dst_port_map,
2084 191 : bool port_nat) :
2085 191 : ListEntry(), VmInterfaceState(),floating_ip_(addr), vn_(NULL),
2086 191 : vrf_(NULL, this), vrf_name_(vrf), vn_uuid_(vn_uuid), fixed_ip_(fixed_ip),
2087 191 : direction_(direction), port_map_enabled_(port_map_enabled),
2088 191 : src_port_map_(src_port_map), dst_port_map_(dst_port_map), ethernet_tag_(0),
2089 191 : port_nat_(port_nat) {
2090 191 : }
2091 :
2092 31558 : VmInterface::FloatingIp::~FloatingIp() {
2093 31558 : }
2094 :
2095 156 : bool VmInterface::FloatingIp::operator() (const FloatingIp &lhs,
2096 : const FloatingIp &rhs) const {
2097 156 : return lhs.IsLess(&rhs);
2098 : }
2099 :
2100 : // Compare key for FloatingIp. Key is <floating_ip_ and vrf_name_> for both
2101 : // Config and Operational processing
2102 312 : bool VmInterface::FloatingIp::IsLess(const FloatingIp *rhs) const {
2103 312 : if (floating_ip_ != rhs->floating_ip_)
2104 0 : return floating_ip_ < rhs->floating_ip_;
2105 :
2106 312 : return (vrf_name_ < rhs->vrf_name_);
2107 : }
2108 :
2109 : const IpAddress
2110 431 : VmInterface::FloatingIp::GetFixedIp(const VmInterface *vmi) const {
2111 431 : if (fixed_ip_.is_unspecified()) {
2112 191 : if (floating_ip_.is_v4() == true) {
2113 191 : return vmi->primary_ip_addr();
2114 : } else {
2115 0 : return vmi->primary_ip6_addr();
2116 : }
2117 : }
2118 240 : return fixed_ip_;
2119 : }
2120 :
2121 43 : bool VmInterface::FloatingIp::port_map_enabled() const {
2122 43 : return port_map_enabled_;
2123 : }
2124 :
2125 0 : uint32_t VmInterface::FloatingIp::PortMappingSize() const {
2126 0 : return src_port_map_.size();
2127 : }
2128 :
2129 4 : bool VmInterface::FloatingIp::port_nat() const {
2130 4 : return port_nat_;
2131 : }
2132 :
2133 0 : int32_t VmInterface::FloatingIp::GetSrcPortMap(uint8_t protocol,
2134 : uint16_t src_port) const {
2135 0 : PortMapIterator it = src_port_map_.find(PortMapKey(protocol, src_port));
2136 0 : if (it == src_port_map_.end())
2137 0 : return -1;
2138 0 : return it->second;
2139 : }
2140 :
2141 0 : int32_t VmInterface::FloatingIp::GetDstPortMap(uint8_t protocol,
2142 : uint16_t dst_port) const {
2143 0 : PortMapIterator it = dst_port_map_.find(PortMapKey(protocol, dst_port));
2144 0 : if (it == dst_port_map_.end())
2145 0 : return -1;
2146 0 : return it->second;
2147 : }
2148 :
2149 309 : void VmInterface::FloatingIp::Copy(const Agent *agent,
2150 : const VmInterface *vmi) const {
2151 : // Delete for FloatingIp happens in CleanupFloatingIpList(). So, dont
2152 : // update vn_ and vrf_ fields in case of delete
2153 309 : if (del_pending_) {
2154 113 : vn_ = NULL;
2155 113 : vrf_ = NULL;
2156 113 : return;
2157 : }
2158 :
2159 196 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
2160 196 : if (vn_.get() == NULL)
2161 113 : vn_ = table->FindVnRef(vn_uuid_);
2162 :
2163 196 : if (vrf_.get() == NULL)
2164 113 : vrf_ = table->FindVrfRef(vrf_name_);
2165 196 : ethernet_tag_ = vmi->ethernet_tag();
2166 :
2167 196 : return;
2168 : }
2169 :
2170 309 : VmInterfaceState::Op VmInterface::FloatingIp::GetOpL3
2171 : (const Agent *agent, const VmInterface *vmi) const {
2172 309 : if (GetIpActiveState(floating_ip_, vmi) == false)
2173 6 : return VmInterfaceState::DEL;
2174 :
2175 303 : if (vmi->vrf() == NULL || vmi->vn() == NULL)
2176 0 : return VmInterfaceState::DEL;
2177 :
2178 303 : return VmInterfaceState::ADD;
2179 : }
2180 :
2181 196 : bool VmInterface::FloatingIp::AddL3(const Agent *agent,
2182 : VmInterface *vmi) const {
2183 196 : if (vrf_.get() == NULL || vn_.get() == NULL || port_nat_)
2184 0 : return false;
2185 :
2186 196 : fixed_ip_ = GetFixedIp(vmi);
2187 196 : uint8_t plen = floating_ip_.is_v4() ?
2188 196 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2189 196 : IpAddress service_ip = Ip4Address();
2190 196 : if (floating_ip_.is_v6())
2191 0 : service_ip = Ip6Address();
2192 :
2193 196 : bool ecmp = floating_ip_.is_v4() ? vmi->ecmp() : vmi->ecmp6();
2194 588 : vmi->AddRoute(vrf_.get()->GetName(), floating_ip_, plen, vn_->GetName(),
2195 196 : false, ecmp, false, false, service_ip, fixed_ip_,
2196 392 : CommunityList(), vmi->label(), kInterface);
2197 :
2198 196 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
2199 196 : if (table->update_floatingip_cb().empty() == false) {
2200 196 : table->update_floatingip_cb()(vmi, vn_.get(), floating_ip_,
2201 : false);
2202 : //TODO:: callback for DNS handling
2203 : }
2204 :
2205 196 : return true;
2206 : }
2207 :
2208 113 : bool VmInterface::FloatingIp::DeleteL3(const Agent *agent,
2209 : VmInterface *vmi) const {
2210 113 : if (vrf_.get() == NULL)
2211 0 : return false;
2212 113 : uint8_t plen = floating_ip_.is_v4() ?
2213 113 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2214 :
2215 113 : vmi->DeleteRoute(vrf_.get()->GetName(), floating_ip_, plen);
2216 :
2217 : // The DNS record is not withdrawn here. This routine runs whenever the
2218 : // interface stops forwarding, which includes the instance being powered
2219 : // off - the tap device goes away and ipv4_active() turns false. The
2220 : // record tracks floating-ip configuration, not forwarding state, the same
2221 : // way the interface's own DNS record does, so it has to survive that.
2222 : //
2223 : // Withdrawing it is CleanupFloatingIpList(), which ApplyConfig() always
2224 : // reaches after the floating-ip list is updated, and which also covers
2225 : // the entries that were never installed because the interface was
2226 : // inactive while they were configured.
2227 113 : return true;
2228 : }
2229 :
2230 309 : VmInterfaceState::Op VmInterface::FloatingIp::GetOpL2
2231 : (const Agent *agent, const VmInterface *vmi) const {
2232 309 : if (GetIpActiveState(floating_ip_, vmi) == false)
2233 6 : return VmInterfaceState::DEL;
2234 :
2235 303 : if (vmi->vrf() == NULL || vmi->vn() == NULL)
2236 0 : return VmInterfaceState::DEL;
2237 :
2238 303 : if (ethernet_tag_ != vmi->ethernet_tag())
2239 0 : return VmInterfaceState::DEL_ADD;
2240 :
2241 303 : return VmInterfaceState::ADD;
2242 : }
2243 :
2244 196 : bool VmInterface::FloatingIp::AddL2(const Agent *agent,
2245 : VmInterface *vmi) const {
2246 196 : if (vrf_.get() == NULL || vn_.get() == NULL || port_nat_)
2247 0 : return false;
2248 :
2249 196 : SecurityGroupList sg_id_list;
2250 196 : vmi->CopySgIdList(&sg_id_list);
2251 :
2252 196 : TagList tag_id_list;
2253 196 : vmi->CopyTagIdList(&tag_id_list);
2254 :
2255 196 : PathPreference path_preference;
2256 196 : vmi->SetPathPreference(&path_preference, false, GetFixedIp(vmi));
2257 :
2258 : EvpnAgentRouteTable *evpn_table = static_cast<EvpnAgentRouteTable *>
2259 196 : (vrf_->GetEvpnRouteTable());
2260 :
2261 196 : std::string vn_name;
2262 196 : if (vmi->vn()) {
2263 196 : vn_name = vmi->vn()->GetName();
2264 : }
2265 :
2266 196 : evpn_table->AddReceiveRoute(vmi->peer_.get(), vrf_->GetName(),
2267 196 : vmi->l2_label(), vmi->vm_mac(), floating_ip_,
2268 : ethernet_tag_, vn_name,
2269 : path_preference);
2270 196 : return true;
2271 196 : }
2272 :
2273 113 : bool VmInterface::FloatingIp::DeleteL2(const Agent *agent,
2274 : VmInterface *vmi) const {
2275 113 : if (vrf_.get() == NULL)
2276 0 : return false;
2277 :
2278 : EvpnAgentRouteTable *evpn_table =
2279 113 : static_cast<EvpnAgentRouteTable *>(vrf_->GetEvpnRouteTable());
2280 113 : if (evpn_table == NULL) {
2281 0 : return false;
2282 : }
2283 :
2284 113 : evpn_table->DelLocalVmRoute(vmi->peer_.get(), vrf_->GetName(),
2285 113 : vmi->vm_mac(), vmi, floating_ip_,
2286 : ethernet_tag_);
2287 113 : return true;
2288 : }
2289 :
2290 : /////////////////////////////////////////////////////////////////////////////
2291 : // AliasIp routines
2292 : /////////////////////////////////////////////////////////////////////////////
2293 0 : void VmInterface::AliasIpList::Insert(const AliasIp *rhs) {
2294 0 : std::pair<AliasIpSet::iterator, bool> ret = list_.insert(*rhs);
2295 0 : if (ret.second) {
2296 0 : if (rhs->alias_ip_.is_v4()) {
2297 0 : v4_count_++;
2298 : } else {
2299 0 : v6_count_++;
2300 : }
2301 : }
2302 0 : }
2303 :
2304 0 : void VmInterface::AliasIpList::Update(const AliasIp *lhs, const AliasIp *rhs) {
2305 0 : lhs->set_del_pending(false);
2306 0 : }
2307 :
2308 0 : void VmInterface::AliasIpList::Remove(AliasIpSet::iterator &it) {
2309 0 : it->set_del_pending(true);
2310 0 : }
2311 :
2312 1329 : bool VmInterface::AliasIpList::UpdateList(const Agent *agent, VmInterface *vmi,
2313 : VmInterfaceState::Op l2_force_op,
2314 : VmInterfaceState::Op l3_force_op) {
2315 1329 : AliasIpSet::iterator it = list_.begin();
2316 1329 : while (it != list_.end()) {
2317 0 : AliasIpSet::iterator prev = it++;
2318 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2319 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2320 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2321 : }
2322 1329 : return true;
2323 : }
2324 :
2325 1329 : void VmInterface::CleanupAliasIpList() {
2326 1329 : AliasIpSet::iterator it = alias_ip_list_.list_.begin();
2327 1329 : while (it != alias_ip_list_.list_.end()) {
2328 0 : AliasIpSet::iterator prev = it++;
2329 0 : if (prev->del_pending_ == false)
2330 0 : continue;
2331 :
2332 0 : if (prev->alias_ip_.is_v4()) {
2333 0 : alias_ip_list_.v4_count_--;
2334 : assert(alias_ip_list_.v4_count_ >= 0);
2335 : } else {
2336 0 : alias_ip_list_.v6_count_--;
2337 : assert(alias_ip_list_.v6_count_ >= 0);
2338 : }
2339 0 : alias_ip_list_.list_.erase(prev);
2340 : }
2341 1329 : }
2342 :
2343 27929 : VmInterface::AliasIp::AliasIp() :
2344 27929 : ListEntry(), VmInterfaceState(), alias_ip_(), vn_(NULL), vrf_(NULL, this),
2345 55858 : vrf_name_(""), vn_uuid_() {
2346 27929 : }
2347 :
2348 0 : VmInterface::AliasIp::AliasIp(const AliasIp &rhs) :
2349 0 : ListEntry(rhs.del_pending_),
2350 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2351 0 : alias_ip_(rhs.alias_ip_), vn_(rhs.vn_), vrf_(rhs.vrf_, this),
2352 0 : vrf_name_(rhs.vrf_name_), vn_uuid_(rhs.vn_uuid_) {
2353 0 : }
2354 :
2355 0 : VmInterface::AliasIp::AliasIp(const IpAddress &addr, const std::string &vrf,
2356 0 : const boost::uuids::uuid &vn_uuid) :
2357 0 : ListEntry(), VmInterfaceState(), alias_ip_(addr), vn_(NULL),
2358 0 : vrf_(NULL, this), vrf_name_(vrf), vn_uuid_(vn_uuid) {
2359 0 : }
2360 :
2361 27929 : VmInterface::AliasIp::~AliasIp() {
2362 27929 : }
2363 :
2364 0 : bool VmInterface::AliasIp::operator() (const AliasIp &lhs,
2365 : const AliasIp &rhs) const {
2366 0 : return lhs.IsLess(&rhs);
2367 : }
2368 :
2369 : // Compare key for AliasIp. Key is <alias_ip_ and vrf_name_> for both
2370 : // Config and Operational processing
2371 0 : bool VmInterface::AliasIp::IsLess(const AliasIp *rhs) const {
2372 0 : if (alias_ip_ != rhs->alias_ip_)
2373 0 : return alias_ip_ < rhs->alias_ip_;
2374 :
2375 0 : return (vrf_name_ < rhs->vrf_name_);
2376 : }
2377 :
2378 0 : VmInterfaceState::Op VmInterface::AliasIp::GetOpL3(const Agent *agent,
2379 : const VmInterface *vmi) const {
2380 0 : if (GetIpActiveState(alias_ip_, vmi) == false)
2381 0 : return VmInterfaceState::DEL;
2382 :
2383 0 : if (vrf_ != vmi->vrf())
2384 0 : return VmInterfaceState::DEL_ADD;
2385 :
2386 0 : return VmInterfaceState::ADD;
2387 : }
2388 :
2389 0 : void VmInterface::AliasIp::Copy(const Agent *agent,
2390 : const VmInterface *vmi) const {
2391 0 : if (del_pending_) {
2392 0 : vrf_ = NULL;
2393 0 : vn_ = NULL;
2394 0 : return;
2395 : }
2396 :
2397 0 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
2398 0 : if (vn_.get() == NULL) {
2399 0 : vn_ = table->FindVnRef(vn_uuid_);
2400 0 : assert(vn_.get());
2401 : }
2402 :
2403 0 : if (vrf_.get() == NULL) {
2404 0 : vrf_ = table->FindVrfRef(vrf_name_);
2405 0 : assert(vrf_.get());
2406 : }
2407 0 : return;
2408 : }
2409 :
2410 0 : bool VmInterface::AliasIp::AddL3(const Agent *agent, VmInterface *vmi) const {
2411 0 : if (vrf_.get() == NULL || vn_.get() == NULL)
2412 0 : return false;
2413 :
2414 0 : uint8_t plen = alias_ip_.is_v4() ?
2415 0 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2416 0 : IpAddress service_ip = Ip4Address();
2417 0 : if (alias_ip_.is_v6())
2418 0 : service_ip = Ip6Address();
2419 0 : vmi->AddRoute(vrf_->GetName(), alias_ip_, plen, vn_->GetName(), false,
2420 0 : vmi->ecmp(), false, false, service_ip, service_ip,
2421 0 : CommunityList(), vmi->label(), kInterface);
2422 0 : return true;
2423 : }
2424 :
2425 0 : bool VmInterface::AliasIp::DeleteL3(const Agent *agent,
2426 : VmInterface *vmi) const {
2427 0 : if (vrf_ == NULL)
2428 0 : return false;
2429 0 : uint8_t plen = alias_ip_.is_v4() ?
2430 0 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2431 0 : vmi->DeleteRoute(vrf_.get()->GetName(), alias_ip_, plen);
2432 0 : return true;
2433 : }
2434 :
2435 : /////////////////////////////////////////////////////////////////////////////
2436 : // StaticRoute routines
2437 : /////////////////////////////////////////////////////////////////////////////
2438 2 : void VmInterface::StaticRouteList::Insert(const StaticRoute *rhs) {
2439 2 : list_.insert(*rhs);
2440 2 : }
2441 :
2442 0 : void VmInterface::StaticRouteList::Update(const StaticRoute *lhs,
2443 : const StaticRoute *rhs) {
2444 0 : if (lhs->communities_ != rhs->communities_) {
2445 0 : (const_cast<StaticRoute *>(lhs))->communities_ = rhs->communities_;
2446 : }
2447 0 : lhs->set_del_pending(false);
2448 0 : }
2449 :
2450 2 : void VmInterface::StaticRouteList::Remove(StaticRouteSet::iterator &it) {
2451 2 : it->set_del_pending(true);
2452 2 : }
2453 :
2454 1329 : bool VmInterface::StaticRouteList::UpdateList
2455 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
2456 : VmInterfaceState::Op l3_force_op) {
2457 1329 : StaticRouteSet::iterator it = list_.begin();
2458 1333 : while (it != list_.end()) {
2459 4 : StaticRouteSet::iterator prev = it++;
2460 4 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2461 4 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2462 4 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2463 4 : if (prev->del_pending_) {
2464 2 : list_.erase(prev);
2465 : }
2466 : }
2467 1329 : return true;
2468 : }
2469 :
2470 27929 : VmInterface::StaticRoute::StaticRoute() :
2471 27929 : ListEntry(), VmInterfaceState(), vrf_(), addr_(), plen_(0), gw_list_(),
2472 55858 : communities_() {
2473 27929 : }
2474 :
2475 6 : VmInterface::StaticRoute::StaticRoute(const StaticRoute &rhs) :
2476 6 : ListEntry(rhs.del_pending_),
2477 6 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2478 6 : vrf_(rhs.vrf_), addr_(rhs.addr_), plen_(rhs.plen_), gw_list_(rhs.gw_list_),
2479 12 : communities_(rhs.communities_) {
2480 6 : }
2481 :
2482 4 : VmInterface::StaticRoute::StaticRoute(const IpAddress &addr,
2483 : uint32_t plen, const AddressList &gw_list,
2484 4 : const CommunityList &communities) :
2485 4 : ListEntry(), VmInterfaceState(), vrf_(), addr_(addr), plen_(plen), gw_list_(gw_list),
2486 8 : communities_(communities) {
2487 4 : }
2488 :
2489 27939 : VmInterface::StaticRoute::~StaticRoute() {
2490 27939 : }
2491 :
2492 0 : bool VmInterface::StaticRoute::operator() (const StaticRoute &lhs,
2493 : const StaticRoute &rhs) const {
2494 0 : return lhs.IsLess(&rhs);
2495 : }
2496 :
2497 0 : bool VmInterface::StaticRoute::IsLess(const StaticRoute *rhs) const {
2498 0 : if (addr_ != rhs->addr_)
2499 0 : return addr_ < rhs->addr_;
2500 :
2501 0 : if (plen_ != rhs->plen_) {
2502 0 : return plen_ < rhs->plen_;
2503 : }
2504 :
2505 0 : return gw_list_.size() < rhs->gw_list_.size();
2506 : }
2507 :
2508 4 : void VmInterface::StaticRoute::Copy(const Agent *agent,
2509 : const VmInterface *vmi) const {
2510 4 : if (vmi->vmi_type() == VmInterface::VHOST) {
2511 2 : vrf_ = vmi->forwarding_vrf();
2512 : } else {
2513 2 : vrf_ = vmi->vrf();
2514 : }
2515 4 : }
2516 :
2517 4 : VmInterfaceState::Op VmInterface::StaticRoute::GetOpL3
2518 : (const Agent *agent, const VmInterface *vmi) const {
2519 4 : if (GetIpActiveState(addr_, vmi) == false)
2520 2 : return VmInterfaceState::DEL;
2521 :
2522 2 : if (vrf_ != vmi->vrf())
2523 2 : return VmInterfaceState::DEL_ADD;
2524 :
2525 0 : return VmInterfaceState::ADD;
2526 : }
2527 :
2528 2 : bool VmInterface::StaticRoute::AddL3(const Agent *agent,
2529 : VmInterface *vmi) const {
2530 2 : if (vrf_ == NULL)
2531 0 : return false;
2532 2 : std::string vn_name;
2533 2 : if (vmi->vn()) {
2534 0 : vn_name = vmi->vn()->GetName();
2535 2 : } else if (vmi->vmi_type() == VHOST) {
2536 2 : vn_name = agent->fabric_vn_name();
2537 : }
2538 :
2539 2 : if (addr_.is_v4() && !gw_list_.empty() && gw_list_[0] != Ip4Address(0)) {
2540 2 : SecurityGroupList sg_id_list;
2541 2 : vmi->CopySgIdList(&sg_id_list);
2542 :
2543 2 : TagList tag_id_list;
2544 2 : vmi->CopyTagIdList(&tag_id_list);
2545 :
2546 2 : VnListType vn_list;
2547 2 : if (vmi->vn()) {
2548 0 : vn_list.insert(vn_name);
2549 : }
2550 :
2551 2 : bool native_encap = false;
2552 2 : const Peer *peer = vmi->peer_.get();
2553 2 : if (vrf_->GetName() == agent->fabric_vrf_name()) {
2554 2 : vn_list.insert(agent->fabric_vn_name());
2555 2 : native_encap = true;
2556 2 : peer = agent->local_peer();
2557 : }
2558 :
2559 : InetUnicastAgentRouteTable::AddGatewayRoute
2560 4 : (peer, vrf_->GetName(), addr_.to_v4(), plen_,
2561 2 : gw_list_, vn_list, vmi->vrf_->table_label(),
2562 2 : sg_id_list, tag_id_list, communities_, native_encap);
2563 2 : } else {
2564 0 : IpAddress dependent_ip;
2565 0 : bool ecmp = false;
2566 0 : if (addr_.is_v4()) {
2567 0 : dependent_ip = vmi->primary_ip_addr();
2568 0 : ecmp = vmi->ecmp();
2569 0 : } else if (addr_.is_v6()) {
2570 0 : dependent_ip = vmi->primary_ip6_addr();
2571 0 : ecmp = vmi->ecmp6();
2572 : }
2573 0 : vmi->AddRoute(vrf_->GetName(), addr_, plen_, vn_name,
2574 0 : false, ecmp, false, false, vmi->GetServiceIp(addr_),
2575 0 : dependent_ip, communities_, vmi->label(),
2576 : kInterfaceStatic);
2577 : }
2578 2 : return true;
2579 2 : }
2580 :
2581 2 : bool VmInterface::StaticRoute::DeleteL3(const Agent *agent,
2582 : VmInterface *vmi) const {
2583 2 : if (vrf_ == NULL)
2584 0 : return false;
2585 :
2586 2 : const Peer *peer = vmi->peer();
2587 2 : if (vmi->vmi_type() == VHOST) {
2588 0 : peer = agent->local_peer();
2589 : }
2590 2 : InetUnicastAgentRouteTable::Delete(peer, vrf_->GetName(),
2591 2 : addr_, plen_);
2592 2 : return true;
2593 : }
2594 :
2595 : ///////////////////////////////////////////////////////////////////////////////
2596 : //Allowed addresss pair route
2597 : ///////////////////////////////////////////////////////////////////////////////
2598 0 : void VmInterface::AllowedAddressPairList::Insert
2599 : (const AllowedAddressPair *rhs){
2600 0 : list_.insert(*rhs);
2601 0 : }
2602 :
2603 0 : void VmInterface::AllowedAddressPairList::Update
2604 : (const AllowedAddressPair *lhs, const AllowedAddressPair *rhs) {
2605 0 : lhs->set_del_pending(false);
2606 0 : if (lhs->ecmp_ != rhs->ecmp_) {
2607 0 : lhs->ecmp_ = rhs->ecmp_;
2608 0 : lhs->ecmp_config_changed_ = true;
2609 : }
2610 0 : }
2611 :
2612 0 : void VmInterface::AllowedAddressPairList::Remove
2613 : (AllowedAddressPairSet::iterator &it) {
2614 0 : it->set_del_pending(true);
2615 0 : }
2616 :
2617 1329 : bool VmInterface::AllowedAddressPairList::UpdateList
2618 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
2619 : VmInterfaceState::Op l3_force_op) {
2620 1329 : AllowedAddressPairSet::iterator it = list_.begin();
2621 1329 : while (it != list_.end()) {
2622 0 : AllowedAddressPairSet::iterator prev = it++;
2623 0 : if (!prev->del_pending_)
2624 0 : continue;
2625 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2626 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2627 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2628 0 : list_.erase(prev);
2629 : }
2630 1329 : it = list_.begin();
2631 1329 : while (it != list_.end()) {
2632 0 : AllowedAddressPairSet::iterator prev = it++;
2633 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2634 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2635 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2636 : }
2637 1329 : return true;
2638 : }
2639 :
2640 27929 : VmInterface::AllowedAddressPair::AllowedAddressPair() :
2641 27929 : ListEntry(), VmInterfaceState(), addr_(), plen_(0), ecmp_(false), mac_(),
2642 27929 : ecmp_config_changed_(false),
2643 27929 : service_ip_(), label_(MplsTable::kInvalidLabel), policy_enabled_nh_(NULL),
2644 55858 : policy_disabled_nh_(NULL), vrf_(NULL), ethernet_tag_(0) {
2645 27929 : }
2646 :
2647 0 : VmInterface::AllowedAddressPair::AllowedAddressPair(
2648 0 : const AllowedAddressPair &rhs) : ListEntry(rhs.del_pending_),
2649 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2650 0 : addr_(rhs.addr_), plen_(rhs.plen_), ecmp_(rhs.ecmp_),
2651 0 : mac_(rhs.mac_),
2652 0 : ecmp_config_changed_(rhs.ecmp_config_changed_),
2653 0 : service_ip_(rhs.service_ip_), label_(rhs.label_),
2654 0 : policy_enabled_nh_(rhs.policy_enabled_nh_),
2655 0 : policy_disabled_nh_(rhs.policy_disabled_nh_),
2656 0 : vrf_(rhs.vrf_), ethernet_tag_(rhs.ethernet_tag_) {
2657 0 : }
2658 :
2659 0 : VmInterface::AllowedAddressPair::AllowedAddressPair(const IpAddress &addr,
2660 : uint32_t plen, bool ecmp,
2661 0 : const MacAddress &mac) :
2662 0 : ListEntry(), VmInterfaceState(), addr_(addr), plen_(plen), ecmp_(ecmp),
2663 0 : mac_(mac), ecmp_config_changed_(false),
2664 0 : label_(MplsTable::kInvalidLabel), policy_enabled_nh_(NULL),
2665 0 : policy_disabled_nh_(NULL), vrf_(NULL), ethernet_tag_(0) {
2666 0 : }
2667 :
2668 27929 : VmInterface::AllowedAddressPair::~AllowedAddressPair() {
2669 27929 : }
2670 :
2671 0 : bool VmInterface::AllowedAddressPair::operator() (const AllowedAddressPair &lhs,
2672 : const AllowedAddressPair &rhs)
2673 : const {
2674 0 : return lhs.IsLess(&rhs);
2675 : }
2676 :
2677 0 : bool VmInterface::AllowedAddressPair::IsLess(const AllowedAddressPair *rhs)
2678 : const {
2679 0 : if (addr_ != rhs->addr_)
2680 0 : return addr_ < rhs->addr_;
2681 :
2682 0 : if (plen_ != rhs->plen_) {
2683 0 : return plen_ < rhs->plen_;
2684 : }
2685 :
2686 0 : return mac_ < rhs->mac_;
2687 : }
2688 :
2689 0 : void VmInterface::AllowedAddressPair::Copy(const Agent *agent,
2690 : const VmInterface *vmi) const {
2691 0 : vrf_ = vmi->vrf();
2692 0 : ethernet_tag_ = vmi->ethernet_tag();
2693 0 : }
2694 :
2695 0 : VmInterfaceState::Op VmInterface::AllowedAddressPair::GetOpL2
2696 : (const Agent *agent, const VmInterface *vmi) const {
2697 0 : if (vmi->bridging() == false)
2698 0 : return VmInterfaceState::DEL;
2699 :
2700 0 : if (ethernet_tag_ != vmi->ethernet_tag())
2701 0 : return VmInterfaceState::DEL_ADD;
2702 :
2703 0 : return VmInterfaceState::ADD;
2704 : }
2705 :
2706 0 : bool VmInterface::AllowedAddressPair::AddL2(const Agent *agent,
2707 : VmInterface *vmi) const {
2708 0 : if (vrf_ == NULL || mac_ == MacAddress::kZeroMac)
2709 0 : return false;
2710 :
2711 0 : IpAddress dependent_rt;
2712 0 : IpAddress route_addr;
2713 0 : if (addr_.is_v4()) {
2714 0 : if (plen_ == 32) {
2715 0 : route_addr = addr_;
2716 : } else {
2717 0 : route_addr = Ip4Address(0);
2718 : }
2719 0 : dependent_rt = Ip4Address(0);
2720 0 : } else if (addr_.is_v6()) {
2721 0 : if (plen_ == 128) {
2722 0 : route_addr = addr_;
2723 : } else {
2724 0 : route_addr = Ip6Address();
2725 : }
2726 0 : dependent_rt = Ip6Address();
2727 : }
2728 0 : vmi->AddL2InterfaceRoute(route_addr, mac_, dependent_rt);
2729 0 : return true;
2730 : }
2731 :
2732 0 : bool VmInterface::AllowedAddressPair::DeleteL2(const Agent *agent,
2733 : VmInterface *vmi) const {
2734 0 : if (vrf_ == NULL || mac_ == MacAddress::kZeroMac)
2735 0 : return false;
2736 :
2737 0 : IpAddress route_addr;
2738 0 : if (addr_.is_v4()) {
2739 0 : if (plen_ == 32) {
2740 0 : route_addr = addr_;
2741 : } else {
2742 0 : route_addr = Ip4Address(0);
2743 : }
2744 0 : } else if (addr_.is_v6()) {
2745 0 : if (plen_ == 128) {
2746 0 : route_addr = addr_;
2747 : } else {
2748 0 : route_addr = Ip6Address();
2749 : }
2750 : }
2751 0 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, route_addr, mac_);
2752 0 : return true;
2753 : }
2754 :
2755 0 : VmInterfaceState::Op VmInterface::AllowedAddressPair::GetOpL3
2756 : (const Agent *agent, const VmInterface *vmi) const {
2757 0 : if (GetIpActiveState(addr_, vmi) == false)
2758 0 : return VmInterfaceState::DEL;
2759 :
2760 0 : return VmInterfaceState::ADD;
2761 : }
2762 :
2763 0 : bool VmInterface::AllowedAddressPair::DeleteL3(const Agent *agent,
2764 : VmInterface *vmi) const {
2765 0 : if (vrf_ == NULL)
2766 0 : return false;
2767 :
2768 0 : vmi->DeleteRoute(vrf_->GetName(), addr_, plen_);
2769 0 : if (label_ != MplsTable::kInvalidLabel) {
2770 0 : label_ = MplsTable::kInvalidLabel;
2771 : }
2772 0 : policy_enabled_nh_ = NULL;
2773 0 : policy_disabled_nh_ = NULL;
2774 0 : return true;
2775 : }
2776 :
2777 0 : bool VmInterface::AllowedAddressPair::AddL3(const Agent *agent,
2778 : VmInterface *vmi) const {
2779 0 : if (vrf_ == NULL || vmi->vn_ == NULL)
2780 0 : return false;
2781 :
2782 0 : service_ip_ = vmi->GetServiceIp(addr_);
2783 0 : if (mac_ == MacAddress::kZeroMac || mac_ == vmi->vm_mac_) {
2784 0 : vmi->AddRoute(vrf_->GetName(), addr_, plen_, vmi->vn_->GetName(),
2785 0 : false, ecmp_, false, false, service_ip_, Ip4Address(0),
2786 0 : CommunityList(), vmi->label(), kInterface);
2787 0 : return true;
2788 : }
2789 :
2790 : InterfaceNH::CreateL3VmInterfaceNH
2791 0 : (vmi->GetUuid(), mac_, vmi->vrf_->GetName(), vmi->learning_enabled_,
2792 : vmi->name());
2793 :
2794 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, vmi->GetUuid(),
2795 0 : vmi->name());
2796 :
2797 : // Get policy disabled nh first
2798 0 : InterfaceNHKey key(vmi_key.Clone(), false, InterfaceNHFlags::INET4, mac_);
2799 0 : InterfaceNH *nh =static_cast<InterfaceNH *>
2800 0 : (agent->nexthop_table()->FindActiveEntry(&key));
2801 0 : policy_disabled_nh_ = nh;
2802 : // Ensure nexthop to be deleted upon refcount falling to 0
2803 0 : nh->set_delete_on_zero_refcount(true);
2804 :
2805 : // Get policy enabled nh first
2806 0 : InterfaceNHKey key1(vmi_key.Clone(), true, InterfaceNHFlags::INET4, mac_);
2807 0 : nh = static_cast<InterfaceNH *>(agent->
2808 0 : nexthop_table()->FindActiveEntry(&key1));
2809 : // Ensure nexthop to be deleted upon refcount falling to 0
2810 0 : nh->set_delete_on_zero_refcount(true);
2811 0 : policy_enabled_nh_ = nh;
2812 :
2813 : // Update AAP mpls label from nh entry
2814 0 : if (vmi->policy_enabled()) {
2815 0 : label_ = policy_enabled_nh_->mpls_label()->label();
2816 : } else {
2817 0 : label_ = policy_disabled_nh_->mpls_label()->label();
2818 : }
2819 :
2820 0 : vmi->AddRoute(vrf_->GetName(), addr_, plen_, vmi->vn_->GetName(),
2821 0 : false, ecmp_, false, false, service_ip_, Ip6Address(),
2822 0 : CommunityList(), label_, kInterface);
2823 0 : return true;
2824 0 : }
2825 :
2826 : /////////////////////////////////////////////////////////////////////////////
2827 : // ServiceVlan routines
2828 : /////////////////////////////////////////////////////////////////////////////
2829 0 : void VmInterface::ServiceVlanList::Insert(const ServiceVlan *rhs) {
2830 0 : list_.insert(*rhs);
2831 0 : }
2832 :
2833 0 : void VmInterface::ServiceVlanList::Update(const ServiceVlan *lhs,
2834 : const ServiceVlan *rhs) {
2835 0 : if (lhs->vrf_name_ != rhs->vrf_name_) {
2836 0 : lhs->vrf_name_ = rhs->vrf_name_;
2837 0 : lhs->del_add_ = true;
2838 : }
2839 :
2840 0 : if (lhs->addr_ != rhs->addr_) {
2841 0 : lhs->addr_ = rhs->addr_;
2842 0 : lhs->del_add_ = true;
2843 : }
2844 :
2845 0 : if (lhs->addr6_ != rhs->addr6_) {
2846 0 : lhs->addr6_ = rhs->addr6_;
2847 0 : lhs->del_add_ = true;
2848 : }
2849 :
2850 0 : if (lhs->smac_ != rhs->smac_) {
2851 0 : lhs->smac_ = rhs->smac_;
2852 0 : lhs->del_add_ = true;
2853 : }
2854 :
2855 0 : if (lhs->dmac_ != rhs->dmac_) {
2856 0 : lhs->dmac_ = rhs->dmac_;
2857 0 : lhs->del_add_ = true;
2858 : }
2859 :
2860 0 : lhs->set_del_pending(false);
2861 0 : }
2862 :
2863 0 : void VmInterface::ServiceVlanList::Remove(ServiceVlanSet::iterator &it) {
2864 0 : it->set_del_pending(true);
2865 0 : }
2866 :
2867 1329 : bool VmInterface::ServiceVlanList::UpdateList
2868 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
2869 : VmInterfaceState::Op l3_force_op) {
2870 1329 : ServiceVlanSet::iterator it = list_.begin();
2871 1329 : while (it != list_.end()) {
2872 0 : ServiceVlanSet::iterator prev = it++;
2873 0 : if (prev->del_pending_ || prev->del_add_) {
2874 0 : prev->Update(agent, vmi);
2875 0 : if (prev->del_pending_) {
2876 0 : list_.erase(prev);
2877 : }
2878 : }
2879 : }
2880 :
2881 1329 : it = list_.begin();
2882 1329 : while (it != list_.end()) {
2883 0 : ServiceVlanSet::iterator prev = it++;
2884 0 : prev->Update(agent, vmi);
2885 : }
2886 :
2887 1329 : return true;
2888 : }
2889 :
2890 : /////////////////////////////////////////////////////////////////////////////
2891 : // TagGroup routines
2892 : /////////////////////////////////////////////////////////////////////////////
2893 32737 : VmInterface::TagEntry::TagEntry() :
2894 32737 : ListEntry(), VmInterfaceState() , type_(0xFFFFFFFF), uuid_(nil_uuid()) {
2895 32737 : }
2896 :
2897 0 : VmInterface::TagEntry::TagEntry(const TagEntry &rhs) :
2898 0 : ListEntry(rhs.del_pending_),
2899 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2900 0 : type_(rhs.type_), uuid_(rhs.uuid_) {
2901 0 : }
2902 :
2903 0 : VmInterface::TagEntry::TagEntry(uint64_t type, const uuid &u) :
2904 0 : ListEntry(), VmInterfaceState(), type_(type), uuid_(u) {
2905 0 : }
2906 :
2907 32737 : VmInterface::TagEntry::~TagEntry() {
2908 32737 : }
2909 :
2910 0 : bool VmInterface::TagEntry::operator ==(const TagEntry &rhs) const {
2911 0 : return uuid_ == rhs.uuid_;
2912 : }
2913 :
2914 0 : bool VmInterface::TagEntry::operator()(const TagEntry &lhs,
2915 : const TagEntry &rhs) const {
2916 0 : return lhs.IsLess(&rhs);
2917 : }
2918 :
2919 0 : bool VmInterface::TagEntry::IsLess(const TagEntry *rhs) const {
2920 0 : if (type_ != rhs->type_) {
2921 0 : return type_ < rhs->type_;
2922 : }
2923 :
2924 : //We can only have duplicate of tag of type Label
2925 : //Rest of tags would be unique
2926 0 : if (type_ != TagTable::LABEL) {
2927 0 : return false;
2928 : }
2929 0 : return uuid_ < rhs->uuid_;
2930 : }
2931 :
2932 0 : bool VmInterface::TagEntry::AddL3(const Agent *agent,
2933 : VmInterface *intrface) const {
2934 0 : if (tag_.get() && tag_->tag_uuid() == uuid_) {
2935 0 : return false;
2936 : }
2937 :
2938 0 : TagKey tag_key(uuid_);
2939 : typedef ::TagEntry GlobalTagEntry;
2940 0 : tag_ = static_cast<GlobalTagEntry *>(agent->tag_table()->
2941 0 : FindActiveEntry(&tag_key));
2942 0 : return true;
2943 0 : }
2944 :
2945 0 : bool VmInterface::TagEntry::DeleteL3(const Agent *agent,
2946 : VmInterface *intrface) const {
2947 0 : tag_.reset();
2948 0 : return true;
2949 : }
2950 :
2951 : VmInterfaceState::Op
2952 0 : VmInterface::TagEntry::GetOpL3(const Agent *agent,
2953 : const VmInterface *vmi) const {
2954 0 : if (del_pending_)
2955 0 : return VmInterfaceState::INVALID;
2956 :
2957 0 : return VmInterfaceState::ADD;
2958 : }
2959 :
2960 0 : void VmInterface::TagEntryList::Insert(const TagEntry *rhs) {
2961 0 : list_.insert(*rhs);
2962 0 : }
2963 :
2964 0 : void VmInterface::TagEntryList::Update(const TagEntry *lhs,
2965 : const TagEntry *rhs) {
2966 0 : if (lhs->uuid_ != rhs->uuid_) {
2967 0 : lhs->uuid_ = rhs->uuid_;
2968 : }
2969 0 : }
2970 :
2971 0 : void VmInterface::TagEntryList::Remove(TagEntrySet::iterator &it) {
2972 0 : it->set_del_pending(true);
2973 0 : }
2974 :
2975 1333 : bool VmInterface::TagEntryList::UpdateList(const Agent *agent,
2976 : VmInterface *vmi,
2977 : VmInterfaceState::Op l2_force_op,
2978 : VmInterfaceState::Op l3_force_op) {
2979 1333 : TagEntrySet::iterator it = list_.begin();
2980 1333 : while (it != list_.end()) {
2981 0 : TagEntrySet::iterator prev = it++;
2982 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2983 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2984 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2985 0 : if (prev->del_pending()) {
2986 0 : list_.erase(prev);
2987 : }
2988 : }
2989 :
2990 1333 : vmi->UpdatePolicySet(agent);
2991 1333 : return true;
2992 : }
2993 :
2994 : /////////////////////////////////////////////////////////////////////////////
2995 : // ServiceVlan routines
2996 : /////////////////////////////////////////////////////////////////////////////
2997 27929 : VmInterface::ServiceVlan::ServiceVlan() :
2998 27929 : ListEntry(), tag_(0), vrf_name_(""), addr_(0), old_addr_(0),
2999 27929 : addr6_(), old_addr6_(), smac_(), dmac_(), vrf_(NULL, this),
3000 27929 : label_(MplsTable::kInvalidLabel), v4_rt_installed_(false),
3001 27929 : v6_rt_installed_(false), del_add_(false) {
3002 27929 : }
3003 :
3004 0 : VmInterface::ServiceVlan::ServiceVlan(const ServiceVlan &rhs) :
3005 0 : ListEntry(rhs.del_pending_), tag_(rhs.tag_),
3006 0 : vrf_name_(rhs.vrf_name_), addr_(rhs.addr_), old_addr_(rhs.old_addr_),
3007 0 : addr6_(rhs.addr6_), old_addr6_(rhs.old_addr6_),
3008 0 : vrf_(rhs.vrf_, this), label_(rhs.label_),
3009 0 : v4_rt_installed_(rhs.v4_rt_installed_),
3010 0 : v6_rt_installed_(rhs.v6_rt_installed_), del_add_(false) {
3011 0 : smac_ = rhs.smac_;
3012 0 : dmac_ = rhs.dmac_;
3013 0 : }
3014 :
3015 0 : VmInterface::ServiceVlan::ServiceVlan(uint16_t tag, const std::string &vrf_name,
3016 : const Ip4Address &addr,
3017 : const Ip6Address &addr6,
3018 : const MacAddress &smac,
3019 0 : const MacAddress &dmac) :
3020 0 : ListEntry(), tag_(tag), vrf_name_(vrf_name), addr_(addr), old_addr_(addr),
3021 0 : addr6_(addr6), old_addr6_(addr6),
3022 0 : smac_(smac), dmac_(dmac), vrf_(NULL, this),
3023 0 : label_(MplsTable::kInvalidLabel) , v4_rt_installed_(false),
3024 0 : v6_rt_installed_(false), del_add_(false) {
3025 0 : }
3026 :
3027 27929 : VmInterface::ServiceVlan::~ServiceVlan() {
3028 27929 : }
3029 :
3030 0 : bool VmInterface::ServiceVlan::operator() (const ServiceVlan &lhs,
3031 : const ServiceVlan &rhs) const {
3032 0 : return lhs.IsLess(&rhs);
3033 : }
3034 :
3035 0 : bool VmInterface::ServiceVlan::IsLess(const ServiceVlan *rhs) const {
3036 0 : return tag_ < rhs->tag_;
3037 : }
3038 :
3039 0 : void VmInterface::ServiceVlan::Update(const Agent *agent,
3040 : VmInterface *vmi) const {
3041 0 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
3042 0 : VrfEntry *vrf = table->FindVrfRef(vrf_name_);
3043 :
3044 0 : if (del_pending_ || vrf_ != vrf || vmi->ipv4_active() == false || del_add_) {
3045 0 : if (v4_rt_installed_) {
3046 0 : InetUnicastAgentRouteTable::Delete(vmi->peer(), vrf_->GetName(),
3047 0 : old_addr_,
3048 : Address::kMaxV4PrefixLen);
3049 0 : v4_rt_installed_ = false;
3050 : }
3051 : }
3052 :
3053 0 : if (del_pending_ || vrf_ != vrf || vmi->ipv6_active() == false || del_add_) {
3054 0 : if (v6_rt_installed_) {
3055 0 : InetUnicastAgentRouteTable::Delete(vmi->peer(), vrf_->GetName(),
3056 0 : old_addr6_,
3057 : Address::kMaxV6PrefixLen);
3058 0 : v6_rt_installed_ = false;
3059 : }
3060 : }
3061 :
3062 0 : if (del_pending_ || vrf_ != vrf || del_add_) {
3063 0 : DeleteCommon(vmi);
3064 : }
3065 :
3066 0 : vrf_ = vrf;
3067 0 : old_addr_ = addr_;
3068 0 : old_addr6_ = addr6_;
3069 0 : bool old_del_add = del_add_;
3070 0 : del_add_ = false;
3071 :
3072 0 : if (del_pending_ || vrf_ == NULL || old_del_add)
3073 0 : return;
3074 :
3075 0 : if (vmi->ipv4_active() == false && vmi->ipv6_active() == false)
3076 0 : return;
3077 :
3078 0 : if (label_ == MplsTable::kInvalidLabel) {
3079 0 : AddCommon(agent, vmi);
3080 : }
3081 :
3082 0 : SecurityGroupList sg_id_list;
3083 0 : vmi->CopySgIdList(&sg_id_list);
3084 :
3085 0 : TagList tag_id_list;
3086 0 : vmi->CopyTagIdList(&tag_id_list);
3087 :
3088 0 : VnListType vn_list;
3089 0 : vn_list.insert(vmi->vn()->GetName());
3090 :
3091 : // Add both ipv4 *and* ipv6 service vlan route if one of v4 or v6 is active
3092 : // TODO : Shouldnt route be added only if corresponding state is active?
3093 0 : if (addr_.is_unspecified() == false) {
3094 0 : PathPreference pref;
3095 0 : vmi->SetServiceVlanPathPreference(&pref, addr_);
3096 :
3097 : InetUnicastAgentRouteTable::AddVlanNHRoute
3098 0 : (vmi->peer(), vrf_->GetName(), addr_, Address::kMaxV4PrefixLen,
3099 0 : vmi->GetUuid(), tag_, label_, vn_list, sg_id_list,
3100 : tag_id_list, pref);
3101 0 : v4_rt_installed_ = true;
3102 0 : }
3103 :
3104 0 : if (addr6_.is_unspecified() == false) {
3105 0 : PathPreference pref;
3106 0 : vmi->SetServiceVlanPathPreference(&pref, addr6_);
3107 :
3108 : InetUnicastAgentRouteTable::AddVlanNHRoute
3109 0 : (vmi->peer(), vrf_->GetName(), addr6_, Address::kMaxV6PrefixLen,
3110 0 : vmi->GetUuid(), tag_, label_, vn_list, sg_id_list,
3111 : tag_id_list, pref);
3112 0 : v6_rt_installed_ = true;
3113 0 : }
3114 :
3115 0 : return;
3116 0 : }
3117 :
3118 0 : void VmInterface::ServiceVlan::DeleteCommon(const VmInterface *vmi) const {
3119 0 : if (label_ == MplsTable::kInvalidLabel)
3120 0 : return;
3121 :
3122 : // Delete the L2 Recive routes added for smac_ and dmac_
3123 : BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
3124 0 : (vrf_->GetBridgeRouteTable());
3125 0 : if (table) {
3126 0 : table->Delete(vmi->peer(), vrf_->GetName(), dmac_, 0);
3127 0 : table->Delete(vmi->peer(), vrf_->GetName(), smac_, 0);
3128 : }
3129 :
3130 0 : VrfAssignTable::DeleteVlan(vmi->GetUuid(), tag_);
3131 0 : VlanNH::Delete(vmi->GetUuid(), tag_);
3132 0 : label_ = MplsTable::kInvalidLabel;
3133 : }
3134 :
3135 0 : void VmInterface::ServiceVlan::AddCommon(const Agent *agent,
3136 : const VmInterface *vmi) const {
3137 0 : if (label_ != MplsTable::kInvalidLabel)
3138 0 : return;
3139 :
3140 0 : assert(vrf_);
3141 0 : VlanNH::Create(vmi->GetUuid(), tag_, vrf_name_, smac_, dmac_);
3142 0 : VrfAssignTable::CreateVlan(vmi->GetUuid(), vrf_name_, tag_);
3143 : // Assign label_ from vlan NH db entry
3144 0 : VlanNHKey key(vmi->GetUuid(), tag_);
3145 0 : const NextHop *nh = static_cast<const NextHop *>
3146 0 : (agent->nexthop_table()->FindActiveEntry(&key));
3147 0 : label_ = nh->mpls_label()->label();
3148 :
3149 : // With IRB model, add L2 Receive route for SMAC and DMAC to ensure
3150 : // packets from service vm go thru routing
3151 : BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
3152 0 : (vrf_->GetBridgeRouteTable());
3153 0 : table->AddBridgeReceiveRoute(vmi->peer(), vrf_->GetName(), 0, dmac_,
3154 : vmi->vn()->GetName());
3155 0 : table->AddBridgeReceiveRoute(vmi->peer(), vrf_->GetName(), 0, smac_,
3156 : vmi->vn()->GetName());
3157 0 : }
3158 :
3159 : ////////////////////////////////////////////////////////////////////////////
3160 : // VRF assign rule routines
3161 : ////////////////////////////////////////////////////////////////////////////
3162 27929 : VmInterface::VrfAssignRule::VrfAssignRule():
3163 27929 : ListEntry(), id_(0), vrf_name_(" "), ignore_acl_(false) {
3164 27929 : }
3165 :
3166 0 : VmInterface::VrfAssignRule::VrfAssignRule(const VrfAssignRule &rhs):
3167 0 : ListEntry(rhs.del_pending_), id_(rhs.id_),
3168 0 : vrf_name_(rhs.vrf_name_), ignore_acl_(rhs.ignore_acl_),
3169 0 : match_condition_(rhs.match_condition_) {
3170 0 : }
3171 :
3172 0 : VmInterface::VrfAssignRule::VrfAssignRule
3173 : (uint32_t id, const autogen::MatchConditionType &match_condition,
3174 0 : const std::string &vrf_name, bool ignore_acl):
3175 0 : ListEntry(), id_(id), vrf_name_(vrf_name), ignore_acl_(ignore_acl),
3176 0 : match_condition_(match_condition) {
3177 0 : }
3178 :
3179 27929 : VmInterface::VrfAssignRule::~VrfAssignRule() {
3180 27929 : }
3181 :
3182 0 : bool VmInterface::VrfAssignRule::operator()(const VrfAssignRule &lhs,
3183 : const VrfAssignRule &rhs) const {
3184 0 : return lhs.IsLess(&rhs);
3185 : }
3186 :
3187 0 : bool VmInterface::VrfAssignRule::IsLess(const VrfAssignRule *rhs) const {
3188 0 : return id_ < rhs->id_;
3189 : }
3190 :
3191 0 : void VmInterface::VrfAssignRuleList::Insert(const VrfAssignRule *rhs) {
3192 0 : list_.insert(*rhs);
3193 0 : }
3194 :
3195 0 : void VmInterface::VrfAssignRuleList::Update(const VrfAssignRule *lhs,
3196 : const VrfAssignRule *rhs) {
3197 0 : lhs->set_del_pending(false);
3198 0 : lhs->match_condition_ = rhs->match_condition_;
3199 0 : lhs->ignore_acl_ = rhs->ignore_acl_;
3200 0 : lhs->vrf_name_ = rhs->vrf_name_;
3201 0 : }
3202 :
3203 0 : void VmInterface::VrfAssignRuleList::Remove(VrfAssignRuleSet::iterator &it) {
3204 0 : it->set_del_pending(true);
3205 0 : }
3206 :
3207 1329 : bool VmInterface::VrfAssignRuleList::UpdateList
3208 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
3209 : VmInterfaceState::Op l3_force_op) {
3210 : // Erase all delete marked entry
3211 1329 : VrfAssignRuleSet::iterator it = list_.begin();
3212 1329 : while (it != list_.end()) {
3213 0 : VrfAssignRuleSet::iterator prev = it++;
3214 0 : if (prev->del_pending_) {
3215 0 : list_.erase(prev);
3216 : }
3217 : }
3218 :
3219 : // Delete vrf_assign_acl_ if there are no more ACE entries
3220 1329 : if (list_.size() == 0 || vmi->IsActive() == false) {
3221 1329 : if (vrf_assign_acl_.get() != NULL) {
3222 0 : vrf_assign_acl_ = NULL;
3223 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
3224 0 : req.key.reset(new AclKey(vmi->GetUuid()));
3225 0 : req.data.reset(NULL);
3226 0 : agent->acl_table()->Process(req);
3227 0 : }
3228 1329 : return true;
3229 : }
3230 :
3231 : // One or more ace-entries present, create corresponding ACL
3232 0 : AclSpec acl_spec;
3233 0 : acl_spec.acl_id = vmi->GetUuid();
3234 0 : uint32_t id = 0;
3235 0 : for (it = list_.begin(); it != list_.end(); it++) {
3236 0 : AclEntrySpec ace_spec;
3237 0 : ace_spec.id = id++;
3238 :
3239 0 : if (ace_spec.Populate(&(it->match_condition_)) == false) {
3240 0 : continue;
3241 : }
3242 :
3243 : // Add both v4 and v6 rules regardless of whether interface is
3244 : //ipv4_active_/ipv6_active_
3245 0 : ActionSpec vrf_translate_spec;
3246 0 : vrf_translate_spec.ta_type = TrafficAction::VRF_TRANSLATE_ACTION;
3247 0 : vrf_translate_spec.simple_action = TrafficAction::VRF_TRANSLATE;
3248 0 : vrf_translate_spec.vrf_translate.set_vrf_name(it->vrf_name_);
3249 0 : vrf_translate_spec.vrf_translate.set_ignore_acl(it->ignore_acl_);
3250 0 : ace_spec.action_l.push_back(vrf_translate_spec);
3251 0 : acl_spec.acl_entry_specs_.push_back(ace_spec);
3252 0 : }
3253 :
3254 : // ACL entries populated, add the DBEntry
3255 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
3256 0 : req.key.reset(new AclKey(acl_spec.acl_id));
3257 0 : Agent *agent1 = static_cast<InterfaceTable *>(vmi->get_table())->agent();
3258 0 : req.data.reset(new AclData(agent1, NULL, acl_spec));
3259 0 : agent->acl_table()->Process(req);
3260 :
3261 : // Query the ACL entry and store it
3262 0 : AclKey entry_key(vmi->GetUuid());
3263 : vrf_assign_acl_ = static_cast<AclDBEntry *>
3264 0 : (agent->acl_table()->FindActiveEntry(&entry_key));
3265 0 : assert(vrf_assign_acl_);
3266 0 : return true;
3267 0 : }
3268 :
3269 : /////////////////////////////////////////////////////////////////////////////
3270 : // RecevieRoute routines
3271 : /////////////////////////////////////////////////////////////////////////////
3272 4 : void VmInterface::VmiReceiveRouteList::Insert(const VmiReceiveRoute *rhs) {
3273 4 : list_.insert(*rhs);
3274 4 : }
3275 :
3276 0 : void VmInterface::VmiReceiveRouteList::Update(const VmiReceiveRoute *lhs,
3277 : const VmiReceiveRoute *rhs) {
3278 0 : lhs->set_del_pending(false);
3279 0 : }
3280 :
3281 4 : void VmInterface::VmiReceiveRouteList::Remove(VmiReceiveRouteSet::iterator &it) {
3282 4 : it->set_del_pending(true);
3283 4 : }
3284 :
3285 1329 : bool VmInterface::VmiReceiveRouteList::UpdateList(const Agent *agent,
3286 : VmInterface *vmi,
3287 : VmInterfaceState::Op l2_force_op,
3288 : VmInterfaceState::Op l3_force_op) {
3289 1329 : VmiReceiveRouteSet::iterator it = list_.begin();
3290 1337 : while (it != list_.end()) {
3291 8 : VmiReceiveRouteSet::iterator prev = it++;
3292 8 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
3293 8 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
3294 8 : vmi->UpdateState(&(*prev), l2_op, l3_op);
3295 8 : if (prev->del_pending_) {
3296 4 : list_.erase(prev);
3297 : }
3298 : }
3299 1329 : return true;
3300 : }
3301 :
3302 27929 : VmInterface::VmiReceiveRoute::VmiReceiveRoute() :
3303 27929 : ListEntry(), VmInterfaceState(), addr_(), plen_(0), add_l2_(false) {
3304 27929 : }
3305 :
3306 12 : VmInterface::VmiReceiveRoute::VmiReceiveRoute(const VmiReceiveRoute &rhs) :
3307 12 : ListEntry(rhs.del_pending_),
3308 12 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
3309 12 : addr_(rhs.addr_), plen_(rhs.plen_), add_l2_(rhs.add_l2_) {
3310 12 : }
3311 :
3312 8 : VmInterface::VmiReceiveRoute::VmiReceiveRoute(const IpAddress &addr,
3313 : uint32_t plen,
3314 8 : bool add_l2):
3315 8 : ListEntry(), VmInterfaceState(), addr_(addr), plen_(plen), add_l2_(add_l2) {
3316 8 : }
3317 :
3318 18 : bool VmInterface::VmiReceiveRoute::operator() (const VmiReceiveRoute &lhs,
3319 : const VmiReceiveRoute &rhs)
3320 : const {
3321 18 : return lhs.IsLess(&rhs);
3322 : }
3323 :
3324 18 : bool VmInterface::VmiReceiveRoute::IsLess(const VmiReceiveRoute *rhs) const {
3325 18 : if (addr_ != rhs->addr_) {
3326 18 : return addr_ < rhs->addr_;
3327 : }
3328 :
3329 0 : if (plen_ != rhs->plen_) {
3330 0 : return plen_ < rhs->plen_;
3331 : }
3332 :
3333 0 : return add_l2_ < rhs->add_l2_;
3334 : }
3335 :
3336 8 : void VmInterface::VmiReceiveRoute::Copy(const Agent *agent,
3337 : const VmInterface *vmi) const {
3338 8 : vrf_ = vmi->forwarding_vrf();
3339 8 : }
3340 :
3341 : VmInterfaceState::Op
3342 8 : VmInterface::VmiReceiveRoute::GetOpL3(const Agent *agent,
3343 : const VmInterface *vmi) const {
3344 8 : if (GetIpActiveState(addr_, vmi) == false)
3345 4 : return VmInterfaceState::DEL;
3346 :
3347 4 : if (vrf_ != vmi->forwarding_vrf())
3348 4 : return VmInterfaceState::DEL_ADD;
3349 :
3350 0 : return VmInterfaceState::ADD;
3351 : }
3352 :
3353 : VmInterfaceState::Op
3354 8 : VmInterface::VmiReceiveRoute::GetOpL2(const Agent *agent,
3355 : const VmInterface *vmi) const {
3356 8 : if (add_l2_ == false) {
3357 8 : return VmInterfaceState::INVALID;
3358 : }
3359 :
3360 0 : if (vrf_ != vmi->forwarding_vrf())
3361 0 : return VmInterfaceState::DEL_ADD;
3362 :
3363 0 : return VmInterfaceState::ADD;
3364 : }
3365 :
3366 4 : bool VmInterface::VmiReceiveRoute::AddL3(const Agent *agent,
3367 : VmInterface *vmi) const {
3368 4 : if (vrf_ == NULL) {
3369 0 : return false;
3370 : }
3371 :
3372 4 : ReceiveNH::Create(agent->nexthop_table(), vmi, vmi->policy_enabled());
3373 4 : ReceiveNH::Create(agent->nexthop_table(), vmi, false);
3374 4 : InetUnicastAgentRouteTable *table = vrf_->GetInet4UnicastRouteTable();
3375 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, vmi->GetUuid(),
3376 4 : vmi->name());
3377 4 : if (addr_.is_v6()) {
3378 2 : table = vrf_->GetInet6UnicastRouteTable();
3379 : }
3380 :
3381 8 : table->AddVHostRecvRoute(agent->local_peer(), vrf_->GetName(), vmi_key,
3382 4 : addr_, plen_, agent->fabric_vn_name(),
3383 4 : vmi->policy_enabled(), true);
3384 4 : return true;
3385 4 : }
3386 :
3387 4 : bool VmInterface::VmiReceiveRoute::DeleteL3(const Agent *agent,
3388 : VmInterface *vmi) const {
3389 4 : if (vrf_ == NULL)
3390 0 : return false;
3391 :
3392 4 : InetUnicastAgentRouteTable::Delete(agent->local_peer(), vrf_->GetName(),
3393 4 : addr_, plen_);
3394 4 : return true;
3395 : }
3396 :
3397 0 : bool VmInterface::VmiReceiveRoute::AddL2(const Agent *agent,
3398 : VmInterface *vmi) const {
3399 0 : if (vrf_ == NULL) {
3400 0 : return false;
3401 : }
3402 :
3403 : BridgeAgentRouteTable *table =
3404 0 : static_cast<BridgeAgentRouteTable *>(vrf_->GetRouteTable(Agent::BRIDGE));
3405 0 : table->AddBridgeReceiveRoute(agent->local_peer(), vrf_->GetName(), 0,
3406 : vmi->GetVifMac(agent), agent->fabric_vn_name());
3407 0 : return true;
3408 : }
3409 :
3410 0 : bool VmInterface::VmiReceiveRoute::DeleteL2(const Agent *agent,
3411 : VmInterface *vmi) const {
3412 0 : if (vrf_ == NULL)
3413 0 : return false;
3414 :
3415 0 : BridgeAgentRouteTable::Delete(agent->local_peer(), vrf_->GetName(),
3416 : vmi->GetVifMac(agent), 0);
3417 0 : return true;
3418 : }
3419 : //Build ACL list to be applied on VMI
3420 : //ACL list build on two criteria
3421 : //1> global-application-policy set.
3422 : //2> application-policy-set attached via application tag
3423 1333 : bool VmInterface::UpdatePolicySet(const Agent *agent) {
3424 1333 : bool ret = false;
3425 1333 : FirewallPolicyList new_firewall_policy_list;
3426 1333 : FirewallPolicyList new_fwaas_firewall_policy_list;
3427 :
3428 1333 : PolicySet *gps = agent->policy_set_table()->global_policy_set();
3429 1333 : if (gps) {
3430 0 : new_firewall_policy_list = gps->fw_policy_list();
3431 : }
3432 :
3433 1333 : contains_new_tags_ = false;
3434 1333 : TagEntrySet::const_iterator it = tag_list_.list_.begin();
3435 1333 : for(; it != tag_list_.list_.end(); it++) {
3436 0 : if (it->tag_ == NULL) {
3437 0 : continue;
3438 : }
3439 0 : contains_new_tags_ |= it->tag_->is_new_tag();
3440 :
3441 : ::TagEntry::PolicySetList::const_iterator ps_it =
3442 0 : it->tag_->policy_set_list().begin();
3443 0 : for(; ps_it != it->tag_->policy_set_list().end(); ps_it++) {
3444 0 : FirewallPolicyList &tag_fp_list = ps_it->get()->fw_policy_list();
3445 0 : FirewallPolicyList::iterator fw_policy_it = tag_fp_list.begin();
3446 0 : for (; fw_policy_it != tag_fp_list.end(); fw_policy_it++) {
3447 0 : if (it->tag_->IsNeutronFwaasTag())
3448 0 : new_fwaas_firewall_policy_list.push_back(*fw_policy_it);
3449 : else
3450 0 : new_firewall_policy_list.push_back(*fw_policy_it);
3451 : }
3452 : }
3453 : }
3454 :
3455 1333 : if (fw_policy_list_ != new_firewall_policy_list) {
3456 0 : fw_policy_list_ = new_firewall_policy_list;
3457 0 : ret = true;
3458 : }
3459 :
3460 1333 : if (fwaas_fw_policy_list_ != new_fwaas_firewall_policy_list) {
3461 0 : fwaas_fw_policy_list_ = new_fwaas_firewall_policy_list;
3462 0 : ret = true;
3463 : }
3464 :
3465 1333 : return ret;
3466 1333 : }
3467 :
3468 2500 : void VmInterface::CopyTagIdList(TagList *tag_id_list) const {
3469 2500 : TagEntrySet::const_iterator it;
3470 2500 : for (it = tag_list_.list_.begin(); it != tag_list_.list_.end(); ++it) {
3471 0 : if (it->del_pending_)
3472 0 : continue;
3473 0 : if (it->tag_.get() == NULL)
3474 0 : continue;
3475 0 : tag_id_list->push_back(it->tag_->tag_id());
3476 : }
3477 2500 : std::sort(tag_id_list->begin(), tag_id_list->end());
3478 2500 : }
3479 :
3480 270 : void VmInterface::update_flow_count(int val) const {
3481 270 : int max_flows = FLOWS_LIMIT_UNLIMITED;
3482 270 : int new_flow_count = flow_count_.fetch_add(val);
3483 :
3484 : {
3485 270 : int maxv = std::max(max_flows_, agent()->global_max_vmi_flows());
3486 270 : int minv = std::min(max_flows_, agent()->global_max_vmi_flows());
3487 270 : max_flows = minv * (max_flows_ != FLOWS_LIMIT_UNLIMITED &&
3488 0 : agent()->global_max_vmi_flows() != FLOWS_LIMIT_UNLIMITED) +
3489 540 : maxv * ((max_flows_ != FLOWS_LIMIT_UNLIMITED) !=
3490 270 : (agent()->global_max_vmi_flows() != FLOWS_LIMIT_UNLIMITED));
3491 : }
3492 :
3493 270 : if (max_flows == FLOWS_LIMIT_UNLIMITED) {
3494 : // max_flows are not configured,
3495 : // disable drop new flows and return
3496 270 : SetInterfacesDropNewFlows(false);
3497 270 : return;
3498 : }
3499 :
3500 0 : if (val < 0) {
3501 0 : assert(new_flow_count >= val);
3502 0 : if ((new_flow_count + val) <
3503 0 : ((max_flows * (Agent::kDropNewFlowsRecoveryThreshold))/100)) {
3504 0 : SetInterfacesDropNewFlows(false);
3505 : }
3506 : } else {
3507 0 : if ((new_flow_count + val) >= max_flows) {
3508 0 : SetInterfacesDropNewFlows(true);
3509 : }
3510 : }
3511 : }
3512 :
3513 270 : void VmInterface::SetInterfacesDropNewFlows(bool drop_new_flows) const {
3514 270 : if (drop_new_flows_vmi_ == drop_new_flows) {
3515 264 : return;
3516 : }
3517 6 : drop_new_flows_vmi_ = drop_new_flows;
3518 6 : DBRequest req;
3519 6 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
3520 12 : req.key.reset(new VmInterfaceKey(AgentKey::RESYNC,
3521 12 : GetUuid(), ""));
3522 6 : req.data.reset(new VmInterfaceNewFlowDropData(drop_new_flows));
3523 6 : agent()->interface_table()->Enqueue(&req);
3524 6 : }
|