2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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
8 package org.opendaylight.netvirt.natservice.internal;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import java.util.List;
13 import java.util.Objects;
14 import java.util.Optional;
15 import java.util.concurrent.ExecutionException;
16 import java.util.stream.Collectors;
17 import javax.annotation.PreDestroy;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.infrautils.utils.concurrent.Executors;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.common.Uint32;
38 import org.opendaylight.yangtools.yang.common.Uint64;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 public class NatVpnMapsChangeListener extends AbstractAsyncDataTreeChangeListener<VpnMap> {
44 private static final Logger LOG = LoggerFactory.getLogger(NatVpnMapsChangeListener.class);
45 private final DataBroker dataBroker;
46 private final ManagedNewTransactionRunner txRunner;
47 private final FloatingIPListener floatingIpListener;
48 private final OdlInterfaceRpcService interfaceManager;
49 private final ExternalRoutersListener externalRoutersListener;
52 public NatVpnMapsChangeListener(final DataBroker dataBroker,
53 final FloatingIPListener floatingIpListener,
54 final OdlInterfaceRpcService interfaceManager,
55 final ExternalRoutersListener externalRoutersListener) {
56 super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(VpnMaps.class)
58 Executors.newListeningSingleThreadExecutor("NatVpnMapsChangeListener", LOG));
59 this.dataBroker = dataBroker;
60 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
61 this.floatingIpListener = floatingIpListener;
62 this.interfaceManager = interfaceManager;
63 this.externalRoutersListener = externalRoutersListener;
67 LOG.info("{} init", getClass().getSimpleName());
74 Executors.shutdownAndAwaitTermination(getExecutorService());
78 public void add(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
79 Uuid vpnUuid = vpnMap.getVpnId();
80 String vpnName = vpnUuid.getValue();
81 if (vpnMap.getRouterIds() != null) {
82 vpnMap.getRouterIds().stream()
83 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
85 String routerName = router.getRouterId().getValue();
86 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
87 onRouterAssociatedToVpn(vpnName, routerName);
93 public void remove(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
94 Uuid vpnUuid = vpnMap.getVpnId();
95 String vpnName = vpnUuid.getValue();
96 if (vpnMap.getRouterIds() != null) {
97 vpnMap.getRouterIds().stream()
98 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
100 String routerName = router.getRouterId().getValue();
101 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
102 onRouterDisassociatedFromVpn(vpnName, routerName);
108 public void update(InstanceIdentifier<VpnMap> identifier, VpnMap original, VpnMap updated) {
109 Uuid vpnUuid = updated.getVpnId();
110 String vpnName = vpnUuid.getValue();
112 List<RouterIds> updatedRouterIdList = updated.getRouterIds();
113 List<RouterIds> originalRouterIdList = original.getRouterIds();
114 List<RouterIds> routersAddedList = null;
115 List<RouterIds> routersRemovedList = null;
117 if (originalRouterIdList == null && updatedRouterIdList != null) {
118 routersAddedList = updatedRouterIdList;
119 } else if (originalRouterIdList != null && updatedRouterIdList != null) {
120 routersAddedList = updatedRouterIdList.stream()
121 .filter(routerId -> (!originalRouterIdList.contains(routerId)))
122 .collect(Collectors.toList());
125 if (originalRouterIdList != null && updatedRouterIdList == null) {
126 routersRemovedList = originalRouterIdList;
127 } else if (originalRouterIdList != null && updatedRouterIdList != null) {
128 routersRemovedList = originalRouterIdList.stream()
129 .filter(routerId -> (!updatedRouterIdList.contains(routerId)))
130 .collect(Collectors.toList());
133 if (routersAddedList != null) {
134 routersAddedList.stream()
135 .filter(router -> !(Objects.equals(router.getRouterId(), updated.getVpnId())))
137 String routerName = router.getRouterId().getValue();
138 onRouterAssociatedToVpn(vpnName, routerName);
142 if (routersRemovedList != null) {
143 routersRemovedList.stream()
144 .filter(router -> !(Objects.equals(router.getRouterId(), original.getVpnId())))
146 String routerName = router.getRouterId().getValue();
147 onRouterDisassociatedFromVpn(vpnName, routerName);
152 public void onRouterAssociatedToVpn(String vpnName, String routerName) {
154 //check router is associated to external network
155 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
156 if (extNetwork != null) {
158 LOG.debug("onRouterAssociatedToVpn : Router {} is associated with ext nw {}", routerName, extNetwork);
159 handleDNATConfigurationForRouterAssociation(routerName, vpnName, extNetwork);
160 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
161 if (extNetworkUuid == null) {
162 LOG.error("onRouterAssociatedToVpn : Unable to retrieve external network Uuid for router {}",
166 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
168 if (extNwProvType == null) {
169 LOG.error("onRouterAssociatedToVpn : External Network Provider Type missing");
172 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
173 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
174 tx -> externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, routerId, extNetwork,
175 vpnName, tx, extNwProvType)).get();
176 } catch (InterruptedException | ExecutionException e) {
177 LOG.error("Error changling local VPN identifier to BGP VPN identifier", e);
180 LOG.debug("onRouterAssociatedToVpn : Ignoring the Router {} association with VPN {} "
181 + "since it is not external router", routerName, vpnName);
186 * router disassociation from vpn.
189 public void onRouterDisassociatedFromVpn(String vpnName, String routerName) {
191 //check router is associated to external network
192 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
193 if (extNetwork != null) {
195 LOG.debug("onRouterDisassociatedFromVpn : Router {} is associated with ext nw {}", routerName,
197 handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
198 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
199 if (extNetworkUuid == null) {
200 LOG.error("onRouterDisassociatedFromVpn : Unable to retrieve external network Uuid for router {}",
204 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
206 if (extNwProvType == null) {
207 LOG.error("onRouterDisassociatedFromVpn : External Network Provider Type missing");
210 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
211 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
212 tx -> externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, extNetwork,
213 vpnName, tx, extNwProvType)).get();
214 } catch (InterruptedException | ExecutionException e) {
215 LOG.error("Error changing BGP VPN identifier to local VPN identifier", e);
218 LOG.debug("onRouterDisassociatedFromVpn : Ignoring the Router {} association with VPN {} "
219 + "since it is not external router", routerName, vpnName);
223 void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork)
224 throws ExecutionException, InterruptedException {
225 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
226 Optional<RouterPorts> optRouterPorts =
227 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
228 if (!optRouterPorts.isPresent()) {
229 LOG.debug("handleDNATConfigurationForRouterAssociation : Could not read Router Ports data "
230 + "object with id: {} to handle associate vpn {}", routerName, vpnName);
233 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
234 for (Ports port : optRouterPorts.get().nonnullPorts()) {
235 String portName = port.getPortName();
236 Uint64 dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
237 if (dpnId.equals(Uint64.ZERO)) {
238 LOG.warn("handleDNATConfigurationForRouterAssociation : DPN not found for {}, "
239 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
243 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
244 //remove all NAT related entries with routerName
245 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, null,
246 // intExtPortMap.getInternalIp(), externalIp);
247 //Create NAT entries with VPN Id
248 LOG.debug("handleDNATConfigurationForRouterAssociation : Updating DNAT flows with VPN metadata {} ",
250 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, vpnName, networkId, intExtPortMap);
255 void handleDNATConfigurationForRouterDisassociation(String routerName, String vpnName, String externalNetwork)
256 throws ExecutionException, InterruptedException {
257 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
258 Optional<RouterPorts> optRouterPorts =
259 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
260 if (!optRouterPorts.isPresent()) {
261 LOG.error("handleDNATConfigurationForRouterDisassociation : Could not read Router Ports "
262 + "data object with id: {} to handle disassociate vpn {}", routerName, vpnName);
265 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
266 for (Ports port : optRouterPorts.get().nonnullPorts()) {
267 String portName = port.getPortName();
268 Uint64 dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
269 if (dpnId.equals(Uint64.ZERO)) {
270 LOG.debug("handleDNATConfigurationForRouterDisassociation : DPN not found for {}, "
271 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
274 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
275 //remove all NAT related entries with routerName
276 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, vpnName,
277 // intExtPortMap.getInternalIp(), externalIp);
278 //Create NAT entries with VPN Id
279 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, null, networkId, intExtPortMap);