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.vpnservice.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.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
\r
17 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
\r
18 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
\r
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
\r
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;
\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
\r
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
\r
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
\r
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
\r
38 import org.opendaylight.yangtools.yang.common.RpcResult;
\r
39 import org.slf4j.Logger;
\r
40 import org.slf4j.LoggerFactory;
\r
42 import java.math.BigInteger;
\r
43 import java.util.List;
\r
44 import java.util.concurrent.ExecutionException;
\r
45 import java.util.concurrent.Future;
\r
47 import org.opendaylight.bgpmanager.api.IBgpManager;
\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
\r
52 * Created by ESUMAMS on 1/21/2016.
\r
54 public class ExternalNetworksChangeListener extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener>
\r
56 private static final Logger LOG = LoggerFactory.getLogger( ExternalNetworksChangeListener.class);
\r
58 private ListenerRegistration<DataChangeListener> listenerRegistration;
\r
59 private final DataBroker dataBroker;
\r
60 private IMdsalApiManager mdsalManager;
\r
61 //private VpnFloatingIpHandler vpnFloatingIpHandler;
\r
62 private FloatingIPListener floatingIpListener;
\r
63 private ExternalRoutersListener externalRouterListener;
\r
64 private OdlInterfaceRpcService interfaceManager;
\r
65 private NaptManager naptManager;
\r
67 private IBgpManager bgpManager;
\r
68 private VpnRpcService vpnService;
\r
69 private FibRpcService fibService;
\r
72 private ExternalRoutersListener externalRoutersListener;
\r
74 void setMdsalManager(IMdsalApiManager mdsalManager) {
\r
75 this.mdsalManager = mdsalManager;
\r
78 void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
\r
79 this.interfaceManager = interfaceManager;
\r
82 void setFloatingIpListener(FloatingIPListener floatingIpListener) {
\r
83 this.floatingIpListener = floatingIpListener;
\r
86 void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
\r
87 this.externalRouterListener = externalRoutersListener;
\r
90 public void setBgpManager(IBgpManager bgpManager) {
\r
91 this.bgpManager = bgpManager;
\r
94 public void setNaptManager(NaptManager naptManager) {
\r
95 this.naptManager = naptManager;
\r
98 public void setVpnService(VpnRpcService vpnService) {
\r
99 this.vpnService = vpnService;
\r
102 public void setFibService(FibRpcService fibService) {
\r
103 this.fibService = fibService;
\r
106 public void setListenerRegistration(ListenerRegistration<DataChangeListener> listenerRegistration) {
\r
107 this.listenerRegistration = listenerRegistration;
\r
110 public ExternalNetworksChangeListener(final DataBroker dataBroker ) {
\r
111 super( Networks.class, ExternalNetworksChangeListener.class );
\r
112 this.dataBroker = dataBroker;
\r
116 protected InstanceIdentifier<Networks> getWildCardPath() {
\r
117 return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);
\r
122 protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {
\r
127 protected ExternalNetworksChangeListener getDataTreeChangeListener() {
\r
128 return ExternalNetworksChangeListener.this;
\r
132 protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {
\r
133 if( identifier == null || networks == null || networks.getRouterIds().isEmpty() ) {
\r
134 LOG.info( "ExternalNetworksChangeListener:remove:: returning without processing since networks/identifier is null" );
\r
138 for( Uuid routerId: networks.getRouterIds() ) {
\r
139 String routerName = routerId.toString();
\r
141 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =
\r
142 getRouterToNaptSwitchInstanceIdentifier( routerName);
\r
144 MDSALUtil.syncDelete( dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier );
\r
146 LOG.debug( "ExternalNetworksChangeListener:delete:: successful deletion of data in napt-switches container" );
\r
150 private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier( String routerName ) {
\r
152 return InstanceIdentifier.builder( NaptSwitches.class )
\r
153 .child( RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
\r
157 public void close() throws Exception {
\r
158 if (listenerRegistration != null) {
\r
160 listenerRegistration.close();
\r
162 catch (final Exception e) {
\r
163 LOG.error("Error when cleaning up ExternalNetworksChangeListener.", e);
\r
166 listenerRegistration = null;
\r
168 LOG.debug("ExternalNetworksChangeListener Closed");
\r
173 protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {
\r
174 //Check for VPN disassociation
\r
175 Uuid originalVpn = original.getVpnid();
\r
176 Uuid updatedVpn = update.getVpnid();
\r
177 if(originalVpn == null && updatedVpn != null) {
\r
178 //external network is dis-associated from L3VPN instance
\r
179 associateExternalNetworkWithVPN(update);
\r
180 } else if(originalVpn != null && updatedVpn == null) {
\r
181 //external network is associated with vpn
\r
182 disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
\r
183 //Remove the SNAT entries
\r
184 removeSnatEntries(original, original.getId());
\r
188 private void removeSnatEntries(Networks original, Uuid networkUuid) {
\r
189 List<Uuid> routerUuids = original.getRouterIds();
\r
190 for (Uuid routerUuid : routerUuids) {
\r
191 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());
\r
192 if (routerId == NatConstants.INVALID_ID) {
\r
193 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerUuid.getValue());
\r
196 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
\r
197 externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), networkUuid, externalIps, false, original.getVpnid().getValue());
\r
201 private void associateExternalNetworkWithVPN(Networks network) {
\r
202 List<Uuid> routerIds = network.getRouterIds();
\r
203 for(Uuid routerId : routerIds) {
\r
204 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
\r
206 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
\r
207 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
\r
208 if(!optRouterPorts.isPresent()) {
\r
209 LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}", routerId, network.getId());
\r
212 RouterPorts routerPorts = optRouterPorts.get();
\r
213 List<Ports> interfaces = routerPorts.getPorts();
\r
214 for(Ports port : interfaces) {
\r
215 String portName = port.getPortName();
\r
216 BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
\r
217 if(dpnId.equals(BigInteger.ZERO)) {
\r
218 LOG.debug("DPN not found for {}, skip handling of ext nw {} association", portName, network.getId());
\r
221 List<IpMapping> ipMapping = port.getIpMapping();
\r
222 for(IpMapping ipMap : ipMapping) {
\r
223 String externalIp = ipMap.getExternalIp();
\r
224 //remove all VPN related entries
\r
225 floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
\r
231 for(Uuid routerId : routerIds) {
\r
232 LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}", routerId);
\r
233 Uuid networkId = network.getId();
\r
234 if(networkId == null) {
\r
235 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
\r
238 final String vpnName = network.getVpnid().getValue();
\r
239 if(vpnName == null) {
\r
240 LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);
\r
244 BigInteger dpnId = new BigInteger("0");
\r
245 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());
\r
246 Optional<RouterToNaptSwitch> rtrToNapt = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch );
\r
247 if(rtrToNapt.isPresent()) {
\r
248 dpnId = rtrToNapt.get().getPrimarySwitchId();
\r
250 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);
\r
252 Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());
\r
253 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> idBuilder =
\r
254 InstanceIdentifier.builder(IntextIpMap.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey(routerIdentifier));
\r
255 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> id = idBuilder.build();
\r
256 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
\r
257 if (ipMapping.isPresent()) {
\r
258 List<IpMap> ipMaps = ipMapping.get().getIpMap();
\r
259 for (IpMap ipMap : ipMaps) {
\r
260 String externalIp = ipMap.getExternalIp();
\r
261 LOG.debug("NAT Service : got externalIp as {}", externalIp);
\r
262 LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, vpnName {} and externalIp {}", dpnId, vpnName, externalIp);
\r
263 externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
\r
266 LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);
\r
269 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
\r
270 // Install 47 entry to point to 21
\r
272 LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for donId {} and vpnId {}", dpnId, vpnId);
\r
273 externalRouterListener.installNaptPfibEntry(dpnId, vpnId);
\r
280 private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {
\r
281 List<Uuid> routerIds = network.getRouterIds();
\r
283 //long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
\r
284 for(Uuid routerId : routerIds) {
\r
285 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
\r
287 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
\r
288 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
\r
289 if(!optRouterPorts.isPresent()) {
\r
290 LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}", routerId, network.getId());
\r
293 RouterPorts routerPorts = optRouterPorts.get();
\r
294 List<Ports> interfaces = routerPorts.getPorts();
\r
295 for(Ports port : interfaces) {
\r
296 String portName = port.getPortName();
\r
297 BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
\r
298 if(dpnId.equals(BigInteger.ZERO)) {
\r
299 LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation", portName, network.getId());
\r
302 List<IpMapping> ipMapping = port.getIpMapping();
\r
303 for(IpMapping ipMap : ipMapping) {
\r
304 String externalIp = ipMap.getExternalIp();
\r
305 floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
\r
311 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
\r
312 BigInteger nodeId = BigInteger.ZERO;
\r
314 GetDpidFromInterfaceInput
\r
316 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
\r
317 Future<RpcResult<GetDpidFromInterfaceOutput>>
\r
319 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
\r
320 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
\r
321 if (dpIdResult.isSuccessful()) {
\r
322 nodeId = dpIdResult.getResult().getDpid();
\r
324 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
\r
326 } catch (InterruptedException | ExecutionException e) {
\r
327 LOG.error("Exception when getting dpn for interface {}", ifName, e);
\r