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