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