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;
11 import static org.opendaylight.netvirt.natservice.internal.NatUtil.requireNonNullElse;
13 import com.google.common.base.Optional;
14 import java.math.BigInteger;
15 import java.util.Collections;
16 import java.util.Objects;
17 import java.util.concurrent.ExecutionException;
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.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 public class NatVpnMapsChangeListener extends AsyncDataTreeChangeListenerBase<VpnMap, NatVpnMapsChangeListener> {
40 private static final Logger LOG = LoggerFactory.getLogger(NatVpnMapsChangeListener.class);
41 private final DataBroker dataBroker;
42 private final ManagedNewTransactionRunner txRunner;
43 private final FloatingIPListener floatingIpListener;
44 private final OdlInterfaceRpcService interfaceManager;
45 private final ExternalRoutersListener externalRoutersListener;
48 public NatVpnMapsChangeListener(final DataBroker dataBroker,
49 final FloatingIPListener floatingIpListener,
50 final OdlInterfaceRpcService interfaceManager,
51 final ExternalRoutersListener externalRoutersListener) {
52 super(VpnMap.class, NatVpnMapsChangeListener.class);
53 this.dataBroker = dataBroker;
54 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
55 this.floatingIpListener = floatingIpListener;
56 this.interfaceManager = interfaceManager;
57 this.externalRoutersListener = externalRoutersListener;
61 LOG.info("{} init", getClass().getSimpleName());
62 registerListener(dataBroker);
66 protected InstanceIdentifier<VpnMap> getWildCardPath() {
67 return InstanceIdentifier.create(VpnMaps.class).child(VpnMap.class);
70 private void registerListener(final DataBroker db) {
71 registerListener(LogicalDatastoreType.CONFIGURATION, db);
75 protected void add(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
76 Uuid vpnUuid = vpnMap.getVpnId();
77 String vpnName = vpnUuid.getValue();
78 vpnMap.getRouterIds().stream()
79 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
81 String routerName = router.getRouterId().getValue();
82 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
83 onRouterAssociatedToVpn(vpnName, routerName);
88 protected void remove(InstanceIdentifier<VpnMap> identifier, VpnMap vpnMap) {
89 Uuid vpnUuid = vpnMap.getVpnId();
90 String vpnName = vpnUuid.getValue();
91 vpnMap.getRouterIds().stream()
92 .filter(router -> !(Objects.equals(router.getRouterId(), vpnUuid)))
94 String routerName = router.getRouterId().getValue();
95 LOG.info("REMOVE: Router {} is disassociated from Vpn {}", routerName, vpnName);
96 onRouterDisassociatedFromVpn(vpnName, routerName);
101 protected void update(InstanceIdentifier<VpnMap> identifier, VpnMap original, VpnMap updated) {
102 Uuid vpnUuid = updated.getVpnId();
103 String vpnName = vpnUuid.getValue();
105 updated.getRouterIds().stream()
106 .filter(router -> ! original.getRouterIds().contains(router))
107 .filter(router -> !(Objects.equals(router.getRouterId(), updated.getVpnId())))
109 String routerName = router.getRouterId().getValue();
110 onRouterAssociatedToVpn(vpnName, routerName);
113 original.getRouterIds().stream()
114 .filter(router -> ! updated.getRouterIds().contains(router))
115 .filter(router -> !(Objects.equals(router.getRouterId(), original.getVpnId())))
117 String routerName = router.getRouterId().getValue();
118 onRouterDisassociatedFromVpn(vpnName, routerName);
123 protected NatVpnMapsChangeListener getDataTreeChangeListener() {
127 public void onRouterAssociatedToVpn(String vpnName, String routerName) {
129 //check router is associated to external network
130 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
131 if (extNetwork != null) {
133 LOG.debug("onRouterAssociatedToVpn : Router {} is associated with ext nw {}", routerName, extNetwork);
134 handleDNATConfigurationForRouterAssociation(routerName, vpnName, extNetwork);
135 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
136 if (extNetworkUuid == null) {
137 LOG.error("onRouterAssociatedToVpn : Unable to retrieve external network Uuid for router {}",
141 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
143 if (extNwProvType == null) {
144 LOG.error("onRouterAssociatedToVpn : External Network Provider Type missing");
147 long routerId = NatUtil.getVpnId(dataBroker, routerName);
148 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
149 tx -> externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, routerId, vpnName, tx,
150 extNwProvType)).get();
151 } catch (InterruptedException | ExecutionException e) {
152 LOG.error("Error changling local VPN identifier to BGP VPN identifier", e);
155 LOG.debug("onRouterAssociatedToVpn : Ignoring the Router {} association with VPN {} "
156 + "since it is not external router", routerName, vpnName);
161 * router disassociation from vpn.
164 public void onRouterDisassociatedFromVpn(String vpnName, String routerName) {
166 //check router is associated to external network
167 String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
168 if (extNetwork != null) {
170 LOG.debug("onRouterDisassociatedFromVpn : Router {} is associated with ext nw {}", routerName,
172 handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
173 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
174 if (extNetworkUuid == null) {
175 LOG.error("onRouterDisassociatedFromVpn : Unable to retrieve external network Uuid for router {}",
179 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
181 if (extNwProvType == null) {
182 LOG.error("onRouterDisassociatedFromVpn : External Network Provider Type missing");
185 long routerId = NatUtil.getVpnId(dataBroker, routerName);
186 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
187 tx -> externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, vpnName, tx,
188 extNwProvType)).get();
189 } catch (InterruptedException | ExecutionException e) {
190 LOG.error("Error changing BGP VPN identifier to local VPN identifier", e);
193 LOG.debug("onRouterDisassociatedFromVpn : Ignoring the Router {} association with VPN {} "
194 + "since it is not external router", routerName, vpnName);
198 void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork)
199 throws ExecutionException, InterruptedException {
200 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
201 Optional<RouterPorts> optRouterPorts =
202 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
203 if (!optRouterPorts.isPresent()) {
204 LOG.debug("handleDNATConfigurationForRouterAssociation : Could not read Router Ports data "
205 + "object with id: {} to handle associate vpn {}", routerName, vpnName);
208 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
209 for (Ports port : requireNonNullElse(optRouterPorts.get().getPorts(), Collections.<Ports>emptyList())) {
210 String portName = port.getPortName();
211 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
212 if (dpnId.equals(BigInteger.ZERO)) {
213 LOG.warn("handleDNATConfigurationForRouterAssociation : DPN not found for {}, "
214 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
218 for (InternalToExternalPortMap intExtPortMap : requireNonNullElse(port.getInternalToExternalPortMap(),
219 Collections.<InternalToExternalPortMap>emptyList())) {
220 //remove all NAT related entries with routerName
221 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, null,
222 // intExtPortMap.getInternalIp(), externalIp);
223 //Create NAT entries with VPN Id
224 LOG.debug("handleDNATConfigurationForRouterAssociation : Updating DNAT flows with VPN metadata {} ",
226 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, vpnName, networkId, intExtPortMap);
231 void handleDNATConfigurationForRouterDisassociation(String routerName, String vpnName, String externalNetwork)
232 throws ExecutionException, InterruptedException {
233 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
234 Optional<RouterPorts> optRouterPorts =
235 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
236 if (!optRouterPorts.isPresent()) {
237 LOG.error("handleDNATConfigurationForRouterDisassociation : Could not read Router Ports "
238 + "data object with id: {} to handle disassociate vpn {}", routerName, vpnName);
241 Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
242 for (Ports port : requireNonNullElse(optRouterPorts.get().getPorts(), Collections.<Ports>emptyList())) {
243 String portName = port.getPortName();
244 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
245 if (dpnId.equals(BigInteger.ZERO)) {
246 LOG.debug("handleDNATConfigurationForRouterDisassociation : DPN not found for {}, "
247 + "skip handling of router {} association with vpn {}", portName, routerName, vpnName);
250 for (InternalToExternalPortMap intExtPortMap : requireNonNullElse(port.getInternalToExternalPortMap(),
251 Collections.<InternalToExternalPortMap>emptyList())) {
252 //remove all NAT related entries with routerName
253 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, vpnName,
254 // intExtPortMap.getInternalIp(), externalIp);
255 //Create NAT entries with VPN Id
256 floatingIpListener.createNATOnlyFlowEntries(dpnId, routerName, null, networkId, intExtPortMap);