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 com.google.common.base.Optional;
11 import java.math.BigInteger;
12 import java.util.List;
13 import javax.annotation.PostConstruct;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.genius.mdsalutil.NwConstants;
21 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
22 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 public class ExternalNetworksChangeListener
46 extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener> {
47 private static final Logger LOG = LoggerFactory.getLogger(ExternalNetworksChangeListener.class);
48 private final DataBroker dataBroker;
49 private final IMdsalApiManager mdsalManager;
50 private final FloatingIPListener floatingIpListener;
51 private final ExternalRoutersListener externalRouterListener;
52 private final OdlInterfaceRpcService interfaceManager;
53 private final NaptManager naptManager;
54 private final IBgpManager bgpManager;
55 private final VpnRpcService vpnService;
56 private final FibRpcService fibService;
57 private NatMode natMode = NatMode.Controller;
60 public ExternalNetworksChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
61 final FloatingIPListener floatingIpListener,
62 final ExternalRoutersListener externalRouterListener,
63 final OdlInterfaceRpcService interfaceManager,
64 final NaptManager naptManager,
65 final IBgpManager bgpManager,
66 final VpnRpcService vpnService,
67 final FibRpcService fibService,
68 final NatserviceConfig config) {
69 super(Networks.class, ExternalNetworksChangeListener.class);
70 this.dataBroker = dataBroker;
71 this.mdsalManager = mdsalManager;
72 this.floatingIpListener = floatingIpListener;
73 this.externalRouterListener = externalRouterListener;
74 this.interfaceManager = interfaceManager;
75 this.naptManager = naptManager;
76 this.bgpManager = bgpManager;
77 this.vpnService = vpnService;
78 this.fibService = fibService;
80 this.natMode = config.getNatMode();
87 LOG.info("{} init", getClass().getSimpleName());
88 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
92 protected InstanceIdentifier<Networks> getWildCardPath() {
93 return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);
97 protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {
102 protected ExternalNetworksChangeListener getDataTreeChangeListener() {
103 return ExternalNetworksChangeListener.this;
107 protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {
108 if (identifier == null || networks == null || networks.getRouterIds().isEmpty()) {
109 LOG.info("ExternalNetworksChangeListener:remove:: returning without processing since "
110 + "networks/identifier is null");
114 for (Uuid routerId: networks.getRouterIds()) {
115 String routerName = routerId.toString();
117 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =
118 getRouterToNaptSwitchInstanceIdentifier(routerName);
120 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier);
122 LOG.debug("ExternalNetworksChangeListener:delete:: successful deletion of data in "
123 + "napt-switches container");
127 private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier(String routerName) {
128 return InstanceIdentifier.builder(NaptSwitches.class)
129 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
133 protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {
134 //Check for VPN disassociation
135 Uuid originalVpn = original.getVpnid();
136 Uuid updatedVpn = update.getVpnid();
137 if (originalVpn == null && updatedVpn != null) {
138 //external network is dis-associated from L3VPN instance
139 associateExternalNetworkWithVPN(update);
140 } else if (originalVpn != null && updatedVpn == null) {
141 //external network is associated with vpn
142 disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
143 //Remove the SNAT entries
144 removeSnatEntries(original, original.getId());
148 private void removeSnatEntries(Networks original, Uuid networkUuid) {
149 List<Uuid> routerUuids = original.getRouterIds();
150 for (Uuid routerUuid : routerUuids) {
151 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());
152 if (routerId == NatConstants.INVALID_ID) {
153 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerUuid.getValue());
156 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
157 if (natMode == NatMode.Controller) {
158 externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), networkUuid, externalIps,
159 false, original.getVpnid().getValue());
164 private void associateExternalNetworkWithVPN(Networks network) {
165 List<Uuid> routerIds = network.getRouterIds();
166 for (Uuid routerId : routerIds) {
167 //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
169 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
170 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
172 if (!optRouterPorts.isPresent()) {
173 LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}",
174 routerId, network.getId());
177 RouterPorts routerPorts = optRouterPorts.get();
178 List<Ports> interfaces = routerPorts.getPorts();
179 for (Ports port : interfaces) {
180 String portName = port.getPortName();
181 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
182 if (dpnId.equals(BigInteger.ZERO)) {
183 LOG.debug("DPN not found for {}, skip handling of ext nw {} association",
184 portName, network.getId());
187 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
188 for (InternalToExternalPortMap ipMap : intExtPortMapList) {
189 //remove all VPN related entries
190 floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(),
197 for (Uuid routerId : routerIds) {
198 LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}", routerId);
199 Uuid networkId = network.getId();
200 if (networkId == null) {
201 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
204 final String vpnName = network.getVpnid().getValue();
205 if (vpnName == null) {
206 LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);
210 BigInteger dpnId = new BigInteger("0");
211 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch =
212 NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());
213 Optional<RouterToNaptSwitch> rtrToNapt =
214 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
215 if (rtrToNapt.isPresent()) {
216 dpnId = rtrToNapt.get().getPrimarySwitchId();
218 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);
219 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
220 LOG.debug("NAT Service : primary napt Switch not found for router {} in "
221 + "associateExternalNetworkWithVPN", routerId);
225 Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());
226 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
227 .rev160111.intext.ip.map.IpMapping> idBuilder =
228 InstanceIdentifier.builder(IntextIpMap.class)
229 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
230 .intext.ip.map.IpMapping.class,
231 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
232 .intext.ip.map.IpMappingKey(routerIdentifier));
233 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
234 .intext.ip.map.IpMapping> id = idBuilder.build();
235 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
236 .intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
237 if (ipMapping.isPresent()) {
238 List<IpMap> ipMaps = ipMapping.get().getIpMap();
239 for (IpMap ipMap : ipMaps) {
240 String externalIp = ipMap.getExternalIp();
241 LOG.debug("NAT Service : got externalIp as {}", externalIp);
242 LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, "
243 + "vpnName {} and externalIp {}", dpnId, vpnName, externalIp);
244 if (natMode == NatMode.Controller) {
245 externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE,
246 vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), routerId.getValue(),
247 externalIp, null /* external-router */, vpnService, fibService, bgpManager, dataBroker,
252 LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);
255 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
256 // Install 47 entry to point to 21
257 if (natMode == NatMode.Controller) {
258 externalRouterListener.installNaptPfibEntriesForExternalSubnets(routerId.getValue(), dpnId);
260 LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for dpnId {} "
261 + "and vpnId {}", dpnId, vpnId);
262 externalRouterListener.installNaptPfibEntry(dpnId, vpnId);
269 private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {
270 List<Uuid> routerIds = network.getRouterIds();
272 for (Uuid routerId : routerIds) {
273 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
274 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
276 if (!optRouterPorts.isPresent()) {
277 LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}",
278 routerId, network.getId());
281 RouterPorts routerPorts = optRouterPorts.get();
282 List<Ports> interfaces = routerPorts.getPorts();
283 for (Ports port : interfaces) {
284 String portName = port.getPortName();
285 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName);
286 if (dpnId.equals(BigInteger.ZERO)) {
287 LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation",
288 portName, network.getId());
291 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
292 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
293 floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(),