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 16151 : VmInterfaceKey::VmInterfaceKey(AgentKey::DBSubOperation sub_op,
43 16151 : const boost::uuids::uuid &uuid, const std::string &name) :
44 16151 : InterfaceKey(sub_op, Interface::VM_INTERFACE, uuid, name, false) {
45 16151 : }
46 :
47 1022 : Interface *VmInterfaceKey::AllocEntry(const InterfaceTable *table) const {
48 1022 : Agent *agent = table->agent();
49 : /* OS oper state is disabled by default in Vmware mode */
50 1022 : bool os_oper_state = !agent->isVmwareMode();
51 1022 : return new VmInterface(uuid_, name_, os_oper_state, nil_uuid());
52 : }
53 :
54 16 : Interface *VmInterfaceKey::AllocEntry(const InterfaceTable *table,
55 : const InterfaceData *data) const {
56 16 : const VmInterfaceData *vm_data =
57 : static_cast<const VmInterfaceData *>(data);
58 :
59 16 : VmInterface *vmi = vm_data->OnAdd(table, this);
60 16 : return vmi;
61 : }
62 :
63 287 : InterfaceKey *VmInterfaceKey::Clone() const {
64 287 : return new VmInterfaceKey(*this);
65 : }
66 :
67 : /////////////////////////////////////////////////////////////////////////////
68 : // VmInterfaceConfigData routines
69 : /////////////////////////////////////////////////////////////////////////////
70 109 : VmInterfaceConfigData::VmInterfaceConfigData(Agent *agent, IFMapNode *node) :
71 : VmInterfaceData(agent, node, CONFIG, Interface::TRANSPORT_INVALID),
72 109 : addr_(0), ip6_addr_(), vm_mac_(""),
73 109 : cfg_name_(""), vm_uuid_(), vm_name_(), vn_uuid_(), vrf_name_(""),
74 109 : fabric_port_(true), need_linklocal_ip_(false), bridging_(true),
75 109 : layer3_forwarding_(true), mirror_enable_(false), ecmp_(false),
76 109 : ecmp6_(false), dhcp_enable_(true), dhcp_enable_v6_(false),
77 109 : proxy_arp_mode_(VmInterface::PROXY_ARP_NONE), admin_state_(true),
78 109 : disable_policy_(false), analyzer_name_(""),
79 109 : local_preference_(0), oper_dhcp_options_(),
80 109 : mirror_direction_(Interface::UNKNOWN),
81 109 : cfg_igmp_enable_(false), igmp_enabled_(false),
82 109 : mac_ip_learning_enable_(false), max_flows_(0), sg_list_(),
83 109 : floating_ip_list_(), alias_ip_list_(), service_vlan_list_(),
84 218 : static_route_list_(), allowed_address_pair_list_(),
85 109 : instance_ipv4_list_(true), instance_ipv6_list_(false),
86 109 : bridge_domain_list_(),
87 109 : device_type_(VmInterface::DEVICE_TYPE_INVALID),
88 109 : vmi_type_(VmInterface::VMI_TYPE_INVALID), hbs_intf_type_(VmInterface::HBS_INTF_INVALID),
89 109 : physical_interface_(""), parent_vmi_(), subnet_(0), subnet_plen_(0),
90 109 : rx_vlan_id_(VmInterface::kInvalidVlanId),
91 109 : tx_vlan_id_(VmInterface::kInvalidVlanId),
92 109 : logical_interface_(nil_uuid()), ecmp_load_balance_(),
93 109 : service_health_check_ip_(), service_ip_(0),
94 109 : service_ip_ecmp_(false), service_ip6_(), service_ip_ecmp6_(false),
95 109 : qos_config_uuid_(), learning_enabled_(false),
96 109 : vhostuser_mode_(VmInterface::vHostUserClient), is_left_si_(false), service_mode_(VmInterface::SERVICE_MODE_ERROR),
97 109 : si_other_end_vmi_(nil_uuid()), vmi_cfg_uuid_(nil_uuid()),
98 763 : service_intf_type_(""), physical_interface_list_() {
99 109 : }
100 :
101 3 : VmInterface *VmInterfaceConfigData::OnAdd(const InterfaceTable *table,
102 : const VmInterfaceKey *key) const {
103 :
104 3 : Interface *parent = NULL;
105 3 : 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 3 : boost::system::error_code ec;
121 3 : MacAddress mac = MacAddress::FromString(vm_mac_, &ec);
122 3 : if (ec.value() != 0) {
123 2 : mac.Zero();
124 : }
125 :
126 3 : Agent *agent = table->agent();
127 : /* OS oper state is disabled by default in Vmware mode */
128 3 : bool os_oper_state = !agent->isVmwareMode();
129 : VmInterface *vmi =
130 3 : new VmInterface(key->uuid_, key->name_, addr_, mac, vm_name_,
131 3 : nil_uuid(), tx_vlan_id_, rx_vlan_id_, parent,
132 3 : ip6_addr_, device_type_, vmi_type_, vhostuser_mode_,
133 3 : os_oper_state, logical_router_uuid_);
134 3 : vmi->SetConfigurer(VmInterface::CONFIG);
135 3 : vmi->set_hbs_intf_type(hbs_intf_type_);
136 3 : return vmi;
137 : }
138 :
139 3 : bool VmInterfaceConfigData::OnDelete(const InterfaceTable *table,
140 : VmInterface *vmi) const {
141 3 : if (vmi->IsConfigurerSet(VmInterface::CONFIG) == false)
142 0 : return true;
143 :
144 3 : VmInterfaceConfigData data(NULL, NULL);
145 3 : vmi->Resync(table, &data);
146 3 : vmi->ResetConfigurer(VmInterface::CONFIG);
147 3 : return true;
148 3 : }
149 :
150 59 : bool VmInterfaceConfigData::OnResync(const InterfaceTable *table,
151 : VmInterface *vmi,
152 : bool *force_update) const {
153 59 : bool sg_changed = false;
154 59 : bool ecmp_changed = false;
155 59 : bool local_pref_changed = false;
156 59 : bool ecmp_load_balance_changed = false;
157 59 : bool static_route_config_changed = false;
158 59 : bool etree_leaf_mode_changed = false;
159 59 : bool tag_changed = false;
160 59 : bool ret = false;
161 :
162 59 : 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 59 : if (sg_changed || ecmp_changed || local_pref_changed ||
167 21 : ecmp_load_balance_changed || static_route_config_changed
168 20 : || etree_leaf_mode_changed || tag_changed )
169 39 : *force_update = true;
170 :
171 59 : vmi->SetConfigurer(VmInterface::CONFIG);
172 59 : return ret;
173 : }
174 :
175 88 : autogen::VirtualMachineInterface *VmInterfaceConfigData::GetVmiCfg() const {
176 88 : IFMapNode *node = ifmap_node();
177 88 : if (node != NULL) {
178 88 : if (node->GetObject() != NULL) {
179 : return static_cast <autogen::VirtualMachineInterface *>
180 88 : (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 2 : void VmInterfaceConfigData::CopyVhostData(const Agent *agent) {
193 2 : transport_ = static_cast<Interface::Transport>
194 2 : (agent->GetInterfaceTransport());
195 :
196 2 : proxy_arp_mode_ = VmInterface::PROXY_ARP_NONE;
197 2 : device_type_ = VmInterface::LOCAL_DEVICE;
198 2 : vmi_type_ = VmInterface::VHOST;
199 :
200 2 : vrf_name_ = agent->fabric_policy_vrf_name();
201 2 : if (agent->router_id() != Ip4Address(0) && agent->is_l3mh() == false) {
202 2 : addr_ = agent->router_id();
203 2 : instance_ipv4_list_.list_.insert(
204 4 : VmInterface::InstanceIp(agent->router_id(), 32, false, true,
205 4 : false, false, false, Ip4Address(0)));
206 : }
207 :
208 2 : boost::system::error_code ec;
209 : IpAddress mc_addr =
210 2 : Ip4Address::from_string(IPV4_MULTICAST_BASE_ADDRESS, ec);
211 2 : receive_route_list_.list_.insert(
212 4 : VmInterface::VmiReceiveRoute(mc_addr, MULTICAST_BASE_ADDRESS_PLEN,
213 : false));
214 :
215 2 : mc_addr = Ip6Address::from_string(IPV6_MULTICAST_BASE_ADDRESS, ec);
216 2 : receive_route_list_.list_.insert(
217 4 : VmInterface::VmiReceiveRoute(mc_addr, MULTICAST_BASE_ADDRESS_PLEN,
218 : false));
219 :
220 2 : if (agent->params()->subnet_hosts_resolvable() == true) {
221 : //Add resolve route
222 2 : subnet_ = agent->router_id();
223 2 : subnet_plen_ = agent->vhost_prefix_len();
224 : }
225 :
226 2 : physical_interface_list_ = agent->fabric_interface_name_list();
227 :
228 2 : PhysicalInterfaceKey physical_key(agent->fabric_interface_name());
229 : const Interface *pif =
230 4 : static_cast<const Interface *>(agent->interface_table()->
231 2 : FindActiveEntry(&physical_key));
232 2 : vm_mac_ = pif->mac().ToString();
233 2 : if (agent->is_l3mh()) {
234 0 : vm_mac_ = agent->vrrp_mac().ToString();
235 : }
236 :
237 : //Add default route pointing to gateway
238 2 : static_route_list_.list_.insert(
239 4 : VmInterface::StaticRoute(Ip4Address(0), 0,
240 2 : agent->params()->gateway_list(),
241 4 : CommunityList()));
242 2 : }
243 :
244 :
245 59 : bool VmInterface::CopyIp6Address(const Ip6Address &addr) {
246 59 : bool ret = false;
247 :
248 : // Retain the old if new IP could not be got
249 59 : if (addr.is_unspecified()) {
250 6 : return false;
251 : }
252 :
253 53 : if (primary_ip6_addr_ != addr) {
254 0 : primary_ip6_addr_ = addr;
255 0 : ret = true;
256 : }
257 :
258 53 : 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 59 : 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 59 : bool ret = false;
273 59 : if (table) {
274 59 : VmEntry *vm = table->FindVmRef(data->vm_uuid_);
275 59 : if (vm_.get() != vm) {
276 30 : vm_ = vm;
277 30 : ret = true;
278 : }
279 :
280 : bool drop_new_flows =
281 59 : (vm_.get() != NULL) ? vm_->drop_new_flows() : false;
282 59 : if (drop_new_flows_ != drop_new_flows) {
283 0 : drop_new_flows_ = drop_new_flows;
284 0 : ret = true;
285 : }
286 :
287 59 : VrfEntry *vrf = table->FindVrfRef(data->vrf_name_);
288 59 : if (vrf_.get() != vrf) {
289 32 : vrf_ = vrf;
290 32 : ret = true;
291 : }
292 :
293 59 : VrfEntry *forwarding_vrf = vrf;
294 59 : if (vrf && vrf_->forwarding_vrf()) {
295 1 : forwarding_vrf = vrf_->forwarding_vrf();
296 : }
297 :
298 59 : if (forwarding_vrf != forwarding_vrf_) {
299 32 : forwarding_vrf_ = forwarding_vrf;
300 32 : ret = true;
301 : }
302 :
303 59 : MirrorEntry *mirror = table->FindMirrorRef(data->analyzer_name_);
304 59 : if (mirror_entry_.get() != mirror) {
305 0 : mirror_entry_ = mirror;
306 0 : ret = true;
307 : }
308 : }
309 :
310 59 : if (vmi_type_ != data->vmi_type_) {
311 16 : *etree_leaf_mode_changed = true;
312 16 : vmi_type_ = data->vmi_type_;
313 16 : ret = true;
314 : }
315 :
316 59 : if (vmi_cfg_uuid_ != data->vmi_cfg_uuid_) {
317 30 : vmi_cfg_uuid_ = data->vmi_cfg_uuid_;
318 30 : ret = true;
319 : }
320 :
321 59 : if (vhostuser_mode_ != data->vhostuser_mode_) {
322 0 : vhostuser_mode_ = data->vhostuser_mode_;
323 0 : ret = true;
324 : }
325 :
326 59 : MirrorDirection mirror_direction = data->mirror_direction_;
327 59 : if (mirror_direction_ != mirror_direction) {
328 16 : mirror_direction_ = mirror_direction;
329 16 : ret = true;
330 : }
331 :
332 59 : string cfg_name = data->cfg_name_;
333 59 : if (cfg_name_ != cfg_name) {
334 30 : cfg_name_ = cfg_name;
335 30 : ret = true;
336 : }
337 :
338 : // Read ifindex for the interface
339 59 : if (table) {
340 59 : VnEntry *vn = table->FindVnRef(data->vn_uuid_);
341 59 : if (vn_.get() != vn) {
342 30 : vn_ = vn;
343 30 : ret = true;
344 : }
345 :
346 59 : bool val = vn ? vn->layer3_forwarding() : false;
347 59 : if (vmi_type_ == VHOST) {
348 1 : val = true;
349 : }
350 :
351 59 : if (layer3_forwarding_ != val) {
352 16 : layer3_forwarding_ = val;
353 16 : ret = true;
354 : }
355 :
356 59 : val = vn ? vn->bridging() : false;
357 59 : if (vmi_type_ == VHOST) {
358 : //Bridging not supported on VHOST vmi
359 1 : val = false;
360 : }
361 :
362 59 : if (bridging_ != val) {
363 30 : bridging_ = val;
364 30 : ret = true;
365 : }
366 :
367 59 : int vxlan_id = vn ? vn->GetVxLanId() : 0;
368 59 : if (vxlan_id_ != vxlan_id) {
369 14 : vxlan_id_ = vxlan_id;
370 14 : ret = true;
371 : }
372 :
373 59 : bool is_etree_leaf = false;
374 59 : if (vn) {
375 42 : is_etree_leaf = vn->pbb_etree_enable();
376 : }
377 :
378 59 : 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 59 : vn ? vn->flood_unknown_unicast(): false;
386 59 : if (flood_unknown_unicast_ != flood_unknown_unicast) {
387 0 : flood_unknown_unicast_ = flood_unknown_unicast;
388 0 : ret = true;
389 : }
390 :
391 59 : bool layer2_control_word = false;
392 59 : if (vn) {
393 42 : layer2_control_word = vn->layer2_control_word();
394 : }
395 59 : 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 59 : if (vmi_type_ != VHOST) {
405 58 : AgentQosConfigTable *qos_table = table->agent()->qos_config_table();
406 58 : AgentQosConfigKey qos_key(data->qos_config_uuid_);
407 58 : const AgentQosConfig *qos_config = static_cast<AgentQosConfig *>
408 58 : (qos_table->FindActiveEntry(&qos_key));
409 58 : bool is_vn_qos_config = false;
410 :
411 58 : if (qos_config == NULL) {
412 58 : if (vn && vn->qos_config()) {
413 0 : qos_config = vn->qos_config();
414 0 : is_vn_qos_config = true;
415 : }
416 : }
417 :
418 58 : if (qos_config_ != qos_config) {
419 0 : qos_config_ = qos_config;
420 0 : ret = true;
421 : }
422 :
423 58 : 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 58 : }
428 :
429 59 : 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 59 : 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 59 : if (need_linklocal_ip_ != data->need_linklocal_ip_) {
451 30 : need_linklocal_ip_ = data->need_linklocal_ip_;
452 30 : ret = true;
453 : }
454 :
455 : // CopyIpAddress uses fabric_port_. So, set it before CopyIpAddresss
456 59 : if (fabric_port_ != data->fabric_port_) {
457 30 : fabric_port_ = data->fabric_port_;
458 30 : ret = true;
459 : }
460 :
461 59 : 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 59 : Ip4Address ipaddr = data->addr_;
472 59 : if (nova_ip_addr_ != Ip4Address(0)) {
473 53 : ipaddr = nova_ip_addr_;
474 : }
475 59 : if (CopyIpAddress(ipaddr)) {
476 0 : ret = true;
477 : }
478 :
479 59 : Ip6Address ip6_addr = data->ip6_addr_;
480 59 : if (nova_ip6_addr_ != Ip6Address()) {
481 53 : ip6_addr = nova_ip6_addr_;
482 : }
483 :
484 59 : if (CopyIp6Address(ip6_addr)) {
485 0 : ret = true;
486 : }
487 :
488 59 : if (dhcp_enable_ != data->dhcp_enable_) {
489 4 : dhcp_enable_ = data->dhcp_enable_;
490 4 : ret = true;
491 : }
492 :
493 59 : if (dhcp_enable_v6_ != data->dhcp_enable_v6_){
494 0 : dhcp_enable_v6_ = data->dhcp_enable_v6_;
495 0 : ret = true;
496 : }
497 :
498 59 : if (cfg_igmp_enable_ != data->cfg_igmp_enable_) {
499 0 : cfg_igmp_enable_ = data->cfg_igmp_enable_;
500 0 : ret = true;
501 : }
502 :
503 59 : if (igmp_enabled_ != data->igmp_enabled_) {
504 0 : igmp_enabled_ = data->igmp_enabled_;
505 0 : ret = true;
506 : }
507 :
508 59 : 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 59 : if (proxy_arp_mode_ != data->proxy_arp_mode_) {
514 0 : proxy_arp_mode_ = data->proxy_arp_mode_;
515 0 : ret = true;
516 : }
517 :
518 59 : if (disable_policy_ != data->disable_policy_) {
519 2 : disable_policy_ = data->disable_policy_;
520 2 : ret = true;
521 : }
522 :
523 59 : if (is_left_si_ != data->is_left_si_) {
524 0 : is_left_si_ = data->is_left_si_;
525 0 : ret = true;
526 : }
527 :
528 59 : if (service_mode_ != data->service_mode_) {
529 0 : service_mode_ = data->service_mode_;
530 0 : ret = true;
531 : }
532 :
533 59 : 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 59 : bool mac_set = true;
541 59 : if (vm_mac_ == MacAddress::kZeroMac) {
542 4 : mac_set = false;
543 : }
544 59 : if (mac_set_ != mac_set) {
545 14 : mac_set_ = mac_set;
546 : }
547 :
548 59 : 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 59 : if (admin_state_ != data->admin_state_) {
567 0 : admin_state_ = data->admin_state_;
568 0 : ret = true;
569 : }
570 :
571 59 : if (subnet_ != data->subnet_ || subnet_plen_ != data->subnet_plen_) {
572 2 : subnet_ = data->subnet_;
573 2 : subnet_plen_ = data->subnet_plen_;
574 : }
575 :
576 59 : 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 59 : 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 59 : oper_dhcp_options_ = data->oper_dhcp_options_;
588 :
589 : // Audit operational and config floating-ip list
590 59 : FloatingIpSet &old_fip_list = floating_ip_list_.list_;
591 59 : const FloatingIpSet &new_fip_list = data->floating_ip_list_.list_;
592 59 : if (AuditList<FloatingIpList, FloatingIpSet::iterator>
593 59 : (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 59 : AliasIpSet &old_aip_list = alias_ip_list_.list_;
602 59 : const AliasIpSet &new_aip_list = data->alias_ip_list_.list_;
603 59 : if (AuditList<AliasIpList, AliasIpSet::iterator>
604 59 : (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 59 : ServiceVlanSet &old_service_list = service_vlan_list_.list_;
613 59 : const ServiceVlanSet &new_service_list = data->service_vlan_list_.list_;
614 59 : if (AuditList<ServiceVlanList, ServiceVlanSet::iterator>
615 59 : (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 59 : StaticRouteSet &old_route_list = static_route_list_.list_;
622 59 : const StaticRouteSet &new_route_list = data->static_route_list_.list_;
623 59 : if (AuditList<StaticRouteList, StaticRouteSet::iterator>
624 59 : (static_route_list_, old_route_list.begin(), old_route_list.end(),
625 : new_route_list.begin(), new_route_list.end())) {
626 2 : *static_route_config_changed = true;
627 2 : ret = true;
628 : }
629 :
630 : // Audit operational and config allowed address pair
631 59 : AllowedAddressPairSet &old_aap_list = allowed_address_pair_list_.list_;
632 59 : const AllowedAddressPairSet &new_aap_list = data->
633 : allowed_address_pair_list_.list_;
634 59 : if (AuditList<AllowedAddressPairList, AllowedAddressPairSet::iterator>
635 59 : (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 59 : SecurityGroupEntrySet &old_sg_list = sg_list_.list_;
642 59 : const SecurityGroupEntrySet &new_sg_list = data->sg_list_.list_;
643 59 : *sg_changed =
644 : AuditList<SecurityGroupEntryList, SecurityGroupEntrySet::iterator>
645 59 : (sg_list_, old_sg_list.begin(), old_sg_list.end(),
646 : new_sg_list.begin(), new_sg_list.end());
647 59 : if (*sg_changed) {
648 6 : ret = true;
649 : }
650 :
651 59 : VrfAssignRuleSet &old_vrf_assign_list = vrf_assign_rule_list_.list_;
652 59 : const VrfAssignRuleSet &new_vrf_assign_list = data->
653 : vrf_assign_rule_list_.list_;
654 59 : if (AuditList<VrfAssignRuleList, VrfAssignRuleSet::iterator>
655 59 : (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 59 : FatFlowEntrySet &old_fat_flow_entry_list = fat_flow_list_.list_;
662 59 : const FatFlowEntrySet &new_fat_flow_entry_list =
663 : data->fat_flow_list_.list_;
664 59 : if (AuditList<FatFlowList, FatFlowEntrySet::iterator>
665 59 : (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 59 : InstanceIpSet &old_ipv4_list = instance_ipv4_list_.list_;
672 59 : 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 112 : if (nova_ip_addr_ != Ip4Address(0) &&
676 53 : data->vrf_name_ != Agent::NullString()) {
677 28 : new_ipv4_list.insert(
678 84 : VmInterface::InstanceIp(nova_ip_addr_, Address::kMaxV4PrefixLen,
679 28 : data->ecmp_, true, false, false, false,
680 56 : Ip4Address(0)));
681 : }
682 59 : if (AuditList<InstanceIpList, InstanceIpSet::iterator>
683 59 : (instance_ipv4_list_, old_ipv4_list.begin(), old_ipv4_list.end(),
684 : new_ipv4_list.begin(), new_ipv4_list.end())) {
685 49 : ret = true;
686 : }
687 :
688 59 : InstanceIpSet &old_ipv6_list = instance_ipv6_list_.list_;
689 59 : InstanceIpSet new_ipv6_list = data->instance_ipv6_list_.list_;
690 112 : if (nova_ip6_addr_ != Ip6Address() &&
691 53 : data->vrf_name_ != Agent::NullString()) {
692 28 : new_ipv6_list.insert(
693 84 : VmInterface::InstanceIp(nova_ip6_addr_, Address::kMaxV6PrefixLen,
694 28 : data->ecmp6_, true, false, false, false,
695 56 : Ip4Address(0)));
696 : }
697 :
698 59 : if (AuditList<InstanceIpList, InstanceIpSet::iterator>
699 59 : (instance_ipv6_list_, old_ipv6_list.begin(), old_ipv6_list.end(),
700 : new_ipv6_list.begin(), new_ipv6_list.end())) {
701 41 : ret = true;
702 : }
703 :
704 59 : BridgeDomainEntrySet &old_bd_list = bridge_domain_list_.list_;
705 59 : const BridgeDomainEntrySet &new_bd_list = data->bridge_domain_list_.list_;
706 59 : if (AuditList<BridgeDomainList, BridgeDomainEntrySet::iterator>
707 59 : (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 59 : TagEntrySet &old_tag_list = tag_list_.list_;
714 59 : const TagEntrySet &new_tag_list = data->tag_list_.list_;
715 59 : *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 59 : if (*tag_changed) {
721 0 : ret = true;
722 : }
723 :
724 59 : VmiReceiveRouteSet &old_recv_list = receive_route_list_.list_;
725 59 : const VmiReceiveRouteSet &new_recv_list = data->receive_route_list_.list_;
726 59 : *tag_changed = AuditList<VmiReceiveRouteList,
727 59 : 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 59 : if (*tag_changed) {
733 2 : ret = true;
734 : }
735 59 : bool pbb_interface = new_bd_list.size() ? true: false;
736 59 : 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 59 : if (data->addr_ != Ip4Address(0) && ecmp_ != data->ecmp_) {
743 2 : ecmp_ = data->ecmp_;
744 2 : *ecmp_changed = true;
745 : }
746 :
747 59 : 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 57 : service_ip_ != data->service_ip_) {
754 2 : service_ip_ecmp_ = data->service_ip_ecmp_;
755 2 : service_ip_ = data->service_ip_;
756 2 : *ecmp_changed = true;
757 2 : ret = true;
758 : }
759 :
760 116 : if (service_ip_ecmp6_ != data->service_ip_ecmp6_ ||
761 57 : service_ip6_ != data->service_ip6_) {
762 2 : service_ip_ecmp6_ = data->service_ip_ecmp6_;
763 2 : service_ip6_ = data->service_ip6_;
764 2 : *ecmp_changed = true;
765 2 : ret = true;
766 : }
767 :
768 59 : 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 59 : if (device_type_ == LOCAL_DEVICE || device_type_ == REMOTE_VM_VLAN_ON_VMI ||
775 57 : device_type_ == VM_VLAN_ON_VMI) {
776 2 : if (rx_vlan_id_ != data->rx_vlan_id_) {
777 0 : rx_vlan_id_ = data->rx_vlan_id_;
778 0 : ret = true;
779 : }
780 2 : 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 59 : if (hbs_intf_type_ != data->hbs_intf_type_) {
787 0 : hbs_intf_type_ = data->hbs_intf_type_;
788 0 : ret = true;
789 : }
790 :
791 59 : if (logical_interface_ != data->logical_interface_) {
792 4 : logical_interface_ = data->logical_interface_;
793 4 : ret = true;
794 : }
795 59 : Interface *new_parent = NULL;
796 59 : InterfaceList new_parent_list;
797 59 : if (data->physical_interface_list_.empty() == false) {
798 1 : std::vector<std::string>::const_iterator ptr;
799 1 : for (ptr = data->physical_interface_list_.begin();
800 2 : ptr < data->physical_interface_list_.end(); ptr++) {
801 1 : PhysicalInterfaceKey key(*ptr);
802 1 : new_parent_list.push_back(static_cast<Interface *>
803 1 : (table->agent()->interface_table()->FindActiveEntry(&key)));
804 1 : }
805 58 : } 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 58 : } 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 56 : new_parent = parent_.get();
815 : }
816 :
817 59 : if (parent_list_ != new_parent_list) {
818 2 : parent_list_ = new_parent_list;
819 2 : ret = true;
820 : }
821 :
822 59 : if (parent_ != new_parent) {
823 2 : parent_ = new_parent;
824 2 : ret = true;
825 : }
826 :
827 59 : if (table) {
828 59 : if (os_index() == kInvalidIndex) {
829 4 : GetOsParams(table->agent());
830 4 : if (os_index() != kInvalidIndex)
831 0 : ret = true;
832 : }
833 : }
834 :
835 59 : if (ecmp_load_balance_ != data->ecmp_load_balance_) {
836 30 : ecmp_load_balance_.Copy(data->ecmp_load_balance_);
837 30 : *ecmp_load_balance_changed = true;
838 30 : ret = true;
839 : }
840 :
841 59 : if (slo_list_ != data->slo_list_) {
842 0 : slo_list_ = data->slo_list_;
843 : }
844 :
845 59 : if (logical_router_uuid() != data->logical_router_uuid_) {
846 0 : set_logical_router_uuid(data->logical_router_uuid_);
847 0 : ret = true;
848 : }
849 59 : return ret;
850 59 : }
851 :
852 : /////////////////////////////////////////////////////////////////////////////
853 : // VmInterfaceNovaData routines
854 : /////////////////////////////////////////////////////////////////////////////
855 13 : VmInterfaceNovaData::VmInterfaceNovaData() :
856 : VmInterfaceData(NULL, NULL, INSTANCE_MSG, Interface::TRANSPORT_INVALID),
857 13 : ipv4_addr_(),
858 13 : ipv6_addr_(),
859 13 : mac_addr_(),
860 13 : vm_name_(),
861 13 : vm_uuid_(),
862 13 : vm_project_uuid_(),
863 13 : physical_interface_(),
864 13 : tx_vlan_id_(),
865 13 : rx_vlan_id_(),
866 13 : vhostuser_mode_() {
867 13 : }
868 :
869 13 : 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 13 : uint8_t link_state) :
883 : VmInterfaceData(NULL, NULL, INSTANCE_MSG, transport),
884 13 : ipv4_addr_(ipv4_addr),
885 13 : ipv6_addr_(ipv6_addr),
886 13 : mac_addr_(mac_addr),
887 13 : vm_name_(vm_name),
888 13 : vm_uuid_(vm_uuid),
889 13 : vm_project_uuid_(vm_project_uuid),
890 13 : physical_interface_(physical_interface),
891 13 : tx_vlan_id_(tx_vlan_id),
892 13 : rx_vlan_id_(rx_vlan_id),
893 13 : device_type_(device_type),
894 13 : vmi_type_(vmi_type),
895 13 : vhostuser_mode_(vhostuser_mode), link_state_(link_state) {
896 13 : }
897 :
898 52 : VmInterfaceNovaData::~VmInterfaceNovaData() {
899 52 : }
900 :
901 13 : VmInterface *VmInterfaceNovaData::OnAdd(const InterfaceTable *table,
902 : const VmInterfaceKey *key) const {
903 13 : Interface *parent = NULL;
904 26 : if (tx_vlan_id_ != VmInterface::kInvalidVlanId &&
905 13 : 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 13 : boost::system::error_code ec;
914 13 : MacAddress mac = MacAddress::FromString(mac_addr_, &ec);
915 13 : 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 13 : bool os_oper_state = link_state_;
922 : VmInterface *vmi =
923 13 : new VmInterface(key->uuid_, key->name_, ipv4_addr_, mac, vm_name_,
924 13 : vm_project_uuid_, tx_vlan_id_, rx_vlan_id_,
925 13 : parent, ipv6_addr_, device_type_, vmi_type_,
926 13 : vhostuser_mode_, os_oper_state, logical_router_uuid_);
927 13 : vmi->SetConfigurer(VmInterface::INSTANCE_MSG);
928 13 : vmi->nova_ip_addr_ = ipv4_addr_;
929 13 : vmi->nova_ip6_addr_ = ipv6_addr_;
930 :
931 13 : return vmi;
932 : }
933 :
934 13 : bool VmInterfaceNovaData::OnDelete(const InterfaceTable *table,
935 : VmInterface *vmi) const {
936 13 : if (vmi->IsConfigurerSet(VmInterface::INSTANCE_MSG) == false)
937 0 : return true;
938 :
939 13 : VmInterfaceConfigData data(NULL, NULL);
940 13 : vmi->Resync(table, &data);
941 13 : vmi->ResetConfigurer(VmInterface::CONFIG);
942 13 : vmi->ResetConfigurer(VmInterface::INSTANCE_MSG);
943 13 : table->operdb()->bgp_as_a_service()->DeleteVmInterface(vmi->GetUuid());
944 13 : table->agent()->interface_table()->DelPhysicalDeviceVnEntry(vmi->GetUuid());
945 13 : return true;
946 13 : }
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 13 : 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 13 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
994 13 : req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid,
995 13 : os_name));
996 :
997 26 : req.data.reset(new VmInterfaceNovaData(addr, ip6, mac, vm_name,
998 26 : 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 13 : transport, link_state));
1004 13 : table->Enqueue(&req);
1005 13 : }
1006 :
1007 : // Delete a VM-Interface
1008 15 : void VmInterface::Delete(InterfaceTable *table, const uuid &intf_uuid,
1009 : VmInterface::Configurer configurer) {
1010 15 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1011 15 : req.key.reset(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid, ""));
1012 :
1013 15 : if (configurer == VmInterface::CONFIG) {
1014 2 : req.data.reset(new VmInterfaceConfigData(NULL, NULL));
1015 13 : } else if (configurer == VmInterface::INSTANCE_MSG) {
1016 13 : req.data.reset(new VmInterfaceNovaData());
1017 : } else {
1018 0 : assert(0);
1019 : }
1020 15 : table->Enqueue(&req);
1021 15 : }
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 : }
|