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 0 : VmInterface::VmInterface(const boost::uuids::uuid &uuid,
49 : const std::string &name,
50 : bool os_oper_state,
51 0 : const boost::uuids::uuid &logical_router_uuid) :
52 : Interface(Interface::VM_INTERFACE, uuid, name, NULL, os_oper_state,
53 : logical_router_uuid),
54 0 : vm_(NULL, this), vn_(NULL), primary_ip_addr_(0), subnet_bcast_addr_(0),
55 0 : primary_ip6_addr_(), vm_mac_(MacAddress::kZeroMac), policy_enabled_(false),
56 0 : mirror_entry_(NULL), mirror_direction_(MIRROR_RX_TX), cfg_name_(""),
57 0 : fabric_port_(true), need_linklocal_ip_(false), drop_new_flows_(false),
58 0 : dhcp_enable_(true), dhcp_enable_v6_(false), do_dhcp_relay_(false), proxy_arp_mode_(PROXY_ARP_NONE),
59 0 : vm_name_(), vm_project_uuid_(nil_uuid()), vxlan_id_(0), bridging_(false),
60 0 : layer3_forwarding_(true), flood_unknown_unicast_(false),
61 0 : mac_set_(false), ecmp_(false), ecmp6_(false), disable_policy_(false),
62 0 : tx_vlan_id_(kInvalidVlanId), rx_vlan_id_(kInvalidVlanId), parent_(NULL, this),
63 0 : local_preference_(0), oper_dhcp_options_(),
64 0 : cfg_igmp_enable_(false), igmp_enabled_(false),
65 0 : mac_ip_learning_enable_(false), max_flows_(0),
66 0 : mac_vm_binding_state_(new MacVmBindingState()),
67 0 : nexthop_state_(new NextHopState()),
68 0 : vrf_table_label_state_(new VrfTableLabelState()),
69 0 : metadata_ip_state_(new MetaDataIpState()),
70 0 : metadata_ip6_state_(new MetaDataIpState(false)),
71 0 : resolve_route_state_(new ResolveRouteState()),
72 0 : interface_route_state_(new VmiRouteState()),
73 0 : sg_list_(), tag_list_(), floating_ip_list_(), alias_ip_list_(), service_vlan_list_(),
74 0 : static_route_list_(), allowed_address_pair_list_(),
75 0 : instance_ipv4_list_(true), instance_ipv6_list_(false), fat_flow_list_(),
76 0 : vrf_assign_rule_list_(), vm_ip_service_addr_(0),
77 0 : device_type_(VmInterface::DEVICE_TYPE_INVALID),
78 0 : vmi_type_(VmInterface::VMI_TYPE_INVALID),
79 0 : hbs_intf_type_(VmInterface::HBS_INTF_INVALID),
80 0 : configurer_(0), subnet_(0), subnet_plen_(0), ethernet_tag_(0),
81 0 : logical_interface_(nil_uuid()), nova_ip_addr_(0), nova_ip6_addr_(),
82 0 : dhcp_addr_(0), metadata_ip_map_(), hc_instance_set_(),
83 0 : ecmp_load_balance_(), service_health_check_ip_(), is_vn_qos_config_(false),
84 0 : learning_enabled_(false), etree_leaf_(false), layer2_control_word_(false),
85 0 : slo_list_(), forwarding_vrf_(NULL), vhostuser_mode_(vHostUserClient),
86 0 : is_left_si_(false),
87 0 : service_mode_(VmInterface::SERVICE_MODE_ERROR),
88 0 : service_intf_type_(""),
89 0 : parent_list_() {
90 0 : metadata_ip_active_ = false;
91 0 : metadata_l2_active_ = false;
92 0 : ipv4_active_ = false;
93 0 : ipv6_active_ = false;
94 0 : l2_active_ = false;
95 0 : flow_count_ = 0;
96 0 : vrf_name_ = "";
97 0 : }
98 :
99 0 : 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 0 : const boost::uuids::uuid &logical_router_uuid) :
109 : Interface(Interface::VM_INTERFACE, uuid, name, NULL, os_oper_state,
110 : logical_router_uuid),
111 0 : vm_(NULL, this), vn_(NULL), primary_ip_addr_(addr), subnet_bcast_addr_(0),
112 0 : primary_ip6_addr_(a6), vm_mac_(mac), policy_enabled_(false),
113 0 : mirror_entry_(NULL), mirror_direction_(MIRROR_RX_TX), cfg_name_(""),
114 0 : fabric_port_(true), need_linklocal_ip_(false), drop_new_flows_(false),
115 0 : dhcp_enable_(true), dhcp_enable_v6_(false), do_dhcp_relay_(false), proxy_arp_mode_(PROXY_ARP_NONE),
116 0 : vm_name_(vm_name), vm_project_uuid_(vm_project_uuid), vxlan_id_(0),
117 0 : bridging_(false), layer3_forwarding_(true),
118 0 : flood_unknown_unicast_(false), mac_set_(false),
119 0 : ecmp_(false), ecmp6_(false), disable_policy_(false),
120 0 : tx_vlan_id_(tx_vlan_id), rx_vlan_id_(rx_vlan_id), parent_(parent, this),
121 0 : local_preference_(0), oper_dhcp_options_(),
122 0 : cfg_igmp_enable_(false), igmp_enabled_(false),
123 0 : mac_ip_learning_enable_(false), max_flows_(0),
124 0 : mac_vm_binding_state_(new MacVmBindingState()),
125 0 : nexthop_state_(new NextHopState()),
126 0 : vrf_table_label_state_(new VrfTableLabelState()),
127 0 : metadata_ip_state_(new MetaDataIpState()),
128 0 : metadata_ip6_state_(new MetaDataIpState(false)),
129 0 : resolve_route_state_(new ResolveRouteState()),
130 0 : interface_route_state_(new VmiRouteState()),
131 0 : sg_list_(), tag_list_(),
132 0 : floating_ip_list_(), alias_ip_list_(), service_vlan_list_(),
133 0 : static_route_list_(), allowed_address_pair_list_(),
134 0 : instance_ipv4_list_(true), instance_ipv6_list_(false), fat_flow_list_(),
135 0 : vrf_assign_rule_list_(), device_type_(device_type),
136 0 : vmi_type_(vmi_type), hbs_intf_type_(VmInterface::HBS_INTF_INVALID),
137 0 : configurer_(0), subnet_(0),
138 0 : subnet_plen_(0), ethernet_tag_(0), logical_interface_(nil_uuid()),
139 0 : nova_ip_addr_(0), nova_ip6_addr_(), dhcp_addr_(0), metadata_ip_map_(),
140 0 : hc_instance_set_(), service_health_check_ip_(), is_vn_qos_config_(false),
141 0 : learning_enabled_(false), etree_leaf_(false), layer2_control_word_(false),
142 0 : slo_list_(), forwarding_vrf_(NULL), vhostuser_mode_(vhostuser_mode),
143 0 : is_left_si_(false),
144 0 : service_mode_(VmInterface::SERVICE_MODE_ERROR),
145 0 : service_intf_type_(""),
146 0 : parent_list_() {
147 0 : metadata_ip_active_ = false;
148 0 : metadata_l2_active_ = false;
149 0 : ipv4_active_ = false;
150 0 : ipv6_active_ = false;
151 0 : l2_active_ = false;
152 0 : flow_count_ = 0;
153 0 : vrf_name_ = "";
154 0 : }
155 :
156 0 : VmInterface::~VmInterface() {
157 : // Release metadata first to ensure metadata_ip_map_ is empty
158 0 : metadata_ip_state_.reset(NULL);
159 0 : metadata_ip6_state_.reset(NULL);
160 0 : assert(metadata_ip_map_.empty());
161 0 : assert(hc_instance_set_.empty());
162 0 : }
163 :
164 0 : void VmInterface::SetConfigurer(VmInterface::Configurer type) {
165 0 : configurer_ |= (1 << type);
166 0 : }
167 :
168 0 : void VmInterface::ResetConfigurer(VmInterface::Configurer type) {
169 0 : configurer_ &= ~(1 << type);
170 0 : }
171 :
172 0 : bool VmInterface::IsConfigurerSet(VmInterface::Configurer type) {
173 0 : return ((configurer_ & (1 << type)) != 0);
174 : }
175 :
176 0 : bool VmInterface::CmpInterface(const DBEntry &rhs) const {
177 0 : const VmInterface &intf=static_cast<const VmInterface &>(rhs);
178 0 : if (uuid_ == nil_uuid() && intf.uuid_ == nil_uuid()) {
179 0 : return name() < intf.name();
180 : }
181 :
182 0 : return uuid_ < intf.uuid_;
183 : }
184 :
185 0 : string VmInterface::ToString() const {
186 0 : return "VM-PORT <" + name() + ">";
187 : }
188 :
189 0 : DBEntryBase::KeyPtr VmInterface::GetDBRequestKey() const {
190 0 : InterfaceKey *key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, uuid_, name());
191 0 : return DBEntryBase::KeyPtr(key);
192 : }
193 :
194 0 : void VmInterface::Add() {
195 0 : peer_.reset(new LocalVmPortPeer(LOCAL_VM_PORT_PEER_NAME, id_));
196 0 : }
197 :
198 0 : bool VmInterface::Delete(const DBRequest *req) {
199 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
200 : const VmInterfaceData *vm_data = static_cast<const VmInterfaceData *>
201 0 : (req->data.get());
202 0 : if (vrf_ && vrf_->GetName() != "") {
203 0 : vrf_name_ = vrf_->GetName();
204 : }
205 0 : vm_data->OnDelete(table, this);
206 0 : if (configurer_) {
207 0 : return false;
208 : }
209 0 : table->DeleteDhcpSnoopEntry(name());
210 0 : 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 0 : void VmInterface::PostAdd() {
218 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
219 0 : IFMapNode *node = ifmap_node();
220 0 : if (node == NULL) {
221 : PortSubscribeTable *subscribe_table =
222 0 : table->agent()->port_ipc_handler()->port_subscribe_table();
223 0 : if (subscribe_table)
224 0 : node = subscribe_table->UuidToIFNode(GetUuid());
225 0 : if (node == NULL)
226 0 : return;
227 : }
228 :
229 : // Config notification would have been ignored till Nova message is
230 : // received. Update config now
231 : IFMapAgentTable *ifmap_table =
232 0 : static_cast<IFMapAgentTable *>(node->table());
233 0 : DBRequest req(DBRequest::DB_ENTRY_NOTIFY);
234 0 : req.key = node->GetDBRequestKey();
235 : IFMapTable::RequestKey *key =
236 0 : dynamic_cast<IFMapTable::RequestKey *>(req.key.get());
237 0 : key->id_type = "virtual-machine-interface";
238 0 : ifmap_table->Enqueue(&req);
239 0 : }
240 :
241 0 : bool VmInterface::ResetVrfDelete(const InterfaceTable *table,
242 : const std::string &vrf_name) {
243 0 : Agent *agent = table->agent();
244 0 : VrfKey vrf_key(vrf_name);
245 0 : VrfEntry *vrf = static_cast<VrfEntry *>(
246 0 : agent->vrf_table()->Find(&vrf_key, true));
247 0 : if (vrf && vrf->IsDeleted()) {
248 0 : SendTrace(table, VRF_REUSE);
249 0 : return vrf->ResetVrfDelete();
250 : }
251 0 : return true;
252 0 : }
253 :
254 0 : bool VmInterface::OnChange(VmInterfaceData *data) {
255 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
256 0 : if (IsDeleted()) {
257 0 : SendTrace(table, VMI_REUSE);
258 0 : ResetVrfDelete(table, vrf_name());
259 : }
260 0 : 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 0 : bool VmInterface::Resync(const InterfaceTable *table,
268 : const VmInterfaceData *data) {
269 0 : bool ret = false;
270 :
271 : // Copy old values used to update config below
272 0 : bool old_ipv4_active = ipv4_active_;
273 0 : bool old_ipv6_active = ipv6_active_;
274 0 : bool old_l2_active = l2_active_;
275 0 : bool old_policy = policy_enabled_;
276 0 : VrfEntryRef old_vrf = vrf_;
277 0 : bool force_update = false;
278 0 : Ip4Address old_subnet = subnet_;
279 0 : uint8_t old_subnet_plen = subnet_plen_;
280 0 : bool old_metadata_ip_active = metadata_ip_active_;
281 0 : bool old_metadata_l2_active = metadata_l2_active_;
282 :
283 0 : if (data) {
284 0 : ret = data->OnResync(table, this, &force_update);
285 0 : std::string ri_name = "";
286 0 : if (data->vrf_name_ == "" && vrf_name_ == "") {
287 0 : if (vn()) {
288 0 : std::string fqdn_name = vn()->GetName();
289 0 : size_t pos = fqdn_name.rfind(":");
290 0 : if (pos != std::string::npos)
291 0 : pos = pos + 1;
292 : else
293 0 : pos = 0;
294 0 : ri_name = fqdn_name + ":" + fqdn_name.substr(pos, fqdn_name.length());
295 0 : }
296 : } else {
297 0 : ri_name = data->vrf_name_;
298 : }
299 0 : if (ri_name != "" && ri_name != vrf_name_) {
300 0 : if (ResetVrfDelete(table, ri_name))
301 0 : vrf_name_ = ri_name;
302 : }
303 0 : }
304 :
305 0 : metadata_ip_active_ = IsMetaDataIPActive();
306 0 : metadata_l2_active_ = IsMetaDataL2Active();
307 0 : ipv4_active_ = IsIpv4Active();
308 0 : ipv6_active_ = IsIpv6Active();
309 0 : l2_active_ = IsL2Active();
310 :
311 0 : if (metadata_ip_active_ != old_metadata_ip_active) {
312 0 : ret = true;
313 : }
314 :
315 0 : if (metadata_l2_active_ != old_metadata_l2_active) {
316 0 : ret = true;
317 : }
318 :
319 0 : if (ipv4_active_ != old_ipv4_active) {
320 0 : InterfaceTable *intf_table = static_cast<InterfaceTable *>(get_table());
321 0 : if (ipv4_active_)
322 0 : intf_table->incr_active_vmi_count();
323 : else
324 0 : intf_table->decr_active_vmi_count();
325 0 : ret = true;
326 : }
327 :
328 0 : if (ipv6_active_ != old_ipv6_active) {
329 0 : ret = true;
330 : }
331 :
332 0 : if (l2_active_ != old_l2_active) {
333 0 : ret = true;
334 : }
335 :
336 0 : policy_enabled_ = PolicyEnabled();
337 0 : if (policy_enabled_ != old_policy) {
338 0 : ret = true;
339 : }
340 :
341 : //Update DHCP and DNS flag in Interface Class.
342 0 : if (dhcp_enable_) {
343 0 : dhcp_enabled_ = true;
344 : } else {
345 0 : dhcp_enabled_ = false;
346 : }
347 :
348 : //Update DHCP and DNS flag for v6 in Interface Class.
349 0 : if (dhcp_enable_v6_) {
350 0 : dhcp_enabled_v6_ = true;
351 : }else {
352 0 : dhcp_enabled_v6_ = false;
353 : }
354 :
355 0 : if (dhcp_enabled_ || dhcp_enable_v6_)
356 0 : dns_enabled_ = true;
357 : else
358 0 : dns_enabled_ = false;
359 :
360 : // Compute service-ip for the interface
361 0 : vm_ip_service_addr_ = GetServiceIp(primary_ip_addr()).to_v4();
362 :
363 : // Add/Update L2
364 0 : if (l2_active_) {
365 0 : UpdateL2();
366 : }
367 :
368 : // Apply config based on old and new values
369 0 : 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 0 : UpdateInterfaceHealthCheckService();
374 0 : return ret;
375 0 : }
376 :
377 :
378 : // Apply the latest configuration
379 0 : 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 0 : VmInterfaceState::Op l2_force_op = VmInterfaceState::INVALID;
384 0 : 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 0 : if ((device_type_ == VmInterface::VM_SRIOV) ||
390 0 : (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 0 : UpdateState(mac_vm_binding_state_.get(), l2_force_op, l3_force_op);
404 :
405 0 : 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 0 : sg_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
409 0 : tag_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
410 :
411 : // Fat flow configuration
412 0 : fat_flow_list_.UpdateList(agent, this);
413 :
414 : // Bridge Domain configuration
415 0 : bridge_domain_list_.Update(agent, this);
416 0 : if (bridge_domain_list_.list_.size() == 0) {
417 0 : 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 0 : if ((device_type_ == VmInterface::TOR ||
428 0 : device_type_ == VmInterface::DEVICE_TYPE_INVALID) &&
429 0 : (old_subnet.is_unspecified() && old_subnet_plen == 0)) {
430 : // TODO : Should force_op be set to VmInterfaceState::DEL instead?
431 0 : 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 0 : UpdateState(vrf_table_label_state_.get(), l2_force_op, l3_force_op);
443 :
444 : // Update NextHop parameters
445 0 : UpdateState(nexthop_state_.get(), l2_force_op, l3_force_op);
446 0 : GetNextHopInfo();
447 :
448 : // Add/Update L3 Metadata for v4 and v6 standards
449 0 : UpdateState(metadata_ip_state_.get(), l2_force_op, l3_force_op);
450 0 : 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 0 : if (device_type() == VmInterface::TOR ||
461 0 : device_type() == VmInterface::DEVICE_TYPE_INVALID) {
462 0 : l2_force_op = VmInterfaceState::DEL;
463 : }
464 0 : if (l2_active_ == false || is_hc_active_ == false) {
465 0 : l2_force_op = VmInterfaceState::DEL;
466 : }
467 :
468 : // Add EVPN and L3 route for do_dhcp_relay_ before instance-ip routes
469 0 : UpdateState(interface_route_state_.get(), l2_force_op, l3_force_op);
470 :
471 : // Add/Update L3/L2 routes routes resulting from instance-ip
472 0 : 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 0 : instance_ipv6_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
476 :
477 : // Update floating-ip related configuration
478 0 : floating_ip_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
479 :
480 0 : alias_ip_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
481 :
482 0 : UpdateState(resolve_route_state_.get(), l2_force_op, l3_force_op);
483 :
484 0 : static_route_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
485 :
486 0 : service_vlan_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
487 :
488 0 : vrf_assign_rule_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
489 :
490 0 : allowed_address_pair_list_.UpdateList(agent, this, l2_force_op,
491 : l3_force_op);
492 0 : receive_route_list_.UpdateList(agent, this, l2_force_op, l3_force_op);
493 0 : 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 0 : DeleteState(nexthop_state_.get());
504 0 : GetNextHopInfo();
505 :
506 : // Del L3 Metadata after deleting L3 information
507 0 : DeleteState(metadata_ip_state_.get());
508 0 : DeleteState(metadata_ip6_state_.get());
509 :
510 : // Remove floating-ip entries marked for deletion
511 0 : CleanupFloatingIpList();
512 :
513 : // Remove Alias-ip entries marked for deletion
514 0 : CleanupAliasIpList();
515 :
516 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
517 0 : if (old_l2_active != l2_active_) {
518 0 : if (l2_active_) {
519 0 : SendTrace(table, ACTIVATED_L2);
520 : } else {
521 0 : SendTrace(table, DEACTIVATED_L2);
522 : }
523 : }
524 :
525 0 : if (old_ipv4_active != ipv4_active_) {
526 0 : if (ipv4_active_) {
527 0 : SendTrace(table, ACTIVATED_IPV4);
528 : } else {
529 0 : SendTrace(table, DEACTIVATED_IPV4);
530 : }
531 : }
532 :
533 0 : if (old_ipv6_active != ipv6_active_) {
534 0 : if (ipv6_active_) {
535 0 : SendTrace(table, ACTIVATED_IPV6);
536 : } else {
537 0 : SendTrace(table, DEACTIVATED_IPV6);
538 : }
539 : }
540 : }
541 :
542 0 : void VmInterface::UpdateL2() {
543 0 : if (device_type() == VmInterface::TOR ||
544 0 : device_type() == VmInterface::DEVICE_TYPE_INVALID)
545 0 : return;
546 :
547 0 : int new_vxlan_id = vn_.get() ? vn_->GetVxLanId() : 0;
548 0 : if (l2_active_ && ((vxlan_id_ == 0) ||
549 0 : (vxlan_id_ != new_vxlan_id))) {
550 0 : vxlan_id_ = new_vxlan_id;
551 : }
552 0 : ethernet_tag_ = IsVxlanMode() ? vxlan_id_ : 0;
553 : }
554 :
555 : ////////////////////////////////////////////////////////////////////////////
556 : // VmInterface attribute methods
557 : ////////////////////////////////////////////////////////////////////////////
558 0 : bool VmInterface::UpdateState(const VmInterfaceState *state,
559 : VmInterfaceState::Op l2_force_op,
560 : VmInterfaceState::Op l3_force_op) {
561 0 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
562 0 : return state->Update(agent, this, l2_force_op, l3_force_op);
563 : }
564 :
565 0 : bool VmInterface::DeleteState(VmInterfaceState *state) {
566 0 : Agent *agent = static_cast<InterfaceTable *>(get_table())->agent();
567 0 : bool ret = true;
568 0 : if (state->l2_installed_) {
569 0 : if (state->DeleteL2(agent, this))
570 0 : state->l2_installed_ = false;
571 : else
572 0 : ret = false;
573 : }
574 0 : if (state->l3_installed_) {
575 0 : if (state->DeleteL3(agent, this))
576 0 : state->l3_installed_ = false;
577 : else
578 0 : ret = false;
579 : }
580 0 : return ret;
581 : }
582 :
583 : /////////////////////////////////////////////////////////////////////////////
584 : // VmInterfaceAttr basic routines
585 : /////////////////////////////////////////////////////////////////////////////
586 0 : VmInterfaceState::Op VmInterfaceState::RecomputeOp(Op old_op, Op new_op) {
587 0 : return (new_op > old_op) ? new_op : old_op;
588 : }
589 :
590 0 : bool VmInterfaceState::Update(const Agent *agent, VmInterface *vmi,
591 : Op l2_force_op, Op l3_force_op) const {
592 0 : Op l2_op = RecomputeOp(l2_force_op, GetOpL2(agent, vmi));
593 0 : Op l3_op = RecomputeOp(l3_force_op, GetOpL3(agent, vmi));
594 :
595 0 : if ((l2_op == DEL || l2_op == DEL_ADD) && l2_installed_) {
596 0 : DeleteL2(agent, vmi);
597 0 : l2_installed_ = false;
598 : }
599 0 : if ((l3_op == DEL || l3_op == DEL_ADD) && l3_installed_) {
600 0 : DeleteL3(agent, vmi);
601 0 : l3_installed_ = false;
602 : }
603 :
604 0 : Copy(agent, vmi);
605 :
606 0 : if (l3_op == ADD || l3_op == DEL_ADD) {
607 0 : if (AddL3(agent, vmi))
608 0 : l3_installed_ = true;
609 : }
610 0 : if (l2_op == ADD || l2_op == DEL_ADD) {
611 0 : if (AddL2(agent, vmi))
612 0 : l2_installed_ = true;
613 : }
614 :
615 0 : return true;
616 : }
617 :
618 : // Force operation to be DEL if del_pending_ is set
619 0 : VmInterfaceState::Op VmInterface::ListEntry::GetOp(VmInterfaceState::Op op)
620 : const {
621 0 : if (del_pending_ == false)
622 0 : return op;
623 :
624 0 : return VmInterfaceState::RecomputeOp(op, VmInterfaceState::DEL);
625 : }
626 :
627 0 : static bool GetIpActiveState(const IpAddress &ip, const VmInterface *vmi) {
628 0 : if (ip.is_v6())
629 0 : return vmi->ipv6_active();
630 :
631 0 : 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 0 : MacVmBindingState::MacVmBindingState() :
639 0 : VmInterfaceState(), vrf_(NULL), dhcp_enabled_(false), dhcp_enabled_v6_(false) {
640 0 : }
641 :
642 0 : MacVmBindingState::~MacVmBindingState() {
643 0 : }
644 :
645 0 : VmInterfaceState::Op MacVmBindingState::GetOpL3(const Agent *agent,
646 : const VmInterface *vmi) const {
647 0 : if (vmi->IsActive() == false)
648 0 : return VmInterfaceState::DEL;
649 :
650 0 : if (vrf_ != vmi->vrf())
651 0 : return VmInterfaceState::DEL_ADD;
652 :
653 0 : return VmInterfaceState::ADD;
654 : }
655 :
656 0 : bool MacVmBindingState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
657 : BridgeAgentRouteTable *table =
658 0 : 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 0 : if (table == NULL)
662 0 : return true;
663 0 : table->DeleteMacVmBindingRoute(agent->mac_vm_binding_peer(),
664 0 : vrf_->GetName(), vmi->vm_mac(), vmi);
665 0 : return true;
666 : }
667 :
668 0 : void MacVmBindingState::Copy(const Agent *agent, const VmInterface *vmi) const {
669 0 : vrf_ = vmi->vrf();
670 0 : dhcp_enabled_ = vmi->dhcp_enable_config();
671 0 : }
672 :
673 0 : bool MacVmBindingState::AddL3(const Agent *agent, VmInterface *vmi) const {
674 : BridgeAgentRouteTable *table =
675 0 : static_cast<BridgeAgentRouteTable *>(vrf_->GetBridgeRouteTable());
676 : // flood_dhcp must be set in route if dhcp is disabled for interface
677 0 : bool flood_dhcp = !vmi->dhcp_enable_config();
678 0 : table->AddMacVmBindingRoute(agent->mac_vm_binding_peer(), vrf_->GetName(),
679 : vmi->vm_mac(), vmi, flood_dhcp);
680 0 : return true;
681 : }
682 :
683 : /////////////////////////////////////////////////////////////////////////////
684 : // SecurityGroup routines
685 : // Does not generate any new state. Only holds reference to SG for interface
686 : /////////////////////////////////////////////////////////////////////////////
687 0 : void VmInterface::SecurityGroupEntryList::Insert
688 : (const SecurityGroupEntry *rhs) {
689 0 : list_.insert(*rhs);
690 0 : }
691 :
692 0 : void VmInterface::SecurityGroupEntryList::Update
693 : (const SecurityGroupEntry *lhs, const SecurityGroupEntry *rhs) {
694 0 : }
695 :
696 0 : void VmInterface::SecurityGroupEntryList::Remove
697 : (SecurityGroupEntrySet::iterator &it) {
698 0 : it->set_del_pending(true);
699 0 : }
700 :
701 0 : bool VmInterface::SecurityGroupEntryList::UpdateList
702 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
703 : VmInterfaceState::Op l3_force_op) {
704 0 : SecurityGroupEntrySet::iterator it = list_.begin();
705 0 : while (it != list_.end()) {
706 0 : SecurityGroupEntrySet::iterator prev = it++;
707 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
708 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
709 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
710 0 : if (prev->del_pending()) {
711 0 : list_.erase(prev);
712 : }
713 : }
714 :
715 0 : return true;
716 : }
717 :
718 0 : VmInterface::SecurityGroupEntry::SecurityGroupEntry() :
719 0 : ListEntry(), VmInterfaceState(), uuid_(nil_uuid()) {
720 0 : }
721 :
722 0 : VmInterface::SecurityGroupEntry::SecurityGroupEntry
723 0 : (const SecurityGroupEntry &rhs) :
724 0 : ListEntry(rhs.del_pending_),
725 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
726 0 : uuid_(rhs.uuid_) {
727 0 : }
728 :
729 0 : VmInterface::SecurityGroupEntry::SecurityGroupEntry(const uuid &u) :
730 0 : ListEntry(), VmInterfaceState(), uuid_(u) {
731 0 : }
732 :
733 0 : VmInterface::SecurityGroupEntry::~SecurityGroupEntry() {
734 0 : }
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 0 : VmInterfaceState::Op VmInterface::SecurityGroupEntry::GetOpL3
754 : (const Agent *agent, const VmInterface *vmi) const {
755 0 : if (del_pending_)
756 0 : return VmInterfaceState::INVALID;
757 :
758 0 : return VmInterfaceState::ADD;
759 : }
760 :
761 0 : bool VmInterface::SecurityGroupEntry::AddL3(const Agent *agent,
762 : VmInterface *vmi) const {
763 0 : if (sg_.get() != NULL)
764 0 : return false;
765 :
766 0 : SgKey sg_key(uuid_);
767 0 : sg_ = static_cast<SgEntry *>(agent->sg_table()->FindActiveEntry(&sg_key));
768 0 : return true;
769 0 : }
770 :
771 0 : bool VmInterface::SecurityGroupEntry::DeleteL3(const Agent *agent,
772 : VmInterface *vmi) const {
773 0 : sg_ = NULL;
774 0 : 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 0 : 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 0 : uint8_t in_dst_aggregate_plen) :
790 0 : protocol(proto), port(p) {
791 0 : ignore_address = fatflow_ignore_addr_map_.find(ignore_addr_value)->second;
792 0 : prefix_aggregate = in_prefix_aggregate;
793 0 : src_prefix = in_src_prefix;
794 0 : src_prefix_mask = in_src_prefix_mask;
795 0 : src_aggregate_plen = in_src_aggregate_plen;
796 0 : dst_prefix = in_dst_prefix;
797 0 : dst_prefix_mask = in_dst_prefix_mask;
798 0 : dst_aggregate_plen = in_dst_aggregate_plen;
799 0 : }
800 :
801 :
802 : VmInterface::FatFlowEntry
803 0 : 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 0 : uint8_t protocol = (uint8_t) Agent::ProtocolStringToInt(proto);
810 0 : IpAddress src_prefix;
811 0 : uint8_t src_prefix_mask = 0, src_aggregate_plen = 0;
812 0 : IpAddress dst_prefix, empty_prefix, empty_prefix_v6 = IpAddress::from_string("0::0");
813 0 : uint8_t dst_prefix_mask = 0, dst_aggregate_plen = 0;
814 0 : FatFlowPrefixAggregateType prefix_aggregate = AGGREGATE_NONE;
815 : FatFlowIgnoreAddressType ignore_address =
816 0 : fatflow_ignore_addr_map_.find(ignore_addr_str)->second;
817 0 : 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 0 : if ((protocol == IPPROTO_ICMP) || (protocol == IPPROTO_ICMPV6)) {
824 0 : protocol = IPPROTO_ICMP;
825 0 : port_num = 0;
826 : }
827 :
828 0 : 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 0 : 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 0 : 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 0 : } 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 0 : if ((in_src_prefix_str.length() == 0) && (prefix_aggregate == AGGREGATE_DST_IPV6)) {
907 0 : src_prefix = empty_prefix_v6;
908 : }
909 0 : 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 0 : src_aggregate_plen, dst_prefix, dst_prefix_mask, dst_aggregate_plen);
916 0 : 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 0 : void VmInterface::FatFlowList::Insert(const FatFlowEntry *rhs) {
927 0 : list_.insert(*rhs);
928 0 : }
929 :
930 0 : void VmInterface::FatFlowList::Update(const FatFlowEntry *lhs,
931 : const FatFlowEntry *rhs) {
932 0 : lhs->ignore_address = rhs->ignore_address;
933 0 : lhs->prefix_aggregate = rhs->prefix_aggregate;
934 0 : lhs->src_prefix = rhs->src_prefix;
935 0 : lhs->src_prefix_mask = rhs->src_prefix_mask;
936 0 : lhs->src_aggregate_plen = rhs->src_aggregate_plen;
937 0 : lhs->dst_prefix = rhs->dst_prefix;
938 0 : lhs->dst_prefix_mask = rhs->dst_prefix_mask;
939 0 : lhs->dst_aggregate_plen = rhs->dst_aggregate_plen;
940 0 : }
941 :
942 0 : void VmInterface::FatFlowList::Remove(FatFlowEntrySet::iterator &it) {
943 0 : it->set_del_pending(true);
944 0 : }
945 :
946 0 : bool VmInterface::FatFlowList::UpdateList(const Agent *agent,
947 : VmInterface *vmi) {
948 0 : FatFlowEntrySet::iterator it = list_.begin();
949 0 : while (it != list_.end()) {
950 0 : FatFlowEntrySet::iterator prev = it++;
951 0 : if (prev->del_pending_) {
952 0 : list_.erase(prev);
953 : }
954 : }
955 0 : 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 0 : bool VmInterface::BridgeDomainList::Update(const Agent *agent,
983 : VmInterface *vmi) {
984 0 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
985 0 : BridgeDomainEntrySet::iterator it = list_.begin();
986 0 : 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 0 : 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 0 : VrfTableLabelState::VrfTableLabelState() : VmInterfaceState() {
1013 0 : }
1014 :
1015 0 : VrfTableLabelState::~VrfTableLabelState() {
1016 0 : }
1017 :
1018 0 : VmInterfaceState::Op VrfTableLabelState::GetOpL3(const Agent *agent,
1019 : const VmInterface *vmi) const {
1020 0 : 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 0 : bool VrfTableLabelState::AddL3(const Agent *agent, VmInterface *vmi) const {
1026 0 : if (vmi->vrf() == NULL || vmi->vmi_type() != VmInterface::GATEWAY) {
1027 0 : 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 0 : NextHopState::NextHopState() : VmInterfaceState() {
1054 0 : }
1055 :
1056 0 : NextHopState::~NextHopState() {
1057 0 : }
1058 :
1059 : // The nexthops are deleted after all update processing by explicitly
1060 : // calling delete. So, dont return DEL operation from here
1061 0 : VmInterfaceState::Op NextHopState::GetOpL2(const Agent *agent,
1062 : const VmInterface *vmi) const {
1063 0 : if (vmi->IsActive() == false)
1064 0 : return VmInterfaceState::INVALID;
1065 0 : return VmInterfaceState::ADD;
1066 : }
1067 :
1068 : // The nexthops must be deleted after all update processing. So, dont return
1069 : // DEL operation from here
1070 0 : VmInterfaceState::Op NextHopState::GetOpL3(const Agent *agent,
1071 : const VmInterface *vmi) const {
1072 0 : if ((vmi->IsActive() == false) || (vmi->layer3_forwarding() == false))
1073 0 : return VmInterfaceState::INVALID;
1074 :
1075 0 : return VmInterfaceState::ADD;
1076 : }
1077 :
1078 0 : bool NextHopState::AddL2(const Agent *agent, VmInterface *vmi) const {
1079 0 : InterfaceNH::CreateL2VmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1080 : vmi->forwarding_vrf()->GetName(),
1081 0 : vmi->learning_enabled(),
1082 0 : vmi->etree_leaf(),
1083 0 : vmi->layer2_control_word(),
1084 : vmi->name());
1085 :
1086 : InterfaceNHKey key1(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1087 0 : vmi->GetUuid(), vmi->name()),
1088 0 : true, InterfaceNHFlags::BRIDGE, vmi->vm_mac());
1089 : l2_nh_policy_ = static_cast<NextHop *>
1090 0 : (agent->nexthop_table()->FindActiveEntry(&key1));
1091 :
1092 : InterfaceNHKey key2(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1093 0 : vmi->GetUuid(), vmi->name()),
1094 0 : false, InterfaceNHFlags::BRIDGE, vmi->vm_mac());
1095 : l2_nh_no_policy_ = static_cast<NextHop *>
1096 0 : (agent->nexthop_table()->FindActiveEntry(&key2));
1097 :
1098 : // Update L2 mpls label from nh entry
1099 0 : if (vmi->policy_enabled()) {
1100 0 : l2_label_ = l2_nh_policy_->mpls_label()->label();
1101 : } else {
1102 0 : l2_label_ = l2_nh_no_policy_->mpls_label()->label();
1103 : }
1104 :
1105 0 : return true;
1106 0 : }
1107 :
1108 0 : 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 0 : if (vmi->IsActive())
1112 0 : return false;
1113 :
1114 0 : l2_nh_policy_.reset();
1115 0 : l2_nh_no_policy_.reset();
1116 0 : l2_label_ = MplsTable::kInvalidLabel;
1117 0 : InterfaceNH::DeleteL2InterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1118 : vmi->name());
1119 0 : return true;
1120 : }
1121 :
1122 0 : bool NextHopState::AddL3(const Agent *agent, VmInterface *vmi) const {
1123 0 : InterfaceNH::CreateL3VmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1124 : vmi->forwarding_vrf()->GetName(),
1125 0 : vmi->learning_enabled(),
1126 : vmi->name());
1127 :
1128 0 : 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 0 : vmi->GetUuid(), vmi->name()),
1134 0 : true, InterfaceNHFlags::INET4, vmi->vm_mac());
1135 : l3_nh_policy_ = static_cast<NextHop *>
1136 0 : (agent->nexthop_table()->FindActiveEntry(&key1));
1137 :
1138 : InterfaceNHKey key2(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1139 0 : vmi->GetUuid(), vmi->name()),
1140 0 : false, InterfaceNHFlags::INET4, vmi->vm_mac());
1141 : l3_nh_no_policy_ = static_cast<NextHop *>
1142 0 : (agent->nexthop_table()->FindActiveEntry(&key2));
1143 :
1144 : InterfaceNHKey key3(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
1145 0 : vmi->GetUuid(), vmi->name()), false,
1146 : (InterfaceNHFlags::INET4|
1147 : InterfaceNHFlags::MULTICAST),
1148 0 : vmi->vm_mac());
1149 : l3_mcast_nh_no_policy_ = static_cast<NextHop *>
1150 0 : (agent->nexthop_table()->FindActiveEntry(&key3));
1151 :
1152 : // Update L3 mpls label from nh entry
1153 0 : if (vmi->policy_enabled()) {
1154 0 : l3_label_ = l3_nh_policy_->mpls_label()->label();
1155 : } else {
1156 0 : l3_label_ = l3_nh_no_policy_->mpls_label()->label();
1157 : }
1158 :
1159 0 : return true;
1160 0 : }
1161 :
1162 0 : 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 0 : if (vmi->IsActive() && vmi->layer3_forwarding())
1167 0 : return false;
1168 :
1169 0 : l3_mcast_nh_no_policy_.reset();
1170 0 : l3_nh_policy_.reset();
1171 0 : l3_nh_no_policy_.reset();
1172 0 : l3_label_ = MplsTable::kInvalidLabel;
1173 0 : InterfaceNH::DeleteMulticastVmInterfaceNH(vmi->GetUuid(), vmi->vm_mac(),
1174 : vmi->name());
1175 0 : InterfaceNH::DeleteL3InterfaceNH(vmi->GetUuid(), vmi->vm_mac(), vmi->name());
1176 0 : 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 0 : void VmInterface::GetNextHopInfo() {
1203 0 : l2_label_ = nexthop_state_->l2_label();
1204 0 : 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 0 : if (layer3_forwarding()) {
1208 0 : flow_key_nh_ = nexthop_state_->l3_nh_policy_;
1209 : } else {
1210 0 : flow_key_nh_ = nexthop_state_->l2_nh_policy_;
1211 : }
1212 0 : }
1213 :
1214 : ////////////////////////////////////////////////////////////////////////////
1215 : // MetaData Ip Routines
1216 : ////////////////////////////////////////////////////////////////////////////
1217 0 : MetaDataIpState::MetaDataIpState(bool ipv4)
1218 : :
1219 0 : VmInterfaceState(), mdata_ip_(), ipv4_(ipv4) {
1220 0 : }
1221 :
1222 0 : MetaDataIpState::~MetaDataIpState() {
1223 0 : mdata_ip_.reset(NULL);
1224 0 : }
1225 :
1226 : // metadata-ip is deleted after all update processing by explicitly
1227 : // calling delete. So, dont return DEL operation from here
1228 0 : VmInterfaceState::Op MetaDataIpState::GetOpL3(const Agent *agent,
1229 : const VmInterface *vmi) const {
1230 0 : if (vmi->need_linklocal_ip() == false ||
1231 0 : vmi->metadata_ip_active() == false)
1232 0 : return VmInterfaceState::INVALID;
1233 :
1234 0 : return VmInterfaceState::ADD;
1235 : }
1236 :
1237 0 : bool MetaDataIpState::AddL3(const Agent *agent, VmInterface *vmi) const {
1238 0 : if (mdata_ip_.get() == NULL) {
1239 0 : mdata_ip_.reset(new MetaDataIp(
1240 0 : ipv4_ ? agent->metadata_ip_allocator() :
1241 0 : agent->metadata_ip6_allocator(),
1242 : vmi,
1243 0 : vmi->id(), ipv4_));
1244 : }
1245 0 : mdata_ip_->set_active(true);
1246 0 : vmi->UpdateMetaDataIpInfo();
1247 0 : return true;
1248 : }
1249 :
1250 : // Delete meta-data route
1251 0 : bool MetaDataIpState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
1252 0 : if (vmi->metadata_ip_active() && vmi->need_linklocal_ip())
1253 0 : return false;
1254 :
1255 0 : if (mdata_ip_.get() == NULL) {
1256 0 : return true;
1257 : }
1258 :
1259 : // Call UpdateMetaDataIpInfo before setting mdata_ip_ state to inactive
1260 0 : vmi->UpdateMetaDataIpInfo();
1261 0 : mdata_ip_->set_active(false);
1262 0 : 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 0 : Ip6Address VmInterface::mdata_ip6_addr() const {
1277 0 : if (metadata_ip6_state_.get() == NULL)
1278 0 : return Ip6Address();
1279 :
1280 0 : if (metadata_ip6_state_->mdata_ip_.get() == NULL) {
1281 0 : return Ip6Address();
1282 : }
1283 :
1284 0 : return metadata_ip6_state_->mdata_ip_->GetLinkLocalIp6();
1285 : }
1286 :
1287 : ////////////////////////////////////////////////////////////////////////////
1288 : // ResolveRoute Attribute Routines
1289 : ////////////////////////////////////////////////////////////////////////////
1290 0 : ResolveRouteState::ResolveRouteState() :
1291 0 : VmInterfaceState(), vrf_(NULL), subnet_(), plen_(0) {
1292 0 : }
1293 :
1294 0 : ResolveRouteState::~ResolveRouteState() {
1295 0 : }
1296 :
1297 0 : void ResolveRouteState::Copy(const Agent *agent, const VmInterface *vmi) const {
1298 0 : vrf_ = vmi->forwarding_vrf();
1299 0 : subnet_ = vmi->subnet();
1300 0 : plen_ = vmi->subnet_plen();
1301 0 : }
1302 :
1303 0 : VmInterfaceState::Op ResolveRouteState::GetOpL3(const Agent *agent,
1304 : const VmInterface *vmi) const {
1305 0 : if (vmi->ipv4_active() == false)
1306 0 : return VmInterfaceState::DEL;
1307 :
1308 0 : if (vrf_ != vmi->forwarding_vrf() || subnet_ != vmi->subnet() ||
1309 0 : plen_ != vmi->subnet_plen())
1310 0 : return VmInterfaceState::DEL_ADD;
1311 :
1312 0 : return VmInterfaceState::ADD;
1313 : }
1314 :
1315 0 : bool ResolveRouteState::DeleteL3(const Agent *agent, VmInterface *vmi) const {
1316 0 : if (vrf_ == NULL)
1317 0 : return false;
1318 :
1319 0 : vmi->DeleteRoute(vrf_->GetName(), subnet_, plen_);
1320 0 : return true;
1321 : }
1322 :
1323 0 : bool ResolveRouteState::AddL3(const Agent *agent, VmInterface *vmi) const {
1324 : /* No need to add resolve route for VHOST in case of l3mh */
1325 0 : if (agent && agent->is_l3mh() && vmi->vmi_type() == VmInterface::VHOST) {
1326 0 : return true;
1327 : }
1328 :
1329 0 : if (vrf_ == NULL || subnet_.is_unspecified())
1330 0 : return false;
1331 :
1332 0 : if (vmi->vmi_type() != VmInterface::VHOST) {
1333 0 : if (vmi->vn() == NULL) {
1334 0 : return false;
1335 : }
1336 : }
1337 :
1338 0 : SecurityGroupList sg_id_list;
1339 0 : vmi->CopySgIdList(&sg_id_list);
1340 :
1341 0 : TagList tag_id_list;
1342 0 : vmi->CopyTagIdList(&tag_id_list);
1343 :
1344 0 : std::string vn_name;
1345 0 : if (vmi->vn() != NULL) {
1346 0 : vn_name = vmi->vn()->GetName();
1347 : }
1348 :
1349 0 : bool policy = vmi->policy_enabled();
1350 0 : if (vmi->vmi_type() == VmInterface::VHOST) {
1351 0 : policy = false;
1352 : }
1353 :
1354 0 : VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, vmi->GetUuid(), vmi->name());
1355 : InetUnicastAgentRouteTable::AddResolveRoute
1356 0 : (vmi->peer(), vrf_->GetName(),
1357 0 : Address::GetIp4SubnetAddress(subnet_, plen_), plen_, key,
1358 0 : vrf_->table_label(), policy, vn_name,
1359 : sg_id_list, tag_id_list);
1360 0 : return true;
1361 0 : }
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 0 : VmInterfaceState::Op ResolveRouteState::GetOpL2(const Agent *agent,
1367 : const VmInterface *vmi) const {
1368 0 : if ((vmi->vmi_type() != VmInterface::GATEWAY &&
1369 0 : vmi->vmi_type() != VmInterface::REMOTE_VM))
1370 0 : 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 0 : VmiRouteState::VmiRouteState() :
1412 0 : VmInterfaceState(), vrf_(NULL), ip_(), ethernet_tag_(0),
1413 0 : do_dhcp_relay_(false) {
1414 0 : }
1415 :
1416 0 : VmiRouteState::~VmiRouteState() {
1417 0 : }
1418 :
1419 0 : void VmiRouteState::Copy(const Agent *agent, const VmInterface *vmi) const {
1420 0 : vrf_ = vmi->vrf();
1421 0 : ethernet_tag_ = vmi->ethernet_tag();
1422 0 : do_dhcp_relay_ = vmi->do_dhcp_relay();
1423 0 : ip_ = do_dhcp_relay_ ? ip_ = vmi->dhcp_addr() : Ip4Address(0);
1424 0 : }
1425 :
1426 0 : VmInterfaceState::Op VmiRouteState::GetOpL3
1427 : (const Agent *agent, const VmInterface *vmi) const {
1428 0 : if (vmi->ipv4_active() == false)
1429 0 : 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 0 : if (do_dhcp_relay_ && vmi->do_dhcp_relay() == false)
1439 0 : return VmInterfaceState::DEL;
1440 :
1441 0 : if (vrf_ != vmi->vrf())
1442 0 : return VmInterfaceState::DEL_ADD;
1443 :
1444 0 : 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 0 : if (vmi->do_dhcp_relay() == false)
1449 0 : 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 0 : bool VmiRouteState::AddL3(const Agent *agent, VmInterface *vmi) const {
1463 0 : if (vrf_ == NULL || vmi->vn() == NULL || ip_.is_unspecified())
1464 0 : 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 0 : VmInterfaceState::Op VmiRouteState::GetOpL2
1475 : (const Agent *agent, const VmInterface *vmi) const {
1476 0 : if (vmi->l2_active() == false || vmi->is_hc_active() == false)
1477 0 : return VmInterfaceState::DEL;
1478 :
1479 0 : if (vrf_ != vmi->vrf())
1480 0 : return VmInterfaceState::DEL_ADD;
1481 :
1482 0 : if (ethernet_tag_ != vmi->ethernet_tag())
1483 0 : return VmInterfaceState::DEL_ADD;
1484 :
1485 0 : return VmInterfaceState::ADD;
1486 : }
1487 :
1488 0 : bool VmiRouteState::DeleteL2(const Agent *agent, VmInterface *vmi) const {
1489 0 : if (vrf_ == NULL)
1490 0 : return false;
1491 :
1492 0 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, Ip4Address(0),
1493 : vmi->vm_mac());
1494 0 : return true;
1495 : }
1496 :
1497 0 : bool VmiRouteState::AddL2(const Agent *agent, VmInterface *vmi) const {
1498 0 : if (vrf_ == NULL || vmi->vn() == NULL)
1499 0 : return false;
1500 :
1501 0 : vmi->AddL2InterfaceRoute(Ip4Address(), vmi->vm_mac(), Ip4Address(0));
1502 : BridgeAgentRouteTable *table =
1503 0 : static_cast<BridgeAgentRouteTable *>(vrf_->GetRouteTable(Agent::BRIDGE));
1504 0 : if(table != NULL){
1505 0 : if(table->FindRoute(agent->vrrp_mac())){
1506 0 : 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 0 : void VmInterface::InstanceIpList::Insert(const InstanceIp *rhs) {
1523 0 : list_.insert(*rhs);
1524 0 : }
1525 :
1526 0 : void VmInterface::InstanceIpList::Update(const InstanceIp *lhs,
1527 : const InstanceIp *rhs) {
1528 0 : lhs->ecmp_ = rhs->ecmp_;
1529 0 : lhs->is_service_ip_ = rhs->is_service_ip_;
1530 0 : lhs->is_service_health_check_ip_ = rhs->is_service_health_check_ip_;
1531 0 : lhs->is_local_ = rhs->is_local_;
1532 0 : lhs->tracking_ip_ = rhs->tracking_ip_;
1533 :
1534 0 : lhs->set_del_pending(false);
1535 0 : }
1536 :
1537 0 : void VmInterface::InstanceIpList::Remove(InstanceIpSet::iterator &it) {
1538 0 : it->set_del_pending(true);
1539 0 : }
1540 :
1541 0 : bool VmInterface::InstanceIpList::UpdateList
1542 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
1543 : VmInterfaceState::Op l3_force_op) {
1544 0 : InstanceIpSet::iterator it = list_.begin();
1545 : // Apply the instance-ip configured for interface
1546 0 : while (it != list_.end()) {
1547 0 : InstanceIpSet::iterator prev = it++;
1548 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
1549 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
1550 0 : if (prev->del_pending() == false)
1551 0 : prev->SetPrefixForAllocUnitIpam(vmi);
1552 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
1553 0 : if (prev->del_pending()) {
1554 0 : list_.erase(prev);
1555 : }
1556 : }
1557 :
1558 0 : return true;
1559 : }
1560 :
1561 0 : VmInterface::InstanceIp::InstanceIp() :
1562 0 : ListEntry(), VmInterfaceState(), ip_(), plen_(), ecmp_(false),
1563 0 : is_primary_(false), is_service_ip_(false),
1564 0 : is_service_health_check_ip_(false), is_local_(false),
1565 0 : tracking_ip_(), vrf_(NULL), ethernet_tag_(0) {
1566 0 : }
1567 :
1568 0 : VmInterface::InstanceIp::InstanceIp(const InstanceIp &rhs) :
1569 0 : ListEntry(rhs.del_pending_),
1570 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
1571 0 : ip_(rhs.ip_), plen_(rhs.plen_), ecmp_(rhs.ecmp_),
1572 0 : is_primary_(rhs.is_primary_), is_service_ip_(rhs.is_service_ip_),
1573 0 : is_service_health_check_ip_(rhs.is_service_health_check_ip_),
1574 0 : is_local_(rhs.is_local_), tracking_ip_(rhs.tracking_ip_),
1575 0 : vrf_(NULL), ethernet_tag_(0) {
1576 0 : }
1577 :
1578 0 : 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 0 : const IpAddress &tracking_ip) :
1584 0 : ListEntry(), VmInterfaceState(), ip_(addr), plen_(plen), ecmp_(ecmp),
1585 0 : is_primary_(is_primary), is_service_ip_(is_service_ip),
1586 0 : is_service_health_check_ip_(is_service_health_check_ip),
1587 0 : is_local_(is_local), tracking_ip_(tracking_ip), vrf_(NULL),
1588 0 : ethernet_tag_(0) {
1589 0 : }
1590 :
1591 0 : VmInterface::InstanceIp::~InstanceIp() {
1592 0 : }
1593 :
1594 0 : bool VmInterface::InstanceIp::operator() (const InstanceIp &lhs,
1595 : const InstanceIp &rhs) const {
1596 0 : return lhs.IsLess(&rhs);
1597 : }
1598 :
1599 0 : bool VmInterface::InstanceIp::IsLess(const InstanceIp *rhs) const {
1600 0 : return ip_ < rhs->ip_;
1601 : }
1602 :
1603 0 : void VmInterface::InstanceIp::SetPrefixForAllocUnitIpam(VmInterface *vmi) const{
1604 0 : if (vmi->vn() == NULL)
1605 0 : return;
1606 :
1607 0 : uint32_t alloc_unit = vmi->vn()->GetAllocUnitFromIpam(ip_);
1608 :
1609 0 : uint8_t alloc_prefix = 0;
1610 0 : if (alloc_unit > 0) {
1611 0 : alloc_prefix = log2(alloc_unit);
1612 : }
1613 :
1614 0 : if (ip_.is_v4()) {
1615 0 : plen_ = Address::kMaxV4PrefixLen - alloc_prefix;
1616 0 : } else if (ip_.is_v6()) {
1617 0 : plen_ = Address::kMaxV6PrefixLen - alloc_prefix;
1618 : }
1619 : }
1620 :
1621 0 : static bool GetInstanceIpActiveState(const VmInterface::InstanceIp *instance_ip,
1622 : const VmInterface *vmi) {
1623 0 : 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 0 : if (instance_ip->ip_.is_v6()) {
1630 0 : return vmi->ipv6_active();
1631 : }
1632 :
1633 0 : return vmi->ipv4_active();
1634 : }
1635 :
1636 0 : VmInterfaceState::Op VmInterface::InstanceIp::GetOpL2
1637 : (const Agent *agent, const VmInterface *vmi) const {
1638 0 : if (GetInstanceIpActiveState(this, vmi) == false)
1639 0 : return VmInterfaceState::DEL;
1640 :
1641 0 : if (!is_service_ip_ && vmi->vmi_type() != VmInterface::VHOST) {
1642 : // Add route only when vn IPAM exists for the IP
1643 0 : if (vmi->vn() && vmi->vn()->GetIpam(ip_) == NULL)
1644 0 : return VmInterfaceState::DEL;
1645 : }
1646 :
1647 0 : if (IsL3Only())
1648 0 : return VmInterfaceState::DEL;
1649 :
1650 0 : if (vrf_ != vmi->vrf())
1651 0 : return VmInterfaceState::DEL_ADD;
1652 :
1653 0 : if (ethernet_tag_ != vmi->ethernet_tag())
1654 0 : return VmInterfaceState::DEL_ADD;
1655 :
1656 0 : return VmInterfaceState::ADD;
1657 : }
1658 :
1659 0 : bool VmInterface::InstanceIp::AddL2(const Agent *agent,
1660 : VmInterface *vmi) const {
1661 0 : if (vrf_ == NULL)
1662 0 : return false;
1663 :
1664 0 : vmi->AddL2InterfaceRoute(ip_, vmi->vm_mac(), tracking_ip_);
1665 0 : return true;
1666 : }
1667 :
1668 0 : bool VmInterface::InstanceIp::DeleteL2(const Agent *agent,
1669 : VmInterface *vmi) const {
1670 0 : if (vrf_ == NULL)
1671 0 : return false;
1672 :
1673 0 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, ip_, vmi->vm_mac());
1674 0 : return true;
1675 : }
1676 :
1677 0 : VmInterfaceState::Op VmInterface::InstanceIp::GetOpL3
1678 : (const Agent *agent, const VmInterface *vmi) const {
1679 : // TODO : Should be check health-check state here?
1680 0 : if (GetInstanceIpActiveState(this, vmi) == false)
1681 0 : return VmInterfaceState::DEL;
1682 :
1683 0 : if (!is_service_ip_ && vmi->vmi_type() != VmInterface::VHOST) {
1684 : // Add route only when vn IPAM exists for the IP
1685 0 : if (vmi->vn() && vmi->vn()->GetIpam(ip_) == NULL)
1686 0 : return VmInterfaceState::DEL;
1687 : }
1688 :
1689 0 : if (vrf_ != vmi->vrf())
1690 0 : return VmInterfaceState::DEL_ADD;
1691 :
1692 0 : return VmInterfaceState::ADD;
1693 : }
1694 :
1695 0 : bool VmInterface::InstanceIp::AddL3(const Agent *agent,
1696 : VmInterface *vmi) const {
1697 0 : if (vrf_ == NULL)
1698 0 : return false;
1699 0 : assert(ip_.is_unspecified() == false);
1700 0 : std::string vn_name;
1701 0 : if (vmi->vn()) {
1702 0 : vn_name = vmi->vn()->GetName();
1703 0 : } else if (vmi->vmi_type() == VHOST) {
1704 0 : vn_name = agent->fabric_vn_name();
1705 : }
1706 :
1707 0 : vmi->AddRoute(vmi->vrf()->GetName(), ip_, plen_, vn_name,
1708 0 : is_force_policy(), ecmp_,is_local_,
1709 0 : is_service_health_check_ip_, vmi->GetServiceIp(ip_),
1710 0 : tracking_ip_, CommunityList(), vmi->label(),
1711 0 : is_service_ip_ ? kServiceInterface : kInterface);
1712 0 : return true;
1713 0 : }
1714 :
1715 0 : bool VmInterface::InstanceIp::DeleteL3(const Agent *agent,
1716 : VmInterface *vmi) const {
1717 0 : if (vrf_ == NULL)
1718 0 : return false;
1719 0 : vmi->DeleteRoute(vrf_->GetName(), ip_, plen_);
1720 0 : return true;
1721 : }
1722 :
1723 0 : void VmInterface::InstanceIp::Copy(const Agent *agent,
1724 : const VmInterface *vmi) const {
1725 0 : vrf_ = vmi->vrf();
1726 0 : ethernet_tag_ = vmi->ethernet_tag();
1727 0 : }
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 0 : bool VmInterface::LearntMacIpList::UpdateList
1751 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
1752 : VmInterfaceState::Op l3_force_op) {
1753 0 : LearntMacIpSet::iterator it = list_.begin();
1754 : // Apply the instance-ip configured for interface
1755 0 : 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 0 : return true;
1766 : }
1767 :
1768 0 : VmInterface::LearntMacIp::LearntMacIp() :
1769 0 : ListEntry(), VmInterfaceState(), ip_(), mac_(),
1770 0 : vrf_(NULL), ethernet_tag_(0) {
1771 0 : }
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 0 : VmInterface::LearntMacIp::~LearntMacIp() {
1787 0 : }
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 0 : void VmInterface::CleanupFloatingIpList() {
1980 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
1981 0 : FloatingIpSet::iterator it = floating_ip_list_.list_.begin();
1982 0 : while (it != floating_ip_list_.list_.end()) {
1983 0 : FloatingIpSet::iterator prev = it++;
1984 0 : if (prev->del_pending_ == false)
1985 0 : continue;
1986 :
1987 : // The floating-ip is leaving the interface configuration, which is
1988 : // the only trigger that withdraws its DNS record. DeleteL3() does not
1989 : // withdraw, so that the record survives the instance being powered
1990 : // off, and an entry configured while the interface was inactive never
1991 : // reached DeleteL3() in the first place.
1992 : //
1993 : // vn_ has been reset by FloatingIp::Copy() by now, hence the lookup by
1994 : // uuid. It returns NULL once the VN is deleted, which is not a missed
1995 : // withdraw: DnsProto::VnNotify() withdraws and erases every record of
1996 : // a deleted VN, so there is nothing left to withdraw by then.
1997 0 : if (table->update_floatingip_cb().empty() == false) {
1998 0 : VnEntry *vn = table->FindVnRef(prev->vn_uuid_);
1999 0 : if (vn != NULL) {
2000 0 : table->update_floatingip_cb()(this, vn, prev->floating_ip_,
2001 : true);
2002 : }
2003 : }
2004 :
2005 0 : if (prev->floating_ip_.is_v4()) {
2006 0 : floating_ip_list_.v4_count_--;
2007 : assert(floating_ip_list_.v4_count_ >= 0);
2008 : } else {
2009 0 : floating_ip_list_.v6_count_--;
2010 : assert(floating_ip_list_.v6_count_ >= 0);
2011 : }
2012 0 : floating_ip_list_.list_.erase(prev);
2013 : }
2014 0 : }
2015 :
2016 0 : void VmInterface::FloatingIpList::Insert(const FloatingIp *rhs) {
2017 0 : std::pair<FloatingIpSet::iterator, bool> ret = list_.insert(*rhs);
2018 0 : if (ret.second) {
2019 0 : if (rhs->floating_ip_.is_v4()) {
2020 0 : v4_count_++;
2021 : } else {
2022 0 : v6_count_++;
2023 : }
2024 : }
2025 0 : }
2026 :
2027 0 : void VmInterface::FloatingIpList::Update(const FloatingIp *lhs,
2028 : const FloatingIp *rhs) {
2029 0 : if (lhs->fixed_ip_ != rhs->fixed_ip_) {
2030 0 : lhs->fixed_ip_ = rhs->fixed_ip_;
2031 : }
2032 :
2033 0 : lhs->direction_ = rhs->direction_;
2034 0 : lhs->port_map_enabled_ = rhs->port_map_enabled_;
2035 0 : lhs->src_port_map_ = rhs->src_port_map_;
2036 0 : lhs->dst_port_map_ = rhs->dst_port_map_;
2037 0 : lhs->set_del_pending(false);
2038 0 : }
2039 :
2040 0 : void VmInterface::FloatingIpList::Remove(FloatingIpSet::iterator &it) {
2041 0 : it->set_del_pending(true);
2042 0 : }
2043 :
2044 0 : bool VmInterface::FloatingIpList::UpdateList(const Agent *agent,
2045 : VmInterface *vmi,
2046 : VmInterfaceState::Op l2_force_op,
2047 : VmInterfaceState::Op l3_force_op) {
2048 0 : FloatingIpSet::iterator it = list_.begin();
2049 0 : while (it != list_.end()) {
2050 0 : FloatingIpSet::iterator prev = it++;
2051 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2052 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2053 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2054 : }
2055 0 : return true;
2056 : }
2057 :
2058 0 : VmInterface::FloatingIp::FloatingIp() :
2059 0 : ListEntry(), VmInterfaceState(), floating_ip_(), vn_(NULL),
2060 0 : vrf_(NULL, this), vrf_name_(""), vn_uuid_(),
2061 0 : fixed_ip_(), direction_(DIRECTION_BOTH), port_map_enabled_(false),
2062 0 : src_port_map_(), dst_port_map_(), ethernet_tag_(0), port_nat_(false) {
2063 0 : }
2064 :
2065 0 : VmInterface::FloatingIp::FloatingIp(const FloatingIp &rhs) :
2066 0 : ListEntry(rhs.del_pending_),
2067 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2068 0 : floating_ip_(rhs.floating_ip_), vn_(rhs.vn_), vrf_(rhs.vrf_, this),
2069 0 : vrf_name_(rhs.vrf_name_), vn_uuid_(rhs.vn_uuid_), fixed_ip_(rhs.fixed_ip_),
2070 0 : direction_(rhs.direction_), port_map_enabled_(rhs.port_map_enabled_),
2071 0 : src_port_map_(rhs.src_port_map_), dst_port_map_(rhs.dst_port_map_),
2072 0 : ethernet_tag_(rhs.ethernet_tag_), port_nat_(rhs.port_nat_) {
2073 0 : }
2074 :
2075 0 : VmInterface::FloatingIp::FloatingIp(const IpAddress &addr,
2076 : const std::string &vrf,
2077 : const boost::uuids::uuid &vn_uuid,
2078 : const IpAddress &fixed_ip,
2079 : Direction direction,
2080 : bool port_map_enabled,
2081 : const PortMap &src_port_map,
2082 : const PortMap &dst_port_map,
2083 0 : bool port_nat) :
2084 0 : ListEntry(), VmInterfaceState(),floating_ip_(addr), vn_(NULL),
2085 0 : vrf_(NULL, this), vrf_name_(vrf), vn_uuid_(vn_uuid), fixed_ip_(fixed_ip),
2086 0 : direction_(direction), port_map_enabled_(port_map_enabled),
2087 0 : src_port_map_(src_port_map), dst_port_map_(dst_port_map), ethernet_tag_(0),
2088 0 : port_nat_(port_nat) {
2089 0 : }
2090 :
2091 0 : VmInterface::FloatingIp::~FloatingIp() {
2092 0 : }
2093 :
2094 0 : bool VmInterface::FloatingIp::operator() (const FloatingIp &lhs,
2095 : const FloatingIp &rhs) const {
2096 0 : return lhs.IsLess(&rhs);
2097 : }
2098 :
2099 : // Compare key for FloatingIp. Key is <floating_ip_ and vrf_name_> for both
2100 : // Config and Operational processing
2101 0 : bool VmInterface::FloatingIp::IsLess(const FloatingIp *rhs) const {
2102 0 : if (floating_ip_ != rhs->floating_ip_)
2103 0 : return floating_ip_ < rhs->floating_ip_;
2104 :
2105 0 : return (vrf_name_ < rhs->vrf_name_);
2106 : }
2107 :
2108 : const IpAddress
2109 0 : VmInterface::FloatingIp::GetFixedIp(const VmInterface *vmi) const {
2110 0 : if (fixed_ip_.is_unspecified()) {
2111 0 : if (floating_ip_.is_v4() == true) {
2112 0 : return vmi->primary_ip_addr();
2113 : } else {
2114 0 : return vmi->primary_ip6_addr();
2115 : }
2116 : }
2117 0 : return fixed_ip_;
2118 : }
2119 :
2120 0 : bool VmInterface::FloatingIp::port_map_enabled() const {
2121 0 : return port_map_enabled_;
2122 : }
2123 :
2124 0 : uint32_t VmInterface::FloatingIp::PortMappingSize() const {
2125 0 : return src_port_map_.size();
2126 : }
2127 :
2128 0 : bool VmInterface::FloatingIp::port_nat() const {
2129 0 : return port_nat_;
2130 : }
2131 :
2132 0 : int32_t VmInterface::FloatingIp::GetSrcPortMap(uint8_t protocol,
2133 : uint16_t src_port) const {
2134 0 : PortMapIterator it = src_port_map_.find(PortMapKey(protocol, src_port));
2135 0 : if (it == src_port_map_.end())
2136 0 : return -1;
2137 0 : return it->second;
2138 : }
2139 :
2140 0 : int32_t VmInterface::FloatingIp::GetDstPortMap(uint8_t protocol,
2141 : uint16_t dst_port) const {
2142 0 : PortMapIterator it = dst_port_map_.find(PortMapKey(protocol, dst_port));
2143 0 : if (it == dst_port_map_.end())
2144 0 : return -1;
2145 0 : return it->second;
2146 : }
2147 :
2148 0 : void VmInterface::FloatingIp::Copy(const Agent *agent,
2149 : const VmInterface *vmi) const {
2150 : // Delete for FloatingIp happens in CleanupFloatingIpList(). So, dont
2151 : // update vn_ and vrf_ fields in case of delete
2152 0 : if (del_pending_) {
2153 0 : vn_ = NULL;
2154 0 : vrf_ = NULL;
2155 0 : return;
2156 : }
2157 :
2158 0 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
2159 0 : if (vn_.get() == NULL)
2160 0 : vn_ = table->FindVnRef(vn_uuid_);
2161 :
2162 0 : if (vrf_.get() == NULL)
2163 0 : vrf_ = table->FindVrfRef(vrf_name_);
2164 0 : ethernet_tag_ = vmi->ethernet_tag();
2165 :
2166 0 : return;
2167 : }
2168 :
2169 0 : VmInterfaceState::Op VmInterface::FloatingIp::GetOpL3
2170 : (const Agent *agent, const VmInterface *vmi) const {
2171 0 : if (GetIpActiveState(floating_ip_, vmi) == false)
2172 0 : return VmInterfaceState::DEL;
2173 :
2174 0 : if (vmi->vrf() == NULL || vmi->vn() == NULL)
2175 0 : return VmInterfaceState::DEL;
2176 :
2177 0 : return VmInterfaceState::ADD;
2178 : }
2179 :
2180 0 : bool VmInterface::FloatingIp::AddL3(const Agent *agent,
2181 : VmInterface *vmi) const {
2182 0 : if (vrf_.get() == NULL || vn_.get() == NULL || port_nat_)
2183 0 : return false;
2184 :
2185 0 : fixed_ip_ = GetFixedIp(vmi);
2186 0 : uint8_t plen = floating_ip_.is_v4() ?
2187 0 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2188 0 : IpAddress service_ip = Ip4Address();
2189 0 : if (floating_ip_.is_v6())
2190 0 : service_ip = Ip6Address();
2191 :
2192 0 : bool ecmp = floating_ip_.is_v4() ? vmi->ecmp() : vmi->ecmp6();
2193 0 : vmi->AddRoute(vrf_.get()->GetName(), floating_ip_, plen, vn_->GetName(),
2194 0 : false, ecmp, false, false, service_ip, fixed_ip_,
2195 0 : CommunityList(), vmi->label(), kInterface);
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 : false);
2201 : //TODO:: callback for DNS handling
2202 : }
2203 :
2204 0 : return true;
2205 : }
2206 :
2207 0 : bool VmInterface::FloatingIp::DeleteL3(const Agent *agent,
2208 : VmInterface *vmi) const {
2209 0 : if (vrf_.get() == NULL)
2210 0 : return false;
2211 0 : uint8_t plen = floating_ip_.is_v4() ?
2212 0 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2213 :
2214 0 : vmi->DeleteRoute(vrf_.get()->GetName(), floating_ip_, plen);
2215 :
2216 : // The DNS record is not withdrawn here. This routine runs whenever the
2217 : // interface stops forwarding, which includes the instance being powered
2218 : // off - the tap device goes away and ipv4_active() turns false. The
2219 : // record tracks floating-ip configuration, not forwarding state, the same
2220 : // way the interface's own DNS record does, so it has to survive that.
2221 : //
2222 : // Withdrawing it is CleanupFloatingIpList(), which ApplyConfig() always
2223 : // reaches after the floating-ip list is updated, and which also covers
2224 : // the entries that were never installed because the interface was
2225 : // inactive while they were configured.
2226 0 : return true;
2227 : }
2228 :
2229 0 : VmInterfaceState::Op VmInterface::FloatingIp::GetOpL2
2230 : (const Agent *agent, const VmInterface *vmi) const {
2231 0 : if (GetIpActiveState(floating_ip_, vmi) == false)
2232 0 : return VmInterfaceState::DEL;
2233 :
2234 0 : if (vmi->vrf() == NULL || vmi->vn() == NULL)
2235 0 : return VmInterfaceState::DEL;
2236 :
2237 0 : if (ethernet_tag_ != vmi->ethernet_tag())
2238 0 : return VmInterfaceState::DEL_ADD;
2239 :
2240 0 : return VmInterfaceState::ADD;
2241 : }
2242 :
2243 0 : bool VmInterface::FloatingIp::AddL2(const Agent *agent,
2244 : VmInterface *vmi) const {
2245 0 : if (vrf_.get() == NULL || vn_.get() == NULL || port_nat_)
2246 0 : return false;
2247 :
2248 0 : SecurityGroupList sg_id_list;
2249 0 : vmi->CopySgIdList(&sg_id_list);
2250 :
2251 0 : TagList tag_id_list;
2252 0 : vmi->CopyTagIdList(&tag_id_list);
2253 :
2254 0 : PathPreference path_preference;
2255 0 : vmi->SetPathPreference(&path_preference, false, GetFixedIp(vmi));
2256 :
2257 : EvpnAgentRouteTable *evpn_table = static_cast<EvpnAgentRouteTable *>
2258 0 : (vrf_->GetEvpnRouteTable());
2259 :
2260 0 : std::string vn_name;
2261 0 : if (vmi->vn()) {
2262 0 : vn_name = vmi->vn()->GetName();
2263 : }
2264 :
2265 0 : evpn_table->AddReceiveRoute(vmi->peer_.get(), vrf_->GetName(),
2266 0 : vmi->l2_label(), vmi->vm_mac(), floating_ip_,
2267 : ethernet_tag_, vn_name,
2268 : path_preference);
2269 0 : return true;
2270 0 : }
2271 :
2272 0 : bool VmInterface::FloatingIp::DeleteL2(const Agent *agent,
2273 : VmInterface *vmi) const {
2274 0 : if (vrf_.get() == NULL)
2275 0 : return false;
2276 :
2277 : EvpnAgentRouteTable *evpn_table =
2278 0 : static_cast<EvpnAgentRouteTable *>(vrf_->GetEvpnRouteTable());
2279 0 : if (evpn_table == NULL) {
2280 0 : return false;
2281 : }
2282 :
2283 0 : evpn_table->DelLocalVmRoute(vmi->peer_.get(), vrf_->GetName(),
2284 0 : vmi->vm_mac(), vmi, floating_ip_,
2285 : ethernet_tag_);
2286 0 : return true;
2287 : }
2288 :
2289 : /////////////////////////////////////////////////////////////////////////////
2290 : // AliasIp routines
2291 : /////////////////////////////////////////////////////////////////////////////
2292 0 : void VmInterface::AliasIpList::Insert(const AliasIp *rhs) {
2293 0 : std::pair<AliasIpSet::iterator, bool> ret = list_.insert(*rhs);
2294 0 : if (ret.second) {
2295 0 : if (rhs->alias_ip_.is_v4()) {
2296 0 : v4_count_++;
2297 : } else {
2298 0 : v6_count_++;
2299 : }
2300 : }
2301 0 : }
2302 :
2303 0 : void VmInterface::AliasIpList::Update(const AliasIp *lhs, const AliasIp *rhs) {
2304 0 : lhs->set_del_pending(false);
2305 0 : }
2306 :
2307 0 : void VmInterface::AliasIpList::Remove(AliasIpSet::iterator &it) {
2308 0 : it->set_del_pending(true);
2309 0 : }
2310 :
2311 0 : bool VmInterface::AliasIpList::UpdateList(const Agent *agent, VmInterface *vmi,
2312 : VmInterfaceState::Op l2_force_op,
2313 : VmInterfaceState::Op l3_force_op) {
2314 0 : AliasIpSet::iterator it = list_.begin();
2315 0 : while (it != list_.end()) {
2316 0 : AliasIpSet::iterator prev = it++;
2317 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2318 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2319 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2320 : }
2321 0 : return true;
2322 : }
2323 :
2324 0 : void VmInterface::CleanupAliasIpList() {
2325 0 : AliasIpSet::iterator it = alias_ip_list_.list_.begin();
2326 0 : while (it != alias_ip_list_.list_.end()) {
2327 0 : AliasIpSet::iterator prev = it++;
2328 0 : if (prev->del_pending_ == false)
2329 0 : continue;
2330 :
2331 0 : if (prev->alias_ip_.is_v4()) {
2332 0 : alias_ip_list_.v4_count_--;
2333 : assert(alias_ip_list_.v4_count_ >= 0);
2334 : } else {
2335 0 : alias_ip_list_.v6_count_--;
2336 : assert(alias_ip_list_.v6_count_ >= 0);
2337 : }
2338 0 : alias_ip_list_.list_.erase(prev);
2339 : }
2340 0 : }
2341 :
2342 0 : VmInterface::AliasIp::AliasIp() :
2343 0 : ListEntry(), VmInterfaceState(), alias_ip_(), vn_(NULL), vrf_(NULL, this),
2344 0 : vrf_name_(""), vn_uuid_() {
2345 0 : }
2346 :
2347 0 : VmInterface::AliasIp::AliasIp(const AliasIp &rhs) :
2348 0 : ListEntry(rhs.del_pending_),
2349 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2350 0 : alias_ip_(rhs.alias_ip_), vn_(rhs.vn_), vrf_(rhs.vrf_, this),
2351 0 : vrf_name_(rhs.vrf_name_), vn_uuid_(rhs.vn_uuid_) {
2352 0 : }
2353 :
2354 0 : VmInterface::AliasIp::AliasIp(const IpAddress &addr, const std::string &vrf,
2355 0 : const boost::uuids::uuid &vn_uuid) :
2356 0 : ListEntry(), VmInterfaceState(), alias_ip_(addr), vn_(NULL),
2357 0 : vrf_(NULL, this), vrf_name_(vrf), vn_uuid_(vn_uuid) {
2358 0 : }
2359 :
2360 0 : VmInterface::AliasIp::~AliasIp() {
2361 0 : }
2362 :
2363 0 : bool VmInterface::AliasIp::operator() (const AliasIp &lhs,
2364 : const AliasIp &rhs) const {
2365 0 : return lhs.IsLess(&rhs);
2366 : }
2367 :
2368 : // Compare key for AliasIp. Key is <alias_ip_ and vrf_name_> for both
2369 : // Config and Operational processing
2370 0 : bool VmInterface::AliasIp::IsLess(const AliasIp *rhs) const {
2371 0 : if (alias_ip_ != rhs->alias_ip_)
2372 0 : return alias_ip_ < rhs->alias_ip_;
2373 :
2374 0 : return (vrf_name_ < rhs->vrf_name_);
2375 : }
2376 :
2377 0 : VmInterfaceState::Op VmInterface::AliasIp::GetOpL3(const Agent *agent,
2378 : const VmInterface *vmi) const {
2379 0 : if (GetIpActiveState(alias_ip_, vmi) == false)
2380 0 : return VmInterfaceState::DEL;
2381 :
2382 0 : if (vrf_ != vmi->vrf())
2383 0 : return VmInterfaceState::DEL_ADD;
2384 :
2385 0 : return VmInterfaceState::ADD;
2386 : }
2387 :
2388 0 : void VmInterface::AliasIp::Copy(const Agent *agent,
2389 : const VmInterface *vmi) const {
2390 0 : if (del_pending_) {
2391 0 : vrf_ = NULL;
2392 0 : vn_ = NULL;
2393 0 : return;
2394 : }
2395 :
2396 0 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
2397 0 : if (vn_.get() == NULL) {
2398 0 : vn_ = table->FindVnRef(vn_uuid_);
2399 0 : assert(vn_.get());
2400 : }
2401 :
2402 0 : if (vrf_.get() == NULL) {
2403 0 : vrf_ = table->FindVrfRef(vrf_name_);
2404 0 : assert(vrf_.get());
2405 : }
2406 0 : return;
2407 : }
2408 :
2409 0 : bool VmInterface::AliasIp::AddL3(const Agent *agent, VmInterface *vmi) const {
2410 0 : if (vrf_.get() == NULL || vn_.get() == NULL)
2411 0 : return false;
2412 :
2413 0 : uint8_t plen = alias_ip_.is_v4() ?
2414 0 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2415 0 : IpAddress service_ip = Ip4Address();
2416 0 : if (alias_ip_.is_v6())
2417 0 : service_ip = Ip6Address();
2418 0 : vmi->AddRoute(vrf_->GetName(), alias_ip_, plen, vn_->GetName(), false,
2419 0 : vmi->ecmp(), false, false, service_ip, service_ip,
2420 0 : CommunityList(), vmi->label(), kInterface);
2421 0 : return true;
2422 : }
2423 :
2424 0 : bool VmInterface::AliasIp::DeleteL3(const Agent *agent,
2425 : VmInterface *vmi) const {
2426 0 : if (vrf_ == NULL)
2427 0 : return false;
2428 0 : uint8_t plen = alias_ip_.is_v4() ?
2429 0 : Address::kMaxV4PrefixLen : Address::kMaxV6PrefixLen;
2430 0 : vmi->DeleteRoute(vrf_.get()->GetName(), alias_ip_, plen);
2431 0 : return true;
2432 : }
2433 :
2434 : /////////////////////////////////////////////////////////////////////////////
2435 : // StaticRoute routines
2436 : /////////////////////////////////////////////////////////////////////////////
2437 0 : void VmInterface::StaticRouteList::Insert(const StaticRoute *rhs) {
2438 0 : list_.insert(*rhs);
2439 0 : }
2440 :
2441 0 : void VmInterface::StaticRouteList::Update(const StaticRoute *lhs,
2442 : const StaticRoute *rhs) {
2443 0 : if (lhs->communities_ != rhs->communities_) {
2444 0 : (const_cast<StaticRoute *>(lhs))->communities_ = rhs->communities_;
2445 : }
2446 0 : lhs->set_del_pending(false);
2447 0 : }
2448 :
2449 0 : void VmInterface::StaticRouteList::Remove(StaticRouteSet::iterator &it) {
2450 0 : it->set_del_pending(true);
2451 0 : }
2452 :
2453 0 : bool VmInterface::StaticRouteList::UpdateList
2454 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
2455 : VmInterfaceState::Op l3_force_op) {
2456 0 : StaticRouteSet::iterator it = list_.begin();
2457 0 : while (it != list_.end()) {
2458 0 : StaticRouteSet::iterator prev = it++;
2459 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2460 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2461 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2462 0 : if (prev->del_pending_) {
2463 0 : list_.erase(prev);
2464 : }
2465 : }
2466 0 : return true;
2467 : }
2468 :
2469 0 : VmInterface::StaticRoute::StaticRoute() :
2470 0 : ListEntry(), VmInterfaceState(), vrf_(), addr_(), plen_(0), gw_list_(),
2471 0 : communities_() {
2472 0 : }
2473 :
2474 0 : VmInterface::StaticRoute::StaticRoute(const StaticRoute &rhs) :
2475 0 : ListEntry(rhs.del_pending_),
2476 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2477 0 : vrf_(rhs.vrf_), addr_(rhs.addr_), plen_(rhs.plen_), gw_list_(rhs.gw_list_),
2478 0 : communities_(rhs.communities_) {
2479 0 : }
2480 :
2481 0 : VmInterface::StaticRoute::StaticRoute(const IpAddress &addr,
2482 : uint32_t plen, const AddressList &gw_list,
2483 0 : const CommunityList &communities) :
2484 0 : ListEntry(), VmInterfaceState(), vrf_(), addr_(addr), plen_(plen), gw_list_(gw_list),
2485 0 : communities_(communities) {
2486 0 : }
2487 :
2488 0 : VmInterface::StaticRoute::~StaticRoute() {
2489 0 : }
2490 :
2491 0 : bool VmInterface::StaticRoute::operator() (const StaticRoute &lhs,
2492 : const StaticRoute &rhs) const {
2493 0 : return lhs.IsLess(&rhs);
2494 : }
2495 :
2496 0 : bool VmInterface::StaticRoute::IsLess(const StaticRoute *rhs) const {
2497 0 : if (addr_ != rhs->addr_)
2498 0 : return addr_ < rhs->addr_;
2499 :
2500 0 : if (plen_ != rhs->plen_) {
2501 0 : return plen_ < rhs->plen_;
2502 : }
2503 :
2504 0 : return gw_list_.size() < rhs->gw_list_.size();
2505 : }
2506 :
2507 0 : void VmInterface::StaticRoute::Copy(const Agent *agent,
2508 : const VmInterface *vmi) const {
2509 0 : if (vmi->vmi_type() == VmInterface::VHOST) {
2510 0 : vrf_ = vmi->forwarding_vrf();
2511 : } else {
2512 0 : vrf_ = vmi->vrf();
2513 : }
2514 0 : }
2515 :
2516 0 : VmInterfaceState::Op VmInterface::StaticRoute::GetOpL3
2517 : (const Agent *agent, const VmInterface *vmi) const {
2518 0 : if (GetIpActiveState(addr_, vmi) == false)
2519 0 : return VmInterfaceState::DEL;
2520 :
2521 0 : if (vrf_ != vmi->vrf())
2522 0 : return VmInterfaceState::DEL_ADD;
2523 :
2524 0 : return VmInterfaceState::ADD;
2525 : }
2526 :
2527 0 : bool VmInterface::StaticRoute::AddL3(const Agent *agent,
2528 : VmInterface *vmi) const {
2529 0 : if (vrf_ == NULL)
2530 0 : return false;
2531 0 : std::string vn_name;
2532 0 : if (vmi->vn()) {
2533 0 : vn_name = vmi->vn()->GetName();
2534 0 : } else if (vmi->vmi_type() == VHOST) {
2535 0 : vn_name = agent->fabric_vn_name();
2536 : }
2537 :
2538 0 : if (addr_.is_v4() && !gw_list_.empty() && gw_list_[0] != Ip4Address(0)) {
2539 0 : SecurityGroupList sg_id_list;
2540 0 : vmi->CopySgIdList(&sg_id_list);
2541 :
2542 0 : TagList tag_id_list;
2543 0 : vmi->CopyTagIdList(&tag_id_list);
2544 :
2545 0 : VnListType vn_list;
2546 0 : if (vmi->vn()) {
2547 0 : vn_list.insert(vn_name);
2548 : }
2549 :
2550 0 : bool native_encap = false;
2551 0 : const Peer *peer = vmi->peer_.get();
2552 0 : if (vrf_->GetName() == agent->fabric_vrf_name()) {
2553 0 : vn_list.insert(agent->fabric_vn_name());
2554 0 : native_encap = true;
2555 0 : peer = agent->local_peer();
2556 : }
2557 :
2558 : InetUnicastAgentRouteTable::AddGatewayRoute
2559 0 : (peer, vrf_->GetName(), addr_.to_v4(), plen_,
2560 0 : gw_list_, vn_list, vmi->vrf_->table_label(),
2561 0 : sg_id_list, tag_id_list, communities_, native_encap);
2562 0 : } else {
2563 0 : IpAddress dependent_ip;
2564 0 : bool ecmp = false;
2565 0 : if (addr_.is_v4()) {
2566 0 : dependent_ip = vmi->primary_ip_addr();
2567 0 : ecmp = vmi->ecmp();
2568 0 : } else if (addr_.is_v6()) {
2569 0 : dependent_ip = vmi->primary_ip6_addr();
2570 0 : ecmp = vmi->ecmp6();
2571 : }
2572 0 : vmi->AddRoute(vrf_->GetName(), addr_, plen_, vn_name,
2573 0 : false, ecmp, false, false, vmi->GetServiceIp(addr_),
2574 0 : dependent_ip, communities_, vmi->label(),
2575 : kInterfaceStatic);
2576 : }
2577 0 : return true;
2578 0 : }
2579 :
2580 0 : bool VmInterface::StaticRoute::DeleteL3(const Agent *agent,
2581 : VmInterface *vmi) const {
2582 0 : if (vrf_ == NULL)
2583 0 : return false;
2584 :
2585 0 : const Peer *peer = vmi->peer();
2586 0 : if (vmi->vmi_type() == VHOST) {
2587 0 : peer = agent->local_peer();
2588 : }
2589 0 : InetUnicastAgentRouteTable::Delete(peer, vrf_->GetName(),
2590 0 : addr_, plen_);
2591 0 : return true;
2592 : }
2593 :
2594 : ///////////////////////////////////////////////////////////////////////////////
2595 : //Allowed addresss pair route
2596 : ///////////////////////////////////////////////////////////////////////////////
2597 0 : void VmInterface::AllowedAddressPairList::Insert
2598 : (const AllowedAddressPair *rhs){
2599 0 : list_.insert(*rhs);
2600 0 : }
2601 :
2602 0 : void VmInterface::AllowedAddressPairList::Update
2603 : (const AllowedAddressPair *lhs, const AllowedAddressPair *rhs) {
2604 0 : lhs->set_del_pending(false);
2605 0 : if (lhs->ecmp_ != rhs->ecmp_) {
2606 0 : lhs->ecmp_ = rhs->ecmp_;
2607 0 : lhs->ecmp_config_changed_ = true;
2608 : }
2609 0 : }
2610 :
2611 0 : void VmInterface::AllowedAddressPairList::Remove
2612 : (AllowedAddressPairSet::iterator &it) {
2613 0 : it->set_del_pending(true);
2614 0 : }
2615 :
2616 0 : bool VmInterface::AllowedAddressPairList::UpdateList
2617 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
2618 : VmInterfaceState::Op l3_force_op) {
2619 0 : AllowedAddressPairSet::iterator it = list_.begin();
2620 0 : while (it != list_.end()) {
2621 0 : AllowedAddressPairSet::iterator prev = it++;
2622 0 : if (!prev->del_pending_)
2623 0 : continue;
2624 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2625 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2626 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2627 0 : list_.erase(prev);
2628 : }
2629 0 : it = list_.begin();
2630 0 : while (it != list_.end()) {
2631 0 : AllowedAddressPairSet::iterator prev = it++;
2632 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2633 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2634 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2635 : }
2636 0 : return true;
2637 : }
2638 :
2639 0 : VmInterface::AllowedAddressPair::AllowedAddressPair() :
2640 0 : ListEntry(), VmInterfaceState(), addr_(), plen_(0), ecmp_(false), mac_(),
2641 0 : ecmp_config_changed_(false),
2642 0 : service_ip_(), label_(MplsTable::kInvalidLabel), policy_enabled_nh_(NULL),
2643 0 : policy_disabled_nh_(NULL), vrf_(NULL), ethernet_tag_(0) {
2644 0 : }
2645 :
2646 0 : VmInterface::AllowedAddressPair::AllowedAddressPair(
2647 0 : const AllowedAddressPair &rhs) : ListEntry(rhs.del_pending_),
2648 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2649 0 : addr_(rhs.addr_), plen_(rhs.plen_), ecmp_(rhs.ecmp_),
2650 0 : mac_(rhs.mac_),
2651 0 : ecmp_config_changed_(rhs.ecmp_config_changed_),
2652 0 : service_ip_(rhs.service_ip_), label_(rhs.label_),
2653 0 : policy_enabled_nh_(rhs.policy_enabled_nh_),
2654 0 : policy_disabled_nh_(rhs.policy_disabled_nh_),
2655 0 : vrf_(rhs.vrf_), ethernet_tag_(rhs.ethernet_tag_) {
2656 0 : }
2657 :
2658 0 : VmInterface::AllowedAddressPair::AllowedAddressPair(const IpAddress &addr,
2659 : uint32_t plen, bool ecmp,
2660 0 : const MacAddress &mac) :
2661 0 : ListEntry(), VmInterfaceState(), addr_(addr), plen_(plen), ecmp_(ecmp),
2662 0 : mac_(mac), ecmp_config_changed_(false),
2663 0 : label_(MplsTable::kInvalidLabel), policy_enabled_nh_(NULL),
2664 0 : policy_disabled_nh_(NULL), vrf_(NULL), ethernet_tag_(0) {
2665 0 : }
2666 :
2667 0 : VmInterface::AllowedAddressPair::~AllowedAddressPair() {
2668 0 : }
2669 :
2670 0 : bool VmInterface::AllowedAddressPair::operator() (const AllowedAddressPair &lhs,
2671 : const AllowedAddressPair &rhs)
2672 : const {
2673 0 : return lhs.IsLess(&rhs);
2674 : }
2675 :
2676 0 : bool VmInterface::AllowedAddressPair::IsLess(const AllowedAddressPair *rhs)
2677 : const {
2678 0 : if (addr_ != rhs->addr_)
2679 0 : return addr_ < rhs->addr_;
2680 :
2681 0 : if (plen_ != rhs->plen_) {
2682 0 : return plen_ < rhs->plen_;
2683 : }
2684 :
2685 0 : return mac_ < rhs->mac_;
2686 : }
2687 :
2688 0 : void VmInterface::AllowedAddressPair::Copy(const Agent *agent,
2689 : const VmInterface *vmi) const {
2690 0 : vrf_ = vmi->vrf();
2691 0 : ethernet_tag_ = vmi->ethernet_tag();
2692 0 : }
2693 :
2694 0 : VmInterfaceState::Op VmInterface::AllowedAddressPair::GetOpL2
2695 : (const Agent *agent, const VmInterface *vmi) const {
2696 0 : if (vmi->bridging() == false)
2697 0 : return VmInterfaceState::DEL;
2698 :
2699 0 : if (ethernet_tag_ != vmi->ethernet_tag())
2700 0 : return VmInterfaceState::DEL_ADD;
2701 :
2702 0 : return VmInterfaceState::ADD;
2703 : }
2704 :
2705 0 : bool VmInterface::AllowedAddressPair::AddL2(const Agent *agent,
2706 : VmInterface *vmi) const {
2707 0 : if (vrf_ == NULL || mac_ == MacAddress::kZeroMac)
2708 0 : return false;
2709 :
2710 0 : IpAddress dependent_rt;
2711 0 : IpAddress route_addr;
2712 0 : if (addr_.is_v4()) {
2713 0 : if (plen_ == 32) {
2714 0 : route_addr = addr_;
2715 : } else {
2716 0 : route_addr = Ip4Address(0);
2717 : }
2718 0 : dependent_rt = Ip4Address(0);
2719 0 : } else if (addr_.is_v6()) {
2720 0 : if (plen_ == 128) {
2721 0 : route_addr = addr_;
2722 : } else {
2723 0 : route_addr = Ip6Address();
2724 : }
2725 0 : dependent_rt = Ip6Address();
2726 : }
2727 0 : vmi->AddL2InterfaceRoute(route_addr, mac_, dependent_rt);
2728 0 : return true;
2729 : }
2730 :
2731 0 : bool VmInterface::AllowedAddressPair::DeleteL2(const Agent *agent,
2732 : VmInterface *vmi) const {
2733 0 : if (vrf_ == NULL || mac_ == MacAddress::kZeroMac)
2734 0 : return false;
2735 :
2736 0 : IpAddress route_addr;
2737 0 : if (addr_.is_v4()) {
2738 0 : if (plen_ == 32) {
2739 0 : route_addr = addr_;
2740 : } else {
2741 0 : route_addr = Ip4Address(0);
2742 : }
2743 0 : } else if (addr_.is_v6()) {
2744 0 : if (plen_ == 128) {
2745 0 : route_addr = addr_;
2746 : } else {
2747 0 : route_addr = Ip6Address();
2748 : }
2749 : }
2750 0 : vmi->DeleteL2InterfaceRoute(vrf_, ethernet_tag_, route_addr, mac_);
2751 0 : return true;
2752 : }
2753 :
2754 0 : VmInterfaceState::Op VmInterface::AllowedAddressPair::GetOpL3
2755 : (const Agent *agent, const VmInterface *vmi) const {
2756 0 : if (GetIpActiveState(addr_, vmi) == false)
2757 0 : return VmInterfaceState::DEL;
2758 :
2759 0 : return VmInterfaceState::ADD;
2760 : }
2761 :
2762 0 : bool VmInterface::AllowedAddressPair::DeleteL3(const Agent *agent,
2763 : VmInterface *vmi) const {
2764 0 : if (vrf_ == NULL)
2765 0 : return false;
2766 :
2767 0 : vmi->DeleteRoute(vrf_->GetName(), addr_, plen_);
2768 0 : if (label_ != MplsTable::kInvalidLabel) {
2769 0 : label_ = MplsTable::kInvalidLabel;
2770 : }
2771 0 : policy_enabled_nh_ = NULL;
2772 0 : policy_disabled_nh_ = NULL;
2773 0 : return true;
2774 : }
2775 :
2776 0 : bool VmInterface::AllowedAddressPair::AddL3(const Agent *agent,
2777 : VmInterface *vmi) const {
2778 0 : if (vrf_ == NULL || vmi->vn_ == NULL)
2779 0 : return false;
2780 :
2781 0 : service_ip_ = vmi->GetServiceIp(addr_);
2782 0 : if (mac_ == MacAddress::kZeroMac || mac_ == vmi->vm_mac_) {
2783 0 : vmi->AddRoute(vrf_->GetName(), addr_, plen_, vmi->vn_->GetName(),
2784 0 : false, ecmp_, false, false, service_ip_, Ip4Address(0),
2785 0 : CommunityList(), vmi->label(), kInterface);
2786 0 : return true;
2787 : }
2788 :
2789 : InterfaceNH::CreateL3VmInterfaceNH
2790 0 : (vmi->GetUuid(), mac_, vmi->vrf_->GetName(), vmi->learning_enabled_,
2791 : vmi->name());
2792 :
2793 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, vmi->GetUuid(),
2794 0 : vmi->name());
2795 :
2796 : // Get policy disabled nh first
2797 0 : InterfaceNHKey key(vmi_key.Clone(), false, InterfaceNHFlags::INET4, mac_);
2798 0 : InterfaceNH *nh =static_cast<InterfaceNH *>
2799 0 : (agent->nexthop_table()->FindActiveEntry(&key));
2800 0 : policy_disabled_nh_ = nh;
2801 : // Ensure nexthop to be deleted upon refcount falling to 0
2802 0 : nh->set_delete_on_zero_refcount(true);
2803 :
2804 : // Get policy enabled nh first
2805 0 : InterfaceNHKey key1(vmi_key.Clone(), true, InterfaceNHFlags::INET4, mac_);
2806 0 : nh = static_cast<InterfaceNH *>(agent->
2807 0 : nexthop_table()->FindActiveEntry(&key1));
2808 : // Ensure nexthop to be deleted upon refcount falling to 0
2809 0 : nh->set_delete_on_zero_refcount(true);
2810 0 : policy_enabled_nh_ = nh;
2811 :
2812 : // Update AAP mpls label from nh entry
2813 0 : if (vmi->policy_enabled()) {
2814 0 : label_ = policy_enabled_nh_->mpls_label()->label();
2815 : } else {
2816 0 : label_ = policy_disabled_nh_->mpls_label()->label();
2817 : }
2818 :
2819 0 : vmi->AddRoute(vrf_->GetName(), addr_, plen_, vmi->vn_->GetName(),
2820 0 : false, ecmp_, false, false, service_ip_, Ip6Address(),
2821 0 : CommunityList(), label_, kInterface);
2822 0 : return true;
2823 0 : }
2824 :
2825 : /////////////////////////////////////////////////////////////////////////////
2826 : // ServiceVlan routines
2827 : /////////////////////////////////////////////////////////////////////////////
2828 0 : void VmInterface::ServiceVlanList::Insert(const ServiceVlan *rhs) {
2829 0 : list_.insert(*rhs);
2830 0 : }
2831 :
2832 0 : void VmInterface::ServiceVlanList::Update(const ServiceVlan *lhs,
2833 : const ServiceVlan *rhs) {
2834 0 : if (lhs->vrf_name_ != rhs->vrf_name_) {
2835 0 : lhs->vrf_name_ = rhs->vrf_name_;
2836 0 : lhs->del_add_ = true;
2837 : }
2838 :
2839 0 : if (lhs->addr_ != rhs->addr_) {
2840 0 : lhs->addr_ = rhs->addr_;
2841 0 : lhs->del_add_ = true;
2842 : }
2843 :
2844 0 : if (lhs->addr6_ != rhs->addr6_) {
2845 0 : lhs->addr6_ = rhs->addr6_;
2846 0 : lhs->del_add_ = true;
2847 : }
2848 :
2849 0 : if (lhs->smac_ != rhs->smac_) {
2850 0 : lhs->smac_ = rhs->smac_;
2851 0 : lhs->del_add_ = true;
2852 : }
2853 :
2854 0 : if (lhs->dmac_ != rhs->dmac_) {
2855 0 : lhs->dmac_ = rhs->dmac_;
2856 0 : lhs->del_add_ = true;
2857 : }
2858 :
2859 0 : lhs->set_del_pending(false);
2860 0 : }
2861 :
2862 0 : void VmInterface::ServiceVlanList::Remove(ServiceVlanSet::iterator &it) {
2863 0 : it->set_del_pending(true);
2864 0 : }
2865 :
2866 0 : bool VmInterface::ServiceVlanList::UpdateList
2867 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
2868 : VmInterfaceState::Op l3_force_op) {
2869 0 : ServiceVlanSet::iterator it = list_.begin();
2870 0 : while (it != list_.end()) {
2871 0 : ServiceVlanSet::iterator prev = it++;
2872 0 : if (prev->del_pending_ || prev->del_add_) {
2873 0 : prev->Update(agent, vmi);
2874 0 : if (prev->del_pending_) {
2875 0 : list_.erase(prev);
2876 : }
2877 : }
2878 : }
2879 :
2880 0 : it = list_.begin();
2881 0 : while (it != list_.end()) {
2882 0 : ServiceVlanSet::iterator prev = it++;
2883 0 : prev->Update(agent, vmi);
2884 : }
2885 :
2886 0 : return true;
2887 : }
2888 :
2889 : /////////////////////////////////////////////////////////////////////////////
2890 : // TagGroup routines
2891 : /////////////////////////////////////////////////////////////////////////////
2892 0 : VmInterface::TagEntry::TagEntry() :
2893 0 : ListEntry(), VmInterfaceState() , type_(0xFFFFFFFF), uuid_(nil_uuid()) {
2894 0 : }
2895 :
2896 0 : VmInterface::TagEntry::TagEntry(const TagEntry &rhs) :
2897 0 : ListEntry(rhs.del_pending_),
2898 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
2899 0 : type_(rhs.type_), uuid_(rhs.uuid_) {
2900 0 : }
2901 :
2902 0 : VmInterface::TagEntry::TagEntry(uint64_t type, const uuid &u) :
2903 0 : ListEntry(), VmInterfaceState(), type_(type), uuid_(u) {
2904 0 : }
2905 :
2906 0 : VmInterface::TagEntry::~TagEntry() {
2907 0 : }
2908 :
2909 0 : bool VmInterface::TagEntry::operator ==(const TagEntry &rhs) const {
2910 0 : return uuid_ == rhs.uuid_;
2911 : }
2912 :
2913 0 : bool VmInterface::TagEntry::operator()(const TagEntry &lhs,
2914 : const TagEntry &rhs) const {
2915 0 : return lhs.IsLess(&rhs);
2916 : }
2917 :
2918 0 : bool VmInterface::TagEntry::IsLess(const TagEntry *rhs) const {
2919 0 : if (type_ != rhs->type_) {
2920 0 : return type_ < rhs->type_;
2921 : }
2922 :
2923 : //We can only have duplicate of tag of type Label
2924 : //Rest of tags would be unique
2925 0 : if (type_ != TagTable::LABEL) {
2926 0 : return false;
2927 : }
2928 0 : return uuid_ < rhs->uuid_;
2929 : }
2930 :
2931 0 : bool VmInterface::TagEntry::AddL3(const Agent *agent,
2932 : VmInterface *intrface) const {
2933 0 : if (tag_.get() && tag_->tag_uuid() == uuid_) {
2934 0 : return false;
2935 : }
2936 :
2937 0 : TagKey tag_key(uuid_);
2938 : typedef ::TagEntry GlobalTagEntry;
2939 0 : tag_ = static_cast<GlobalTagEntry *>(agent->tag_table()->
2940 0 : FindActiveEntry(&tag_key));
2941 0 : return true;
2942 0 : }
2943 :
2944 0 : bool VmInterface::TagEntry::DeleteL3(const Agent *agent,
2945 : VmInterface *intrface) const {
2946 0 : tag_.reset();
2947 0 : return true;
2948 : }
2949 :
2950 : VmInterfaceState::Op
2951 0 : VmInterface::TagEntry::GetOpL3(const Agent *agent,
2952 : const VmInterface *vmi) const {
2953 0 : if (del_pending_)
2954 0 : return VmInterfaceState::INVALID;
2955 :
2956 0 : return VmInterfaceState::ADD;
2957 : }
2958 :
2959 0 : void VmInterface::TagEntryList::Insert(const TagEntry *rhs) {
2960 0 : list_.insert(*rhs);
2961 0 : }
2962 :
2963 0 : void VmInterface::TagEntryList::Update(const TagEntry *lhs,
2964 : const TagEntry *rhs) {
2965 0 : if (lhs->uuid_ != rhs->uuid_) {
2966 0 : lhs->uuid_ = rhs->uuid_;
2967 : }
2968 0 : }
2969 :
2970 0 : void VmInterface::TagEntryList::Remove(TagEntrySet::iterator &it) {
2971 0 : it->set_del_pending(true);
2972 0 : }
2973 :
2974 0 : bool VmInterface::TagEntryList::UpdateList(const Agent *agent,
2975 : VmInterface *vmi,
2976 : VmInterfaceState::Op l2_force_op,
2977 : VmInterfaceState::Op l3_force_op) {
2978 0 : TagEntrySet::iterator it = list_.begin();
2979 0 : while (it != list_.end()) {
2980 0 : TagEntrySet::iterator prev = it++;
2981 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
2982 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
2983 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
2984 0 : if (prev->del_pending()) {
2985 0 : list_.erase(prev);
2986 : }
2987 : }
2988 :
2989 0 : vmi->UpdatePolicySet(agent);
2990 0 : return true;
2991 : }
2992 :
2993 : /////////////////////////////////////////////////////////////////////////////
2994 : // ServiceVlan routines
2995 : /////////////////////////////////////////////////////////////////////////////
2996 0 : VmInterface::ServiceVlan::ServiceVlan() :
2997 0 : ListEntry(), tag_(0), vrf_name_(""), addr_(0), old_addr_(0),
2998 0 : addr6_(), old_addr6_(), smac_(), 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 0 : VmInterface::ServiceVlan::ServiceVlan(const ServiceVlan &rhs) :
3004 0 : ListEntry(rhs.del_pending_), tag_(rhs.tag_),
3005 0 : vrf_name_(rhs.vrf_name_), addr_(rhs.addr_), old_addr_(rhs.old_addr_),
3006 0 : addr6_(rhs.addr6_), old_addr6_(rhs.old_addr6_),
3007 0 : vrf_(rhs.vrf_, this), label_(rhs.label_),
3008 0 : v4_rt_installed_(rhs.v4_rt_installed_),
3009 0 : v6_rt_installed_(rhs.v6_rt_installed_), del_add_(false) {
3010 0 : smac_ = rhs.smac_;
3011 0 : dmac_ = rhs.dmac_;
3012 0 : }
3013 :
3014 0 : VmInterface::ServiceVlan::ServiceVlan(uint16_t tag, const std::string &vrf_name,
3015 : const Ip4Address &addr,
3016 : const Ip6Address &addr6,
3017 : const MacAddress &smac,
3018 0 : const MacAddress &dmac) :
3019 0 : ListEntry(), tag_(tag), vrf_name_(vrf_name), addr_(addr), old_addr_(addr),
3020 0 : addr6_(addr6), old_addr6_(addr6),
3021 0 : smac_(smac), dmac_(dmac), vrf_(NULL, this),
3022 0 : label_(MplsTable::kInvalidLabel) , v4_rt_installed_(false),
3023 0 : v6_rt_installed_(false), del_add_(false) {
3024 0 : }
3025 :
3026 0 : VmInterface::ServiceVlan::~ServiceVlan() {
3027 0 : }
3028 :
3029 0 : bool VmInterface::ServiceVlan::operator() (const ServiceVlan &lhs,
3030 : const ServiceVlan &rhs) const {
3031 0 : return lhs.IsLess(&rhs);
3032 : }
3033 :
3034 0 : bool VmInterface::ServiceVlan::IsLess(const ServiceVlan *rhs) const {
3035 0 : return tag_ < rhs->tag_;
3036 : }
3037 :
3038 0 : void VmInterface::ServiceVlan::Update(const Agent *agent,
3039 : VmInterface *vmi) const {
3040 0 : InterfaceTable *table = static_cast<InterfaceTable *>(vmi->get_table());
3041 0 : VrfEntry *vrf = table->FindVrfRef(vrf_name_);
3042 :
3043 0 : if (del_pending_ || vrf_ != vrf || vmi->ipv4_active() == false || del_add_) {
3044 0 : if (v4_rt_installed_) {
3045 0 : InetUnicastAgentRouteTable::Delete(vmi->peer(), vrf_->GetName(),
3046 0 : old_addr_,
3047 : Address::kMaxV4PrefixLen);
3048 0 : v4_rt_installed_ = false;
3049 : }
3050 : }
3051 :
3052 0 : if (del_pending_ || vrf_ != vrf || vmi->ipv6_active() == false || del_add_) {
3053 0 : if (v6_rt_installed_) {
3054 0 : InetUnicastAgentRouteTable::Delete(vmi->peer(), vrf_->GetName(),
3055 0 : old_addr6_,
3056 : Address::kMaxV6PrefixLen);
3057 0 : v6_rt_installed_ = false;
3058 : }
3059 : }
3060 :
3061 0 : if (del_pending_ || vrf_ != vrf || del_add_) {
3062 0 : DeleteCommon(vmi);
3063 : }
3064 :
3065 0 : vrf_ = vrf;
3066 0 : old_addr_ = addr_;
3067 0 : old_addr6_ = addr6_;
3068 0 : bool old_del_add = del_add_;
3069 0 : del_add_ = false;
3070 :
3071 0 : if (del_pending_ || vrf_ == NULL || old_del_add)
3072 0 : return;
3073 :
3074 0 : if (vmi->ipv4_active() == false && vmi->ipv6_active() == false)
3075 0 : return;
3076 :
3077 0 : if (label_ == MplsTable::kInvalidLabel) {
3078 0 : AddCommon(agent, vmi);
3079 : }
3080 :
3081 0 : SecurityGroupList sg_id_list;
3082 0 : vmi->CopySgIdList(&sg_id_list);
3083 :
3084 0 : TagList tag_id_list;
3085 0 : vmi->CopyTagIdList(&tag_id_list);
3086 :
3087 0 : VnListType vn_list;
3088 0 : vn_list.insert(vmi->vn()->GetName());
3089 :
3090 : // Add both ipv4 *and* ipv6 service vlan route if one of v4 or v6 is active
3091 : // TODO : Shouldnt route be added only if corresponding state is active?
3092 0 : if (addr_.is_unspecified() == false) {
3093 0 : PathPreference pref;
3094 0 : vmi->SetServiceVlanPathPreference(&pref, addr_);
3095 :
3096 : InetUnicastAgentRouteTable::AddVlanNHRoute
3097 0 : (vmi->peer(), vrf_->GetName(), addr_, Address::kMaxV4PrefixLen,
3098 0 : vmi->GetUuid(), tag_, label_, vn_list, sg_id_list,
3099 : tag_id_list, pref);
3100 0 : v4_rt_installed_ = true;
3101 0 : }
3102 :
3103 0 : if (addr6_.is_unspecified() == false) {
3104 0 : PathPreference pref;
3105 0 : vmi->SetServiceVlanPathPreference(&pref, addr6_);
3106 :
3107 : InetUnicastAgentRouteTable::AddVlanNHRoute
3108 0 : (vmi->peer(), vrf_->GetName(), addr6_, Address::kMaxV6PrefixLen,
3109 0 : vmi->GetUuid(), tag_, label_, vn_list, sg_id_list,
3110 : tag_id_list, pref);
3111 0 : v6_rt_installed_ = true;
3112 0 : }
3113 :
3114 0 : return;
3115 0 : }
3116 :
3117 0 : void VmInterface::ServiceVlan::DeleteCommon(const VmInterface *vmi) const {
3118 0 : if (label_ == MplsTable::kInvalidLabel)
3119 0 : return;
3120 :
3121 : // Delete the L2 Recive routes added for smac_ and dmac_
3122 : BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
3123 0 : (vrf_->GetBridgeRouteTable());
3124 0 : if (table) {
3125 0 : table->Delete(vmi->peer(), vrf_->GetName(), dmac_, 0);
3126 0 : table->Delete(vmi->peer(), vrf_->GetName(), smac_, 0);
3127 : }
3128 :
3129 0 : VrfAssignTable::DeleteVlan(vmi->GetUuid(), tag_);
3130 0 : VlanNH::Delete(vmi->GetUuid(), tag_);
3131 0 : label_ = MplsTable::kInvalidLabel;
3132 : }
3133 :
3134 0 : void VmInterface::ServiceVlan::AddCommon(const Agent *agent,
3135 : const VmInterface *vmi) const {
3136 0 : if (label_ != MplsTable::kInvalidLabel)
3137 0 : return;
3138 :
3139 0 : assert(vrf_);
3140 0 : VlanNH::Create(vmi->GetUuid(), tag_, vrf_name_, smac_, dmac_);
3141 0 : VrfAssignTable::CreateVlan(vmi->GetUuid(), vrf_name_, tag_);
3142 : // Assign label_ from vlan NH db entry
3143 0 : VlanNHKey key(vmi->GetUuid(), tag_);
3144 0 : const NextHop *nh = static_cast<const NextHop *>
3145 0 : (agent->nexthop_table()->FindActiveEntry(&key));
3146 0 : label_ = nh->mpls_label()->label();
3147 :
3148 : // With IRB model, add L2 Receive route for SMAC and DMAC to ensure
3149 : // packets from service vm go thru routing
3150 : BridgeAgentRouteTable *table = static_cast<BridgeAgentRouteTable *>
3151 0 : (vrf_->GetBridgeRouteTable());
3152 0 : table->AddBridgeReceiveRoute(vmi->peer(), vrf_->GetName(), 0, dmac_,
3153 : vmi->vn()->GetName());
3154 0 : table->AddBridgeReceiveRoute(vmi->peer(), vrf_->GetName(), 0, smac_,
3155 : vmi->vn()->GetName());
3156 0 : }
3157 :
3158 : ////////////////////////////////////////////////////////////////////////////
3159 : // VRF assign rule routines
3160 : ////////////////////////////////////////////////////////////////////////////
3161 0 : VmInterface::VrfAssignRule::VrfAssignRule():
3162 0 : ListEntry(), id_(0), vrf_name_(" "), ignore_acl_(false) {
3163 0 : }
3164 :
3165 0 : VmInterface::VrfAssignRule::VrfAssignRule(const VrfAssignRule &rhs):
3166 0 : ListEntry(rhs.del_pending_), id_(rhs.id_),
3167 0 : vrf_name_(rhs.vrf_name_), ignore_acl_(rhs.ignore_acl_),
3168 0 : match_condition_(rhs.match_condition_) {
3169 0 : }
3170 :
3171 0 : VmInterface::VrfAssignRule::VrfAssignRule
3172 : (uint32_t id, const autogen::MatchConditionType &match_condition,
3173 0 : const std::string &vrf_name, bool ignore_acl):
3174 0 : ListEntry(), id_(id), vrf_name_(vrf_name), ignore_acl_(ignore_acl),
3175 0 : match_condition_(match_condition) {
3176 0 : }
3177 :
3178 0 : VmInterface::VrfAssignRule::~VrfAssignRule() {
3179 0 : }
3180 :
3181 0 : bool VmInterface::VrfAssignRule::operator()(const VrfAssignRule &lhs,
3182 : const VrfAssignRule &rhs) const {
3183 0 : return lhs.IsLess(&rhs);
3184 : }
3185 :
3186 0 : bool VmInterface::VrfAssignRule::IsLess(const VrfAssignRule *rhs) const {
3187 0 : return id_ < rhs->id_;
3188 : }
3189 :
3190 0 : void VmInterface::VrfAssignRuleList::Insert(const VrfAssignRule *rhs) {
3191 0 : list_.insert(*rhs);
3192 0 : }
3193 :
3194 0 : void VmInterface::VrfAssignRuleList::Update(const VrfAssignRule *lhs,
3195 : const VrfAssignRule *rhs) {
3196 0 : lhs->set_del_pending(false);
3197 0 : lhs->match_condition_ = rhs->match_condition_;
3198 0 : lhs->ignore_acl_ = rhs->ignore_acl_;
3199 0 : lhs->vrf_name_ = rhs->vrf_name_;
3200 0 : }
3201 :
3202 0 : void VmInterface::VrfAssignRuleList::Remove(VrfAssignRuleSet::iterator &it) {
3203 0 : it->set_del_pending(true);
3204 0 : }
3205 :
3206 0 : bool VmInterface::VrfAssignRuleList::UpdateList
3207 : (const Agent *agent, VmInterface *vmi, VmInterfaceState::Op l2_force_op,
3208 : VmInterfaceState::Op l3_force_op) {
3209 : // Erase all delete marked entry
3210 0 : VrfAssignRuleSet::iterator it = list_.begin();
3211 0 : while (it != list_.end()) {
3212 0 : VrfAssignRuleSet::iterator prev = it++;
3213 0 : if (prev->del_pending_) {
3214 0 : list_.erase(prev);
3215 : }
3216 : }
3217 :
3218 : // Delete vrf_assign_acl_ if there are no more ACE entries
3219 0 : if (list_.size() == 0 || vmi->IsActive() == false) {
3220 0 : if (vrf_assign_acl_.get() != NULL) {
3221 0 : vrf_assign_acl_ = NULL;
3222 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
3223 0 : req.key.reset(new AclKey(vmi->GetUuid()));
3224 0 : req.data.reset(NULL);
3225 0 : agent->acl_table()->Process(req);
3226 0 : }
3227 0 : return true;
3228 : }
3229 :
3230 : // One or more ace-entries present, create corresponding ACL
3231 0 : AclSpec acl_spec;
3232 0 : acl_spec.acl_id = vmi->GetUuid();
3233 0 : uint32_t id = 0;
3234 0 : for (it = list_.begin(); it != list_.end(); it++) {
3235 0 : AclEntrySpec ace_spec;
3236 0 : ace_spec.id = id++;
3237 :
3238 0 : if (ace_spec.Populate(&(it->match_condition_)) == false) {
3239 0 : continue;
3240 : }
3241 :
3242 : // Add both v4 and v6 rules regardless of whether interface is
3243 : //ipv4_active_/ipv6_active_
3244 0 : ActionSpec vrf_translate_spec;
3245 0 : vrf_translate_spec.ta_type = TrafficAction::VRF_TRANSLATE_ACTION;
3246 0 : vrf_translate_spec.simple_action = TrafficAction::VRF_TRANSLATE;
3247 0 : vrf_translate_spec.vrf_translate.set_vrf_name(it->vrf_name_);
3248 0 : vrf_translate_spec.vrf_translate.set_ignore_acl(it->ignore_acl_);
3249 0 : ace_spec.action_l.push_back(vrf_translate_spec);
3250 0 : acl_spec.acl_entry_specs_.push_back(ace_spec);
3251 0 : }
3252 :
3253 : // ACL entries populated, add the DBEntry
3254 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
3255 0 : req.key.reset(new AclKey(acl_spec.acl_id));
3256 0 : Agent *agent1 = static_cast<InterfaceTable *>(vmi->get_table())->agent();
3257 0 : req.data.reset(new AclData(agent1, NULL, acl_spec));
3258 0 : agent->acl_table()->Process(req);
3259 :
3260 : // Query the ACL entry and store it
3261 0 : AclKey entry_key(vmi->GetUuid());
3262 : vrf_assign_acl_ = static_cast<AclDBEntry *>
3263 0 : (agent->acl_table()->FindActiveEntry(&entry_key));
3264 0 : assert(vrf_assign_acl_);
3265 0 : return true;
3266 0 : }
3267 :
3268 : /////////////////////////////////////////////////////////////////////////////
3269 : // RecevieRoute routines
3270 : /////////////////////////////////////////////////////////////////////////////
3271 0 : void VmInterface::VmiReceiveRouteList::Insert(const VmiReceiveRoute *rhs) {
3272 0 : list_.insert(*rhs);
3273 0 : }
3274 :
3275 0 : void VmInterface::VmiReceiveRouteList::Update(const VmiReceiveRoute *lhs,
3276 : const VmiReceiveRoute *rhs) {
3277 0 : lhs->set_del_pending(false);
3278 0 : }
3279 :
3280 0 : void VmInterface::VmiReceiveRouteList::Remove(VmiReceiveRouteSet::iterator &it) {
3281 0 : it->set_del_pending(true);
3282 0 : }
3283 :
3284 0 : bool VmInterface::VmiReceiveRouteList::UpdateList(const Agent *agent,
3285 : VmInterface *vmi,
3286 : VmInterfaceState::Op l2_force_op,
3287 : VmInterfaceState::Op l3_force_op) {
3288 0 : VmiReceiveRouteSet::iterator it = list_.begin();
3289 0 : while (it != list_.end()) {
3290 0 : VmiReceiveRouteSet::iterator prev = it++;
3291 0 : VmInterfaceState::Op l2_op = prev->GetOp(l2_force_op);
3292 0 : VmInterfaceState::Op l3_op = prev->GetOp(l3_force_op);
3293 0 : vmi->UpdateState(&(*prev), l2_op, l3_op);
3294 0 : if (prev->del_pending_) {
3295 0 : list_.erase(prev);
3296 : }
3297 : }
3298 0 : return true;
3299 : }
3300 :
3301 0 : VmInterface::VmiReceiveRoute::VmiReceiveRoute() :
3302 0 : ListEntry(), VmInterfaceState(), addr_(), plen_(0), add_l2_(false) {
3303 0 : }
3304 :
3305 0 : VmInterface::VmiReceiveRoute::VmiReceiveRoute(const VmiReceiveRoute &rhs) :
3306 0 : ListEntry(rhs.del_pending_),
3307 0 : VmInterfaceState(rhs.l2_installed_, rhs.l3_installed_),
3308 0 : addr_(rhs.addr_), plen_(rhs.plen_), add_l2_(rhs.add_l2_) {
3309 0 : }
3310 :
3311 0 : VmInterface::VmiReceiveRoute::VmiReceiveRoute(const IpAddress &addr,
3312 : uint32_t plen,
3313 0 : bool add_l2):
3314 0 : ListEntry(), VmInterfaceState(), addr_(addr), plen_(plen), add_l2_(add_l2) {
3315 0 : }
3316 :
3317 0 : bool VmInterface::VmiReceiveRoute::operator() (const VmiReceiveRoute &lhs,
3318 : const VmiReceiveRoute &rhs)
3319 : const {
3320 0 : return lhs.IsLess(&rhs);
3321 : }
3322 :
3323 0 : bool VmInterface::VmiReceiveRoute::IsLess(const VmiReceiveRoute *rhs) const {
3324 0 : if (addr_ != rhs->addr_) {
3325 0 : return addr_ < rhs->addr_;
3326 : }
3327 :
3328 0 : if (plen_ != rhs->plen_) {
3329 0 : return plen_ < rhs->plen_;
3330 : }
3331 :
3332 0 : return add_l2_ < rhs->add_l2_;
3333 : }
3334 :
3335 0 : void VmInterface::VmiReceiveRoute::Copy(const Agent *agent,
3336 : const VmInterface *vmi) const {
3337 0 : vrf_ = vmi->forwarding_vrf();
3338 0 : }
3339 :
3340 : VmInterfaceState::Op
3341 0 : VmInterface::VmiReceiveRoute::GetOpL3(const Agent *agent,
3342 : const VmInterface *vmi) const {
3343 0 : if (GetIpActiveState(addr_, vmi) == false)
3344 0 : return VmInterfaceState::DEL;
3345 :
3346 0 : if (vrf_ != vmi->forwarding_vrf())
3347 0 : return VmInterfaceState::DEL_ADD;
3348 :
3349 0 : return VmInterfaceState::ADD;
3350 : }
3351 :
3352 : VmInterfaceState::Op
3353 0 : VmInterface::VmiReceiveRoute::GetOpL2(const Agent *agent,
3354 : const VmInterface *vmi) const {
3355 0 : if (add_l2_ == false) {
3356 0 : return VmInterfaceState::INVALID;
3357 : }
3358 :
3359 0 : if (vrf_ != vmi->forwarding_vrf())
3360 0 : return VmInterfaceState::DEL_ADD;
3361 :
3362 0 : return VmInterfaceState::ADD;
3363 : }
3364 :
3365 0 : bool VmInterface::VmiReceiveRoute::AddL3(const Agent *agent,
3366 : VmInterface *vmi) const {
3367 0 : if (vrf_ == NULL) {
3368 0 : return false;
3369 : }
3370 :
3371 0 : ReceiveNH::Create(agent->nexthop_table(), vmi, vmi->policy_enabled());
3372 0 : ReceiveNH::Create(agent->nexthop_table(), vmi, false);
3373 0 : InetUnicastAgentRouteTable *table = vrf_->GetInet4UnicastRouteTable();
3374 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, vmi->GetUuid(),
3375 0 : vmi->name());
3376 0 : if (addr_.is_v6()) {
3377 0 : table = vrf_->GetInet6UnicastRouteTable();
3378 : }
3379 :
3380 0 : table->AddVHostRecvRoute(agent->local_peer(), vrf_->GetName(), vmi_key,
3381 0 : addr_, plen_, agent->fabric_vn_name(),
3382 0 : vmi->policy_enabled(), true);
3383 0 : return true;
3384 0 : }
3385 :
3386 0 : bool VmInterface::VmiReceiveRoute::DeleteL3(const Agent *agent,
3387 : VmInterface *vmi) const {
3388 0 : if (vrf_ == NULL)
3389 0 : return false;
3390 :
3391 0 : InetUnicastAgentRouteTable::Delete(agent->local_peer(), vrf_->GetName(),
3392 0 : addr_, plen_);
3393 0 : return true;
3394 : }
3395 :
3396 0 : bool VmInterface::VmiReceiveRoute::AddL2(const Agent *agent,
3397 : VmInterface *vmi) const {
3398 0 : if (vrf_ == NULL) {
3399 0 : return false;
3400 : }
3401 :
3402 : BridgeAgentRouteTable *table =
3403 0 : static_cast<BridgeAgentRouteTable *>(vrf_->GetRouteTable(Agent::BRIDGE));
3404 0 : table->AddBridgeReceiveRoute(agent->local_peer(), vrf_->GetName(), 0,
3405 : vmi->GetVifMac(agent), agent->fabric_vn_name());
3406 0 : return true;
3407 : }
3408 :
3409 0 : bool VmInterface::VmiReceiveRoute::DeleteL2(const Agent *agent,
3410 : VmInterface *vmi) const {
3411 0 : if (vrf_ == NULL)
3412 0 : return false;
3413 :
3414 0 : BridgeAgentRouteTable::Delete(agent->local_peer(), vrf_->GetName(),
3415 : vmi->GetVifMac(agent), 0);
3416 0 : return true;
3417 : }
3418 : //Build ACL list to be applied on VMI
3419 : //ACL list build on two criteria
3420 : //1> global-application-policy set.
3421 : //2> application-policy-set attached via application tag
3422 0 : bool VmInterface::UpdatePolicySet(const Agent *agent) {
3423 0 : bool ret = false;
3424 0 : FirewallPolicyList new_firewall_policy_list;
3425 0 : FirewallPolicyList new_fwaas_firewall_policy_list;
3426 :
3427 0 : PolicySet *gps = agent->policy_set_table()->global_policy_set();
3428 0 : if (gps) {
3429 0 : new_firewall_policy_list = gps->fw_policy_list();
3430 : }
3431 :
3432 0 : contains_new_tags_ = false;
3433 0 : TagEntrySet::const_iterator it = tag_list_.list_.begin();
3434 0 : for(; it != tag_list_.list_.end(); it++) {
3435 0 : if (it->tag_ == NULL) {
3436 0 : continue;
3437 : }
3438 0 : contains_new_tags_ |= it->tag_->is_new_tag();
3439 :
3440 : ::TagEntry::PolicySetList::const_iterator ps_it =
3441 0 : it->tag_->policy_set_list().begin();
3442 0 : for(; ps_it != it->tag_->policy_set_list().end(); ps_it++) {
3443 0 : FirewallPolicyList &tag_fp_list = ps_it->get()->fw_policy_list();
3444 0 : FirewallPolicyList::iterator fw_policy_it = tag_fp_list.begin();
3445 0 : for (; fw_policy_it != tag_fp_list.end(); fw_policy_it++) {
3446 0 : if (it->tag_->IsNeutronFwaasTag())
3447 0 : new_fwaas_firewall_policy_list.push_back(*fw_policy_it);
3448 : else
3449 0 : new_firewall_policy_list.push_back(*fw_policy_it);
3450 : }
3451 : }
3452 : }
3453 :
3454 0 : if (fw_policy_list_ != new_firewall_policy_list) {
3455 0 : fw_policy_list_ = new_firewall_policy_list;
3456 0 : ret = true;
3457 : }
3458 :
3459 0 : if (fwaas_fw_policy_list_ != new_fwaas_firewall_policy_list) {
3460 0 : fwaas_fw_policy_list_ = new_fwaas_firewall_policy_list;
3461 0 : ret = true;
3462 : }
3463 :
3464 0 : return ret;
3465 0 : }
3466 :
3467 0 : void VmInterface::CopyTagIdList(TagList *tag_id_list) const {
3468 0 : TagEntrySet::const_iterator it;
3469 0 : for (it = tag_list_.list_.begin(); it != tag_list_.list_.end(); ++it) {
3470 0 : if (it->del_pending_)
3471 0 : continue;
3472 0 : if (it->tag_.get() == NULL)
3473 0 : continue;
3474 0 : tag_id_list->push_back(it->tag_->tag_id());
3475 : }
3476 0 : std::sort(tag_id_list->begin(), tag_id_list->end());
3477 0 : }
3478 :
3479 0 : void VmInterface::update_flow_count(int val) const {
3480 0 : int max_flows = FLOWS_LIMIT_UNLIMITED;
3481 0 : int new_flow_count = flow_count_.fetch_add(val);
3482 :
3483 : {
3484 0 : int maxv = std::max(max_flows_, agent()->global_max_vmi_flows());
3485 0 : int minv = std::min(max_flows_, agent()->global_max_vmi_flows());
3486 0 : max_flows = minv * (max_flows_ != FLOWS_LIMIT_UNLIMITED &&
3487 0 : agent()->global_max_vmi_flows() != FLOWS_LIMIT_UNLIMITED) +
3488 0 : maxv * ((max_flows_ != FLOWS_LIMIT_UNLIMITED) !=
3489 0 : (agent()->global_max_vmi_flows() != FLOWS_LIMIT_UNLIMITED));
3490 : }
3491 :
3492 0 : if (max_flows == FLOWS_LIMIT_UNLIMITED) {
3493 : // max_flows are not configured,
3494 : // disable drop new flows and return
3495 0 : SetInterfacesDropNewFlows(false);
3496 0 : return;
3497 : }
3498 :
3499 0 : if (val < 0) {
3500 0 : assert(new_flow_count >= val);
3501 0 : if ((new_flow_count + val) <
3502 0 : ((max_flows * (Agent::kDropNewFlowsRecoveryThreshold))/100)) {
3503 0 : SetInterfacesDropNewFlows(false);
3504 : }
3505 : } else {
3506 0 : if ((new_flow_count + val) >= max_flows) {
3507 0 : SetInterfacesDropNewFlows(true);
3508 : }
3509 : }
3510 : }
3511 :
3512 0 : void VmInterface::SetInterfacesDropNewFlows(bool drop_new_flows) const {
3513 0 : if (drop_new_flows_vmi_ == drop_new_flows) {
3514 0 : return;
3515 : }
3516 0 : drop_new_flows_vmi_ = drop_new_flows;
3517 0 : DBRequest req;
3518 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
3519 0 : req.key.reset(new VmInterfaceKey(AgentKey::RESYNC,
3520 0 : GetUuid(), ""));
3521 0 : req.data.reset(new VmInterfaceNewFlowDropData(drop_new_flows));
3522 0 : agent()->interface_table()->Enqueue(&req);
3523 0 : }
|