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 com.google.common.base.Optional;
13 import java.util.List;
14 import java.util.Objects;
15 import java.util.concurrent.ExecutionException;
16 import java.util.stream.Collectors;
17 import javax.annotation.PostConstruct;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
23 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
25 import org.opendaylight.genius.mdsalutil.MDSALUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.opendaylight.yangtools.yang.common.Uint32;
37 import org.opendaylight.yangtools.yang.common.Uint64;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 public class NatVpnMapsChangeListener extends AsyncDataTreeChangeListenerBase<VpnMap, NatVpnMapsChangeListener> {
43 private static final Logger LOG = LoggerFactory.getLogger(NatVpnMapsChangeListener.class);
44 private final DataBroker dataBroker;
45 private final ManagedNewTransactionRunner txRunner;
46 private final FloatingIPListener floatingIpListener;
47 private final OdlInterfaceRpcService interfaceManager;
48 private final ExternalRoutersListener externalRoutersListener;
51 public NatVpnMapsChangeListener(final DataBroker dataBroker,
52 final FloatingIPListener floatingIpListener,
53 final OdlInterfaceRpcService interfaceManager,
54 final ExternalRoutersListener externalRoutersListener) {
55 super(VpnMap.class, NatVpnMapsChangeListener.class);
56 this.dataBroker = dataBroker;
57 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
58 this.floatingIpListener = floatingIpListener;
59 this.interfaceManager = interfaceManager;
60 this.externalRoutersListener = externalRoutersListener;
66 LOG.info("{} init", getClass().getSimpleName());
67 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
71 protected InstanceIdentifier<VpnMap> getWildCardPath() {
72 return InstanceIdentifier.create(VpnMaps.class).child(VpnMap.class);
76 protected void add(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
77 Uuid vpnUuid = vpnMap.getVpnId();
78 String vpnName = vpnUuid.getValue();
79 if (vpnMap.getRouterIds() != null) {
80 vpnMap.getRouterIds().stream()
81 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
83 String routerName = router.getRouterId().getValue();
84 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
85 onRouterAssociatedToVpn(vpnName, routerName);
91 protected void remove(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
92 Uuid vpnUuid = vpnMap.getVpnId();
93 String vpnName = vpnUuid.getValue();
94 if (vpnMap.getRouterIds() != null) {
95 vpnMap.getRouterIds().stream()
96 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
98 String routerName = router.getRouterId().getValue();
99 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
100 onRouterDisassociatedFromVpn(vpnName, routerName);
106 protected void update(InstanceIdentifier<VpnMap> identifier, VpnMap original, VpnMap updated) {
107 Uuid vpnUuid = updated.getVpnId();
108 String vpnName = vpnUuid.getValue();
110 List<RouterIds> updatedRouterIdList = updated.getRouterIds();
111 List<RouterIds> originalRouterIdList = original.getRouterIds();
112 List<RouterIds> routersAddedList = null;
113 List<RouterIds> routersRemovedList = null;
115 if (originalRouterIdList == null && updatedRouterIdList != null) {
116 routersAddedList = updatedRouterIdList;
117 } else if (originalRouterIdList != null && updatedRouterIdList != null) {
118 routersAddedList = updatedRouterIdList.stream()
119 .filter(routerId -> (!originalRouterIdList.contains(routerId)))
120 .collect(Collectors.toList());
123 if (originalRouterIdList != null && updatedRouterIdList == null) {
124 routersRemovedList = originalRouterIdList;
125 } else if (originalRouterIdList != null && updatedRouterIdList != null) {
126 routersRemovedList = originalRouterIdList.stream()
127 .filter(routerId -> (!updatedRouterIdList.contains(routerId)))
128 .collect(Collectors.toList());
131 if (routersAddedList != null) {
132 routersAddedList.stream()
133 .filter(router -> !(Objects.equals(router.getRouterId(), updated.getVpnId())))
135 String routerName = router.getRouterId().getValue();
136 onRouterAssociatedToVpn(vpnName, routerName);
140 if (routersRemovedList != null) {
141 routersRemovedList.stream()
142 .filter(router -> !(Objects.equals(router.getRouterId(), original.getVpnId())))
144 String routerName = router.getRouterId().getValue();
145 onRouterDisassociatedFromVpn(vpnName, routerName);
151 protected NatVpnMapsChangeListener getDataTreeChangeListener() {
155 public void onRouterAssociatedToVpn(String vpnName, String routerName) {
157 //check router is associated to external network
158 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
159 if (extNetwork != null) {
161 LOG.debug("onRouterAssociatedToVpn : Router {} is associated with ext nw {}", routerName, extNetwork);
162 handleDNATConfigurationForRouterAssociation(routerName, vpnName, extNetwork);
163 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
164 if (extNetworkUuid == null) {
165 LOG.error("onRouterAssociatedToVpn : Unable to retrieve external network Uuid for router {}",
169 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
171 if (extNwProvType == null) {
172 LOG.error("onRouterAssociatedToVpn : External Network Provider Type missing");
175 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
176 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
177 tx -> externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, routerId, extNetwork,
178 vpnName, tx, extNwProvType)).get();
179 } catch (InterruptedException | ExecutionException e) {
180 LOG.error("Error changling local VPN identifier to BGP VPN identifier", e);
183 LOG.debug("onRouterAssociatedToVpn : Ignoring the Router {} association with VPN {} "
184 + "since it is not external router", routerName, vpnName);
189 * router disassociation from vpn.
192 public void onRouterDisassociatedFromVpn(String vpnName, String routerName) {
194 //check router is associated to external network
195 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
196 if (extNetwork != null) {
198 LOG.debug("onRouterDisassociatedFromVpn : Router {} is associated with ext nw {}", routerName,
200 handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
201 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
202 if (extNetworkUuid == null) {
203 LOG.error("onRouterDisassociatedFromVpn : Unable to retrieve external network Uuid for router {}",
207 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
209 if (extNwProvType == null) {
210 LOG.error("onRouterDisassociatedFromVpn : External Network Provider Type missing");
213 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
214 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
215 tx -> externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, extNetwork,
216 vpnName, tx, extNwProvType)).get();
217 } catch (InterruptedException | ExecutionException e) {
218 LOG.error("Error changing BGP VPN identifier to local VPN identifier", e);
221 LOG.debug("onRouterDisassociatedFromVpn : Ignoring the Router {} association with VPN {} "
222 + "since it is not external router", routerName, vpnName);
226 void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork)
227 throws ExecutionException, InterruptedException {
228 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
229 Optional<RouterPorts> optRouterPorts =
230 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
231 if (!optRouterPorts.isPresent()) {
232 LOG.debug("handleDNATConfigurationForRouterAssociation : Could not read Router Ports data "
233 + "object with id: {} to handle associate vpn {}", routerName, vpnName);
236 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
237 for (Ports port : optRouterPorts.get().nonnullPorts()) {
238 String portName = port.getPortName();
239 Uint64 dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
240 if (dpnId.equals(Uint64.ZERO)) {
241 LOG.warn("handleDNATConfigurationForRouterAssociation : DPN not found for {}, "
242 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
246 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
247 //remove all NAT related entries with routerName
248 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, null,
249 // intExtPortMap.getInternalIp(), externalIp);
250 //Create NAT entries with VPN Id
251 LOG.debug("handleDNATConfigurationForRouterAssociation : Updating DNAT flows with VPN metadata {} ",
253 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, vpnName, networkId, intExtPortMap);
258 void handleDNATConfigurationForRouterDisassociation(String routerName, String vpnName, String externalNetwork)
259 throws ExecutionException, InterruptedException {
260 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
261 Optional<RouterPorts> optRouterPorts =
262 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
263 if (!optRouterPorts.isPresent()) {
264 LOG.error("handleDNATConfigurationForRouterDisassociation : Could not read Router Ports "
265 + "data object with id: {} to handle disassociate vpn {}", routerName, vpnName);
268 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
269 for (Ports port : optRouterPorts.get().nonnullPorts()) {
270 String portName = port.getPortName();
271 Uint64 dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
272 if (dpnId.equals(Uint64.ZERO)) {
273 LOG.debug("handleDNATConfigurationForRouterDisassociation : DPN not found for {}, "
274 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
277 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
278 //remove all NAT related entries with routerName
279 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, vpnName,
280 // intExtPortMap.getInternalIp(), externalIp);
281 //Create NAT entries with VPN Id
282 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, null, networkId, intExtPortMap);