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.vpnservice.natservice.internal;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.vpnservice.mdsalutil.*;
17 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AddDpnEvent;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.add.dpn.event.AddEventData;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.RemoveDpnEvent;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.OdlL3vpnListener;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 import com.google.common.base.Optional;
36 public class DpnInVpnListener implements OdlL3vpnListener {
37 private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnListener.class);
38 private DataBroker dataBroker;
39 private SNATDefaultRouteProgrammer defaultRouteProgrammer;
40 private NaptSwitchHA naptSwitchHA;
41 private IMdsalApiManager mdsalManager;
42 private IdManagerService idManager;
44 public DpnInVpnListener(DataBroker dataBroker) {
45 this.dataBroker = dataBroker;
48 void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
49 this.defaultRouteProgrammer = defaultRouteProgrammer;
52 void setNaptSwitchHA(NaptSwitchHA switchHA) {
53 naptSwitchHA = switchHA;
56 void setMdsalManager(IMdsalApiManager mdsalManager) {
57 this.mdsalManager = mdsalManager;
60 public void setIdManager(IdManagerService idManager) {
61 this.idManager = idManager;
64 public void onAddDpnEvent(AddDpnEvent notification) {
66 AddEventData eventData = notification.getAddEventData();
67 BigInteger dpnId = eventData.getDpnId();
68 String vpnName = eventData.getVpnName();
69 LOG.info("Received add dpn {} in vpn {} event", dpnId, vpnName);
70 String routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
71 if (routerId != null) {
72 //check router is associated to external network
73 InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
74 Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
75 if (routerData.isPresent()) {
76 Uuid networkId = routerData.get().getNetworkId();
77 if(networkId != null) {
78 LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
79 long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
80 if(vpnId != NatConstants.INVALID_ID) {
81 //Install default entry in FIB to SNAT table
82 LOG.debug("Installing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
83 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
85 LOG.debug("Add DPN Event: Could not read vpnId for vpnName {}", vpnName);
87 if (routerData.get().isEnableSnat()) {
88 LOG.info("SNAT enabled for router {}", routerId);
89 handleSNATForDPN(dpnId, routerId);
91 LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
99 void handleSNATForDPN(BigInteger dpnId, String routerName) {
100 //Check if primary and secondary switch are selected, If not select the role
101 //Install select group to NAPT switch
102 //Install default miss entry to NAPT switch
104 BigInteger naptSwitch;
106 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
107 if (routerId == NatConstants.INVALID_ID) {
108 LOG.error("Invalid routerId returned for routerName {}",routerName);
111 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
112 if (naptId == null || naptId.equals(BigInteger.ZERO)) {
113 LOG.debug("No Naptswitch is selected for router {}", routerName);
116 boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
118 LOG.error("Failed to update newNaptSwitch {} for routername {}",naptSwitch,routerName);
121 LOG.debug("Switch {} is elected as NaptSwitch for router {}",dpnId,routerName);
124 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInPrimarySwitch();
125 naptSwitchHA.installSnatGroupEntry(naptSwitch,bucketInfo,routerName);
127 naptSwitchHA.installSnatFlows(routerName,routerId,naptSwitch);
130 LOG.debug("Napt switch with Id {} is already elected for router {}",naptId, routerName);
134 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, routerName, naptSwitch);
135 if (bucketInfo == null) {
136 LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}",dpnId,routerName,
140 naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
142 // Install miss entry (table 26) pointing to group
143 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
144 FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,NatConstants.ADD_FLOW);
145 if (flowEntity == null) {
146 LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}",routerName,dpnId,groupId);
149 LOG.debug("Successfully installed flow for dpnId {} router {} group {}",dpnId,routerName,groupId);
150 mdsalManager.installFlow(flowEntity);
151 } catch (Exception ex) {
152 LOG.error("Exception in handleSNATForDPN method : {}",ex);
157 public void onRemoveDpnEvent(RemoveDpnEvent notification) {
159 RemoveEventData eventData = notification.getRemoveEventData();
160 BigInteger dpnId = eventData.getDpnId();
161 String vpnName = eventData.getVpnName();
162 LOG.info("Received remove dpn {} in vpn {} event", dpnId, vpnName);
163 String routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
164 if (routerId != null) {
165 //check router is associated to external network
166 InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
167 Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
168 if (routerData.isPresent()) {
169 Uuid networkId = routerData.get().getNetworkId();
170 if(networkId != null) {
171 LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
172 long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
173 if(vpnId != NatConstants.INVALID_ID) {
174 //Remove default entry in FIB
175 LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
176 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId);
178 LOG.debug("Remove DPN Event: Could not read vpnId for vpnName {}", vpnName);
180 if (routerData.get().isEnableSnat()) {
181 LOG.info("SNAT enabled for router {}", routerId);
182 removeSNATFromDPN(dpnId,routerId);
184 LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId);
192 /*void removeSNATFromDPN(BigInteger dpnId, String routerName) {
193 //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
194 //remove miss entry to NAPT switch
195 //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
197 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
198 if (routerId == NatConstants.INVALID_ID) {
199 LOG.error("Invalid routerId returned for routerName {}",routerName);
202 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
203 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
204 LOG.debug("No naptSwitch is selected for router {}", routerName);
208 boolean naptStatus = naptSwitchHA.isNaptSwitchDown(routerName,dpnId,naptSwitch);
210 LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
213 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName,naptSwitch);
215 } catch (Exception ex) {
216 LOG.debug("Exception while handling naptSwitch down for router {} : {}",routerName,ex);
219 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
220 FlowEntity flowEntity = null;
222 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, NatConstants.DEL_FLOW);
223 if (flowEntity == null) {
224 LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",routerName,dpnId,groupId);
227 LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}",flowEntity);
228 mdsalManager.removeFlow(flowEntity);
230 } catch (Exception ex) {
231 LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex);
234 LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName);
237 GroupEntity groupEntity = null;
239 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
240 GroupTypes.GroupAll, null);
241 LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity);
242 mdsalManager.removeGroup(groupEntity);
243 } catch (Exception ex) {
244 LOG.debug("NAT Service : Failed to remove group entity {} : {}",groupEntity,ex);
247 LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}", dpnId, routerName);