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.math.BigInteger;
14 import java.util.Objects;
15 import java.util.concurrent.ExecutionException;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 public class NatVpnMapsChangeListener extends AsyncDataTreeChangeListenerBase<VpnMap, NatVpnMapsChangeListener> {
38 private static final Logger LOG = LoggerFactory.getLogger(NatVpnMapsChangeListener.class);
39 private final DataBroker dataBroker;
40 private final ManagedNewTransactionRunner txRunner;
41 private final FloatingIPListener floatingIpListener;
42 private final OdlInterfaceRpcService interfaceManager;
43 private final ExternalRoutersListener externalRoutersListener;
46 public NatVpnMapsChangeListener(final DataBroker dataBroker,
47 final FloatingIPListener floatingIpListener,
48 final OdlInterfaceRpcService interfaceManager,
49 final ExternalRoutersListener externalRoutersListener) {
50 super(VpnMap.class, NatVpnMapsChangeListener.class);
51 this.dataBroker = dataBroker;
52 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
53 this.floatingIpListener = floatingIpListener;
54 this.interfaceManager = interfaceManager;
55 this.externalRoutersListener = externalRoutersListener;
59 LOG.info("{} init", getClass().getSimpleName());
60 registerListener(dataBroker);
64 protected InstanceIdentifier<VpnMap> getWildCardPath() {
65 return InstanceIdentifier.create(VpnMaps.class).child(VpnMap.class);
68 private void registerListener(final DataBroker db) {
69 registerListener(LogicalDatastoreType.CONFIGURATION, db);
73 protected void add(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
74 Uuid vpnUuid = vpnMap.getVpnId();
75 String vpnName = vpnUuid.getValue();
76 vpnMap.getRouterIds().stream()
77 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
79 String routerName = router.getRouterId().getValue();
80 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
81 onRouterAssociatedToVpn(vpnName, routerName);
86 protected void remove(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
87 Uuid vpnUuid = vpnMap.getVpnId();
88 String vpnName = vpnUuid.getValue();
89 vpnMap.getRouterIds().stream()
90 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
92 String routerName = router.getRouterId().getValue();
93 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
94 onRouterDisassociatedFromVpn(vpnName, routerName);
99 protected void update(InstanceIdentifier<VpnMap> identifier, VpnMap original, VpnMap updated) {
100 Uuid vpnUuid = updated.getVpnId();
101 String vpnName = vpnUuid.getValue();
103 updated.getRouterIds().stream()
104 .filter(router -> ! original.getRouterIds().contains(router))
105 .filter(router -> !(Objects.equals(router.getRouterId(), updated.getVpnId())))
107 String routerName = router.getRouterId().getValue();
108 onRouterAssociatedToVpn(vpnName, routerName);
111 original.getRouterIds().stream()
112 .filter(router -> ! updated.getRouterIds().contains(router))
113 .filter(router -> !(Objects.equals(router.getRouterId(), original.getVpnId())))
115 String routerName = router.getRouterId().getValue();
116 onRouterDisassociatedFromVpn(vpnName, routerName);
121 protected NatVpnMapsChangeListener getDataTreeChangeListener() {
125 public void onRouterAssociatedToVpn(String vpnName, String routerName) {
127 //check router is associated to external network
128 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
129 if (extNetwork != null) {
131 LOG.debug("onRouterAssociatedToVpn : Router {} is associated with ext nw {}", routerName, extNetwork);
132 handleDNATConfigurationForRouterAssociation(routerName, vpnName, extNetwork);
133 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
134 if (extNetworkUuid == null) {
135 LOG.error("onRouterAssociatedToVpn : Unable to retrieve external network Uuid for router {}",
139 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
141 if (extNwProvType == null) {
142 LOG.error("onRouterAssociatedToVpn : External Network Provider Type missing");
145 long routerId = NatUtil.getVpnId(dataBroker, routerName);
146 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
147 tx -> externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, routerId, vpnName, tx,
148 extNwProvType)).get();
149 } catch (InterruptedException | ExecutionException e) {
150 LOG.error("Error changling local VPN identifier to BGP VPN identifier", e);
153 LOG.debug("onRouterAssociatedToVpn : Ignoring the Router {} association with VPN {} "
154 + "since it is not external router", routerName, vpnName);
159 * router disassociation from vpn.
162 public void onRouterDisassociatedFromVpn(String vpnName, String routerName) {
164 //check router is associated to external network
165 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
166 if (extNetwork != null) {
168 LOG.debug("onRouterDisassociatedFromVpn : Router {} is associated with ext nw {}", routerName,
170 handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
171 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
172 if (extNetworkUuid == null) {
173 LOG.error("onRouterDisassociatedFromVpn : Unable to retrieve external network Uuid for router {}",
177 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
179 if (extNwProvType == null) {
180 LOG.error("onRouterDisassociatedFromVpn : External Network Provider Type missing");
183 long routerId = NatUtil.getVpnId(dataBroker, routerName);
184 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
185 tx -> externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, vpnName, tx,
186 extNwProvType)).get();
187 } catch (InterruptedException | ExecutionException e) {
188 LOG.error("Error changing BGP VPN identifier to local VPN identifier", e);
191 LOG.debug("onRouterDisassociatedFromVpn : Ignoring the Router {} association with VPN {} "
192 + "since it is not external router", routerName, vpnName);
196 void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork)
197 throws ExecutionException, InterruptedException {
198 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
199 Optional<RouterPorts> optRouterPorts =
200 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
201 if (!optRouterPorts.isPresent()) {
202 LOG.debug("handleDNATConfigurationForRouterAssociation : Could not read Router Ports data "
203 + "object with id: {} to handle associate vpn {}", routerName, vpnName);
206 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
207 for (Ports port : optRouterPorts.get().nonnullPorts()) {
208 String portName = port.getPortName();
209 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
210 if (dpnId.equals(BigInteger.ZERO)) {
211 LOG.warn("handleDNATConfigurationForRouterAssociation : DPN not found for {}, "
212 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
216 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
217 //remove all NAT related entries with routerName
218 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, null,
219 // intExtPortMap.getInternalIp(), externalIp);
220 //Create NAT entries with VPN Id
221 LOG.debug("handleDNATConfigurationForRouterAssociation : Updating DNAT flows with VPN metadata {} ",
223 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, vpnName, networkId, intExtPortMap);
228 void handleDNATConfigurationForRouterDisassociation(String routerName, String vpnName, String externalNetwork)
229 throws ExecutionException, InterruptedException {
230 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
231 Optional<RouterPorts> optRouterPorts =
232 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
233 if (!optRouterPorts.isPresent()) {
234 LOG.error("handleDNATConfigurationForRouterDisassociation : Could not read Router Ports "
235 + "data object with id: {} to handle disassociate vpn {}", routerName, vpnName);
238 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
239 for (Ports port : optRouterPorts.get().nonnullPorts()) {
240 String portName = port.getPortName();
241 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
242 if (dpnId.equals(BigInteger.ZERO)) {
243 LOG.debug("handleDNATConfigurationForRouterDisassociation : DPN not found for {}, "
244 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
247 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
248 //remove all NAT related entries with routerName
249 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, vpnName,
250 // intExtPortMap.getInternalIp(), externalIp);
251 //Create NAT entries with VPN Id
252 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, null, networkId, intExtPortMap);