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/bgp_as_service.h>
26 : #include <oper/tag.h>
27 :
28 : #include <filter/acl.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 :
39 : /////////////////////////////////////////////////////////////////////////////
40 : // VM Port Key routines
41 : /////////////////////////////////////////////////////////////////////////////
42 46211 : VmInterfaceKey::VmInterfaceKey(AgentKey::DBSubOperation sub_op,
43 46211 : const boost::uuids::uuid &uuid, const std::string &name) :
44 46211 : InterfaceKey(sub_op, Interface::VM_INTERFACE, uuid, name, false) {
45 46211 : }
46 :
47 1089 : Interface *VmInterfaceKey::AllocEntry(const InterfaceTable *table) const {
48 1089 : Agent *agent = table->agent();
49 : /* OS oper state is disabled by default in Vmware mode */
50 1089 : bool os_oper_state = !agent->isVmwareMode();
51 1089 : return new VmInterface(uuid_, name_, os_oper_state, nil_uuid());
52 : }
53 :
54 17 : Interface *VmInterfaceKey::AllocEntry(const InterfaceTable *table,
55 : const InterfaceData *data) const {
56 17 : const VmInterfaceData *vm_data =
57 : static_cast<const VmInterfaceData *>(data);
58 :
59 17 : VmInterface *vmi = vm_data->OnAdd(table, this);
60 17 : return vmi;
61 : }
62 :
63 353 : InterfaceKey *VmInterfaceKey::Clone() const {
64 353 : return new VmInterfaceKey(*this);
65 : }
66 :
67 : /////////////////////////////////////////////////////////////////////////////
68 : // VmInterfaceConfigData routines
69 : /////////////////////////////////////////////////////////////////////////////
70 98 : VmInterfaceConfigData::VmInterfaceConfigData(Agent *agent, IFMapNode *node) :
71 : VmInterfaceData(agent, node, CONFIG, Interface::TRANSPORT_INVALID),
72 98 : addr_(0), ip6_addr_(), vm_mac_(""),
73 98 : cfg_name_(""), vm_uuid_(), vm_name_(), vn_uuid_(), vrf_name_(""),
74 98 : fabric_port_(true), need_linklocal_ip_(false), bridging_(true),
75 98 : layer3_forwarding_(true), mirror_enable_(false), ecmp_(false),
76 98 : ecmp6_(false), dhcp_enable_(true), dhcp_enable_v6_(false),
77 98 : proxy_arp_mode_(VmInterface::PROXY_ARP_NONE), admin_state_(true),
78 98 : disable_policy_(false), analyzer_name_(""),
79 98 : local_preference_(0), oper_dhcp_options_(),
80 98 : mirror_direction_(Interface::UNKNOWN),
81 98 : cfg_igmp_enable_(false), igmp_enabled_(false),
82 98 : mac_ip_learning_enable_(false), max_flows_(0), sg_list_(),
83 98 : floating_ip_list_(), alias_ip_list_(), service_vlan_list_(),
84 196 : static_route_list_(), allowed_address_pair_list_(),
85 98 : instance_ipv4_list_(true), instance_ipv6_list_(false),
86 98 : bridge_domain_list_(),
87 98 : device_type_(VmInterface::DEVICE_TYPE_INVALID),
88 98 : vmi_type_(VmInterface::VMI_TYPE_INVALID), hbs_intf_type_(VmInterface::HBS_INTF_INVALID),
89 98 : physical_interface_(""), parent_vmi_(), subnet_(0), subnet_plen_(0),
90 98 : rx_vlan_id_(VmInterface::kInvalidVlanId),
91 98 : tx_vlan_id_(VmInterface::kInvalidVlanId),
92 98 : logical_interface_(nil_uuid()), ecmp_load_balance_(),
93 98 : service_health_check_ip_(), service_ip_(0),
94 98 : service_ip_ecmp_(false), service_ip6_(), service_ip_ecmp6_(false),
95 98 : qos_config_uuid_(), learning_enabled_(false),
96 98 : vhostuser_mode_(VmInterface::vHostUserClient), is_left_si_(false), service_mode_(VmInterface::SERVICE_MODE_ERROR),
97 98 : si_other_end_vmi_(nil_uuid()), vmi_cfg_uuid_(nil_uuid()),
98 686 : service_intf_type_(""), physical_interface_list_() {
99 98 : }
100 :
101 5 : VmInterface *VmInterfaceConfigData::OnAdd(const InterfaceTable *table,
102 : const VmInterfaceKey *key) const {
103 :
104 5 : Interface *parent = NULL;
105 5 : if (device_type_ == VmInterface::REMOTE_VM_VLAN_ON_VMI) {
106 0 : if (rx_vlan_id_ == VmInterface::kInvalidVlanId ||
107 0 : tx_vlan_id_ == VmInterface::kInvalidVlanId)
108 0 : return NULL;
109 :
110 0 : if (physical_interface_ != Agent::NullString()) {
111 0 : PhysicalInterfaceKey key_1(physical_interface_);
112 0 : parent = static_cast<Interface *>
113 0 : (table->agent()->interface_table()->FindActiveEntry(&key_1));
114 0 : }
115 :
116 0 : if (parent == NULL)
117 0 : return NULL;
118 : }
119 :
120 5 : boost::system::error_code ec;
121 5 : MacAddress mac = MacAddress::FromString(vm_mac_, &ec);
122 5 : if (ec.value() != 0) {
123 2 : mac.Zero();
124 : }
125 :
126 5 : Agent *agent = table->agent();
127 : /* OS oper state is disabled by default in Vmware mode */
128 5 : bool os_oper_state = !agent->isVmwareMode();
129 : VmInterface *vmi =
130 5 : new VmInterface(key->uuid_, key->name_, addr_, mac, vm_name_,
131 5 : nil_uuid(), tx_vlan_id_, rx_vlan_id_, parent,
132 5 : ip6_addr_, device_type_, vmi_type_, vhostuser_mode_,
133 5 : os_oper_state, logical_router_uuid_);
134 5 : vmi->SetConfigurer(VmInterface::CONFIG);
135 5 : vmi->set_hbs_intf_type(hbs_intf_type_);
136 5 : return vmi;
137 : }
138 :
139 5 : bool VmInterfaceConfigData::OnDelete(const InterfaceTable *table,
140 : VmInterface *vmi) const {
141 5 : if (vmi->IsConfigurerSet(VmInterface::CONFIG) == false)
142 0 : return true;
143 :
144 5 : VmInterfaceConfigData data(NULL, NULL);
145 5 : vmi->Resync(table, &data);
146 5 : vmi->ResetConfigurer(VmInterface::CONFIG);
147 5 : return true;
148 5 : }
149 :
150 60 : bool VmInterfaceConfigData::OnResync(const InterfaceTable *table,
151 : VmInterface *vmi,
152 : bool *force_update) const {
153 60 : bool sg_changed = false;
154 60 : bool ecmp_changed = false;
155 60 : bool local_pref_changed = false;
156 60 : bool ecmp_load_balance_changed = false;
157 60 : bool static_route_config_changed = false;
158 60 : bool etree_leaf_mode_changed = false;
159 60 : bool tag_changed = false;
160 60 : bool ret = false;
161 :
162 60 : ret = vmi->CopyConfig(table, this, &sg_changed, &ecmp_changed,
163 : &local_pref_changed, &ecmp_load_balance_changed,
164 : &static_route_config_changed,
165 : &etree_leaf_mode_changed, &tag_changed);
166 60 : if (sg_changed || ecmp_changed || local_pref_changed ||
167 22 : ecmp_load_balance_changed || static_route_config_changed
168 19 : || etree_leaf_mode_changed || tag_changed )
169 41 : *force_update = true;
170 :
171 60 : vmi->SetConfigurer(VmInterface::CONFIG);
172 60 : return ret;
173 : }
174 :
175 70 : autogen::VirtualMachineInterface *VmInterfaceConfigData::GetVmiCfg() const {
176 70 : IFMapNode *node = ifmap_node();
177 70 : if (node != NULL) {
178 70 : if (node->GetObject() != NULL) {
179 : return static_cast <autogen::VirtualMachineInterface *>
180 70 : (node->GetObject());
181 : }
182 : }
183 0 : return NULL;
184 : }
185 :
186 : //Configuration of vhost interface to be filled from
187 : //config file. This include
188 : //1> IP of vhost
189 : //2> Default route to be populated if any
190 : //3> Resolve route to be added
191 : //4> Multicast receive route
192 6 : void VmInterfaceConfigData::CopyVhostData(const Agent *agent) {
193 6 : transport_ = static_cast<Interface::Transport>
194 6 : (agent->GetInterfaceTransport());
195 :
196 6 : proxy_arp_mode_ = VmInterface::PROXY_ARP_NONE;
197 6 : device_type_ = VmInterface::LOCAL_DEVICE;
198 6 : vmi_type_ = VmInterface::VHOST;
199 :
200 6 : vrf_name_ = agent->fabric_policy_vrf_name();
201 6 : if (agent->router_id() != Ip4Address(0) && agent->is_l3mh() == false) {
202 6 : addr_ = agent->router_id();
203 6 : instance_ipv4_list_.list_.insert(
204 12 : VmInterface::InstanceIp(agent->router_id(), 32, false, true,
205 12 : false, false, false, Ip4Address(0)));
206 : }
207 :
208 6 : boost::system::error_code ec;
209 : IpAddress mc_addr =
210 6 : Ip4Address::from_string(IPV4_MULTICAST_BASE_ADDRESS, ec);
211 6 : receive_route_list_.list_.insert(
212 12 : VmInterface::VmiReceiveRoute(mc_addr, MULTICAST_BASE_ADDRESS_PLEN,
213 : false));
214 :
215 6 : mc_addr = Ip6Address::from_string(IPV6_MULTICAST_BASE_ADDRESS, ec);
216 6 : receive_route_list_.list_.insert(
217 12 : VmInterface::VmiReceiveRoute(mc_addr, MULTICAST_BASE_ADDRESS_PLEN,
218 : false));
219 :
220 6 : if (agent->params()->subnet_hosts_resolvable() == true) {
221 : //Add resolve route
222 6 : subnet_ = agent->router_id();
223 6 : subnet_plen_ = agent->vhost_prefix_len();
224 : }
225 :
226 6 : physical_interface_list_ = agent->fabric_interface_name_list();
227 :
228 6 : PhysicalInterfaceKey physical_key(agent->fabric_interface_name());
229 : const Interface *pif =
230 12 : static_cast<const Interface *>(agent->interface_table()->
231 6 : FindActiveEntry(&physical_key));
232 6 : vm_mac_ = pif->mac().ToString();
233 6 : if (agent->is_l3mh()) {
234 0 : vm_mac_ = agent->vrrp_mac().ToString();
235 : }
236 :
237 : //Add default route pointing to gateway
238 6 : static_route_list_.list_.insert(
239 12 : VmInterface::StaticRoute(Ip4Address(0), 0,
240 6 : agent->params()->gateway_list(),
241 12 : CommunityList()));
242 6 : }
243 :
244 :
245 60 : bool VmInterface::CopyIp6Address(const Ip6Address &addr) {
246 60 : bool ret = false;
247 :
248 : // Retain the old if new IP could not be got
249 60 : if (addr.is_unspecified()) {
250 10 : return false;
251 : }
252 :
253 50 : if (primary_ip6_addr_ != addr) {
254 0 : primary_ip6_addr_ = addr;
255 0 : ret = true;
256 : }
257 :
258 50 : return ret;
259 : }
260 :
261 : // Copies configuration from DB-Request data. The actual applying of
262 : // configuration, like adding/deleting routes must be done with ApplyConfig()
263 60 : bool VmInterface::CopyConfig(const InterfaceTable *table,
264 : const VmInterfaceConfigData *data,
265 : bool *sg_changed,
266 : bool *ecmp_changed,
267 : bool *local_pref_changed,
268 : bool *ecmp_load_balance_changed,
269 : bool *static_route_config_changed,
270 : bool *etree_leaf_mode_changed,
271 : bool *tag_changed) {
272 60 : bool ret = false;
273 60 : if (table) {
274 60 : VmEntry *vm = table->FindVmRef(data->vm_uuid_);
275 60 : if (vm_.get() != vm) {
276 28 : vm_ = vm;
277 28 : ret = true;
278 : }
279 :
280 : bool drop_new_flows =
281 60 : (vm_.get() != NULL) ? vm_->drop_new_flows() : false;
282 60 : if (drop_new_flows_ != drop_new_flows) {
283 0 : drop_new_flows_ = drop_new_flows;
284 0 : ret = true;
285 : }
286 :
287 60 : VrfEntry *vrf = table->FindVrfRef(data->vrf_name_);
288 60 : if (vrf_.get() != vrf) {
289 34 : vrf_ = vrf;
290 34 : ret = true;
291 : }
292 :
293 60 : VrfEntry *forwarding_vrf = vrf;
294 60 : if (vrf && vrf_->forwarding_vrf()) {
295 3 : forwarding_vrf = vrf_->forwarding_vrf();
296 : }
297 :
298 60 : if (forwarding_vrf != forwarding_vrf_) {
299 34 : forwarding_vrf_ = forwarding_vrf;
300 34 : ret = true;
301 : }
302 :
303 60 : MirrorEntry *mirror = table->FindMirrorRef(data->analyzer_name_);
304 60 : if (mirror_entry_.get() != mirror) {
305 0 : mirror_entry_ = mirror;
306 0 : ret = true;
307 : }
308 : }
309 :
310 60 : if (vmi_type_ != data->vmi_type_) {
311 17 : *etree_leaf_mode_changed = true;
312 17 : vmi_type_ = data->vmi_type_;
313 17 : ret = true;
314 : }
315 :
316 60 : if (vmi_cfg_uuid_ != data->vmi_cfg_uuid_) {
317 28 : vmi_cfg_uuid_ = data->vmi_cfg_uuid_;
318 28 : ret = true;
319 : }
320 :
321 60 : if (vhostuser_mode_ != data->vhostuser_mode_) {
322 0 : vhostuser_mode_ = data->vhostuser_mode_;
323 0 : ret = true;
324 : }
325 :
326 60 : MirrorDirection mirror_direction = data->mirror_direction_;
327 60 : if (mirror_direction_ != mirror_direction) {
328 17 : mirror_direction_ = mirror_direction;
329 17 : ret = true;
330 : }
331 :
332 60 : string cfg_name = data->cfg_name_;
333 60 : if (cfg_name_ != cfg_name) {
334 28 : cfg_name_ = cfg_name;
335 28 : ret = true;
336 : }
337 :
338 : // Read ifindex for the interface
339 60 : if (table) {
340 60 : VnEntry *vn = table->FindVnRef(data->vn_uuid_);
341 60 : if (vn_.get() != vn) {
342 28 : vn_ = vn;
343 28 : ret = true;
344 : }
345 :
346 60 : bool val = vn ? vn->layer3_forwarding() : false;
347 60 : if (vmi_type_ == VHOST) {
348 3 : val = true;
349 : }
350 :
351 60 : if (layer3_forwarding_ != val) {
352 17 : layer3_forwarding_ = val;
353 17 : ret = true;
354 : }
355 :
356 60 : val = vn ? vn->bridging() : false;
357 60 : if (vmi_type_ == VHOST) {
358 : //Bridging not supported on VHOST vmi
359 3 : val = false;
360 : }
361 :
362 60 : if (bridging_ != val) {
363 28 : bridging_ = val;
364 28 : ret = true;
365 : }
366 :
367 60 : int vxlan_id = vn ? vn->GetVxLanId() : 0;
368 60 : if (vxlan_id_ != vxlan_id) {
369 12 : vxlan_id_ = vxlan_id;
370 12 : ret = true;
371 : }
372 :
373 60 : bool is_etree_leaf = false;
374 60 : if (vn) {
375 40 : is_etree_leaf = vn->pbb_etree_enable();
376 : }
377 :
378 60 : if (etree_leaf_ != is_etree_leaf) {
379 0 : etree_leaf_ = is_etree_leaf;
380 0 : *etree_leaf_mode_changed = true;
381 0 : ret = true;
382 : }
383 :
384 : bool flood_unknown_unicast =
385 60 : vn ? vn->flood_unknown_unicast(): false;
386 60 : if (flood_unknown_unicast_ != flood_unknown_unicast) {
387 0 : flood_unknown_unicast_ = flood_unknown_unicast;
388 0 : ret = true;
389 : }
390 :
391 60 : bool layer2_control_word = false;
392 60 : if (vn) {
393 40 : layer2_control_word = vn->layer2_control_word();
394 : }
395 60 : if (layer2_control_word_ != layer2_control_word) {
396 0 : layer2_control_word_ = layer2_control_word;
397 0 : *etree_leaf_mode_changed = true;
398 0 : ret = true;
399 : }
400 :
401 : // global_qos_config is applicable for vmi of VHOST type.
402 : // Skip checking for qos for vmi of VHOST type, since cfg_qos_table
403 : // is not applicable.
404 60 : if (vmi_type_ != VHOST) {
405 57 : AgentQosConfigTable *qos_table = table->agent()->qos_config_table();
406 57 : AgentQosConfigKey qos_key(data->qos_config_uuid_);
407 57 : const AgentQosConfig *qos_config = static_cast<AgentQosConfig *>
408 57 : (qos_table->FindActiveEntry(&qos_key));
409 57 : bool is_vn_qos_config = false;
410 :
411 57 : if (qos_config == NULL) {
412 57 : if (vn && vn->qos_config()) {
413 0 : qos_config = vn->qos_config();
414 0 : is_vn_qos_config = true;
415 : }
416 : }
417 :
418 57 : if (qos_config_ != qos_config) {
419 0 : qos_config_ = qos_config;
420 0 : ret = true;
421 : }
422 :
423 57 : if (is_vn_qos_config != is_vn_qos_config_) {
424 0 : is_vn_qos_config_ = is_vn_qos_config;
425 0 : ret = true;
426 : }
427 57 : }
428 :
429 60 : if (max_flows_ != data->max_flows_) {
430 0 : if(data->max_flows_ != 0) {
431 0 : max_flows_ = data->max_flows_;
432 : } else {
433 0 : uint32_t max_flow = 0;
434 0 : if (vn) {
435 0 : max_flow = vn->vn_max_flows();
436 : }
437 0 : max_flows_ = max_flow;
438 : }
439 0 : ret = true;
440 : }
441 :
442 : }
443 :
444 60 : if (local_preference_ != data->local_preference_) {
445 0 : local_preference_ = data->local_preference_;
446 0 : *local_pref_changed = true;
447 0 : ret = true;
448 : }
449 :
450 60 : if (need_linklocal_ip_ != data->need_linklocal_ip_) {
451 28 : need_linklocal_ip_ = data->need_linklocal_ip_;
452 28 : ret = true;
453 : }
454 :
455 : // CopyIpAddress uses fabric_port_. So, set it before CopyIpAddresss
456 60 : if (fabric_port_ != data->fabric_port_) {
457 28 : fabric_port_ = data->fabric_port_;
458 28 : ret = true;
459 : }
460 :
461 60 : if (service_health_check_ip_ != data->service_health_check_ip_) {
462 0 : service_health_check_ip_ = data->service_health_check_ip_;
463 0 : ret = true;
464 : }
465 :
466 : //If nova gives a instance-ip then retain that
467 : //ip address as primary ip address
468 : //Else choose the ip address to be old
469 : //primary ip address as long as its present in
470 : //new configuration also
471 60 : Ip4Address ipaddr = data->addr_;
472 60 : if (nova_ip_addr_ != Ip4Address(0)) {
473 50 : ipaddr = nova_ip_addr_;
474 : }
475 60 : if (CopyIpAddress(ipaddr)) {
476 0 : ret = true;
477 : }
478 :
479 60 : Ip6Address ip6_addr = data->ip6_addr_;
480 60 : if (nova_ip6_addr_ != Ip6Address()) {
481 50 : ip6_addr = nova_ip6_addr_;
482 : }
483 :
484 60 : if (CopyIp6Address(ip6_addr)) {
485 0 : ret = true;
486 : }
487 :
488 60 : if (dhcp_enable_ != data->dhcp_enable_) {
489 4 : dhcp_enable_ = data->dhcp_enable_;
490 4 : ret = true;
491 : }
492 :
493 60 : if (dhcp_enable_v6_ != data->dhcp_enable_v6_){
494 0 : dhcp_enable_v6_ = data->dhcp_enable_v6_;
495 0 : ret = true;
496 : }
497 :
498 60 : if (cfg_igmp_enable_ != data->cfg_igmp_enable_) {
499 0 : cfg_igmp_enable_ = data->cfg_igmp_enable_;
500 0 : ret = true;
501 : }
502 :
503 60 : if (igmp_enabled_ != data->igmp_enabled_) {
504 0 : igmp_enabled_ = data->igmp_enabled_;
505 0 : ret = true;
506 : }
507 :
508 60 : if (mac_ip_learning_enable_ != data->mac_ip_learning_enable_) {
509 0 : mac_ip_learning_enable_ = data->mac_ip_learning_enable_;
510 0 : ret = true;
511 : }
512 :
513 60 : if (proxy_arp_mode_ != data->proxy_arp_mode_) {
514 0 : proxy_arp_mode_ = data->proxy_arp_mode_;
515 0 : ret = true;
516 : }
517 :
518 60 : if (disable_policy_ != data->disable_policy_) {
519 6 : disable_policy_ = data->disable_policy_;
520 6 : ret = true;
521 : }
522 :
523 60 : if (is_left_si_ != data->is_left_si_) {
524 0 : is_left_si_ = data->is_left_si_;
525 0 : ret = true;
526 : }
527 :
528 60 : if (service_mode_ != data->service_mode_) {
529 0 : service_mode_ = data->service_mode_;
530 0 : ret = true;
531 : }
532 :
533 60 : if (si_other_end_vmi_ != data->si_other_end_vmi_) {
534 0 : si_other_end_vmi_ = data->si_other_end_vmi_;
535 0 : ret = true;
536 : }
537 :
538 : // Update MAC address if not set already. We dont allow modification
539 : // of mac-address
540 60 : bool mac_set = true;
541 60 : if (vm_mac_ == MacAddress::kZeroMac) {
542 4 : mac_set = false;
543 : }
544 60 : if (mac_set_ != mac_set) {
545 15 : mac_set_ = mac_set;
546 : }
547 :
548 60 : if (mac_set_ == false) {
549 4 : boost::system::error_code ec;
550 4 : mac_set_ = true;
551 4 : vm_mac_ = MacAddress::FromString(data->vm_mac_, &ec);
552 4 : if (ec.value() != 0) {
553 4 : vm_mac_ = MacAddress();
554 4 : mac_set_ = false;
555 : }
556 :
557 4 : if (vmi_type_ == VHOST) {
558 0 : vm_mac_ = GetVifMac(table->agent());
559 0 : if (vm_mac_ != MacAddress()) {
560 0 : mac_set_ = true;
561 : }
562 : }
563 4 : ret = true;
564 : }
565 :
566 60 : if (admin_state_ != data->admin_state_) {
567 0 : admin_state_ = data->admin_state_;
568 0 : ret = true;
569 : }
570 :
571 60 : if (subnet_ != data->subnet_ || subnet_plen_ != data->subnet_plen_) {
572 6 : subnet_ = data->subnet_;
573 6 : subnet_plen_ = data->subnet_plen_;
574 : }
575 :
576 60 : if (learning_enabled_ != data->learning_enabled_) {
577 0 : learning_enabled_ = data->learning_enabled_;
578 0 : *etree_leaf_mode_changed = true;
579 0 : ret = true;
580 : }
581 :
582 60 : if (service_intf_type_ != data->service_intf_type_) {
583 0 : service_intf_type_ = data->service_intf_type_;
584 0 : ret = true;
585 : }
586 : // Copy DHCP options; ret is not modified as there is no dependent action
587 60 : oper_dhcp_options_ = data->oper_dhcp_options_;
588 :
589 : // Audit operational and config floating-ip list
590 60 : FloatingIpSet &old_fip_list = floating_ip_list_.list_;
591 60 : const FloatingIpSet &new_fip_list = data->floating_ip_list_.list_;
592 60 : if (AuditList<FloatingIpList, FloatingIpSet::iterator>
593 60 : (floating_ip_list_, old_fip_list.begin(), old_fip_list.end(),
594 : new_fip_list.begin(), new_fip_list.end())) {
595 0 : ret = true;
596 0 : assert(floating_ip_list_.list_.size() ==
597 : (floating_ip_list_.v4_count_ + floating_ip_list_.v6_count_));
598 : }
599 :
600 : // Audit operational and config alias-ip list
601 60 : AliasIpSet &old_aip_list = alias_ip_list_.list_;
602 60 : const AliasIpSet &new_aip_list = data->alias_ip_list_.list_;
603 60 : if (AuditList<AliasIpList, AliasIpSet::iterator>
604 60 : (alias_ip_list_, old_aip_list.begin(), old_aip_list.end(),
605 : new_aip_list.begin(), new_aip_list.end())) {
606 0 : ret = true;
607 0 : assert(alias_ip_list_.list_.size() ==
608 : (alias_ip_list_.v4_count_ + alias_ip_list_.v6_count_));
609 : }
610 :
611 : // Audit operational and config Service VLAN list
612 60 : ServiceVlanSet &old_service_list = service_vlan_list_.list_;
613 60 : const ServiceVlanSet &new_service_list = data->service_vlan_list_.list_;
614 60 : if (AuditList<ServiceVlanList, ServiceVlanSet::iterator>
615 60 : (service_vlan_list_, old_service_list.begin(), old_service_list.end(),
616 : new_service_list.begin(), new_service_list.end())) {
617 0 : ret = true;
618 : }
619 :
620 : // Audit operational and config Static Route list
621 60 : StaticRouteSet &old_route_list = static_route_list_.list_;
622 60 : const StaticRouteSet &new_route_list = data->static_route_list_.list_;
623 60 : if (AuditList<StaticRouteList, StaticRouteSet::iterator>
624 60 : (static_route_list_, old_route_list.begin(), old_route_list.end(),
625 : new_route_list.begin(), new_route_list.end())) {
626 6 : *static_route_config_changed = true;
627 6 : ret = true;
628 : }
629 :
630 : // Audit operational and config allowed address pair
631 60 : AllowedAddressPairSet &old_aap_list = allowed_address_pair_list_.list_;
632 60 : const AllowedAddressPairSet &new_aap_list = data->
633 : allowed_address_pair_list_.list_;
634 60 : if (AuditList<AllowedAddressPairList, AllowedAddressPairSet::iterator>
635 60 : (allowed_address_pair_list_, old_aap_list.begin(), old_aap_list.end(),
636 : new_aap_list.begin(), new_aap_list.end())) {
637 0 : ret = true;
638 : }
639 :
640 : // Audit operational and config Security Group list
641 60 : SecurityGroupEntrySet &old_sg_list = sg_list_.list_;
642 60 : const SecurityGroupEntrySet &new_sg_list = data->sg_list_.list_;
643 60 : *sg_changed =
644 : AuditList<SecurityGroupEntryList, SecurityGroupEntrySet::iterator>
645 60 : (sg_list_, old_sg_list.begin(), old_sg_list.end(),
646 : new_sg_list.begin(), new_sg_list.end());
647 60 : if (*sg_changed) {
648 6 : ret = true;
649 : }
650 :
651 60 : VrfAssignRuleSet &old_vrf_assign_list = vrf_assign_rule_list_.list_;
652 60 : const VrfAssignRuleSet &new_vrf_assign_list = data->
653 : vrf_assign_rule_list_.list_;
654 60 : if (AuditList<VrfAssignRuleList, VrfAssignRuleSet::iterator>
655 60 : (vrf_assign_rule_list_, old_vrf_assign_list.begin(),
656 : old_vrf_assign_list.end(), new_vrf_assign_list.begin(),
657 : new_vrf_assign_list.end())) {
658 0 : ret = true;
659 : }
660 :
661 60 : FatFlowEntrySet &old_fat_flow_entry_list = fat_flow_list_.list_;
662 60 : const FatFlowEntrySet &new_fat_flow_entry_list =
663 : data->fat_flow_list_.list_;
664 60 : if (AuditList<FatFlowList, FatFlowEntrySet::iterator>
665 60 : (fat_flow_list_, old_fat_flow_entry_list.begin(),
666 : old_fat_flow_entry_list.end(), new_fat_flow_entry_list.begin(),
667 : new_fat_flow_entry_list.end())) {
668 8 : ret = true;
669 : }
670 :
671 60 : InstanceIpSet &old_ipv4_list = instance_ipv4_list_.list_;
672 60 : InstanceIpSet new_ipv4_list = data->instance_ipv4_list_.list_;
673 : //Native ip of instance should be advertised even if
674 : //config is not present, so manually add that entry
675 110 : if (nova_ip_addr_ != Ip4Address(0) &&
676 50 : data->vrf_name_ != Agent::NullString()) {
677 26 : new_ipv4_list.insert(
678 78 : VmInterface::InstanceIp(nova_ip_addr_, Address::kMaxV4PrefixLen,
679 26 : data->ecmp_, true, false, false, false,
680 52 : Ip4Address(0)));
681 : }
682 60 : if (AuditList<InstanceIpList, InstanceIpSet::iterator>
683 60 : (instance_ipv4_list_, old_ipv4_list.begin(), old_ipv4_list.end(),
684 : new_ipv4_list.begin(), new_ipv4_list.end())) {
685 50 : ret = true;
686 : }
687 :
688 60 : InstanceIpSet &old_ipv6_list = instance_ipv6_list_.list_;
689 60 : InstanceIpSet new_ipv6_list = data->instance_ipv6_list_.list_;
690 110 : if (nova_ip6_addr_ != Ip6Address() &&
691 50 : data->vrf_name_ != Agent::NullString()) {
692 26 : new_ipv6_list.insert(
693 78 : VmInterface::InstanceIp(nova_ip6_addr_, Address::kMaxV6PrefixLen,
694 26 : data->ecmp6_, true, false, false, false,
695 52 : Ip4Address(0)));
696 : }
697 :
698 60 : if (AuditList<InstanceIpList, InstanceIpSet::iterator>
699 60 : (instance_ipv6_list_, old_ipv6_list.begin(), old_ipv6_list.end(),
700 : new_ipv6_list.begin(), new_ipv6_list.end())) {
701 38 : ret = true;
702 : }
703 :
704 60 : BridgeDomainEntrySet &old_bd_list = bridge_domain_list_.list_;
705 60 : const BridgeDomainEntrySet &new_bd_list = data->bridge_domain_list_.list_;
706 60 : if (AuditList<BridgeDomainList, BridgeDomainEntrySet::iterator>
707 60 : (bridge_domain_list_, old_bd_list.begin(), old_bd_list.end(),
708 : new_bd_list.begin(), new_bd_list.end())) {
709 0 : ret = true;
710 : }
711 :
712 :
713 60 : TagEntrySet &old_tag_list = tag_list_.list_;
714 60 : const TagEntrySet &new_tag_list = data->tag_list_.list_;
715 60 : *tag_changed = AuditList<TagEntryList, TagEntrySet::iterator>(tag_list_,
716 : old_tag_list.begin(),
717 : old_tag_list.end(),
718 : new_tag_list.begin(),
719 : new_tag_list.end());
720 60 : if (*tag_changed) {
721 0 : ret = true;
722 : }
723 :
724 60 : VmiReceiveRouteSet &old_recv_list = receive_route_list_.list_;
725 60 : const VmiReceiveRouteSet &new_recv_list = data->receive_route_list_.list_;
726 60 : *tag_changed = AuditList<VmiReceiveRouteList,
727 60 : VmiReceiveRouteSet::iterator>(receive_route_list_,
728 : old_recv_list.begin(),
729 : old_recv_list.end(),
730 : new_recv_list.begin(),
731 : new_recv_list.end());
732 60 : if (*tag_changed) {
733 6 : ret = true;
734 : }
735 60 : bool pbb_interface = new_bd_list.size() ? true: false;
736 60 : if (pbb_interface_ != pbb_interface) {
737 0 : pbb_interface_ = pbb_interface;
738 0 : *etree_leaf_mode_changed = true;
739 0 : ret = true;
740 : }
741 :
742 60 : if (data->addr_ != Ip4Address(0) && ecmp_ != data->ecmp_) {
743 2 : ecmp_ = data->ecmp_;
744 2 : *ecmp_changed = true;
745 : }
746 :
747 60 : if (!data->ip6_addr_.is_unspecified() && ecmp6_ != data->ecmp6_) {
748 0 : ecmp6_ = data->ecmp6_;
749 0 : *ecmp_changed = true;
750 : }
751 :
752 116 : if (service_ip_ecmp_ != data->service_ip_ecmp_ ||
753 56 : service_ip_ != data->service_ip_) {
754 4 : service_ip_ecmp_ = data->service_ip_ecmp_;
755 4 : service_ip_ = data->service_ip_;
756 4 : *ecmp_changed = true;
757 4 : ret = true;
758 : }
759 :
760 117 : if (service_ip_ecmp6_ != data->service_ip_ecmp6_ ||
761 57 : service_ip6_ != data->service_ip6_) {
762 3 : service_ip_ecmp6_ = data->service_ip_ecmp6_;
763 3 : service_ip6_ = data->service_ip6_;
764 3 : *ecmp_changed = true;
765 3 : ret = true;
766 : }
767 :
768 60 : if (data->device_type_ != VmInterface::DEVICE_TYPE_INVALID &&
769 43 : device_type_ != data->device_type_) {
770 0 : device_type_= data->device_type_;
771 0 : ret = true;
772 : }
773 :
774 60 : if (device_type_ == LOCAL_DEVICE || device_type_ == REMOTE_VM_VLAN_ON_VMI ||
775 54 : device_type_ == VM_VLAN_ON_VMI) {
776 6 : if (rx_vlan_id_ != data->rx_vlan_id_) {
777 0 : rx_vlan_id_ = data->rx_vlan_id_;
778 0 : ret = true;
779 : }
780 6 : if (tx_vlan_id_ != data->tx_vlan_id_) {
781 0 : tx_vlan_id_ = data->tx_vlan_id_;
782 0 : ret = true;
783 : }
784 : }
785 :
786 60 : if (hbs_intf_type_ != data->hbs_intf_type_) {
787 0 : hbs_intf_type_ = data->hbs_intf_type_;
788 0 : ret = true;
789 : }
790 :
791 60 : if (logical_interface_ != data->logical_interface_) {
792 4 : logical_interface_ = data->logical_interface_;
793 4 : ret = true;
794 : }
795 60 : Interface *new_parent = NULL;
796 60 : InterfaceList new_parent_list;
797 60 : if (data->physical_interface_list_.empty() == false) {
798 3 : std::vector<std::string>::const_iterator ptr;
799 3 : for (ptr = data->physical_interface_list_.begin();
800 6 : ptr < data->physical_interface_list_.end(); ptr++) {
801 3 : PhysicalInterfaceKey key(*ptr);
802 3 : new_parent_list.push_back(static_cast<Interface *>
803 3 : (table->agent()->interface_table()->FindActiveEntry(&key)));
804 3 : }
805 57 : } else if (data->physical_interface_.empty() == false) {
806 2 : PhysicalInterfaceKey key(data->physical_interface_);
807 2 : new_parent = static_cast<Interface *>
808 2 : (table->agent()->interface_table()->FindActiveEntry(&key));
809 57 : } else if (data->parent_vmi_.is_nil() == false) {
810 0 : VmInterfaceKey key(AgentKey::RESYNC, data->parent_vmi_, "");
811 0 : new_parent = static_cast<Interface *>
812 0 : (table->agent()->interface_table()->FindActiveEntry(&key));
813 0 : } else {
814 55 : new_parent = parent_.get();
815 : }
816 :
817 60 : if (parent_list_ != new_parent_list) {
818 6 : parent_list_ = new_parent_list;
819 6 : ret = true;
820 : }
821 :
822 60 : if (parent_ != new_parent) {
823 2 : parent_ = new_parent;
824 2 : ret = true;
825 : }
826 :
827 60 : if (table) {
828 60 : if (os_index() == kInvalidIndex) {
829 4 : GetOsParams(table->agent());
830 4 : if (os_index() != kInvalidIndex)
831 0 : ret = true;
832 : }
833 : }
834 :
835 60 : if (ecmp_load_balance_ != data->ecmp_load_balance_) {
836 28 : ecmp_load_balance_.Copy(data->ecmp_load_balance_);
837 28 : *ecmp_load_balance_changed = true;
838 28 : ret = true;
839 : }
840 :
841 60 : if (slo_list_ != data->slo_list_) {
842 0 : slo_list_ = data->slo_list_;
843 : }
844 :
845 60 : if (logical_router_uuid() != data->logical_router_uuid_) {
846 0 : set_logical_router_uuid(data->logical_router_uuid_);
847 0 : ret = true;
848 : }
849 60 : return ret;
850 60 : }
851 :
852 : /////////////////////////////////////////////////////////////////////////////
853 : // VmInterfaceNovaData routines
854 : /////////////////////////////////////////////////////////////////////////////
855 12 : VmInterfaceNovaData::VmInterfaceNovaData() :
856 : VmInterfaceData(NULL, NULL, INSTANCE_MSG, Interface::TRANSPORT_INVALID),
857 12 : ipv4_addr_(),
858 12 : ipv6_addr_(),
859 12 : mac_addr_(),
860 12 : vm_name_(),
861 12 : vm_uuid_(),
862 12 : vm_project_uuid_(),
863 12 : physical_interface_(),
864 12 : tx_vlan_id_(),
865 12 : rx_vlan_id_(),
866 12 : vhostuser_mode_() {
867 12 : }
868 :
869 12 : VmInterfaceNovaData::VmInterfaceNovaData(const Ip4Address &ipv4_addr,
870 : const Ip6Address &ipv6_addr,
871 : const std::string &mac_addr,
872 : const std::string vm_name,
873 : boost::uuids::uuid vm_uuid,
874 : boost::uuids::uuid vm_project_uuid,
875 : const std::string &physical_interface,
876 : uint16_t tx_vlan_id,
877 : uint16_t rx_vlan_id,
878 : VmInterface::DeviceType device_type,
879 : VmInterface::VmiType vmi_type,
880 : uint8_t vhostuser_mode,
881 : Interface::Transport transport,
882 12 : uint8_t link_state) :
883 : VmInterfaceData(NULL, NULL, INSTANCE_MSG, transport),
884 12 : ipv4_addr_(ipv4_addr),
885 12 : ipv6_addr_(ipv6_addr),
886 12 : mac_addr_(mac_addr),
887 12 : vm_name_(vm_name),
888 12 : vm_uuid_(vm_uuid),
889 12 : vm_project_uuid_(vm_project_uuid),
890 12 : physical_interface_(physical_interface),
891 12 : tx_vlan_id_(tx_vlan_id),
892 12 : rx_vlan_id_(rx_vlan_id),
893 12 : device_type_(device_type),
894 12 : vmi_type_(vmi_type),
895 12 : vhostuser_mode_(vhostuser_mode), link_state_(link_state) {
896 12 : }
897 :
898 48 : VmInterfaceNovaData::~VmInterfaceNovaData() {
899 48 : }
900 :
901 12 : VmInterface *VmInterfaceNovaData::OnAdd(const InterfaceTable *table,
902 : const VmInterfaceKey *key) const {
903 12 : Interface *parent = NULL;
904 24 : if (tx_vlan_id_ != VmInterface::kInvalidVlanId &&
905 12 : rx_vlan_id_ != VmInterface::kInvalidVlanId &&
906 0 : physical_interface_ != Agent::NullString()) {
907 0 : PhysicalInterfaceKey key_1(physical_interface_);
908 0 : parent = static_cast<Interface *>
909 0 : (table->agent()->interface_table()->FindActiveEntry(&key_1));
910 0 : assert(parent != NULL);
911 0 : }
912 :
913 12 : boost::system::error_code ec;
914 12 : MacAddress mac = MacAddress::FromString(mac_addr_, &ec);
915 12 : if (ec.value() != 0) {
916 0 : mac.Zero();
917 : }
918 :
919 : /* OS oper state is passed by PortIpc module (VmiSubscribeEntry) which
920 : * invokes NovaAdd in case of vmware */
921 12 : bool os_oper_state = link_state_;
922 : VmInterface *vmi =
923 12 : new VmInterface(key->uuid_, key->name_, ipv4_addr_, mac, vm_name_,
924 12 : vm_project_uuid_, tx_vlan_id_, rx_vlan_id_,
925 12 : parent, ipv6_addr_, device_type_, vmi_type_,
926 12 : vhostuser_mode_, os_oper_state, logical_router_uuid_);
927 12 : vmi->SetConfigurer(VmInterface::INSTANCE_MSG);
928 12 : vmi->nova_ip_addr_ = ipv4_addr_;
929 12 : vmi->nova_ip6_addr_ = ipv6_addr_;
930 :
931 12 : return vmi;
932 : }
933 :
934 12 : bool VmInterfaceNovaData::OnDelete(const InterfaceTable *table,
935 : VmInterface *vmi) const {
936 12 : if (vmi->IsConfigurerSet(VmInterface::INSTANCE_MSG) == false)
937 0 : return true;
938 :
939 12 : VmInterfaceConfigData data(NULL, NULL);
940 12 : vmi->Resync(table, &data);
941 12 : vmi->ResetConfigurer(VmInterface::CONFIG);
942 12 : vmi->ResetConfigurer(VmInterface::INSTANCE_MSG);
943 12 : table->operdb()->bgp_as_a_service()->DeleteVmInterface(vmi->GetUuid());
944 12 : table->agent()->interface_table()->DelPhysicalDeviceVnEntry(vmi->GetUuid());
945 12 : return true;
946 12 : }
947 :
948 0 : bool VmInterfaceNovaData::OnResync(const InterfaceTable *table,
949 : VmInterface *vmi,
950 : bool *force_update) const {
951 0 : bool ret = false;
952 :
953 0 : if (vmi->vm_project_uuid_ != vm_project_uuid_) {
954 0 : vmi->vm_project_uuid_ = vm_project_uuid_;
955 0 : ret = true;
956 : }
957 :
958 0 : if (vmi->tx_vlan_id_ != tx_vlan_id_) {
959 0 : vmi->tx_vlan_id_ = tx_vlan_id_;
960 0 : ret = true;
961 : }
962 :
963 0 : if (vmi->rx_vlan_id_ != rx_vlan_id_) {
964 0 : vmi->rx_vlan_id_ = rx_vlan_id_;
965 0 : ret = true;
966 : }
967 :
968 0 : if (vmi->nova_ip_addr_ != ipv4_addr_) {
969 0 : vmi->nova_ip_addr_ = ipv4_addr_;
970 0 : ret = true;
971 : }
972 :
973 0 : if (vmi->nova_ip6_addr_ != ipv6_addr_) {
974 0 : vmi->nova_ip6_addr_ = ipv6_addr_;
975 0 : ret = true;
976 : }
977 :
978 0 : vmi->SetConfigurer(VmInterface::INSTANCE_MSG);
979 :
980 0 : return ret;
981 : }
982 :
983 : // Add a VM-Interface
984 12 : void VmInterface::NovaAdd(InterfaceTable *table, const uuid &intf_uuid,
985 : const string &os_name, const Ip4Address &addr,
986 : const string &mac, const string &vm_name,
987 : const uuid &vm_project_uuid, uint16_t tx_vlan_id,
988 : uint16_t rx_vlan_id, const std::string &parent,
989 : const Ip6Address &ip6,
990 : uint8_t vhostuser_mode,
991 : Interface::Transport transport,
992 : uint8_t link_state) {
993 12 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
994 12 : req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid,
995 12 : os_name));
996 :
997 24 : req.data.reset(new VmInterfaceNovaData(addr, ip6, mac, vm_name,
998 24 : nil_uuid(), vm_project_uuid, parent,
999 : tx_vlan_id, rx_vlan_id,
1000 : VmInterface::VM_ON_TAP,
1001 : VmInterface::INSTANCE,
1002 : vhostuser_mode,
1003 12 : transport, link_state));
1004 12 : table->Enqueue(&req);
1005 12 : }
1006 :
1007 : // Delete a VM-Interface
1008 14 : void VmInterface::Delete(InterfaceTable *table, const uuid &intf_uuid,
1009 : VmInterface::Configurer configurer) {
1010 14 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1011 14 : req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid, ""));
1012 :
1013 14 : if (configurer == VmInterface::CONFIG) {
1014 2 : req.data.reset(new VmInterfaceConfigData(NULL, NULL));
1015 12 : } else if (configurer == VmInterface::INSTANCE_MSG) {
1016 12 : req.data.reset(new VmInterfaceNovaData());
1017 : } else {
1018 0 : assert(0);
1019 : }
1020 14 : table->Enqueue(&req);
1021 14 : }
1022 :
1023 : /////////////////////////////////////////////////////////////////////////////
1024 : // VmInterfaceMirrorData routines
1025 : /////////////////////////////////////////////////////////////////////////////
1026 0 : bool VmInterfaceMirrorData::OnResync(const InterfaceTable *table,
1027 : VmInterface *vmi,
1028 : bool *force_update) const {
1029 0 : bool ret = false;
1030 :
1031 0 : MirrorEntry *mirror_entry = NULL;
1032 0 : if (mirror_enable_ == true) {
1033 0 : mirror_entry = table->FindMirrorRef(analyzer_name_);
1034 : }
1035 :
1036 0 : if (vmi->mirror_entry_ != mirror_entry) {
1037 0 : vmi->mirror_entry_ = mirror_entry;
1038 0 : ret = true;
1039 : }
1040 :
1041 0 : return ret;
1042 : }
1043 :
1044 : /////////////////////////////////////////////////////////////////////////////
1045 : // VmInterfaceIpAddressData routines
1046 : /////////////////////////////////////////////////////////////////////////////
1047 : // Update for VM IP address only
1048 : // For interfaces in IP Fabric VRF, we send DHCP requests to external servers
1049 : // if config doesnt provide an address. This address is updated here.
1050 0 : bool VmInterfaceIpAddressData::OnResync(const InterfaceTable *table,
1051 : VmInterface *vmi,
1052 : bool *force_update) const {
1053 0 : bool ret = false;
1054 :
1055 0 : if (vmi->os_index() == VmInterface::kInvalidIndex) {
1056 0 : vmi->GetOsParams(table->agent());
1057 0 : if (vmi->os_index() != VmInterface::kInvalidIndex)
1058 0 : ret = true;
1059 : }
1060 :
1061 : // Ignore IP address change if L3 Forwarding not enabled
1062 0 : if (!vmi->layer3_forwarding_) {
1063 0 : return ret;
1064 : }
1065 :
1066 0 : Ip4Address addr = Ip4Address(0);
1067 0 : if (vmi->CopyIpAddress(addr)) {
1068 0 : ret = true;
1069 : }
1070 :
1071 0 : return ret;
1072 : }
1073 :
1074 : /////////////////////////////////////////////////////////////////////////////
1075 : // VmInterfaceOsOperStateData routines
1076 : /////////////////////////////////////////////////////////////////////////////
1077 : // Resync oper-state for the interface
1078 0 : bool VmInterfaceOsOperStateData::OnResync(const InterfaceTable *table,
1079 : VmInterface *vmi,
1080 : bool *force_update) const {
1081 0 : bool ret = false;
1082 0 : Agent *agent = table->agent();
1083 :
1084 0 : uint32_t old_os_index = vmi->os_index();
1085 0 : bool old_ipv4_active = vmi->ipv4_active_;
1086 0 : bool old_ipv6_active = vmi->ipv6_active_;
1087 :
1088 0 : vmi->GetOsParams(agent);
1089 : /* In DPDK mode (where we have interfaces of type TRANSPORT_PMD), oper_state
1090 : * is updated based on Netlink notification received from vrouter */
1091 0 : if ((vmi->transport_ == Interface::TRANSPORT_PMD) ||
1092 0 : vmi->NeedDefaultOsOperStateDisabled(agent)) {
1093 0 : if (vmi->os_params_.os_oper_state_ != oper_state_) {
1094 0 : vmi->os_params_.os_oper_state_ = oper_state_;
1095 0 : ret = true;
1096 : }
1097 : }
1098 0 : if (vmi->os_index() != old_os_index)
1099 0 : ret = true;
1100 :
1101 0 : vmi->ipv4_active_ = vmi->IsIpv4Active();
1102 0 : if (vmi->ipv4_active_ != old_ipv4_active)
1103 0 : ret = true;
1104 :
1105 0 : vmi->ipv6_active_ = vmi->IsIpv6Active();
1106 0 : if (vmi->ipv6_active_ != old_ipv6_active)
1107 0 : ret = true;
1108 : // Update the Oper data for SubInterfaces if attached to parent interface.
1109 0 : if (ret == true)
1110 0 : vmi->UpdateOperStateOfSubIntf(table);
1111 :
1112 0 : return ret;
1113 : }
1114 :
1115 : /////////////////////////////////////////////////////////////////////////////
1116 : // Global VRouter config update
1117 : /////////////////////////////////////////////////////////////////////////////
1118 0 : bool VmInterfaceGlobalVrouterData::OnResync(const InterfaceTable *table,
1119 : VmInterface *vmi,
1120 : bool *force_update) const {
1121 0 : bool ret = false;
1122 :
1123 0 : if (layer3_forwarding_ != vmi->layer3_forwarding_) {
1124 0 : vmi->layer3_forwarding_ = layer3_forwarding_;
1125 0 : *force_update = true;
1126 0 : ret = true;
1127 : }
1128 :
1129 0 : if (bridging_ != vmi->bridging_) {
1130 0 : vmi->bridging_= bridging_;
1131 0 : *force_update = true;
1132 0 : ret = true;
1133 : }
1134 :
1135 0 : if (vxlan_id_ != vmi->vxlan_id_)
1136 0 : ret = true;
1137 :
1138 0 : if (vmi->ecmp_load_balance().use_global_vrouter()) {
1139 0 : *force_update = true;
1140 0 : ret = true;
1141 : }
1142 :
1143 0 : return ret;
1144 : }
1145 :
1146 : /////////////////////////////////////////////////////////////////////////////
1147 : // Health Check update
1148 : /////////////////////////////////////////////////////////////////////////////
1149 0 : VmInterfaceHealthCheckData::VmInterfaceHealthCheckData() :
1150 0 : VmInterfaceData(NULL, NULL, HEALTH_CHECK, Interface::TRANSPORT_INVALID) {
1151 0 : }
1152 :
1153 0 : VmInterfaceHealthCheckData::~VmInterfaceHealthCheckData() {
1154 0 : }
1155 :
1156 0 : bool VmInterfaceHealthCheckData::OnResync(const InterfaceTable *table,
1157 : VmInterface *vmi,
1158 : bool *force_update) const {
1159 0 : return vmi->UpdateIsHealthCheckActive();
1160 : }
1161 :
1162 0 : VmInterfaceNewFlowDropData::VmInterfaceNewFlowDropData(bool drop_new_flows) :
1163 : VmInterfaceData(NULL, NULL, DROP_NEW_FLOWS, Interface::TRANSPORT_INVALID),
1164 0 : drop_new_flows_(drop_new_flows) {
1165 0 : }
1166 :
1167 0 : VmInterfaceNewFlowDropData::~VmInterfaceNewFlowDropData() {
1168 0 : }
1169 :
1170 0 : bool VmInterfaceNewFlowDropData::OnResync(const InterfaceTable *table,
1171 : VmInterface *vmi,
1172 : bool *force_update) const {
1173 0 : if (vmi->drop_new_flows_ != drop_new_flows_) {
1174 0 : vmi->drop_new_flows_ = drop_new_flows_;
1175 0 : return true;
1176 : }
1177 :
1178 0 : return false;
1179 : }
1180 :
1181 0 : bool VmInterface::UpdateIsHealthCheckActive() {
1182 0 : bool is_hc_active = true;
1183 0 : HealthCheckInstanceSet::iterator it = hc_instance_set_.begin();
1184 0 : while (it != hc_instance_set_.end()) {
1185 0 : if ((*it)->active() == false) {
1186 : // if any of the health check instance reports not active
1187 : // status mark interface health check status inactive
1188 0 : is_hc_active = false;
1189 0 : break;
1190 : }
1191 0 : it++;
1192 : }
1193 :
1194 0 : if (is_hc_active_ != is_hc_active) {
1195 0 : is_hc_active_ = is_hc_active;
1196 0 : return true;
1197 : }
1198 0 : return false;
1199 : }
1200 :
1201 : /////////////////////////////////////////////////////////////////////////////
1202 : // VmInterfaceIfNameData routines
1203 : // The request is used to add/delete interface with only ifname as data
1204 : /////////////////////////////////////////////////////////////////////////////
1205 0 : VmInterfaceIfNameData::VmInterfaceIfNameData() :
1206 : VmInterfaceData(NULL, NULL, INSTANCE_MSG, Interface::TRANSPORT_INVALID),
1207 0 : ifname_() {
1208 0 : }
1209 :
1210 0 : VmInterfaceIfNameData::VmInterfaceIfNameData
1211 0 : (const std::string &ifname):
1212 : VmInterfaceData(NULL, NULL, INSTANCE_MSG, Interface::TRANSPORT_ETHERNET),
1213 0 : ifname_(ifname) {
1214 0 : }
1215 :
1216 0 : VmInterfaceIfNameData::~VmInterfaceIfNameData() {
1217 0 : }
1218 :
1219 0 : VmInterface *VmInterfaceIfNameData::OnAdd(const InterfaceTable *table,
1220 : const VmInterfaceKey *key) const {
1221 0 : Agent *agent = table->agent();
1222 : /* OS oper state is disabled by default in Vmware mode */
1223 0 : bool os_oper_state = !agent->isVmwareMode();
1224 : VmInterface *vmi =
1225 0 : new VmInterface(key->uuid_, key->name_, Ip4Address(), MacAddress(), "",
1226 0 : nil_uuid(), VmInterface::kInvalidVlanId,
1227 0 : VmInterface::kInvalidVlanId, NULL, Ip6Address(),
1228 : VmInterface::VM_ON_TAP, VmInterface::INSTANCE,
1229 : VmInterface::vHostUserClient, os_oper_state,
1230 0 : logical_router_uuid_);
1231 0 : vmi->SetConfigurer(VmInterface::INSTANCE_MSG);
1232 0 : return vmi;
1233 : }
1234 :
1235 0 : bool VmInterfaceIfNameData::OnDelete(const InterfaceTable *table,
1236 : VmInterface *vmi) const {
1237 0 : if (vmi->IsConfigurerSet(VmInterface::INSTANCE_MSG) == false)
1238 0 : return true;
1239 :
1240 0 : VmInterfaceConfigData data(NULL, NULL);
1241 0 : vmi->Resync(table, &data);
1242 0 : vmi->ResetConfigurer(VmInterface::CONFIG);
1243 0 : vmi->ResetConfigurer(VmInterface::INSTANCE_MSG);
1244 0 : table->operdb()->bgp_as_a_service()->DeleteVmInterface(vmi->GetUuid());
1245 0 : table->agent()->interface_table()->DelPhysicalDeviceVnEntry(vmi->GetUuid());
1246 0 : return true;
1247 0 : }
1248 :
1249 0 : bool VmInterfaceIfNameData::OnResync(const InterfaceTable *table,
1250 : VmInterface *vmi,
1251 : bool *force_update) const {
1252 0 : bool ret = false;
1253 0 : vmi->SetConfigurer(VmInterface::INSTANCE_MSG);
1254 0 : return ret;
1255 : }
1256 0 : VmInterfaceLearntMacIpData::VmInterfaceLearntMacIpData() :
1257 : VmInterfaceData(NULL, NULL, HEALTH_CHECK, Interface::TRANSPORT_INVALID),
1258 0 : is_add(true), mac_ip_list_() {
1259 0 : }
1260 0 : VmInterfaceLearntMacIpData::~VmInterfaceLearntMacIpData() {}
1261 :
1262 0 : bool VmInterface::copyMacIpData(const VmInterfaceLearntMacIpData *data) {
1263 0 : LearntMacIpSet::iterator it = data->mac_ip_list_.list_.begin();
1264 0 : while (it != data->mac_ip_list_.list_.end()) {
1265 0 : if (data->is_add) {
1266 0 : learnt_mac_ip_list_.Insert(it.operator->());
1267 : } else {
1268 0 : learnt_mac_ip_list_.Remove(it.operator->());
1269 : }
1270 0 : it++;
1271 : }
1272 0 : return true;
1273 : }
1274 0 : bool VmInterfaceLearntMacIpData::OnResync(const InterfaceTable *table,
1275 : VmInterface *vmi,
1276 : bool *force_update) const {
1277 0 : return vmi->copyMacIpData(this);
1278 : }
1279 :
1280 : // Utility methods to enqueue add/delete requests
1281 0 : void VmInterface::SetIfNameReq(InterfaceTable *table, const uuid &uuid,
1282 : const string &ifname) {
1283 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1284 0 : req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, uuid,
1285 0 : ifname));
1286 :
1287 0 : req.data.reset(new VmInterfaceIfNameData(ifname));
1288 0 : table->Enqueue(&req);
1289 0 : }
1290 :
1291 0 : void VmInterface::DeleteIfNameReq(InterfaceTable *table, const uuid &uuid) {
1292 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1293 0 : req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, uuid, ""));
1294 0 : req.data.reset(new VmInterfaceIfNameData());
1295 0 : table->Enqueue(&req);
1296 0 : }
1297 :
1298 : /////////////////////////////////////////////////////////////////////////////
1299 : // QoS Config change - used from introspect
1300 : /////////////////////////////////////////////////////////////////////////////
1301 0 : void AddVmiQosConfig::HandleRequest() const {
1302 0 : QosResponse *resp = new QosResponse();
1303 0 : resp->set_context(context());
1304 :
1305 0 : boost::uuids::uuid vmi_uuid = StringToUuid(std::string(get_vmi_uuid()));
1306 : boost::uuids::uuid qos_config_uuid =
1307 0 : StringToUuid(std::string(get_qos_config_uuid()));
1308 0 : DBTable *table = Agent::GetInstance()->interface_table();
1309 :
1310 0 : DBRequest req;
1311 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1312 0 : req.key.reset(new VmInterfaceKey(AgentKey::RESYNC, vmi_uuid, ""));
1313 0 : req.data.reset(new InterfaceQosConfigData(NULL, NULL, qos_config_uuid));
1314 0 : table->Enqueue(&req);
1315 0 : resp->set_resp("Success");
1316 0 : resp->Response();
1317 0 : }
|