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