2 * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others. All rights reserved.
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
9 package org.opendaylight.unimgr.mef.netvirt;
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.stream.Collectors;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
17 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
18 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
21 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.Subnets;
22 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
23 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
24 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn;
25 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.IpvcChoice;
28 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
29 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans;
30 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;
31 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import com.google.common.base.Optional;
40 public class SubnetListener extends UnimgrDataTreeChangeListener<Subnet> implements ISubnetManager {
41 private static final Logger Log = LoggerFactory.getLogger(SubnetListener.class);
42 private ListenerRegistration<SubnetListener> subnetListenerRegistration;
43 private final NotificationPublishService notificationPublishService;
44 private final IGwMacListener gwMacListener;
45 private final int waitForElanInterval;
47 public SubnetListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
48 final IGwMacListener gwMacListener, int sleepInterval) {
50 this.notificationPublishService = notPublishService;
51 this.gwMacListener = gwMacListener;
52 this.waitForElanInterval = sleepInterval;
56 public void registerListener() {
58 final DataTreeIdentifier<Subnet> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
59 MefInterfaceUtils.getSubnetsInstanceIdentifier());
60 subnetListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
61 Log.info("IpvcDataTreeChangeListener created and registered");
62 } catch (final Exception e) {
63 Log.error("Ipvc DataChange listener registration failed !", e);
64 throw new IllegalStateException("Ipvc registration Listener failed.", e);
69 public void close() throws Exception {
70 subnetListenerRegistration.close();
74 public void add(DataTreeModification<Subnet> newDataObject) {
75 if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
76 Log.info("subnet {} created", newDataObject.getRootNode().getIdentifier());
79 createNetwork(newDataObject);
83 public void remove(DataTreeModification<Subnet> removedDataObject) {
84 if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
85 Log.info("subnet {} deleted", removedDataObject.getRootNode().getIdentifier());
87 removeNetwork(removedDataObject);
91 public void update(DataTreeModification<Subnet> modifiedDataObject) {
92 if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
93 Log.info("subnet {} updated", modifiedDataObject.getRootNode().getIdentifier());
94 Log.info("process as delete / create");
95 removeNetwork(modifiedDataObject);
96 createNetwork(modifiedDataObject);
101 public void assignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId) {
102 InstanceIdentifier<Subnets> id = MefInterfaceUtils.getSubnetListInstanceIdentifier();
103 Optional<Subnets> allList = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
104 Subnets allSubnets = allList.isPresent() ? allList.get() : null;
105 List<Subnet> allSubnet = allSubnets != null && allSubnets.getSubnet() != null ? allSubnets.getSubnet()
106 : Collections.emptyList();
107 List<Subnet> ipUniSubnets = allSubnet.stream()
108 .filter(s -> s.getUniId().equals(uniId) && s.getIpUniId().equals(ipUniId)).collect(Collectors.toList());
109 // recreate networks on restart
110 ipUniSubnets.forEach(s -> createNetwork(s, uniId, ipUniId));
114 public void unAssignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId) {
115 InstanceIdentifier<Subnets> id = MefInterfaceUtils.getSubnetListInstanceIdentifier();
116 Optional<Subnets> allList = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
117 Subnets allSubnets = allList.isPresent() ? allList.get() : null;
118 List<Subnet> allSubnet = allSubnets != null && allSubnets.getSubnet() != null ? allSubnets.getSubnet()
119 : Collections.emptyList();
120 List<Subnet> ipUniSubnets = allSubnet.stream()
121 .filter(s -> s.getUniId().equals(uniId) && s.getIpUniId().equals(ipUniId)).collect(Collectors.toList());
122 ipUniSubnets.forEach(s -> removeNetwork(s, uniId, ipUniId, ipvcId));
125 private void createNetwork(DataTreeModification<Subnet> newDataObject) {
126 Subnet newSubnet = newDataObject.getRootNode().getDataAfter();
128 Identifier45 nwUniId = newSubnet.getUniId();
129 Identifier45 nwIpUniId = newSubnet.getIpUniId();
131 createNetwork(newSubnet, nwUniId, nwIpUniId);
134 private void createNetwork(Subnet newSubnet, Identifier45 nwUniId, Identifier45 nwIpUniId) {
135 String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
137 InstanceIdentifier<Ipvc> ipvcId = findService(nwUniId, nwIpUniId);
138 if (ipvcId == null) {
139 Log.info("Subnet Uni {} IpUNI {} is not assosiated to service", nwUniId, nwIpUniId);
142 IpvcVpn ipvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
143 if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
144 Log.error("Subnet Uni {} IpUNI {} is not operational", nwUniId, nwIpUniId);
147 VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(newSubnet, ipvcVpn);
148 if (vpnElan == null) {
149 Log.error("Subnet Uni {} IpUNI {} for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
152 if (MefServicesUtils.findNetwork(newSubnet, vpnElan) != null) {
153 Log.info("Network {} exists already", subnetStr);
157 String vpnId = ipvcVpn.getVpnId();
158 synchronized (vpnId.intern()) {
159 if (newSubnet.getGateway() == null) {
160 checkCreateDirectNetwork(newSubnet, ipvcVpn, ipvcId, vpnElan);
162 createNonDirectNetwork(newSubnet, ipvcVpn, ipvcId, vpnElan);
165 MefServicesUtils.addOperIpvcVpnElan(dataBroker, ipvcId, ipvcVpn.getVpnId(), nwUniId, nwIpUniId,
166 vpnElan.getElanId(), vpnElan.getElanPort(), Collections.singletonList(subnetStr));
170 private void createNonDirectNetwork(Subnet newSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId,
172 if (newSubnet.getGateway() == null) {
176 Identifier45 nwUniId = newSubnet.getUniId();
177 Identifier45 nwIpUniId = newSubnet.getIpUniId();
178 String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
180 IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, nwUniId, nwIpUniId, LogicalDatastoreType.CONFIGURATION);
182 Log.error("Uni {} IpUni {} for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
186 String srcTpAddressStr = NetvirtVpnUtils
187 .getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
188 IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
189 String subnet = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
190 gwMacListener.resolveGwMac(ipvcVpn.getVpnId(), vpnElan.getElanPort(), srcIpAddress, newSubnet.getGateway(),
194 private void checkCreateDirectNetwork(Subnet newSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId,
196 if (newSubnet.getGateway() != null) {
200 org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni operUni = MefInterfaceUtils
201 .getUni(dataBroker, newSubnet.getUniId().getValue(), LogicalDatastoreType.OPERATIONAL);
202 if (operUni == null) {
203 Log.error("Uni {} for network {} is not operational", newSubnet.getUniId(), newSubnet.getSubnet());
206 String portMacAddress = operUni.getMacAddress().getValue();
208 NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
209 vpnElan.getElanId(), newSubnet.getSubnet(), vpnElan.getElanPort(), portMacAddress, waitForElanInterval);
213 private void removeNetwork(DataTreeModification<Subnet> deletedDataObject) {
214 Subnet deletedSubnet = deletedDataObject.getRootNode().getDataBefore();
215 Identifier45 dlUniId = deletedSubnet.getUniId();
216 Identifier45 dlIpUniId = deletedSubnet.getIpUniId();
217 InstanceIdentifier<Ipvc> ipvcId = findService(dlUniId, dlIpUniId);
218 if (ipvcId == null) {
219 Log.info("Subnet Uni {} IpUNI {} for deleted network is not assosiated to service", dlUniId, dlIpUniId);
222 removeNetwork(deletedSubnet, dlUniId, dlIpUniId, ipvcId);
225 private void removeNetwork(Subnet dlSubnet, Identifier45 dlUniId, Identifier45 dlIpUniId,
226 InstanceIdentifier<Ipvc> ipvcId) {
227 String subnetStr = NetvirtVpnUtils.ipPrefixToString(dlSubnet.getSubnet());
228 IpvcVpn ipvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
229 if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
230 Log.error("Subnet Uni {} IpUNI {} is not operational", dlUniId, dlIpUniId);
233 VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(dlSubnet, ipvcVpn);
234 if (vpnElan == null) {
235 Log.error("Trying to remove non-operational network {}", subnetStr);
238 if (MefServicesUtils.findNetwork(dlSubnet, vpnElan) == null) {
239 Log.error("Trying to remove non-operational network {}", subnetStr);
243 String vpnId = ipvcVpn.getVpnId();
244 synchronized (vpnId.intern()) {
245 if (dlSubnet.getGateway() == null) {
246 removeDirectNetwork(dlSubnet, ipvcVpn, ipvcId);
248 removeNonDirectNetwork(dlSubnet, ipvcVpn, ipvcId);
251 MefServicesUtils.removeOperIpvcSubnet(dataBroker, ipvcId, ipvcVpn.getVpnId(), dlUniId, dlIpUniId,
252 vpnElan.getElanId(), vpnElan.getElanPort(), subnetStr);
255 private void removeDirectNetwork(Subnet deletedSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId) {
256 if (deletedSubnet.getGateway() != null) {
260 String subnetStr = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
261 VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(deletedSubnet, ipvcVpn);
262 if (vpnElan == null) {
263 Log.error("Network {} has not been created as required, nothing to remove", subnetStr);
267 NetvirtVpnUtils.removeDirectSubnetFromVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
268 vpnElan.getElanId(), vpnElan.getElanPort());
272 private void removeNonDirectNetwork(Subnet deletedSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId) {
273 if (deletedSubnet.getGateway() == null) {
277 Identifier45 nwUniId = deletedSubnet.getUniId();
278 Identifier45 nwIpUniId = deletedSubnet.getIpUniId();
279 String subnetStr = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
280 VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(deletedSubnet, ipvcVpn);
281 if (vpnElan == null) {
282 Log.error("Network {} has not been created as required, nothing to remove", subnetStr);
286 IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, nwUniId, nwIpUniId, LogicalDatastoreType.CONFIGURATION);
288 Log.error("Uni {} IpUni {} for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
292 String srcTpAddressStr = NetvirtVpnUtils
293 .getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
294 IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
295 String subnet = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
296 gwMacListener.unResolveGwMac(ipvcVpn.getVpnId(), vpnElan.getElanPort(), srcIpAddress,
297 deletedSubnet.getGateway(), subnet);
299 NetvirtVpnUtils.removeVpnInterfaceAdjacency(dataBroker, vpnElan.getElanPort(), deletedSubnet.getSubnet());
300 NetvirtVpnUtils.removeVpnInterfaceAdjacency(dataBroker, vpnElan.getElanPort(), deletedSubnet.getGateway());
303 private InstanceIdentifier<Ipvc> findService(Identifier45 uniId, Identifier45 ipUniId) {
304 InstanceIdentifier<MefServices> path = MefServicesUtils.getMefServicesInstanceIdentifier();
305 Optional<MefServices> mefServices = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
306 if (!mefServices.isPresent() || mefServices.get() == null) {
307 Log.info("Uni {} IpUni {} is not assosiated with service", uniId, ipUniId);
310 for (MefService service : mefServices.get().getMefService()) {
311 if (service.getMefServiceChoice() instanceof IpvcChoice) {
312 Ipvc ipvc = ((IpvcChoice) service.getMefServiceChoice()).getIpvc();
313 if (ipvc.getUnis() == null || ipvc.getUnis().getUni() == null) {
316 List<Uni> unis = ipvc.getUnis().getUni();
317 for (Uni uni : unis) {
318 if (uni.getUniId().equals(uniId) && uni.getIpUniId().equals(ipUniId)) {
319 Log.info("Find service {} for uni {} ipuni {}", service.getSvcId(), uniId, ipUniId);
320 return MefServicesUtils.getIpvcInstanceIdentifier(service.getSvcId());
325 Log.info("Uni {} IpUni {} is not assosiated with service", uniId, ipUniId);