Add l3vpn support
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / IpvcListener.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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
9 package org.opendaylight.unimgr.mef.netvirt;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
17 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
20 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
21 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.ip.uni.subnets.Subnet;
22 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
23 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.Uni;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
27 import org.opendaylight.yangtools.concepts.ListenerRegistration;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 public class IpvcListener extends UnimgrDataTreeChangeListener<Ipvc> {
32     private static final Logger Log = LoggerFactory.getLogger(IpvcListener.class);
33     private ListenerRegistration<IpvcListener> ipvcListenerRegistration;
34     private final NotificationPublishService notificationPublishService;
35     private final OdlArputilService arpUtilService;
36
37     public IpvcListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
38             final OdlArputilService arputilService) {
39         super(dataBroker);
40         this.notificationPublishService = notPublishService;
41         this.arpUtilService = arputilService;
42         registerListener();
43     }
44
45     public void registerListener() {
46         try {
47             final DataTreeIdentifier<Ipvc> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
48                     MefUtils.getIpvcInstanceIdentifier());
49             ipvcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
50             Log.info("IpvcDataTreeChangeListener created and registered");
51         } catch (final Exception e) {
52             Log.error("Ipvc DataChange listener registration failed !", e);
53             throw new IllegalStateException("Ipvc registration Listener failed.", e);
54         }
55     }
56
57     @Override
58     public void close() throws Exception {
59         ipvcListenerRegistration.close();
60     }
61
62     @Override
63     public void add(DataTreeModification<Ipvc> newDataObject) {
64         if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
65             Log.info("ipvc {} created", newDataObject.getRootNode().getIdentifier());
66             addIpvc(newDataObject);
67         }
68     }
69
70     @Override
71     public void remove(DataTreeModification<Ipvc> removedDataObject) {
72         if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
73             Log.info("ipvc {} deleted", removedDataObject.getRootNode().getIdentifier());
74             removeIpvc(removedDataObject);
75         }
76     }
77
78     @Override
79     public void update(DataTreeModification<Ipvc> modifiedDataObject) {
80         if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
81             Log.info("ipvc {} updated", modifiedDataObject.getRootNode().getIdentifier());
82             updateIpvc(modifiedDataObject);
83         }
84     }
85
86     private void addIpvc(DataTreeModification<Ipvc> newDataObject) {
87         try {
88             Ipvc data = newDataObject.getRootNode().getDataAfter();
89             String instanceName = data.getIpvcId().getValue();
90             final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
91
92             Log.info("Adding vpn instance: " + instanceName);
93             NetvirtVpnUtils.createVpnInstance(dataBroker, vpnName);
94
95             // Create elan interfaces
96             for (Uni uni : data.getUnis().getUni()) {
97                 createInterfaces(vpnName, uni);
98             }
99         } catch (final Exception e) {
100             Log.error("Add ipvc failed !", e);
101         }
102     }
103
104     private void updateIpvc(DataTreeModification<Ipvc> modifiedDataObject) {
105         try {
106             Ipvc original = modifiedDataObject.getRootNode().getDataBefore();
107             Ipvc update = modifiedDataObject.getRootNode().getDataAfter();
108
109             String instanceName = original.getIpvcId().getValue();
110
111             Log.info("Updating elan instance: " + instanceName);
112
113             List<Uni> originalUni = original.getUnis().getUni();
114             List<Uni> updateUni = update.getUnis().getUni();
115             if (updateUni != null && !updateUni.isEmpty()) {
116                 List<Uni> existingClonedUni = new ArrayList<>();
117                 if (originalUni != null && !originalUni.isEmpty()) {
118                     existingClonedUni.addAll(0, originalUni);
119                     originalUni.removeAll(updateUni);
120                     updateUni.removeAll(existingClonedUni);
121                     // removing the Uni which are not presented in the updated
122                     // List
123                     for (Uni uni : originalUni) {
124                         removeElanInterface(instanceName, uni);
125                     }
126                 }
127
128                 // Adding the new Uni which are presented in the updated List
129                 if (updateUni.size() > 0) {
130                     for (Uni uni : updateUni) {
131                         createInterfaces(original, uni);
132                     }
133                 }
134             } else if (originalUni != null && !originalUni.isEmpty()) {
135                 for (Uni uni : originalUni) {
136                     removeElanInterface(instanceName, uni);
137                 }
138             }
139         } catch (final Exception e) {
140             Log.error("Update ipvc failed !", e);
141         }
142     }
143
144     private void removeIpvc(DataTreeModification<Ipvc> removedDataObject) {
145         try {
146             Ipvc data = removedDataObject.getRootNode().getDataBefore();
147
148             String instanceName = data.getIpvcId().getValue();
149
150             for (Uni uni : data.getUnis().getUni()) {
151                 removeElanInterface(instanceName, uni);
152             }
153
154             Log.info("Removing elan instance: " + instanceName);
155             NetvirtUtils.deleteElanInstance(dataBroker, instanceName);
156         } catch (final Exception e) {
157             Log.error("Remove ipvc failed !", e);
158         }
159     }
160
161     private void createInterfaces(Ipvc ipvc, Uni uni) {
162         String instanceName = ipvc.getIpvcId().getValue();
163         createInterfaces(instanceName, uni);
164     }
165
166     private void createInterfaces(String vpnName, Uni uniInService) {
167         String uniId = uniInService.getUniId().getValue();
168         String ipUniId = uniInService.getIpUniId().getValue();
169
170         org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = IpvcUniUtils
171                 .getUni(dataBroker, uniId);
172         if (uni == null) {
173             Log.error("Couldn't find uni {} for ipvc-uni", uniId);
174             throw new UnsupportedOperationException();
175         }
176         IpUni ipUni = IpvcUniUtils.getIpUni(dataBroker, uniId, ipUniId);
177         Integer vlan = (ipUni.getVlan()) != null ? ipUni.getVlan().getValue() : null;
178
179         Log.info("Adding/updating elan instance: " + uniId);
180         String elanName = NetvirtVpnUtils.getElanNameForVpnPort(uniId);
181         Log.info("Adding elan instance: " + elanName);
182         NetvirtUtils.updateElanInstance(dataBroker, elanName);
183
184         String interfaceName = NetvirtVpnUtils.getInterfaceNameForVlan(ipUniId, vlan);
185         Log.info("Adding trunk interface: " + interfaceName);
186         IpvcUniUtils.addUni(dataBroker, uniInService, interfaceName, vlan);
187
188         Log.info("Adding elan interface: " + interfaceName);
189         NetvirtUtils.createInterface(dataBroker, elanName, interfaceName, EtreeInterfaceType.Root, false);
190
191         Log.info("Adding vpn interface: " + interfaceName);
192         NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
193                 uni.getMacAddress(), true, null);
194         NetvirtVpnUtils.createVpnPortFixedIp(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
195                 uni.getMacAddress());
196
197         Log.info("Adding connected network for interface : " + interfaceName);
198         NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, vpnName, elanName,
199                 ipUni.getIpAddress(), interfaceName);
200
201         if (ipUni.getSubnets() != null) {
202             for (Subnet subnet : ipUni.getSubnets().getSubnet()) {
203                 MacAddress gwMacAddress = NetvirtVpnUtils.resolveGwMac(dataBroker, arpUtilService, vpnName,
204                         ipUni.getIpAddress(), subnet.getGateway(), interfaceName); // trunk
205                 if (gwMacAddress == null) {
206                     continue;
207                 }
208                 NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, interfaceName, subnet.getSubnet(),
209                         gwMacAddress, false, ipUni.getIpAddress());
210             }
211         }
212     }
213
214     private void removeElanInterface(String instanceName, Uni uni) {
215         String uniId = uni.getIpUniId().getValue();
216         String interfaceName = uniId;
217         Log.info("Removing elan interface: " + uniId);
218         NetvirtUtils.deleteElanInterface(dataBroker, instanceName, interfaceName);
219     }
220 }