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
9 package org.opendaylight.vpnservice.natservice.internal;
11 import com.google.common.base.Optional;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
17 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
18 import org.opendaylight.vpnservice.mdsalutil.ActionType;
19 import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
20 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
21 import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
22 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
23 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
24 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
25 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
26 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
27 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
28 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
29 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
48 import org.opendaylight.yangtools.concepts.ListenerRegistration;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
51 import org.opendaylight.yangtools.yang.common.RpcResult;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 import java.math.BigInteger;
56 import java.util.List;
57 import java.util.concurrent.ExecutionException;
58 import java.util.concurrent.Future;
60 import org.opendaylight.bgpmanager.api.IBgpManager;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
65 * Created by ESUMAMS on 1/21/2016.
67 public class ExternalNetworksChangeListener extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener>
69 private static final Logger LOG = LoggerFactory.getLogger( ExternalNetworksChangeListener.class);
71 private ListenerRegistration<DataChangeListener> listenerRegistration;
72 private final DataBroker dataBroker;
73 private IMdsalApiManager mdsalManager;
74 //private VpnFloatingIpHandler vpnFloatingIpHandler;
75 private FloatingIPListener floatingIpListener;
76 private ExternalRoutersListener externalRouterListener;
77 private OdlInterfaceRpcService interfaceManager;
78 private NaptManager naptManager;
80 private IBgpManager bgpManager;
81 private VpnRpcService vpnService;
82 private FibRpcService fibService;
85 private ExternalRoutersListener externalRoutersListener;
87 void setMdsalManager(IMdsalApiManager mdsalManager) {
88 this.mdsalManager = mdsalManager;
91 void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
92 this.interfaceManager = interfaceManager;
95 void setFloatingIpListener(FloatingIPListener floatingIpListener) {
96 this.floatingIpListener = floatingIpListener;
99 void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
100 this.externalRouterListener = externalRoutersListener;
103 public void setBgpManager(IBgpManager bgpManager) {
104 this.bgpManager = bgpManager;
107 public void setNaptManager(NaptManager naptManager) {
108 this.naptManager = naptManager;
111 public void setVpnService(VpnRpcService vpnService) {
112 this.vpnService = vpnService;
115 public void setFibService(FibRpcService fibService) {
116 this.fibService = fibService;
119 public void setListenerRegistration(ListenerRegistration<DataChangeListener> listenerRegistration) {
120 this.listenerRegistration = listenerRegistration;
123 public ExternalNetworksChangeListener(final DataBroker dataBroker ) {
124 super( Networks.class, ExternalNetworksChangeListener.class );
125 this.dataBroker = dataBroker;
129 protected InstanceIdentifier<Networks> getWildCardPath() {
130 return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);
135 protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {
140 protected ExternalNetworksChangeListener getDataTreeChangeListener() {
141 return ExternalNetworksChangeListener.this;
145 protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {
146 if( identifier == null || networks == null || networks.getRouterIds().isEmpty() ) {
147 LOG.info( "ExternalNetworksChangeListener:remove:: returning without processing since networks/identifier is null" );
151 for( Uuid routerId: networks.getRouterIds() ) {
152 String routerName = routerId.toString();
154 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =
155 getRouterToNaptSwitchInstanceIdentifier( routerName);
157 MDSALUtil.syncDelete( dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier );
159 LOG.debug( "ExternalNetworksChangeListener:delete:: successful deletion of data in napt-switches container" );
163 private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier( String routerName ) {
165 return InstanceIdentifier.builder( NaptSwitches.class )
166 .child( RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
170 public void close() throws Exception {
171 if (listenerRegistration != null) {
173 listenerRegistration.close();
175 catch (final Exception e) {
176 LOG.error("Error when cleaning up ExternalNetworksChangeListener.", e);
179 listenerRegistration = null;
181 LOG.debug("ExternalNetworksChangeListener Closed");
186 protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {
187 //Check for VPN disassociation
188 Uuid originalVpn = original.getVpnid();
189 Uuid updatedVpn = update.getVpnid();
190 if(originalVpn == null && updatedVpn != null) {
191 //external network is dis-associated from L3VPN instance
192 associateExternalNetworkWithVPN(update);
193 //Install the VPN related FIB entries
194 installVpnFibEntries(update, updatedVpn.getValue());
195 } else if(originalVpn != null && updatedVpn == null) {
196 //external network is associated with vpn
197 disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
198 //Remove the SNAT entries
199 removeSnatEntries(original, original.getId());
203 private void installVpnFibEntries(Networks update, String vpnName){
204 List<Uuid> routerUuids = update.getRouterIds();
205 for(Uuid routerUuid :routerUuids){
206 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
207 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
208 Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
209 if(!routerData.isPresent()){
212 String routerName = routerData.get().getRouterName();
213 List<String> externalIps = routerData.get().getExternalIps();
214 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
215 Optional<RouterToNaptSwitch> rtrToNapt = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch);
216 if(!rtrToNapt.isPresent()) {
217 LOG.debug("Unable to retrieve the Primary switch DPN ID");
220 BigInteger naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
221 for(String externalIp: externalIps) {
222 externalRouterListener.advToBgpAndInstallFibAndTsFlows(naptSwitchDpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerName), externalIp,
223 vpnService, fibService, bgpManager, dataBroker, LOG);
228 private void removeSnatEntries(Networks original, Uuid networkUuid){
229 List<Uuid> routerUuids = original.getRouterIds();
230 for(Uuid routerUuid :routerUuids){
231 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
232 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
233 Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
234 List<String> externalIps = null;
235 if(!routerData.isPresent()){
238 externalIps = routerData.get().getExternalIps();
239 externalRouterListener.handleDisableSnat(routerUuid.getValue(), networkUuid, externalIps);
243 private void associateExternalNetworkWithVPN(Networks network) {
244 List<Uuid> routerIds = network.getRouterIds();
245 for(Uuid routerId : routerIds) {
246 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
248 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
249 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
250 if(!optRouterPorts.isPresent()) {
251 LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}", routerId, network.getId());
254 RouterPorts routerPorts = optRouterPorts.get();
255 List<Ports> interfaces = routerPorts.getPorts();
256 for(Ports port : interfaces) {
257 String portName = port.getPortName();
258 BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
259 if(dpnId.equals(BigInteger.ZERO)) {
260 LOG.debug("DPN not found for {}, skip handling of ext nw {} association", portName, network.getId());
263 List<IpMapping> ipMapping = port.getIpMapping();
264 for(IpMapping ipMap : ipMapping) {
265 String externalIp = ipMap.getExternalIp();
266 //remove all VPN related entries
267 floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
273 for(Uuid routerId : routerIds) {
274 LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}", routerId);
275 Uuid networkId = network.getId();
276 if(networkId == null) {
277 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
280 final String vpnName = network.getVpnid().getValue();
281 if(vpnName == null) {
282 LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);
286 BigInteger dpnId = new BigInteger("0");
287 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());
288 Optional<RouterToNaptSwitch> rtrToNapt = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch );
289 if(rtrToNapt.isPresent()) {
290 dpnId = rtrToNapt.get().getPrimarySwitchId();
292 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);
294 Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());
295 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> idBuilder =
296 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));
297 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> id = idBuilder.build();
298 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
299 if (ipMapping.isPresent()) {
300 List<IpMap> ipMaps = ipMapping.get().getIpMap();
301 for (IpMap ipMap : ipMaps) {
302 String externalIp = ipMap.getExternalIp();
303 LOG.debug("NAT Service : got externalIp as {}", externalIp);
304 LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, vpnName {} and externalIp {}", dpnId, vpnName, externalIp);
305 externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
308 LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);
311 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
312 // Install 47 entry to point to 21
314 LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for donId {} and vpnId {}", dpnId, vpnId);
315 externalRouterListener.installNaptPfibEntry(dpnId, vpnId);
322 private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {
323 List<Uuid> routerIds = network.getRouterIds();
325 //long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
326 for(Uuid routerId : routerIds) {
327 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
329 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
330 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
331 if(!optRouterPorts.isPresent()) {
332 LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}", routerId, network.getId());
335 RouterPorts routerPorts = optRouterPorts.get();
336 List<Ports> interfaces = routerPorts.getPorts();
337 for(Ports port : interfaces) {
338 String portName = port.getPortName();
339 BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
340 if(dpnId.equals(BigInteger.ZERO)) {
341 LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation", portName, network.getId());
344 List<IpMapping> ipMapping = port.getIpMapping();
345 for(IpMapping ipMap : ipMapping) {
346 String externalIp = ipMap.getExternalIp();
347 floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
353 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
354 BigInteger nodeId = BigInteger.ZERO;
356 GetDpidFromInterfaceInput
358 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
359 Future<RpcResult<GetDpidFromInterfaceOutput>>
361 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
362 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
363 if (dpIdResult.isSuccessful()) {
364 nodeId = dpIdResult.getResult().getDpid();
366 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
368 } catch (InterruptedException | ExecutionException e) {
369 LOG.error("Exception when getting dpn for interface {}", ifName, e);