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