2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
9 package org.opendaylight.netvirt.natservice.internal;
\r
11 import com.google.common.base.Optional;
\r
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
\r
14 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
\r
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
\r
16 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
\r
17 import org.opendaylight.genius.mdsalutil.MDSALUtil;
\r
18 import org.opendaylight.genius.mdsalutil.NwConstants;
\r
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
\r
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey;
\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
\r
36 import org.opendaylight.yangtools.concepts.ListenerRegistration;
\r
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
\r
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
\r
39 import org.opendaylight.yangtools.yang.common.RpcResult;
\r
40 import org.slf4j.Logger;
\r
41 import org.slf4j.LoggerFactory;
\r
43 import java.math.BigInteger;
\r
44 import java.util.List;
\r
45 import java.util.concurrent.ExecutionException;
\r
46 import java.util.concurrent.Future;
\r
48 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
\r
53 * Created by ESUMAMS on 1/21/2016.
\r
55 public class ExternalNetworksChangeListener extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener>
\r
57 private static final Logger LOG = LoggerFactory.getLogger( ExternalNetworksChangeListener.class);
\r
59 private ListenerRegistration<DataChangeListener> listenerRegistration;
\r
60 private final DataBroker dataBroker;
\r
61 private IMdsalApiManager mdsalManager;
\r
62 //private VpnFloatingIpHandler vpnFloatingIpHandler;
\r
63 private FloatingIPListener floatingIpListener;
\r
64 private ExternalRoutersListener externalRouterListener;
\r
65 private OdlInterfaceRpcService interfaceManager;
\r
66 private NaptManager naptManager;
\r
68 private IBgpManager bgpManager;
\r
69 private VpnRpcService vpnService;
\r
70 private FibRpcService fibService;
\r
73 private ExternalRoutersListener externalRoutersListener;
\r
75 void setMdsalManager(IMdsalApiManager mdsalManager) {
\r
76 this.mdsalManager = mdsalManager;
\r
79 void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
\r
80 this.interfaceManager = interfaceManager;
\r
83 void setFloatingIpListener(FloatingIPListener floatingIpListener) {
\r
84 this.floatingIpListener = floatingIpListener;
\r
87 void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
\r
88 this.externalRouterListener = externalRoutersListener;
\r
91 public void setBgpManager(IBgpManager bgpManager) {
\r
92 this.bgpManager = bgpManager;
\r
95 public void setNaptManager(NaptManager naptManager) {
\r
96 this.naptManager = naptManager;
\r
99 public void setVpnService(VpnRpcService vpnService) {
\r
100 this.vpnService = vpnService;
\r
103 public void setFibService(FibRpcService fibService) {
\r
104 this.fibService = fibService;
\r
107 public void setListenerRegistration(ListenerRegistration<DataChangeListener> listenerRegistration) {
\r
108 this.listenerRegistration = listenerRegistration;
\r
111 public ExternalNetworksChangeListener(final DataBroker dataBroker ) {
\r
112 super( Networks.class, ExternalNetworksChangeListener.class );
\r
113 this.dataBroker = dataBroker;
\r
117 protected InstanceIdentifier<Networks> getWildCardPath() {
\r
118 return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);
\r
123 protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {
\r
128 protected ExternalNetworksChangeListener getDataTreeChangeListener() {
\r
129 return ExternalNetworksChangeListener.this;
\r
133 protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {
\r
134 if( identifier == null || networks == null || networks.getRouterIds().isEmpty() ) {
\r
135 LOG.info( "ExternalNetworksChangeListener:remove:: returning without processing since networks/identifier is null" );
\r
139 for( Uuid routerId: networks.getRouterIds() ) {
\r
140 String routerName = routerId.toString();
\r
142 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =
\r
143 getRouterToNaptSwitchInstanceIdentifier( routerName);
\r
145 MDSALUtil.syncDelete( dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier );
\r
147 LOG.debug( "ExternalNetworksChangeListener:delete:: successful deletion of data in napt-switches container" );
\r
151 private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier( String routerName ) {
\r
153 return InstanceIdentifier.builder( NaptSwitches.class )
\r
154 .child( RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
\r
158 public void close() throws Exception {
\r
159 if (listenerRegistration != null) {
\r
161 listenerRegistration.close();
\r
163 catch (final Exception e) {
\r
164 LOG.error("Error when cleaning up ExternalNetworksChangeListener.", e);
\r
167 listenerRegistration = null;
\r
169 LOG.debug("ExternalNetworksChangeListener Closed");
\r
174 protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {
\r
175 //Check for VPN disassociation
\r
176 Uuid originalVpn = original.getVpnid();
\r
177 Uuid updatedVpn = update.getVpnid();
\r
178 if(originalVpn == null && updatedVpn != null) {
\r
179 //external network is dis-associated from L3VPN instance
\r
180 associateExternalNetworkWithVPN(update);
\r
181 } else if(originalVpn != null && updatedVpn == null) {
\r
182 //external network is associated with vpn
\r
183 disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
\r
184 //Remove the SNAT entries
\r
185 removeSnatEntries(original, original.getId());
\r
189 private void removeSnatEntries(Networks original, Uuid networkUuid) {
\r
190 List<Uuid> routerUuids = original.getRouterIds();
\r
191 for (Uuid routerUuid : routerUuids) {
\r
192 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());
\r
193 if (routerId == NatConstants.INVALID_ID) {
\r
194 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerUuid.getValue());
\r
197 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
\r
198 externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), networkUuid, externalIps, false, original.getVpnid().getValue());
\r
202 private void associateExternalNetworkWithVPN(Networks network) {
\r
203 List<Uuid> routerIds = network.getRouterIds();
\r
204 for(Uuid routerId : routerIds) {
\r
205 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
\r
207 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
\r
208 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
\r
209 if(!optRouterPorts.isPresent()) {
\r
210 LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}", routerId, network.getId());
\r
213 RouterPorts routerPorts = optRouterPorts.get();
\r
214 List<Ports> interfaces = routerPorts.getPorts();
\r
215 for(Ports port : interfaces) {
\r
216 String portName = port.getPortName();
\r
217 BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
\r
218 if(dpnId.equals(BigInteger.ZERO)) {
\r
219 LOG.debug("DPN not found for {}, skip handling of ext nw {} association", portName, network.getId());
\r
222 List<IpMapping> ipMapping = port.getIpMapping();
\r
223 for(IpMapping ipMap : ipMapping) {
\r
224 String externalIp = ipMap.getExternalIp();
\r
225 //remove all VPN related entries
\r
226 floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
\r
232 for(Uuid routerId : routerIds) {
\r
233 LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}", routerId);
\r
234 Uuid networkId = network.getId();
\r
235 if(networkId == null) {
\r
236 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
\r
239 final String vpnName = network.getVpnid().getValue();
\r
240 if(vpnName == null) {
\r
241 LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);
\r
245 BigInteger dpnId = new BigInteger("0");
\r
246 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());
\r
247 Optional<RouterToNaptSwitch> rtrToNapt = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch );
\r
248 if(rtrToNapt.isPresent()) {
\r
249 dpnId = rtrToNapt.get().getPrimarySwitchId();
\r
251 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);
\r
252 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
\r
253 LOG.debug("NAT Service : primary napt Switch not found for router {} in associateExternalNetworkWithVPN", routerId);
\r
257 Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());
\r
258 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> idBuilder =
\r
259 InstanceIdentifier.builder(IntextIpMap.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey(routerIdentifier));
\r
260 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> id = idBuilder.build();
\r
261 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
\r
262 if (ipMapping.isPresent()) {
\r
263 List<IpMap> ipMaps = ipMapping.get().getIpMap();
\r
264 for (IpMap ipMap : ipMaps) {
\r
265 String externalIp = ipMap.getExternalIp();
\r
266 LOG.debug("NAT Service : got externalIp as {}", externalIp);
\r
267 LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, vpnName {} and externalIp {}", dpnId, vpnName, externalIp);
\r
268 externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
\r
271 LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);
\r
274 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
\r
275 // Install 47 entry to point to 21
\r
277 LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for donId {} and vpnId {}", dpnId, vpnId);
\r
278 externalRouterListener.installNaptPfibEntry(dpnId, vpnId);
\r
285 private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {
\r
286 List<Uuid> routerIds = network.getRouterIds();
\r
288 //long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
\r
289 for(Uuid routerId : routerIds) {
\r
290 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
\r
292 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
\r
293 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
\r
294 if(!optRouterPorts.isPresent()) {
\r
295 LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}", routerId, network.getId());
\r
298 RouterPorts routerPorts = optRouterPorts.get();
\r
299 List<Ports> interfaces = routerPorts.getPorts();
\r
300 for(Ports port : interfaces) {
\r
301 String portName = port.getPortName();
\r
302 BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
\r
303 if(dpnId.equals(BigInteger.ZERO)) {
\r
304 LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation", portName, network.getId());
\r
307 List<IpMapping> ipMapping = port.getIpMapping();
\r
308 for(IpMapping ipMap : ipMapping) {
\r
309 String externalIp = ipMap.getExternalIp();
\r
310 floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
\r
316 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
\r
317 BigInteger nodeId = BigInteger.ZERO;
\r
319 GetDpidFromInterfaceInput
\r
321 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
\r
322 Future<RpcResult<GetDpidFromInterfaceOutput>>
\r
324 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
\r
325 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
\r
326 if (dpIdResult.isSuccessful()) {
\r
327 nodeId = dpIdResult.getResult().getDpid();
\r
329 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
\r
331 } catch (InterruptedException | ExecutionException e) {
\r
332 LOG.error("Exception when getting dpn for interface {}", ifName, e);
\r