Merge "Finish renaming odl-netvirt-vpnservice features."
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronPortChangeListener.java
1 /*
2  * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netvirt.neutronvpn;
9
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Lists;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
18 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
19 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
20 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
25 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.PortAddedToSubnetBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.PortRemovedFromSubnetBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
59 import org.opendaylight.yangtools.concepts.ListenerRegistration;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64
65 public class NeutronPortChangeListener extends AbstractDataChangeListener<Port> implements AutoCloseable {
66     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
67
68     private ListenerRegistration<DataChangeListener> listenerRegistration;
69     private final DataBroker broker;
70     private NeutronvpnManager nvpnManager;
71     private NeutronvpnNatManager nvpnNatManager;
72     private LockManagerService lockManager;
73     private NotificationPublishService notificationPublishService;
74     private NotificationService notificationService;
75
76
77     public NeutronPortChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr,
78                                      NeutronvpnNatManager nVpnNatMgr,
79                                      NotificationPublishService notiPublishService, NotificationService notiService) {
80         super(Port.class);
81         broker = db;
82         nvpnManager = nVpnMgr;
83         nvpnNatManager = nVpnNatMgr;
84         notificationPublishService = notiPublishService;
85         notificationService = notiService;
86         registerListener(db);
87     }
88
89     public void setLockManager(LockManagerService lockManager) {
90         this.lockManager = lockManager;
91     }
92
93     @Override
94     public void close() throws Exception {
95         if (listenerRegistration != null) {
96             try {
97                 listenerRegistration.close();
98             } catch (final Exception e) {
99                 LOG.error("Error when cleaning up DataChangeListener.", e);
100             }
101             listenerRegistration = null;
102         }
103         LOG.info("N_Port listener Closed");
104     }
105
106
107     private void registerListener(final DataBroker db) {
108         try {
109             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
110                     InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class),
111                     NeutronPortChangeListener.this, DataChangeScope.SUBTREE);
112         } catch (final Exception e) {
113             LOG.error("Neutron Manager Port DataChange listener registration fail!", e);
114             throw new IllegalStateException("Neutron Manager Port DataChange listener registration failed.", e);
115         }
116     }
117
118     @Override
119     protected void add(InstanceIdentifier<Port> identifier, Port input) {
120         if (LOG.isTraceEnabled()) {
121             LOG.trace("Adding Port : key: " + identifier + ", value=" + input);
122         }
123         Network network = NeutronvpnUtils.getNeutronNetwork(broker, input.getNetworkId());
124         if (network == null || NeutronvpnUtils.isNetworkTypeVlanOrGre(network)) {
125             //FIXME: This should be removed when support for VLAN and GRE network types is added
126             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}.",
127                     input.getName(), network);
128             return;
129         }
130         NeutronvpnUtils.addToPortCache(input);
131
132         /* check if router interface has been created */
133         if ((input.getDeviceOwner() != null) && (input.getDeviceId() != null)) {
134             if (input.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF)) {
135                 handleRouterInterfaceAdded(input);
136                 /* nothing else to do here */
137                 return;
138             }
139         }
140         if (input.getFixedIps() != null && !input.getFixedIps().isEmpty()) {
141             handleNeutronPortCreated(input);
142         }
143     }
144
145     @Override
146     protected void remove(InstanceIdentifier<Port> identifier, Port input) {
147         if (LOG.isTraceEnabled()) {
148             LOG.trace("Removing Port : key: " + identifier + ", value=" + input);
149         }
150         Network network = NeutronvpnUtils.getNeutronNetwork(broker, input.getNetworkId());
151         if (network == null || NeutronvpnUtils.isNetworkTypeVlanOrGre(network)) {
152             //FIXME: This should be removed when support for VLAN and GRE network types is added
153             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of " +
154                     "network {}.", input.getName(), network);
155             return;
156         }
157         NeutronvpnUtils.removeFromPortCache(input);
158
159         if ((input.getDeviceOwner() != null) && (input.getDeviceId() != null)) {
160             if (input.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF)) {
161                 handleRouterInterfaceRemoved(input);
162                 /* nothing else to do here */
163                 return;
164             }
165         }
166         if (input.getFixedIps() != null && !input.getFixedIps().isEmpty()) {
167             handleNeutronPortDeleted(input);
168         }
169     }
170
171     @Override
172     protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
173         if (LOG.isTraceEnabled()) {
174             LOG.trace("Updating Port : key: " + identifier + ", original value=" + original + ", update value=" +
175                     update);
176         }
177         Network network = NeutronvpnUtils.getNeutronNetwork(broker, update.getNetworkId());
178         if (network == null || NeutronvpnUtils.isNetworkTypeVlanOrGre(network)) {
179             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}."
180                     + " Skipping the processing of Port update DCN", update.getName(), network);
181             return;
182         }
183         List<FixedIps> oldIPs = (original.getFixedIps() != null) ? original.getFixedIps() : new ArrayList<>();
184         List<FixedIps> newIPs = (update.getFixedIps() != null) ? update.getFixedIps() : new ArrayList<>();
185
186         /* check if VIF type updated as part of port binding */
187         if(NeutronvpnUtils.isPortVifTypeUpdated(original, update)) {
188             updateOfPortInterface(original, update);
189         }
190         NeutronvpnUtils.addToPortCache(update);
191
192         /* check if router interface has been updated */
193         if ((update.getDeviceOwner() != null) && (update.getDeviceId() != null)) {
194             if (update.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF)) {
195                 handleRouterInterfaceAdded(update);
196                 /* nothing else to do here */
197                 return;
198             }
199         }
200         if (!oldIPs.equals(newIPs)) {
201             Iterator<FixedIps> iterator = newIPs.iterator();
202             while (iterator.hasNext()) {
203                 FixedIps ip = iterator.next();
204                 if (oldIPs.remove(ip)) {
205                     iterator.remove();
206                 }
207             }
208             handleNeutronPortUpdated(original, update);
209         }
210         handlePortSecurityUpdated(original, update);
211     }
212
213     private void handleRouterInterfaceAdded(Port routerPort) {
214         if (routerPort.getDeviceId() != null) {
215             Uuid routerId = new Uuid(routerPort.getDeviceId());
216             Uuid infNetworkId = routerPort.getNetworkId();
217             Uuid existingVpnId = NeutronvpnUtils.getVpnForNetwork(broker, infNetworkId);
218             if (existingVpnId == null) {
219                 for (FixedIps portIP : routerPort.getFixedIps()) {
220                     if (portIP.getIpAddress().getIpv4Address() != null) {
221                         Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
222                         if (vpnId == null) {
223                             vpnId = routerId;
224                         }
225                         nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId());
226                         String ipValue = portIP.getIpAddress().getIpv4Address().getValue();
227                         nvpnManager.updateSubnetNodeWithFixedIps(portIP.getSubnetId(), routerId,
228                                 routerPort.getUuid(), ipValue, routerPort.getMacAddress().getValue());
229                         nvpnNatManager.handleSubnetsForExternalRouter(routerId, broker);
230                         PhysAddress mac = new PhysAddress(routerPort.getMacAddress().getValue());
231                         LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
232                                 portIP.getIpAddress().getIpv4Address(),routerPort.getMacAddress(),
233                                 routerPort.getUuid().getValue(), vpnId.getValue());
234                         NeutronvpnUtils.createVpnPortFixedIpToPort(broker, vpnId.getValue(), ipValue, routerPort
235                                 .getUuid().getValue(), routerPort.getMacAddress().getValue(), true, true, false);
236                     } else {
237                         LOG.error("No IPv4 address assigned to port {)", routerPort.getUuid().getValue());
238                     }
239                 }
240             } else {
241                 LOG.error("Neutron network {} corresponding to router interface port {} for neutron router {} already" +
242                         " associated to VPN {}", infNetworkId.getValue(), routerPort.getUuid().getValue(), routerId
243                         .getValue(), existingVpnId.getValue());
244             }
245         }
246     }
247
248     private void handleRouterInterfaceRemoved(Port routerPort) {
249         if (routerPort.getDeviceId() != null) {
250             Uuid routerId = new Uuid(routerPort.getDeviceId());
251             for (FixedIps portIP : routerPort.getFixedIps()) {
252                 if (portIP.getIpAddress().getIpv4Address() != null) {
253                     Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
254                     if(vpnId == null) {
255                         vpnId = routerId;
256                     }
257                     nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId());
258                     nvpnManager.updateSubnetNodeWithFixedIps(portIP.getSubnetId(), null,
259                             null, null, null);
260                     nvpnNatManager.handleSubnetsForExternalRouter(routerId, broker);
261                     String ipValue = portIP.getIpAddress().getIpv4Address().getValue();
262                     NeutronvpnUtils.removeVpnPortFixedIpToPort(broker, vpnId.getValue(), ipValue);
263                 } else {
264                     LOG.error("No IPv4 address assigned to port {)", routerPort.getUuid().getValue());
265                 }
266             }
267         }
268     }
269
270     private Long getVpnIdFromUuid(Uuid vpnId) {
271         long vpn = 1;
272         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstanceToVpnId.class).
273                 child(VpnInstance.class, new VpnInstanceKey(vpnId.getValue())).build();
274         try {
275             Optional<VpnInstance> optional = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
276                     id);
277             if (optional.isPresent()) {
278                 vpn = optional.get().getVpnId();
279             }
280         } catch (Exception e) {
281             LOG.error("Failed to retrieve vpn instance for the Subnet .", e.getMessage());
282         }
283         return vpn;
284     }
285
286     private void handleNeutronPortCreated(Port port) {
287         if (!NeutronUtils.isPortVnicTypeNormal(port)) {
288             nvpnManager.updateSubnetmapNodeWithPorts(port.getFixedIps().get(0).getSubnetId(), null, port.getUuid());
289             LOG.info("Port {} is not a NORMAL VNIC Type port; OF Port interfaces are not created",
290                     port.getUuid().getValue());
291             return;
292         }
293         LOG.info("Of-port-interface creation");
294         // Create of-port interface for this neutron port
295         String portInterfaceName = createOfPortInterface(port);
296         LOG.debug("Creating ELAN Interface");
297         createElanInterface(port, portInterfaceName);
298         LOG.debug("Add port to subnet");
299         // add port to local Subnets DS
300         Uuid vpnId = addPortToSubnets(port);
301
302         if (vpnId != null) {
303             // create vpn-interface on this neutron port
304             LOG.debug("Adding VPN Interface");
305             nvpnManager.createVpnInterface(vpnId, port);
306             Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnId).getRouterId();
307             if(routerId != null) {
308                 nvpnManager.addToNeutronRouterInterfacesMap(routerId, port.getUuid().getValue());
309             }
310         }
311     }
312
313     private void handleNeutronPortDeleted(Port port) {
314         if (!NeutronUtils.isPortVnicTypeNormal(port)) {
315             nvpnManager.removePortsFromSubnetmapNode(port.getFixedIps().get(0).getSubnetId(), null, port.getUuid());
316             LOG.info("Port {} is not a NORMAL VNIC Type port; OF Port interfaces are not created",
317                     port.getUuid().getValue());
318             return;
319         }
320         //dissociate fixedIP from floatingIP if associated
321         nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
322         LOG.debug("Remove port from subnet");
323         // remove port from local Subnets DS
324         Uuid vpnId = removePortFromSubnets(port);
325
326         if (vpnId != null) {
327             // remove vpn-interface for this neutron port
328             LOG.debug("removing VPN Interface");
329             nvpnManager.deleteVpnInterface(vpnId, port);
330         }
331
332         // Remove of-port interface for this neutron port
333         // ELAN interface is also implicitly deleted as part of this operation
334         LOG.debug("Of-port-interface removal");
335         deleteOfPortInterface(port);
336         if (vpnId != null) {
337             Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnId).getRouterId();
338             if (routerId != null) {
339                 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, port.getUuid().getValue());
340             }
341         }
342     }
343
344     private void handleNeutronPortUpdated(Port portoriginal, Port portupdate) {
345         if (portoriginal.getFixedIps() == null || portoriginal.getFixedIps().isEmpty()) {
346             handleNeutronPortCreated(portupdate);
347             return;
348         }
349         LOG.debug("Add port to subnet");
350         // add port FixedIP to local Subnets DS
351         Uuid vpnIdup = addPortToSubnets(portupdate);
352
353         if (vpnIdup != null) {
354             nvpnManager.createVpnInterface(vpnIdup, portupdate);
355             Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnIdup).getRouterId();
356             if(routerId != null) {
357                 nvpnManager.addToNeutronRouterInterfacesMap(routerId, portupdate.getUuid().getValue());
358             }
359         }
360
361         // remove port FixedIP from local Subnets DS
362         Uuid vpnIdor = removePortFromSubnets(portoriginal);
363
364         if (vpnIdor != null) {
365             nvpnManager.deleteVpnInterface(vpnIdor, portoriginal);
366             Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnIdor).getRouterId();
367             if(routerId != null) {
368                 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portoriginal.getUuid().getValue());
369             }
370         }
371     }
372
373     private void handlePortSecurityUpdated(Port portOriginal, Port portUpdated) {
374         Boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(portOriginal);
375         Boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(portUpdated);
376         String interfaceName = portUpdated.getUuid().getValue();
377         Interface portInterface = NeutronvpnUtils.getOfPortInterface(broker, portUpdated);
378         if (portInterface != null) {
379             InterfaceAclBuilder interfaceAclBuilder = null;
380             if (origSecurityEnabled != updatedSecurityEnabled) {
381                 interfaceAclBuilder = new InterfaceAclBuilder();
382                 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
383                 if (updatedSecurityEnabled) {
384                     // Handle security group enabled
385                     List<Uuid> securityGroups = portUpdated.getSecurityGroups();
386                     if (securityGroups != null) {
387                         interfaceAclBuilder.setSecurityGroups(securityGroups);
388                     }
389                     List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> portAllowedAddressPairs =
390                             portUpdated.getAllowedAddressPairs();
391                     if (portAllowedAddressPairs != null) {
392                         interfaceAclBuilder
393                                 .setAllowedAddressPairs(getAllowedAddressPairsForAclService(portAllowedAddressPairs));
394                     }
395                 } else {
396                     // Handle security group disabled
397                     interfaceAclBuilder.setSecurityGroups(Lists.newArrayList());
398                     interfaceAclBuilder.setAllowedAddressPairs(Lists.newArrayList());
399                 }
400             } else {
401                 if (updatedSecurityEnabled) {
402                     // handle SG add/delete delta
403                     InterfaceAcl interfaceAcl = portInterface.getAugmentation(InterfaceAcl.class);
404                     interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
405                     List<Uuid> addedGroups = getsecurityGroupChanged(portUpdated.getSecurityGroups(),
406                             portOriginal.getSecurityGroups());
407                     List<Uuid> deletedGroups = getsecurityGroupChanged(portOriginal.getSecurityGroups(),
408                             portUpdated.getSecurityGroups());
409                     List<Uuid> securityGroups = interfaceAcl.getSecurityGroups();
410                     List<Uuid> updatedSecurityGroups =
411                             (securityGroups != null) ? new ArrayList<>(securityGroups) : new ArrayList<>();
412                     if (addedGroups != null) {
413                         updatedSecurityGroups.addAll(addedGroups);
414                     }
415                     if (deletedGroups != null) {
416                         updatedSecurityGroups.removeAll(deletedGroups);
417                     }
418                     interfaceAclBuilder.setSecurityGroups(updatedSecurityGroups);
419
420                     List<AllowedAddressPairs> addedAllowedAddressPairs = getAllowedAddressPairsChanged(
421                             portUpdated.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs());
422                     List<AllowedAddressPairs> deletedAllowedAddressPairs = getAllowedAddressPairsChanged(
423                             portOriginal.getAllowedAddressPairs(), portUpdated.getAllowedAddressPairs());
424                     List<AllowedAddressPairs> allowedAddressPairs = interfaceAcl.getAllowedAddressPairs();
425                     List<AllowedAddressPairs> updatedAllowedAddressPairs =
426                             (allowedAddressPairs != null) ? new ArrayList<>(allowedAddressPairs) : new ArrayList<>();
427                     if (addedAllowedAddressPairs != null) {
428                         updatedAllowedAddressPairs.addAll(addedAllowedAddressPairs);
429                     }
430                     if (deletedAllowedAddressPairs != null) {
431                         updatedAllowedAddressPairs.removeAll(deletedAllowedAddressPairs);
432                     }
433                     interfaceAclBuilder.setAllowedAddressPairs(updatedAllowedAddressPairs);
434                 }
435             }
436
437             if (interfaceAclBuilder != null) {
438                 InterfaceBuilder builder = new InterfaceBuilder(portInterface).addAugmentation(InterfaceAcl.class,
439                         interfaceAclBuilder.build());
440                 InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(interfaceName);
441                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, builder.build());
442             }
443         } else {
444             LOG.error("Interface {} is not present", interfaceName);
445         }
446     }
447
448     private List<Uuid> getsecurityGroupChanged(List<Uuid> port1SecurityGroups, List<Uuid> port2SecurityGroups) {
449         if (port1SecurityGroups == null) {
450             return null;
451         }
452
453         if (port2SecurityGroups == null) {
454             return port1SecurityGroups;
455         }
456
457         List<Uuid> list1 = new ArrayList<>(port1SecurityGroups);
458         List<Uuid> list2 = new ArrayList<>(port2SecurityGroups);
459         for (Iterator<Uuid> iterator = list1.iterator(); iterator.hasNext();) {
460             Uuid securityGroup1 = iterator.next();
461             for (Uuid securityGroup2 : list2) {
462                 if (securityGroup1.getValue().equals(securityGroup2.getValue())) {
463                     iterator.remove();
464                     break;
465                 }
466             }
467         }
468         return list1;
469     }
470
471     private List<AllowedAddressPairs> getAllowedAddressPairsChanged(
472             List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> port1AllowedAddressPairs,
473             List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> port2AllowedAddressPairs) {
474         if (port1AllowedAddressPairs == null) {
475             return null;
476         }
477
478         if (port2AllowedAddressPairs == null) {
479             return getAllowedAddressPairsForAclService(port1AllowedAddressPairs);
480         }
481
482         List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> list1 =
483                 new ArrayList<>(port1AllowedAddressPairs);
484         List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> list2 =
485                 new ArrayList<>(port2AllowedAddressPairs);
486         for (Iterator<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> iterator =
487              list1.iterator(); iterator.hasNext();) {
488             org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs allowedAddressPair1 =
489                     iterator.next();
490             for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs allowedAddressPair2 : list2) {
491                 if (allowedAddressPair1.getKey().equals(allowedAddressPair2.getKey())) {
492                     iterator.remove();
493                     break;
494                 }
495             }
496         }
497         return getAllowedAddressPairsForAclService(list1);
498     }
499
500     private List<AllowedAddressPairs> getAllowedAddressPairsForAclService(
501             List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> portAllowedAddressPairs) {
502         List<AllowedAddressPairs> aclAllowedAddressPairs = new ArrayList<>();
503         for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs portAllowedAddressPair : portAllowedAddressPairs) {
504             AllowedAddressPairsBuilder aclAllowedAdressPairBuilder = new AllowedAddressPairsBuilder();
505             org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddress ipAddress =
506                     portAllowedAddressPair.getIpAddress();
507             if (ipAddress != null && ipAddress.getValue() != null) {
508                 if (ipAddress.getIpPrefix() != null) {
509                     aclAllowedAdressPairBuilder.setIpAddress(new IpPrefixOrAddress(ipAddress.getIpPrefix()));
510                 } else {
511                     aclAllowedAdressPairBuilder.setIpAddress(new IpPrefixOrAddress(ipAddress.getIpAddress()));
512                 }
513             }
514
515             aclAllowedAdressPairBuilder.setMacAddress(portAllowedAddressPair.getMacAddress());
516             aclAllowedAddressPairs.add(aclAllowedAdressPairBuilder.build());
517         }
518         return aclAllowedAddressPairs;
519     }
520
521     private String createOfPortInterface(Port port) {
522         Interface inf = createInterface(port);
523         String infName = inf.getName();
524
525         LOG.debug("Creating OFPort Interface {}", infName);
526         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
527         try {
528             Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
529                     interfaceIdentifier);
530             if (!optionalInf.isPresent()) {
531                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
532             } else {
533                 LOG.error("Interface {} is already present", infName);
534             }
535         } catch (Exception e) {
536             LOG.error("failed to create interface {} due to the exception {} ", infName, e.getMessage());
537         }
538
539         return infName;
540     }
541
542     private Interface createInterface(Port port) {
543         String parentRefName = NeutronvpnUtils.getVifPortName(port);
544         String interfaceName = port.getUuid().getValue();
545         IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
546         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
547         IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
548
549         Network network = NeutronvpnUtils.getNeutronNetwork(broker, port.getNetworkId());
550         ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
551
552         if(parentRefName != null) {
553             ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
554             interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
555         }
556
557         interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
558                 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
559
560         if (NeutronvpnUtils.isPortSecurityEnabled(port)) {
561             InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
562             interfaceAclBuilder.setPortSecurityEnabled(true);
563             List<Uuid> securityGroups = port.getSecurityGroups();
564             if (securityGroups != null) {
565                 interfaceAclBuilder.setSecurityGroups(securityGroups);
566             }
567
568             List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs> portAllowedAddressPairs =
569                     port.getAllowedAddressPairs();
570             if (portAllowedAddressPairs != null) {
571                 interfaceAclBuilder
572                         .setAllowedAddressPairs(getAllowedAddressPairsForAclService(portAllowedAddressPairs));
573             }
574             interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
575         }
576         return interfaceBuilder.build();
577     }
578
579     private void deleteOfPortInterface(Port port) {
580         String name = port.getUuid().getValue();
581         LOG.debug("Removing OFPort Interface {}", name);
582         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
583         try {
584             Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
585                     interfaceIdentifier);
586             if (optionalInf.isPresent()) {
587                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
588             } else {
589                 LOG.error("Interface {} is not present", name);
590             }
591         } catch (Exception e) {
592             LOG.error("Failed to delete interface {} due to the exception {}", name, e.getMessage());
593         }
594     }
595
596     private Interface updateInterface(Port original, Port update) {
597         String parentRefName = NeutronvpnUtils.getVifPortName(update);
598         String interfaceName = original.getUuid().getValue();
599         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
600
601         if(parentRefName != null) {
602             ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
603             interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
604         }
605
606         interfaceBuilder.setName(interfaceName);
607         return interfaceBuilder.build();
608     }
609
610     private String updateOfPortInterface(Port original, Port updated) {
611         Interface inf = updateInterface(original, updated);
612         String infName = inf.getName();
613
614         LOG.debug("Updating OFPort Interface {}", infName);
615         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
616         try {
617             Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
618                     interfaceIdentifier);
619             if (optionalInf.isPresent()) {
620                 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
621             } else {
622                 LOG.error("Interface {} doesn't exist", infName);
623             }
624         } catch (Exception e) {
625             LOG.error("failed to update interface {} due to the exception {} ", infName, e.getMessage());
626         }
627
628         return infName;
629     }
630
631     private void createElanInterface(Port port, String name) {
632         String elanInstanceName = port.getNetworkId().getValue();
633         List<PhysAddress> physAddresses = new ArrayList<>();
634         physAddresses.add(new PhysAddress(port.getMacAddress().getValue()));
635
636         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
637                 .class, new ElanInterfaceKey(name)).build();
638         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
639                 .setName(name).setStaticMacEntries(physAddresses).setKey(new ElanInterfaceKey(name)).build();
640         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInterface);
641         LOG.debug("Creating new ELan Interface {}", elanInterface);
642     }
643
644     // adds port to subnet list and creates vpnInterface
645     private Uuid addPortToSubnets(Port port) {
646         Uuid subnetId = null;
647         Uuid vpnId = null;
648         String infName = port.getUuid().getValue();
649         Subnetmap subnetmap = null;
650         boolean isLockAcquired = false;
651         String lockName = port.getUuid().getValue();
652         String elanInstanceName = port.getNetworkId().getValue();
653         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class).child
654                 (ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
655         Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
656                 elanIdentifierId);
657         long elanTag = elanInstance.get().getElanTag();
658
659         // find the subnet to which this port is associated
660         FixedIps ip = port.getFixedIps().get(0);
661         subnetId = ip.getSubnetId();
662         subnetmap = nvpnManager.updateSubnetmapNodeWithPorts(subnetId, port.getUuid(), null);
663         if (subnetmap != null) {
664             vpnId = subnetmap.getVpnId();
665         }
666         if (vpnId != null) {
667             try {
668                 isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
669                 checkAndPublishPortAddNotification(subnetmap.getSubnetIp(), subnetId, port.getUuid(), elanTag);
670                 LOG.debug("Port added to subnet notification sent");
671             } catch (Exception e) {
672                 LOG.error("Port added to subnet notification failed", e);
673             } finally {
674                 if (isLockAcquired) {
675                     NeutronvpnUtils.unlock(lockManager, lockName);
676                 }
677             }
678         }
679         return vpnId;
680     }
681
682     private Uuid removePortFromSubnets(Port port) {
683         Uuid subnetId = null;
684         Uuid vpnId = null;
685         Subnetmap subnetmap = null;
686         boolean isLockAcquired = false;
687         String lockName = port.getUuid().getValue();
688         String elanInstanceName = port.getNetworkId().getValue();
689         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class).child
690                 (ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
691         Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
692                 elanIdentifierId);
693         long elanTag = elanInstance.get().getElanTag();
694
695         // find the subnet to which this port is associated
696         FixedIps ip = port.getFixedIps().get(0);
697         subnetId = ip.getSubnetId();
698         subnetmap = nvpnManager.removePortsFromSubnetmapNode(subnetId, port.getUuid(), null);
699         if (subnetmap != null) {
700             vpnId = subnetmap.getVpnId();
701         }
702         if (vpnId != null) {
703             try {
704                 isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
705                 checkAndPublishPortRemoveNotification(subnetmap.getSubnetIp(), subnetId, port.getUuid(), elanTag);
706                 LOG.debug("Port removed from subnet notification sent");
707             } catch (Exception e) {
708                 LOG.error("Port removed from subnet notification failed", e);
709             } finally {
710                 if (isLockAcquired) {
711                     NeutronvpnUtils.unlock(lockManager, lockName);
712                 }
713             }
714         }
715         return vpnId;
716     }
717
718     private void checkAndPublishPortAddNotification(String subnetIp, Uuid subnetId, Uuid portId, Long elanTag) throws
719             InterruptedException {
720         PortAddedToSubnetBuilder builder = new PortAddedToSubnetBuilder();
721
722         LOG.info("publish notification called");
723
724         builder.setSubnetIp(subnetIp);
725         builder.setSubnetId(subnetId);
726         builder.setPortId(portId);
727         builder.setElanTag(elanTag);
728
729         notificationPublishService.putNotification(builder.build());
730     }
731
732     private void checkAndPublishPortRemoveNotification(String subnetIp, Uuid subnetId, Uuid portId, Long elanTag)
733             throws InterruptedException {
734         PortRemovedFromSubnetBuilder builder = new PortRemovedFromSubnetBuilder();
735
736         LOG.info("publish notification called");
737
738         builder.setPortId(portId);
739         builder.setSubnetIp(subnetIp);
740         builder.setSubnetId(subnetId);
741         builder.setElanTag(elanTag);
742
743         notificationPublishService.putNotification(builder.build());
744     }
745
746 }